Skip to content
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

feat: double spend spam protection #1945

Merged
merged 6 commits into from
Jul 11, 2024

Conversation

grumbach
Copy link
Member

@grumbach grumbach commented Jul 5, 2024

Description

  • protects from spend shadowing through spamming attack
  • now Network Spend entries can only ever contain 2 entries max, chosen deterministically so all nodes are eventually consistent and there are NO FORKS in the knowledge, and less space is used!
  • small cleanup of spend verification API

The attack

An attack to hide a good spend. Say we have:
A->B->C->D
The attacker wants to get rid of B to poison C and D. They can spam the network with lots of double spends for B until none of the nodes have the original one. The attack is quite intricate and we discussed different alternatives with 2 spends as max for a spend record or unlimited (record size) as max. In both cases the attack was successful.
The solution was to add a descendency check in the case where we have more than 2 spends to choose which to keep:

  • spend arrives from put
  • check local kad (assume those are correct)
  • ask peers for what they have at this addr (verify those)
  • then verify the incoming put ones
  • If we have more than 2 spends in total after all these checks, order by
    • Do they have valid descendants?
    • determistic Hash (order in BTreeSet)
  • And keep 2 of them only
    • If only one has a valid descendency, we successfully saved the good branch
    • If two or more do, we keep two, both become invalid, and the others orphans (invalid too as a result)
    • If none do, the line stops here and that’s what we want

Comment on lines -31 to -36
/// The maximum number of double spend attempts to store that we got from PUTs
const MAX_DOUBLE_SPEND_ATTEMPTS_TO_KEEP_FROM_PUTS: usize = 15;

/// The maximum number of double spend attempts to store inside a record
const MAX_DOUBLE_SPEND_ATTEMPTS_TO_KEEP_PER_RECORD: usize = 30;

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 MAX is now 2 as this measure protected us until the attackers reached the MAX double spent attempt to keep!

@grumbach grumbach force-pushed the double_spend_spam_protection branch from bd81c37 to 4cec77c Compare July 5, 2024 16:46
@RolandSherwin RolandSherwin force-pushed the double_spend_spam_protection branch from 4cec77c to 551b542 Compare July 6, 2024 09:06
let array: Vec<_> = live_spends.clone().into_iter().collect();
if let [one, two] = array.as_slice() {
warn!("Got two live spends {one:?} and {two:?}, things are messed up!");
return Ok((one.to_owned().clone(), two.to_owned().clone()));
Copy link
Member

Choose a reason for hiding this comment

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

If we return early here, will we have an inconsistent state among our nodes if there are more than 2 live branches?
Having >1 live branch is very unlikely, but should we collect all live branches and then return the first 2, just to be deterministic?

Copy link
Member Author

Choose a reason for hiding this comment

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

You are absolutely right!

@grumbach grumbach force-pushed the double_spend_spam_protection branch from 551b542 to 1bc3e4a Compare July 9, 2024 13:57
@grumbach grumbach force-pushed the double_spend_spam_protection branch from 331bdf8 to 8071507 Compare July 10, 2024 14:05
@grumbach grumbach force-pushed the double_spend_spam_protection branch from 0e489e1 to b3a73f7 Compare July 10, 2024 18:21
@RolandSherwin RolandSherwin added this pull request to the merge queue Jul 11, 2024
Merged via the queue into maidsafe:main with commit 42e9d6c Jul 11, 2024
40 of 43 checks passed
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.

2 participants