Skip to content

Add randomized delay when forwarding txes from i2p/tor -> ipv4/6 - #6354

Merged
Snipa22 merged 1 commit into
monero-project:masterfrom
vtnerd:feature/forward_delay
Aug 9, 2020
Merged

Add randomized delay when forwarding txes from i2p/tor -> ipv4/6#6354
Snipa22 merged 1 commit into
monero-project:masterfrom
vtnerd:feature/forward_delay

Conversation

@vtnerd

@vtnerd vtnerd commented Feb 25, 2020

Copy link
Copy Markdown
Contributor

The last bullet point on the CCS for transaction privacy is a randomized delay before a node takes an incoming transaction from i2p/tor and sends it over ipv4/6. My thought was an attempt to conceal the bandwidth/timing analysis of i2p/tor. If the the i2p/tor hidden service only has one incoming connection, this delay possibly/probably does nothing. But if the hidden service has 2+ incoming connections sending white noise, the transaction could've been received over any of the white noise connections.

This creates another mempool state.

@SarangNoether might be interested.

Comment thread src/blockchain_db/blockchain_db.h Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This drops a mempool meta bit flag that has never been in a release, but has been in master. I realized it was more efficient to use kept_by_block instead. Anyone running from master that has a is_local flag in their pool will see incorrect behavior when running this change. I think its better to clean this up before a release, but ... ?

@moneromooo-monero moneromooo-monero Feb 26, 2020

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Are you saying kept_by_block is new ? It's not. Or are you talking about something else here ? nvm, the relevant part is not what's displayed in this bit of code.

Comment thread src/cryptonote_core/tx_pool.cpp Outdated
Comment thread src/blockchain_db/blockchain_db.h Outdated
@vtnerd
vtnerd force-pushed the feature/forward_delay branch from 788c4d9 to 51adada Compare March 10, 2020 22:46
@vtnerd

vtnerd commented Mar 10, 2020

Copy link
Copy Markdown
Contributor Author

Rebased, and made changes suggested by @xiphon .

Comment thread src/blockchain_db/blockchain_db.cpp Outdated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

tbh, this is really dodgy. Does this really need to be obfuscated like this ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The code could continue using the inefficient bit mechanism, or could "break" the existing txpool between releases (this code breaks the txpool for users running master branch only).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why do we care about efficient bit twiddling when it's about I/O ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Its less wasted space and less CPU cycles to just store/retrieve this value as the enum value.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Well, whatever. If you prefer saving a few cycles hidden next to massive amounts of them for confusing code, fine.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No, my preference was to break the existing txpool (pain should be minimal) to do: m_state = uint8_t(tx_relay);.

I think in the end, I will drop this. This creates a hard dependency on the enum value and DB value. How about something like:

const uin8_t state =
  uint8_t(do_not_relay) +
  uint8_t(kept_by_block) << 1 +
  uint8_t(forward) << 2;

switch (state)
{
  default:
  case 0:
    return relay_method::fluff;
  case 1:
    return relay_method::none;
  case 2:
    return relay_method::block;
  case 4:
    return relay_method::forward:
}

which also handles the incorrect DB state, and maps it to fluff. Or the if-else ladder (which maps the incorrect DB state to some other value - but I doubt that matters anyway).

@moneromooo-monero moneromooo-monero Apr 16, 2020

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I much prefer this since I find it much clearer. It looks equivalent to the even simpler:

if (forward)
  return relay_method::forward;
if (kept_by_block)
  return relay_method::block;
if (do_not_relay)
  return relay_method::none;
return fluff;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Amusingly, it looks close to what you had before. The thing I was finding objectionable was not the set of tests, it was the case on enum+1.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, the original version was iffy because it required knowledge of the enum values to read it correctly. And a change in enum values could break the function. This version is similar looking, but everything is self-contained within the function.

FWIW, I disassembled this version and gcc 9 was able to optimize the function into a single comparison for the "error" case. Otherwise it used adds, shifts and a 64-bit constant to put the enum value in the return register. Roughly half of the instructions could be done in parallel by the CPU backend.

The if-ladder is less x64-64 instructions but 3-total comparison instructions. The compiler can still generate the same ASM with the switch version, but chose one with more math instructions and less comparisons.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

For clarity, I really don't care about a dozen cycles saved for this. What I care about is the complexity of the C code.

@vtnerd
vtnerd force-pushed the feature/forward_delay branch from 51adada to db8606f Compare April 14, 2020 20:41
@vtnerd

vtnerd commented Apr 14, 2020

Copy link
Copy Markdown
Contributor Author

