mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-24 18:23:26 -03:00
Merge #19569: Enable fetching of orphan parents from wtxid peers
10b7a6d532
refactor: make txmempool interface use GenTxid (Pieter Wuille)5c124e1740
refactor: make FindTxForGetData use GenTxid (Pieter Wuille)a2bfac8935
refactor: use GenTxid in tx request functions (Pieter Wuille)e65d115b72
test: request parents of orphan from wtxid relay peer (Anthony Towns)900d7f6c07
p2p: enable fetching of orphans from wtxid peers (Pieter Wuille)9efd86a908
refactor: add GenTxid (=txid or wtxid) type and use it for tx request logic (Pieter Wuille)d362f19355
doc: list support for BIP 339 in doc/bips.md (Pieter Wuille) Pull request description: This is based on https://github.com/bitcoin/bitcoin/pull/18044#discussion_r450687076. A new type `GenTxid` is added to protocol.h, which represents a tagged txid-or-wtxid. The tx request logic is updated to use these instead of uint256s, permitting per-announcement distinguishing of txid/wtxid (instead of assuming that everything we want to request from a wtxid peer is wtx). Then the restriction of orphan-parent requesting to non-wtxid peers is lifted. Also document BIP339 in doc/bips.md. ACKs for top commit: jnewbery: Code review ACK10b7a6d532
jonatack: ACK10b7a6d532
ajtowns: ACK10b7a6d532
-- code review. Using gtxid to replace the is_txid_or_wtxid flag for the mempool functions is nice. naumenkogs: utACK10b7a6d
Tree-SHA512: d518d13ffd71f8d2b3c175dc905362a7259689e6022a97a0b4f14f1f9fdd87475cf5af70cb12338d1e5d31b52c12e4faaea436114056a2ae9669cb506240758b
This commit is contained in:
commit
f7c73b03d9
8 changed files with 96 additions and 63 deletions
|
@ -1,4 +1,4 @@
|
|||
BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.19.0**):
|
||||
BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.21.0**):
|
||||
|
||||
* [`BIP 9`](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki): The changes allowing multiple soft-forks to be deployed in parallel have been implemented since **v0.12.1** ([PR #7575](https://github.com/bitcoin/bitcoin/pull/7575))
|
||||
* [`BIP 11`](https://github.com/bitcoin/bips/blob/master/bip-0011.mediawiki): Multisig outputs are standard since **v0.6.0** ([PR #669](https://github.com/bitcoin/bitcoin/pull/669)).
|
||||
|
@ -42,3 +42,4 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.19.0**):
|
|||
* [`BIP 173`](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki): Bech32 addresses for native Segregated Witness outputs are supported as of **v0.16.0** ([PR 11167](https://github.com/bitcoin/bitcoin/pull/11167)). Bech32 addresses are generated by default as of **v0.20.0** ([PR 16884](https://github.com/bitcoin/bitcoin/pull/16884)).
|
||||
* [`BIP 174`](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki): RPCs to operate on Partially Signed Bitcoin Transactions (PSBT) are present as of **v0.17.0** ([PR 13557](https://github.com/bitcoin/bitcoin/pull/13557)).
|
||||
* [`BIP 176`](https://github.com/bitcoin/bips/blob/master/bip-0176.mediawiki): Bits Denomination [QT only] is supported as of **v0.16.0** ([PR 12035](https://github.com/bitcoin/bitcoin/pull/12035)).
|
||||
* [`BIP 339`](https://github.com/bitcoin/bips/blob/master/bip-0339.mediawiki): Relay of transactions by wtxid is supported as of **v0.21.0** ([PR 18044](https://github.com/bitcoin/bitcoin/pull/18044)).
|
||||
|
|
|
@ -236,7 +236,7 @@ namespace {
|
|||
/** When our tip was last updated. */
|
||||
std::atomic<int64_t> g_last_tip_update(0);
|
||||
|
||||
/** Relay map */
|
||||
/** Relay map (txid or wtxid -> CTransactionRef) */
|
||||
typedef std::map<uint256, CTransactionRef> MapRelay;
|
||||
MapRelay mapRelay GUARDED_BY(cs_main);
|
||||
/** Expiration-time ordered list of (expire time, relay map entry) pairs. */
|
||||
|
@ -398,7 +398,7 @@ struct CNodeState {
|
|||
/* Track when to attempt download of announced transactions (process
|
||||
* time in micros -> txid)
|
||||
*/
|
||||
std::multimap<std::chrono::microseconds, uint256> m_tx_process_time;
|
||||
std::multimap<std::chrono::microseconds, GenTxid> m_tx_process_time;
|
||||
|
||||
//! Store all the transactions a peer has recently announced
|
||||
std::set<uint256> m_tx_announced;
|
||||
|
@ -751,34 +751,34 @@ static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vec
|
|||
}
|
||||
}
|
||||
|
||||
void EraseTxRequest(const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
void EraseTxRequest(const GenTxid& gtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
g_already_asked_for.erase(txid);
|
||||
g_already_asked_for.erase(gtxid.GetHash());
|
||||
}
|
||||
|
||||
std::chrono::microseconds GetTxRequestTime(const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
std::chrono::microseconds GetTxRequestTime(const GenTxid& gtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
auto it = g_already_asked_for.find(txid);
|
||||
auto it = g_already_asked_for.find(gtxid.GetHash());
|
||||
if (it != g_already_asked_for.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void UpdateTxRequestTime(const uint256& txid, std::chrono::microseconds request_time) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
void UpdateTxRequestTime(const GenTxid& gtxid, std::chrono::microseconds request_time) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
auto it = g_already_asked_for.find(txid);
|
||||
auto it = g_already_asked_for.find(gtxid.GetHash());
|
||||
if (it == g_already_asked_for.end()) {
|
||||
g_already_asked_for.insert(std::make_pair(txid, request_time));
|
||||
g_already_asked_for.insert(std::make_pair(gtxid.GetHash(), request_time));
|
||||
} else {
|
||||
g_already_asked_for.update(it, request_time);
|
||||
}
|
||||
}
|
||||
|
||||
std::chrono::microseconds CalculateTxGetDataTime(const uint256& txid, std::chrono::microseconds current_time, bool use_inbound_delay, bool use_txid_delay) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
std::chrono::microseconds CalculateTxGetDataTime(const GenTxid& gtxid, std::chrono::microseconds current_time, bool use_inbound_delay, bool use_txid_delay) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
std::chrono::microseconds process_time;
|
||||
const auto last_request_time = GetTxRequestTime(txid);
|
||||
const auto last_request_time = GetTxRequestTime(gtxid);
|
||||
// First time requesting this tx
|
||||
if (last_request_time.count() == 0) {
|
||||
process_time = current_time;
|
||||
|
@ -797,23 +797,23 @@ std::chrono::microseconds CalculateTxGetDataTime(const uint256& txid, std::chron
|
|||
return process_time;
|
||||
}
|
||||
|
||||
void RequestTx(CNodeState* state, const uint256& txid, std::chrono::microseconds current_time) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
void RequestTx(CNodeState* state, const GenTxid& gtxid, std::chrono::microseconds current_time) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
CNodeState::TxDownloadState& peer_download_state = state->m_tx_download;
|
||||
if (peer_download_state.m_tx_announced.size() >= MAX_PEER_TX_ANNOUNCEMENTS ||
|
||||
peer_download_state.m_tx_process_time.size() >= MAX_PEER_TX_ANNOUNCEMENTS ||
|
||||
peer_download_state.m_tx_announced.count(txid)) {
|
||||
peer_download_state.m_tx_announced.count(gtxid.GetHash())) {
|
||||
// Too many queued announcements from this peer, or we already have
|
||||
// this announcement
|
||||
return;
|
||||
}
|
||||
peer_download_state.m_tx_announced.insert(txid);
|
||||
peer_download_state.m_tx_announced.insert(gtxid.GetHash());
|
||||
|
||||
// Calculate the time to try requesting this transaction. Use
|
||||
// fPreferredDownload as a proxy for outbound peers.
|
||||
const auto process_time = CalculateTxGetDataTime(txid, current_time, !state->fPreferredDownload, !state->m_wtxid_relay && g_wtxid_relay_peers > 0);
|
||||
const auto process_time = CalculateTxGetDataTime(gtxid, current_time, !state->fPreferredDownload, !state->m_wtxid_relay && g_wtxid_relay_peers > 0);
|
||||
|
||||
peer_download_state.m_tx_process_time.emplace(process_time, txid);
|
||||
peer_download_state.m_tx_process_time.emplace(process_time, gtxid);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -1453,7 +1453,7 @@ bool static AlreadyHave(const CInv& inv, const CTxMemPool& mempool) EXCLUSIVE_LO
|
|||
if (g_recent_confirmed_transactions->contains(inv.hash)) return true;
|
||||
}
|
||||
|
||||
return recentRejects->contains(inv.hash) || mempool.exists(inv.hash, inv.IsMsgWtx());
|
||||
return recentRejects->contains(inv.hash) || mempool.exists(ToGenTxid(inv));
|
||||
}
|
||||
case MSG_BLOCK:
|
||||
case MSG_WITNESS_BLOCK:
|
||||
|
@ -1671,9 +1671,9 @@ void static ProcessGetBlockData(CNode& pfrom, const CChainParams& chainparams, c
|
|||
}
|
||||
|
||||
//! Determine whether or not a peer can request a transaction, and return it (or nullptr if not found or not allowed).
|
||||
CTransactionRef static FindTxForGetData(const CNode& peer, const uint256& txid_or_wtxid, bool use_wtxid, const std::chrono::seconds mempool_req, const std::chrono::seconds now) LOCKS_EXCLUDED(cs_main)
|
||||
CTransactionRef static FindTxForGetData(const CNode& peer, const GenTxid& gtxid, const std::chrono::seconds mempool_req, const std::chrono::seconds now) LOCKS_EXCLUDED(cs_main)
|
||||
{
|
||||
auto txinfo = mempool.info(txid_or_wtxid, use_wtxid);
|
||||
auto txinfo = mempool.info(gtxid);
|
||||
if (txinfo.tx) {
|
||||
// If a TX could have been INVed in reply to a MEMPOOL request,
|
||||
// or is older than UNCONDITIONAL_RELAY_DELAY, permit the request
|
||||
|
@ -1686,11 +1686,11 @@ CTransactionRef static FindTxForGetData(const CNode& peer, const uint256& txid_o
|
|||
{
|
||||
LOCK(cs_main);
|
||||
// Otherwise, the transaction must have been announced recently.
|
||||
if (State(peer.GetId())->m_recently_announced_invs.contains(txid_or_wtxid)) {
|
||||
if (State(peer.GetId())->m_recently_announced_invs.contains(gtxid.GetHash())) {
|
||||
// If it was, it can be relayed from either the mempool...
|
||||
if (txinfo.tx) return std::move(txinfo.tx);
|
||||
// ... or the relay pool.
|
||||
auto mi = mapRelay.find(txid_or_wtxid);
|
||||
auto mi = mapRelay.find(gtxid.GetHash());
|
||||
if (mi != mapRelay.end()) return mi->second;
|
||||
}
|
||||
}
|
||||
|
@ -1727,7 +1727,7 @@ void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnm
|
|||
continue;
|
||||
}
|
||||
|
||||
CTransactionRef tx = FindTxForGetData(pfrom, inv.hash, inv.IsMsgWtx(), mempool_req, now);
|
||||
CTransactionRef tx = FindTxForGetData(pfrom, ToGenTxid(inv), mempool_req, now);
|
||||
if (tx) {
|
||||
// WTX and WITNESS_TX imply we serialize with witness
|
||||
int nSendFlags = (inv.IsMsgTx() ? SERIALIZE_TRANSACTION_NO_WITNESS : 0);
|
||||
|
@ -2647,7 +2647,9 @@ void ProcessMessage(
|
|||
if (interruptMsgProc)
|
||||
return;
|
||||
|
||||
// ignore INVs that don't match wtxidrelay setting
|
||||
// Ignore INVs that don't match wtxidrelay setting.
|
||||
// Note that orphan parent fetching always uses MSG_TX GETDATAs regardless of the wtxidrelay setting.
|
||||
// This is fine as no INV messages are involved in that process.
|
||||
if (State(pfrom.GetId())->m_wtxid_relay) {
|
||||
if (inv.IsMsgTx()) continue;
|
||||
} else {
|
||||
|
@ -2678,7 +2680,7 @@ void ProcessMessage(
|
|||
pfrom.fDisconnect = true;
|
||||
return;
|
||||
} else if (!fAlreadyHave && !chainman.ActiveChainstate().IsInitialBlockDownload()) {
|
||||
RequestTx(State(pfrom.GetId()), inv.hash, current_time);
|
||||
RequestTx(State(pfrom.GetId()), ToGenTxid(inv), current_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2931,9 +2933,11 @@ void ProcessMessage(
|
|||
|
||||
TxValidationState state;
|
||||
|
||||
nodestate->m_tx_download.m_tx_announced.erase(hash);
|
||||
nodestate->m_tx_download.m_tx_in_flight.erase(hash);
|
||||
EraseTxRequest(hash);
|
||||
for (const GenTxid& gtxid : {GenTxid(false, txid), GenTxid(true, wtxid)}) {
|
||||
nodestate->m_tx_download.m_tx_announced.erase(gtxid.GetHash());
|
||||
nodestate->m_tx_download.m_tx_in_flight.erase(gtxid.GetHash());
|
||||
EraseTxRequest(gtxid);
|
||||
}
|
||||
|
||||
std::list<CTransactionRef> lRemovedTxn;
|
||||
|
||||
|
@ -2985,17 +2989,15 @@ void ProcessMessage(
|
|||
uint32_t nFetchFlags = GetFetchFlags(pfrom);
|
||||
const auto current_time = GetTime<std::chrono::microseconds>();
|
||||
|
||||
if (!State(pfrom.GetId())->m_wtxid_relay) {
|
||||
for (const CTxIn& txin : tx.vin) {
|
||||
// Here, we only have the txid (and not wtxid) of the
|
||||
// inputs, so we only request parents from
|
||||
// non-wtxid-relay peers.
|
||||
// Eventually we should replace this with an improved
|
||||
// protocol for getting all unconfirmed parents.
|
||||
CInv _inv(MSG_TX | nFetchFlags, txin.prevout.hash);
|
||||
pfrom.AddKnownTx(txin.prevout.hash);
|
||||
if (!AlreadyHave(_inv, mempool)) RequestTx(State(pfrom.GetId()), _inv.hash, current_time);
|
||||
}
|
||||
for (const CTxIn& txin : tx.vin) {
|
||||
// Here, we only have the txid (and not wtxid) of the
|
||||
// inputs, so we only request in txid mode, even for
|
||||
// wtxidrelay peers.
|
||||
// Eventually we should replace this with an improved
|
||||
// protocol for getting all unconfirmed parents.
|
||||
CInv _inv(MSG_TX | nFetchFlags, txin.prevout.hash);
|
||||
pfrom.AddKnownTx(txin.prevout.hash);
|
||||
if (!AlreadyHave(_inv, mempool)) RequestTx(State(pfrom.GetId()), ToGenTxid(_inv), current_time);
|
||||
}
|
||||
AddOrphanTx(ptx, pfrom.GetId());
|
||||
|
||||
|
@ -4356,6 +4358,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
|||
std::set<uint256>::iterator it = vInvTx.back();
|
||||
vInvTx.pop_back();
|
||||
uint256 hash = *it;
|
||||
CInv inv(state.m_wtxid_relay ? MSG_WTX : MSG_TX, hash);
|
||||
// Remove it from the to-be-sent set
|
||||
pto->m_tx_relay->setInventoryTxToSend.erase(it);
|
||||
// Check if not in the filter already
|
||||
|
@ -4363,7 +4366,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
|||
continue;
|
||||
}
|
||||
// Not in the mempool anymore? don't bother sending it.
|
||||
auto txinfo = m_mempool.info(hash, state.m_wtxid_relay);
|
||||
auto txinfo = m_mempool.info(ToGenTxid(inv));
|
||||
if (!txinfo.tx) {
|
||||
continue;
|
||||
}
|
||||
|
@ -4376,7 +4379,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
|||
if (pto->m_tx_relay->pfilter && !pto->m_tx_relay->pfilter->IsRelevantAndUpdate(*txinfo.tx)) continue;
|
||||
// Send
|
||||
State(pto->GetId())->m_recently_announced_invs.insert(hash);
|
||||
vInv.push_back(CInv(state.m_wtxid_relay ? MSG_WTX : MSG_TX, hash));
|
||||
vInv.push_back(inv);
|
||||
nRelayedTransactions++;
|
||||
{
|
||||
// Expire old relay messages
|
||||
|
@ -4529,15 +4532,15 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
|||
|
||||
auto& tx_process_time = state.m_tx_download.m_tx_process_time;
|
||||
while (!tx_process_time.empty() && tx_process_time.begin()->first <= current_time && state.m_tx_download.m_tx_in_flight.size() < MAX_PEER_TX_IN_FLIGHT) {
|
||||
const uint256 txid = tx_process_time.begin()->second;
|
||||
const GenTxid gtxid = tx_process_time.begin()->second;
|
||||
// Erase this entry from tx_process_time (it may be added back for
|
||||
// processing at a later time, see below)
|
||||
tx_process_time.erase(tx_process_time.begin());
|
||||
CInv inv(state.m_wtxid_relay ? MSG_WTX : (MSG_TX | GetFetchFlags(*pto)), txid);
|
||||
CInv inv(gtxid.IsWtxid() ? MSG_WTX : (MSG_TX | GetFetchFlags(*pto)), gtxid.GetHash());
|
||||
if (!AlreadyHave(inv, m_mempool)) {
|
||||
// If this transaction was last requested more than 1 minute ago,
|
||||
// then request.
|
||||
const auto last_request_time = GetTxRequestTime(inv.hash);
|
||||
const auto last_request_time = GetTxRequestTime(gtxid);
|
||||
if (last_request_time <= current_time - GETDATA_TX_INTERVAL) {
|
||||
LogPrint(BCLog::NET, "Requesting %s peer=%d\n", inv.ToString(), pto->GetId());
|
||||
vGetData.push_back(inv);
|
||||
|
@ -4545,8 +4548,8 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
|||
connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
|
||||
vGetData.clear();
|
||||
}
|
||||
UpdateTxRequestTime(inv.hash, current_time);
|
||||
state.m_tx_download.m_tx_in_flight.emplace(inv.hash, current_time);
|
||||
UpdateTxRequestTime(gtxid, current_time);
|
||||
state.m_tx_download.m_tx_in_flight.emplace(gtxid.GetHash(), current_time);
|
||||
} else {
|
||||
// This transaction is in flight from someone else; queue
|
||||
// up processing to happen after the download times out
|
||||
|
@ -4560,13 +4563,13 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
|||
// would open us up to an attacker using inbound
|
||||
// wtxid-relay to prevent us from requesting transactions
|
||||
// from outbound txid-relay peers).
|
||||
const auto next_process_time = CalculateTxGetDataTime(txid, current_time, !state.fPreferredDownload, false);
|
||||
tx_process_time.emplace(next_process_time, txid);
|
||||
const auto next_process_time = CalculateTxGetDataTime(gtxid, current_time, !state.fPreferredDownload, false);
|
||||
tx_process_time.emplace(next_process_time, gtxid);
|
||||
}
|
||||
} else {
|
||||
// We have already seen this transaction, no need to download.
|
||||
state.m_tx_download.m_tx_announced.erase(inv.hash);
|
||||
state.m_tx_download.m_tx_in_flight.erase(inv.hash);
|
||||
state.m_tx_download.m_tx_announced.erase(gtxid.GetHash());
|
||||
state.m_tx_download.m_tx_in_flight.erase(gtxid.GetHash());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include <serialize.h>
|
||||
#include <uint256.h>
|
||||
|
||||
#include <tuple>
|
||||
|
||||
static const int SERIALIZE_TRANSACTION_NO_WITNESS = 0x40000000;
|
||||
|
||||
/** An outpoint - a combination of a transaction hash and an index n into its vout */
|
||||
|
@ -388,4 +390,17 @@ typedef std::shared_ptr<const CTransaction> CTransactionRef;
|
|||
static inline CTransactionRef MakeTransactionRef() { return std::make_shared<const CTransaction>(); }
|
||||
template <typename Tx> static inline CTransactionRef MakeTransactionRef(Tx&& txIn) { return std::make_shared<const CTransaction>(std::forward<Tx>(txIn)); }
|
||||
|
||||
/** A generic txid reference (txid or wtxid). */
|
||||
class GenTxid
|
||||
{
|
||||
const bool m_is_wtxid;
|
||||
const uint256 m_hash;
|
||||
public:
|
||||
GenTxid(bool is_wtxid, const uint256& hash) : m_is_wtxid(is_wtxid), m_hash(hash) {}
|
||||
bool IsWtxid() const { return m_is_wtxid; }
|
||||
const uint256& GetHash() const { return m_hash; }
|
||||
friend bool operator==(const GenTxid& a, const GenTxid& b) { return a.m_is_wtxid == b.m_is_wtxid && a.m_hash == b.m_hash; }
|
||||
friend bool operator<(const GenTxid& a, const GenTxid& b) { return std::tie(a.m_is_wtxid, a.m_hash) < std::tie(b.m_is_wtxid, b.m_hash); }
|
||||
};
|
||||
|
||||
#endif // BITCOIN_PRIMITIVES_TRANSACTION_H
|
||||
|
|
|
@ -241,3 +241,9 @@ std::vector<std::string> serviceFlagsToStr(uint64_t flags)
|
|||
|
||||
return str_flags;
|
||||
}
|
||||
|
||||
GenTxid ToGenTxid(const CInv& inv)
|
||||
{
|
||||
assert(inv.IsGenTxMsg());
|
||||
return {inv.IsMsgWtx(), inv.hash};
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define BITCOIN_PROTOCOL_H
|
||||
|
||||
#include <netaddress.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <serialize.h>
|
||||
#include <uint256.h>
|
||||
#include <version.h>
|
||||
|
@ -442,4 +443,7 @@ public:
|
|||
uint256 hash;
|
||||
};
|
||||
|
||||
/** Convert a TX/WITNESS_TX/WTX CInv to a GenTxid. */
|
||||
GenTxid ToGenTxid(const CInv& inv);
|
||||
|
||||
#endif // BITCOIN_PROTOCOL_H
|
||||
|
|
|
@ -811,15 +811,17 @@ CTransactionRef CTxMemPool::get(const uint256& hash) const
|
|||
return i->GetSharedTx();
|
||||
}
|
||||
|
||||
TxMempoolInfo CTxMemPool::info(const uint256& hash, bool wtxid) const
|
||||
TxMempoolInfo CTxMemPool::info(const GenTxid& gtxid) const
|
||||
{
|
||||
LOCK(cs);
|
||||
indexed_transaction_set::const_iterator i = (wtxid ? get_iter_from_wtxid(hash) : mapTx.find(hash));
|
||||
indexed_transaction_set::const_iterator i = (gtxid.IsWtxid() ? get_iter_from_wtxid(gtxid.GetHash()) : mapTx.find(gtxid.GetHash()));
|
||||
if (i == mapTx.end())
|
||||
return TxMempoolInfo();
|
||||
return GetInfo(i);
|
||||
}
|
||||
|
||||
TxMempoolInfo CTxMemPool::info(const uint256& txid) const { return info(GenTxid{false, txid}); }
|
||||
|
||||
void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeDelta)
|
||||
{
|
||||
{
|
||||
|
|
|
@ -716,14 +716,15 @@ public:
|
|||
return totalTxSize;
|
||||
}
|
||||
|
||||
bool exists(const uint256& hash, bool wtxid=false) const
|
||||
bool exists(const GenTxid& gtxid) const
|
||||
{
|
||||
LOCK(cs);
|
||||
if (wtxid) {
|
||||
return (mapTx.get<index_by_wtxid>().count(hash) != 0);
|
||||
if (gtxid.IsWtxid()) {
|
||||
return (mapTx.get<index_by_wtxid>().count(gtxid.GetHash()) != 0);
|
||||
}
|
||||
return (mapTx.count(hash) != 0);
|
||||
return (mapTx.count(gtxid.GetHash()) != 0);
|
||||
}
|
||||
bool exists(const uint256& txid) const { return exists(GenTxid{false, txid}); }
|
||||
|
||||
CTransactionRef get(const uint256& hash) const;
|
||||
txiter get_iter_from_wtxid(const uint256& wtxid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
|
||||
|
@ -731,7 +732,8 @@ public:
|
|||
AssertLockHeld(cs);
|
||||
return mapTx.project<0>(mapTx.get<index_by_wtxid>().find(wtxid));
|
||||
}
|
||||
TxMempoolInfo info(const uint256& hash, bool wtxid=false) const;
|
||||
TxMempoolInfo info(const uint256& hash) const;
|
||||
TxMempoolInfo info(const GenTxid& gtxid) const;
|
||||
std::vector<TxMempoolInfo> infoAll() const;
|
||||
|
||||
size_t DynamicMemoryUsage() const;
|
||||
|
|
|
@ -2133,17 +2133,17 @@ class SegWitTest(BitcoinTestFramework):
|
|||
|
||||
# Send tx2 through; it's an orphan so won't be accepted
|
||||
with mininode_lock:
|
||||
self.tx_node.last_message.pop("getdata", None)
|
||||
test_transaction_acceptance(self.nodes[0], self.tx_node, tx2, with_witness=True, accepted=False)
|
||||
self.wtx_node.last_message.pop("getdata", None)
|
||||
test_transaction_acceptance(self.nodes[0], self.wtx_node, tx2, with_witness=True, accepted=False)
|
||||
|
||||
# Expect a request for parent (tx) due to use of non-WTX peer
|
||||
self.tx_node.wait_for_getdata([tx.sha256], 60)
|
||||
# Expect a request for parent (tx) by txid despite use of WTX peer
|
||||
self.wtx_node.wait_for_getdata([tx.sha256], 60)
|
||||
with mininode_lock:
|
||||
lgd = self.tx_node.lastgetdata[:]
|
||||
lgd = self.wtx_node.lastgetdata[:]
|
||||
assert_equal(lgd, [CInv(MSG_TX|MSG_WITNESS_FLAG, tx.sha256)])
|
||||
|
||||
# Send tx through
|
||||
test_transaction_acceptance(self.nodes[0], self.tx_node, tx, with_witness=False, accepted=True)
|
||||
test_transaction_acceptance(self.nodes[0], self.wtx_node, tx, with_witness=False, accepted=True)
|
||||
|
||||
# Check tx2 is there now
|
||||
assert_equal(tx2.hash in self.nodes[0].getrawmempool(), True)
|
||||
|
|
Loading…
Add table
Reference in a new issue