public void Mempool_SendTransactionWithEarlyTimestamp_ShouldRejectByMempool() { var network = KnownNetworks.StratisRegTest; using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisSender = builder.CreateStratisPosNode(network).WithWallet().Start(); int maturity = (int)network.Consensus.CoinbaseMaturity; TestHelper.MineBlocks(stratisSender, maturity + 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); // Use timestamp value that is definitely earlier than the input's timestamp trx.Time = 1; // Sign trx again after mutating timestamp 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("timestamp earlier than input", entry.ErrorMessage); } }
public void Mempool_SendOversizeTransaction_ShouldRejectByMempool() { var network = KnownNetworks.StratisRegTest; using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisSender = builder.CreateStratisPosNode(network).WithWallet().Start(); int maturity = (int)network.Consensus.CoinbaseMaturity; TestHelper.MineBlocks(stratisSender, maturity + 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 Mempool_SendPosTransaction_AheadOfFutureDrift_ShouldRejectByMempool() { var network = KnownNetworks.StratisRegTest; using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisSender = builder.CreateStratisPosNode(network).WithWallet().Start(); int maturity = (int)network.Consensus.CoinbaseMaturity; TestHelper.MineBlocks(stratisSender, maturity + 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); // This should make the mempool reject a POS trx. trx.Time = Utils.DateTimeToUnixTime(Utils.UnixTimeToDateTime(trx.Time).AddMinutes(5)); // Sign trx again after changing the time property. 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("time-too-new", entry.ErrorMessage); } }
public void Mempool_SendTransactionWithLargeOpReturn_ShouldRejectByMempool() { var network = KnownNetworks.StratisRegTest; using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisSender = builder.CreateStratisPosNode(network).WithWallet().Start(); int maturity = (int)network.Consensus.CoinbaseMaturity; TestHelper.MineBlocks(stratisSender, maturity + 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) { int[] data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 void Miner_PosNetwork_CreatePowTransaction_AheadOfFutureDrift_ShouldNotBeIncludedInBlock() { var network = KnownNetworks.StratisRegTest; using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisMiner = builder.CreateStratisPosNode(network).WithWallet().Start(); int maturity = (int)network.Consensus.CoinbaseMaturity; TestHelper.MineBlocks(stratisMiner, maturity + 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 = stratisMiner.FullNode.WalletTransactionHandler().BuildTransaction(context); // This should make the mempool reject a POS trx. if (trx is IPosTransactionWithTime posTrx) { posTrx.Time = Utils.DateTimeToUnixTime(Utils.UnixTimeToDateTime(posTrx.Time).AddMinutes(5)); } // Sign trx again after changing the time property. trx = context.TransactionBuilder.SignTransaction(trx); var broadcaster = stratisMiner.FullNode.NodeService <IBroadcasterManager>(); broadcaster.BroadcastTransactionAsync(trx).GetAwaiter().GetResult(); var entry = broadcaster.GetTransaction(trx.GetHash()); Assert.Equal(TransactionBroadcastState.ReadyToBroadcast, entry.TransactionBroadcastState); Assert.NotNull(stratisMiner.FullNode.MempoolManager().GetTransaction(trx.GetHash()).Result); TestHelper.MineBlocks(stratisMiner, 1); Assert.NotNull(stratisMiner.FullNode.MempoolManager().GetTransaction(trx.GetHash()).Result); } }
public void Mempool_SendPosTransaction_WithFutureLockTime_ShouldBeRejectedByMempool() { // See AcceptToMemoryPool_TxFinalCannotMine_ReturnsFalseAsync for the 'unit test' version var network = KnownNetworks.StratisRegTest; using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisSender = builder.CreateStratisPosNode(network).WithWallet().Start(); int maturity = (int)network.Consensus.CoinbaseMaturity; TestHelper.MineBlocks(stratisSender, maturity + 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.Chain.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 void Mempool_SendPosTransaction_WithElapsedLockTime_ShouldBeAcceptedByMempool() { // See CheckFinalTransaction_WithElapsedLockTime_ReturnsTrueAsync for the 'unit test' version var network = KnownNetworks.StratisRegTest; using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisSender = builder.CreateStratisPosNode(network).WithWallet().Start(); int maturity = (int)network.Consensus.CoinbaseMaturity; TestHelper.MineBlocks(stratisSender, maturity + 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.Chain.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); TestHelper.WaitLoop(() => stratisSender.CreateRPCClient().GetRawMempool().Length == 1); } }
private void SendCoins(CoreNode from, CoreNode to, Money coins, HdAddress toAddress = null) { // Get a receive address. if (toAddress == null) { toAddress = to.FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference(walletName, accountName)); } // Send 10 coins to node. var transaction = from.FullNode.WalletTransactionHandler().BuildTransaction(WalletTests.CreateContext(from.FullNode.Network, new WalletAccountReference(walletName, accountName), password, toAddress.ScriptPubKey, coins, FeeType.Medium, 10)); from.FullNode.NodeController <WalletController>().SendTransaction(new SendTransactionRequest(transaction.ToHex())); TestBase.WaitLoop(() => from.CreateRPCClient().GetRawMempool().Length > 0); // Mine the transaction. TestHelper.MineBlocks(this.miner, 10); TestBase.WaitLoop(() => TestHelper.AreNodesSynced(from, to)); TestBase.WaitLoop(() => to.FullNode.WalletManager().GetSpendableTransactionsInWallet(walletName).Sum(x => x.Transaction.Amount) > 0); }
public void MineBlocksBlockOrphanedAfterReorgTxsReturnedToMempool() { using (NodeBuilder builder = NodeBuilder.Create(this)) { // Setup two synced nodes with some mined blocks. string password = "******"; string name = "mywallet"; string accountName = "account 0"; CoreNode node1 = builder.CreateStratisPowNode(new BitcoinRegTest()).WithWallet().Start(); CoreNode node2 = builder.CreateStratisPowNode(new BitcoinRegTest()).WithWallet().Start(); var mempoolValidationState = new MempoolValidationState(true); int maturity = (int)node1.FullNode.Network.Consensus.CoinbaseMaturity; TestHelper.MineBlocks(node1, maturity + 20); TestHelper.ConnectAndSync(node1, node2); // Nodes disconnect. TestHelper.Disconnect(node1, node2); // Create tx and node 1 has this in mempool. HdAddress receivingAddress = node2.FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference(name, accountName)); Transaction transaction = node1.FullNode.WalletTransactionHandler().BuildTransaction(WalletTests.CreateContext(node1.FullNode.Network, new WalletAccountReference(name, accountName), password, receivingAddress.ScriptPubKey, Money.COIN * 100, FeeType.Medium, 101)); Assert.True(node1.FullNode.MempoolManager().Validator.AcceptToMemoryPool(mempoolValidationState, transaction).Result); Assert.Contains(transaction.GetHash(), node1.FullNode.MempoolManager().GetMempoolAsync().Result); // Node 2 has none in its mempool. TestHelper.WaitLoop(() => node2.FullNode.MempoolManager().MempoolSize().Result == 0); // Node 1 mines new tx into block - removed from mempool. (HdAddress addressUsed, List <uint256> blockHashes) = TestHelper.MineBlocks(node1, 1); uint256 minedBlockHash = blockHashes.Single(); TestHelper.WaitLoop(() => node1.FullNode.MempoolManager().MempoolSize().Result == 0); // Node 2 mines two blocks to have greatest chainwork. TestHelper.MineBlocks(node2, 2); // Sync nodes and reorg occurs. TestHelper.ConnectAndSync(node1, true, node2); // Block mined by Node 1 is orphaned. Assert.Null(node1.FullNode.ChainBehaviorState.ConsensusTip.FindAncestorOrSelf(minedBlockHash)); // Tx is returned to mempool. Assert.Contains(transaction.GetHash(), node1.FullNode.MempoolManager().GetMempoolAsync().Result); // New mined block contains this transaction from the orphaned block. TestHelper.MineBlocks(node1, 1); Assert.Contains(transaction, node1.FullNode.Chain.Tip.Block.Transactions); } }