Documentation ¶
Index ¶
- Constants
- Variables
- func IsStrongQuorum(part, total *StoragePower) bool
- func MakeCid(data []byte) []byte
- func ValidateMessage(powerTable *PowerTable, beacon []byte, host Host, msg *GMessage) error
- func VerifyTicket(nn NetworkName, beacon []byte, instance uint64, round uint64, source PubKey, ...) bool
- type ActorID
- type CID
- type Chain
- type ChainKey
- type Clock
- type ConvergeTicket
- type ConvergeValue
- type DecisionReceiver
- type ECChain
- func (c ECChain) Base() *TipSet
- func (c ECChain) BaseChain() ECChain
- func (c ECChain) Eq(other ECChain) bool
- func (c ECChain) Extend(tips ...TipSetKey) ECChain
- func (c ECChain) HasBase(t *TipSet) bool
- func (c ECChain) HasPrefix(other ECChain) bool
- func (c ECChain) HasTipset(t *TipSet) bool
- func (c ECChain) Head() *TipSet
- func (c ECChain) IsZero() bool
- func (c ECChain) Key() ChainKey
- func (c ECChain) Prefix(to int) ECChain
- func (c ECChain) SameBase(other ECChain) bool
- func (c ECChain) String() string
- func (c ECChain) Suffix() []TipSet
- func (c ECChain) Validate() error
- type GMessage
- type Host
- type Justification
- type MessageBuilder
- func (mb MessageBuilder) BeaconForTicket() []byte
- func (mt MessageBuilder) Build(networkName NetworkName, signer SignerWithMarshaler, id ActorID) (*GMessage, error)
- func (mb MessageBuilder) Justification() *Justification
- func (mb MessageBuilder) Payload() Payload
- func (mt MessageBuilder) PrepareSigningInputs(msh SigningMarshaler, networkName NetworkName, id ActorID) (SignatureBuilder, error)
- func (mb *MessageBuilder) SetBeaconForTicket(b []byte)
- func (mb *MessageBuilder) SetJustification(j *Justification)
- func (mb *MessageBuilder) SetPayload(p Payload)
- type MessageReceiver
- type MessageValidator
- type Network
- type NetworkName
- type Option
- type PanicError
- type Participant
- func (p *Participant) CurrentRound() uint64
- func (p *Participant) Describe() string
- func (p *Participant) ReceiveAlarm() (err error)
- func (p *Participant) ReceiveMessage(vmsg ValidatedMessage) (err error)
- func (p *Participant) Start() (err error)
- func (p *Participant) ValidateMessage(msg *GMessage) (valid ValidatedMessage, err error)
- type Payload
- type Phase
- type PowerEntries
- type PowerEntry
- type PowerTable
- func (p *PowerTable) Add(entries ...PowerEntry) error
- func (p *PowerTable) Copy() *PowerTable
- func (p *PowerTable) Get(id ActorID) (*StoragePower, PubKey)
- func (p *PowerTable) Has(id ActorID) bool
- func (p *PowerTable) Len() int
- func (p *PowerTable) Less(i, j int) bool
- func (p *PowerTable) Swap(i, j int)
- func (p *PowerTable) Validate() error
- type PubKey
- type QuorumResult
- type Receiver
- type SignatureBuilder
- type Signatures
- type Signer
- type SignerWithMarshaler
- type SigningMarshaler
- type StoragePower
- type SupplementalData
- type Ticket
- type TipSet
- type TipSetKey
- type Tracer
- type VRFHost
- type ValidatedMessage
- type Verifier
Constants ¶
const CHAIN_MAX_LEN = 100
Maximum length of a chain value.
const DOMAIN_SEPARATION_TAG = "GPBFT"
const DOMAIN_SEPARATION_TAG_VRF = "VRF"
Variables ¶
var ( ErrValidationTooOld = errors.New("message is for prior instance") ErrValidationNoCommittee = errors.New("no committee for instance") ErrValidationInvalid = errors.New("message invalid") ErrValidationWrongBase = errors.New("unexpected base chain") ErrReceivedWrongInstance = errors.New("received message for wrong instance") ErrReceivedAfterTermination = errors.New("received message after terminating") ErrReceivedInternalError = errors.New("error processing message") )
Sentinel errors for the message validation and reception APIs.
Functions ¶
func IsStrongQuorum ¶
func IsStrongQuorum(part, total *StoragePower) bool
Check whether a portion of storage power is a strong quorum of the total
func ValidateMessage ¶
func ValidateMessage(powerTable *PowerTable, beacon []byte, host Host, msg *GMessage) error
Checks message validity, including justification and signatures. An invalid message can never become valid, so may be dropped. This is a pure function and does not modify its arguments. It must be safe for concurrent use.
func VerifyTicket ¶
Types ¶
type Chain ¶
type Chain interface { // Returns the supplemental data and the chain to propose for a new GPBFT instance. // The chain must be a suffix of the chain finalised by the immediately prior instance. // The supplemental data must be derived entirely from prior instances and all participants // must propose the same supplemental data. // // Returns an error if the chain for the instance is not available. GetProposalForInstance(instance uint64) (data *SupplementalData, chain ECChain, err error) // Returns the power table and beacon value to be used for a GPBFT instance. // These values should be derived from a chain previously received as final by the host, // or known to be final via some other channel (e.g. when bootstrapping the protocol). // The offset (how many instances to look back) is determined by the host. // Returns an error if the committee for the instance is not available. GetCommitteeForInstance(instance uint64) (power *PowerTable, beacon []byte, err error) }
type Clock ¶
type Clock interface { // Returns the current network time. Time() time.Time // Sets an alarm to fire after the given timestamp. // At most one alarm can be set at a time. // Setting an alarm replaces any previous alarm that has not yet fired. // The timestamp may be in the past, in which case the alarm will fire as soon as possible // (but not synchronously). SetAlarm(at time.Time) }
type ConvergeTicket ¶
type ConvergeValue ¶
type ConvergeValue struct { Chain ECChain Justification *Justification }
type DecisionReceiver ¶
type DecisionReceiver interface { // Receives a finality decision from the instance, with signatures from a strong quorum // of participants justifying it. // The decision payload always has round = 0 and step = DECIDE. // The notification must return the timestamp at which the next instance should begin, // based on the decision received (which may be in the past). // E.g. this might be: finalised tipset timestamp + epoch duration + stabilisation delay. ReceiveDecision(decision *Justification) time.Time }
type ECChain ¶
type ECChain []TipSet
A chain of tipsets comprising a base (the last finalised tipset from which the chain extends). and (possibly empty) suffix. Tipsets are assumed to be built contiguously on each other, though epochs may be missing due to null rounds. The zero value is not a valid chain, and represents a "bottom" value when used in a Granite message.
func (ECChain) BaseChain ¶
Returns a new chain with the same base and no suffix. Invalid for a zero value.
func (ECChain) HasBase ¶
Check whether a chain has a specific base tipset. Always false for a zero value.
func (ECChain) HasPrefix ¶
Checks whether a chain has some prefix (including the base). Always false for a zero value.
func (ECChain) Head ¶
Returns the last tipset in the chain. This could be the base tipset if there is no suffix. This will panic on a zero value.
func (ECChain) Key ¶
Returns an identifier for the chain suitable for use as a map key. This must completely determine the sequence of tipsets in the chain.
func (ECChain) Prefix ¶
Returns a chain with suffix (after the base) truncated to a maximum length. Prefix(0) returns the base chain. Invalid for a zero value.
func (ECChain) SameBase ¶
Checks whether two chains have the same base. Always false for a zero value.
func (ECChain) Suffix ¶
Returns the suffix of the chain after the base. An empty slice for a zero value.
func (ECChain) Validate ¶
Validates a chain value, returning an error if it finds any issues. A chain is valid if it meets the following criteria: 1) All contained tipsets are non-empty. 2) All epochs are >= 0 and increasing. 3) The chain is not longer than CHAIN_MAX_LEN. An entirely zero-valued chain itself is deemed valid. See ECChain.IsZero.
type GMessage ¶
type GMessage struct { // ID of the sender/signer of this message (a miner actor ID). Sender ActorID // Vote is the payload that is signed by the signature Vote Payload // Signature by the sender's public key over Instance || Round || Step || Value. Signature []byte // VRF ticket for CONVERGE messages (otherwise empty byte array). Ticket Ticket // Justification for this message (some messages must be justified by a strong quorum of messages from some previous step). Justification *Justification }
A message in the Granite protocol. The same message structure is used for all rounds and phases. Note that the message is self-attesting so no separate envelope or signature is needed. - The signature field fixes the included sender ID via the implied public key; - The signature payload includes all fields a sender can freely choose; - The ticket field is a signature of the same public key, so also self-attesting.
type Host ¶
type Host interface { Chain Network Clock Signatures DecisionReceiver }
Participant interface to the host system resources.
type Justification ¶
type Justification struct { // Vote is the payload that is signed by the signature Vote Payload // Indexes in the base power table of the signers (bitset) Signers bitfield.BitField // BLS aggregate signature of signers Signature []byte }
func (*Justification) MarshalCBOR ¶
func (t *Justification) MarshalCBOR(w io.Writer) error
func (*Justification) UnmarshalCBOR ¶
func (t *Justification) UnmarshalCBOR(r io.Reader) (err error)
type MessageBuilder ¶
type MessageBuilder struct {
// contains filtered or unexported fields
}
func NewMessageBuilder ¶
func NewMessageBuilder(powerTable powerTableAccessor) MessageBuilder
NewMessageBuilder creates a new message builder with the provided beacon for ticket, justification and payload.
func NewMessageBuilderWithPowerTable ¶
func NewMessageBuilderWithPowerTable(power *PowerTable) MessageBuilder
NewMessageBuilderWithPowerTable allows to create a new message builder from an existing power table.
This is needed to sign forged messages in adversary hosts
func (MessageBuilder) BeaconForTicket ¶
func (mb MessageBuilder) BeaconForTicket() []byte
func (MessageBuilder) Build ¶
func (mt MessageBuilder) Build(networkName NetworkName, signer SignerWithMarshaler, id ActorID) (*GMessage, error)
Build uses the builder and a signer interface to build GMessage It is a shortcut for when separated flow is not required
func (MessageBuilder) Justification ¶
func (mb MessageBuilder) Justification() *Justification
func (MessageBuilder) Payload ¶
func (mb MessageBuilder) Payload() Payload
func (MessageBuilder) PrepareSigningInputs ¶
func (mt MessageBuilder) PrepareSigningInputs(msh SigningMarshaler, networkName NetworkName, id ActorID) (SignatureBuilder, error)
func (*MessageBuilder) SetBeaconForTicket ¶
func (mb *MessageBuilder) SetBeaconForTicket(b []byte)
SetBeaconForTicket sets the beacon for the ticket in the message builder.
func (*MessageBuilder) SetJustification ¶
func (mb *MessageBuilder) SetJustification(j *Justification)
SetJustification sets the justification in the message builder.
func (*MessageBuilder) SetPayload ¶
func (mb *MessageBuilder) SetPayload(p Payload)
SetPayload sets the payload in the message builder.
type MessageReceiver ¶
type MessageReceiver interface { // Receives a validated Granite message from some other participant. // Returns an error, wrapping (use errors.Is()/Unwrap()): // - ErrValidationTooOld if the message is for a prior instance // - ErrValidationWrongBase if the message has an invalid base chain // - ErrReceivedAfterTermination if the message is received after the instance has terminated (a programming error) // - both ErrReceivedInternalError and a cause if there was an internal error processing the message // This method is not safe for concurrent use. ReceiveMessage(msg ValidatedMessage) error // This method is not safe for concurrent use. ReceiveAlarm() error }
Receives a Granite protocol message.
type MessageValidator ¶
type MessageValidator interface { // Validates a Granite message. // An invalid message can never become valid, so may be dropped. // Returns an error, wrapping (use errors.Is()/Unwrap()): // - ErrValidationTooOld if the message is for a prior instance; // - both ErrValidationNoCommittee and an error describing the reason; // if there is no committee available with with to validate the message; // - both ErrValidationInvalid and a cause if the message is invalid, // Returns a validated message if the message is valid. // // Implementations must be safe for concurrent use. ValidateMessage(msg *GMessage) (valid ValidatedMessage, err error) }
type Network ¶
type Network interface { // Returns the network's name (for signature separation) NetworkName() NetworkName // Requests that the message is signed and broadcasted, it should also be delivered locally RequestBroadcast(mb *MessageBuilder) error }
Endpoint to which participants can send messages.
type NetworkName ¶
type NetworkName string
NetworkName provides separation between different networks it is implicitly included in all signatures and VRFs
func (NetworkName) DatastorePrefix ¶
func (nn NetworkName) DatastorePrefix() datastore.Key
func (NetworkName) PubSubTopic ¶
func (nn NetworkName) PubSubTopic() string
type Option ¶
type Option func(*options) error
Option represents a configurable parameter.
func WithDelta ¶
WithDelta sets the expected bound on message propagation latency. Defaults to 3 seconds if unspecified. Delta must be larger than zero.
The default of 3 seconds for the value of Dela is based previous observations of the upper bound on the GossipSub network-wide propagation time in Filecoin network.
func WithDeltaBackOffExponent ¶
WithDeltaBackOffExponent sets the delta back-off exponent for each round. Defaults to 1.3 if unspecified. It must be larger than zero.
func WithInitialInstance ¶
WithInitialInstance sets the first instance number. Defaults to zero if unspecified.
func WithMaxLookaheadRounds ¶
WithMaxLookaheadRounds sets the maximum number of rounds ahead of the current round for which messages without justification are buffered. Setting a max value of larger than zero would aid gPBFT to potentially reach consensus in fewer rounds during periods of asynchronous broadcast as well as re-broadcast. Defaults to zero if unset.
func WithTracer ¶
WithTracer sets the Tracer for this gPBFT instance, which receives diagnostic logs about the state mutation. Defaults to no tracer if unspecified.
type PanicError ¶
type PanicError struct {
Err any
}
func (*PanicError) Error ¶
func (e *PanicError) Error() string
type Participant ¶
type Participant struct {
// contains filtered or unexported fields
}
An F3 participant runs repeated instances of Granite to finalise longer chains.
func NewParticipant ¶
func NewParticipant(host Host, o ...Option) (*Participant, error)
func (*Participant) CurrentRound ¶
func (p *Participant) CurrentRound() uint64
func (*Participant) Describe ¶
func (p *Participant) Describe() string
func (*Participant) ReceiveAlarm ¶
func (p *Participant) ReceiveAlarm() (err error)
func (*Participant) ReceiveMessage ¶
func (p *Participant) ReceiveMessage(vmsg ValidatedMessage) (err error)
Receives a validated Granite message from some other participant.
func (*Participant) Start ¶
func (p *Participant) Start() (err error)
Fetches the preferred EC chain for the instance and begins the GPBFT protocol.
func (*Participant) ValidateMessage ¶
func (p *Participant) ValidateMessage(msg *GMessage) (valid ValidatedMessage, err error)
Validates a message
type Payload ¶
type Payload struct { // GossiPBFT instance (epoch) number. Instance uint64 // GossiPBFT round number. Round uint64 // GossiPBFT step name. Step Phase // The common data. SupplementalData SupplementalData // The value agreed-upon in a single instance. Value ECChain }
Fields of the message that make up the signature payload.
func (*Payload) MarshalForSigning ¶
func (p *Payload) MarshalForSigning(nn NetworkName) []byte
type PowerEntries ¶
type PowerEntries []PowerEntry
func (PowerEntries) Len ¶
func (p PowerEntries) Len() int
Len returns the number of entries in this PowerTable.
func (PowerEntries) Less ¶
func (p PowerEntries) Less(i, j int) bool
Less determines if the entry at index i should be sorted before the entry at index j. Entries are sorted descending order of their power, where entries with equal power are sorted by ascending order of their ID. This ordering is guaranteed to be stable, since a valid PowerTable cannot contain entries with duplicate IDs; see Validate.
func (*PowerEntries) MarshalCBOR ¶
func (t *PowerEntries) MarshalCBOR(w io.Writer) error
func (PowerEntries) Swap ¶
func (p PowerEntries) Swap(i, j int)
Swap swaps the entry at index i with the entry at index j. This function must not be called directly since it is used as part of sort.Interface.
func (*PowerEntries) UnmarshalCBOR ¶
func (t *PowerEntries) UnmarshalCBOR(r io.Reader) (err error)
type PowerEntry ¶
type PowerEntry struct { ID ActorID Power *StoragePower PubKey PubKey }
PowerEntry represents a single entry in the PowerTable, including ActorID and its StoragePower and PubKey.
func (*PowerEntry) MarshalCBOR ¶
func (t *PowerEntry) MarshalCBOR(w io.Writer) error
func (*PowerEntry) UnmarshalCBOR ¶
func (t *PowerEntry) UnmarshalCBOR(r io.Reader) (err error)
type PowerTable ¶
type PowerTable struct { Entries PowerEntries // Slice to maintain the order. Meant to be maintained in order in order by (Power descending, ID ascending) Lookup map[ActorID]int // Maps ActorID to the index of the associated entry in Entries Total *StoragePower }
PowerTable maps ActorID to a unique index in the range [0, len(powerTable.Entries)). Entries is the reverse mapping to a PowerEntry.
func NewPowerTable ¶
func NewPowerTable() *PowerTable
NewPowerTable creates a new PowerTable from a slice of PowerEntry . It is more efficient than Add, as it only needs to sort the entries once. Note that the function takes ownership of the slice - it must not be modified afterwards.
func (*PowerTable) Add ¶
func (p *PowerTable) Add(entries ...PowerEntry) error
Add inserts one or more entries to this PowerTable.
Each inserted entry must meet the following criteria: * It must not already be present int the PowerTable. * It must have StoragePower larger than zero. * It must have a non-zero length public key.
func (*PowerTable) Copy ¶
func (p *PowerTable) Copy() *PowerTable
Copy creates a deep copy of this PowerTable.
func (*PowerTable) Get ¶
func (p *PowerTable) Get(id ActorID) (*StoragePower, PubKey)
Get retrieves the StoragePower and PubKey for the given id, if present in the table. Otherwise, returns nil.
func (*PowerTable) Has ¶
func (p *PowerTable) Has(id ActorID) bool
Has check whether this PowerTable contains an entry for the given id.
func (*PowerTable) Len ¶
func (p *PowerTable) Len() int
Len returns the number of entries in this PowerTable.
func (*PowerTable) Less ¶
func (p *PowerTable) Less(i, j int) bool
Less determines if the entry at index i should be sorted before the entry at index j. Entries are sorted descending order of their power, where entries with equal power are sorted by ascending order of their ID. This ordering is guaranteed to be stable, since a valid PowerTable cannot contain entries with duplicate IDs; see Validate.
func (*PowerTable) Swap ¶
func (p *PowerTable) Swap(i, j int)
Swap swaps the entry at index i with the entry at index j. This function must not be called directly since it is used as part of sort.Interface.
func (*PowerTable) Validate ¶
func (p *PowerTable) Validate() error
Validate checks the validity of this PowerTable. Such table must meet the following criteria: * Its entries must be in order as defined by Less. * It must not contain any entries with duplicate ID. * All entries must have power larger than zero * All entries must have non-zero public key. * PowerTable.Total must correspond to the total aggregated power of entries. * PowerTable.Lookup must contain the expected mapping of entry actor ID to index.
type QuorumResult ¶
type QuorumResult struct { // Signers is an array of indexes into the powertable, sorted in increasing order Signers []int PubKeys []PubKey Signatures [][]byte }
func (QuorumResult) SignersBitfield ¶
func (q QuorumResult) SignersBitfield() bitfield.BitField
type Receiver ¶
type Receiver interface { // Begins executing the protocol. // The node will request the canonical chain to propose from the host. Start() error MessageValidator MessageReceiver }
Interface which network participants must implement.
type SignatureBuilder ¶
type SignatureBuilder struct { NetworkName NetworkName // contains filtered or unexported fields }
func (*SignatureBuilder) Justification ¶
func (sb *SignatureBuilder) Justification() *Justification
func (*SignatureBuilder) ParticipantID ¶
func (sb *SignatureBuilder) ParticipantID() ActorID
func (*SignatureBuilder) Payload ¶
func (sb *SignatureBuilder) Payload() Payload
func (*SignatureBuilder) PayloadToSign ¶
func (sb *SignatureBuilder) PayloadToSign() []byte
func (*SignatureBuilder) PubKey ¶
func (sb *SignatureBuilder) PubKey() PubKey
func (*SignatureBuilder) VRFToSign ¶
func (sb *SignatureBuilder) VRFToSign() []byte
type Signatures ¶
type Signatures interface { SigningMarshaler Signer Verifier }
type SignerWithMarshaler ¶
type SignerWithMarshaler interface { Signer SigningMarshaler }
type SigningMarshaler ¶
type SigningMarshaler interface { // MarshalPayloadForSigning marshals the given payload into the bytes that should be signed. // This should usually call `Payload.MarshalForSigning(NetworkName)` except when testing as // that method is slow (computes a merkle tree that's necessary for testing). // Implementations must be safe for concurrent use. MarshalPayloadForSigning(NetworkName, *Payload) []byte }
type StoragePower ¶
func NewStoragePower ¶
func NewStoragePower(value int64) *StoragePower
Creates a new StoragePower struct with a specific value and returns the result
type SupplementalData ¶
type SupplementalData struct { // Merkle-tree of instance-specific commitments. Currently empty but this will eventually // include things like snark-friendly power-table commitments. Commitments [32]byte // The DagCBOR-blake2b256 CID of the power table used to validate the next instance, taking // lookback into account. PowerTable CID // []PowerEntry }
func (*SupplementalData) Eq ¶
func (d *SupplementalData) Eq(other *SupplementalData) bool
func (*SupplementalData) MarshalCBOR ¶
func (t *SupplementalData) MarshalCBOR(w io.Writer) error
func (*SupplementalData) UnmarshalCBOR ¶
func (t *SupplementalData) UnmarshalCBOR(r io.Reader) (err error)
type Ticket ¶
type Ticket []byte
A ticket is a signature over some common payload.
func MakeTicket ¶
type TipSet ¶
type TipSet struct { // The EC epoch (strictly increasing). Epoch int64 // The tipset's key (canonically ordered concatenated block-header CIDs). Key TipSetKey // Blake2b256-32 CID of the CBOR-encoded power table. PowerTable CID // []PowerEntry // Keccak256 root hash of the commitments merkle tree. Commitments [32]byte }
TipSet represents a single EC tipset.
func (*TipSet) MarshalForSigning ¶
type TipSetKey ¶
type TipSetKey = []byte
TipSetKey is the canonically ordered concatenation of the block CIDs in a tipset.
type Tracer ¶
Tracer collects trace logs that capture logical state changes. The primary purpose of Tracer is to aid debugging and simulation.
type ValidatedMessage ¶
type ValidatedMessage interface { // Returns the validated message. Message() *GMessage }
Opaque type tagging a validated message.
type Verifier ¶
type Verifier interface { // Verifies a signature for the given public key. // Implementations must be safe for concurrent use. Verify(pubKey PubKey, msg, sig []byte) error // Aggregates signatures from a participants. Aggregate(pubKeys []PubKey, sigs [][]byte) ([]byte, error) // VerifyAggregate verifies an aggregate signature. // Implementations must be safe for concurrent use. VerifyAggregate(payload, aggSig []byte, signers []PubKey) error }