Example #1
0
        public Testnet3Rules(Logger logger)
            : base(logger)
        {
            this._genesisBlock =
                new Block
                (
                    header: new BlockHeader
                    (
                        version: 1,
                        previousBlock: 0,
                        merkleRoot: UInt256.Parse("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", NumberStyles.HexNumber),
                        time: 1296688602,
                        bits: 0x1D00FFFF,
                        nonce: 414098458
                    ),
                    transactions: ImmutableArray.Create
                    (
                        new Transaction
                        (
                            version: 1,
                            inputs: ImmutableArray.Create
                            (
                                new TxInput
                                (
                                    previousTxOutputKey: new TxOutputKey
                                    (
                                        txHash: 0,
                                        txOutputIndex: 0xFFFFFFFF
                                    ),
                                    scriptSignature: ImmutableArray.Create <byte>
                                    (
                                        0x04, 0xFF, 0xFF, 0x00, 0x1D, 0x01, 0x04, 0x45, 0x54, 0x68, 0x65, 0x20, 0x54, 0x69, 0x6D, 0x65,
                                        0x73, 0x20, 0x30, 0x33, 0x2F, 0x4A, 0x61, 0x6E, 0x2F, 0x32, 0x30, 0x30, 0x39, 0x20, 0x43, 0x68,
                                        0x61, 0x6E, 0x63, 0x65, 0x6C, 0x6C, 0x6F, 0x72, 0x20, 0x6F, 0x6E, 0x20, 0x62, 0x72, 0x69, 0x6E,
                                        0x6B, 0x20, 0x6F, 0x66, 0x20, 0x73, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x20, 0x62, 0x61, 0x69, 0x6C,
                                        0x6F, 0x75, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x62, 0x61, 0x6E, 0x6B, 0x73
                                    ),
                                    sequence: 0xFFFFFFFF
                                )
                            ),
                            outputs: ImmutableArray.Create
                            (
                                new TxOutput
                                (
                                    value: (UInt64)(50L * 100.MILLION()),
                                    scriptPublicKey: ImmutableArray.Create <byte>
                                    (
                                        0x41, 0x04, 0x67, 0x8A, 0xFD, 0xB0, 0xFE, 0x55, 0x48, 0x27, 0x19, 0x67, 0xF1, 0xA6, 0x71, 0x30,
                                        0xB7, 0x10, 0x5C, 0xD6, 0xA8, 0x28, 0xE0, 0x39, 0x09, 0xA6, 0x79, 0x62, 0xE0, 0xEA, 0x1F, 0x61,
                                        0xDE, 0xB6, 0x49, 0xF6, 0xBC, 0x3F, 0x4C, 0xEF, 0x38, 0xC4, 0xF3, 0x55, 0x04, 0xE5, 0x1E, 0xC1,
                                        0x12, 0xDE, 0x5C, 0x38, 0x4D, 0xF7, 0xBA, 0x0B, 0x8D, 0x57, 0x8A, 0x4C, 0x70, 0x2B, 0x6B, 0xF1,
                                        0x1D, 0x5F, 0xAC
                                    )
                                )
                            ),
                            lockTime: 0
                        )
                    )
                );

            Debug.Assert(_genesisBlock.Hash == UInt256.Parse("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943", NumberStyles.HexNumber));

            this._genesisChainedHeader = ChainedHeader.CreateForGenesisBlock(this._genesisBlock.Header);
        }
        private void TestRollback(ITestStorageProvider provider)
        {
            var logger = LogManager.CreateNullLogger();
            var sha256 = new SHA256Managed();

            var blockProvider = new MainnetBlockProvider();
            var blocks        = Enumerable.Range(0, 500).Select(x => blockProvider.GetBlock(x)).ToList();

            var genesisBlock  = blocks[0];
            var genesisHeader = new ChainedHeader(genesisBlock.Header, height: 0, totalWork: 0);
            var genesisChain  = Chain.CreateForGenesisBlock(genesisHeader);

            var rules = new MainnetRules(logger);

            using (var storageManager = provider.OpenStorageManager())
                using (var coreStorage = new CoreStorage(storageManager, logger))
                    using (var chainStateBuilder = new ChainStateBuilder(logger, rules, coreStorage))
                    {
                        // add blocks to storage
                        coreStorage.AddGenesisBlock(ChainedHeader.CreateForGenesisBlock(blocks[0].Header));
                        foreach (var block in blocks)
                        {
                            coreStorage.TryAddBlock(block);
                        }

                        // calculate utxo forward and store its state at each step along the way
                        var expectedUtxos = new List <List <UnspentTx> >();
                        for (var blockIndex = 0; blockIndex < blocks.Count; blockIndex++)
                        {
                            var block         = blocks[blockIndex];
                            var chainedHeader = new ChainedHeader(block.Header, blockIndex, 0);

                            chainStateBuilder.AddBlock(chainedHeader, block.Transactions);

                            using (var chainState = chainStateBuilder.ToImmutable())
                            {
                                expectedUtxos.Add(chainState.ReadUnspentTransactions().ToList());
                            }
                        }

                        // verify the utxo state before rolling back
                        //TODO verify the UTXO hash hard-coded here is correct
                        var expectedUtxoHash = UInt256.Parse("609eb5882e0b71a707fb876c844fbfe6b4579e04eb27c7c0cefbb7478bac737b", NumberStyles.HexNumber);
                        using (var utxoStream = new UtxoStream(logger, expectedUtxos.Last()))
                        {
                            var utxoHash = new UInt256(sha256.ComputeDoubleHash(utxoStream));
                            Assert.AreEqual(expectedUtxoHash, utxoHash);
                        }
                        expectedUtxos.RemoveAt(expectedUtxos.Count - 1);

                        // roll utxo backwards and validate its state at each step along the way
                        for (var blockIndex = blocks.Count - 1; blockIndex >= 1; blockIndex--)
                        {
                            var block         = blocks[blockIndex];
                            var chainedHeader = new ChainedHeader(block.Header, blockIndex, 0);
                            var blockTxes     = block.Transactions.Select((tx, txIndex) => new BlockTx(txIndex, 0, tx.Hash, /*pruned:*/ false, tx));

                            chainStateBuilder.RollbackBlock(chainedHeader, blockTxes);

                            var expectedUtxo = expectedUtxos.Last();
                            expectedUtxos.RemoveAt(expectedUtxos.Count - 1);

                            List <UnspentTx> actualUtxo;
                            using (var chainState = chainStateBuilder.ToImmutable())
                            {
                                actualUtxo = chainState.ReadUnspentTransactions().ToList();
                            }

                            CollectionAssert.AreEqual(expectedUtxo, actualUtxo, "UTXO differs at height: {0}".Format2(blockIndex));
                        }
                    }
        }
