Skip to content

Dandelion transaction relay (BIP 156) #13947

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from

Conversation

maflcko
Copy link
Member

@maflcko maflcko commented Aug 12, 2018

The implementation of BIP 156 (Dandelion transaction relay) is done in three steps:

Add the protocol messages

  • dandeliontx, which contains a transaction serialized with all witness data
  • dandelionacc, which is always empty and only used to signal dandelion support to other peers

Shuffle dandelion stems

We shuffle a list of all peers that sent us the message that they accept dandelion txs (dandelionacc). This list can be used on demand by nodes that want to forward a dandelion transaction. (Actual receiving of dandelion txs is done in the next step).

Also, we add a command line option -dandelion, which can be used to opt out of all dandelion features.

Keep a cache of recent dandelion transactions

Dandelion transactions are never added to the global tx pool and only forwarded to one peer (the next hop in the stem). To guard against the next peer going offline, we keep a cache of recent dandelion transactions that are not yet fluffed (added to the mempool) or mined. Entries in this cache expire after some random timeout and transition to fluff phase.

@maflcko
Copy link
Member Author

maflcko commented Aug 12, 2018

This is completely untested, so TODO:

  • add tests
  • use dandelion relay for our wallet txs

@@ -755,6 +778,10 @@ class CNode
// Our address, as reported by the peer
CService addrLocal;
mutable CCriticalSection cs_addrLocal;

/** Our current dandelion destination */
CConnman::DandelionPeer* m_dandelion_destination /* GUARDED_BY(CConnman::cs_dandelion_peers) */ {nullptr};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any drawbacks from uncommenting the GUARDED_BY(…) annotation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The drawback was that it didn't compile for me

@maflcko maflcko added the P2P label Aug 12, 2018
@maflcko maflcko added this to the 0.18.0 milestone Aug 12, 2018
src/init.cpp Outdated
@@ -1027,6 +1031,12 @@ bool AppInitParameterInteraction()
LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainparams.GetConsensus().nMinimumChainWork.GetHex());
}

