public ConsensusStats( CoinViewStack stack, CoinView coinView, ConsensusLoop consensusLoop, ChainState chainState, ConcurrentChain chain, IConnectionManager connectionManager, ILoggerFactory loggerFactory) { stack = new CoinViewStack(coinView); this.cache = stack.Find <CachedCoinView>(); this.dbreeze = stack.Find <DBreezeCoinView>(); this.bottom = stack.Bottom; this.consensusLoop = consensusLoop; this.lookaheadPuller = this.consensusLoop.Puller as LookaheadBlockPuller; this.lastSnapshot = consensusLoop.Validator.PerformanceCounter.Snapshot(); this.lastSnapshot2 = this.dbreeze?.PerformanceCounter.Snapshot(); this.lastSnapshot3 = this.cache?.PerformanceCounter.Snapshot(); this.chainState = chainState; this.chain = chain; this.connectionManager = connectionManager; this.logger = loggerFactory.CreateLogger(this.GetType().FullName); }
public void TestCacheCoinView() { using (NodeContext ctx = NodeContext.Create(this)) { Block genesis = ctx.Network.GetGenesis(); var genesisChainedHeader = new ChainedHeader(genesis.Header, ctx.Network.GenesisHash, 0); ChainedHeader chained = this.MakeNext(genesisChainedHeader, ctx.Network); var dateTimeProvider = new DateTimeProvider(); var cacheCoinView = new CachedCoinView(ctx.PersistentCoinView, dateTimeProvider, this.loggerFactory, new NodeStats(dateTimeProvider)); cacheCoinView.SaveChangesAsync(new UnspentOutputs[] { new UnspentOutputs(genesis.Transactions[0].GetHash(), new Coins(genesis.Transactions[0], 0)) }, null, genesisChainedHeader.HashBlock, chained.HashBlock).Wait(); Assert.NotNull(cacheCoinView.FetchCoinsAsync(new[] { genesis.Transactions[0].GetHash() }).Result.UnspentOutputs[0]); Assert.Null(cacheCoinView.FetchCoinsAsync(new[] { new uint256() }).Result.UnspentOutputs[0]); Assert.Equal(chained.HashBlock, cacheCoinView.GetTipHashAsync().Result); Assert.Null(ctx.PersistentCoinView.FetchCoinsAsync(new[] { genesis.Transactions[0].GetHash() }).Result.UnspentOutputs[0]); Assert.Equal(chained.Previous.HashBlock, ctx.PersistentCoinView.GetTipHashAsync().Result); cacheCoinView.FlushAsync().GetAwaiter().GetResult(); Assert.NotNull(ctx.PersistentCoinView.FetchCoinsAsync(new[] { genesis.Transactions[0].GetHash() }).Result.UnspentOutputs[0]); Assert.Equal(chained.HashBlock, ctx.PersistentCoinView.GetTipHashAsync().Result); //Assert.Null(ctx.PersistentCoinView.FetchCoinsAsync(new[] { new uint256() }).Result.UnspentOutputs[0]); //var previous = chained; //chained = MakeNext(MakeNext(genesisChainedBlock)); //chained = MakeNext(MakeNext(genesisChainedBlock)); //ctx.PersistentCoinView.SaveChangesAsync(new UnspentOutputs[0], previous.HashBlock, chained.HashBlock).Wait(); //Assert.Equal(chained.HashBlock, ctx.PersistentCoinView.GetTipHashAsync().GetAwaiter().GetResult()); //ctx.ReloadPersistentCoinView(); //Assert.Equal(chained.HashBlock, ctx.PersistentCoinView.GetTipHashAsync().GetAwaiter().GetResult()); //Assert.NotNull(ctx.PersistentCoinView.FetchCoinsAsync(new[] { genesis.Transactions[0].GetHash() }).Result.UnspentOutputs[0]); //Assert.Null(ctx.PersistentCoinView.FetchCoinsAsync(new[] { new uint256() }).Result.UnspentOutputs[0]); } }
public CoinviewTests() { this.network = new StraxMain(); this.dataFolder = TestBase.CreateDataFolder(this); this.dateTimeProvider = new DateTimeProvider(); this.loggerFactory = new ExtendedLoggerFactory(); this.nodeStats = new NodeStats(this.dateTimeProvider, this.loggerFactory); this.coindb = new DBreezeCoindb(this.network, this.dataFolder, this.dateTimeProvider, this.loggerFactory, this.nodeStats, new DBreezeSerializer(this.network.Consensus.ConsensusFactory)); this.coindb.Initialize(); this.chainIndexer = new ChainIndexer(this.network); this.stakeChainStore = new StakeChainStore(this.network, this.chainIndexer, (IStakedb)this.coindb, this.loggerFactory); this.stakeChainStore.Load(); this.rewindDataIndexCache = new RewindDataIndexCache(this.dateTimeProvider, this.network, new FinalizedBlockInfoRepository(new HashHeightPair()), new Checkpoints()); this.cachedCoinView = new CachedCoinView(this.network, new Checkpoints(), this.coindb, this.dateTimeProvider, this.loggerFactory, this.nodeStats, new ConsensusSettings(new NodeSettings(this.network)), this.stakeChainStore, this.rewindDataIndexCache); this.rewindDataIndexCache.Initialize(this.chainIndexer.Height, this.cachedCoinView); this.random = new Random(); ChainedHeader newTip = ChainedHeadersHelper.CreateConsecutiveHeaders(1000, this.chainIndexer.Tip, true, null, this.network).Last(); this.chainIndexer.SetTip(newTip); }
public void TestCacheCoinView() { using (NodeContext ctx = NodeContext.Create(this)) { Block genesis = ctx.Network.GetGenesis(); var genesisChainedHeader = new ChainedHeader(genesis.Header, ctx.Network.GenesisHash, 0); ChainedHeader chained = this.MakeNext(genesisChainedHeader, ctx.Network); var dateTimeProvider = new DateTimeProvider(); var cacheCoinView = new CachedCoinView(this.network, new Checkpoints(), ctx.Coindb, dateTimeProvider, this.loggerFactory, new NodeStats(dateTimeProvider, NodeSettings.Default(this.network), new Mock <IVersionProvider>().Object), new ConsensusSettings(new NodeSettings(this.network))); cacheCoinView.SaveChanges(new UnspentOutput[] { new UnspentOutput(new OutPoint(genesis.Transactions[0], 0), new Coins(0, genesis.Transactions[0].Outputs.First(), true)) }, new HashHeightPair(genesisChainedHeader), new HashHeightPair(chained)); Assert.NotNull(cacheCoinView.FetchCoins(new[] { new OutPoint(genesis.Transactions[0], 0) }).UnspentOutputs.Values.FirstOrDefault().Coins); Assert.Null(cacheCoinView.FetchCoins(new[] { new OutPoint() }).UnspentOutputs.Values.FirstOrDefault().Coins); Assert.Equal(new HashHeightPair(chained), cacheCoinView.GetTipHash()); Assert.Null(ctx.Coindb.FetchCoins(new[] { new OutPoint(genesis.Transactions[0], 0) }).UnspentOutputs.Values.FirstOrDefault().Coins); Assert.Equal(chained.Previous.HashBlock, ctx.Coindb.GetTipHash().Hash); cacheCoinView.Flush(); Assert.NotNull(ctx.Coindb.FetchCoins(new[] { new OutPoint(genesis.Transactions[0], 0) }).UnspentOutputs.Values.FirstOrDefault().Coins); Assert.Equal(chained.HashBlock, ctx.Coindb.GetTipHash().Hash); //Assert.Null(ctx.PersistentCoinView.FetchCoinsAsync(new[] { new uint256() }).Result.UnspentOutputs[0]); //var previous = chained; //chained = MakeNext(MakeNext(genesisChainedBlock)); //chained = MakeNext(MakeNext(genesisChainedBlock)); //ctx.PersistentCoinView.SaveChangesAsync(new UnspentOutputs[0], previous.HashBlock, chained.HashBlock).Wait(); //Assert.Equal(chained.HashBlock, ctx.PersistentCoinView.GetTipHashAsync().GetAwaiter().GetResult()); //ctx.ReloadPersistentCoinView(); //Assert.Equal(chained.HashBlock, ctx.PersistentCoinView.GetTipHashAsync().GetAwaiter().GetResult()); //Assert.NotNull(ctx.PersistentCoinView.FetchCoinsAsync(new[] { genesis.Transactions[0].GetHash() }).Result.UnspentOutputs[0]); //Assert.Null(ctx.PersistentCoinView.FetchCoinsAsync(new[] { new uint256() }).Result.UnspentOutputs[0]); } }
public ConsensusStats( ICoinView coinView, IConsensusManager consensusManager, IConsensusRuleEngine consensusRules, IInitialBlockDownloadState initialBlockDownloadState, ConcurrentChain chain, IConnectionManager connectionManager, IDateTimeProvider dateTimeProvider, IBlockPuller blockPuller, ILoggerFactory loggerFactory, INodeLifetime nodeLifetime) { var stack = new CoinViewStack(coinView); this.cache = stack.Find <CachedCoinView>(); this.dbreeze = stack.Find <DBreezeCoinView>(); this.bottom = stack.Bottom; this.consensusManager = consensusManager; this.consensusRules = consensusRules; this.lastSnapshot = consensusRules.PerformanceCounter.Snapshot(); this.lastSnapshot2 = this.dbreeze?.PerformanceCounter.Snapshot(); this.lastSnapshot3 = this.cache?.PerformanceCounter.Snapshot(); this.initialBlockDownloadState = initialBlockDownloadState; this.chain = chain; this.connectionManager = connectionManager; this.dateTimeProvider = dateTimeProvider; this.blockPuller = blockPuller; this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.nodeLifetime = nodeLifetime; }
public void TestCacheCoinView() { using (NodeContext ctx = NodeContext.Create()) { var genesis = ctx.Network.GetGenesis(); var genesisChainedBlock = new ChainedBlock(genesis.Header, 0); var chained = MakeNext(genesisChainedBlock); var cacheCoinView = new CachedCoinView(ctx.PersistentCoinView); cacheCoinView.SaveChangesAsync(new UnspentOutputs[] { new UnspentOutputs(genesis.Transactions[0].GetHash(), new Coins(genesis.Transactions[0], 0)) }, null, genesisChainedBlock.HashBlock, chained.HashBlock).Wait(); Assert.NotNull(cacheCoinView.FetchCoinsAsync(new[] { genesis.Transactions[0].GetHash() }).Result.UnspentOutputs[0]); Assert.Null(cacheCoinView.FetchCoinsAsync(new[] { new uint256() }).Result.UnspentOutputs[0]); Assert.Equal(chained.HashBlock, cacheCoinView.GetBlockHashAsync().Result); Assert.Null(ctx.PersistentCoinView.FetchCoinsAsync(new[] { genesis.Transactions[0].GetHash() }).Result.UnspentOutputs[0]); Assert.Equal(chained.Previous.HashBlock, ctx.PersistentCoinView.GetBlockHashAsync().Result); cacheCoinView.FlushAsync().GetAwaiter().GetResult(); Assert.NotNull(ctx.PersistentCoinView.FetchCoinsAsync(new[] { genesis.Transactions[0].GetHash() }).Result.UnspentOutputs[0]); Assert.Equal(chained.HashBlock, ctx.PersistentCoinView.GetBlockHashAsync().Result); //Assert.Null(ctx.PersistentCoinView.FetchCoinsAsync(new[] { new uint256() }).Result.UnspentOutputs[0]); //var previous = chained; //chained = MakeNext(MakeNext(genesisChainedBlock)); //chained = MakeNext(MakeNext(genesisChainedBlock)); //ctx.PersistentCoinView.SaveChangesAsync(new UnspentOutputs[0], previous.HashBlock, chained.HashBlock).Wait(); //Assert.Equal(chained.HashBlock, ctx.PersistentCoinView.GetBlockHashAsync().GetAwaiter().GetResult()); //ctx.ReloadPersistentCoinView(); //Assert.Equal(chained.HashBlock, ctx.PersistentCoinView.GetBlockHashAsync().GetAwaiter().GetResult()); //Assert.NotNull(ctx.PersistentCoinView.FetchCoinsAsync(new[] { genesis.Transactions[0].GetHash() }).Result.UnspentOutputs[0]); //Assert.Null(ctx.PersistentCoinView.FetchCoinsAsync(new[] { new uint256() }).Result.UnspentOutputs[0]); } }
public CoinviewTests() { this.network = new StratisMain(); this.dataFolder = TestBase.CreateDataFolder(this); this.dateTimeProvider = new DateTimeProvider(); this.loggerFactory = new ExtendedLoggerFactory(); this.nodeStats = new NodeStats(this.dateTimeProvider); this.dbreezeCoinview = new DBreezeCoinView(this.network, this.dataFolder, this.dateTimeProvider, this.loggerFactory, this.nodeStats, new DBreezeSerializer(this.network)); this.dbreezeCoinview.InitializeAsync().GetAwaiter().GetResult(); this.concurrentChain = new ConcurrentChain(this.network); this.stakeChainStore = new StakeChainStore(this.network, this.concurrentChain, this.dbreezeCoinview, this.loggerFactory); this.stakeChainStore.LoadAsync().GetAwaiter().GetResult(); this.rewindDataIndexCache = new RewindDataIndexCache(this.dateTimeProvider, this.network); this.cachedCoinView = new CachedCoinView(this.dbreezeCoinview, this.dateTimeProvider, this.loggerFactory, this.nodeStats, this.stakeChainStore, this.rewindDataIndexCache); this.rewindDataIndexCache.InitializeAsync(this.concurrentChain.Height, this.cachedCoinView); this.random = new Random(); ChainedHeader newTip = ChainedHeadersHelper.CreateConsecutiveHeaders(1000, this.concurrentChain.Tip, true, null, this.network).Last(); this.concurrentChain.SetTip(newTip); }
public ConsensusStats( CoinView coinView, IConsensusLoop consensusLoop, IInitialBlockDownloadState initialBlockDownloadState, ConcurrentChain chain, IConnectionManager connectionManager, IDateTimeProvider dateTimeProvider, ILoggerFactory loggerFactory) { CoinViewStack stack = new CoinViewStack(coinView); this.cache = stack.Find <CachedCoinView>(); this.dbreeze = stack.Find <DBreezeCoinView>(); this.bottom = stack.Bottom; this.consensusLoop = consensusLoop; this.lookaheadPuller = this.consensusLoop.Puller as LookaheadBlockPuller; this.lastSnapshot = consensusLoop.ConsensusRules.PerformanceCounter.Snapshot(); this.lastSnapshot2 = this.dbreeze?.PerformanceCounter.Snapshot(); this.lastSnapshot3 = this.cache?.PerformanceCounter.Snapshot(); this.initialBlockDownloadState = initialBlockDownloadState; this.chain = chain; this.connectionManager = connectionManager; this.dateTimeProvider = dateTimeProvider; this.logger = loggerFactory.CreateLogger(this.GetType().FullName); }
/// <summary> /// Creates test chain with a consensus loop. /// </summary> public static async Task <TestChainContext> CreateAsync(Network network, string dataDir) { var testChainContext = new TestChainContext() { Network = network }; testChainContext.NodeSettings = new NodeSettings(network, args: new string[] { $"-datadir={dataDir}" }); if (dataDir != null) { testChainContext.NodeSettings.DataDir = dataDir; } testChainContext.ConnectionSettings = new ConnectionManagerSettings(); testChainContext.ConnectionSettings.Load(testChainContext.NodeSettings); testChainContext.LoggerFactory = testChainContext.NodeSettings.LoggerFactory; testChainContext.DateTimeProvider = DateTimeProvider.Default; network.Consensus.Options = new PowConsensusOptions(); ConsensusSettings consensusSettings = new ConsensusSettings().Load(testChainContext.NodeSettings); testChainContext.Checkpoints = new Checkpoints(); PowConsensusValidator consensusValidator = new PowConsensusValidator(network, testChainContext.Checkpoints, testChainContext.DateTimeProvider, testChainContext.LoggerFactory); testChainContext.Chain = new ConcurrentChain(network); CachedCoinView cachedCoinView = new CachedCoinView(new InMemoryCoinView(testChainContext.Chain.Tip.HashBlock), DateTimeProvider.Default, testChainContext.LoggerFactory); DataFolder dataFolder = new DataFolder(TestBase.AssureEmptyDir(dataDir)); testChainContext.PeerAddressManager = new PeerAddressManager(DateTimeProvider.Default, dataFolder, testChainContext.LoggerFactory, new SelfEndpointTracker()); testChainContext.MockConnectionManager = new Moq.Mock <IConnectionManager>(); testChainContext.MockReadOnlyNodesCollection = new Moq.Mock <IReadOnlyNetworkPeerCollection>(); testChainContext.MockConnectionManager.Setup(s => s.ConnectedPeers).Returns(testChainContext.MockReadOnlyNodesCollection.Object); testChainContext.MockConnectionManager.Setup(s => s.NodeSettings).Returns(testChainContext.NodeSettings); testChainContext.MockConnectionManager.Setup(s => s.ConnectionSettings).Returns(testChainContext.ConnectionSettings); testChainContext.ConnectionManager = testChainContext.MockConnectionManager.Object; LookaheadBlockPuller blockPuller = new LookaheadBlockPuller(testChainContext.Chain, testChainContext.ConnectionManager, testChainContext.LoggerFactory); testChainContext.PeerBanning = new PeerBanning(testChainContext.ConnectionManager, testChainContext.LoggerFactory, testChainContext.DateTimeProvider, testChainContext.PeerAddressManager); NodeDeployments deployments = new NodeDeployments(testChainContext.Network, testChainContext.Chain); ConsensusRules consensusRules = new PowConsensusRules(testChainContext.Network, testChainContext.LoggerFactory, testChainContext.DateTimeProvider, testChainContext.Chain, deployments, consensusSettings, testChainContext.Checkpoints).Register(new FullNodeBuilderConsensusExtension.PowConsensusRulesRegistration()); testChainContext.Consensus = new ConsensusLoop(new AsyncLoopFactory(testChainContext.LoggerFactory), consensusValidator, new NodeLifetime(), testChainContext.Chain, cachedCoinView, blockPuller, new NodeDeployments(network, testChainContext.Chain), testChainContext.LoggerFactory, new ChainState(new InvalidBlockHashStore(testChainContext.DateTimeProvider)), testChainContext.ConnectionManager, testChainContext.DateTimeProvider, new Signals.Signals(), consensusSettings, testChainContext.NodeSettings, testChainContext.PeerBanning, consensusRules); await testChainContext.Consensus.StartAsync(); return(testChainContext); }
public ConsensusStats(FullNode fullNode, CoinViewStack stack) { this.fullNode = fullNode; stack = new CoinViewStack(fullNode.CoinView); cache = stack.Find <CachedCoinView>(); dbreeze = stack.Find <DBreezeCoinView>(); bottom = stack.Bottom; lookaheadPuller = fullNode.ConsensusLoop.Puller as LookaheadBlockPuller; lastSnapshot = fullNode.ConsensusLoop.Validator.PerformanceCounter.Snapshot(); lastSnapshot2 = dbreeze?.PerformanceCounter.Snapshot(); lastSnapshot3 = cache?.PerformanceCounter.Snapshot(); }
/// <summary> /// Creates test chain with a consensus loop. /// </summary> public static async Task <TestChainContext> CreateAsync(Network network, string dataDir) { var testChainContext = new TestChainContext() { Network = network }; testChainContext.NodeSettings = new NodeSettings(network.Name, network).LoadArguments(new string[] { $"-datadir={dataDir}" }); if (dataDir != null) { testChainContext.NodeSettings.DataDir = dataDir; } testChainContext.LoggerFactory = new ExtendedLoggerFactory(); testChainContext.LoggerFactory.AddConsoleWithFilters(); testChainContext.DateTimeProvider = DateTimeProvider.Default; network.Consensus.Options = new PowConsensusOptions(); ConsensusSettings consensusSettings = new ConsensusSettings(testChainContext.NodeSettings, testChainContext.LoggerFactory); PowConsensusValidator consensusValidator = new PowConsensusValidator(network, new Checkpoints(network, consensusSettings), testChainContext.DateTimeProvider, testChainContext.LoggerFactory); testChainContext.Chain = new ConcurrentChain(network); CachedCoinView cachedCoinView = new CachedCoinView(new InMemoryCoinView(testChainContext.Chain.Tip.HashBlock), DateTimeProvider.Default, testChainContext.LoggerFactory); testChainContext.MockConnectionManager = new Moq.Mock <IConnectionManager>(); testChainContext.MockReadOnlyNodesCollection = new Moq.Mock <IReadOnlyNetworkPeerCollection>(); testChainContext.MockConnectionManager.Setup(s => s.ConnectedNodes).Returns(testChainContext.MockReadOnlyNodesCollection.Object); testChainContext.MockConnectionManager.Setup(s => s.NodeSettings).Returns(testChainContext.NodeSettings); testChainContext.ConnectionManager = testChainContext.MockConnectionManager.Object; LookaheadBlockPuller blockPuller = new LookaheadBlockPuller(testChainContext.Chain, testChainContext.ConnectionManager, new LoggerFactory()); testChainContext.PeerBanning = new PeerBanning(testChainContext.ConnectionManager, testChainContext.LoggerFactory, testChainContext.DateTimeProvider, testChainContext.NodeSettings); testChainContext.Consensus = new ConsensusLoop(new AsyncLoopFactory(testChainContext.LoggerFactory), consensusValidator, new NodeLifetime(), testChainContext.Chain, cachedCoinView, blockPuller, new NodeDeployments(network, testChainContext.Chain), testChainContext.LoggerFactory, new ChainState(new FullNode(), new InvalidBlockHashStore(testChainContext.DateTimeProvider)), testChainContext.ConnectionManager, testChainContext.DateTimeProvider, new Signals.Signals(), new Checkpoints(network, consensusSettings), consensusSettings, testChainContext.NodeSettings, testChainContext.PeerBanning); await testChainContext.Consensus.StartAsync(); return(testChainContext); }
public static IFullNodeBuilder AddRequired(this IFullNodeBuilder builder) { builder.UseBaseFeature(); // TODO: move some of the required services will move to their own feature return(builder.ConfigureServices(service => { var dataFolder = new DataFolder(builder.NodeSettings); // TODO: move to ConsensusFeature (required for mempool) var coinviewdb = new DBreezeCoinView(builder.Network, dataFolder.CoinViewPath); var coinView = new CachedCoinView(coinviewdb) { MaxItems = builder.NodeSettings.Cache.MaxItems }; var consensusValidator = new ConsensusValidator(builder.Network.Consensus); service.AddSingleton(consensusValidator); service.AddSingleton <DBreezeCoinView>(coinviewdb); service.AddSingleton <CoinView>(coinView); })); }
/// <summary> /// Before we continue to persist coindb we need to make sure the /// store is not behind our tip, if it is we will wait to let store /// catchup even if it means we need to block consensus form advancing /// </summary> /// <param name="cachedCoinView"></param> private void WaitForBlockstore(CachedCoinView cachedCoinView) { if (this.chainState.BlockStoreTip != null) { int delaySec = 3; int rewindDataWindow = cachedCoinView.CalculateRewindWindow(); HashHeightPair cachedCoinViewTip = cachedCoinView.GetTipHash(); while (cachedCoinViewTip.Height - rewindDataWindow + 1 > this.chainState.BlockStoreTip.Height) { if (this.nodeLifetime.ApplicationStopping.IsCancellationRequested) { // node is closing do nothing. return; } // wait 3 seconds to let blockstore catch up this.Logger.LogWarning("Store tip `{0}` is behind coindb rewind data tip `{1}` waiting {2} seconds to let store catch up", this.chainState.BlockStoreTip.Height, cachedCoinViewTip.Height - rewindDataWindow + 1, delaySec); Task.Delay(delaySec * 1000).Wait(); } } }
/// <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 ITestChainContext Create(Network network, Script scriptPubKey) { NodeSettings nodeSettings = NodeSettings.Default(); LoggerFactory loggerFactory = new LoggerFactory(); IDateTimeProvider dateTimeProvider = DateTimeProvider.Default; network.Consensus.Options = new PowConsensusOptions(); PowConsensusValidator consensusValidator = new PowConsensusValidator(network); ConcurrentChain chain = new ConcurrentChain(network); CachedCoinView cachedCoinView = new CachedCoinView(new InMemoryCoinView(chain.Tip.HashBlock), loggerFactory); ConnectionManager connectionManager = new ConnectionManager(network, new NodeConnectionParameters(), nodeSettings, loggerFactory, new NodeLifetime()); LookaheadBlockPuller blockPuller = new LookaheadBlockPuller(chain, connectionManager, new LoggerFactory()); ConsensusLoop consensus = new ConsensusLoop(consensusValidator, chain, cachedCoinView, blockPuller, new NodeDeployments(network)); consensus.Initialize(); BlockPolicyEstimator blockPolicyEstimator = new BlockPolicyEstimator(new FeeRate(1000), nodeSettings, loggerFactory); TxMempool mempool = new TxMempool(new FeeRate(1000), dateTimeProvider, blockPolicyEstimator, loggerFactory); MempoolAsyncLock mempoolLock = new MempoolAsyncLock(); // Simple block creation, nothing special yet: PowBlockAssembler blockAssembler = CreatePowBlockAssembler(network, consensus, chain, mempoolLock, mempool, dateTimeProvider); BlockTemplate newBlock = blockAssembler.CreateNewBlock(scriptPubKey); chain.SetTip(newBlock.Block.Header); consensus.AcceptBlock(new ContextInformation(new BlockResult { Block = newBlock.Block }, network.Consensus) { 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); consensus.AcceptBlock(new ContextInformation(new BlockResult { Block = currentBlock }, network.Consensus) { 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); newBlock = blockAssembler.CreateNewBlock(scriptPubKey); MempoolValidator mempoolValidator = new MempoolValidator(mempool, mempoolLock, consensusValidator, dateTimeProvider, nodeSettings, chain, cachedCoinView, loggerFactory); return(new TestChainContext { MempoolValidator = mempoolValidator, SrcTxs = srcTxs }); }
public async Task InitializeAsync() { this.blockinfo = new List <Blockinfo>(); var lst = blockinfoarr.Cast <long>().ToList(); for (int i = 0; i < lst.Count; i += 2) { this.blockinfo.Add(new Blockinfo { extranonce = (int)lst[i], nonce = (uint)lst[i + 1] }); } // Note that by default, these tests run with size accounting enabled. this.network = Network.Main; var hex = Encoders.Hex.DecodeData("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"); this.scriptPubKey = new Script(new[] { Op.GetPushOp(hex), OpcodeType.OP_CHECKSIG }); this.newBlock = new BlockTemplate(this.network); this.entry = new TestMemPoolEntryHelper(); this.chain = new ConcurrentChain(this.network); this.network.Consensus.Options = new PowConsensusOptions(); IDateTimeProvider dateTimeProvider = DateTimeProvider.Default; this.cachedCoinView = new CachedCoinView(new InMemoryCoinView(this.chain.Tip.HashBlock), dateTimeProvider, new LoggerFactory()); var loggerFactory = new ExtendedLoggerFactory(); loggerFactory.AddConsoleWithFilters(); NodeSettings nodeSettings = new NodeSettings(args: new string[] { "-checkpoints" }); var consensusSettings = new ConsensusSettings().Load(nodeSettings); PowConsensusValidator consensusValidator = new PowConsensusValidator(this.network, new Checkpoints(), dateTimeProvider, loggerFactory); NetworkPeerFactory networkPeerFactory = new NetworkPeerFactory(this.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, this.network, networkPeerFactory, nodeSettings, new NodeLifetime(), new NetworkPeerConnectionParameters(), peerAddressManager, new IPeerConnector[] { }, peerDiscovery, connectionSettings); LookaheadBlockPuller blockPuller = new LookaheadBlockPuller(this.chain, connectionManager, new LoggerFactory()); PeerBanning peerBanning = new PeerBanning(connectionManager, loggerFactory, dateTimeProvider, peerAddressManager); NodeDeployments deployments = new NodeDeployments(this.network, this.chain); ConsensusRules consensusRules = new PowConsensusRules(this.network, loggerFactory, dateTimeProvider, this.chain, deployments, consensusSettings, new Checkpoints(), this.cachedCoinView, blockPuller).Register(new FullNodeBuilderConsensusExtension.PowConsensusRulesRegistration()); this.consensus = new ConsensusLoop(new AsyncLoopFactory(loggerFactory), consensusValidator, new NodeLifetime(), this.chain, this.cachedCoinView, blockPuller, new NodeDeployments(this.network, this.chain), loggerFactory, new ChainState(new InvalidBlockHashStore(dateTimeProvider)), connectionManager, dateTimeProvider, new Signals.Signals(), consensusSettings, nodeSettings, peerBanning, consensusRules); await this.consensus.StartAsync(); this.entry.Fee(11); this.entry.Height(11); var date1 = new MemoryPoolTests.DateTimeProviderSet(); date1.time = dateTimeProvider.GetTime(); date1.timeutc = dateTimeProvider.GetUtcNow(); this.DateTimeProvider = date1; this.mempool = new TxMempool(dateTimeProvider, new BlockPolicyEstimator(new MempoolSettings(nodeSettings), new LoggerFactory(), nodeSettings), new LoggerFactory(), nodeSettings); this.mempoolLock = new MempoolSchedulerLock(); // Simple block creation, nothing special yet: this.newBlock = AssemblerForTest(this).Build(this.chain.Tip, this.scriptPubKey); this.chain.SetTip(this.newBlock.Block.Header); await this.consensus.ValidateAndExecuteBlockAsync(new RuleContext(new BlockValidationContext { Block = this.newBlock.Block }, this.network.Consensus, this.consensus.Tip) { CheckPow = false, CheckMerkleRoot = false }); // We can't make transactions until we have inputs // Therefore, load 100 blocks :) this.baseheight = 0; List <Block> blocks = new List <Block>(); this.txFirst = new List <Transaction>(); for (int i = 0; i < this.blockinfo.Count; ++i) { var pblock = this.newBlock.Block.Clone(); // pointer for convenience pblock.Header.HashPrevBlock = this.chain.Tip.HashBlock; pblock.Header.Version = 1; pblock.Header.Time = Utils.DateTimeToUnixTime(this.chain.Tip.GetMedianTimePast()) + 1; Transaction txCoinbase = pblock.Transactions[0].Clone(); txCoinbase.Inputs.Clear(); txCoinbase.Version = 1; txCoinbase.AddInput(new TxIn(new Script(new[] { Op.GetPushOp(this.blockinfo[i].extranonce), Op.GetPushOp(this.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())); pblock.Transactions[0] = txCoinbase; if (this.txFirst.Count == 0) { this.baseheight = this.chain.Height; } if (this.txFirst.Count < 4) { this.txFirst.Add(pblock.Transactions[0]); } pblock.UpdateMerkleRoot(); pblock.Header.Nonce = this.blockinfo[i].nonce; this.chain.SetTip(pblock.Header); await this.consensus.ValidateAndExecuteBlockAsync(new RuleContext(new BlockValidationContext { Block = pblock }, this.network.Consensus, this.consensus.Tip) { CheckPow = false, CheckMerkleRoot = false }); blocks.Add(pblock); } // Just to make sure we can still make simple blocks this.newBlock = AssemblerForTest(this).Build(this.chain.Tip, this.scriptPubKey); Assert.NotNull(this.newBlock); }
public void CanRewind() { using (NodeContext nodeContext = NodeContext.Create(this)) { var dateTimeProvider = new DateTimeProvider(); var cacheCoinView = new CachedCoinView(nodeContext.PersistentCoinView, dateTimeProvider, this.loggerFactory, new NodeStats(dateTimeProvider)); var tester = new CoinViewTester(cacheCoinView); Coin[] coinsA = tester.CreateCoins(5); Coin[] coinsB = tester.CreateCoins(1); tester.NewBlock(); cacheCoinView.FlushAsync().Wait(); Assert.True(tester.Exists(coinsA[2])); Assert.True(tester.Exists(coinsB[0])); // Spend some coins. tester.Spend(coinsA[2]); tester.Spend(coinsB[0]); tester.NewBlock(); // This will save an empty RewindData instance tester.NewBlock(); // Create a new coin set/ Coin[] coinsC = tester.CreateCoins(1); tester.NewBlock(); Assert.True(tester.Exists(coinsA[0])); Assert.True(tester.Exists(coinsC[0])); Assert.False(tester.Exists(coinsA[2])); Assert.False(tester.Exists(coinsB[0])); // We need to rewind 3 times as we are now rewinding one block at a time. tester.Rewind(); // coinsC[0] should not exist any more. tester.Rewind(); // coinsA[2] should be spendable again. tester.Rewind(); // coinsB[2] should be spendable again. Assert.False(tester.Exists(coinsC[0])); Assert.True(tester.Exists(coinsA[2])); Assert.True(tester.Exists(coinsB[0])); // Spend some coins and esnure they are not spendable. tester.Spend(coinsA[2]); tester.Spend(coinsB[0]); tester.NewBlock(); cacheCoinView.FlushAsync().Wait(); Assert.False(tester.Exists(coinsA[2])); Assert.False(tester.Exists(coinsB[0])); // Rewind so that coinsA[2] and coinsB[0] become spendable again. tester.Rewind(); Assert.True(tester.Exists(coinsA[2])); Assert.True(tester.Exists(coinsB[0])); // Create 7 coins in a new coin set and spend the first coin. Coin[] coinsD = tester.CreateCoins(7); tester.Spend(coinsD[0]); // Create a coin in a new coin set and spend it. Coin[] coinsE = tester.CreateCoins(1); tester.Spend(coinsE[0]); tester.NewBlock(); Assert.True(tester.Exists(coinsD[1])); Assert.False(tester.Exists(coinsD[0])); cacheCoinView.FlushAsync().Wait(); // Creates another empty RewindData instance. tester.NewBlock(); // Rewind one block. tester.Rewind(); // coinsD[1] was never touched, so should remain unchanged. // coinsD[0] was spent but the block in which the changes happened was not yet rewound to, so it remains unchanged. // coinsE[0] was spent but the block in which the changes happened was not yet rewound to, so it remains unchanged. // coinsA[1] was not touched, so should remain unchanged. // coinsB[1] was not touched, so should remain unchanged. Assert.True(tester.Exists(coinsD[1])); Assert.False(tester.Exists(coinsD[0])); Assert.False(tester.Exists(coinsE[0])); Assert.True(tester.Exists(coinsA[2])); Assert.True(tester.Exists(coinsB[0])); // Rewind one block. tester.Rewind(); // coinsD[0] should now not exist in CoinView anymore. // coinsE[0] should now not exist in CoinView anymore. Assert.False(tester.Exists(coinsD[0])); Assert.False(tester.Exists(coinsE[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 }); }
public async Task InitializeAsync() { this.blockinfo = new List <Blockinfo>(); List <long> lst = blockinfoarr.Cast <long>().ToList(); for (int i = 0; i < lst.Count; i += 2) { this.blockinfo.Add(new Blockinfo { extranonce = (int)lst[i], nonce = (uint)lst[i + 1] }); } // Note that by default, these tests run with size accounting enabled. this.network = KnownNetworks.RegTest; byte[] hex = Encoders.Hex.DecodeData("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"); this.scriptPubKey = new Script(new[] { Op.GetPushOp(hex), OpcodeType.OP_CHECKSIG }); this.entry = new TestMemPoolEntryHelper(); this.chain = new ConcurrentChain(this.network); this.network.Consensus.Options = new ConsensusOptions(); new FullNodeBuilderConsensusExtension.PowConsensusRulesRegistration().RegisterRules(this.network.Consensus); IDateTimeProvider dateTimeProvider = DateTimeProvider.Default; this.cachedCoinView = new CachedCoinView(new InMemoryCoinView(this.chain.Tip.HashBlock), dateTimeProvider, new LoggerFactory()); var loggerFactory = new ExtendedLoggerFactory(); loggerFactory.AddConsoleWithFilters(); var nodeSettings = new NodeSettings(args: new string[] { "-checkpoints" }); var consensusSettings = new ConsensusSettings(nodeSettings); var networkPeerFactory = new NetworkPeerFactory(this.network, dateTimeProvider, loggerFactory, new PayloadProvider().DiscoverPayloads(), new SelfEndpointTracker(loggerFactory), new Mock <IInitialBlockDownloadState>().Object, new ConnectionManagerSettings()); var peerAddressManager = new PeerAddressManager(DateTimeProvider.Default, nodeSettings.DataFolder, loggerFactory, new SelfEndpointTracker(loggerFactory)); var peerDiscovery = new PeerDiscovery(new AsyncLoopFactory(loggerFactory), loggerFactory, this.network, networkPeerFactory, new NodeLifetime(), nodeSettings, peerAddressManager); var connectionSettings = new ConnectionManagerSettings(nodeSettings); var selfEndpointTracker = new SelfEndpointTracker(loggerFactory); var connectionManager = new ConnectionManager(dateTimeProvider, loggerFactory, this.network, networkPeerFactory, nodeSettings, new NodeLifetime(), new NetworkPeerConnectionParameters(), peerAddressManager, new IPeerConnector[] { }, peerDiscovery, selfEndpointTracker, connectionSettings, new VersionProvider(), new Mock <INodeStats>().Object); var peerBanning = new PeerBanning(connectionManager, loggerFactory, dateTimeProvider, peerAddressManager); var deployments = new NodeDeployments(this.network, this.chain); var genesis = this.network.GetGenesis(); var chainState = new ChainState() { BlockStoreTip = new ChainedHeader(genesis.Header, genesis.GetHash(), 0) }; this.ConsensusRules = new PowConsensusRuleEngine(this.network, loggerFactory, dateTimeProvider, this.chain, deployments, consensusSettings, new Checkpoints(), this.cachedCoinView, chainState, new InvalidBlockHashStore(dateTimeProvider)).Register(); this.consensus = ConsensusManagerHelper.CreateConsensusManager(this.network); await this.consensus.InitializeAsync(chainState.BlockStoreTip); this.entry.Fee(11); this.entry.Height(11); var dateTimeProviderSet = new MemoryPoolTests.DateTimeProviderSet { time = dateTimeProvider.GetTime(), timeutc = dateTimeProvider.GetUtcNow() }; this.DateTimeProvider = dateTimeProviderSet; this.mempool = new TxMempool(dateTimeProvider, new BlockPolicyEstimator(new MempoolSettings(nodeSettings), loggerFactory, nodeSettings), loggerFactory, nodeSettings); this.mempoolLock = new MempoolSchedulerLock(); // We can't make transactions until we have inputs // Therefore, load 100 blocks :) this.baseheight = 0; var blocks = new List <Block>(); this.txFirst = new List <Transaction>(); this.nonce = 0; for (int i = 0; i < this.blockinfo.Count; ++i) { Block block = this.network.CreateBlock(); block.Header.HashPrevBlock = this.chain.Tip.HashBlock; block.Header.Version = 1; block.Header.Time = Utils.DateTimeToUnixTime(this.chain.Tip.GetMedianTimePast()) + 1; Transaction txCoinbase = this.network.CreateTransaction(); txCoinbase.Version = 1; txCoinbase.AddInput(new TxIn(new Script(new[] { Op.GetPushOp(this.blockinfo[i].extranonce), Op.GetPushOp(this.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())); block.AddTransaction(txCoinbase); if (this.txFirst.Count == 0) { this.baseheight = this.chain.Height; } if (this.txFirst.Count < 4) { this.txFirst.Add(block.Transactions[0]); } block.Header.Bits = block.Header.GetWorkRequired(this.network, this.chain.Tip); block.UpdateMerkleRoot(); while (!block.CheckProofOfWork()) { block.Header.Nonce = ++this.nonce; } // Serialization sets the BlockSize property. block = Block.Load(block.ToBytes(), this.network); await this.consensus.BlockMinedAsync(block); blocks.Add(block); } // Just to make sure we can still make simple blocks this.newBlock = AssemblerForTest(this).Build(this.chain.Tip, this.scriptPubKey); Assert.NotNull(this.newBlock); }
public void CanRewind() { using (NodeContext ctx = NodeContext.Create()) { var cacheCoinView = new CachedCoinView(ctx.PersistentCoinView); var tester = new CoinViewTester(cacheCoinView); var coins = tester.CreateCoins(5); var coin = tester.CreateCoins(1); // 1 var h1 = tester.NewBlock(); cacheCoinView.FlushAsync().Wait(); Assert.True(tester.Exists(coins[2])); Assert.True(tester.Exists(coin[0])); tester.Spend(coins[2]); tester.Spend(coin[0]); //2 tester.NewBlock(); //3 tester.NewBlock(); //4 var coin2 = tester.CreateCoins(1); tester.NewBlock(); Assert.True(tester.Exists(coins[0])); Assert.True(tester.Exists(coin2[0])); Assert.False(tester.Exists(coins[2])); Assert.False(tester.Exists(coin[0])); //1 tester.Rewind(); Assert.False(tester.Exists(coin2[0])); Assert.True(tester.Exists(coins[2])); Assert.True(tester.Exists(coin[0])); tester.Spend(coins[2]); tester.Spend(coin[0]); //2 var h2 = tester.NewBlock(); cacheCoinView.FlushAsync().Wait(); Assert.False(tester.Exists(coins[2])); Assert.False(tester.Exists(coin[0])); //1 Assert.True(h1 == tester.Rewind()); Assert.True(tester.Exists(coins[2])); Assert.True(tester.Exists(coin[0])); var coins2 = tester.CreateCoins(7); tester.Spend(coins2[0]); coin2 = tester.CreateCoins(1); tester.Spend(coin2[0]); //2 tester.NewBlock(); Assert.True(tester.Exists(coins2[1])); Assert.False(tester.Exists(coins2[0])); cacheCoinView.FlushAsync().Wait(); //3 tester.NewBlock(); //2 tester.Rewind(); Assert.True(tester.Exists(coins2[1])); Assert.False(tester.Exists(coins2[0])); Assert.False(tester.Exists(coin2[0])); Assert.True(tester.Exists(coins[2])); Assert.True(tester.Exists(coin[0])); } }
/// <summary> /// Creates test chain with a consensus loop. /// </summary> public static async Task <TestChainContext> CreateAsync(Network network, string dataDir, Mock <IPeerAddressManager> mockPeerAddressManager = null) { var testChainContext = new TestChainContext() { Network = network }; testChainContext.NodeSettings = new NodeSettings(network, args: new string[] { $"-datadir={dataDir}" }); testChainContext.ConnectionSettings = new ConnectionManagerSettings(testChainContext.NodeSettings); testChainContext.LoggerFactory = testChainContext.NodeSettings.LoggerFactory; testChainContext.DateTimeProvider = DateTimeProvider.Default; network.Consensus.Options = new ConsensusOptions(); new FullNodeBuilderConsensusExtension.PowConsensusRulesRegistration().RegisterRules(network.Consensus); var consensusSettings = new ConsensusSettings(testChainContext.NodeSettings); testChainContext.Checkpoints = new Checkpoints(); testChainContext.Chain = new ConcurrentChain(network); testChainContext.ChainState = new ChainState(); testChainContext.InitialBlockDownloadState = new InitialBlockDownloadState(testChainContext.ChainState, testChainContext.Network, consensusSettings, new Checkpoints()); var inMemoryCoinView = new InMemoryCoinView(testChainContext.Chain.Tip.HashBlock); var cachedCoinView = new CachedCoinView(inMemoryCoinView, DateTimeProvider.Default, testChainContext.LoggerFactory); var dataFolder = new DataFolder(TestBase.AssureEmptyDir(dataDir)); testChainContext.PeerAddressManager = mockPeerAddressManager == null ? new PeerAddressManager(DateTimeProvider.Default, dataFolder, testChainContext.LoggerFactory, new SelfEndpointTracker(testChainContext.LoggerFactory)) : mockPeerAddressManager.Object; testChainContext.MockConnectionManager = new Mock <IConnectionManager>(); testChainContext.MockReadOnlyNodesCollection = new Mock <IReadOnlyNetworkPeerCollection>(); testChainContext.MockConnectionManager.Setup(s => s.ConnectedPeers).Returns(testChainContext.MockReadOnlyNodesCollection.Object); testChainContext.MockConnectionManager.Setup(s => s.NodeSettings).Returns(testChainContext.NodeSettings); testChainContext.MockConnectionManager.Setup(s => s.ConnectionSettings).Returns(testChainContext.ConnectionSettings); testChainContext.ConnectionManager = testChainContext.MockConnectionManager.Object; testChainContext.PeerBanning = new PeerBanning(testChainContext.ConnectionManager, testChainContext.LoggerFactory, testChainContext.DateTimeProvider, testChainContext.PeerAddressManager); var deployments = new NodeDeployments(testChainContext.Network, testChainContext.Chain); testChainContext.ConsensusRules = new PowConsensusRuleEngine(testChainContext.Network, testChainContext.LoggerFactory, testChainContext.DateTimeProvider, testChainContext.Chain, deployments, consensusSettings, testChainContext.Checkpoints, cachedCoinView, testChainContext.ChainState, new InvalidBlockHashStore(new DateTimeProvider())) .Register(); testChainContext.HeaderValidator = new HeaderValidator(testChainContext.ConsensusRules, testChainContext.LoggerFactory); testChainContext.IntegrityValidator = new IntegrityValidator(testChainContext.ConsensusRules, testChainContext.LoggerFactory); testChainContext.PartialValidator = new PartialValidator(testChainContext.ConsensusRules, testChainContext.LoggerFactory); testChainContext.FullValidator = new FullValidator(testChainContext.ConsensusRules, testChainContext.LoggerFactory); var blockRepository = new BlockRepository(testChainContext.Network, dataFolder, testChainContext.DateTimeProvider, testChainContext.LoggerFactory); var blockStore = new BlockStoreQueue(testChainContext.Chain, testChainContext.ChainState, new Mock <StoreSettings>().Object, new Mock <INodeLifetime>().Object, blockRepository, testChainContext.LoggerFactory, new Mock <INodeStats>().Object); await blockStore.InitializeAsync(); testChainContext.Consensus = ConsensusManagerHelper.CreateConsensusManager(network, dataDir); await testChainContext.Consensus.InitializeAsync(testChainContext.Chain.Tip); return(testChainContext); }
public void CanRewind() { using (NodeContext ctx = NodeContext.Create(this)) { var cacheCoinView = new CachedCoinView(ctx.PersistentCoinView, DateTimeProvider.Default, this.loggerFactory); var tester = new CoinViewTester(cacheCoinView); Coin[] coins = tester.CreateCoins(5); Coin[] coin = tester.CreateCoins(1); // 1 uint256 h1 = tester.NewBlock(); cacheCoinView.FlushAsync().Wait(); Assert.True(tester.Exists(coins[2])); Assert.True(tester.Exists(coin[0])); tester.Spend(coins[2]); tester.Spend(coin[0]); //2 tester.NewBlock(); //3 tester.NewBlock(); //4 Coin[] coin2 = tester.CreateCoins(1); tester.NewBlock(); Assert.True(tester.Exists(coins[0])); Assert.True(tester.Exists(coin2[0])); Assert.False(tester.Exists(coins[2])); Assert.False(tester.Exists(coin[0])); //1 tester.Rewind(); Assert.False(tester.Exists(coin2[0])); Assert.True(tester.Exists(coins[2])); Assert.True(tester.Exists(coin[0])); tester.Spend(coins[2]); tester.Spend(coin[0]); //2 uint256 h2 = tester.NewBlock(); cacheCoinView.FlushAsync().Wait(); Assert.False(tester.Exists(coins[2])); Assert.False(tester.Exists(coin[0])); //1 Assert.True(h1 == tester.Rewind()); Assert.True(tester.Exists(coins[2])); Assert.True(tester.Exists(coin[0])); Coin[] coins2 = tester.CreateCoins(7); tester.Spend(coins2[0]); coin2 = tester.CreateCoins(1); tester.Spend(coin2[0]); //2 tester.NewBlock(); Assert.True(tester.Exists(coins2[1])); Assert.False(tester.Exists(coins2[0])); cacheCoinView.FlushAsync().Wait(); //3 tester.NewBlock(); //2 tester.Rewind(); Assert.True(tester.Exists(coins2[1])); Assert.False(tester.Exists(coins2[0])); Assert.False(tester.Exists(coin2[0])); Assert.True(tester.Exists(coins[2])); Assert.True(tester.Exists(coin[0])); } }
private Task RunLoop(CancellationToken cancellationToken) { try { var stack = new CoinViewStack(this.coinView); CachedCoinView cache = stack.Find <CachedCoinView>(); var stats = new ConsensusStats(stack, this.coinView, this.consensusLoop, this.chainState, this.chain, this.connectionManager, this.loggerFactory); ChainedBlock lastTip = this.consensusLoop.Tip; foreach (BlockResult block in this.consensusLoop.Execute(cancellationToken)) { if (this.consensusLoop.Tip.FindFork(lastTip) != lastTip) { this.logger.LogInformation("Reorg detected, rewinding from '{0}' to '{1}'.", lastTip.HashBlock, this.consensusLoop.Tip); } lastTip = this.consensusLoop.Tip; cancellationToken.ThrowIfCancellationRequested(); if (block.Error != null) { this.logger.LogError("Block rejected: {0}", block.Error.Message); // Pull again. this.consensusLoop.Puller.SetLocation(this.consensusLoop.Tip); if (block.Error == ConsensusErrors.BadWitnessNonceSize) { this.logger.LogInformation("You probably need witness information, activating witness requirement for peers."); this.connectionManager.AddDiscoveredNodesRequirement(NodeServices.NODE_WITNESS); this.consensusLoop.Puller.RequestOptions(TransactionOptions.Witness); continue; } // Set the PoW chain back to ConsensusLoop.Tip. this.chain.SetTip(this.consensusLoop.Tip); // Since ChainHeadersBehavior check PoW, MarkBlockInvalid can't be spammed. this.logger.LogError("Marking block as invalid."); this.chainState.MarkBlockInvalid(block.Block.GetHash()); } if (block.Error == null) { this.chainState.HighestValidatedPoW = this.consensusLoop.Tip; // We really want to flush if we are at the top of the chain. // Otherwise, we just allow the flush to happen if it is needed. bool forceFlush = this.chain.Tip.HashBlock == block.ChainedBlock?.HashBlock; this.consensusLoop.FlushAsync(forceFlush).GetAwaiter().GetResult(); this.signals.SignalBlock(block.Block); } // TODO: Replace this with a signalling object. if (stats.CanLog) { stats.Log(); } } } catch (Exception ex) { if (ex is OperationCanceledException) { if (this.nodeLifetime.ApplicationStopping.IsCancellationRequested) { return(Task.FromException(ex)); } } // TODO Need to revisit unhandled exceptions in a way that any process can signal an exception has been // thrown so that the node and all the disposables can stop gracefully. this.logger.LogDebug("Exception occurred in consensus loop: {0}", ex.ToString()); this.logger.LogCritical(new EventId(0), ex, "Consensus loop at Tip:{0} unhandled exception {1}", this.consensusLoop.Tip?.Height, ex.ToString()); NLog.LogManager.Flush(); throw; } return(Task.CompletedTask); }
/// <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 }); }
public async Task InitializeAsync() { this.blockinfo = new List <Blockinfo>(); List <long> lst = blockinfoarr.Cast <long>().ToList(); for (int i = 0; i < lst.Count; i += 2) { this.blockinfo.Add(new Blockinfo { extranonce = (int)lst[i], nonce = (uint)lst[i + 1] }); } // Note that by default, these tests run with size accounting enabled. this.network = KnownNetworks.RegTest; byte[] hex = Encoders.Hex.DecodeData("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"); this.scriptPubKey = new Script(new[] { Op.GetPushOp(hex), OpcodeType.OP_CHECKSIG }); this.entry = new TestMemPoolEntryHelper(); this.ChainIndexer = new ChainIndexer(this.network); this.network.Consensus.Options = new ConsensusOptions(); IDateTimeProvider dateTimeProvider = DateTimeProvider.Default; var loggerFactory = ExtendedLoggerFactory.Create(); var nodeSettings = new NodeSettings(this.network, args: new string[] { "-checkpoints" }); var consensusSettings = new ConsensusSettings(nodeSettings); var inMemoryCoinView = new InMemoryCoinView(new HashHeightPair(this.ChainIndexer.Tip)); var nodeStats = new NodeStats(dateTimeProvider, loggerFactory); this.cachedCoinView = new CachedCoinView(this.network, new Checkpoints(), inMemoryCoinView, dateTimeProvider, new LoggerFactory(), nodeStats, consensusSettings); var signals = new Signals.Signals(loggerFactory, null); var asyncProvider = new AsyncProvider(loggerFactory, signals, new NodeLifetime()); var deployments = new NodeDeployments(this.network, this.ChainIndexer); var genesis = this.network.GetGenesis(); var chainState = new ChainState() { BlockStoreTip = new ChainedHeader(genesis.Header, genesis.GetHash(), 0) }; var consensusRulesContainer = new ConsensusRulesContainer(); foreach (var ruleType in this.network.Consensus.ConsensusRules.HeaderValidationRules) { consensusRulesContainer.HeaderValidationRules.Add(Activator.CreateInstance(ruleType) as HeaderValidationConsensusRule); } foreach (var ruleType in this.network.Consensus.ConsensusRules.FullValidationRules) { FullValidationConsensusRule rule = null; if (ruleType == typeof(FlushUtxosetRule)) { rule = new FlushUtxosetRule(new Mock <IInitialBlockDownloadState>().Object); } else { rule = Activator.CreateInstance(ruleType) as FullValidationConsensusRule; } consensusRulesContainer.FullValidationRules.Add(rule); } this.ConsensusRules = new PowConsensusRuleEngine(this.network, loggerFactory, dateTimeProvider, this.ChainIndexer, deployments, consensusSettings, new Checkpoints(), this.cachedCoinView, chainState, new InvalidBlockHashStore(dateTimeProvider), nodeStats, asyncProvider, consensusRulesContainer).SetupRulesEngineParent(); this.consensus = ConsensusManagerHelper.CreateConsensusManager(this.network, chainState: chainState, inMemoryCoinView: inMemoryCoinView, chainIndexer: this.ChainIndexer, consensusRules: this.ConsensusRules); await this.consensus.InitializeAsync(chainState.BlockStoreTip); this.entry.Fee(11); this.entry.Height(11); var dateTimeProviderSet = new DateTimeProviderSet { time = dateTimeProvider.GetTime(), timeutc = dateTimeProvider.GetUtcNow() }; this.DateTimeProvider = dateTimeProviderSet; this.mempool = new TxMempool(dateTimeProvider, new BlockPolicyEstimator(new MempoolSettings(nodeSettings), loggerFactory, nodeSettings), loggerFactory, nodeSettings); this.mempoolLock = new MempoolSchedulerLock(); // We can't make transactions until we have inputs // Therefore, load 100 blocks :) this.baseheight = 0; var blocks = new List <Block>(); this.txFirst = new List <Transaction>(); this.nonce = 0; for (int i = 0; i < this.blockinfo.Count; ++i) { Block block = this.network.CreateBlock(); block.Header.HashPrevBlock = this.consensus.Tip.HashBlock; block.Header.Version = 1; block.Header.Time = Utils.DateTimeToUnixTime(this.ChainIndexer.Tip.GetMedianTimePast()) + 1; Transaction txCoinbase = this.network.CreateTransaction(); txCoinbase.Version = 1; txCoinbase.AddInput(new TxIn(new Script(new[] { Op.GetPushOp(this.blockinfo[i].extranonce), Op.GetPushOp(this.ChainIndexer.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())); block.AddTransaction(txCoinbase); if (this.txFirst.Count == 0) { this.baseheight = this.ChainIndexer.Height; } if (this.txFirst.Count < 4) { this.txFirst.Add(block.Transactions[0]); } block.Header.Bits = block.Header.GetWorkRequired(this.network, this.ChainIndexer.Tip); block.UpdateMerkleRoot(); while (!block.CheckProofOfWork()) { block.Header.Nonce = ++this.nonce; } // Serialization sets the BlockSize property. block = Block.Load(block.ToBytes(), this.network.Consensus.ConsensusFactory); var res = await this.consensus.BlockMinedAsync(block); if (res == null) { throw new InvalidOperationException(); } blocks.Add(block); } // Just to make sure we can still make simple blocks this.newBlock = AssemblerForTest(this).Build(this.ChainIndexer.Tip, this.scriptPubKey); Assert.NotNull(this.newBlock); }
public TestContext() { this.blockinfo = new List <Blockinfo>(); var lst = blockinfoarr.Cast <long>().ToList(); for (int i = 0; i < lst.Count; i += 2) { this.blockinfo.Add(new Blockinfo() { extranonce = (int)lst[i], nonce = (uint)lst[i + 1] }); } // Note that by default, these tests run with size accounting enabled. this.network = Network.Main; var hex = Encoders.Hex.DecodeData("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"); this.scriptPubKey = new Script(new[] { Op.GetPushOp(hex), OpcodeType.OP_CHECKSIG }); this.newBlock = new BlockTemplate(); this.entry = new TestMemPoolEntryHelper(); this.chain = new ConcurrentChain(this.network); this.network.Consensus.Options = new PowConsensusOptions(); this.cachedCoinView = new CachedCoinView(new InMemoryCoinView(this.chain.Tip.HashBlock), new LoggerFactory()); this.consensus = new ConsensusLoop(new PowConsensusValidator(this.network), this.chain, this.cachedCoinView, new LookaheadBlockPuller(this.chain, new ConnectionManager(this.network, new NodeConnectionParameters(), new NodeSettings(), new LoggerFactory(), new NodeLifetime()), new LoggerFactory()), new NodeDeployments(this.network)); this.consensus.Initialize(); this.entry.Fee(11); this.entry.Height(11); var date1 = new MemoryPoolTests.DateTimeProviderSet(); date1.time = DateTimeProvider.Default.GetTime(); date1.timeutc = DateTimeProvider.Default.GetUtcNow(); this.date = date1; this.mempool = new TxMempool(new FeeRate(1000), DateTimeProvider.Default, new BlockPolicyEstimator(new FeeRate(1000), NodeSettings.Default(), new LoggerFactory()), new LoggerFactory());; this.mempoolLock = new MempoolAsyncLock(); // Simple block creation, nothing special yet: this.newBlock = AssemblerForTest(this).CreateNewBlock(this.scriptPubKey); this.chain.SetTip(this.newBlock.Block.Header); this.consensus.AcceptBlock(new ContextInformation(new BlockResult { Block = this.newBlock.Block }, this.network.Consensus) { CheckPow = false, CheckMerkleRoot = false }); // We can't make transactions until we have inputs // Therefore, load 100 blocks :) this.baseheight = 0; List <Block> blocks = new List <Block>(); this.txFirst = new List <Transaction>(); for (int i = 0; i < this.blockinfo.Count; ++i) { var pblock = this.newBlock.Block.Clone(); // pointer for convenience pblock.Header.HashPrevBlock = this.chain.Tip.HashBlock; pblock.Header.Version = 1; pblock.Header.Time = Utils.DateTimeToUnixTime(this.chain.Tip.GetMedianTimePast()) + 1; Transaction txCoinbase = pblock.Transactions[0].Clone(); txCoinbase.Inputs.Clear(); txCoinbase.Version = 1; txCoinbase.AddInput(new TxIn(new Script(new[] { Op.GetPushOp(this.blockinfo[i].extranonce), Op.GetPushOp(this.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())); pblock.Transactions[0] = txCoinbase; if (this.txFirst.Count == 0) { this.baseheight = this.chain.Height; } if (this.txFirst.Count < 4) { this.txFirst.Add(pblock.Transactions[0]); } pblock.UpdateMerkleRoot(); pblock.Header.Nonce = this.blockinfo[i].nonce; this.chain.SetTip(pblock.Header); this.consensus.AcceptBlock(new ContextInformation(new BlockResult { Block = pblock }, this.network.Consensus) { CheckPow = false, CheckMerkleRoot = false }); blocks.Add(pblock); } // Just to make sure we can still make simple blocks this.newBlock = AssemblerForTest(this).CreateNewBlock(this.scriptPubKey); Assert.NotNull(this.newBlock); }