Beispiel #1
0
        public void TestSimpleSpend()
        {
            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 some simple blocks
                var block1 = daemon.MineAndAddEmptyBlock(daemon.GenesisBlock);
                var block2 = daemon.MineAndAddEmptyBlock(block1);

                // check
                daemon.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(2, block2.Hash, daemon.CoreDaemon);

                // attempt to spend block 2's coinbase in block 3
                var spendTx       = daemon.TxManager.CreateSpendTransaction(block2.Transactions[0], 0, (byte)ScriptHashType.SIGHASH_ALL, 50 * SATOSHI_PER_BTC, daemon.CoinbasePrivateKey, daemon.CoinbasePublicKey, toPublicKey);
                var block3Unmined = daemon.CreateEmptyBlock(block2)
                                    .WithAddedTransactions(spendTx);
                var block3 = daemon.MineAndAddBlock(block3Unmined);

                // check
                daemon.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(3, block3.Hash, daemon.CoreDaemon);

                // add a simple block
                var block4 = daemon.MineAndAddEmptyBlock(block3);

                // check
                daemon.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(4, block4.Hash, daemon.CoreDaemon);
            }
        }
Beispiel #2
0
        public void TestInsufficientBalance()
        {
            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 some simple blocks
                var block1 = daemon.MineAndAddEmptyBlock(daemon.GenesisBlock);
                var block2 = daemon.MineAndAddEmptyBlock(block1);

                // check
                daemon.WaitForDaemon();
                AssertMethods.AssertDaemonAtBlock(2, block2.Hash, daemon.BlockchainDaemon);

                // attempt to spend block 2's coinbase in block 3, using twice its value
                var spendTx          = daemon.TxManager.CreateSpendTransaction(block2.Transactions[0], 0, (byte)ScriptHashType.SIGHASH_ALL, 100 * SATOSHI_PER_BTC, daemon.CoinbasePrivateKey, daemon.CoinbasePublicKey, toPublicKey);
                var block3BadUnmined = daemon.CreateEmptyBlock(block2)
                                       .WithAddedTransactions(spendTx);
                var block3Bad = daemon.MineAndAddBlock(block3BadUnmined);

                // check that bad block wasn't added
                daemon.WaitForDaemon();
                AssertMethods.AssertDaemonAtBlock(2, block2.Hash, daemon.BlockchainDaemon);

                // add a simple block
                var block3Good = daemon.MineAndAddEmptyBlock(block2);

                // check
                daemon.WaitForDaemon();
                AssertMethods.AssertDaemonAtBlock(3, block3Good.Hash, daemon.BlockchainDaemon);
            }
        }
Beispiel #3
0
        public void TestAddSingleBlock()
        {
            using (var daemon = new TestDaemon())
            {
                var block1 = daemon.MineAndAddEmptyBlock(daemon.GenesisBlock);

                daemon.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(1, block1.Hash, daemon.CoreDaemon);
            }
        }
Beispiel #4
0
        public void TestLongBlockchain()
        {
            using (var daemon = new TestDaemon())
            {
                var count = 1.THOUSAND();

                var height = 0;
                var block  = daemon.GenesisBlock;
                for (var i = 0; i < count; i++)
                {
                    height++;
                    block = daemon.MineAndAddEmptyBlock(block);
                }

                daemon.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(height, block.Hash, daemon.CoreDaemon);
            }
        }
Beispiel #5
0
        public void TestShorterChainWins()
        {
            using (var daemon = new TestDaemon())
            {
                // add some simple blocks
                var block1  = daemon.MineAndAddEmptyBlock(daemon.GenesisBlock);
                var block2  = daemon.MineAndAddEmptyBlock(block1);
                var block3a = daemon.MineAndAddEmptyBlock(block2);
                var block4a = daemon.MineAndAddEmptyBlock(block3a);
                var block5a = daemon.MineAndAddEmptyBlock(block4a);

                // check
                daemon.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(5, block5a.Hash, daemon.CoreDaemon);

                // create a split with 3b, but do more work than current height 5 chain
                daemon.Rules.SetHighestTarget(UnitTestRules.Target2);
                var block3b = daemon.MineAndAddEmptyBlock(block2, UnitTestRules.Target2);

                // check that blockchain reorganized to shorter chain
                daemon.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(3, block3b.Hash, daemon.CoreDaemon);
            }
        }
Beispiel #6
0
        public void TestLongBlockchain()
        {
            if (Debugger.IsAttached)
            {
                Assert.Inconclusive();
            }

            using (var daemon = new TestDaemon())
            {
                var count = 1.THOUSAND();

                var height = 0;
                var block  = daemon.GenesisBlock;
                for (var i = 0; i < count; i++)
                {
                    Debug.WriteLine("TestLongBlockchain mining block {0:#,##0}".Format2(i));
                    height++;
                    block = daemon.MineAndAddEmptyBlock(block);
                }

                daemon.WaitForDaemon();
                AssertMethods.AssertDaemonAtBlock(height, block.Hash, daemon.BlockchainDaemon);
            }
        }
Beispiel #7
0
        public void TestSimpleBlockchainSplit()
        {
            using (var daemon1 = new TestDaemon())
            {
                // add some simple blocks
                var block1  = daemon1.MineAndAddEmptyBlock(daemon1.GenesisBlock);
                var block2  = daemon1.MineAndAddEmptyBlock(block1);
                var block3a = daemon1.MineAndAddEmptyBlock(block2);
                daemon1.WaitForUpdate();

                // wait for daemon
                daemon1.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(3, block3a.Hash, daemon1.CoreDaemon);

                // introduce a tie split
                var block3b = daemon1.MineAndAddEmptyBlock(block2);

                // check that 3a is still current as it was first
                daemon1.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(3, block3a.Hash, daemon1.CoreDaemon);

                // continue with currently winning branch
                var block4a = daemon1.MineAndAddEmptyBlock(block3a);

                // wait for daemon
                daemon1.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(4, block4a.Hash, daemon1.CoreDaemon);

                // continue with tied branch
                var block4b = daemon1.MineAndAddEmptyBlock(block3b);

                // check that 4a is still current as it was first
                daemon1.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(4, block4a.Hash, daemon1.CoreDaemon);

                // resolve tie split, with other chain winning
                var block5b = daemon1.MineAndAddEmptyBlock(block4b);

                // check that blockchain reorged to the winning chain
                daemon1.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(5, block5b.Hash, daemon1.CoreDaemon);

                // continue on winning fork
                var block6b = daemon1.MineAndAddEmptyBlock(block5b);

                // check that blockchain continued on the winning chain
                daemon1.WaitForUpdate();
                AssertMethods.AssertDaemonAtBlock(6, block6b.Hash, daemon1.CoreDaemon);

                // 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();
                    AssertMethods.AssertDaemonAtBlock(6, block6b.Hash, daemon2.CoreDaemon);

                    // 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);
                        }
                }
            }
        }
Beispiel #8
0
        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);
                        }
                }
            }
        }