public RewardClaimerTests()
        {
            this.network = new StraxRegTest
            {
                RewardClaimerBatchActivationHeight = 40,
                RewardClaimerBlockInterval         = 10
            };

            this.addressHelper               = new MultisigAddressHelper(this.network, new CirrusRegTest());
            this.broadCasterManager          = Substitute.For <IBroadcasterManager>();
            this.chainIndexer                = new ChainIndexer(this.network);
            this.consensusManager            = Substitute.For <IConsensusManager>();
            this.dbreezeSerializer           = new DBreezeSerializer(this.network.Consensus.ConsensusFactory);
            this.conversionRequestRepository = Substitute.For <IConversionRequestRepository>();

            this.loggerFactory = Substitute.For <ILoggerFactory>();
            this.signals       = new Signals(this.loggerFactory, null);

            this.initialBlockDownloadState = Substitute.For <IInitialBlockDownloadState>();
            this.initialBlockDownloadState.IsInitialBlockDownload().Returns(false);

            this.opReturnDataReader = new OpReturnDataReader(new CirrusRegTest());

            this.federatedPegSettings = Substitute.For <IFederatedPegSettings>();
            this.federatedPegSettings.MultiSigRedeemScript.Returns(this.addressHelper.PayToMultiSig);

            this.federatedPegSettings.MinimumConfirmationsSmallDeposits.Returns(5);
            this.federatedPegSettings.MinimumConfirmationsNormalDeposits.Returns(10);
            this.federatedPegSettings.MinimumConfirmationsLargeDeposits.Returns(20);

            this.federatedPegSettings.SmallDepositThresholdAmount.Returns(Money.Coins(10));
            this.federatedPegSettings.NormalDepositThresholdAmount.Returns(Money.Coins(100));
        }
Beispiel #2
0
        public async Task Can_UnBan_Peer_From_ApiAsync()
        {
            using (var builder = NodeBuilder.Create(this))
            {
                var network = new StraxRegTest();

                var nodeA = builder.CreateStratisPosNode(network, "nc-2-nodeA").Start();

                var nodeB_Ip        = "127.0.0.2";
                var nodeB_IpAddress = IPAddress.Parse(nodeB_Ip);
                var nodeB_EndPoint  = new IPEndPoint(nodeB_IpAddress, 0);

                var nodeAaddressManager = nodeA.FullNode.NodeService <IPeerAddressManager>();
                nodeAaddressManager.AddPeer(new IPEndPoint(nodeB_IpAddress, 0), IPAddress.Loopback);

                var peerBanning = nodeA.FullNode.NodeService <IPeerBanning>();
                peerBanning.BanAndDisconnectPeer(nodeB_EndPoint);
                Assert.True(peerBanning.IsBanned(nodeB_EndPoint));

                var unBanPeerModel = new SetBanPeerViewModel()
                {
                    BanCommand  = "remove",
                    PeerAddress = nodeB_Ip
                };

                await $"http://localhost:{nodeA.ApiPort}/api".AppendPathSegment("network/setban").PostJsonAsync(unBanPeerModel);

                Assert.False(peerBanning.IsBanned(nodeB_EndPoint));
            }
        }
Beispiel #3
0
        public void Mempool_SendOversizeTransaction_ShouldRejectByMempool()
        {
            var network = new StraxRegTest();

            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode stratisSender = builder.CreateStratisPosNode(network).WithReadyBlockchainData(ReadyBlockchain.StraxRegTest10Miner).Start();

                TestHelper.MineBlocks(stratisSender, 5);

                // Send coins to the receiver
                var context = WalletTests.CreateContext(network, new WalletAccountReference(WalletName, Account), Password, new Key().PubKey.GetAddress(network).ScriptPubKey, Money.COIN * 100, FeeType.Medium, 1);

                Transaction trx = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(context);

                // Add nonsense script to make tx large.
                Script script = Script.FromBytesUnsafe(new string('A', network.Consensus.Options.MaxStandardTxWeight).Select(c => (byte)c).ToArray());
                trx.Outputs.Add(new TxOut(new Money(1), script));

                // Sign trx again after adding an output
                trx = context.TransactionBuilder.SignTransaction(trx);

                // Enable standard policy relay.
                stratisSender.FullNode.NodeService <MempoolSettings>().RequireStandard = true;

                var broadcaster = stratisSender.FullNode.NodeService <IBroadcasterManager>();

                broadcaster.BroadcastTransactionAsync(trx).GetAwaiter().GetResult();
                var entry = broadcaster.GetTransaction(trx.GetHash());

                Assert.Equal("tx-size", entry.ErrorMessage);
            }
        }