Example #3
0
 public void SetGenesisBlock(Block genesisBlock)
 {
     this._genesisBlock         = genesisBlock;
     this._genesisChainedHeader = ChainedHeader.CreateForGenesisBlock(this._genesisBlock.Header);
 }
Example #4
0
        public void TestSimpleChain()
        {
            // prepare test kernel
            var kernel = new StandardKernel(new ConsoleLoggingModule(), new MemoryStorageModule());

            kernel.Bind <CoreStorage>().ToSelf().InSingletonScope();
            var coreStorage = kernel.Get <CoreStorage>();

            // initialize data
            var fakeHeaders = new FakeHeaders();
            var header0     = fakeHeaders.Genesis();
            var header1     = fakeHeaders.Next();
            var header2     = fakeHeaders.Next();

            // store genesis block
            var chainedHeader0 = ChainedHeader.CreateForGenesisBlock(header0);

            coreStorage.AddGenesisBlock(chainedHeader0);

            // mock rules
            var mockRules = new Mock <IBlockchainRules>();

            mockRules.Setup(rules => rules.GenesisChainedHeader).Returns(chainedHeader0);
            kernel.Bind <IBlockchainRules>().ToConstant(mockRules.Object);

            // initialize the target chain worker
            using (var targetChainWorker = kernel.Get <TargetChainWorker>(new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue))))
            {
                // verify initial state
                Assert.AreEqual(null, targetChainWorker.TargetChain);

                // monitor event firing
                var targetChainChangedEvent   = new AutoResetEvent(false);
                var onTargetChainChangedCount = 0;
                targetChainWorker.OnTargetChainChanged += () => { onTargetChainChangedCount++; targetChainChangedEvent.Set(); };

                // start worker and wait for initial chain
                targetChainWorker.Start();
                targetChainChangedEvent.WaitOne();

                // verify chained to block 0
                Assert.AreEqual(chainedHeader0, targetChainWorker.TargetChain.LastBlock);
                AssertBlockListEquals(new[] { chainedHeader0 }, targetChainWorker.TargetChain.Blocks);
                Assert.AreEqual(1, onTargetChainChangedCount);

                // add block 1
                ChainedHeader chainedHeader1;
                coreStorage.TryChainHeader(header1, out chainedHeader1);

                // wait for worker
                targetChainChangedEvent.WaitOne();

                // verify chained to block 1
                Assert.AreEqual(chainedHeader1, targetChainWorker.TargetChain.LastBlock);
                AssertBlockListEquals(new[] { chainedHeader0, chainedHeader1 }, targetChainWorker.TargetChain.Blocks);
                Assert.AreEqual(2, onTargetChainChangedCount);

                // add block 2
                ChainedHeader chainedHeader2;
                coreStorage.TryChainHeader(header2, out chainedHeader2);

                // wait for worker
                targetChainChangedEvent.WaitOne();

                // verify chained to block 2
                Assert.AreEqual(chainedHeader2, targetChainWorker.TargetChain.LastBlock);
                AssertBlockListEquals(new[] { chainedHeader0, chainedHeader1, chainedHeader2 }, targetChainWorker.TargetChain.Blocks);
                Assert.AreEqual(3, onTargetChainChangedCount);

                // verify no other work was done
                Assert.IsFalse(targetChainChangedEvent.WaitOne(50));
            }
        }
