Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Add nonce to repair request/response #9903

Closed
wants to merge 21 commits into from

Conversation

carllin
Copy link
Contributor

@carllin carllin commented May 6, 2020

Problem

People could send arbitrary shreds for ingestion via the repair port

Summary of Changes

  1. Add a nonce to repair/responses that needs to match in order for response to be accepted
  1. Reduce shred by 4 byte size of nonce: https://github.com/solana-labs/solana/pull/9903/files#diff-dc91d3a3b6051569c3c1d9979c3e4df1R46. New shred size will be: https://github.com/solana-labs/solana/pull/9903/files#diff-dc91d3a3b6051569c3c1d9979c3e4df1R50
    Because we still have to support old shred size as well, changes like: https://github.com/solana-labs/solana/pull/9903/files#diff-dc91d3a3b6051569c3c1d9979c3e4df1R896 are necessary.

Backwards Compatibility:

(Painful, but good exercise in what we want to do for any future changes to shreds :P)

  1. Window service has been modified to accept both the old and the new shred sizes, where previously it was assumed that the shred was the entire packet.data.
  1. Due to new shred size, changes like https://github.com/solana-labs/solana/pull/9903/files#diff-dc91d3a3b6051569c3c1d9979c3e4df1R750 and https://github.com/solana-labs/solana/pull/9903/files#diff-dc91d3a3b6051569c3c1d9979c3e4df1R843 are needed to guarantee erasure and de-shredding still work with old shred sizes.

  2. Repair request structure has changed to include nonce: https://github.com/solana-labs/solana/pull/9903/files#diff-dc108ad584300fa57f99d1675ccff3b9R93-R95. TODO: support old version as well

Proposed Upgrade Path:

  1. Land Backwards Compatibility 1) and 2) above without changing the shred size so that everyone has the code to parse/perform erasure/deshred on smaller shreds. This way when we upgrade, people will understand turbine shreds regardless of whether they have upgraded.

  2. This step is dependent on knowing what version people in gossip are on, @mvines is there a way to do that? If not I was thinking maybe we could set the storage_addr in ContactInfo as a flag.

Perform upgrade and modify repair such that:

  • only make nonce repair requests to people on new version.
  • only serve nonce repair responses to people on new version.

Fixes #

@carllin carllin requested review from sakridge and mvines May 6, 2020 21:08
@codecov
Copy link

codecov bot commented May 6, 2020

Codecov Report

Merging #9903 into master will decrease coverage by 0.0%.
The diff coverage is 79.4%.

@@           Coverage Diff            @@
##           master   #9903     +/-   ##
========================================
- Coverage    80.4%   80.4%   -0.1%     
========================================
  Files         287     289      +2     
  Lines       66539   67016    +477     
========================================
+ Hits        53555   53922    +367     
- Misses      12984   13094    +110     

@mvines
Copy link
Contributor

mvines commented May 8, 2020

Darn, all those nice links you setup in the description don't work @carllin :(

@mvines
Copy link
Contributor

mvines commented May 8, 2020

This step is dependent on knowing what version people in gossip are on, @mvines is there a way to do that? If not I was thinking maybe we could set the storage_addr in ContactInfo as a flag.

I've been wanting a way to determine Solana version from gossip actually, now that everybody is locking down RPC.

Stealing bits from the storage_add in ContactInfo sounds great for this! I'd do that as a completely independent PR that I'd actually love to backport all the way to 1.0.

It would be amazing if solana-gossip spy also included software version info for all the nodes

@carllin
Copy link
Contributor Author

carllin commented May 8, 2020

Darn, all those nice links you setup in the description don't work @carllin :(

Ah shucks, updated all of them, hopefully they work now?

Copy link
Contributor

@mvines mvines left a comment

Choose a reason for hiding this comment

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

This is looking really good overall. I think you should hack this PR to little bits though, so we can incrementally roll this out to the clusters.

For example we know we'll need that shred nonce, so we can carve that bit out ASAP and get mainnet-beta/testnet using it. That looks like the stickiest part of enabling a rolling update.

ledger/src/repair_response.rs Outdated Show resolved Hide resolved
@@ -0,0 +1,271 @@
use crate::request_response::RequestResponse;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: outstanding_requests feels too generic to me in core: outstanding_repair_requests. If we had that repair crate then calling this module outstanding_requests would be fine 😵

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mvines, so the way it's currently set up, outstanding_requests::OutstandingRequests<T, S> is designed to be more general than just repair, it can track any request type T that implements T: RequestResponse<Response = S>.

For instance gossip could potentially initialize an OutstandingRequests<T, S> for gossip requests/responses as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is that a thing we need though? Building generic interfaces in the hopes that somebody in the future will use them when there's only a single consumer today usually doesn't end too well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mvines yeah I would agree in mosts cases, but there was a lot of talk of a similar solution to solve the gossip replay issue here: #9491.

It was a also a nice way to logically bundle the verification of responses into the actual request object like this: https://github.com/solana-labs/solana/pull/9903/files#diff-dc108ad584300fa57f99d1675ccff3b9R66, so that they fit together rather than in disparate functions.

core/src/serve_repair.rs Outdated Show resolved Hide resolved
ledger/src/sigverify_shreds.rs Outdated Show resolved Hide resolved
@mvines
Copy link
Contributor

mvines commented May 9, 2020

  1. Separate thread for repair inserts so that grabbing the lock/verifying nonce doesn't block turbine shreds. Also greedily send shreds for insert: https://github.com/solana-labs/solana/pull/9903/files#diff-65dbf75f4753cd8c1a130e96e72cd1b4R242-R246 instead of blocking waiting for entire batch.

This feels like it's own PR too.

@carllin carllin force-pushed the FixRepair branch 9 times, most recently from 6977ef6 to 9eb8c57 Compare May 12, 2020 22:08
@carllin carllin force-pushed the FixRepair branch 5 times, most recently from 56f7e3f to 86cd4c5 Compare May 13, 2020 07:28
@carllin
Copy link
Contributor Author

carllin commented May 13, 2020

Tested by setting the "crossover" slot (the slot at which the nonces are turned on) to 1200 on a testnet, and also induced 3-min long partitions every 10 mins so that the cluster was partitioned during the "crossover" point, and at many points afterwards testing the repair path.

After a couple of edge cases, the results, no panics after an hour:
Screen Shot 2020-05-13 at 2 52 43 AM

Time to split it up and it should be ready to go!

@carllin
Copy link
Contributor Author

carllin commented May 14, 2020

  1. Separate thread for repair inserts so that grabbing the lock/verifying nonce doesn't block turbine shreds. Also greedily send shreds for insert: https://github.com/solana-labs/solana/pull/9903/files#diff-65dbf75f4753cd8c1a130e96e72cd1b4R242-R246 instead of blocking waiting for entire batch.

This feels like it's own PR too.

Removed that change as it didn't yield the expected perf benefits

slots_iter = slots.into_iter();
slots_iter_ref = &mut slots_iter;
}
for (batch, slots) in batches.iter().zip(slots_iter_ref) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it easier to just read the slot out of the shred data here?

@mvines
Copy link
Contributor

mvines commented May 18, 2020

@carllin - thanks for landing the v1.1 version of shred nonce. Rolling out the v1.0 version and master quickly would be very nice too. We're coming up on branch day for v1.2 (next Tuesday!)

@stale
Copy link

stale bot commented May 25, 2020

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale [bot only] Added to stale content; results in auto-close after a week. label May 25, 2020
@carllin carllin closed this May 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
stale [bot only] Added to stale content; results in auto-close after a week.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants