-
Notifications
You must be signed in to change notification settings - Fork 22
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
Documentation #496
base: dev
Are you sure you want to change the base?
Documentation #496
Changes from all commits
96fac27
8a62e82
a42db96
3316705
a636f0c
0b9e4f7
ec914af
b1ae3e6
8fcf27d
7060cac
770e204
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,182 +5,43 @@ | |
|
||
Secret Shared Validator ('SSV') is a unique technology that enables the distributed control and operation of an Ethereum validator. | ||
|
||
SSV uses an MPC threshold scheme with a consensus layer on top ([Istanbul BFT](https://arxiv.org/pdf/2002.03613.pdf)), | ||
that governs the network. \ | ||
Its core strength is in its robustness and fault tolerance which leads the way for an open network of staking operators | ||
SSV uses an MPC threshold scheme with a consensus layer on top ([Istanbul BFT](https://arxiv.org/pdf/2002.03613.pdf)) to execute Ethereum duties in a secure way. | ||
|
||
Its core strength is in its robustness and fault tolerance which leads the way for an open network of staking operators | ||
to run validators in a decentralized and trustless way. | ||
|
||
## SSV Spec | ||
This repo contains the spec for SSV.Network node. | ||
|
||
### SSVMessage | ||
SSV network message is called SSVMessage, it includes a MessageID and MsgType to route messages within the SSV node code, and, data for the actual message (QBFT/ pre/ Post consensus messages for example). | ||
|
||
Any message data struct must be signed and nested within a signed message struct which follows the MessageSignature interface. | ||
A signed message structure includes the signature over the data structure, the signed root and signer list. | ||
|
||
#### QBFT Message | ||
This type of message is used for all consensus messages | ||
```go | ||
type Message struct { | ||
MsgType MessageType | ||
Height Height // QBFT instance Height | ||
Round Round // QBFT round for which the msg is for | ||
Identifier []byte // instance Identifier this msg belongs to | ||
Data []byte | ||
} | ||
``` | ||
This repo contains the spec of the SSV protocol for the SSV.Network node. | ||
|
||
#### Partial Signature Message | ||
Used for pre and post consensus sigantures for collecting partial BN signatures and then reconstructing them | ||
```go | ||
type PartialSignatureMessage struct { | ||
Type PartialSigMsgType | ||
PartialSignature []byte // The beacon chain partial Signature for a duty | ||
SigningRoot []byte // the root signed in PartialSignature | ||
Signers []types.OperatorID | ||
} | ||
``` | ||
## The Network | ||
|
||
### Signing messages | ||
The KeyManager interface has a function to sign roots, a slice of bytes. | ||
The root is computed over the original data structure (which follows the MessageRoot interface), domain and signature type. | ||
|
||
**Use ComputeSigningRoot and ComputeSignatureDomain functions for signing** | ||
```go | ||
func ComputeSigningRoot(data MessageRoot, domain SignatureDomain) ([]byte, error) { | ||
dataRoot, err := data.GetRoot() | ||
if err != nil { | ||
return nil, errors.Wrap(err, "could not get root from MessageRoot") | ||
} | ||
|
||
ret := sha256.Sum256(append(dataRoot[:], domain...)) | ||
return ret[:], nil | ||
} | ||
``` | ||
```go | ||
func ComputeSignatureDomain(domain DomainType, sigType SignatureType) SignatureDomain { | ||
return SignatureDomain(append(domain, sigType...)) | ||
} | ||
``` | ||
The SSV network is composed of several `operators`. Each operator is identified by a unique [`OperatorID`](./types/docs/README.md#operatorid-and-committeeid) and holds a netwok key for message authentication. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. several -> many holds a netwok key for message authentication. -> holds a network key for message authentication on SSV network. |
||
|
||
Domain Constants: | ||
|
||
| Domain | Value | Description | | ||
|----------------|-------------------------------|-----------------------------------| | ||
| Primus Testnet | DomainType ("primus_testnet") | Domain for the the Primus testnet | | ||
|
||
Signature type Constants: | ||
|
||
| Signature Type | Value | Description | | ||
|----------------------|----------------------|------------------------------------------| | ||
| QBFTSignatureType | [] byte {1, 0, 0, 0} | SignedMessage specific signatures | | ||
| PartialSignatureType | [] byte {2, 0, 0, 0} | PostConsensusMessage specific signatures | | ||
| DKGSignatureType | [] byte {3, 0, 0, 0} | PostConsensusMessage specific signatures | | ||
|
||
## Validator and Runners | ||
A validator instance is created for each validator independently, each validator will have multiple Runner for each beacon chain duty type (Attestations, Blocks, etc.) | ||
Duty runners are responsible for processing incoming messages and act upon them, completing a full beacon chain duty cycle. | ||
|
||
Each duty starts by calling the StartNewDuty func in the respective Runner. | ||
StartNewDuty might return error if can't start a new duty, depending on the previous duty life cycle. | ||
As a general rule, when a runner is executing a duty in the consensus phase, a new duty can't start. | ||
Pre/ Post partial signature collection will not enable starting a new duty if not completed except if timed out. | ||
|
||
**Attestation Duty Full Cycle:**\ | ||
-> Wait to slot 1/3\ | ||
-> Received new beacon chain duty\ | ||
-> Check can start a new consensus instance\ | ||
-> Come to consensus on duty + attestation data\ | ||
-> Broadcast and collect partial signature to reconstruct signature\ | ||
-> Reconstruct signature, broadcast to BN | ||
|
||
**Block Proposal Duty Full Cycle:**\ | ||
-> Received new beacon chain duty\ | ||
-> Check can start a new consensus instance\ | ||
-> Sign partial RANDAO and wait for other signatures\ | ||
-> Come to consensus on duty + beacon block\ | ||
-> Broadcast and collect partial signature to reconstruct signature\ | ||
-> Reconstruct signature, broadcast to BN | ||
|
||
**Attestation Aggregator Duty Full Cycle:**\ | ||
-> Received new beacon chain duty\ | ||
-> Check can start a new consensus instance\ | ||
-> Sign partial selection proof and wait for other signatures\ | ||
-> Wait to slot 2/3\ | ||
-> Come to consensus on duty + aggregated selection proof\ | ||
-> Broadcast and collect partial signature to reconstruct signature\ | ||
-> Reconstruct signature, broadcast to BN | ||
|
||
**Sync Committee Duty Full Cycle:**\ | ||
-> Wait to slot 1/3\ | ||
-> Received new beacon chain duty\ | ||
-> Check can start a new consensus instance\ | ||
-> Come to consensus on duty + sync message\ | ||
-> Broadcast and collect partial signature to reconstruct signature\ | ||
-> Reconstruct signature, broadcast to BN | ||
|
||
**Sync Committee Aggregator Duty Full Cycle:**\ | ||
-> Received new beacon chain duty\ | ||
-> Check can start a new consensus instance\ | ||
-> Locally get sync subcommittee indexes for slot\ | ||
-> Partial sign contribution proofs (for each subcommittee) and wait for other signatures\ | ||
-> wait to slot 2/3\ | ||
-> Come to consensus on duty + contribution (for each subcommittee)\ | ||
-> Broadcast and collect partial signature to reconstruct signature\ | ||
-> Reconstruct signature, broadcast to BN | ||
|
||
A runner holds a QBFT controller for processing QBFT messages and a State which keeps progress for all stages of duty execution: pre/ post consensus messages. | ||
Partial signatures are collected and reconstructed (when threshold reached) to be broadcasted to the BN network. | ||
|
||
## Validator Share | ||
A share is generated and broadcasted publicly when a new SSV validator is registered to its operators. | ||
Shares include: | ||
- Node ID: The Operator ID the share belongs to | ||
- Validator Public Key | ||
- Committee: An array of Nodes that constitute the SSV validator committee. A node must include it's NodeID and share public key. | ||
- Domain | ||
|
||
```go | ||
type Share struct { | ||
OperatorID OperatorID | ||
ValidatorPubKey ValidatorPK | ||
SharePubKey []byte | ||
Committee []*Operator | ||
Quorum, PartialQuorum uint64 | ||
DomainType DomainType | ||
Graffiti []byte | ||
} | ||
``` | ||
Every `validator` is registered to a unique committee of operators to execute its duties. When this happens, [`Share`](./types/docs/README.md#share--sharemember-and-committeemember--operator) objext are broadcasted publicly to the network. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. objext -> objects
perhaps worth mentioning what "broadcasted publicly" means, is it through writing those shared into Ethereum smart contract or just sending messages to be delivered through SSV network |
||
|
||
## Node | ||
A node represents a registered SSV operator, each node has a unique ID and encryption key which is used to encrypt assigned shares. | ||
NodeIDs are extremely important as they are used when splitting a validator key via Shamir-Secret-Sharing, later on they are used to verify messages and reconstruct signatures. | ||
A single `committee` of operators may run several validators at the same time. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. run several validators at the same time -> run several validators (of independent users) at the same time |
||
|
||
Shares use the Node data (for committee) to verify that incoming messages were signed by a committee member | ||
The following image illustrates these relations. | ||
|
||
```go | ||
type Node struct { | ||
NodeID NodeID | ||
PubKey []byte | ||
} | ||
``` | ||
<p align="center",float="left"> | ||
<img src="./ssv/docs/network.drawio.png", width="45%" height="10%"> | ||
</p> | ||
|
||
To execute the validators' duties, the operators exchange messages in the network. These messages are of type [`SignedSSVMessage`](./types/README.md#signedssvmessage-and-ssvmessage) which wraps either a consensus message ([`qbft.Message`](qbft/docs/README.md#message)) or a partial signature message ([`PartialSignatureMessages`](./types/README.md#partialsignaturemessages)). | ||
|
||
To understand the protocol for executing duties, check out the [protocol explanation file](./ssv/README.md). The protocol is built upon the QBFT BFT consensus protocol. To understand our specification for the QBFT protocol, check the [QBFT module file](./qbft/README.md). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To understand the protocol for executing duties, check out the protocol explanation file. The protocol is built upon the QBFT BFT consensus protocol. To understand our specification for the QBFT protocol, check the QBFT module file. -> To understand the protocol for executing duties check out protocol overview doc. Note, it's built around QBFT BFT consensus protocol. |
||
|
||
### NodeID and share creation example | ||
NodeID is unique to each node, starting from ID 1 and incrementally going froward. | ||
Each ValidatorPK has a committee of nodes, each with a unique ID, share and share public key. | ||
Also, for more details, check the documentation for the [`Operator`](./types/docs/README.md#share--sharemember-and-committeemember--operator), [`Validator`](./ssv/docs/README.md#validator), and [`Committee`](./ssv/docs/README.md#committee) structures. | ||
|
||
f(x) = a0 + a1X + a2X^2+a3X^3 + ... + ak-1X^(k-1)\ | ||
f(0) = a0 = secret\ | ||
Share1 = f(NodeID1)\ | ||
Share1 = f(NodeID1)\ | ||
... | ||
## Spec tests | ||
|
||
### Spec tests | ||
The [spec tests](ssv/spectest) are a generated as a json file that can be run in any implementation. They test the various flows within the SSV package, treating the consensus protocol as as black box. | ||
The [spec tests](ssv/spectest) are generated as a json file that can be run in any implementation. They test the various flows within the SSV package, treating the consensus protocol as as black box. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can be run in any implementation -> can be run in against implementation |
||
To generate all json spec tests, run: | ||
|
||
```console | ||
foo@bar:~$ go generate ./... | ||
foo@bar:~$ make generate-jsons | ||
``` | ||
Then run all tests with | ||
|
||
```console | ||
foo@bar:~$ make test | ||
``` | ||
Then run all tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the the SSV.Network node, perhaps just the SSV node (or the SSV network node) ?
Update: I see, it's called like that through the docs ... a redundant term to be honest, I'd change it to SSV network node if that's easy to do.