Beispiel #4
0
        public void CanCheckBlockWithWitnessInInput()
        {
            var network = new StraxRegTest();

            var blockHex = "00000020e46299aa9ab7a76ce77c705ac50d6b031386246689cea9bde33fb851ca3c287726236faaa13be02ea891cdffbc229c9c39f9fdd957009ccf86d8c3311c377353eda4645fffff7f200500000001010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff025100ffffffff0200d2496b000000002321033ee9fd42c7ea8a3374710ea4e8af00d56015e1ed7c61a31eac29114e080f120fac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf9012000000000000000000000000000000000000000000000000000000000000000000000000000";

            Block block = Block.Load(Encoders.Hex.DecodeData(blockHex), network.Consensus.ConsensusFactory);

            var consensusFlags = new DeploymentFlags
            {
                ScriptFlags   = ScriptVerify.Witness | ScriptVerify.P2SH | ScriptVerify.Standard,
                LockTimeFlags = Transaction.LockTimeFlags.MedianTimePast,
                EnforceBIP34  = true
            };

            var context = new RuleContext
            {
                Time = DateTimeOffset.UtcNow,
                ValidationContext = new ValidationContext {
                    BlockToValidate = block
                },
                Flags = consensusFlags,
            };

            network.Consensus.Options = new ConsensusOptions();
            new WitnessCommitmentsRule().ValidateWitnessCommitment(context, network).GetAwaiter().GetResult();

            var rule    = new CheckPowTransactionRule();
            var options = network.Consensus.Options;

            foreach (Transaction tx in block.Transactions)
            {
                rule.CheckTransaction(network, options, tx);
            }
        }
