Skip to content
Draft
Changes from 4 commits
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
101 changes: 101 additions & 0 deletions simple.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ Epoch Index = u32 (Slot / E)
Validator Index = u16
Core Index = u16

Ed25519 Public = [u8; 32]
Ed25519 Signature = [u8; 64]

Erasure-Root = [u8; 32]
Expand All @@ -157,6 +158,21 @@ Bundle Shard = [u8]
Segment Shard = [u8; 12]
```

### Grandpa types

Common types used in Grandpa and Justification request protocols.

```
Round Number = u64
Set Id = u32
Copy link
Owner

Choose a reason for hiding this comment

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

I assume Set Id refers to the validator/voter set? I think we need to be explicit here about what it actually is, eg is it an epoch index or something?

Copy link
Author

Choose a reason for hiding this comment

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

Clarified this. It starts at 0 at genesis and increments after each set change block is finalized. So it normally increments with epoch but it is not strictly the same as epoch index.

Prevote = Header Hash ++ Slot
Precommit = Header Hash ++ Slot
PrimaryPropose = Header Hash ++ Slot
Copy link
Owner

Choose a reason for hiding this comment

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

Might be simpler to just define Vote = Header Hash ++ Slot?

Copy link
Author

Choose a reason for hiding this comment

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

Yup, done.

Signed Prevote = Prevote ++ Ed25519 Signature ++ Ed25519 Public
Copy link
Owner

Choose a reason for hiding this comment

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

What does the signature cover? Presumably it should cover round number and set ID to avoid weird replay attacks? In any case I think this should be documented here given that it isn't covered in the GP. Also should document the prefix used for the signature.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, I've clarified this now. The signature does cover round number and set ID.

Signed Precommit = Precommit ++ Ed25519 Signature ++ Ed25519 Public
Commit = Header Hash ++ Slot ++ len++[Signed Precommit]
```

### Grid structure

Primarily for the purpose of block and preimage announcements, the previous, current, and next
Expand Down Expand Up @@ -270,6 +286,30 @@ Node -> Node
<-- FIN
```

### CE 130: Justification request
Copy link
Owner

Choose a reason for hiding this comment

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

I think this needs a less generic name -- "justification" is used in a few other places, so is not obviously a finality thing. Maybe "Finality justification request"?

Copy link
Author

Choose a reason for hiding this comment

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

Replaced it with Grandpa justification request.


Request for justifications associated with a block.

Justification Type is an enum where 0 is Grandpa and 1 is Beefy (not implemented yet).
Encoded Justification is the encoding of the specific justification based on type. If the type is Grandpa then this decodes to Grandpa Justification.

Votes Ancestries is the set of headers routing all precommit target blocks to the commit target block. In normal operation this will be empty as validators will vote for the same proposed block that will then be the committed block.

```
Votes Ancestries = len++[Header]
Grandpa Justification = Round Number ++ Commit ++ Votes Ancestries
Copy link
Owner

Choose a reason for hiding this comment

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

I assume this does not include a Set Id because that is implied or something?

Copy link
Author

Choose a reason for hiding this comment

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

It does not strictly need Set Id as all the votes inside Commit are signed with the Set Id so the Justification will only validate with the correct Set Id.
I've decided to add Set Id to it though as I think that will make syncing and tracking set changes easier.


Justification Type = 0 OR 1
Encoded Justification = len++[u8]
Copy link
Owner

Choose a reason for hiding this comment

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

What's the reason for the double-encoding here?

Copy link
Author

Choose a reason for hiding this comment

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

This was for a generic finality justification system that would work with eg, Grandpa and Beefy. Replaced this with a simple Grandpa Justification protocol for now so the double encoding has gone.

Justification = Justification Type ++ Encoded Justification
Justifications = len++[Justification]
Copy link
Owner

Choose a reason for hiding this comment

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

Why are multiple justifications returned here? I think the use of this protocol needs a bit of explanation, don't think I understand it. If you want a chain of finality justifications I assume you are supposed to send multiple requests? As it seems there is no way for the recipient of the request to know how far back the chain would need to go.

Copy link
Author

Choose a reason for hiding this comment

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

This was intended to return different types of justification (eg, Grandpa and Beefy) but I've simplified this to just return a single Grandpa justification for the block. There will be a separate Warp Sync protocol that will allow retrieval of Grandpa justifications based on Set Id rather than hash so the chain of set changes can be proven easily. Will add more details for this.


--> Header Hash
--> FIN
<-- Justifications
<-- FIN
```

