Skip to content

Latest commit

 

History

History
338 lines (244 loc) · 15.4 KB

README.md

File metadata and controls

338 lines (244 loc) · 15.4 KB

SSV Module

This document contains the specification of the SSV module.

Table of Contents

Beacon Node

The Beacon node interface is a composition of all interfaces below along with a method to get a Beacon Network object.

It comprises the interface, as an API style, between the operator implementation and the Beacon Network.

Its purpose is to provide a set of functions that the operator will use to interact with the Beacon Nodes, both for requesting data objects, and states, and for submitting signed objects to the network.

---
title: Beacon Node Interface
---
flowchart LR
    Validator([Validator])
    BeaconNode{Beacon Node Interface}
    BeaconNetwork[(Beacon Network)]

    Validator-->|Request Data|BeaconNode
    BeaconNode-->|Returns Data|Validator
    Validator-->|Submits Data|BeaconNode
    BeaconNode---BeaconNetwork
Loading

Each interface below will provide methods for getting and submitting data related to their duty type.

Domain Calls

DomainCalls is an interface with a single method DomainData used to return a signature domain.

For each different duty, Ethereum adds a specific salt, the DomainType, to the hash of the object to be signed. Therefore, for different duty types, equal objects would have different hashes and, therefore, signatures. This is a common technique to prevent the Rainbow attack to hashing functions.

Similarly, SSV also defines a DomainType, defined by the network and its fork version, to be included in the signing process.

Proposer Calls

ProposerCalls is an interface used for the Proposer duty. It defines functions for getting Beacon blocks, blinded Beacon blocks (blocks with only a transaction root instead of a full transactions list) and for submitting these blocks to the node.

Attester Calls

AttesterCalls is an interface for the Attestation duty. It defines functions for getting the attestation data and for submitting it to the node.

Aggregator Calls

AggregatorCalls is an interface for the Aggregator duty. It has functions to get an AggregateAndProof object, that contains:

  • Aggregator index (validator index)
  • aggregate attestation
  • BLSSignature selection proof,

and to submit a signed aggregator message.

Sync Committee Calls

SyncCommitteeCalls is an interface for the Sync Committee's duty. It has a method to get beacon block roots and another method to submit a signed sync committee message.

Sync Committee Contribution Calls

SyncCommitteeCalls is an interface for the Sync committee aggregator duty. It has:

Runner

The runner is an entity responsible for performing validator duties for an operator. For that,

  • it will collaborate with other operators to create signatures and
  • it will count on the Beacon node to get and send data to the blockchain.

For each duty, there is a specific runner since each duty requires a different sequence of steps, or subprotocol, to be followed by the operators. In general, it comprises three phases:

  • Pre-consensus: a threshold signature is created on some structure for later getting specific data from the Beacon node.
  • Consensus: decides on the data to send back to the Beacon node.
  • Post-consensus: generates a threshold signature on the decided data and sends s signed object to the Beacon node.

Runner Interface

The Runner interface establishes every method that a runner of any type should have. It includes functions to process pre-consensus, consensus and post-consensus methods and to execute duties.

Base Runner

The BaseRunner structure represents a common ground for all different types of runners. It's comprised by:

  • a state,
  • share that contains information about the validators the node runs, and their committees.
  • committee member that contains infomration about the operator itself seperated from the validators it runs.
  • a QBFT controller to manage consensus instances,
  • the Beacon network, its Beacon role and the highest decided slot number.

State

RunnerState stores the state of the runner during its execution. The state is composed of:

  • a duty type,
  • the duty-decided output,
  • the consensus instance that decided the output and
  • partial signature containers for the pre-consensus and post-consensus steps.
Partial Signature Container

The PartialSigContainer structure stores partial signatures and performs validator signature reconstruction after a quorum is reached.

The reconstruction uses Lagrange Interpolation to reconstruct a message signed with the shared secret.

This is crucial for DVT technology since it provides a way to construct a validator signature without any party ever having possession of the private key. This is accomplished by Adi Shamir Secret Sharing and the mathematical associative property of signing in BLS signatures.

---
title: Signature reconstruction 
---
flowchart LR
    op1([Operator 1])
    op2([Operator 2])
    op3([Operator 3])
    op4([Operator 4])
    container[(PartialSigContainer)]
    signature{{Validator Signature}}
    op1-->|partial signature|container 
    op2-->|partial signature|container 
    op3-->|partial signature|container 
    op4-->|partial signature|container 
    container-->|Lagrange Interpolation|signature 
Loading

Proposer Runner

To propose a block, the validator must:

  • Fetch the head of the chain using the fork choice rule.
  • Construct a Beacon block.
  • Sign the beacon block and broadcast it.

Block creation is abstracted by the Beacon Node interface and the operator can just fetch the block from it.

However, there is a block field, randao_reveal, which is a signature of the validator over the epoch number. Thus, for the Beacon node to return the block, it needs to receive the signature first.

Thus the overall steps are:

  1. Produce the randao_reveal by broadcasting and collecting partial signatures over the epoch number.
  2. Send rando_reveal and get the Beacon block from the Beacon node interface.
  3. Run consensus on the duty and block data.
  4. Produce the signed Beacon block, by broadcasting and collecting partial signatures, and send it to the Beacon node.