Beispiel #5
0
        public void Mempool_SendTransactionWithLargeOpReturn_ShouldRejectByMempool()
        {
            var network = new StraxRegTest();

            using (var builder = NodeBuilder.Create(this))
            {
                CoreNode stratisSender = builder.CreateStratisPosNode(network).WithReadyBlockchainData(ReadyBlockchain.StraxRegTest10Miner).Start();

                TestHelper.MineBlocks(stratisSender, 5);

                // Send coins to the receiver.
                var context = WalletTests.CreateContext(network, new WalletAccountReference(WalletName, Account), Password, new Key().PubKey.GetAddress(network).ScriptPubKey, Money.COIN * 100, FeeType.Medium, 1);
                context.OpReturnData   = "1";
                context.OpReturnAmount = Money.Coins(0.01m);
                Transaction trx = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(context);

                foreach (TxOut output in trx.Outputs)
                {
                    if (output.ScriptPubKey.IsUnspendable)
                    {
                        var data = new int[StraxStandardScriptsRegistry.MaxOpReturnRelay + 1];
                        for (int i = 0; i < StraxStandardScriptsRegistry.MaxOpReturnRelay + 1; i++)
                        {
                            data[i] = 0;
                        }
                        var ops = new Op[data.Length + 1];
                        ops[0] = OpcodeType.OP_RETURN;
                        for (int i = 0; i < data.Length; i++)
                        {
                            ops[1 + i] = Op.GetPushOp(data[i]);
                        }

                        output.ScriptPubKey = new Script(ops);
                    }
                }

                // Sign trx again after lengthening nulldata output.
                trx = context.TransactionBuilder.SignTransaction(trx);

                // Enable standard policy relay.
                stratisSender.FullNode.NodeService <MempoolSettings>().RequireStandard = true;

                var broadcaster = stratisSender.FullNode.NodeService <IBroadcasterManager>();

                broadcaster.BroadcastTransactionAsync(trx).GetAwaiter().GetResult();
                var entry = broadcaster.GetTransaction(trx.GetHash());

                Assert.Equal("scriptpubkey", entry.ErrorMessage);
            }
        }
        public async Task CanRetrieveFilteredUtxosAsync()
        {
            using (var builder = NodeBuilder.Create(this))
            {
                var network = new StraxRegTest();

                CoreNode stratisSender    = CreatePowPosMiningNode(builder, network, TestBase.CreateTestDir(this), coldStakeNode: false);
                CoreNode stratisColdStake = CreatePowPosMiningNode(builder, network, TestBase.CreateTestDir(this), coldStakeNode: true);

                stratisSender.WithReadyBlockchainData(ReadyBlockchain.StraxRegTest150Miner).Start();
                stratisColdStake.WithWallet().Start();

                var coldWalletManager = stratisColdStake.FullNode.WalletManager() as ColdStakingManager;

                // Set up cold staking account on cold wallet.
                coldWalletManager.GetOrCreateColdStakingAccount(WalletName, true, Password, null);
                HdAddress coldWalletAddress = coldWalletManager.GetFirstUnusedColdStakingAddress(WalletName, true);

                var  walletAccountReference = new WalletAccountReference(WalletName, Account);
                long total2 = stratisSender.FullNode.WalletManager().GetSpendableTransactionsInAccount(walletAccountReference, 1).Sum(s => s.Transaction.Amount);

                // Sync nodes.
                TestHelper.Connect(stratisSender, stratisColdStake);

                // Send coins to cold address.
                Money       amountToSend = total2 - network.Consensus.ProofOfWorkReward;
                Transaction transaction1 = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(CreateContext(stratisSender.FullNode.Network, new WalletAccountReference(WalletName, Account), Password, coldWalletAddress.ScriptPubKey, amountToSend, FeeType.Medium, 1));

                // Broadcast to the other nodes.
                await stratisSender.FullNode.NodeController <WalletController>().SendTransaction(new SendTransactionRequest(transaction1.ToHex()));

                // Wait for the transaction to arrive.
                TestBase.WaitLoop(() => stratisColdStake.CreateRPCClient().GetRawMempool().Length > 0);

                // Despite the funds being sent to an address in the cold account, the wallet does not recognise the output as funds belonging to it.
                Assert.True(stratisColdStake.FullNode.WalletManager().GetBalances(WalletName, Account).Sum(a => a.AmountUnconfirmed + a.AmountUnconfirmed) == 0);

                uint256[] mempoolTransactionId = stratisColdStake.CreateRPCClient().GetRawMempool();

                Transaction misspentTransaction = stratisColdStake.CreateRPCClient().GetRawTransaction(mempoolTransactionId[0]);

                // Now retrieve the UTXO sent to the cold address. The funds will reappear in a normal account on the cold staking node.
                stratisColdStake.FullNode.NodeController <ColdStakingController>().RetrieveFilteredUtxos(new RetrieveFilteredUtxosRequest()
                {
                    WalletName = stratisColdStake.WalletName, WalletPassword = stratisColdStake.WalletPassword, Hex = misspentTransaction.ToHex(), WalletAccount = null, Broadcast = true
                });

                TestBase.WaitLoop(() => stratisColdStake.FullNode.WalletManager().GetBalances(WalletName, Account).Sum(a => a.AmountUnconfirmed + a.AmountUnconfirmed) > 0);
            }
        }
        public void MiningAndPropagatingPOS_MineBlockCheckPeerHasNewBlock()
        {
            using (NodeBuilder nodeBuilder = NodeBuilder.Create(this))
            {
                var network = new StraxRegTest();

                CoreNode node   = nodeBuilder.CreateStratisPosNode(network, "posmining-1-node").WithDummyWallet().Start();
                CoreNode syncer = nodeBuilder.CreateStratisPosNode(network, "posmining-1-syncer").Start();

                TestHelper.MineBlocks(node, 1);
                Assert.NotEqual(node.FullNode.ConsensusManager().Tip, syncer.FullNode.ConsensusManager().Tip);

                TestHelper.ConnectAndSync(node, syncer);
                Assert.Equal(node.FullNode.ConsensusManager().Tip, syncer.FullNode.ConsensusManager().Tip);
            }
        }
Beispiel #8
0
        public async Task TestScanRPCCapabilitiesOnStratisNetworkAsync()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                Network   network   = new StraxRegTest();
                var       node      = builder.CreateStratisPosNode(network).WithReadyBlockchainData(ReadyBlockchain.StraxRegTest10Miner).Start();
                RPCClient rpcClient = node.CreateRPCClient();

                RPCCapabilities capabilities = await rpcClient.ScanRPCCapabilitiesAsync();

                capabilities.SupportEstimateSmartFee.Should().BeFalse();
                capabilities.SupportGetNetworkInfo.Should().BeTrue();
                capabilities.SupportScanUTXOSet.Should().BeFalse();
                capabilities.SupportSignRawTransactionWith.Should().BeFalse();
                capabilities.SupportSegwit.Should().BeTrue();
                capabilities.SupportGenerateToAddress.Should().BeTrue();
            }
        }