### CE 131/132: Safrole ticket distribution

Sharing of a Safrole ticket for inclusion in a block.
Expand Down Expand Up @@ -703,3 +743,64 @@ Auditor -> Validator
--> FIN
<-- FIN
```

### CE 146: GRANDPA Vote

GRANDPA voter sets match validator sets for each epoch.
This is sent by each voting validator to all other voting validators.

Copy link
Owner

Choose a reason for hiding this comment

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

A summary of the vote types here and when they are sent would be good. Ideally it should be possible to implement this using only the GRANDPA paper and this document. So in particular, I think PrimaryPropose needs clarifying here, as I don't think that wording is used in the paper. I assume it is the block broadcast by the primary in step 2 of the protocol? We also need to define here how the primary is chosen as this is not defined in the paper.

```
Message = 0 ++ Prevote OR 1 ++ Precommit OR 2 ++ PrimaryPropose
Signed Message = Message ++ Ed25519 Signature ++ Ed25519 Public
Copy link
Owner

Choose a reason for hiding this comment

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

Probably don't need the public key here given that it should match the peer ID?


Validator -> Validator

--> Round Number ++ Set Id ++ Signed Message
--> FIN
<-- FIN
```

### CE 147: GRANDPA Commit

This is sent by each voting validator to all other voting validators.
Copy link
Owner

Choose a reason for hiding this comment

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

I think we need to be clearer about the sending behaviour here. The paper says that to reduce spam, we should:

  1. Delay broadcasting a commit by a random time from 0..1 seconds.
  2. Don't broadcast if we receive a commit from another validator.

I assume this is implemented in the Rust crate? Although it doesn't seem critical that all implementations do exactly the same thing here, we should probably still document the expected behaviour.


```
Precommits = len++[Precommit]
Multi Auth Data = len++[Ed25519 Signature ++ Ed25519 Public]
Copy link
Owner

Choose a reason for hiding this comment

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

I assume the nth signature applies to the nth precommit? This should be documented. Preferable to identify signers by their index rather than their public key here? Seems like this would cut message size by ~25%, and would be consistent with the other protocols and the GP.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, the signatures are in order of precommit. I've removed this along with Compact Commit though.

Compact Commit = Header Hash ++ Slot ++ Precommits ++ Multi Auth Data
Copy link
Owner

Choose a reason for hiding this comment

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

What's going on with Commit vs Compact Commit? What makes a Compact Commit compact? Why not just use Commit here?

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, this is left over from a potential optimization in the grandpa crate that never happened. I've removed Compact Commit.


Validator -> Validator

--> Round Number ++ Set Id ++ Compact Commit
--> FIN
<-- FIN
```

### CE 148: GRANDPA State

This is sent by each voting validator to all other voting validators and informs them of the latest round it is participating in.
Copy link
Owner

Choose a reason for hiding this comment

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

Should clarify when this is sent. Is it sent once the validator "starts the round" as defined in the paper?


```
Validator -> Validator

--> Round Number ++ Set Id ++ Slot
--> FIN
<-- FIN
```

### CE 149: GRANDPA CatchUp

Catchup Request. This is sent by a voting validator to another validator. The response includes all votes required to catch up state to that of the responding voter.
Copy link
Owner

Choose a reason for hiding this comment

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

This needs more explanation, particularly as this isn't really covered by the GRANDPA paper AFAICT. eg:

  • What are Base Hash and Base Header?
  • What do the round number and set ID in the request and response mean?
  • You say "the response includes all votes required to catch up state to that of the responding voter", but it seems like only the votes for one round are returned? If the requester is multiple rounds behind, are they supposed to request votes for one round at a time or something? Given the protocol defined in the paper, it does not seem possible for an honest voter to skip rounds? But perhaps this is possible based on observed commits or something?

Copy link
Author

Choose a reason for hiding this comment

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

I've clarified this a bit. Base refers to a block that all vote targets are a descendent of. There is no longer a response set ID, just for the request. The responding validator only returns the votes for the last completed round from it's view.


```
Base Hash = Header Hash
Base Number = Slot
Catchup = Round Number ++ len++[Signed Prevote] ++ len++[Signed Precommit] ++ Base Hash ++ Base Number

Validator -> Validator

--> Round Number ++ Set Id
--> FIN
<-- Set Id ++ Catchup
<-- FIN
```