public void CreateNewBlock_WithScript_ValidatesTemplateUsingRuleContext() { var newOptions = new PowConsensusOptions() { MaxBlockWeight = 1500 }; this.ExecuteWithConsensusOptions(newOptions, () => { var chain = GenerateChainWithHeight(5, this.network, this.key); this.dateTimeProvider.Setup(d => d.GetAdjustedTimeAsUnixTimestamp()) .Returns(new DateTime(2017, 1, 7, 0, 0, 1, DateTimeKind.Utc).ToUnixTimestamp()); this.consensusLoop.Setup(c => c.Tip) .Returns(chain.GetBlock(5)); var transaction = CreateTransaction(this.network, this.key, 5, new Money(400 * 1000 * 1000), new Key(), new uint256(124124)); var txFee = new Money(1000); SetupTxMempool(chain, this.network.Consensus.Options as PowConsensusOptions, txFee, transaction); var powBlockAssembler = new PowBlockAssembler(this.consensusLoop.Object, this.dateTimeProvider.Object, this.LoggerFactory.Object, this.txMempool.Object, new MempoolSchedulerLock(), this.network); var blockTemplate = powBlockAssembler.Build(chain.Tip, this.key.ScriptPubKey); Assert.NotNull(this.callbackRuleContext); Assert.False(this.callbackRuleContext.CheckMerkleRoot); Assert.False(this.callbackRuleContext.CheckPow); Assert.Equal(blockTemplate.Block.GetHash(), this.callbackRuleContext.BlockValidationContext.Block.GetHash()); Assert.Equal(chain.GetBlock(5).HashBlock, this.callbackRuleContext.ConsensusTip.HashBlock); Assert.Equal(1500, this.callbackRuleContext.Consensus.Option <PowConsensusOptions>().MaxBlockWeight); this.consensusLoop.Verify(); }); }
public void CreateNewBlock_WithScript_ReturnsBlockTemplate() { this.ExecuteWithConsensusOptions(new PowConsensusOptions(), () => { var chain = GenerateChainWithHeight(5, this.network, this.key); this.dateTimeProvider.Setup(d => d.GetAdjustedTimeAsUnixTimestamp()) .Returns(new DateTime(2017, 1, 7, 0, 0, 1, DateTimeKind.Utc).ToUnixTimestamp()); var transaction = CreateTransaction(this.network, this.key, 5, new Money(400 * 1000 * 1000), new Key(), new uint256(124124)); var txFee = new Money(1000); SetupTxMempool(chain, this.network.Consensus.Options as PowConsensusOptions, txFee, transaction); var powBlockAssembler = new PowBlockAssembler(this.consensusLoop.Object, this.dateTimeProvider.Object, this.LoggerFactory.Object, this.txMempool.Object, new MempoolSchedulerLock(), this.network); var blockTemplate = powBlockAssembler.Build(chain.Tip, this.key.ScriptPubKey); Assert.Null(blockTemplate.CoinbaseCommitment); Assert.Equal(new Money(1000), blockTemplate.TotalFee); Assert.Equal(2, blockTemplate.TxSigOpsCost.Count); Assert.Equal(-1, blockTemplate.TxSigOpsCost[0]); Assert.Equal(2, blockTemplate.TxSigOpsCost[1]); Assert.Equal(2, blockTemplate.VTxFees.Count); Assert.Equal(new Money(-1000), blockTemplate.VTxFees[0]); Assert.Equal(new Money(1000), blockTemplate.VTxFees[1]); Assert.Equal(2, blockTemplate.Block.Transactions.Count); Assert.Equal(536870912, blockTemplate.Block.Header.Version); Assert.Equal(2, blockTemplate.Block.Transactions.Count); var resultingTransaction = blockTemplate.Block.Transactions[0]; Assert.Equal((uint)new DateTime(2017, 1, 7, 0, 0, 1, DateTimeKind.Utc).ToUnixTimestamp(), resultingTransaction.Time); Assert.NotEmpty(resultingTransaction.Inputs); Assert.NotEmpty(resultingTransaction.Outputs); Assert.True(resultingTransaction.IsCoinBase); Assert.False(resultingTransaction.IsCoinStake); Assert.Equal(TxIn.CreateCoinbase(6).ScriptSig, resultingTransaction.Inputs[0].ScriptSig); Assert.Equal(this.powReward + txFee, resultingTransaction.TotalOut); Assert.Equal(this.key.ScriptPubKey, resultingTransaction.Outputs[0].ScriptPubKey); Assert.Equal(this.powReward + txFee, resultingTransaction.Outputs[0].Value); resultingTransaction = blockTemplate.Block.Transactions[1]; Assert.NotEmpty(resultingTransaction.Inputs); Assert.NotEmpty(resultingTransaction.Outputs); Assert.False(resultingTransaction.IsCoinBase); Assert.False(resultingTransaction.IsCoinStake); Assert.Equal(new Money(400 * 1000 * 1000), resultingTransaction.TotalOut); Assert.Equal(transaction.Inputs[0].PrevOut.Hash, resultingTransaction.Inputs[0].PrevOut.Hash); Assert.Equal(transaction.Inputs[0].ScriptSig, transaction.Inputs[0].ScriptSig); Assert.Equal(transaction.Outputs[0].ScriptPubKey, resultingTransaction.Outputs[0].ScriptPubKey); Assert.Equal(new Money(400 * 1000 * 1000), resultingTransaction.Outputs[0].Value); }); }
private static BlockTemplate CreateBlockTemplate(TestChainContext testChainContext, Script scriptPubKey, TxMempool mempool, MempoolSchedulerLock mempoolLock) { PowBlockAssembler blockAssembler = CreatePowBlockAssembler(testChainContext.Consensus, testChainContext.DateTimeProvider, testChainContext.LoggerFactory as LoggerFactory, mempool, mempoolLock, testChainContext.Network); BlockTemplate newBlock = blockAssembler.Build(testChainContext.Chain.Tip, scriptPubKey); int nHeight = testChainContext.Chain.Tip.Height + 1; // Height first in coinbase required for block.version=2 Transaction txCoinbase = newBlock.Block.Transactions[0]; txCoinbase.Inputs[0] = TxIn.CreateCoinbase(nHeight); return(newBlock); }
/// <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, args: new string[] { $"-datadir={dataDir}" }); var loggerFactory = nodeSettings.LoggerFactory; IDateTimeProvider dateTimeProvider = DateTimeProvider.Default; network.Consensus.Options = new PowConsensusOptions(); ConsensusSettings consensusSettings = new ConsensusSettings().Load(nodeSettings); 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, 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.Main, networkPeerFactory, new NodeLifetime(), nodeSettings, peerAddressManager); var connectionSettings = new ConnectionManagerSettings(); connectionSettings.Load(nodeSettings); var connectionManager = new ConnectionManager(dateTimeProvider, loggerFactory, network, networkPeerFactory, nodeSettings, new NodeLifetime(), new NetworkPeerConnectionParameters(), peerAddressManager, new IPeerConnector[] { }, peerDiscovery, connectionSettings); LookaheadBlockPuller blockPuller = new LookaheadBlockPuller(chain, connectionManager, new LoggerFactory()); PeerBanning peerBanning = new PeerBanning(connectionManager, loggerFactory, dateTimeProvider, peerAddressManager); NodeDeployments deployments = new NodeDeployments(network, chain); ConsensusRules consensusRules = new PowConsensusRules(network, loggerFactory, dateTimeProvider, chain, deployments, consensusSettings, new Checkpoints(), new InMemoryCoinView(new uint256()), new Mock <ILookaheadBlockPuller>().Object).Register(new FullNodeBuilderConsensusExtension.PowConsensusRulesRegistration()); 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(consensus, dateTimeProvider, loggerFactory as LoggerFactory, mempool, mempoolLock, network); BlockTemplate newBlock = blockAssembler.Build(chain.Tip, 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(consensus, dateTimeProvider, loggerFactory as LoggerFactory, mempool, mempoolLock, network); newBlock = blockAssembler.Build(chain.Tip, scriptPubKey); MempoolValidator mempoolValidator = new MempoolValidator(mempool, mempoolLock, consensusValidator, dateTimeProvider, new MempoolSettings(nodeSettings), chain, cachedCoinView, loggerFactory, nodeSettings); return(new TestChainContext { MempoolValidator = mempoolValidator, SrcTxs = srcTxs }); }