Beispiel #9
0
        public async Task Can_BanAndDisconnect_Peer_From_ApiAsync()
        {
            using (var builder = NodeBuilder.Create(this))

            {
                var network = new StraxRegTest();

                var nodeA = builder.CreateStratisPosNode(network, "nc-1-nodeA").Start();

                var nodeBIp        = "127.0.0.2";
                var nodeBIpAddress = IPAddress.Parse(nodeBIp);

                var nodeBConfig = new NodeConfigParameters
                {
                    { "-externalip", nodeBIp }
                };

                var nodeB = builder.CreateStratisPosNode(network, agent: "nc-1-nodeB", configParameters: nodeBConfig).Start();

                var nodeAaddressManager = nodeA.FullNode.NodeService <IPeerAddressManager>();
                nodeAaddressManager.AddPeer(new IPEndPoint(nodeBIpAddress, nodeB.Endpoint.Port), IPAddress.Loopback);

                TestHelper.Connect(nodeA, nodeB);

                var banPeerModel = new SetBanPeerViewModel()
                {
                    BanDurationSeconds = 100,
                    BanCommand         = "add",
                    PeerAddress        = nodeBIp
                };

                await $"http://localhost:{nodeA.ApiPort}/api".AppendPathSegment("network/setban").PostJsonAsync(banPeerModel);

                TestBase.WaitLoop(() => !TestHelper.IsNodeConnectedTo(nodeA, nodeB));

                var nodeBEndPoint = new IPEndPoint(nodeBIpAddress, nodeB.Endpoint.Port);

                var addressManager = nodeA.FullNode.NodeService <IPeerAddressManager>();
                var peer           = nodeAaddressManager.FindPeer(nodeBEndPoint);

                var peerBanning = nodeA.FullNode.NodeService <IPeerBanning>();
                Assert.True(peerBanning.IsBanned(nodeBEndPoint));
            }
        }
Beispiel #10
0
        public async Task Can_GetBannedPeers_From_ApiAsync()
        {
            using (var builder = NodeBuilder.Create(this))
            {
                var network = new StraxRegTest();

                var nodeA = builder.CreateStratisPosNode(network, "nc-4-nodeA").Start();

                var nodeB_Ip        = "127.0.0.2";
                var nodeB_IpAddress = IPAddress.Parse(nodeB_Ip);
                var nodeB_EndPoint  = new IPEndPoint(nodeB_IpAddress, 0);

                var nodeB_Ip2        = "127.0.0.3";
                var nodeB_IpAddress2 = IPAddress.Parse(nodeB_Ip2);
                var nodeB_EndPoint2  = new IPEndPoint(nodeB_IpAddress2, 0);

                var nodeAaddressManager = nodeA.FullNode.NodeService <IPeerAddressManager>();
                nodeAaddressManager.AddPeer(new IPEndPoint(nodeB_IpAddress, 0), IPAddress.Loopback);

                var peerBanning = nodeA.FullNode.NodeService <IPeerBanning>();
                peerBanning.BanAndDisconnectPeer(nodeB_EndPoint, "This peer is banned because of a reason");
                Assert.True(peerBanning.IsBanned(nodeB_EndPoint));

                peerBanning.BanAndDisconnectPeer(nodeB_EndPoint2, "This peer is banned because of another reason");
                Assert.True(peerBanning.IsBanned(nodeB_EndPoint2));

                var bannedPeers = await $"http://localhost:{nodeA.ApiPort}/api".AppendPathSegment("network/getbans").GetJsonAsync <List <BannedPeerModel> >();

                Assert.Equal(2, bannedPeers.Count);
                bannedPeers = bannedPeers.OrderBy(b => b.EndPoint).ToList();

                var bannedPeer = bannedPeers[0];
                Assert.Equal("This peer is banned because of a reason", bannedPeer.BanReason);
                Assert.True(DateTime.UtcNow < bannedPeer.BanUntil.Value);
                Assert.Equal("[::ffff:127.0.0.2]:0", bannedPeer.EndPoint);

                bannedPeer = bannedPeers[1];
                Assert.Equal("This peer is banned because of another reason", bannedPeer.BanReason);
                Assert.True(DateTime.UtcNow < bannedPeer.BanUntil.Value);
                Assert.Equal("[::ffff:127.0.0.3]:0", bannedPeer.EndPoint);
            }
        }