Example #5
0
        public void TestReverseChaining()
        {
            // prepare test kernel
            var kernel             = new StandardKernel(new ConsoleLoggingModule(), new MemoryStorageModule(), new CoreCacheModule(), new RulesModule(RulesEnum.MainNet));
            var blockHeaderCache   = kernel.Get <BlockHeaderCache>();
            var chainedHeaderCache = kernel.Get <ChainedHeaderCache>();

            // mock rules
            var mockRules = Mock.Of <IBlockchainRules>();

            // initialize data
            var blockHeader0 = new BlockHeader(version: 0, previousBlock: 0, merkleRoot: 0, time: 0, bits: 0x1D00FFFF, nonce: 0);
            var blockHeader1 = new BlockHeader(version: 0, previousBlock: blockHeader0.Hash, merkleRoot: 0, time: 0, bits: 0x1D00FFFF, nonce: 0);
            var blockHeader2 = new BlockHeader(version: 0, previousBlock: blockHeader1.Hash, merkleRoot: 0, time: 0, bits: 0x1D00FFFF, nonce: 0);
            var blockHeader3 = new BlockHeader(version: 0, previousBlock: blockHeader2.Hash, merkleRoot: 0, time: 0, bits: 0x1D00FFFF, nonce: 0);
            var blockHeader4 = new BlockHeader(version: 0, previousBlock: blockHeader3.Hash, merkleRoot: 0, time: 0, bits: 0x1D00FFFF, nonce: 0);

            // store genesis block
            blockHeaderCache[blockHeader0.Hash]   = blockHeader0;
            chainedHeaderCache[blockHeader0.Hash] = ChainedHeader.CreateForGenesisBlock(blockHeader0);

            // initialize the chaining worker
            using (var chainingWorker = kernel.Get <ChainingWorker>(new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: false, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue))))
            {
                // monitor event firing
                var workStoppedEvent = new AutoResetEvent(false);
                chainingWorker.OnWorkStopped += () => workStoppedEvent.Set();

                // start and wait for initial chaining
                chainingWorker.Start();
                workStoppedEvent.WaitOne();

                // add block 4
                blockHeaderCache[blockHeader4.Hash] = blockHeader4;

                // wait for chaining
                workStoppedEvent.WaitOne();

                // verify nothing chained
                Assert.AreEqual(1, chainedHeaderCache.Count);
                Assert.AreEqual(1, chainingWorker.UnchainedByPrevious.Count);
                AssertSingleUnchainedHeaderByPrevious(blockHeader4, chainingWorker.UnchainedByPrevious);

                // add block 3
                blockHeaderCache[blockHeader3.Hash] = blockHeader3;

                // wait for chaining
                workStoppedEvent.WaitOne();

                // verify nothing chained
                Assert.AreEqual(1, chainedHeaderCache.Count);
                Assert.AreEqual(2, chainingWorker.UnchainedByPrevious.Count);
                AssertSingleUnchainedHeaderByPrevious(blockHeader3, chainingWorker.UnchainedByPrevious);
                AssertSingleUnchainedHeaderByPrevious(blockHeader4, chainingWorker.UnchainedByPrevious);

                // add block 2
                blockHeaderCache[blockHeader2.Hash] = blockHeader2;

                // wait for chaining
                workStoppedEvent.WaitOne();

                // verify nothing chained
                Assert.AreEqual(1, chainedHeaderCache.Count);
                Assert.AreEqual(3, chainingWorker.UnchainedByPrevious.Count);
                Assert.IsTrue(chainingWorker.UnchainedByPrevious.ContainsKey(blockHeader2.PreviousBlock));
                AssertSingleUnchainedHeaderByPrevious(blockHeader2, chainingWorker.UnchainedByPrevious);
                AssertSingleUnchainedHeaderByPrevious(blockHeader3, chainingWorker.UnchainedByPrevious);
                AssertSingleUnchainedHeaderByPrevious(blockHeader4, chainingWorker.UnchainedByPrevious);

                // add block 1
                blockHeaderCache[blockHeader1.Hash] = blockHeader1;

                // wait for chaining
                workStoppedEvent.WaitOne();

                // verify all blocks chained
                Assert.AreEqual(5, chainedHeaderCache.Count);
                Assert.AreEqual(0, chainingWorker.UnchainedByPrevious.Count);

                // verify block 1
                Assert.IsTrue(chainedHeaderCache.ContainsKey(blockHeader1.Hash));
                Assert.AreEqual(
                    new ChainedHeader(
                        blockHeader: blockHeader1,
                        height: 1,
                        totalWork: new[] { blockHeader0, blockHeader1 }.SumBigInteger(x => x.CalculateWork())
                        )
                    , chainedHeaderCache[blockHeader1.Hash]);

                // verify block 2
                Assert.IsTrue(chainedHeaderCache.ContainsKey(blockHeader2.Hash));
                Assert.AreEqual(
                    new ChainedHeader(
                        blockHeader: blockHeader2,
                        height: 2,
                        totalWork: new[] { blockHeader0, blockHeader1, blockHeader2 }.SumBigInteger(x => x.CalculateWork())
                        )
                    , chainedHeaderCache[blockHeader2.Hash]);

                // verify block 3
                Assert.IsTrue(chainedHeaderCache.ContainsKey(blockHeader3.Hash));
                Assert.AreEqual(
                    new ChainedHeader(
                        blockHeader: blockHeader3,
                        height: 3,
                        totalWork: new[] { blockHeader0, blockHeader1, blockHeader2, blockHeader3 }.SumBigInteger(x => x.CalculateWork())
                        )
                    , chainedHeaderCache[blockHeader3.Hash]);

                // verify block 4
                Assert.IsTrue(chainedHeaderCache.ContainsKey(blockHeader4.Hash));
                Assert.AreEqual(
                    new ChainedHeader(
                        blockHeader: blockHeader4,
                        height: 4,
                        totalWork: new[] { blockHeader0, blockHeader1, blockHeader2, blockHeader3, blockHeader4 }.SumBigInteger(x => x.CalculateWork())
                        )
                    , chainedHeaderCache[blockHeader4.Hash]);

                // verify no other work was done
                Assert.IsFalse(workStoppedEvent.WaitOne(0));
            }
        }