---
title: Block proposer steps
---
%%{ init: { 'flowchart': { 'curve': 'linear' } } }%%
flowchart LR
        randao_cell(Construct Randao Signature)
        beaconnode(Get Beacon Block)
        Consensus(Consensus)

        signedBlock(Construct Block Signature)
        send(Send Signed Block to Beacon Node)


        randao_cell-->beaconnode
        beaconnode-->Consensus
        Consensus-->signedBlock
        signedBlock-->send

Loading

Committee Runner

This runner creates several beacon objects from one consensus. For the attestation duty and sync committee duty, the validator should construct an AttestationData, which is composed by:

  • a slot,
  • committee index,
  • a beacon block root (for the LMD GHOST vote)
  • a source and target checkpoint (for the FFG vote)

From the AttestationData it can create an Attestation and SyncCommitteeMessage.

The operator can rely on the Beacon node to get the AttestationData object.

The overall steps are:

  1. Get an AttestationData from the Beacon node.
  2. Reach a consensus on the duty and the attestation data.
  3. Construct the validator signature for the Attestation and Sync Committee objects and send it back to the Beacon node.
---
title:  steps
---
%%{ init: { 'flowchart': { 'curve': 'linear' } } }%%
flowchart LR
        attestationData(Get AttestationData)
        Consensus(Consensus)
        attestation(Construct Attestations Signatures)
        SyncCommittee(Construct Sync Committees Signatures)
        send(Send Attestations to Beacon Node)
        sendSync(Send Sync Committees to Beacon Node)
        

        attestationData-->Consensus
        Consensus-->attestation
        Consensus-->SyncCommittee
        attestation-->send
        SyncCommittee-->sendSync

Loading

Aggregator Runner

For the aggregator duty, the validator must collect AttestationData from other attesters that are similar to its own created. Then, it should create an AggregateAndProof object, sign it and broadcast a SignedAggregateAndProof to the network.

The AggregateAndProof object can be obtained by the Beacon node. However, one of its fields is the validator's signature over the slot value (selection_proof). Thus, this field must be created and delivered to the Beacon node in order to get the AggregateAndProof object.

Thus, the overall steps are:

  1. Construct the validator signature over the slot value (selection_proof).
  2. Send it to the Beacon node and request the AggregateAndProof object.
  3. Do consensus over the duty and the data.
  4. Construct the validator signature on the consensus output.
  5. Construct the SignedAggregateAndProof object and send it to the Beacon node.
---
title: Aggregator steps
---
%%{ init: { 'flowchart': { 'curve': 'linear' } } }%%
flowchart LR
        selectionProof(Construct selection_proof)
        aggregateAndProof(Get AggregateAndProof)
        consensus(Consensus)
        signedAggregateAndProof(Construct SignedAggregateAndProof)
        send(Send to Beacon node)

        selectionProof-->aggregateAndProof
        aggregateAndProof-->consensus
        consensus-->signedAggregateAndProof
        signedAggregateAndProof-->send
Loading

Sync Committee Aggregator Runner

Similarly to an attestation aggregator, a validator with a Sync Committee Aggregator duty should collect SyncCommitteeMessages, aggregate them into a SyncCommitteeContribution and send it to the network.

To know if a validator is an aggregator for the current sync committee slot, it must compute its signature over a SyncAggregatorSelectionData (selection proof) and use it as input of a function is_sync_committee_aggregator.

Using the SyncCommitteContribution data, it constructs a ContributionAndProof message, signs it to create a SignedContributionAndProof and sends it to the network.

The Beacon node provides the is_sync_committee_aggregator function and the ContributionAndProof object.

Thus, the operator's steps for this duty are:

  1. Compute the validator signature over SyncAggregatorSelectionData (selection proof).
  2. Ask the Beacon node if it's an aggregator. If not, stop.
  3. If so, get the ContributionAndProof object with the Beacon node.
  4. Compute the validator signature to create a SignedContributionAndProof and send it to the Beacon node.
---
title: Sync committee aggregator steps
---
%%{ init: { 'flowchart': { 'curve': 'linear' } } }%%
flowchart LR
        selectionProof(Selection Proof)
        checkAggregator(Check if it's aggregator)
        contribution(Get Contribution)
        contributionSignature(Construct validator signature)
        send(Send to Beacon node)

        selectionProof-->checkAggregator
        checkAggregator-->contribution
        contribution-->contributionSignature
        contributionSignature-->send
Loading

NOTE: a validator may be part of multiple sync committees and, therefore, it should check if it's an aggregator for every committee that it's part of.

Validator Registration Runner

NOTE: This is not an actual validator duty. However, here, it's considered a duty for MEV-Boost purpose, to set the validator's fee_recipient and gas_limit preferences.

To register a validator, it needs to create the operator needs to:

  1. Get the ValidatorRegistration object.
  2. Compute the validator signature over the object.
  3. Submit the validator registration to the Beacon node.
---
title: Validator registration steps
---
%%{ init: { 'flowchart': { 'curve': 'linear' } } }%%
flowchart LR
        registrationObject(Get ValidatorRegistration)
        signature(Compute signature)
        send(Submit to Beacon node)

        registrationObject-->signature
        signature-->send
Loading

Validator

The Validator entity represents a share of a validator that participates in the Ethereum Beacon chain consensus. Note that it's not the validator itself, but actually a virtual representation of a validator that the real operator entity will use.

The operator will use this structure to execute validator-related duties, managed by DutyRunners.

Duty runners

DutyRunners is a map: Beacon roles (as proposer, attester, etc) → Runner. Each duty type has its unique runner.

Additional documents