Beispiel #11
0
        public void Mempool_SendPosTransaction_WithFutureLockTime_ShouldBeRejectedByMempool()
        {
            // See AcceptToMemoryPool_TxFinalCannotMine_ReturnsFalseAsync for the 'unit test' version

            var network = new StraxRegTest();

            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode stratisSender = builder.CreateStratisPosNode(network).WithReadyBlockchainData(ReadyBlockchain.StraxRegTest10Miner).Start();

                TestHelper.MineBlocks(stratisSender, 5);

                // Send coins to the receiver.
                var context = WalletTests.CreateContext(network, new WalletAccountReference(WalletName, Account), Password, new Key().PubKey.GetAddress(network).ScriptPubKey, Money.COIN * 100, FeeType.Medium, 1);

                Transaction trx = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(context);

                // Treat the locktime as absolute, not relative.
                trx.Inputs.First().Sequence = new Sequence(Sequence.SEQUENCE_LOCKTIME_DISABLE_FLAG);

                // Set the nLockTime to be ahead of the current tip so that locktime has not elapsed.
                trx.LockTime = new LockTime(stratisSender.FullNode.ChainIndexer.Height + 1);

                // Sign trx again after changing the nLockTime.
                trx = context.TransactionBuilder.SignTransaction(trx);

                // Enable standard policy relay.
                stratisSender.FullNode.NodeService <MempoolSettings>().RequireStandard = true;

                var broadcaster = stratisSender.FullNode.NodeService <IBroadcasterManager>();

                broadcaster.BroadcastTransactionAsync(trx).GetAwaiter().GetResult();
                var entry = broadcaster.GetTransaction(trx.GetHash());

                Assert.Equal("non-final", entry.ErrorMessage);
            }
        }
Beispiel #12
0
        public async Task Can_ClearAll_Banned_PeersAsync()
        {
            using (var builder = NodeBuilder.Create(this))
            {
                var network = new StraxRegTest();

                var nodeA = builder.CreateStratisPosNode(network, "nc-3-nodeA").Start();

                var nodeB_Ip        = "127.0.0.2";
                var nodeB_IpAddress = IPAddress.Parse(nodeB_Ip);
                var nodeB_EndPoint  = new IPEndPoint(nodeB_IpAddress, 0);

                var nodeAaddressManager = nodeA.FullNode.NodeService <IPeerAddressManager>();
                nodeAaddressManager.AddPeer(new IPEndPoint(nodeB_IpAddress, 0), IPAddress.Loopback);

                var peerBanning = nodeA.FullNode.NodeService <IPeerBanning>();
                peerBanning.BanAndDisconnectPeer(nodeB_EndPoint);
                Assert.True(peerBanning.IsBanned(nodeB_EndPoint));

                await $"http://localhost:{nodeA.ApiPort}/api".AppendPathSegment("network/clearbanned").PostJsonAsync(null);

                Assert.False(peerBanning.IsBanned(nodeB_EndPoint));
            }
        }
Beispiel #13
0
        public void Mempool_SendPosTransaction_WithElapsedLockTime_ShouldBeAcceptedByMempool()
        {
            // See CheckFinalTransaction_WithElapsedLockTime_ReturnsTrueAsync for the 'unit test' version

            var network = new StraxRegTest();

            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode stratisSender = builder.CreateStratisPosNode(network).WithReadyBlockchainData(ReadyBlockchain.StraxRegTest10Miner).Start();

                TestHelper.MineBlocks(stratisSender, 5);

                // Send coins to the receiver.
                var context = WalletTests.CreateContext(network, new WalletAccountReference(WalletName, Account), Password, new Key().PubKey.GetAddress(network).ScriptPubKey, Money.COIN * 100, FeeType.Medium, 1);

                Transaction trx = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(context);

                // Treat the locktime as absolute, not relative.
                trx.Inputs.First().Sequence = new Sequence(Sequence.SEQUENCE_LOCKTIME_DISABLE_FLAG);

                // Set the nLockTime to be behind the current tip so that locktime has elapsed.
                trx.LockTime = new LockTime(stratisSender.FullNode.ChainIndexer.Height - 1);

                // Sign trx again after changing the nLockTime.
                trx = context.TransactionBuilder.SignTransaction(trx);

                // Enable standard policy relay.
                stratisSender.FullNode.NodeService <MempoolSettings>().RequireStandard = true;

                var broadcaster = stratisSender.FullNode.NodeService <IBroadcasterManager>();

                broadcaster.BroadcastTransactionAsync(trx);

                TestBase.WaitLoop(() => stratisSender.CreateRPCClient().GetRawMempool().Length == 1);
            }
        }
