BitSharp.Core.Test.BlockReplayerTest.TestReplayBlockRollback C# (CSharp) Method

TestReplayBlockRollback() private method

private TestReplayBlockRollback ( ) : void
return void
        public void TestReplayBlockRollback()
        {
            using (var daemon = new TestDaemon())
            {
                // create a new keypair to spend to
                var toKeyPair = daemon.TxManager.CreateKeyPair();
                var toPrivateKey = toKeyPair.Item1;
                var toPublicKey = toKeyPair.Item2;

                // add block 1
                var block0 = daemon.GenesisBlock;
                var block1 = daemon.MineAndAddEmptyBlock();

                // add some blocks so coinbase is mature to spend
                Block lastBlock = null;
                for (var i = 0; i < 100; i++)
                    lastBlock = daemon.MineAndAddEmptyBlock();

                // add block 2, spending from block 1
                var spendTx1 = daemon.TxManager.CreateSpendTransaction(block1.Transactions[0], 0, (byte)ScriptHashType.SIGHASH_ALL, block1.Transactions[0].OutputValue(), daemon.CoinbasePrivateKey, daemon.CoinbasePublicKey, toPublicKey);
                var block2Unmined = daemon.CreateEmptyBlock(lastBlock.Hash)
                    .CreateWithAddedTransactions(spendTx1);
                var block2 = daemon.MineAndAddBlock(block2Unmined);

                // add some blocks so coinbase is mature to spend
                for (var i = 0; i < 100; i++)
                    lastBlock = daemon.MineAndAddEmptyBlock();

                // add block 3, spending from block 2
                var spendTx2 = daemon.TxManager.CreateSpendTransaction(block2.Transactions[1], 0, (byte)ScriptHashType.SIGHASH_ALL, block2.Transactions[1].OutputValue(), toPrivateKey, toPublicKey, toPublicKey);
                var block3Unmined = daemon.CreateEmptyBlock(lastBlock.Hash)
                    .CreateWithAddedTransactions(spendTx2);
                var block3 = daemon.MineAndAddBlock(block3Unmined);

                // replay all blocks up to block 3
                daemon.WaitForUpdate();
                using (var chainState = daemon.CoreDaemon.GetChainState())
                {
                    Assert.AreEqual(203, chainState.Chain.Height);

                    var replayTransactions = new List<ValidatableTx>();
                    foreach (var blockHash in chainState.Chain.Blocks.Select(x => x.Hash))
                    {
                        replayTransactions.AddRange(BlockReplayer.ReplayBlock(daemon.CoreStorage, chainState, blockHash, replayForward: true)
                            .ToEnumerable());
                    }

                    // verify all transactions were replayed
                    Assert.AreEqual(206, replayTransactions.Count);
                    Assert.AreEqual(block0.Transactions[0].Hash, replayTransactions[0].Transaction.Hash);
                    Assert.AreEqual(block1.Transactions[0].Hash, replayTransactions[1].Transaction.Hash);
                    Assert.AreEqual(block2.Transactions[0].Hash, replayTransactions[102].Transaction.Hash);
                    Assert.AreEqual(block2.Transactions[1].Hash, replayTransactions[103].Transaction.Hash);
                    Assert.AreEqual(block3.Transactions[0].Hash, replayTransactions[204].Transaction.Hash);
                    Assert.AreEqual(block3.Transactions[1].Hash, replayTransactions[205].Transaction.Hash);
                }

                // mark block 2 invalid, it will be rolled back
                daemon.CoreStorage.MarkBlockInvalid(block2.Hash, daemon.CoreDaemon.TargetChain);
                daemon.WaitForUpdate();

                // replay rollback of block 3
                using (var chainState = daemon.CoreDaemon.GetChainState())
                {
                    Assert.AreEqual(101, chainState.Chain.Height);

                    var replayTransactions = new List<ValidatableTx>(
                        BlockReplayer.ReplayBlock(daemon.CoreStorage, chainState, block3.Hash, replayForward: false)
                        .ToEnumerable());

                    // verify transactions were replayed
                    Assert.AreEqual(2, replayTransactions.Count);
                    Assert.AreEqual(block3.Transactions[1].Hash, replayTransactions[0].Transaction.Hash);
                    Assert.AreEqual(block3.Transactions[0].Hash, replayTransactions[1].Transaction.Hash);

                    // verify correct previous output was replayed (block 3 tx 1 spent block 2 tx 1)
                    Assert.AreEqual(1, replayTransactions[0].PrevTxOutputs.Length);
                    CollectionAssert.AreEqual(block2.Transactions[1].Outputs[0].ScriptPublicKey, replayTransactions[0].PrevTxOutputs[0].ScriptPublicKey);

                    // verify correct previous output was replayed (block 3 tx 0 spends nothing, coinbase)
                    Assert.AreEqual(0, replayTransactions[1].PrevTxOutputs.Length);
                }

                // replay rollback of block 2
                using (var chainState = daemon.CoreDaemon.GetChainState())
                {
                    Assert.AreEqual(101, chainState.Chain.Height);

                    var replayTransactions = new List<ValidatableTx>(
                        BlockReplayer.ReplayBlock(daemon.CoreStorage, chainState, block2.Hash, replayForward: false)
                        .ToEnumerable());

                    // verify transactions were replayed
                    Assert.AreEqual(2, replayTransactions.Count);
                    Assert.AreEqual(block2.Transactions[1].Hash, replayTransactions[0].Transaction.Hash);
                    Assert.AreEqual(block2.Transactions[0].Hash, replayTransactions[1].Transaction.Hash);

                    // verify correct previous output was replayed (block 2 tx 1 spent block 1 tx 0)
                    Assert.AreEqual(1, replayTransactions[0].PrevTxOutputs.Length);
                    CollectionAssert.AreEqual(block1.Transactions[0].Outputs[0].ScriptPublicKey, replayTransactions[0].PrevTxOutputs[0].ScriptPublicKey);

                    // verify correct previous output was replayed (block 2 tx 0 spends nothing, coinbase)
                    Assert.AreEqual(0, replayTransactions[1].PrevTxOutputs.Length);
                }
            }
        }
    }