예제 #1
0
        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));
        }
예제 #2
0
        public async Task PeerBanning_ResettingExpiredBannedPeerAsync()
        {
            // Arrange
            string     dataDir    = Path.Combine("TestData", nameof(PeerBanningTest), nameof(this.PeerBanning_ResettingExpiredBannedPeerAsync));
            DataFolder dataFolder = AssureEmptyDirAsDataFolder(dataDir);

            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);
        }
예제 #3
0
        public async Task PeerBanning_SavingAndLoadingBannedPeerToAddressManagerStoreAsync()
        {
            // Arrange
            string     dataDir    = Path.Combine("TestData", nameof(PeerBanningTest), nameof(this.PeerBanning_SavingAndLoadingBannedPeerToAddressManagerStoreAsync));
            DataFolder dataFolder = AssureEmptyDirAsDataFolder(dataDir);

            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);
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
        /// <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(testChainContext.Network.Consensus))
                {
                    ++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);
        }
예제 #6
0
        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.PeerAddressManager.AddPeer(peer, peer.Address.MapToIPv6());

            context.MockReadOnlyNodesCollection.Setup(s => s.FindByEndpoint(It.IsAny <IPEndPoint>())).Returns((INetworkPeer)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));
        }