Example #6
0
        private void TestRollback(ITestStorageProvider provider)
        {
            ConsoleLoggingModule.Configure();
            var logger = LogManager.GetCurrentClassLogger();

            var blockCount = 10.THOUSAND();
            var checkUtxoHashFrequencey = 1000;

            var blockProvider = new TestNet3BlockProvider();
            var blocks        = blockProvider.ReadBlocks().Take(blockCount).ToList();

            var genesisBlock  = blocks[0];
            var genesisHeader = new ChainedHeader(genesisBlock.Header, height: 0, totalWork: 0, dateSeen: DateTimeOffset.Now);
            var genesisChain  = Chain.CreateForGenesisBlock(genesisHeader);

            var chainParams = new Testnet3Params();
            var rules       = new CoreRules(chainParams)
            {
                IgnoreScripts      = true,
                IgnoreSignatures   = true,
                IgnoreScriptErrors = true
            };

            using (var storageManager = provider.OpenStorageManager())
                using (var coreStorage = new CoreStorage(storageManager))
                    using (var chainStateBuilder = new ChainStateBuilder(rules, coreStorage, storageManager))
                    {
                        // add blocks to storage
                        coreStorage.AddGenesisBlock(ChainedHeader.CreateForGenesisBlock(blocks[0].Header));
                        foreach (var block in blocks)
                        {
                            coreStorage.TryAddBlock(block);
                        }

                        // store empty utxo hash
                        var expectedUtxoHashes = new List <UInt256>();
                        using (var chainState = chainStateBuilder.ToImmutable())
                            expectedUtxoHashes.Add(UtxoCommitment.ComputeHash(chainState));

                        // calculate utxo forward and store its state at each step along the way
                        for (var blockIndex = 0; blockIndex < blocks.Count; blockIndex++)
                        {
                            logger.Info($"Adding: {blockIndex:N0}");

                            var block         = blocks[blockIndex];
                            var chainedHeader = new ChainedHeader(block.Header, blockIndex, 0, DateTimeOffset.Now);

                            chainStateBuilder.AddBlockAsync(chainedHeader, block.Transactions.Select(
                                                                (tx, txIndex) => BlockTx.Create(txIndex, tx))).Wait();

                            if (blockIndex % checkUtxoHashFrequencey == 0 || blockIndex == blocks.Count - 1)
                            {
                                using (var chainState = chainStateBuilder.ToImmutable())
                                    expectedUtxoHashes.Add(UtxoCommitment.ComputeHash(chainState));
                            }
                        }

                        // verify the utxo state before rolling back
                        var expectedLastUtxoHash = UInt256.ParseHex("5f155c7d8a5c850d5fb2566aec5110caa40e270184126d17022ae9780fd65fd9");
                        Assert.AreEqual(expectedLastUtxoHash, expectedUtxoHashes.Last());
                        expectedUtxoHashes.RemoveAt(expectedUtxoHashes.Count - 1);

                        // roll utxo backwards and validate its state at each step along the way
                        for (var blockIndex = blocks.Count - 1; blockIndex >= 0; blockIndex--)
                        {
                            logger.Info($"Rolling back: {blockIndex:N0}");

                            var block         = blocks[blockIndex];
                            var chainedHeader = new ChainedHeader(block.Header, blockIndex, 0, DateTimeOffset.Now);
                            var blockTxes     = block.Transactions.Select((tx, txIndex) => BlockTx.Create(txIndex, tx));

                            chainStateBuilder.RollbackBlock(chainedHeader, blockTxes);

                            if ((blockIndex - 1) % checkUtxoHashFrequencey == 0 || blockIndex == 0)
                            {
                                var expectedUtxoHash = expectedUtxoHashes.Last();
                                expectedUtxoHashes.RemoveAt(expectedUtxoHashes.Count - 1);

                                using (var chainState = chainStateBuilder.ToImmutable())
                                    Assert.AreEqual(expectedUtxoHash, UtxoCommitment.ComputeHash(chainState));
                            }
                        }

                        // verify chain state was rolled all the way back
                        Assert.AreEqual(-1, chainStateBuilder.Chain.Height);
                        Assert.AreEqual(0, expectedUtxoHashes.Count);

                        // calculate utxo forward again
                        for (var blockIndex = 0; blockIndex < blocks.Count; blockIndex++)
                        {
                            logger.Info($"Adding: {blockIndex:N0}");

                            var block         = blocks[blockIndex];
                            var chainedHeader = new ChainedHeader(block.Header, blockIndex, 0, DateTimeOffset.Now);

                            chainStateBuilder.AddBlockAsync(chainedHeader, block.Transactions.Select(
                                                                (tx, txIndex) => BlockTx.Create(txIndex, tx))).Wait();
                        }

                        // verify final utxo state again
                        using (var chainState = chainStateBuilder.ToImmutable())
                            Assert.AreEqual(expectedLastUtxoHash, UtxoCommitment.ComputeHash(chainState));
                    }
        }
