gpbft

package
v0.0.0-...-7eaa6d1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 29, 2024 License: Apache-2.0, MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

View Source
const DOMAIN_SEPARATION_TAG = "GPBFT"
View Source
const DOMAIN_SEPARATION_TAG_VRF = "VRF"

Variables

View Source
var ErrECChainNotAcceptable = errors.New("ec chain is not acceptable")

ErrECChainNotAcceptable signals that ECChain is not acceptable by gpbft instance, due to mismatching prefix.

Functions

func VerifyTicket

func VerifyTicket(beacon []byte, instance uint64, round uint64, source PubKey, host VRFHost, ticket Ticket) bool

Types

type ActorID

type ActorID uint64

type ActorTicket

type ActorTicket struct {
	Actor  ActorID
	Ticket Ticket
}

type Chain

type Chain interface {
	// Returns the best EC chain, and the power table and beacon value for its base.
	// These will be used as input to a subsequent instance of the protocol.
	GetCanonicalChain() (chain ECChain, power PowerTable, beacon []byte)
}

type ChainKey

type ChainKey string

A map key for a chain. The zero value means "bottom".

type ChainReceiver

type ChainReceiver interface {
	// ReceiveECChain processes an incoming EC chain update. It assesses whether the new chain
	// extends or is compatible with the currently accepted chain maintained by the instance.
	//
	//Returns ErrECChainNotAcceptable error if the chain was not accepted. Otherwise, an error
	// is returned if the chain is invalid.
	ReceiveECChain(chain ECChain) error
}

ChainReceiver defines the interface for receiving updates to an Expected Consensus (EC) chain. Implementers of this interface can act upon received EC chain data, potentially considering the given chain as the expected consensus chain in the current GPBFT instance.

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 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 NewChain

func NewChain(base TipSet, suffix ...TipSet) (ECChain, error)

Creates a new chain.

func (ECChain) Base

func (c ECChain) Base() TipSet

Returns the base tipset.

func (ECChain) BaseChain

func (c ECChain) BaseChain() ECChain

Returns a new chain with the same base and no suffix. Invalid for a zero value.

func (ECChain) Eq

func (c ECChain) Eq(other ECChain) bool

Compares two ECChains for equality.

func (ECChain) Extend

func (c ECChain) Extend(tip TipSet) ECChain

func (ECChain) HasBase

func (c ECChain) HasBase(t TipSet) bool

Check whether a chain has a specific base tipset. Always false for a zero value.

func (ECChain) HasPrefix

func (c ECChain) HasPrefix(other ECChain) bool

Checks whether a chain has some prefix (including the base). Always false for a zero value.

func (ECChain) HasTipset

func (c ECChain) HasTipset(t TipSet) bool

Checks whether a chain has some tipset (including as its base).

func (ECChain) Head

func (c ECChain) Head() TipSet

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) IsZero

func (c ECChain) IsZero() bool

func (ECChain) Key

func (c ECChain) Key() ChainKey

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

func (c ECChain) Prefix(to int) ECChain

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

func (c ECChain) SameBase(other ECChain) bool

Checks whether two chains have the same base. Always false for a zero value.

func (ECChain) String

func (c ECChain) String() string

func (ECChain) Suffix

func (c ECChain) Suffix() []TipSet

Returns the suffix of the chain after the base. An empty slice for a zero value.

func (ECChain) Validate

func (c ECChain) Validate() error

Validate verifies the integrity of the chain, returning an error if it finds any issues. A chain is valid if it meets the following criteria: 1) All contained elements have non-zero values. Use TipSet.IsZero to check for zero-valued elements. 2) TipSets are arranged in strictly increasing order by their epochs, without any repetitions. 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.

func (*GMessage) MarshalCBOR

func (t *GMessage) MarshalCBOR(w io.Writer) error

func (GMessage) String

func (m GMessage) String() string

func (*GMessage) UnmarshalCBOR

func (t *GMessage) UnmarshalCBOR(r io.Reader) (err error)

type GraniteConfig

type GraniteConfig struct {
	// Expected bound on message propagation latency.
	Delta time.Duration
	// Delta back-off exponent for the round.
	DeltaBackOffExponent float64
}

type Host

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 MessageReceiver

type MessageReceiver interface {
	// Validates a message received from another participant, if possible.
	// Returns whether the message could be validated, and an error if it was invalid.
	ValidateMessage(msg *GMessage) (bool, error)
	// Receives a message from another participant.
	// The `validated` parameter indicates whether the message has already passed validation.
	ReceiveMessage(msg *GMessage, validated bool) (bool, error)
	ReceiveAlarm() error
}

Receives a Granite protocol message.

type Network