Beispiel #14
0
        public void Staking_Wallet_Can_Mint_New_Coins()
        {
            using (var builder = NodeBuilder.Create(this))
            {
                var configParameters = new NodeConfigParameters {
                    { "txindex", "1" }
                };
                var network = new StraxRegTest();

                var minerA = builder.CreateStratisPosNode(network, "stake-1-minerA", configParameters: configParameters).OverrideDateTimeProvider().WithWallet().Start();

                var addressUsed = TestHelper.MineBlocks(minerA, (int)network.Consensus.PremineHeight).AddressUsed;

                //Since the pre - mine will not be immediately spendable, the transactions have to be counted directly from the address.
                addressUsed.Transactions.Count().Should().Be((int)network.Consensus.PremineHeight);

                addressUsed.Transactions.Sum(s => s.Amount).Should().Be(network.Consensus.PremineReward + network.Consensus.ProofOfWorkReward);

                // Mine blocks to maturity
                TestHelper.MineBlocks(minerA, (int)network.Consensus.CoinbaseMaturity + 10);

                // Get set of transaction IDs present in wallet before staking is started.
                this.transactionsBeforeStaking.Clear();
                foreach (TransactionData transactionData in this.GetTransactionsSnapshot(minerA))
                {
                    this.transactionsBeforeStaking.Add(transactionData.Id);
                }

                // Start staking on the node.
                var minter = minerA.FullNode.NodeService <IPosMinting>();
                minter.Stake(new WalletSecret()
                {
                    WalletName = "mywallet", WalletPassword = "******"
                });

                // If new transactions are appearing in the wallet, staking has been successful. Due to coin maturity settings the
                // spendable balance of the wallet actually drops after staking, so the wallet balance should not be used to
                // determine whether staking occurred.
                TestBase.WaitLoop(() =>
                {
                    List <TransactionData> transactions = this.GetTransactionsSnapshot(minerA);

                    foreach (TransactionData transactionData in transactions)
                    {
                        if (!this.transactionsBeforeStaking.Contains(transactionData.Id) && (transactionData.IsCoinStake ?? false))
                        {
                            return(true);
                        }
                    }

                    return(false);
                });

                // build a dictionary of coinstake tx's indexed by tx id.
                foreach (var tx in this.GetTransactionsSnapshot(minerA))
                {
                    this.transactionLookup[tx.Id] = tx;
                }

                TestBase.WaitLoop(() =>
                {
                    List <TransactionData> transactions = this.GetTransactionsSnapshot(minerA);

                    foreach (TransactionData transactionData in transactions)
                    {
                        if (!this.transactionsBeforeStaking.Contains(transactionData.Id) && (transactionData.IsCoinStake ?? false))
                        {
                            Transaction coinstakeTransaction = minerA.FullNode.BlockStore().GetTransactionById(transactionData.Id);
                            var balance = new Money(0);

                            // Add coinstake outputs to balance.
                            foreach (TxOut output in coinstakeTransaction.Outputs)
                            {
                                balance += output.Value;
                            }

                            //Subtract coinstake inputs from balance.
                            foreach (TxIn input in coinstakeTransaction.Inputs)
                            {
                                this.transactionLookup.TryGetValue(input.PrevOut.Hash, out TransactionData prevTransactionData);

                                if (prevTransactionData == null)
                                {
                                    continue;
                                }

                                Transaction prevTransaction = minerA.FullNode.BlockStore().GetTransactionById(prevTransactionData.Id);

                                balance -= prevTransaction.Outputs[input.PrevOut.N].Value;
                            }

                            Assert.Equal(minerA.FullNode.Network.Consensus.ProofOfStakeReward, balance);

                            return(true);
                        }
                    }

                    return(false);
                });
            }
        }
