Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Approval Distribution Subsystem #1951

Merged
merged 19 commits into from
Nov 25, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,7 @@ Iterate over every `BlockEntry` and remove `PeerId` from it.

#### `NetworkBridgeEvent::PeerViewChange`

For each block in the view:
1. Initialize `fresh_blocks = {}`
2. Load the `BlockEntry` for the block. If the block is unknown, or the number is less than the view's finalized number, go to step 6.
3. Inspect the `known_by` set. If the peer is already present, go to step 6.
4. Add the peer to `known_by` and add the hash of the block to `fresh_blocks`.
5. Return to step 2 with the ancestor of the block.
6. For each block in `fresh_blocks`, send all assignments and approvals for all candidates in those blocks to the peer.
Invoke `unify_with_peer(peer, view)` to catch them up to messages we have.

We also need to use the `view.finalized_number` to remove the `PeerId` from any blocks that it won't be wanting information about anymore. Note that we have to be on guard for peers doing crazy stuff like jumping their 'finalized_number` forward 10 trillion blocks to try and get us stuck in a loop for ages.

Expand All @@ -119,8 +113,11 @@ If the message is of type `ApprovalDistributionV1Message::Approval(approval_vote

#### `ApprovalDistributionMessage::NewBlocks`

TODO: create `BlockEntry` and `CandidateEntries` for all blocks.
TODO: check for new commonality with peers. Broadcast new information to peers we now understand better.
Create `BlockEntry` and `CandidateEntries` for all blocks.

For all peers:
* Compute `view_intersection` as the intersection of the peer's view blocks with the hashes of the new blocks.
* Invoke `unify_with_peer(peer, view_intersection)`.

#### `ApprovalDistributionMessage::DistributeAsignment`

Expand Down Expand Up @@ -182,4 +179,15 @@ Imports an approval signature referenced by block hash and candidate index.
* Dispatch a `ApprovalDistributionV1Message::Approval(approval)` to all peers in the `BlockEntry`'s `known_by` set, excluding the peer in the `source`, if `source` has kind `MessageSource::Peer`. Add the fingerprint of the assignment to the knowledge of each peer. Note that this obeys the politeness conditions:
* We guarantee elsewhere that all peers within `known_by` are aware of all assignments relative to the block.
* We've checked that this specific approval has a corresponding assignment within the `BlockEntry`.
* Thus, all peers are aware of the assignment or have a message to them in-flight which will make them so.
* Thus, all peers are aware of the assignment or have a message to them in-flight which will make them so.
Copy link
Contributor

Choose a reason for hiding this comment

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

All this sounds fine, but it's quadratic so another reason candidates should be rejected long before "escalation by DoS".

It breaks gossip assumptions if one compares fingerprints between peers using publicly keyed bloom filters, but if each pair of peers computes their own shared secret bloom filter key, then they could compare using bloom filters. Yet another optimization I guess.



#### `unify_with_peer(peer: PeerId, view)`:

For each block in the view:
1. Initialize `fresh_blocks = {}`
rphmeier marked this conversation as resolved.
Show resolved Hide resolved
2. Load the `BlockEntry` for the block. If the block is unknown, or the number is less than the view's finalized number, go to step 6.
3. Inspect the `known_by` set of the `BlockEntry`. If the peer is already present, go to step 6.
4. Add the peer to `known_by` with a cloned version of `block_entry.knowledge`. and add the hash of the block to `fresh_blocks`.
5. Return to step 2 with the ancestor of the block.
6. For each block in `fresh_blocks`, send all assignments and approvals for all candidates in those blocks to the peer.
8 changes: 4 additions & 4 deletions roadmap/implementers-guide/src/types/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ enum ObservedRole {

```rust
enum ApprovalDistributionV1Message {
/// An assignment for a candidate in some recent, unfinalized block.
/// Assignments for candidates in recent, unfinalized blocks.
///
/// The u32 is the claimed index of the candidate this assignment corresponds to. Actually checking the assignment
/// may yield a different result.
Assignment(IndirectAssignmentCert, u32),
/// An approval for a candidate in some recent, unfinalized block.
Approval(IndirectSignedApprovalVote),
Assignments(Vec<(IndirectAssignmentCert, u32)>),
/// Approvals for candidates in some recent, unfinalized block.
Approvals(Vec<IndirectSignedApprovalVote>),
}
```

Expand Down