Exemple #1
0
        /// <summary>
        /// Creates the test chain with some default blocks and txs.
        /// </summary>
        /// <param name="network">Network to create the chain on.</param>
        /// <param name="scriptPubKey">Public key to create blocks/txs with.</param>
        /// <returns>Context object representing the test chain.</returns>
        public static async Task <ITestChainContext> CreateAsync(Network network, Script scriptPubKey, string dataDir)
        {
            var nodeSettings = new NodeSettings(network, args: new string[] { $"-datadir={dataDir}" });

            ILoggerFactory    loggerFactory    = nodeSettings.LoggerFactory;
            IDateTimeProvider dateTimeProvider = DateTimeProvider.Default;

            network.Consensus.Options = new ConsensusOptions();
            network.Consensus.Rules   = new FullNodeBuilderConsensusExtension.PowConsensusRulesRegistration().GetRules();

            var consensusSettings             = new ConsensusSettings(nodeSettings);
            var chain                         = new ConcurrentChain(network);
            InMemoryCoinView inMemoryCoinView = new InMemoryCoinView(chain.Tip.HashBlock);

            var cachedCoinView     = new CachedCoinView(inMemoryCoinView, DateTimeProvider.Default, loggerFactory);
            var networkPeerFactory = new NetworkPeerFactory(network, dateTimeProvider, loggerFactory, new PayloadProvider().DiscoverPayloads(), new SelfEndpointTracker());

            var peerAddressManager = new PeerAddressManager(DateTimeProvider.Default, nodeSettings.DataFolder, loggerFactory, new SelfEndpointTracker());
            var peerDiscovery      = new PeerDiscovery(new AsyncLoopFactory(loggerFactory), loggerFactory, network, networkPeerFactory, new NodeLifetime(), nodeSettings, peerAddressManager);
            var connectionSettings = new ConnectionManagerSettings(nodeSettings);
            var connectionManager  = new ConnectionManager(dateTimeProvider, loggerFactory, network, networkPeerFactory, nodeSettings, new NodeLifetime(), new NetworkPeerConnectionParameters(), peerAddressManager, new IPeerConnector[] { }, peerDiscovery, connectionSettings, new VersionProvider());

            var            blockPuller    = new LookaheadBlockPuller(chain, connectionManager, new LoggerFactory());
            var            peerBanning    = new PeerBanning(connectionManager, loggerFactory, dateTimeProvider, peerAddressManager);
            var            deployments    = new NodeDeployments(network, chain);
            ConsensusRules consensusRules = new PowConsensusRules(network, loggerFactory, dateTimeProvider, chain, deployments, consensusSettings, new Checkpoints(), inMemoryCoinView, new Mock <ILookaheadBlockPuller>().Object).Register();
            var            consensusLoop  = new ConsensusLoop(new AsyncLoopFactory(loggerFactory), new NodeLifetime(), chain, cachedCoinView, blockPuller, deployments, loggerFactory, new ChainState(new InvalidBlockHashStore(dateTimeProvider)), connectionManager, dateTimeProvider, new Signals.Signals(), consensusSettings, nodeSettings, peerBanning, consensusRules);
            await consensusLoop.StartAsync();

            var blockPolicyEstimator = new BlockPolicyEstimator(new MempoolSettings(nodeSettings), loggerFactory, nodeSettings);
            var mempool     = new TxMempool(dateTimeProvider, blockPolicyEstimator, loggerFactory, nodeSettings);
            var mempoolLock = new MempoolSchedulerLock();

            var minerSettings = new MinerSettings(nodeSettings);

            // Simple block creation, nothing special yet:
            PowBlockDefinition blockDefinition = new PowBlockDefinition(consensusLoop, dateTimeProvider, loggerFactory, mempool, mempoolLock, minerSettings, network, consensusRules);
            BlockTemplate      newBlock        = blockDefinition.Build(chain.Tip, scriptPubKey);

            chain.SetTip(newBlock.Block.Header);

            RuleContext ruleContext = consensusRules.CreateRuleContext(new ValidationContext {
                Block = newBlock.Block
            }, consensusLoop.Tip);

            ruleContext.MinedBlock = true;
            await consensusLoop.ValidateAndExecuteBlockAsync(ruleContext);

            List <BlockInfo> blockinfo = CreateBlockInfoList();

            // We can't make transactions until we have inputs
            // Therefore, load 100 blocks :)
            int baseheight = 0;
            var blocks     = new List <Block>();
            var srcTxs     = new List <Transaction>();

            for (int i = 0; i < blockinfo.Count; ++i)
            {
                Block currentBlock = Block.Load(newBlock.Block.ToBytes(network.Consensus.ConsensusFactory), network);
                currentBlock.Header.HashPrevBlock = chain.Tip.HashBlock;
                currentBlock.Header.Version       = 1;
                currentBlock.Header.Time          = Utils.DateTimeToUnixTime(chain.Tip.GetMedianTimePast()) + 1;

                Transaction txCoinbase = network.CreateTransaction(currentBlock.Transactions[0].ToBytes());
                txCoinbase.Inputs.Clear();
                txCoinbase.Version = 1;
                txCoinbase.AddInput(new TxIn(new Script(new[] { Op.GetPushOp(blockinfo[i].extraNonce), Op.GetPushOp(chain.Height) })));
                // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
                txCoinbase.AddOutput(new TxOut(Money.Zero, new Script()));
                currentBlock.Transactions[0] = txCoinbase;

                if (srcTxs.Count == 0)
                {
                    baseheight = chain.Height;
                }
                if (srcTxs.Count < 4)
                {
                    srcTxs.Add(currentBlock.Transactions[0]);
                }

                currentBlock.UpdateMerkleRoot();

                currentBlock.Header.Nonce = blockinfo[i].nonce;

                chain.SetTip(currentBlock.Header);
                RuleContext ruleContextForBlock = consensusRules.CreateRuleContext(new ValidationContext {
                    Block = currentBlock
                }, consensusLoop.Tip);
                ruleContextForBlock.MinedBlock = true;
                await consensusLoop.ValidateAndExecuteBlockAsync(ruleContextForBlock);

                blocks.Add(currentBlock);
            }

            // Just to make sure we can still make simple blocks
            blockDefinition = new PowBlockDefinition(consensusLoop, dateTimeProvider, loggerFactory, mempool, mempoolLock, minerSettings, network, consensusRules);
            newBlock        = blockDefinition.Build(chain.Tip, scriptPubKey);

            var mempoolValidator = new MempoolValidator(mempool, mempoolLock, dateTimeProvider, new MempoolSettings(nodeSettings), chain, cachedCoinView, loggerFactory, nodeSettings, consensusRules);

            return(new TestChainContext {
                MempoolValidator = mempoolValidator, SrcTxs = srcTxs
            });
        }
        /// <summary>
        /// Creates the test chain with some default blocks and txs.
        /// </summary>
        /// <param name="network">Network to create the chain on.</param>
        /// <param name="scriptPubKey">Public key to create blocks/txs with.</param>
        /// <returns>Context object representing the test chain.</returns>
        public static async Task <ITestChainContext> CreateAsync(Network network, Script scriptPubKey, string dataDir)
        {
            NodeSettings nodeSettings = new NodeSettings(network.Name, network).LoadArguments(new string[] { $"-datadir={dataDir}" });

            if (dataDir != null)
            {
                nodeSettings.DataDir = dataDir;
            }

            var loggerFactory = new ExtendedLoggerFactory();
            IDateTimeProvider dateTimeProvider = DateTimeProvider.Default;

            network.Consensus.Options = new PowConsensusOptions();
            ConsensusSettings     consensusSettings  = new ConsensusSettings(nodeSettings, loggerFactory);
            PowConsensusValidator consensusValidator = new PowConsensusValidator(network, new Checkpoints(), dateTimeProvider, loggerFactory);
            ConcurrentChain       chain              = new ConcurrentChain(network);
            CachedCoinView        cachedCoinView     = new CachedCoinView(new InMemoryCoinView(chain.Tip.HashBlock), DateTimeProvider.Default, loggerFactory);
            NetworkPeerFactory    networkPeerFactory = new NetworkPeerFactory(network, dateTimeProvider, loggerFactory);

            var peerAddressManager = new PeerAddressManager(nodeSettings.DataFolder, loggerFactory);
            var peerDiscovery      = new PeerDiscovery(new AsyncLoopFactory(loggerFactory), loggerFactory, Network.PurpleMain, networkPeerFactory, new NodeLifetime(), nodeSettings, peerAddressManager);
            var connectionManager  = new ConnectionManager(dateTimeProvider, loggerFactory, network, networkPeerFactory, nodeSettings, new NodeLifetime(), new NetworkPeerConnectionParameters(), peerAddressManager, new IPeerConnector[] { }, peerDiscovery);

            LookaheadBlockPuller blockPuller    = new LookaheadBlockPuller(chain, connectionManager, new LoggerFactory());
            PeerBanning          peerBanning    = new PeerBanning(connectionManager, loggerFactory, dateTimeProvider, nodeSettings);
            NodeDeployments      deployments    = new NodeDeployments(network, chain);
            ConsensusRules       consensusRules = new ConsensusRules(network, loggerFactory, dateTimeProvider, chain, deployments, consensusSettings, new Checkpoints()).Register(new FullNodeBuilderConsensusExtension.CoreConsensusRules());
            ConsensusLoop        consensus      = new ConsensusLoop(new AsyncLoopFactory(loggerFactory), consensusValidator, new NodeLifetime(), chain, cachedCoinView, blockPuller, deployments, loggerFactory, new ChainState(new InvalidBlockHashStore(dateTimeProvider)), connectionManager, dateTimeProvider, new Signals.Signals(), consensusSettings, nodeSettings, peerBanning, consensusRules);
            await consensus.StartAsync();

            BlockPolicyEstimator blockPolicyEstimator = new BlockPolicyEstimator(new MempoolSettings(nodeSettings), loggerFactory, nodeSettings);
            TxMempool            mempool     = new TxMempool(dateTimeProvider, blockPolicyEstimator, loggerFactory, nodeSettings);
            MempoolSchedulerLock mempoolLock = new MempoolSchedulerLock();

            // Simple block creation, nothing special yet:
            PowBlockAssembler blockAssembler = CreatePowBlockAssembler(network, consensus, chain, mempoolLock, mempool, dateTimeProvider, loggerFactory);
            BlockTemplate     newBlock       = blockAssembler.CreateNewBlock(scriptPubKey);

            chain.SetTip(newBlock.Block.Header);
            await consensus.ValidateAndExecuteBlockAsync(new RuleContext(new BlockValidationContext {
                Block = newBlock.Block
            }, network.Consensus, consensus.Tip) { CheckPow = false, CheckMerkleRoot = false });

            List <BlockInfo> blockinfo = CreateBlockInfoList();

            // We can't make transactions until we have inputs
            // Therefore, load 100 blocks :)
            int                baseheight = 0;
            List <Block>       blocks     = new List <Block>();
            List <Transaction> srcTxs     = new List <Transaction>();

            for (int i = 0; i < blockinfo.Count; ++i)
            {
                Block currentBlock = newBlock.Block.Clone(); // pointer for convenience
                currentBlock.Header.HashPrevBlock = chain.Tip.HashBlock;
                currentBlock.Header.Version       = 1;
                currentBlock.Header.Time          = Utils.DateTimeToUnixTime(chain.Tip.GetMedianTimePast()) + 1;
                Transaction txCoinbase = currentBlock.Transactions[0].Clone();
                txCoinbase.Inputs.Clear();
                txCoinbase.Version = 1;
                txCoinbase.AddInput(new TxIn(new Script(new[] { Op.GetPushOp(blockinfo[i].extraNonce), Op.GetPushOp(chain.Height) })));
                // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
                txCoinbase.AddOutput(new TxOut(Money.Zero, new Script()));
                currentBlock.Transactions[0] = txCoinbase;

                if (srcTxs.Count == 0)
                {
                    baseheight = chain.Height;
                }
                if (srcTxs.Count < 4)
                {
                    srcTxs.Add(currentBlock.Transactions[0]);
                }
                currentBlock.UpdateMerkleRoot();

                currentBlock.Header.Nonce = blockinfo[i].nonce;

                chain.SetTip(currentBlock.Header);
                await consensus.ValidateAndExecuteBlockAsync(new RuleContext(new BlockValidationContext {
                    Block = currentBlock
                }, network.Consensus, consensus.Tip) { CheckPow = false, CheckMerkleRoot = false });

                blocks.Add(currentBlock);
            }

            // Just to make sure we can still make simple blocks
            blockAssembler = CreatePowBlockAssembler(network, consensus, chain, mempoolLock, mempool, dateTimeProvider, loggerFactory);
            newBlock       = blockAssembler.CreateNewBlock(scriptPubKey);

            MempoolValidator mempoolValidator = new MempoolValidator(mempool, mempoolLock, consensusValidator, dateTimeProvider, new MempoolSettings(nodeSettings), chain, cachedCoinView, loggerFactory, nodeSettings);

            return(new TestChainContext {
                MempoolValidator = mempoolValidator, SrcTxs = srcTxs
            });
        }