Beispiel #15
0
        public async Task WalletCanMineWithColdWalletCoinsAsync()
        {
            using (var builder = NodeBuilder.Create(this))
            {
                var network = new StraxRegTest();

                CoreNode stratisSender    = CreatePowPosMiningNode(builder, network, TestBase.CreateTestDir(this), coldStakeNode: false);
                CoreNode stratisHotStake  = CreatePowPosMiningNode(builder, network, TestBase.CreateTestDir(this), coldStakeNode: true);
                CoreNode stratisColdStake = CreatePowPosMiningNode(builder, network, TestBase.CreateTestDir(this), coldStakeNode: true);

                stratisSender.WithReadyBlockchainData(ReadyBlockchain.StraxRegTest150Miner).Start();
                stratisHotStake.WithWallet().Start();
                stratisColdStake.WithWallet().Start();

                var senderWalletManager = stratisSender.FullNode.WalletManager() as ColdStakingManager;
                var coldWalletManager   = stratisColdStake.FullNode.WalletManager() as ColdStakingManager;
                var hotWalletManager    = stratisHotStake.FullNode.WalletManager() as ColdStakingManager;

                // Set up cold staking account on cold wallet.
                coldWalletManager.GetOrCreateColdStakingAccount(WalletName, true, Password);
                HdAddress coldWalletAddress = coldWalletManager.GetFirstUnusedColdStakingAddress(WalletName, true);

                // Set up cold staking account on hot wallet.
                hotWalletManager.GetOrCreateColdStakingAccount(WalletName, false, Password);
                HdAddress hotWalletAddress = hotWalletManager.GetFirstUnusedColdStakingAddress(WalletName, false);

                var  walletAccountReference = new WalletAccountReference(WalletName, Account);
                long total2 = stratisSender.FullNode.WalletManager().GetSpendableTransactionsInAccount(walletAccountReference, 1).Sum(s => s.Transaction.Amount);

                // Sync all nodes
                TestHelper.ConnectAndSync(stratisHotStake, stratisSender);
                TestHelper.ConnectAndSync(stratisHotStake, stratisColdStake);
                TestHelper.Connect(stratisSender, stratisColdStake);

                // Send coins to hot wallet.
                Money     amountToSend = total2 - network.Consensus.ProofOfWorkReward;
                HdAddress sendto       = hotWalletManager.GetUnusedAddress(new WalletAccountReference(WalletName, Account));

                Transaction transaction1 = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(CreateContext(stratisSender.FullNode.Network, new WalletAccountReference(WalletName, Account), Password, sendto.ScriptPubKey, amountToSend, FeeType.Medium, 1));

                // Broadcast to the other node
                await stratisSender.FullNode.NodeController <WalletController>().SendTransaction(new SendTransactionRequest(transaction1.ToHex()));

                // Wait for the transaction to arrive
                TestBase.WaitLoop(() => stratisHotStake.CreateRPCClient().GetRawMempool().Length > 0);
                Assert.NotNull(stratisHotStake.CreateRPCClient().GetRawTransaction(transaction1.GetHash(), null, false));
                TestBase.WaitLoop(() => stratisHotStake.FullNode.WalletManager().GetSpendableTransactionsInWallet(WalletName).Any());

                long receiveTotal = stratisHotStake.FullNode.WalletManager().GetSpendableTransactionsInWallet(WalletName).Sum(s => s.Transaction.Amount);
                Assert.Equal(amountToSend, (Money)receiveTotal);
                Assert.Null(stratisHotStake.FullNode.WalletManager().GetSpendableTransactionsInWallet(WalletName).First().Transaction.BlockHeight);

                // Setup cold staking from the hot wallet.
                Money       amountToSend2 = receiveTotal - network.Consensus.ProofOfWorkReward;
                Transaction transaction2  = hotWalletManager.GetColdStakingSetupTransaction(stratisHotStake.FullNode.WalletTransactionHandler(),
                                                                                            coldWalletAddress.Address, hotWalletAddress.Address, WalletName, Account, Password, amountToSend2, new Money(0.02m, MoneyUnit.BTC));

                // Broadcast to the other node
                await stratisHotStake.FullNode.NodeController <WalletController>().SendTransaction(new SendTransactionRequest(transaction2.ToHex()));

                // Wait for the transaction to arrive
                TestBase.WaitLoop(() => coldWalletManager.GetSpendableTransactionsInColdWallet(WalletName, true).Any());

                long receivetotal2 = coldWalletManager.GetSpendableTransactionsInColdWallet(WalletName, true).Sum(s => s.Transaction.Amount);
                Assert.Equal(amountToSend2, (Money)receivetotal2);
                Assert.Null(coldWalletManager.GetSpendableTransactionsInColdWallet(WalletName, true).First().Transaction.BlockHeight);

                // Allow coins to reach maturity
                int stakingMaturity = ((PosConsensusOptions)network.Consensus.Options).GetStakeMinConfirmations(0, network);
                TestHelper.MineBlocks(stratisSender, stakingMaturity, true);

                // Start staking.
                var hotMiningFeature = stratisHotStake.FullNode.NodeFeature <MiningFeature>();
                hotMiningFeature.StartStaking(WalletName, Password);

                TestBase.WaitLoop(() =>
                {
                    var stakingInfo = stratisHotStake.FullNode.NodeService <IPosMinting>().GetGetStakingInfoModel();
                    return(stakingInfo.Staking);
                });

                // Wait for money from staking.
                var cancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(3)).Token;
                TestBase.WaitLoop(() =>
                {
                    // Keep mining to ensure that staking outputs reach maturity.
                    TestHelper.MineBlocks(stratisSender, 1, true);
                    return(coldWalletManager.GetSpendableTransactionsInColdWallet(WalletName, true).Sum(s => s.Transaction.Amount) > receivetotal2);
                }, cancellationToken: cancellationToken);
            }
        }
