private static async Task <BlockTemplate> MineBlockAsync(TestChainContext testChainContext, Script scriptPubKey, TxMempool mempool, MempoolSchedulerLock mempoolLock, bool getMutatedBlock = false) { BlockTemplate newBlock = CreateBlockTemplate(testChainContext, scriptPubKey, mempool, mempoolLock); if (getMutatedBlock) { BuildMutatedBlock(newBlock); } newBlock.Block.UpdateMerkleRoot(); TryFindNonceForProofOfWork(testChainContext, newBlock); if (!getMutatedBlock) { await ValidateBlock(testChainContext, newBlock); } else { CheckBlockIsMutated(newBlock); } return(newBlock); }
public async Task NodeIsSynced_PeerSendsABadBlockAndPeerIsWhitelisted_ThePeerIsNotBanned_Async() { string dataDir = Path.Combine("TestData", nameof(PeerBanningTest), nameof(this.NodeIsSynced_PeerSendsABadBlockAndPeerIsWhitelisted_ThePeerIsNotBanned_Async)); Directory.CreateDirectory(dataDir); TestChainContext context = await TestChainFactory.CreateAsync(Network.RegTest, dataDir); var peerEndPoint = new IPEndPoint(IPAddress.Parse("1.2.3.4"), context.Network.DefaultPort); var connectionManagerBehavior = new ConnectionManagerBehavior(false, context.ConnectionManager, context.LoggerFactory) { Whitelisted = true }; var peer = new Mock <INetworkPeer>(); peer.Setup(p => p.Behavior <ConnectionManagerBehavior>()).Returns(connectionManagerBehavior); context.MockReadOnlyNodesCollection.Setup(s => s.FindByEndpoint(It.IsAny <IPEndPoint>())).Returns(peer.Object); var blocks = await TestChainFactory.MineBlocksAsync(context, 2, new Key().ScriptPubKey); // create a new block that breaks consensus. var block = blocks.First(); block.Header.HashPrevBlock = context.Chain.Tip.HashBlock; await context.Consensus.AcceptBlockAsync(new BlockValidationContext { Block = block, Peer = peerEndPoint }); Assert.False(context.PeerBanning.IsBanned(peerEndPoint)); }
public async Task PeerBanning_SavingAndLoadingBannedPeerToAddressManagerStoreAsync() { // Arrange string dataDir = GetTestDirectoryPath(this); TestChainContext context = await TestChainFactory.CreateAsync(Network.RegTest, dataDir); IPAddress ipAddress = IPAddress.Parse("::ffff:192.168.0.1"); var endpoint = new IPEndPoint(ipAddress, 80); context.PeerAddressManager.AddPeer(endpoint, endpoint.Address.MapToIPv6()); // Act - Ban Peer, save store, clear current Peers, load store context.PeerBanning.BanPeer(endpoint, context.ConnectionManager.ConnectionSettings.BanTimeSeconds, nameof(PeerBanningTest)); context.PeerAddressManager.SavePeers(); context.PeerAddressManager.Peers.Clear(); context.PeerAddressManager.LoadPeers(); // Assert PeerAddress peer = context.PeerAddressManager.FindPeer(endpoint); Assert.NotNull(peer.BanTimeStamp); Assert.NotNull(peer.BanUntil); Assert.NotEmpty(peer.BanReason); }
public async Task PeerBanning_ResettingExpiredBannedPeerAsync() { // Arrange string dataDir = GetTestDirectoryPath(this); TestChainContext context = await TestChainFactory.CreateAsync(Network.RegTest, dataDir); IPAddress ipAddress = IPAddress.Parse("::ffff:192.168.0.1"); var endpoint = new IPEndPoint(ipAddress, 80); context.PeerAddressManager.AddPeer(endpoint, endpoint.Address.MapToIPv6()); // Act context.PeerBanning.BanPeer(endpoint, 1, nameof(PeerBanningTest)); context.PeerAddressManager.SavePeers(); // Wait one second for ban to expire. Thread.Sleep(1000); context.PeerAddressManager.Peers.Clear(); context.PeerAddressManager.LoadPeers(); // Assert PeerAddress peer = context.PeerAddressManager.FindPeer(endpoint); Assert.Null(peer.BanTimeStamp); Assert.Null(peer.BanUntil); Assert.Empty(peer.BanReason); }
public async Task NodeIsSynced_PeerSendsABadBlockAndPeerIsBandAndBanIsExpired_ThePeerIsNotBanned_Async() { string dataDir = Path.Combine("TestData", nameof(PeerBanningTest), nameof(this.NodeIsSynced_PeerSendsABadBlockAndPeerIsBandAndBanIsExpired_ThePeerIsNotBanned_Async)); Directory.CreateDirectory(dataDir); TestChainContext context = await TestChainFactory.CreateAsync(Network.RegTest, dataDir); var peer = new IPEndPoint(IPAddress.Parse("1.2.3.4"), context.Network.DefaultPort); var connectionManagerBehavior = new ConnectionManagerBehavior(false, context.ConnectionManager, context.LoggerFactory) { Whitelisted = true }; var node = new NetworkPeer(context.DateTimeProvider, context.LoggerFactory); node.Behaviors.Add(connectionManagerBehavior); context.MockReadOnlyNodesCollection.Setup(s => s.FindByEndpoint(It.IsAny <IPEndPoint>())).Returns(node); var blocks = await TestChainFactory.MineBlocksAsync(context, 2, new Key().ScriptPubKey); // create a new block that breaks consensus. var block = blocks.First(); block.Header.HashPrevBlock = context.Chain.Tip.HashBlock; await context.Consensus.AcceptBlockAsync(new BlockValidationContext { Block = block, Peer = peer, BanDurationSeconds = 1 }); // ban for 1 second // wait 1 sec for ban to expire. Thread.Sleep(1000); Assert.False(context.PeerBanning.IsBanned(peer)); }
private static async Task <Block> MineAMutatedBlockAsync(TestChainContext context) { var blocks = await TestChainFactory.MineBlocksWithLastBlockMutatedAsync(context, 1, MinerScriptPubKey); var block = blocks.Last(); return(block); }
private static async Task ValidateBlock(TestChainContext testChainContext, BlockTemplate newBlock) { var context = new ValidationContext { Block = newBlock.Block }; await testChainContext.Consensus.AcceptBlockAsync(context); Assert.Null(context.Error); }
private static void MockPeerConnection(TestChainContext context, bool whiteListedPeer) { var connectionManagerBehavior = new ConnectionManagerBehavior(false, context.ConnectionManager, context.LoggerFactory) { Whitelisted = whiteListedPeer }; var peer = new Mock <INetworkPeer>(); peer.Setup(p => p.Behavior <ConnectionManagerBehavior>()).Returns(connectionManagerBehavior); context.MockReadOnlyNodesCollection.Setup(s => s.FindByEndpoint(It.IsAny <IPEndPoint>())).Returns(peer.Object); }
/// <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); }
private async Task <(TestChainContext context, IPEndPoint peerEndPoint)> InitialiseContextAndPeerEndpointAsync() { string dataDir = GetTestDirectoryPath(this); TestChainContext context = await TestChainFactory.CreateAsync(Network.RegTest, dataDir); var peerEndPoint = new IPEndPoint(IPAddress.Parse("1.2.3.4"), context.Network.DefaultPort); context.PeerAddressManager.AddPeer(peerEndPoint, peerEndPoint.Address.MapToIPv6()); return(context, peerEndPoint); }
private static void TryFindNonceForProofOfWork(TestChainContext testChainContext, BlockTemplate newBlock) { int maxTries = int.MaxValue; while (maxTries > 0 && !newBlock.Block.CheckProofOfWork()) { ++newBlock.Block.Header.Nonce; --maxTries; } if (maxTries == 0) { throw new XunitException("Test failed no blocks found"); } }
private static BlockTemplate CreateBlockTemplate(TestChainContext testChainContext, Script scriptPubKey, TxMempool mempool, MempoolSchedulerLock mempoolLock) { PowBlockDefinition blockAssembler = new PowBlockDefinition(testChainContext.Consensus, testChainContext.DateTimeProvider, testChainContext.LoggerFactory as LoggerFactory, mempool, mempoolLock, new MinerSettings(testChainContext.NodeSettings), testChainContext.Network, testChainContext.ConsensusRules); 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> /// Mine new blocks in to the consensus database and the chain. /// </summary> public static async Task <List <Block> > MineBlocksAsync(TestChainContext testChainContext, int count, Script scriptPubKey) { BlockPolicyEstimator blockPolicyEstimator = new BlockPolicyEstimator(new MempoolSettings(testChainContext.NodeSettings), testChainContext.LoggerFactory, testChainContext.NodeSettings); TxMempool mempool = new TxMempool(testChainContext.DateTimeProvider, blockPolicyEstimator, testChainContext.LoggerFactory, testChainContext.NodeSettings); MempoolSchedulerLock mempoolLock = new MempoolSchedulerLock(); // Simple block creation, nothing special yet: List <Block> blocks = new List <Block>(); for (int i = 0; i < count; ++i) { PowBlockAssembler blockAssembler = CreatePowBlockAssembler(testChainContext.Network, testChainContext.Consensus, testChainContext.Chain, mempoolLock, mempool, testChainContext.DateTimeProvider, testChainContext.LoggerFactory as LoggerFactory); BlockTemplate newBlock = blockAssembler.CreateNewBlock(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); newBlock.Block.UpdateMerkleRoot(); var maxTries = int.MaxValue; while (maxTries > 0 && !newBlock.Block.CheckProofOfWork()) { ++newBlock.Block.Header.Nonce; --maxTries; } if (maxTries == 0) { throw new XunitException("Test failed no blocks found"); } var context = new BlockValidationContext { Block = newBlock.Block }; await testChainContext.Consensus.AcceptBlockAsync(context); Assert.Null(context.Error); blocks.Add(newBlock.Block); } return(blocks); }
/// <summary> /// Mine new blocks in to the consensus database and the chain. /// </summary> private static async Task <List <Block> > MineBlocksAsync(TestChainContext testChainContext, int count, Script receiver, bool mutateLastBlock) { var blockPolicyEstimator = new BlockPolicyEstimator(new MempoolSettings(testChainContext.NodeSettings), testChainContext.LoggerFactory, testChainContext.NodeSettings); var mempool = new TxMempool(testChainContext.DateTimeProvider, blockPolicyEstimator, testChainContext.LoggerFactory, testChainContext.NodeSettings); var mempoolLock = new MempoolSchedulerLock(); // Simple block creation, nothing special yet: var blocks = new List <Block>(); for (int i = 0; i < count; i++) { BlockTemplate newBlock = await MineBlockAsync(testChainContext, receiver, mempool, mempoolLock, mutateLastBlock&& i == count - 1); blocks.Add(newBlock.Block); } return(blocks); }
/// <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 async Task NodeIsSynced_PeerSendsABadBlockAndPeerDiconnected_ThePeerGetsBanned_Async() { string dataDir = Path.Combine("TestData", nameof(PeerBanningTest), nameof(this.NodeIsSynced_PeerSendsABadBlockAndPeerDiconnected_ThePeerGetsBanned_Async)); Directory.CreateDirectory(dataDir); TestChainContext context = await TestChainFactory.CreateAsync(Network.RegTest, dataDir); var peer = new IPEndPoint(IPAddress.Parse("1.2.3.4"), context.Network.DefaultPort); context.MockReadOnlyNodesCollection.Setup(s => s.FindByEndpoint(It.IsAny <IPEndPoint>())).Returns((NetworkPeer)null); var blocks = await TestChainFactory.MineBlocksAsync(context, 2, new Key().ScriptPubKey); var block = blocks.First(); block.Header.HashPrevBlock = context.Chain.Tip.HashBlock; await context.Consensus.AcceptBlockAsync(new BlockValidationContext { Block = block, Peer = peer }); Assert.True(context.PeerBanning.IsBanned(peer)); }
public async Task PeerBanning_AddingBannedPeerToAddressManagerStoreAsync() { // Arrange string dataDir = GetTestDirectoryPath(this); TestChainContext context = await TestChainFactory.CreateAsync(Network.RegTest, dataDir); IPAddress ipAddress = IPAddress.Parse("::ffff:192.168.0.1"); var endpoint = new IPEndPoint(ipAddress, 80); context.PeerAddressManager.AddPeer(endpoint, endpoint.Address.MapToIPv6()); // Act context.PeerBanning.BanAndDisconnectPeer(endpoint, context.ConnectionManager.ConnectionSettings.BanTimeSeconds, nameof(PeerBanningTest)); // Assert PeerAddress peer = context.PeerAddressManager.FindPeer(endpoint); Assert.True(peer.BanUntil.HasValue); Assert.NotNull(peer.BanUntil); Assert.NotEmpty(peer.BanReason); }
private static async Task <Block> Mine2BlocksAndCreateABlockWithBadPrevHashAsync(TestChainContext context) { var blocks = await TestChainFactory.MineBlocksAsync(context, 2, MinerScriptPubKey); var block = blocks.First(); block.Header.HashPrevBlock = context.Chain.Tip.HashBlock; return(block); }
/// <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); }
private static async Task ValidateBlock(TestChainContext testChainContext, BlockTemplate newBlock) { var res = await testChainContext.Consensus.BlockMinedAsync(newBlock.Block); Assert.NotNull(res); }
public static async Task <List <Block> > MineBlocksAsync(TestChainContext testChainContext, int count, Script receiver) { return(await MineBlocksAsync(testChainContext, count, receiver, false)); }
public static async Task <List <Block> > MineBlocksWithLastBlockMutatedAsync(TestChainContext testChainContext, int count, Script receiver) { return(await MineBlocksAsync(testChainContext, count, receiver, true)); }