{
const int64_t pct = gArgs.GetArg("-dandelion", DEFAULT_DANDELION_STEM_PERCENTAGE);
if (pct < 0 || 100 < pct) return InitError(_("-dandelion must be 0 or a percentage less than 100"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should -dandelion=100 generate an error message? From the error message it looks like it should, but not from the logic :-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100% is allowed to always extend the stem by one hop. So the interval is [0, 100].

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the error message should be -dandelion must be 0 or a percentage up to 100 or something equivalent?

@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 12, 2018

Note to reviewers: This pull request conflicts with the following ones:

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@@ -33,6 +33,7 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.17.0**):
* [`BIP 145`](https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki): getblocktemplate updates for Segregated Witness as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)).
* [`BIP 147`](https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki): NULLDUMMY softfork as of **v0.13.1** ([PR 8636](https://github.com/bitcoin/bitcoin/pull/8636) and [PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)).
* [`BIP 152`](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki): Compact block transfer and related optimizations are used as of **v0.13.0** ([PR 8068](https://github.com/bitcoin/bitcoin/pull/8068)).
* [`BIP 156`](https://github.com/bitcoin/bips/blob/master/bip-0156.mediawiki): Dandelion transaction relay is supported as of **v0.18.0** ([PR 13947](https://github.com/bitcoin/bitcoin/pull/13947)).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@clodhopp that's because the BIP PR hasn't been merged, you can see it here: bitcoin/bips#703
Once merged, the link should work

@sipa
Copy link
Member

sipa commented Aug 12, 2018

This code doesn't seem to include a "stempool"; how does it deal with dandelion transactions that depend on other dandelion transactions? ATMP will fail for those.

@maflcko
Copy link
Member Author

maflcko commented Aug 12, 2018

This code doesn't seem to include a "stempool"; how does it deal with dandelion transactions that depend on other dandelion transactions? ATMP will fail for those.

Continued here https://botbot.me/freenode/bitcoin-core-dev/2018-08-12/?msg=103212266&page=2
EDIT by ajtowns: http://www.erisian.com.au/bitcoin-core-dev/log-2018-08-12.html#l-190

Copy link
Member

@sdaftuar sdaftuar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just left some initial comments from a quick-read of the code. As discussed on IRC we still need to figure out what the right behavior is for transaction chains and replacement transactions (and combinations of the two), and generally how to prevent DoS attacks during stem routing.

If we use a stempool to address those issues, then I'm not sure I understand how we could share a stempool across multiple inbound peers without leaking dandelion routing information to an adversary (and if we have separate stempools for each inbound peer, then that sounds like a lot of overhead).

if (gArgs.SoftSetBoolArg("-whitelistrelay", false))
LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -whitelistrelay=0\n", __func__);
if (gArgs.SoftSetBoolArg("-dandelion", false)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we use SoftSetBoolArg() like this elsewhere, on arguments that take numeric values? It was not clear to me that this worked until I saw that SoftSetBoolArg converts the false to std::string("0"). (Neat, though.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to not mix up values, this should set 0 instead of false, even if false would be converted automatically to 0.

src/net.h Outdated
@@ -803,7 +847,19 @@ class CNode
nRefCount--;
}

/** If this peer is not yet connected or soon to be disconnected */
bool IsEphermal() const
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: IsEphemeral

else if (strCommand == NetMsgType::TX_DANDELION) {
// Stop processing the transaction early if
// dandelion is disabled and peer is either not whitelisted or whitelistrelay is off
if (!CNode::IsDandelionEnabled()&& (!pfrom->fWhitelisted || !gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some IRC discussion around not extending whitelist-relay behavior further with dandelion processing:
https://botbot.me/freenode/bitcoin-core-dev/2018-08-13/?msg=103271568&page=3

return true;
}

if (pfrom->fWhitelisted && gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment about dropping this behavior for whitelisted peers.

* The dandelion tx message transmits a single transaction.
* @see https://github.com/bitcoin/bips/blob/master/bip-0156.mediawiki
*/
extern const char* TX_DANDELION;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in the past, we've usually bumped the protocol version when introducing new p2p messages so that we only send the new messages (like ACCEPT_DANDELION) to peers that are signaling that they've upgraded. Not sure how important that is...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that we'd never send a TX_DANDELION to a peer that never sent us ACCEPT_DANDELION in the first place. So I don't think this is an issue at all.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps my comment was not placed on the right line of this file; I was thinking of the dandelionacc message. With sendheaders and I think compact blocks, I believe we bumped the protocol version and only tried to send the new p2p messages (even for handshaking/negotiating the protocol to use) to peers with that higher version?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I think it is a lot easier to do this without enforcing a global network version bump.

Note that the dandelionacc message is properly read by all nodes that implement dandelion (regardless of their network protocol version) or choose to ignore that message. And for all other nodes (that are completely unaware of dandelion) they simply treat this as unknown message (once per connection) in their logs. I think this one debug log is not enough reason to go through the hassle of bumping the protocol version.

LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->GetId());

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not a service bit?

CValidationState state;
bool missing_inputs;
if (AcceptToMemoryPool(mempool, state, tx, &missing_inputs, nullptr /* lRemovedTxn */, false /* bypass_limits */, 0 /* nAbsurdFee */, true /* test_accept */)) {
RelayDandelionTransaction(mempool, pfrom, tx, msgMaker, connman);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should queue transactions for relay to a peer, rather than doing a direct send as is done here. Otherwise transaction relay can fill up our send buffers and delay block relay.

Further our current transaction relay system batches transactions for relay and, at each broadcast time, we sort the to-be-relayed transactions for the purposes of prioritising transactions that have fewer ancestors and higher feerate. I think being able to prioritise transactions with higher feerate for relay is probably useful (to prevent low-feerate transactions from harming propagation times of higher feerate transactions).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's also better for privacy against traffic analysis to batch things.

@@ -1908,6 +1967,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
State(pfrom->GetId())->fPreferHeaders = true;
}

else if (strCommand == NetMsgType::ACCEPT_DANDELION) {
pfrom->m_accept_dandelion = true;
return true;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should write something to debug log here.

@maflcko maflcko force-pushed the Mf1804-dandelion branch 3 times, most recently from 2728324 to be9db89 Compare August 14, 2018 23:41
@maflcko maflcko force-pushed the Mf1804-dandelion branch 4 times, most recently from 0526b2d to b508ed1 Compare August 17, 2018 12:46
src/init.cpp Outdated
@@ -399,6 +399,7 @@ void SetupServerArgs()
gArgs.AddArg("-bantime=<n>", strprintf("Number of seconds to keep misbehaving peers from reconnecting (default: %u)", DEFAULT_MISBEHAVING_BANTIME), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-bind=<addr>", "Bind to given address and always listen on it. Use [host]:port notation for IPv6", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-connect=<ip>", "Connect only to the specified node; -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-dandelion", strprintf("Probability to extend the stem in Dandelion transaction relay by one hop (default: %d, 0 to disable dandelion)", DEFAULT_DANDELION_STEM_PERCENTAGE), false, OptionsCategory::CONNECTION);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A simple "probability" should a number between 0 and 1. The variable used as default and the code below suggest a percentage is used instead. I think it would make sense to document it as such as well.

Copy link
Contributor

@practicalswift practicalswift Aug 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about this as well: normally I’d expect a probability parameter to be in the interval [0.0, 1.0]. Are we trying to be consistent with other parameters taking probabilities as [0, 100] here, or what is the rationale? :-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that is the case, it should at least be mentioned in the help line.

Probability in % to extend ..

if (gArgs.SoftSetBoolArg("-whitelistrelay", false))
LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -whitelistrelay=0\n", __func__);
if (gArgs.SoftSetBoolArg("-dandelion", false)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to not mix up values, this should set 0 instead of false, even if false would be converted automatically to 0.

src/net.cpp Outdated
{
from->m_dandelion_destination = nullptr;

if (!CNode::IsDandelionEnabled()) return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check should not be necessary, failing it means there's a bug. I'd suggest either using an assertion or something more severe than this or just removing the check.

@@ -317,6 +327,16 @@ class CConnman
*/
int64_t PoissonNextSendInbound(int64_t now, int average_interval_seconds);

using DandelionPeer = std::pair<CNode*, /* use count */ unsigned>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please elaborate a bit more on the documentation of the integer.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is better to create a struct? This integer will look much better with a name. It is very hard to read all those peer.first and peer.second

/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
static const int PING_INTERVAL = 2 * 60;
/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
static const int TIMEOUT_INTERVAL = 20 * 60;
/** Run the feeler connection loop once every 2 minutes or 120 seconds. **/
static const int FEELER_INTERVAL = 120;
/** Pick new dandelion peers once every 10 minutes or 600 seconds. */
static constexpr int INTERVAL_DANDELION = 600;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The convention seems to be XXX_INTERVAL instead of INTERVAL_XXX.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, why 10 minutes?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevenroose as per the BIP: https://github.com/bitcoin/bips/blob/master/bip-0156.mediawiki#periodic-dandelion-route-shuffling (the value suggested in the BIP is best discussed on the bitcoin-dev mailinglist)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sjors this would do:
/** As per BIP156, pick new dandelion peers once every 10 minutes or 600 seconds. */


/** Default for -dandelion stem percentage */
static constexpr int64_t DEFAULT_DANDELION_STEM_PERCENTAGE = 90;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 90? This is like the most important parameter of the dandelion algorithm, I think it deserves some motivation..

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevenroose the BIP specifies that:

When relaying a Dandelion transaction along a Dandelion route, there is a 10% chance that the Dandelion transaction becomes a typical Bitcoin transaction and is therefore relayed via diffusion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sjors So I'd suggest referring to the BIP in the comment of that variable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I'm trying to say with this comments is that this is supposed to be an implementation of the BIP, so it should refer to the BIP for logic/params etc. It has happened too often that a BIP is just a description of the implementation.

});
}

static void FluffTransaction(CTxMemPool& tx_pool, const CNode* from, const CTransactionRef& ptx, CConnman* connman)
{
LogPrint(BCLog::DANDELION, "fluff\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps mention txid?

static void RelayDandelionTransaction(CTxMemPool& tx_pool, CNode* node_from, const CTransactionRef& ptx, const CNetMsgMaker& msg_maker, CConnman* connman)
{
bool fluff = GetRand(100 * 100) / 100. >= CNode::m_dandelion_stem_pct_threshold;
if (fluff) return FluffTransaction(tx_pool, node_from, ptx, connman);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this check also be made for the wallet's own transactions? Or should a forced non-fluff be done in that case?

}

LogPrint(BCLog::DANDELION, "dandelion relay to peer=%d\n", dest->GetId());
connman->PushMessage(dest, msg_maker.Make(DANDELION_SEND_FLAGS, NetMsgType::TX_DANDELION, *ptx));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong indentation since after return.

* The dandelion tx message transmits a single transaction.
* @see https://github.com/bitcoin/bips/blob/master/bip-0156.mediawiki
*/
extern const char* TX_DANDELION;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not a service bit?

@maflcko maflcko force-pushed the Mf1804-dandelion branch 3 times, most recently from 8252b0e to ce8c6d6 Compare August 21, 2018 14:31
@scravy
Copy link
Contributor

scravy commented Sep 19, 2018

Shouldn't the functional test from the reference implementation (dandelion-org@d043e36#diff-21ab9447686d819eeeb7668ce8011e0d) run more-or-less unchanged on top of this branch?

m_nodes_dandelion.clear();
for (CNode* node : all_nodes) {
// Ignore inbound nodes
if (node->fInbound) continue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why ignore inbound nodes? Does this mean non-listening dandelion nodes send only their own transactions and that the peer who receives such will know with undeniable certainty that the non-listening node initiated the transaction?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inbound nodes are much more likely to be snooping peers.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While that is true, aren't there solutions that do not make dandelion break firewalled nodes' privacy? For example, send only to outgoing peers if you originated the transaction, but send to incoming as well for forwarded txes? Perhaps weigh the outgoing peers more heavily than incoming peers when selecting a random peer to forward to (either by assigning a weight to individual peers based on incoming/outgoing status, or by first randomly selecting the outgoing or incoming pool with a fixed weighting before selecting a peer from whichever pool).

@jb55
Copy link
Contributor

jb55 commented Oct 3, 2018

These commits could be documented more in general, I'm finding it hard to review when there are no descriptions about what is being implemented.

@AM5800
Copy link

AM5800 commented Oct 9, 2018

It has been mentioned several times that common stempool might leak dandelion routing information to an adversary. Can someone help me understand how exactly?

Also, what is the current status of this issue? I would like to offer some help. For example with tests

@scravy
Copy link
Contributor

scravy commented Oct 9, 2018

@jb55 BIP156 should explain a lot of things.

@jb55
Copy link
Contributor

jb55 commented Oct 9, 2018

@scravy I'm more interested in documentation of the implementation itself, how each commit relates to a part of the bip, etc. It's much harder to verify an implementation without that, especially with important privacy/security features. I don't think we should be making it harder on reviewers than it needs to be.

@stevenroose
Copy link
Contributor

@jb55 Totally agree. All the non-trivial pieces of code should explain themselves, refer to the BIP when relevant, etc..

});
}

static void FluffTransaction(CTxMemPool& tx_pool, const CNode* from, const CTransactionRef& ptx, CConnman* connman)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wandering... FluffTransaction is logically equivalent to receiving a transaction, right?
Then shouldn't we also execute all this code on fluff?


if (CNode::IsDandelionEnabled()) {
// Shuffle dandelion destinations
m_thread_shuffle_dandelion = std::thread(&TraceThread<std::function<void()>>, "dandelionshuff", [&] { ThreadShuffleDandelionDestinations(); });
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I tried this PR in action - dandelion was turned off for the first epoch. I believe this happens because we do the very first shuffle when there are no connections. Maybe the first shuffle should be delayed until someone connects?

from->m_cache_expiry.pop();
} while (from->m_cache_expiry.top() < now_millis);

for (auto it = from->m_cache_dandelion.cbegin(); it != from->m_cache_dandelion.cend(); ++it) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An idea: if you define m_cache_expiry as std::map<int64_t, CTransactionRef> - you will get the same 'Constant time lookup' but you won't need to walk the whole cache - expired transactions are already available

// Dandelion relay (at least one hop)
const int64_t now_micros = GetTimeMicros();
const int64_t expiry = now_micros + EXPIRE_DANDELION_CACHE * 1000 * 1000 + PoissonNextSend(now_micros, EXPIRE_DANDELION_CACHE_AVG_ADD);
node_from->m_cache_dandelion.emplace(std::make_pair(ptx->GetWitnessHash(), std::make_pair(ptx, expiry)));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:
node_from->m_cache_dandelion.emplace(ptx->GetWitnessHash(), std::make_pair(ptx, expiry))
does absolutely the same, but shorter.

@maflcko maflcko removed this from the 0.18.0 milestone Dec 3, 2018
@riclas
Copy link

riclas commented Feb 4, 2019

I believe this explanation of the DDoS possibilities on Dandelion by @sdaftuar belongs here:
https://bitcoin.stackexchange.com/questions/81503/what-is-the-tradeoff-between-privacy-and-implementation-complexity-of-dandelion

regarding option b), maybe dynamically adjusting stem % according to fullness of the stempool/cache could be a solution? at worst, we would fluff all the time just like a regular tx spam attack.

@maflcko maflcko closed this Jul 11, 2019
@maflcko maflcko deleted the Mf1804-dandelion branch July 11, 2019 21:12
@maflcko
Copy link
Member Author

maflcko commented Jul 22, 2019

I closed this for now because it is non-trivial to allow for all wallet behavior (e.g. cpfp and rbf) while not opening DOS vectors. I think a simpler first step would be to go for "Dandelion Light" or "Dandelion one-hop".

That approach would not need any DOS protection, since the only sender is our own wallet and the next hop would already fluff the tx (and send it back to us, so that our wallet can know it made it into the mempool eventually)

@ghost ghost mentioned this pull request Oct 20, 2020
barrystyle pushed a commit to barrystyle/digibyte that referenced this pull request Nov 11, 2021
Dandelion transaction relay (BIP156) original source available at
bitcoin/bitcoin#13947. Ported forward from
Bitcoin 0.17 - looks to be written in a much neater manner.

Signed-off-by: barrystyle <baz@tiltpool.com>
barrystyle pushed a commit to barrystyle/digibyte that referenced this pull request Nov 15, 2021
Dandelion transaction relay (BIP156) original source available at
bitcoin/bitcoin#13947. Ported forward from
Bitcoin 0.17 - looks to be written in a much neater manner.

Signed-off-by: barrystyle <baz@tiltpool.com>
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
@fanquake
Copy link
Member

fanquake commented Aug 4, 2022

Removed up for grabs.

static constexpr int DANDELION_SEND_FLAGS{0}; // Always send as witness tx

// Check if the next peer would fluff (assume same probability)
bool force_fluff = GetRand(100 * 100) / 100. >= CNode::m_dandelion_stem_pct_threshold;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doubles the odds of the next node fluffing -- 10% chance that we thought they should fluff, but if we don't think they should fluff, they'll still make their own decision, giving another 9% (=90%*10%) chance that they'll think they should fluff for a total of 19%.

(necroreviewing!)

@bitcoin bitcoin unlocked this conversation Nov 4, 2022
@bitcoin bitcoin locked and limited conversation to collaborators Nov 4, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.