Example #7
0
 public MainnetParams()
 {
     GenesisChainedHeader = ChainedHeader.CreateForGenesisBlock(genesisBlock.Header);
 }
Example #8
0
        public MainnetRules(Logger logger)
        {
            this.logger = logger;

            this.highestTarget = UInt256.Parse("00000000FFFF0000000000000000000000000000000000000000000000000000", NumberStyles.HexNumber);

            this.genesisBlock =
                new Block
                (
                    header: new BlockHeader
                    (
                        version: 1,
                        previousBlock: 0,
                        merkleRoot: UInt256.Parse("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", NumberStyles.HexNumber),
                        time: 1231006505,
                        bits: 0x1D00FFFF,
                        nonce: 2083236893
                    ),
                    transactions: ImmutableArray.Create
                    (
                        new Transaction
                        (
                            version: 1,
                            inputs: ImmutableArray.Create
                            (
                                new TxInput
                                (
                                    previousTxOutputKey: new TxOutputKey
                                    (
                                        txHash: 0,
                                        txOutputIndex: 0xFFFFFFFF
                                    ),
                                    scriptSignature: ImmutableArray.Create <byte>
                                    (
                                        0x04, 0xFF, 0xFF, 0x00, 0x1D, 0x01, 0x04, 0x45, 0x54, 0x68, 0x65, 0x20, 0x54, 0x69, 0x6D, 0x65,
                                        0x73, 0x20, 0x30, 0x33, 0x2F, 0x4A, 0x61, 0x6E, 0x2F, 0x32, 0x30, 0x30, 0x39, 0x20, 0x43, 0x68,
                                        0x61, 0x6E, 0x63, 0x65, 0x6C, 0x6C, 0x6F, 0x72, 0x20, 0x6F, 0x6E, 0x20, 0x62, 0x72, 0x69, 0x6E,
                                        0x6B, 0x20, 0x6F, 0x66, 0x20, 0x73, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x20, 0x62, 0x61, 0x69, 0x6C,
                                        0x6F, 0x75, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x62, 0x61, 0x6E, 0x6B, 0x73
                                    ),
                                    sequence: 0xFFFFFFFF
                                )
                            ),
                            outputs: ImmutableArray.Create
                            (
                                new TxOutput
                                (
                                    value: 50 * SATOSHI_PER_BTC,
                                    scriptPublicKey: ImmutableArray.Create <byte>
                                    (
                                        0x41, 0x04, 0x67, 0x8A, 0xFD, 0xB0, 0xFE, 0x55, 0x48, 0x27, 0x19, 0x67, 0xF1, 0xA6, 0x71, 0x30,
                                        0xB7, 0x10, 0x5C, 0xD6, 0xA8, 0x28, 0xE0, 0x39, 0x09, 0xA6, 0x79, 0x62, 0xE0, 0xEA, 0x1F, 0x61,
                                        0xDE, 0xB6, 0x49, 0xF6, 0xBC, 0x3F, 0x4C, 0xEF, 0x38, 0xC4, 0xF3, 0x55, 0x04, 0xE5, 0x1E, 0xC1,
                                        0x12, 0xDE, 0x5C, 0x38, 0x4D, 0xF7, 0xBA, 0x0B, 0x8D, 0x57, 0x8A, 0x4C, 0x70, 0x2B, 0x6B, 0xF1,
                                        0x1D, 0x5F, 0xAC
                                    )
                                )
                            ),
                            lockTime: 0
                        )
                    )
                );

            this.genesisChainedHeader = ChainedHeader.CreateForGenesisBlock(this.genesisBlock.Header);
        }
