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)); }
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)); } }
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); } }
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); } }
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); } }
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(); } }
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)); } }
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); } }
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); } }
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)); } }
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); } }
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); }); } }
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); } }
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()); } }