type Network interface {
	// Returns the network's name (for signature separation)
	NetworkName() NetworkName
	// Sends a message to all other participants.
	// The message's sender must be one that the network interface can sign on behalf of.
	Broadcast(msg *GMessage)
}

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 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(id ActorID, config GraniteConfig, host Host, tracer Tracer, instance uint64) *Participant

func (*Participant) CurrentRound

func (p *Participant) CurrentRound() uint64

func (*Participant) Describe

func (p *Participant) Describe() string

func (*Participant) ID

func (p *Participant) ID() ActorID

func (*Participant) ReceiveAlarm

func (p *Participant) ReceiveAlarm() (err error)

func (*Participant) ReceiveECChain

func (p *Participant) ReceiveECChain(chain ECChain) (err error)

Receives a new EC chain, and notifies the current instance. This may modify the set of valid values for the current instance.

func (*Participant) ReceiveMessage

func (p *Participant) ReceiveMessage(msg *GMessage, validated bool) (accepted bool, err error)

Receives a Granite message from some other participant. If the message is for the current instance, it is delivered immediately. If it is for a future instance, it is locally queued, to be delivered when that instance begins. If it is for a previous instance, it is dropped.

This method checks message validity only if the validated parameter is false. Validity can only be checked when the messages instance begins. Returns whether the message was for the current instance, and an error if it was invalid or could not be processed.

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) (checked bool, err error)

Validates a message received from another participant, if possible. An invalid message can never become valid, so may be dropped. A message can only be validated if it is for the currently-executing protocol instance. Returns whether the message could be validated, and an error if it was invalid.

type Payload

type Payload struct {
	// GossiPBFT instance (epoch) number.
	Instance uint64
	// GossiPBFT round number.
	Round uint64
	// GossiPBFT step name.
	Step Phase
	// Chain of tipsets proposed/voted for finalisation.
	// Always non-empty; the first entry is the base tipset finalised in the previous instance.
	Value ECChain
}

Fields of the message that make up the signature payload.

func (Payload) Eq

func (p Payload) Eq(other *Payload) bool

func (*Payload) MarshalCBOR

func (t *Payload) MarshalCBOR(w io.Writer) error

func (Payload) MarshalForSigning

func (p Payload) MarshalForSigning(nn NetworkName) []byte

func (*Payload) UnmarshalCBOR

func (t *Payload) UnmarshalCBOR(r io.Reader) (err error)

type Phase

type Phase uint8
const (
	INITIAL_PHASE Phase = iota
	QUALITY_PHASE
	CONVERGE_PHASE
	PREPARE_PHASE
	COMMIT_PHASE
	DECIDE_PHASE
	TERMINATED_PHASE
)

func (Phase) String

func (p Phase) String() string

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.

type PowerTable

type PowerTable struct {
	Entries []PowerEntry    // 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 PubKey

type PubKey []byte

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) Aggregate

func (q QuorumResult) Aggregate(v Verifier) ([]byte, error)

func (QuorumResult) SignersBitfield

func (q QuorumResult) SignersBitfield() bitfield.BitField

type Receiver

type Receiver interface {
	ID() ActorID
	// Begins executing the protocol.
	// The node will request the canonical chain to propose from the host.
	Start() error
	ChainReceiver
	MessageReceiver
}

Interface which network participants must implement.

type Signer

type Signer interface {
	// Signs a message with the secret key corresponding to a public key.
	Sign(sender PubKey, msg []byte) ([]byte, error)
}

type StoragePower

type StoragePower = big.Int

func NewStoragePower

func NewStoragePower(value int64) *StoragePower

Creates a new StoragePower struct with a specific value and returns the result

type Ticket

type Ticket []byte

A ticket is a signature over some common payload.

func MakeTicket

func MakeTicket(beacon []byte, instance uint64, round uint64, source PubKey, host VRFHost) (Ticket, error)

func (Ticket) Compare

func (t Ticket) Compare(other Ticket) int

type TipSet

type TipSet = []byte

Opaque type representing a tipset. This is expected to be: - a canonical sequence of CIDs of block headers identifying a tipset, - a commitment to the resulting power table, - a commitment to additional derived values. However, GossipPBFT doesn't need to know anything about that structure.

type Tracer

type Tracer interface {
	Log(format string, args ...any)
}

Tracer collects trace logs that capture logical state changes. The primary purpose of Tracer is to aid debugging and simulation.

type VRFHost

type VRFHost interface {
	Network
	Signer
	Verifier
}

type Verifier

type Verifier interface {
	// Verifies a signature for the given public key
	Verify(pubKey PubKey, msg, sig []byte) error
	// Aggregates signatures from a participants
	Aggregate(pubKeys []PubKey, sigs [][]byte) ([]byte, error)
	// VerifyAggregate verifies an aggregate signature.
	VerifyAggregate(payload, aggSig []byte, signers []PubKey) error
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL