public void TestShorterChainWins() { using (var daemon = new TestDaemon()) { // add some simple blocks var block1 = daemon.MineAndAddEmptyBlock(); var block2 = daemon.MineAndAddEmptyBlock(); var block3a = daemon.MineAndAddEmptyBlock(); var block4a = daemon.MineAndAddEmptyBlock(); var block5a = daemon.MineAndAddEmptyBlock(); // check daemon.WaitForUpdate(); daemon.AssertAtBlock(5, block5a.Hash); // create a split with 3b, but do more work than current height 5 chain var testBlocksFork = daemon.TestBlocks.Fork(3); daemon.ChainParams.HighestTarget = UnitTestParams.Target2; var block3b = daemon.AddBlock(testBlocksFork.MineAndAddEmptyBlock(UnitTestParams.Target2)); // check that blockchain reorganized to shorter chain daemon.WaitForUpdate(); daemon.AssertAtBlock(3, block3b.Hash); } }
public void TestSimpleBlockchainSplit() { using (var daemon1 = new TestDaemon()) { // add some simple blocks var block1 = daemon1.MineAndAddEmptyBlock(); var block2 = daemon1.MineAndAddEmptyBlock(); var block3a = daemon1.MineAndAddEmptyBlock(); daemon1.WaitForUpdate(); // create a fork test block chain, starting at block2 var testBlocksFork = daemon1.TestBlocks.Fork(1); // wait for daemon daemon1.WaitForUpdate(); daemon1.AssertAtBlock(3, block3a.Hash); // introduce a tie split var block3b = daemon1.AddBlock(testBlocksFork.MineAndAddEmptyBlock()); // check that 3a is still current as it was first daemon1.WaitForUpdate(); daemon1.AssertAtBlock(3, block3a.Hash); // continue with currently winning branch var block4a = daemon1.MineAndAddEmptyBlock(); // wait for daemon daemon1.WaitForUpdate(); daemon1.AssertAtBlock(4, block4a.Hash); // continue with tied branch var block4b = daemon1.AddBlock(testBlocksFork.MineAndAddEmptyBlock()); // check that 4a is still current as it was first daemon1.WaitForUpdate(); daemon1.AssertAtBlock(4, block4a.Hash); // resolve tie split, with other chain winning var block5b = daemon1.AddBlock(testBlocksFork.MineAndAddEmptyBlock()); // check that blockchain reorged to the winning chain daemon1.WaitForUpdate(); daemon1.AssertAtBlock(5, block5b.Hash); // continue on winning fork var block6b = daemon1.AddBlock(testBlocksFork.MineAndAddEmptyBlock()); // check that blockchain continued on the winning chain daemon1.WaitForUpdate(); daemon1.AssertAtBlock(6, block6b.Hash); // create a second blockchain, reusing the genesis from the first using (var daemon2 = new TestDaemon(daemon1.GenesisBlock)) { // add only the winning blocks to the second blockchain daemon2.AddBlock(block1); daemon2.AddBlock(block2); daemon2.AddBlock(block3b); daemon2.AddBlock(block4b); daemon2.AddBlock(block5b); daemon2.AddBlock(block6b); // check second blockchain daemon2.WaitForUpdate(); daemon2.AssertAtBlock(6, block6b.Hash); // verify that re-organized blockchain matches winning-only blockchain using (var expectedChainState = daemon2.CoreDaemon.GetChainState()) using (var actualChainState = daemon1.CoreDaemon.GetChainState()) { var expectedUtxo = expectedChainState.ReadUnspentTransactions().ToList(); var actualUtxo = actualChainState.ReadUnspentTransactions().ToList(); CollectionAssert.AreEqual(expectedUtxo, actualUtxo); } } } }
public void TestSimpleBlockchainSplit() { using (var daemon1 = new TestDaemon()) { // add some simple blocks var block1 = daemon1.MineAndAddEmptyBlock(daemon1.GenesisBlock); var block2 = daemon1.MineAndAddEmptyBlock(block1); // introduce a tie split var block3a = daemon1.MineAndAddEmptyBlock(block2); var block3b = daemon1.MineAndAddEmptyBlock(block2); // check that 3a is current as it was first daemon1.WaitForDaemon(); AssertMethods.AssertDaemonAtBlock(3, block3a.Hash, daemon1.BlockchainDaemon); // continue split var block4a = daemon1.MineAndAddEmptyBlock(block3a); var block4b = daemon1.MineAndAddEmptyBlock(block3b); // check that 4a is current as it was first daemon1.WaitForDaemon(); AssertMethods.AssertDaemonAtBlock(4, block4a.Hash, daemon1.BlockchainDaemon); // resolve tie split, with other chain winning var block5b = daemon1.MineAndAddEmptyBlock(block4b); // check that blockchain reorged to the winning chain daemon1.WaitForDaemon(); AssertMethods.AssertDaemonAtBlock(5, block5b.Hash, daemon1.BlockchainDaemon); // continue on winning fork var block6b = daemon1.MineAndAddEmptyBlock(block5b); // check that blockchain continued on the winning chain daemon1.WaitForDaemon(); AssertMethods.AssertDaemonAtBlock(6, block6b.Hash, daemon1.BlockchainDaemon); // create a second blockchain, reusing the genesis from the first using (var daemon2 = new TestDaemon(daemon1.GenesisBlock)) { // add only the winning blocks to the second blockchain daemon2.AddBlock(block1); daemon2.AddBlock(block2); daemon2.AddBlock(block3b); daemon2.AddBlock(block4b); daemon2.AddBlock(block5b); daemon2.AddBlock(block6b); // check second blockchain daemon2.WaitForDaemon(); AssertMethods.AssertDaemonAtBlock(6, block6b.Hash, daemon2.BlockchainDaemon); // verify that re-organized blockchain matches winning-only blockchain using (var expectedChainSate = daemon2.BlockchainDaemon.GetChainState()) using (var actualChainSate = daemon1.BlockchainDaemon.GetChainState()) { var expectedUtxo = expectedChainSate.Utxo; var expectedUnspentTransactions = ImmutableDictionary.CreateRange <UInt256, UnspentTx>(expectedUtxo.GetUnspentTransactions()); var expectedUnspentOutputs = ImmutableDictionary.CreateRange <TxOutputKey, TxOutput>(expectedUtxo.GetUnspentOutputs()); var actualUtxo = actualChainSate.Utxo; var actualUnspentTransactions = ImmutableDictionary.CreateRange <UInt256, UnspentTx>(actualUtxo.GetUnspentTransactions()); var actualUnspentOutputs = ImmutableDictionary.CreateRange <TxOutputKey, TxOutput>(actualUtxo.GetUnspentOutputs()); CollectionAssert.AreEquivalent(expectedUnspentTransactions, actualUnspentTransactions); CollectionAssert.AreEquivalent(expectedUnspentOutputs, actualUnspentOutputs); } } } }