Rebased and reverted to a bitfield. Reviewers should inspect new implementation of get_relay_method().

@dEBRUYNE-1

Copy link
Copy Markdown
Contributor

@vtnerd - Needs a rebase.

@vtnerd
vtnerd force-pushed the feature/forward_delay branch 2 times, most recently from b3df447 to 20d26bb Compare April 22, 2020 00:18

@vtnerd vtnerd left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Rebased. This was not trivial after the Dandelion++ changes. I provided comments to help point out the changes. Please inspect.

Committers - this PR should be considered unsafe due to the one issue pointed out in this review (caused by complications with Dandelion++ changes). Sorry for not noticing this potential issue earlier, it wasn't immediately obvious. All tests are expected to pass.

Comment thread src/cryptonote_core/tx_pool.cpp Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This merge here was a little more than usual, might be worth inspecting.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

And @moneromooo-monero I ruined tabs again just for you. I switched to emacs recently :/ will fix.

Comment thread tests/unit_tests/levin.cpp Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

New test.

Comment thread tests/unit_tests/levin.cpp Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

New test.

Comment thread tests/unit_tests/levin.cpp Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed (see other comment).

Comment thread tests/unit_tests/levin.cpp Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed (see other comment).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

See removal of tx_relay = relay_method::fluff. @moneromooo-monero asked about this in the Dandelion++ review, and the original code was/is incorrect. I thought it was appropriate to mark the txes as "fluff" because the fluff routine was being used. However, if someone disables i2p/tor white noise, its only using the fluff algorithm, and isn't intended to be marked as public. So the "state" change is not made here. This is verified in the unit tests (see other comments).

Comment thread src/cryptonote_core/cryptonote_core.cpp Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Another reasonable big change. Transactions in the forward state get relayed over Dandelion++ stems when the timer expires.

Comment thread src/cryptonote_core/tx_pool.cpp Outdated
@vtnerd
vtnerd force-pushed the feature/forward_delay branch from 20d26bb to 37f836c Compare April 22, 2020 05:06
@vtnerd

vtnerd commented Apr 22, 2020

Copy link
Copy Markdown
Contributor Author

Tabs removed, and everything should go green. But see my own review above.

@vtnerd
vtnerd force-pushed the feature/forward_delay branch 2 times, most recently from a6505b7 to 7392e65 Compare April 24, 2020 02:32

@vtnerd vtnerd left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Marked two of my own "issues" as resolved. This PR should be ready, pending reviewers doing a partial "re-review" after the Dandelion++ changes were merged.

@moneromooo-monero @xiphon @SarangNoether (others?) - Another semi-major change. If the user disables "noise" (i.e. --tx-proxy,127.0.0.1:9050,disable_noise), then the tx is "fluffed" over outbound Tor connections, and the receiving hidden service will immediately fluff the transaction over ipv4/6 upon receive. The i2p/tor network is replacing Dandelion++ stem - (hopefully) breaking the p2p sybil attacks that Dandelion++ was designed to mitigate. This also allows users to use i2p/tor, but still get reasonable delays when sending a tx (the noise feature is more aggressive in its privacy and latency).

If the user leaves the default ("noise"), then the stem flag is set over i2p/tor. The receiving hidden service will forward over ipv4/6 using Dandelion++ stem after a randomized delay. The delay is to help mitigate against ISP packet+timing analysis (which is only useful if noise is being used). Arguably it could "fluff" mode after all this, but if the user waits that long for the send, whats a few more for Dandelion++ stem.

Any of this can be tweaked as more analysis is done.

Comment thread src/cryptonote_core/tx_pool.cpp Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Marking the above comment as resolved, see comment here about the change to the PR.

Comment thread src/cryptonote_core/tx_pool.cpp Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Marked this change earlier with poor tabbing (which is now marked as resolved), and re-marking to highlight the somewhat complex rebase since earlier reviews.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

See the change here, and associated comment above.

Comment thread tests/unit_tests/levin.cpp Outdated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed within this PR (see other comment within this review in levin_notify.cpp). All similar changes were for same reason.

Comment thread src/cryptonote_core/tx_pool.cpp Outdated
Comment thread src/cryptonote_core/tx_pool.cpp Outdated
@vtnerd
vtnerd force-pushed the feature/forward_delay branch from 7392e65 to 67ade80 Compare August 9, 2020 02:28
@Snipa22
Snipa22 merged commit c108c5e into monero-project:master Aug 9, 2020
@vtnerd
vtnerd deleted the feature/forward_delay branch April 1, 2024 00:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants