Page MenuHomePhabricator

D9024.diff
No OneTemporary

D9024.diff

diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -523,6 +523,9 @@
"unconfirmed transactions spending outputs from this transaction",
{RPCResult{RPCResult::Type::STR_HEX, "transactionid",
"child transaction id"}}},
+ RPCResult{RPCResult::Type::BOOL, "unbroadcast",
+ "Whether this transaction is currently unbroadcast (initial "
+ "broadcast not yet confirmed)"},
};
}
@@ -572,6 +575,7 @@
}
info.pushKV("spentby", spent);
+ info.pushKV("unbroadcast", pool.IsUnbroadcastTx(tx.GetId()));
}
UniValue MempoolToJSON(const CTxMemPool &pool, bool verbose) {
@@ -1725,7 +1729,7 @@
ValueFromAmount(std::max(pool.GetMinFee(maxmempool), ::minRelayTxFee)
.GetFeePerK()));
ret.pushKV("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
-
+ ret.pushKV("unbroadcastcount", uint64_t{pool.GetUnbroadcastTxs().size()});
return ret;
}
@@ -1754,6 +1758,9 @@
"minrelaytxfee and minimum mempool fee"},
{RPCResult::Type::STR_AMOUNT, "minrelaytxfee",
"Current minimum relay fee for transactions"},
+ {RPCResult::Type::NUM, "unbroadcastcount",
+ "Current number of transactions that haven't passed initial "
+ "broadcast yet"},
}},
RPCExamples{HelpExampleCli("getmempoolinfo", "") +
HelpExampleRpc("getmempoolinfo", "")},
diff --git a/src/txmempool.h b/src/txmempool.h
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -798,6 +798,12 @@
return m_unbroadcast_txids;
}
+ // Returns if a txid is in the unbroadcast set
+ bool IsUnbroadcastTx(const TxId &txid) const {
+ LOCK(cs);
+ return (m_unbroadcast_txids.count(txid) != 0);
+ }
+
private:
/**
* UpdateForDescendants is used by UpdateTransactionsFromBlock to update the
diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py
--- a/test/functional/mempool_packages.py
+++ b/test/functional/mempool_packages.py
@@ -7,6 +7,7 @@
from decimal import Decimal
from test_framework.messages import COIN
+from test_framework.mininode import P2PTxInvStore
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -52,6 +53,8 @@
def run_test(self):
# Mine some blocks and have them mature.
+ # keep track of invs
+ self.nodes[0].add_p2p_connection(P2PTxInvStore())
self.nodes[0].generate(101)
utxo = self.nodes[0].listunspent(10)
txid = utxo[0]['txid']
@@ -67,6 +70,12 @@
value = sent_value
chain.append(txid)
+ # Wait until mempool transactions have passed initial broadcast
+ # (sent inv and received getdata)
+ # Otherwise, getrawmempool may be inconsistent with getmempoolentry if
+ # unbroadcast changes in between
+ self.nodes[0].p2p.wait_for_broadcast(chain)
+
# Check mempool has MAX_ANCESTORS transactions in it, and descendant and ancestor
# count and fees should look correct
mempool = self.nodes[0].getrawmempool(True)
@@ -226,6 +235,11 @@
for tx in chain[:MAX_ANCESTORS_CUSTOM]:
assert tx in mempool1
# TODO: more detailed check of node1's mempool (fees etc.)
+ # check transaction unbroadcast info (should be false if in both
+ # mempools)
+ mempool = self.nodes[0].getrawmempool(True)
+ for tx in mempool:
+ assert_equal(mempool[tx]['unbroadcast'], False)
# TODO: test ancestor size limits
diff --git a/test/functional/mempool_unbroadcast.py b/test/functional/mempool_unbroadcast.py
--- a/test/functional/mempool_unbroadcast.py
+++ b/test/functional/mempool_unbroadcast.py
@@ -55,6 +55,13 @@
txFS = node.signrawtransactionwithwallet(txF["hex"])
rpc_tx_hsh = node.sendrawtransaction(txFS["hex"])
+ # check transactions are in unbroadcast using rpc
+ mempoolinfo = self.nodes[0].getmempoolinfo()
+ assert_equal(mempoolinfo['unbroadcastcount'], 2)
+ mempool = self.nodes[0].getrawmempool(True)
+ for tx in mempool:
+ assert_equal(mempool[tx]['unbroadcast'], True)
+
# check that second node doesn't have these two txns
mempool = self.nodes[1].getrawmempool()
assert rpc_tx_hsh not in mempool
@@ -74,6 +81,11 @@
assert rpc_tx_hsh in mempool
assert wallet_tx_hsh in mempool
+ # check that transactions are no longer in first node's unbroadcast set
+ mempool = self.nodes[0].getrawmempool(True)
+ for tx in mempool:
+ assert_equal(mempool[tx]['unbroadcast'], False)
+
self.log.info(
"Add another connection & ensure transactions aren't broadcast again")
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -754,6 +754,8 @@
self.tx_invs_received = defaultdict(int)
def on_inv(self, message):
+ # Send getdata in response.
+ super().on_inv(message)
# Store how many times invs have been received for each tx.
for i in message.inv:
if i.type == MSG_TX:
@@ -763,3 +765,13 @@
def get_invs(self):
with mininode_lock:
return list(self.tx_invs_received.keys())
+
+ def wait_for_broadcast(self, txns, timeout=60):
+ """Waits for the txns (list of txids) to complete initial broadcast.
+ The mempool should mark unbroadcast=False for these transactions.
+ """
+ # Wait until invs have been received (and getdatas sent) for each txid.
+ self.wait_until(lambda: set(self.get_invs()) == set(
+ [int(tx, 16) for tx in txns]), timeout)
+ # Flush messages and wait for the getdatas to be processed
+ self.sync_with_ping()

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 1, 11:38 (1 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187647
Default Alt Text
D9024.diff (6 KB)

Event Timeline