Example #9
0
        public void TestTargetChainReorganize()
        {
            // prepare test kernel
            var kernel = new StandardKernel(new ConsoleLoggingModule(), new MemoryStorageModule());

            kernel.Bind <CoreStorage>().ToSelf().InSingletonScope();
            var coreStorage = kernel.Get <CoreStorage>();

            // initialize data
            var fakeHeaders = new FakeHeaders();
            var header0     = fakeHeaders.Genesis();
            var header1     = fakeHeaders.Next();
            var header2     = fakeHeaders.Next();

            var fakeHeadersA = new FakeHeaders(fakeHeaders);
            var header3A     = fakeHeadersA.Next();
            var header4A     = fakeHeadersA.Next();
            var header5A     = fakeHeadersA.Next();

            var fakeHeadersB = new FakeHeaders(fakeHeaders);
            var header3B     = fakeHeadersB.Next();
            var header4B     = fakeHeadersB.Next(DataCalculator.ToCompact(UnitTestParams.Target2));

            // store genesis block
            var chainedHeader0 = ChainedHeader.CreateForGenesisBlock(header0);

            coreStorage.AddGenesisBlock(chainedHeader0);

            // mock chain params
            var mockChainParams = new Mock <IChainParams>();

            mockChainParams.Setup(rules => rules.GenesisChainedHeader).Returns(chainedHeader0);
            kernel.Bind <IChainParams>().ToConstant(mockChainParams.Object);

            // initialize the target chain worker
            using (var targetChainWorker = kernel.Get <TargetChainWorker>(new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue))))
            {
                // monitor event firing
                var targetChainChangedEvent   = new AutoResetEvent(false);
                var onTargetChainChangedCount = 0;
                targetChainWorker.OnTargetChainChanged += () => { onTargetChainChangedCount++; targetChainChangedEvent.Set(); };

                // start worker and wait for initial chain
                targetChainWorker.Start();
                targetChainChangedEvent.WaitOne();

                // verify chained to block 0
                Assert.AreEqual(chainedHeader0, targetChainWorker.TargetChain.LastBlock);
                AssertBlockListEquals(new[] { chainedHeader0 }, targetChainWorker.TargetChain.Blocks);
                Assert.AreEqual(1, onTargetChainChangedCount);

                // add block 1
                ChainedHeader chainedHeader1;
                coreStorage.TryChainHeader(header1, out chainedHeader1);

                // wait for worker
                targetChainChangedEvent.WaitOne();

                // verify chained to block 1
                Assert.AreEqual(chainedHeader1, targetChainWorker.TargetChain.LastBlock);
                AssertBlockListEquals(new[] { chainedHeader0, chainedHeader1 }, targetChainWorker.TargetChain.Blocks);
                Assert.AreEqual(2, onTargetChainChangedCount);

                // add block 2
                ChainedHeader chainedHeader2;
                coreStorage.TryChainHeader(header2, out chainedHeader2);

                // wait for worker
                targetChainChangedEvent.WaitOne();

                // verify chained to block 2
                Assert.AreEqual(chainedHeader2, targetChainWorker.TargetChain.LastBlock);
                AssertBlockListEquals(new[] { chainedHeader0, chainedHeader1, chainedHeader2 }, targetChainWorker.TargetChain.Blocks);
                Assert.AreEqual(3, onTargetChainChangedCount);

                // add block 3A
                ChainedHeader chainedHeader3A;
                coreStorage.TryChainHeader(header3A, out chainedHeader3A);

                // wait for worker
                targetChainChangedEvent.WaitOne();

                // verify chained to block 3A
                Assert.AreEqual(chainedHeader3A, targetChainWorker.TargetChain.LastBlock);
                AssertBlockListEquals(new[] { chainedHeader0, chainedHeader1, chainedHeader2, chainedHeader3A }, targetChainWorker.TargetChain.Blocks);
                Assert.AreEqual(4, onTargetChainChangedCount);

                // add block 4A
                ChainedHeader chainedHeader4A;
                coreStorage.TryChainHeader(header4A, out chainedHeader4A);

                // wait for worker
                targetChainChangedEvent.WaitOne();

                // verify chained to block 4A
                Assert.AreEqual(chainedHeader4A, targetChainWorker.TargetChain.LastBlock);
                AssertBlockListEquals(new[] { chainedHeader0, chainedHeader1, chainedHeader2, chainedHeader3A, chainedHeader4A }, targetChainWorker.TargetChain.Blocks);
                Assert.AreEqual(5, onTargetChainChangedCount);

                // add block 5A
                ChainedHeader chainedHeader5A;
                coreStorage.TryChainHeader(header5A, out chainedHeader5A);

                // wait for worker
                targetChainChangedEvent.WaitOne();

                // verify chained to block 5A
                Assert.AreEqual(chainedHeader5A, targetChainWorker.TargetChain.LastBlock);
                AssertBlockListEquals(new[] { chainedHeader0, chainedHeader1, chainedHeader2, chainedHeader3A, chainedHeader4A, chainedHeader5A }, targetChainWorker.TargetChain.Blocks);
                Assert.AreEqual(6, onTargetChainChangedCount);

                // add block 3B
                ChainedHeader chainedHeader3B;
                coreStorage.TryChainHeader(header3B, out chainedHeader3B);

                // wait for worker, it should not fire
                Assert.IsFalse(targetChainChangedEvent.WaitOne(50));

                // verify no chaining done
                Assert.AreEqual(chainedHeader5A, targetChainWorker.TargetChain.LastBlock);
                AssertBlockListEquals(new[] { chainedHeader0, chainedHeader1, chainedHeader2, chainedHeader3A, chainedHeader4A, chainedHeader5A }, targetChainWorker.TargetChain.Blocks);
                Assert.AreEqual(6, onTargetChainChangedCount);

                // add block 4B
                ChainedHeader chainedHeader4B;
                coreStorage.TryChainHeader(header4B, out chainedHeader4B);

                // wait for worker
                targetChainChangedEvent.WaitOne();

                // verify chained to block 4B
                Assert.AreEqual(chainedHeader4B, targetChainWorker.TargetChain.LastBlock);
                AssertBlockListEquals(new[] { chainedHeader0, chainedHeader1, chainedHeader2, chainedHeader3B, chainedHeader4B }, targetChainWorker.TargetChain.Blocks);
                Assert.AreEqual(7, onTargetChainChangedCount);

                // verify no other work was done
                Assert.IsFalse(targetChainChangedEvent.WaitOne(50));
            }
        }
