Documentation ¶
Index ¶
- Constants
- Variables
- func BytesToPublic(c CipherSuite, b []byte) (*ecdsa.PublicKey, error)
- func ConditionSeed(seed []byte) (uint64, error)
- func NodeIDBytesFromPub(c CipherSuite, pub *ecdsa.PublicKey) []byte
- func PubMarshal(c CipherSuite, pub *ecdsa.PublicKey) []byte
- func RandSampleRange(source DRNG, limit int, s []int) []int
- func RandSelect(source DRNG, limit, nsamples int) map[int]bool
- func ReadBits(bigint *big.Int, buf []byte)
- func RecoverPublic(c CipherSuite, h []byte, sig []byte) (*ecdsa.PublicKey, error)
- func RoundsInRange(start time.Time, end time.Time, roundLength uint64) uint64
- func RoundsSince(when time.Time, roundLength uint64) uint64
- func VerifyNodeSig(c CipherSuite, nodeID Hash, digest, sig []byte) bool
- func VerifyRecoverNodeSig(c CipherSuite, nodeID Hash, digest, sig []byte) (bool, []byte, error)
- type ActiveSelection
- type Address
- type Alpha
- type BlockActivity
- type BlockHeader
- type BlockHeaderReader
- type Broadcaster
- type ByAge
- type BytesCodec
- type BytesDecoder
- type BytesEncoder
- type ChainInit
- type CipherCodec
- func (codec *CipherCodec) BytesToPublic(pub []byte) (*ecdsa.PublicKey, error)
- func (codec *CipherCodec) ChainID(ci *ChainInit) (Hash, error)
- func (codec *CipherCodec) DecodeBlockActivity(a *BlockActivity, chainID Hash, header BlockHeader) error
- func (codec *CipherCodec) DecodeBytes(b []byte, val interface{}) error
- func (codec *CipherCodec) DecodeGenesisExtra(genesisExtra []byte, extra *GenesisExtraData) error
- func (codec *CipherCodec) DecodeHeaderSeal(header BlockHeader) (*SignedExtraData, Hash, []byte, error)
- func (codec *CipherCodec) DecodeSigned(msg []byte) ([65]byte, []byte, []byte, error)
- func (codec *CipherCodec) DecodeSignedEndorsement(e *SignedEndorsement, b []byte) ([]byte, error)
- func (codec *CipherCodec) DecodeSignedExtraData(e *SignedExtraData, b []byte) ([]byte, error)
- func (codec *CipherCodec) DecodeSignedIntent(i *SignedIntent, b []byte) ([]byte, error)
- func (codec *CipherCodec) EncodeHashGenesisExtraData(gd *GenesisExtraData) ([]byte, error)
- func (codec *CipherCodec) EncodeSignEndorsement(e *SignedEndorsement, k *ecdsa.PrivateKey) ([]byte, error)
- func (codec *CipherCodec) EncodeSignExtraData(e *SignedExtraData, k *ecdsa.PrivateKey) ([]byte, error)
- func (codec *CipherCodec) EncodeSignIntent(i *SignedIntent, k *ecdsa.PrivateKey) ([]byte, error)
- func (codec *CipherCodec) EncodeToBytes(val interface{}) ([]byte, error)
- func (codec *CipherCodec) FillEnrolmentQuote(q []byte, u Hash, a *ecdsa.PrivateKey) error
- func (codec *CipherCodec) HashEnrolmentBinding(e *EnrolmentBinding) (Hash, error)
- func (codec *CipherCodec) HashIntent(i *Intent) (Hash, error)
- func (codec *CipherCodec) Keccak256Hash(b ...[]byte) Hash
- func (codec *CipherCodec) NodeIDBytesFromPub(pub *ecdsa.PublicKey) []byte
- func (codec *CipherCodec) NodeIDFromPub(pub *ecdsa.PublicKey) Hash
- func (codec *CipherCodec) NodeIDFromPubBytes(pub []byte) (Hash, error)
- func (codec *CipherCodec) PopulateChainInit(ci *ChainInit, ck *ecdsa.PrivateKey, initIdents []Enrolment, ...) error
- func (codec *CipherCodec) RecoverEnrolerID(q Quote, u Hash) (Hash, error)
- func (codec *CipherCodec) RecoverEnrolmentPublic(q Quote, u Hash) (*ecdsa.PublicKey, error)
- func (codec *CipherCodec) SignEnrolmentBindingHash(q *Quote, key *ecdsa.PrivateKey, chainID Hash, nodeid Hash, round uint64, ...) error
- func (codec *CipherCodec) SignedEncode(k *ecdsa.PrivateKey, v interface{}) ([65]byte, []byte, error)
- func (codec *CipherCodec) VerifyNodeSig(nodeID Hash, digest, sig []byte) bool
- func (codec *CipherCodec) VerifyRecoverNodeSig(nodeID Hash, digest, sig []byte) (bool, []byte, error)
- type CipherSuite
- type Config
- type DRNG
- type Endorsement
- type EndorsmentProtocol
- func (r *EndorsmentProtocol) CalcDifficulty(nodeAddr Address) *big.Int
- func (r *EndorsmentProtocol) CheckGenesis(chain headerByNumberChainReader) error
- func (r *EndorsmentProtocol) GetChainHeadRoundStart() time.Time
- func (r *EndorsmentProtocol) GetSealTime(header BlockHeader) (time.Time, error)
- func (r *EndorsmentProtocol) IsEnrolmentPending(nodeID Hash) bool
- func (r *EndorsmentProtocol) NewChainHead(b Broadcaster, chain EngineChainReader, head BlockHeader)
- func (r *EndorsmentProtocol) NewSealTask(b Broadcaster, et *EngSealTask)
- func (r *EndorsmentProtocol) NewSignedEndorsement(et *EngSignedEndorsement)
- func (r *EndorsmentProtocol) NewSignedIntent(et *EngSignedIntent)
- func (r *EndorsmentProtocol) PhaseTick(b Broadcaster, chain EngineChainReader)
- func (r *EndorsmentProtocol) PrimeActiveSelection(chain EngineChainReader) error
- func (r *EndorsmentProtocol) QueueEnrolment(et *EngEnrolIdentity)
- func (r *EndorsmentProtocol) SetState(state RoundState) RoundState
- func (r *EndorsmentProtocol) StableSeed(chain EngineChainReader, headNumber uint64) (uint64, uint64, error)
- func (r *EndorsmentProtocol) StartRounds(b Broadcaster, chain EngineChainReader)
- func (r *EndorsmentProtocol) State() RoundState
- func (r *EndorsmentProtocol) UntilRoundEnd() time.Duration
- func (r *EndorsmentProtocol) VerifyBranchHeaders(chain VerifyBranchChainReader, header BlockHeader, parents []BlockHeader) error
- func (r *EndorsmentProtocol) VerifyHeader(chain headerByHashChainReader, header BlockHeader) (*SignedExtraData, error)
- type EngEnrolIdentity
- type EngNewChainHead
- type EngSealTask
- type EngSignedEndorsement
- type EngSignedIntent
- type Engine
- func (e *Engine) Author(header BlockHeader) (Address, error)
- func (e *Engine) Broadcast(self Address, peers map[Address]Peer, msg []byte) error
- func (e *Engine) CalcDifficulty(chain interface{}, time uint64, parent BlockHeader) *big.Int
- func (e *Engine) ChainID() Hash
- func (e *Engine) FindPeers(peers map[Address]bool) map[Address]Peer
- func (e *Engine) HandleMsg(peerAddr Address, msg []byte) (bool, error)
- func (e *Engine) IsEnrolmentPending(nodeID [32]byte) bool
- func (e *Engine) IsRunning() bool
- func (e *Engine) NodeAddress() Address
- func (e *Engine) NodeID() Hash
- func (e *Engine) NodePublic() []byte
- func (e *Engine) PostIfRunning(i interface{}) bool
- func (e *Engine) RunLock()
- func (e *Engine) RunUnlock()
- func (e *Engine) Seal(blockHeader BlockHeader, sealCommitter SealCommitter) error
- func (e *Engine) Send(peerAddr Address, rmsg RMsg) error
- func (e *Engine) SendSignedEndorsement(intenderAddr Address, et *EngSignedIntent) error
- func (e *Engine) SetPeerFinder(f PeerFinder)
- func (e *Engine) Start(chain EngineChainReader, withLock WithLock) error
- func (e *Engine) Stop(withLock WithLock)
- func (e *Engine) VerifyBranchHeaders(chain VerifyBranchChainReader, header BlockHeader, parents []BlockHeader) error
- func (e *Engine) VerifyHeader(chain headerByHashChainReader, header BlockHeader) error
- func (e *Engine) VerifySeal(chain VerifyBranchChainReader, header BlockHeader) error
- type EngineChainReader
- type EngineOption
- type Enrolment
- type EnrolmentBinding
- type ExtraData
- type ExtraHeader
- type GenesisExtraData
- type Hash
- type Intent
- type Logger
- type Participant
- type ParticipantByAge
- type ParticipantByID
- type Peer
- type PeerFinder
- type Quote
- type RMsg
- type RMsgCode
- type RoundPhase
- type RoundState
- type RoundTime
- type RoundTimeOption
- type SealCommitter
- type SignedEndorsement
- type SignedExtraData
- type SignedExtraDecoder
- type SignedIntent
- type VerifyBranchChainReader
- type WithLock
Constants ¶
const ( RRRActiveMethodSortEndorsers = "sortendorsers" // RRRActiveMethodRotateCandidates is implemented as a variant on // sortendorsers where rather than idling leaders that fail to produce // within Nc, we 'rotate' the candidate selection through the active // selection acording to the number of failed rounds. RRRActiveMethodRotateCandidates = "rotatecandidates" RRRActiveMethodSampleAged = "sampleaged" )
const ( AddressLength = 20 HashLen = 32 )
Variables ¶
var ( ErrIntentAndConfirmPhaseToLarge = errors.New("intent + confirm phase can not be longer than the round") ErrIncompatibleChainReader = errors.New("chainreader missing required interfaces for RRR") ErrNoGenesisHeader = errors.New("failed to get genesis header") ErrNotLeaderCandidate = errors.New("expected to be leader candidate") ErrEngineStopped = errors.New("consensus not running") ErrRMsgInvalidCode = errors.New("recevived RMsg with invalid code") )
var ( ErrUnknownAncestor = errors.New("unknown ancestor") ErrDecodingGenesisExtra = errors.New("failed to decode extra field from genesis block") ErrBadHeaderSeal = errors.New("invalid or corrupt header seal") )
var DefaultConfig = &Config{ IntentPhase: 1000, ConfirmPhase: 1000, RoundLength: 4000, Candidates: 2, Endorsers: 7, Quorum: 4, Activity: 2000, StablePrefixDepth: 6, MinIdleAttempts: 5, GossipFanout: 4, ActivityMethod: RRRActiveMethodSortEndorsers, }
DefaultConfig provides the default rrr consensus configuration
var (
ErrBranchDetected = errors.New("branch detected")
)
var (
ErrFutureBlock = errors.New("the time on the head block is in the future with respect to the reference value")
)
var (
ErrGenesisExtraDigestMismatch = errors.New("the included digest of the genesis extra doesn't match the actual")
)
var (
ErrSignedDecodeSignedFailed = errors.New("decoding signed rlp struct failed")
)
Functions ¶
func BytesToPublic ¶
func BytesToPublic(c CipherSuite, b []byte) (*ecdsa.PublicKey, error)
func ConditionSeed ¶
ConditionSeed takes a 32 byte input and XOR's it into a single uint64
func NodeIDBytesFromPub ¶
func NodeIDBytesFromPub(c CipherSuite, pub *ecdsa.PublicKey) []byte
NodeIDBytesFromPub NodeID is Keccak256 (Pub.X || Pub.Y ) In contexts where we have the id and a signature, we can recover the pub key of the signer using Ecrecover
func PubMarshal ¶
func PubMarshal(c CipherSuite, pub *ecdsa.PublicKey) []byte
PubMarshal converts public ecdsa key into the uncompressed form specified in section 4.3.6 of ANSI X9.62
func RecoverPublic ¶
RecoverPublic ...
func RoundsSince ¶
RoundsSince returns the number of rounds since the provided time for the given round length in seconds.
func VerifyNodeSig ¶
func VerifyNodeSig(c CipherSuite, nodeID Hash, digest, sig []byte) bool
VerifyNodeSig verifies if sig over digest was produced using the private key corresponding to nodeID. We EC recover the public key from the digest and the signature and then compare the hash of the recovered public key with the node ID. As ethereum node identities are the hash of the node's public key, this is equivelant to verification using the public key.
https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Public_key_recovery:
"The recovery algorithm can only be used to check validity of a signature if the signer's public key (or its hash) is known beforehand"
Note: Use VerifyRecoverNodeSig if you want the err from Ecrecover rather than true/false
func VerifyRecoverNodeSig ¶
Types ¶
type ActiveSelection ¶
type ActiveSelection interface { // AccumulateActive should be called each time a new block arrives to // maintain the active selection of candidates and endorsers. AccumulateActive( roundNumber uint64, chainID Hash, chain BlockHeaderReader, head BlockHeader, ) error NumActive() int NOldest(roundNumber uint64, n int) []Address NextActiveSample(roundNumber uint64, source DRNG, s []int) []int // SelectCandidatesAndEndorsers should be called once a round with a fresh // permutation of indices into the active selection. There must be exactly // nEndorsers worth of indices. SelectCandidatesAndEndorsers( roundNumber uint64, permutation []int, ) (map[Address]bool, map[Address]bool, error) // Reset resets and primes the active selection such that head - ta is the // furthest back the next selection will look Reset(head BlockHeader) // Prime primes the active selection such that the next selection will look as // far back as head - ta but no further Prime(head BlockHeader) // AgeOf returns the age of the identity. The boolean return is false if the // identity is not active. AgeOf(nodeID Address) (uint64, bool) IsActive(roundNumber uint64, addr Address) bool }
func NewActiveSelection ¶
func NewActiveSelection( config *Config, codec *CipherCodec, selfNodeID Hash, logger Logger) ActiveSelection
func NewActiveSelection3 ¶
func NewActiveSelection3( config *Config, codec *CipherCodec, selfNodeID Hash, logger Logger) ActiveSelection
type Address ¶
type Address [20]byte
Address is the ethereum style right most 20 bytes of Keccak256 (pub.X || pub.Y )
func PubToAddress ¶
func PubToAddress(c CipherSuite, pub *ecdsa.PublicKey) Address
type Alpha ¶
Alpha encodes the seed contribution for a single genesis identity. The initial seed is calculted using the keccak of the catentaion of each contribution::
alpha = KeccaK(contribution-id0 | ... | contribution-idN) seed, pi = VRF-Prove(alpha).
The original paper suggests a warmup phase in the consensus protocol which utilises RandHound and this is planed for future work.
type BlockActivity ¶
type BlockActivity struct { Confirm []Endorsement Enrol []Enrolment SealerID Hash SealerPub []byte RoundNumber uint64 }
BlockActivity is the decoded RRR consensus block activity data from the block header extra data.
type BlockHeader ¶
type BlockHeader interface { Hash() [32]byte // includes rrr seal HashForSeal() [32]byte // excludes rrr seal GetParentHash() [32]byte GetRoot() [32]byte GetTxHash() [32]byte GetNumber() *big.Int GetTime() uint64 GetSeal() []byte GetRound(SignedExtraDecoder) (uint64, error) GetNonce() [8]byte GetExtra() []byte }
type BlockHeaderReader ¶
type BlockHeaderReader interface {
GetHeaderByHash(hash [32]byte) BlockHeader
}
BlockHeaderReader defines the interface required by AccumulateActive
type Broadcaster ¶
type Broadcaster interface { PeerFinder // Broadcast self, peers, msg Broadcast(Address, map[Address]Peer, []byte) error // SendSignedEndorsement ... SendSignedEndorsement(intenderAddr Address, et *EngSignedIntent) error }
The engine supplies these so that the roundstate can call out to the network at the right points.
type BytesCodec ¶
type BytesCodec interface { BytesEncoder BytesDecoder }
type BytesDecoder ¶
type BytesEncoder ¶
type ChainInit ¶
type ChainInit struct { ExtraHeader Alpha []Alpha // one per enrolment, contributions are catenated in ident genesis age order }
ChainInit holds the RRR consensus genesis configuration, including genesis enroled identities
type CipherCodec ¶
type CipherCodec struct {
// contains filtered or unexported fields
}
func NewCodec ¶
func NewCodec(c CipherSuite, ed BytesCodec) *CipherCodec
func (*CipherCodec) BytesToPublic ¶
func (codec *CipherCodec) BytesToPublic(pub []byte) (*ecdsa.PublicKey, error)
func (*CipherCodec) ChainID ¶
func (codec *CipherCodec) ChainID(ci *ChainInit) (Hash, error)
ChainID returns the ChainID
func (*CipherCodec) DecodeBlockActivity ¶
func (codec *CipherCodec) DecodeBlockActivity(a *BlockActivity, chainID Hash, header BlockHeader) error
Decode decodes the RRR consensus activity data from the header extra data. Any activity previously held is completely discarded
func (*CipherCodec) DecodeBytes ¶
func (codec *CipherCodec) DecodeBytes(b []byte, val interface{}) error
func (*CipherCodec) DecodeGenesisExtra ¶
func (codec *CipherCodec) DecodeGenesisExtra(genesisExtra []byte, extra *GenesisExtraData) error
DecodeGenesisExtra decodes the RRR genesis extra data
func (*CipherCodec) DecodeHeaderSeal ¶
func (codec *CipherCodec) DecodeHeaderSeal(header BlockHeader) (*SignedExtraData, Hash, []byte, error)
func (*CipherCodec) DecodeSigned ¶
decodeSigned decodes a hash and its 65 byte ecdsa signture and recovers the puplic key. In this implementation, the recovered public key is the RRR long term identity and we pretty much always want that to hand.
func (*CipherCodec) DecodeSignedEndorsement ¶
func (codec *CipherCodec) DecodeSignedEndorsement(e *SignedEndorsement, b []byte) ([]byte, error)
DecodeSigned decodes the endorsment and returns the signers ecrecovered public key
func (*CipherCodec) DecodeSignedExtraData ¶
func (codec *CipherCodec) DecodeSignedExtraData(e *SignedExtraData, b []byte) ([]byte, error)
DecodeSigned decodes a SignedExtraData from the stream
func (*CipherCodec) DecodeSignedIntent ¶
func (codec *CipherCodec) DecodeSignedIntent(i *SignedIntent, b []byte) ([]byte, error)
DecodeSigned decodes ... (does not verify)
func (*CipherCodec) EncodeHashGenesisExtraData ¶
func (codec *CipherCodec) EncodeHashGenesisExtraData(gd *GenesisExtraData) ([]byte, error)
EncodeHashGenesisExtraData encodes
func (*CipherCodec) EncodeSignEndorsement ¶
func (codec *CipherCodec) EncodeSignEndorsement(e *SignedEndorsement, k *ecdsa.PrivateKey) ([]byte, error)
EncodeSignEndorsement encode and sign an endorsment
func (*CipherCodec) EncodeSignExtraData ¶
func (codec *CipherCodec) EncodeSignExtraData(e *SignedExtraData, k *ecdsa.PrivateKey) ([]byte, error)
SignedEncode signs and encodes the extra data
func (*CipherCodec) EncodeSignIntent ¶
func (codec *CipherCodec) EncodeSignIntent(i *SignedIntent, k *ecdsa.PrivateKey) ([]byte, error)
EncodeSignIntent encodes the intent body, signs the result and returns the serialised encoding of the result. k will typically be a leader candidate private key.
func (*CipherCodec) EncodeToBytes ¶
func (codec *CipherCodec) EncodeToBytes(val interface{}) ([]byte, error)
func (*CipherCodec) FillEnrolmentQuote ¶
func (codec *CipherCodec) FillEnrolmentQuote(q []byte, u Hash, a *ecdsa.PrivateKey) error
FillEnrolmentQuote intitialises a Quote for an identity to be enroled on the chain. a is the attestor. For genesis enrolment, this should be the chain creators private key. u is the 'userdata' hash to attest. For genesis identity enrolment it is just the enode identity directly (they are already 32 byte hashes). For operational enrolment it the hash of the rlp encoded EnrolmentBinding struct
func (*CipherCodec) HashEnrolmentBinding ¶
func (codec *CipherCodec) HashEnrolmentBinding(e *EnrolmentBinding) (Hash, error)
U encodes the userdata hash to sign for the enrolment.
func (*CipherCodec) HashIntent ¶
func (codec *CipherCodec) HashIntent(i *Intent) (Hash, error)
Hash hashes the intent
func (*CipherCodec) Keccak256Hash ¶
func (codec *CipherCodec) Keccak256Hash(b ...[]byte) Hash
func (*CipherCodec) NodeIDBytesFromPub ¶
func (codec *CipherCodec) NodeIDBytesFromPub(pub *ecdsa.PublicKey) []byte
func (*CipherCodec) NodeIDFromPub ¶
func (codec *CipherCodec) NodeIDFromPub(pub *ecdsa.PublicKey) Hash
func (*CipherCodec) NodeIDFromPubBytes ¶
func (codec *CipherCodec) NodeIDFromPubBytes(pub []byte) (Hash, error)
func (*CipherCodec) PopulateChainInit ¶
func (codec *CipherCodec) PopulateChainInit( ci *ChainInit, ck *ecdsa.PrivateKey, initIdents []Enrolment, alphaContrib map[Hash]Alpha) error
Populate fills in a ChainInit ready for encoding in the genesis extraData See EIP-rrr/extraData of Block0/9.
func (*CipherCodec) RecoverEnrolerID ¶
func (codec *CipherCodec) RecoverEnrolerID(q Quote, u Hash) (Hash, error)
RecoverEnrolerID recovers the identity that signed the enrolment hash u.
func (*CipherCodec) RecoverEnrolmentPublic ¶
RecoverEnrolmentPublic recovers the public component of the key which signed the enrolment from the signature q and and the userdata hash u. For a genesis enrolment, that is just the nodeid directly. For operational enrolments, obtain u by filling in the EnrolementBinding type and calling HashEnrolmentBinding()
func (*CipherCodec) SignEnrolmentBindingHash ¶
func (codec *CipherCodec) SignEnrolmentBindingHash( q *Quote, key *ecdsa.PrivateKey, chainID Hash, nodeid Hash, round uint64, blockHash Hash, reEnrol bool, ) error
SignIdentityEnrolment fills in a quote for operational enrolment of the supplied nodeid. This binds the enrolment to the chain identified by chainID. Round is the current round of consensus. blockHash identifies the current head of the chain (selected branch)
func (*CipherCodec) SignedEncode ¶
func (codec *CipherCodec) SignedEncode(k *ecdsa.PrivateKey, v interface{}) ([65]byte, []byte, error)
func (*CipherCodec) VerifyNodeSig ¶
func (codec *CipherCodec) VerifyNodeSig( nodeID Hash, digest, sig []byte) bool
VerifyNodeSig verifies that sig over digest was produced by the public key for the node identified by nodeID. This works because the nodeID is the hash of the nodes public key.
func (*CipherCodec) VerifyRecoverNodeSig ¶
func (codec *CipherCodec) VerifyRecoverNodeSig( nodeID Hash, digest, sig []byte) (bool, []byte, error)
VerifyRecoverNodeSig verifies that sig over digest was produced by the public key for the node identified by nodeID and returns the recovered public key bytes. This works because the nodeID is the hash of the nodes public key.
type CipherSuite ¶
type CipherSuite interface { Curve() elliptic.Curve // Keccak256 returns a digest suitable for Sign. (draft sha3 before the padding was added) Keccak256(b ...[]byte) []byte // Sign is given a digest to sign. Sign(digest []byte, key *ecdsa.PrivateKey) ([]byte, error) // VerifySignature verifies VerifySignature(bub, digest, sig []byte) bool // Ecrecover a public key from a recoverable signature. Ecrecover(digest, sig []byte) ([]byte, error) }
CipherSuite abstracts essential cryptographic primitives used by rrr. It exists principally to avoid licensing issues and circular dependencies on go-ethereum. Implementations are assumed to be EC secp256k1 + draft sha3. This interface does not allow for algorithmic agility of any kind.
type Config ¶
type Config struct { IntentPhase uint64 `toml:",omitempty"` // How long endorsers wait to decide the oldes leader ConfirmPhase uint64 `toml:",omitempty"` // Duration of the confirmation phase in milliseconds (must be < round) RoundLength uint64 `toml:",omitempty"` // Duration of each round in milliseconds Candidates uint64 `toml:",omitempty"` // Number of leader candidates (Nc) to propose from the oldest identities on each round Endorsers uint64 `toml:",omitempty"` // Number of endorsers (Ne) to select from the most recently active identities Quorum uint64 `toml:",omitempty"` // Number of endorsments required to confirm an intent Activity uint64 `toml:",omitempty"` // Activity threshold (Ta) (in blocks). Any identity with confirmation messages recorded within this many rounds of the head are considered active. StablePrefixDepth uint64 `toml:"omitempty"` // d stable block prefix (for seed r-d) // MinIdleAttempts if the identity is oldest for // MAX(Candidates,MinIdleAttempts) it is made idle. Used to avoid over // agressive idling in small networks. MinIdleAttempts uint64 `toml:"omitempty"` GossipFanout int `toml:"omitempty"` // ActivityMethod selects one of the alternative implementations for // tracking identity activity // sortendorsers - closest to paper, simplest implementation, may struggle with > 10000s of identities // sampleaged - maintains all idenities in age order all the time and does not sort in SelectActive ActivityMethod string `toml:"ommitempty"` }
Config carries the RRR consensus configuration
type Endorsement ¶
Endorsement represents the unsigned approval of a leader candidates intent.
type EndorsmentProtocol ¶
type EndorsmentProtocol struct { T RoundTime Phase RoundPhase Number uint64 FailedAttempts uint32 // contains filtered or unexported fields }
EndorsmentProtocol implements 5.2 "Endorsement Protocol" and 5.3 "Chain Validation" (from the paper)
func NewRoundState ¶
func NewRoundState( codec *CipherCodec, key *ecdsa.PrivateKey, config *Config, logger Logger, ) *EndorsmentProtocol
NewRoundState creates and initialises a RoundState
func (*EndorsmentProtocol) CalcDifficulty ¶
func (r *EndorsmentProtocol) CalcDifficulty(nodeAddr Address) *big.Int
CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty that a new block should have. For rrr this is just the round number
func (*EndorsmentProtocol) CheckGenesis ¶
func (r *EndorsmentProtocol) CheckGenesis(chain headerByNumberChainReader) error
CheckGenesis checks that the RRR consensus configuration in the genesis block is correct.
func (*EndorsmentProtocol) GetChainHeadRoundStart ¶
func (r *EndorsmentProtocol) GetChainHeadRoundStart() time.Time
func (*EndorsmentProtocol) GetSealTime ¶
func (r *EndorsmentProtocol) GetSealTime(header BlockHeader) (time.Time, error)
GetBlockTime returns the time the block was sealed. It decodes the extra data to do this. Consider caching the result.
func (*EndorsmentProtocol) IsEnrolmentPending ¶
func (r *EndorsmentProtocol) IsEnrolmentPending(nodeID Hash) bool
IsEnrolmentPending returns true if there is an enrolment request queued for the nodeID
func (*EndorsmentProtocol) NewChainHead ¶
func (r *EndorsmentProtocol) NewChainHead( b Broadcaster, chain EngineChainReader, head BlockHeader)
NewChainHead is called to handle the chainHead event from the block chain. For a block to make it this far, VerifyHeader and VerifySeal must have seen and accepted the block. A 'bad' block here is the result of a programming error.
func (*EndorsmentProtocol) NewSealTask ¶
func (r *EndorsmentProtocol) NewSealTask(b Broadcaster, et *EngSealTask)
NewSealTask delivers work from the node to be mined. If we are the leader, and we are in the intent phase we immediately broadcast our intent. If not, we hang on to it until we are or we receive the next one.
func (*EndorsmentProtocol) NewSignedEndorsement ¶
func (r *EndorsmentProtocol) NewSignedEndorsement(et *EngSignedEndorsement)
NewSignedEndorsement keeps track of endorsments received from peers. At the end of the confirmation phase, in PhaseTick, if we are a leader and our *current* intent has sufficient endorsments, we seal the block. This causes geth to broad cast it to the network.
func (*EndorsmentProtocol) NewSignedIntent ¶
func (r *EndorsmentProtocol) NewSignedIntent(et *EngSignedIntent)
NewSignedIntent keeps track of the oldest intent seen in a round. At the end of the intent phase (in PhaseTick), if the node is an endorser, an endorsment is sent to the oldest seen. Only the most recent intent from any identity counts.
func (*EndorsmentProtocol) PhaseTick ¶
func (r *EndorsmentProtocol) PhaseTick(b Broadcaster, chain EngineChainReader)
PhaseTick deals with the time based round state transitions. It MUST be called each time a tick is read from the ticker. At the end of the intent phase, if an endorser, the oldest seen intent is endorsed. At the end of the confirmation phase, if a leader candidate AND the current intent has sufficient endorsements, the block for the intent is sealed. Geth will then broadcast it.
func (*EndorsmentProtocol) PrimeActiveSelection ¶
func (r *EndorsmentProtocol) PrimeActiveSelection(chain EngineChainReader) error
PrimeActiveSelection should be called for engine Start
func (*EndorsmentProtocol) QueueEnrolment ¶
func (r *EndorsmentProtocol) QueueEnrolment(et *EngEnrolIdentity)
QueueEnrolment enrols a node id. This enrolment is completely open. The SGX identity attestation and the minining identity approaches are not presently included.
func (*EndorsmentProtocol) SetState ¶
func (r *EndorsmentProtocol) SetState(state RoundState) RoundState
func (*EndorsmentProtocol) StableSeed ¶
func (r *EndorsmentProtocol) StableSeed(chain EngineChainReader, headNumber uint64) (uint64, uint64, error)
func (*EndorsmentProtocol) StartRounds ¶
func (r *EndorsmentProtocol) StartRounds(b Broadcaster, chain EngineChainReader)
StartRounds initialises the current round, establishes the current seed and starts the phase ticker. The engine run go routine calls this exactly once when it starts up.
func (*EndorsmentProtocol) State ¶
func (r *EndorsmentProtocol) State() RoundState
func (*EndorsmentProtocol) UntilRoundEnd ¶
func (r *EndorsmentProtocol) UntilRoundEnd() time.Duration
func (*EndorsmentProtocol) VerifyBranchHeaders ¶
func (r *EndorsmentProtocol) VerifyBranchHeaders( chain VerifyBranchChainReader, header BlockHeader, parents []BlockHeader) error
func (*EndorsmentProtocol) VerifyHeader ¶
func (r *EndorsmentProtocol) VerifyHeader(chain headerByHashChainReader, header BlockHeader) (*SignedExtraData, error)
type EngEnrolIdentity ¶
type EngNewChainHead ¶
type EngNewChainHead struct {
BlockHeader BlockHeader
}
EngNewChainHead notifies the run loop of a NewChainHead event.
type EngSealTask ¶
type EngSealTask struct { BlockHeader BlockHeader Committer SealCommitter // RoundNumber the Seal was requested. Filled in by the endorsment protocol // when it retrieves the task of the run queue. RoundNumber uint64 }
EngSealTask is sent to the engines runningCh to request endorsment to create a block. This is initiated by the local miner invoking Seal interface method. If the local node is a leader candidate in the current round this will result in an Intent being broadcast. Otherwise it will be ignored by the engine. The miner will clear un-answered Seal requests when it sees a new chain head.
type EngSignedEndorsement ¶
type EngSignedEndorsement struct { SignedEndorsement Pub []byte // Derived from signature }
type EngSignedIntent ¶
type EngSignedIntent struct { SignedIntent Pub []byte // Derived from signature }
eng* types can be sent at any tome the the engines runningCh.
type Engine ¶
type Engine struct { *EndorsmentProtocol // contains filtered or unexported fields }
Engine implements consensus.Engine using Robust Round Robin consensus https://arxiv.org/abs/1804.07391
func NewEngine ¶
func NewEngine( config *Config, codec *CipherCodec, privateKey *ecdsa.PrivateKey, logger Logger, opts ...EngineOption) (*Engine, error)
NewEngine a new instance of the rrr consensus engine. Assumes the provided engine instance is new.
func (*Engine) Author ¶
func (e *Engine) Author(header BlockHeader) (Address, error)
Author retrieves the Ethereum address of the account that minted the given block, which may be different from the header's coinbase if a consensus engine is based on signatures.
func (*Engine) Broadcast ¶
Broadcast the message to the provided peers, skipping self. If we have previously sent the message to a peer, it is not resent.
func (*Engine) CalcDifficulty ¶
func (e *Engine) CalcDifficulty(chain interface{}, time uint64, parent BlockHeader) *big.Int
CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty that a new block should have. For rrr this is just the round number
func (*Engine) ChainID ¶
ChainID is the chain identifier. Will return the zero hash until Start is called.
func (*Engine) HandleMsg ¶
HandleMsg handles a message from peer and deals with gossiping consensus messages where necessary.
func (*Engine) IsEnrolmentPending ¶
func (*Engine) NodeAddress ¶
NodeAddress returns the node address
func (*Engine) NodePublic ¶
NodePublic returns the marshaled public key. (uncompressed form specified in section 4.3.6 of ANSI X9.62)
func (*Engine) PostIfRunning ¶
func (*Engine) Seal ¶
func (e *Engine) Seal(blockHeader BlockHeader, sealCommitter SealCommitter) error
func (*Engine) Send ¶
Send the message to the peer - if its hash is not in the ARU cache for the peer
func (*Engine) SendSignedEndorsement ¶
func (e *Engine) SendSignedEndorsement(intenderAddr Address, et *EngSignedIntent) error
SendSignedEndorsement sends a signed (endorsed) intent back to the intender
func (*Engine) SetPeerFinder ¶
func (e *Engine) SetPeerFinder(f PeerFinder)
SetBroadcaster implements consensus.Handler.SetBroadcaster Which, for the quorum fork, is called by eth/handler.go NewProtocolManager
func (*Engine) Start ¶
func (e *Engine) Start( chain EngineChainReader, withLock WithLock) error
Start the consensus protocol. To allow for atomic cleanup, the caller provided withLock is invoked as soon as the lock is aquired. Note that withLock is *always* called if it is not nil - regardless of whether the engine is already started.
func (*Engine) Stop ¶
Stop stops the engine. To allow for atomic cleanup, the caller provided withLock is invoked as soon as the lock is aquired.
func (*Engine) VerifyBranchHeaders ¶
func (e *Engine) VerifyBranchHeaders( chain VerifyBranchChainReader, header BlockHeader, parents []BlockHeader) error
func (*Engine) VerifyHeader ¶
func (e *Engine) VerifyHeader(chain headerByHashChainReader, header BlockHeader) error
func (*Engine) VerifySeal ¶
func (e *Engine) VerifySeal(chain VerifyBranchChainReader, header BlockHeader) error
type EngineChainReader ¶
type EngineChainReader interface { CurrentHeader() BlockHeader GetHeaderByNumber(number uint64) BlockHeader GetHeaderByHash(hash [32]byte) BlockHeader }
type EngineOption ¶
type EngineOption func(e *Engine)
func WithClockCheck ¶
func WithClockCheck(checker func()) EngineOption
type Enrolment ¶
type Enrolment struct { Q Quote U Hash // nodeid for genesis, EnrolmentBinding.U() otherwise // ID can be verified by reconstructing an EnrolmentBinding, getting its // hash, comparing that hash with U (above) and then checking that the // public key for the node that sealed the block with the Enrolment can // verify the quote. ID Hash // must be verified by re-creating an Enrol }
Enrolment provides the RRR identity enrolment data.
func IdentInit ¶
func IdentInit( codec *CipherCodec, ck *ecdsa.PrivateKey, init []Enrolment, nodeids ...Hash) ([]Enrolment, error)
IdentInit creates, or extends, the identity initialisation vector for the extraData in the genesis block. init is nil or the currently included identities. One or more nodeids are passed as the trailing parameters. The updated init vector is returned. See EIP-rrr/extraData of Block0
type EnrolmentBinding ¶
type EnrolmentBinding struct { ChainID Hash // ChainID is EIP-rrr/extraData of Block0 NodeID Hash // NodeID is defined by ethereum as keccak 256 ( PublicKey X || Y ) Round uint64 // Round is the consensus round BlockHash Hash // BlockHash is the block hash for the head of the selected chain branch ReEnrol bool // true if the identity has been enroled before. }
EnrolmentBinding is rlp encoded, hashed and signed to introduce NodeID as a member.
type ExtraData ¶
type ExtraData struct { ExtraHeader Intent Intent Confirm []Endorsement }
ExtraData is the complete (minus sig) RRR consensus data included on each block
type ExtraHeader ¶
type ExtraHeader struct { SealTime []byte // result of time.Now().UTC().MarshalBinary() at seal time Seed []byte // VRF beta output, alpha is previous seed Proof []byte // VRF proof Enrol []Enrolment }
ExtraHeader is the common header for the genesis block and consensus produced blocks
type GenesisExtraData ¶
GenesisExtraData adds the ChainID which is the hash of the ChainInit
type Hash ¶
type Hash [32]byte
Hash is a hash. We always work with Keccak256 (draft sha3)
func Keccak256Hash ¶
func Keccak256Hash(c CipherSuite, b ...[]byte) Hash
Keccak256Hash hashes a variable number of byte slices and returns a Hash
func NodeIDFromPub ¶
func NodeIDFromPub(c CipherSuite, pub *ecdsa.PublicKey) Hash
NodeIDFromPub gets a node id from an ecdsa pub key
func NodeIDFromPubBytes ¶
func NodeIDFromPubBytes(c CipherSuite, pub []byte) (Hash, error)
NodeIDFromPubBytes gets a node id from the bytes of an ecdsa public key
func (Hash) EnodeIDFromSig ¶
func (h Hash) EnodeIDFromSig(c CipherSuite, sig []byte) ([]byte, error)
EnodeIDFromSig recovers the enode id for the signer of the hash
func (Hash) NodeIDFromSig ¶
func (h Hash) NodeIDFromSig(c CipherSuite, sig []byte) (Hash, error)
NodeIDFromSig gets the recovers the signers node id from the signature
type Intent ¶
type Intent struct { // ChainID is established in the extradata of the genesis block ChainID Hash // NodeID is Keccak256 ( PublicKey X || Y ) NodeID Hash // RoundNumber is the block number proposed. RoundNumber uint64 // ParentHash parent block hash ParentHash Hash // TxHash is the hash of the transactions (merkle root for block) TxHash Hash }
Intent declares a leader candidates intent to seal a block
type Logger ¶
type Logger interface { LazyValue(func() string) interface{} Trace(msg string, ctx ...interface{}) Debug(msg string, ctx ...interface{}) Info(msg string, ctx ...interface{}) Warn(msg string, ctx ...interface{}) Crit(msg string, ctx ...interface{}) }
Logger is the go-ethereum compatible logging interface used in rrr
type Participant ¶
type Participant struct {
// contains filtered or unexported fields
}
type ParticipantByAge ¶
type ParticipantByAge []*Participant
func (ParticipantByAge) Len ¶
func (a ParticipantByAge) Len() int
func (ParticipantByAge) Less ¶
func (a ParticipantByAge) Less(i, j int) bool
func (ParticipantByAge) Swap ¶
func (a ParticipantByAge) Swap(i, j int)
type ParticipantByID ¶
type ParticipantByID []*Participant
func (ParticipantByID) Len ¶
func (a ParticipantByID) Len() int
func (ParticipantByID) Less ¶
func (a ParticipantByID) Less(i, j int) bool
func (ParticipantByID) Swap ¶
func (a ParticipantByID) Swap(i, j int)
type Peer ¶
type Peer interface { // SendConsensus sends a consensus message to this peer SendConsensus(data interface{}) error }
type Quote ¶
type Quote [65]byte
Quote is the 'pseudo' attestation of identity performed using node private keys rather than SGX. See RRR-spec 'extraData of Block0' and 'Enrolment data'. It is only the "Quote" refrenced in the original paper in so far as it will be the Qi that gets included in Block0 or in Enroln messages. It's an ecdsa signature the [R || S || V] format
type RMsg ¶
type RMsg struct { Code RMsgCode Raw []byte Round uint64 // If the message is to be gossiped, To are the intended recipients. Any // node that has a direct connection for any To address will simply send // directly, remove it from the To list, and only re-broadcast if any To's // remain. Note that in any given round we are only gossiping RMsgIntent's or // RMsgConfirm's. And we are only gossiping amongst leader candidates and // endorsers selected for the current round - not the entire network. To []Address // telemetry only, incremented each time the message is re-gossiped PathLength uint32 }
RMsg is the dev p2p (eth) message for RRR
type RMsgCode ¶
type RMsgCode uint
RMsgCode identifies the rrr message type. rrrMsg identifies rrr's message type to the devp2p layer as being consensus engine specific. Once that outer message is delivered to rrr, RMsgCode is how rrr differentiates each of its supported message payloads.
const ( // RMsgInvalid is the *never set* invalid message code RMsgInvalid RMsgCode = iota // RMsgIntent identifies RRR intent messages RMsgIntent // RMsgConfirm identifies RRR endorsement messages (confirmations) RMsgConfirm // RMsgEnrol is used to alow nodes to self enrol and automatically re-enrol // without needing to go through the rpc mechanism RMsgEnrol // RMsgRandContribSolicit ... RMsgRandContribSolicit // RMsgRandContrib ... RMsgRandContrib // RMsgRandAgreementSolicit ... RMsgRandAgreementSolicit // RMsgRandAgreement ... RMsgRandAgreement )
type RoundPhase ¶
type RoundPhase int
RoundPhase is the type for the round phase
const ( // RoundPhaseInvalid is the invalid state for RoundPhase RoundPhaseInvalid RoundPhase = iota // RoundPhaseIntent During the Intent phase, the endorser committee is // allowing for intents to arrive so they can, with high probability, pick // the oldest active leader candidate. RoundPhaseIntent // RoundPhaseConfirm During the confirmation phase leaders are waiting for // all the endorsements to come in so they fairly represent activity. RoundPhaseConfirm // RoundPhaseBroadcast during the Broadcast phase all nodes are waiting for // a NewChainHead event for the current round (including the c nsensus // leaders). Any node receiving an otherwise valid HEAD for a different // round must align with the round on the recieved head. RoundPhaseBroadcast // Used to absorb and align the start time with the round time. Means we // can deal with most initialisation the same as we do the end of the // Broadcast round *and* we may get a block while we wait. RoundPhaseStartup )
func (RoundPhase) String ¶
func (p RoundPhase) String() string
Home for stringers and other telemetry related distractions
type RoundState ¶
type RoundState int
RoundState type for the round state
const ( // RoundStateInvalid is the invalid and never set state RoundStateInvalid RoundState = iota // RoundStateInactive is set if the node is not in the active selection for the round. RoundStateInactive // Indicates conditions we expect to be transitor - endorsers not online etc // RoundStateActive is entered if the node is active but is not selected as // either a leader or an endorser RoundStateActive // Has endorsed or mined in some time in the last Ta rounds. // RoundStateLeaderCandidate selected as leader candidate for current round RoundStateLeaderCandidate // RoundStateEndorserCommittee Is in the endorser committee for the current round. RoundStateEndorserCommittee )
func (RoundState) String ¶
func (s RoundState) String() string
type RoundTime ¶
type RoundTime struct { Confirm time.Duration Intent time.Duration Broadcast time.Duration RoundLength time.Duration Ticker *time.Timer }
RoundTime takes (some) of the sharp edges of go's time.Timer and provides conveniences for manaing the time based RRR state
func NewRoundTime ¶
func NewRoundTime( config *Config, opts ...RoundTimeOption) RoundTime
NewRoundTime creates and configures a RoundTime. Does *not* call Start
func (*RoundTime) ResetForBroadcastPhase ¶
func (t *RoundTime) ResetForBroadcastPhase()
func (*RoundTime) ResetForConfirmPhase ¶
func (t *RoundTime) ResetForConfirmPhase()
ResetForConfirmPhase resets the ticker appropriately for begining the confirm phase (without adjustment). Be very careful to call StopTicker exactly once before calling this.
func (*RoundTime) ResetForIntentPhase ¶
func (t *RoundTime) ResetForIntentPhase()
ResetForIntentPhase resets the ticker appropriately for begining the intent phase (without adjustment). Be very careful to call StopTicker exactly once before calling this.
type RoundTimeOption ¶
type RoundTimeOption func(r *RoundTime)
type SealCommitter ¶
type SignedEndorsement ¶
type SignedEndorsement struct { Endorsement // Sig is the ecdsa signature the [R || S || V] format Sig [65]byte }
SignedEndorsement is the approval with the appropriate sig
type SignedExtraData ¶
type SignedExtraData struct { ExtraData // Sig is the ecdsa signature the [R || S || V] format Sig [65]byte }
SignedExtraData is ExtraData with signature
type SignedExtraDecoder ¶
type SignedExtraDecoder interface {
DecodeSignedExtraData(se *SignedExtraData, b []byte) ([]byte, error)
}
type SignedIntent ¶
type SignedIntent struct { Intent // Sig is the ecdsa signature the [R || S || V] format Sig [65]byte }
SignedIntent holds the Intent plus its sig
type VerifyBranchChainReader ¶
type VerifyBranchChainReader interface { // GetHeader retrieves a block header from the database by hash and number. GetHeader(hash [32]byte, number uint64) BlockHeader // GetHeaderByNumber retrieves a block header from the database by number. GetHeaderByNumber(number uint64) BlockHeader // GetHeaderByNumber retrieves a block header from the database by number. GetHeaderByHash(hash [32]byte) BlockHeader }
Source Files ¶
- activeparticipant.go
- activeselection.go
- activeselection3.go
- addrex.go
- blockactivity.go
- blockheader.go
- ciphercodec.go
- config.go
- crypto.go
- endorsement.go
- engine.go
- engmsg.go
- enrol.go
- enumstrings.go
- extra.go
- genesisextra.go
- intent.go
- logger.go
- nextround.go
- readbits.go
- roundstate.go
- roundtime.go
- sealtask.go
- verifybranch.go