diff --git a/src/dandelion.cpp b/src/dandelion.cpp index 99f8ddc561..ea573ce907 100644 --- a/src/dandelion.cpp +++ b/src/dandelion.cpp @@ -65,28 +65,38 @@ bool CConnman::insertDandelionEmbargo(const uint256& hash, std::chrono::microsec bool CConnman::isTxDandelionEmbargoed(const uint256& hash) const { - auto pair = mDandelionEmbargo.find(hash); - if (pair != mDandelionEmbargo.end()) { - return true; - } else { + auto it = mDandelionEmbargo.find(hash); + if (it == mDandelionEmbargo.end()) { return false; } + // Compare current time with stored embargo time + auto now = GetTime(); + if (now < it->second) { + // Embargo not yet expired + return true; + } + // Otherwise, embargo expired — best practice is to remove it here or in CheckDandelionEmbargoes() + // We'll just return false, so that net_processing can proceed and eventually remove it. + return false; } + bool CConnman::removeDandelionEmbargo(const uint256& hash) { bool removed = false; - for (auto iter = mDandelionEmbargo.begin(); iter != mDandelionEmbargo.end();) { + for (auto iter = mDandelionEmbargo.begin(); iter != mDandelionEmbargo.end(); ) + { if (iter->first == hash) { iter = mDandelionEmbargo.erase(iter); removed = true; } else { - iter++; + ++iter; } } return removed; } + CNode* CConnman::SelectFromDandelionDestinations() const { std::map mDandelionDestinationCounts; diff --git a/src/net.h b/src/net.h index b9ceeef38f..d71c399e1f 100644 --- a/src/net.h +++ b/src/net.h @@ -80,7 +80,7 @@ static const int64_t DEFAULT_PEER_CONNECT_TIMEOUT = 60; /** Number of file descriptors required for message capture **/ static const int NUM_FDS_MESSAGE_CAPTURE = 1; /** The default setting for dandelion transactions */ -static const bool DEFAULT_DANDELION = false; +static const bool DEFAULT_DANDELION = true; static const bool DEFAULT_FORCEDNSSEED = false; static const bool DEFAULT_DNSSEED = true; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index b16f52e1ac..651bd3e739 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1967,19 +1967,29 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic bool push = false; // handle dandelion messages - if (!push && inv.IsDandelionMsg()) { + if (inv.IsDandelionMsg()) { int nSendFlags = (inv.type == MSG_DANDELION_TX ? SERIALIZE_TRANSACTION_NO_WITNESS : 0); + // Possibly find the tx in the stempool auto txinfo = m_stempool.info(inv.hash); - LOCK(pfrom.m_tx_relay->cs_tx_inventory); - if (txinfo.tx && !m_connman.isDandelionInbound(&pfrom) && pfrom.m_tx_relay->setDandelionInventoryKnown.count(inv.hash)!=0) { + + // Before deciding to send the transaction, check the embargo: + if (m_connman.isTxDandelionEmbargoed(inv.hash)) { + // Embargo is in effect => respond with NOTFOUND + vNotFound.push_back(inv); + continue; + } + + // If not embargoed, proceed with normal "send the tx" if we actually have it + if (txinfo.tx && pfrom.m_tx_relay->setDandelionInventoryKnown.count(inv.hash) != 0) { m_connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::DANDELIONTX, *txinfo.tx)); - } else if (inv.hash == DANDELION_DISCOVERYHASH) { - LogPrint(BCLog::DANDELION, "Peer %d supports Dandelion\n", pfrom.GetId()); - pfrom.fSupportsDandelion = true; + } else { + // If we do not have it, or it's not known, respond with NOTFOUND + vNotFound.push_back(inv); } - push = true; + continue; } + // handle normal messages if (!push && inv.IsGenTxMsg()) { CTransactionRef tx = FindTxForGetData(pfrom, ToGenTxid(inv), mempool_req, now); diff --git a/test/functional/p2p_dandelion.py b/test/functional/p2p_dandelion.py index a5a2b86700..7da2f94e15 100755 --- a/test/functional/p2p_dandelion.py +++ b/test/functional/p2p_dandelion.py @@ -28,7 +28,7 @@ from test_framework.p2p import P2PInterface from test_framework.test_framework import DigiByteTestFramework -from test_framework.blocktools import COINBASE_MATURITY +from test_framework.blocktools import COINBASE_MATURITY_2 from test_framework.messages import ( CTransaction, tx_from_hex, @@ -84,7 +84,7 @@ def run_test(self): self.generatetoaddress(node, 1, w0.getnewaddress(), sync_fun=self.no_op) # Generate funds for node0 - self.generate(node0, COINBASE_MATURITY + 1) + self.generate(node0, COINBASE_MATURITY_2 + 1) # Tests 1,2,3 # There is a low probability that one of these tests will fail even if