Beispiel #16
0
        public void CheckSegwitP2PSerialisationForNonWitnessNode()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                // We have to name the networks differently because the NBitcoin network registration won't allow two identical networks to coexist otherwise.
                var network = new StraxRegTest();
                network.SetPrivatePropertyValue("Name", "StraxRegTestWithDeployments");
                Assert.NotNull(network.Consensus.BIP9Deployments[2]);

                var networkNoBIP9 = new StraxRegTest();
                networkNoBIP9.SetPrivatePropertyValue("Name", "StraxRegTestWithoutDeployments");
                Assert.NotNull(networkNoBIP9.Consensus.BIP9Deployments[2]);

                // Remove BIP9 deployments (i.e. segwit).
                for (int i = 0; i < networkNoBIP9.Consensus.BIP9Deployments.Length; i++)
                {
                    networkNoBIP9.Consensus.BIP9Deployments[i] = null;
                }

                // Ensure the workaround had the desired effect.
                Assert.Null(networkNoBIP9.Consensus.BIP9Deployments[2]);
                Assert.NotNull(network.Consensus.BIP9Deployments[2]);

                // Explicitly use new & separate instances of StratisRegTest because we modified the BIP9 deployments on one instance.
                CoreNode node     = builder.CreateStratisPosNode(network).Start();
                CoreNode listener = builder.CreateStratisPosNode(networkNoBIP9).Start();

                // Sanity check.
                Assert.Null(listener.FullNode.Network.Consensus.BIP9Deployments[2]);
                Assert.NotNull(node.FullNode.Network.Consensus.BIP9Deployments[2]);

                // By disabling Segwit on the listener node we also prevent the WitnessCommitments rule from rejecting the mining node's blocks once we modify the listener's peer services.

                IConnectionManager listenerConnMan = listener.FullNode.NodeService <IConnectionManager>();
                listenerConnMan.Parameters.TemplateBehaviors.Add(new TestBehavior());

                // Override the listener node's default settings, so that it will not ask for witness data in P2P messages.
                listenerConnMan.Parameters.Services &= ~NetworkPeerServices.NODE_WITNESS;

                TestHelper.Connect(listener, node);

                // Mine a Segwit block on the first node. It should have commitment data as its settings have not been modified.
                var            script     = new Key().PubKey.WitHash.ScriptPubKey;
                var            miner      = node.FullNode.NodeService <IPowMining>() as PowMining;
                List <uint256> res        = miner.GenerateBlocks(new ReserveScript(script), 1, int.MaxValue);
                Block          block      = node.FullNode.ChainIndexer.GetHeader(res.First()).Block;
                Script         commitment = WitnessCommitmentsRule.GetWitnessCommitment(node.FullNode.Network, block);
                Assert.NotNull(commitment);

                // The listener should sync the mined block without validation failures.
                var cancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token;
                TestBase.WaitLoop(() => listener.CreateRPCClient().GetBlockCount() >= 1, cancellationToken: cancellationToken);

                // We need to capture a message on the non-witness-enabled destination node and see that it contains a block serialised without witness data.
                INetworkPeer connectedPeer = listenerConnMan.ConnectedPeers.FindByEndpoint(node.Endpoint);
                TestBehavior testBehavior  = connectedPeer.Behavior <TestBehavior>();

                var blockMessages = testBehavior.receivedMessageTracker["block"];
                var blockReceived = blockMessages.First();

                var receivedBlock = blockReceived.Message.Payload as BlockPayload;
                var parsedBlock   = receivedBlock.Obj;

                // The block mined on the mining node (witness) should be bigger than the one received by the listener (no witness).
                Assert.True(block.GetSerializedSize() > parsedBlock.GetSerializedSize());

                // Reserialise the received block without witness data (this should have no effect on its size).
                var nonWitnessBlock = parsedBlock.WithOptions(listener.FullNode.Network.Consensus.ConsensusFactory, TransactionOptions.None);

                // We received a block without witness data in the first place.
                Assert.True(parsedBlock.GetSerializedSize() == nonWitnessBlock.GetSerializedSize());
            }
        }