Example #10
0
        public Testnet2Rules(Logger logger, BlockHeaderCache blockHeaderCache)
            : base(logger, blockHeaderCache)
        {
            this._genesisBlock =
                new Block
                (
                    header: new BlockHeader
                    (
                        version: 1,
                        previousBlock: 0,
                        merkleRoot: UInt256.Parse("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", NumberStyles.HexNumber),
                        time: 1296688602,
                        bits: 0x207FFFFF,
                        nonce: 2
                    ),
                    transactions: ImmutableArray.Create
                    (
                        new Transaction
                        (
                            version: 1,
                            inputs: ImmutableArray.Create
                            (
                                new TxInput
                                (
                                    previousTxOutputKey: new TxOutputKey
                                    (
                                        txHash: 0,
                                        txOutputIndex: 0xFFFFFFFF
                                    ),
                                    scriptSignature: ImmutableArray.Create <byte>
                                    (
                                        0x04, 0xFF, 0xFF, 0x00, 0x1D, 0x01, 0x04, 0x45, 0x54, 0x68, 0x65, 0x20, 0x54, 0x69, 0x6D, 0x65,
                                        0x73, 0x20, 0x30, 0x33, 0x2F, 0x4A, 0x61, 0x6E, 0x2F, 0x32, 0x30, 0x30, 0x39, 0x20, 0x43, 0x68,
                                        0x61, 0x6E, 0x63, 0x65, 0x6C, 0x6C, 0x6F, 0x72, 0x20, 0x6F, 0x6E, 0x20, 0x62, 0x72, 0x69, 0x6E,
                                        0x6B, 0x20, 0x6F, 0x66, 0x20, 0x73, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x20, 0x62, 0x61, 0x69, 0x6C,
                                        0x6F, 0x75, 0x74, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x62, 0x61, 0x6E, 0x6B, 0x73
                                    ),
                                    sequence: 0xFFFFFFFF
                                )
                            ),
                            outputs: ImmutableArray.Create
                            (
                                new TxOutput
                                (
                                    value: (UInt64)(50L * 100.MILLION()),
                                    scriptPublicKey: ImmutableArray.Create <byte>
                                    (
                                        0x41, 0x04, 0x67, 0x8A, 0xFD, 0xB0, 0xFE, 0x55, 0x48, 0x27, 0x19, 0x67, 0xF1, 0xA6, 0x71, 0x30,
                                        0xB7, 0x10, 0x5C, 0xD6, 0xA8, 0x28, 0xE0, 0x39, 0x09, 0xA6, 0x79, 0x62, 0xE0, 0xEA, 0x1F, 0x61,
                                        0xDE, 0xB6, 0x49, 0xF6, 0xBC, 0x3F, 0x4C, 0xEF, 0x38, 0xC4, 0xF3, 0x55, 0x04, 0xE5, 0x1E, 0xC1,
                                        0x12, 0xDE, 0x5C, 0x38, 0x4D, 0xF7, 0xBA, 0x0B, 0x8D, 0x57, 0x8A, 0x4C, 0x70, 0x2B, 0x6B, 0xF1,
                                        0x1D, 0x5F, 0xAC
                                    )
                                )
                            ),
                            lockTime: 0
                        )
                    )
                );

            Debug.Assert(_genesisBlock.Hash == UInt256.Parse("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206", NumberStyles.HexNumber));

            this._genesisChainedHeader = ChainedHeader.CreateForGenesisBlock(this._genesisBlock.Header);
        }
Example #11
0
 public void SetGenesisBlock(Block genesisBlock)
 {
     GenesisBlock         = genesisBlock;
     GenesisChainedHeader = ChainedHeader.CreateForGenesisBlock(genesisBlock.Header);
 }
Example #12
0
 public Testnet3Params()
 {
     GenesisChainedHeader = ChainedHeader.CreateForGenesisBlock(genesisBlock.Header);
 }