Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13115641
D9024.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Subscribers
None
D9024.diff
View Options
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
Details
Attached
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)
Attached To
D9024: [rpc] add unbroadcast info to mempool entries and getmempoolinfo
Event Timeline
Log In to Comment