Documentation ¶
Overview ¶
Package modules contains the module system used in the hotstuff project. The module system allows us to use different implementations of key components, such as the crypto module or the consensus module, and ensures that each module has access to the other modules it depends on.
There are two main reason one might want to use the module system for a component:
1. To give the component access to other modules.
2. To give other modules access to the component.
To be able to access other modules from a struct, you will need to implement the Module interface from this package. The InitModule method of the Module interface gives your struct a pointer to the Core object, which can be used to obtain pointers to the other modules. If your module will be interacting with the event loop, then this method is the preferred location to set up handlers for events.
Finally, to set up the module system and its modules, you must create a Builder using the NewBuilder function, and then all your modules to the builder using the Add method. For example:
builder := NewBuilder() // replace the logger builder.Add(logging.New("foo")) mods := builder.Build()
If two modules satisfy the same interface, then the one that was registered last will be returned by the module system, though note that both modules will be initialized if they implement the Module interface.
After building the module system, you can use the TryGet or Get methods to get pointers to the modules:
var module MyModule mods.Get(&module)
Index ¶
- func GetModule[T any](name string) (out T, ok bool)
- func GetModuleUntyped(name string) (m any, ok bool)
- func ListModules() map[string][]string
- func RegisterModule[T any](name string, constructor func() T)
- type Acceptor
- type BlockChain
- type Builder
- type CommandQueue
- type Configuration
- type Consensus
- type Core
- type Crypto
- type CryptoBase
- type Executor
- type ExecutorExt
- type ForkHandler
- type ForkHandlerExt
- type Handel
- type LeaderRotation
- type Module
- type OptionID
- type Options
- func (opts *Options) ConnectionMetadata() map[string]string
- func (opts *Options) Get(id OptionID) any
- func (opts *Options) ID() consbench.ID
- func (opts *Options) PrivateKey() consbench.PrivateKey
- func (opts *Options) Set(id OptionID, value any)
- func (opts *Options) SetConnectionMetadata(key string, value string)
- func (opts *Options) SetSharedRandomSeed(seed int64)
- func (opts *Options) SetShouldUseAggQC()
- func (opts *Options) SetShouldUseHandel()
- func (opts *Options) SetShouldVerifyVotesSync()
- func (opts *Options) SharedRandomSeed() int64
- func (opts *Options) ShouldUseAggQC() bool
- func (opts *Options) ShouldUseHandel() bool
- func (opts *Options) ShouldVerifyVotesSync() bool
- type Replica
- type Synchronizer
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetModule ¶
GetModule constructs a new instance of the module with the specified name. GetModule returns true if the module is found, false otherwise. For example:
rules, ok := GetModule[consensus.Rules]("chainedhotstuff")
func GetModuleUntyped ¶
GetModuleUntyped returns a new instance of the named module, if it exists.
func ListModules ¶
ListModules returns a map of interface names to module names.
func RegisterModule ¶
RegisterModule registers a constructor for a module implementation with the specified name. For example:
RegisterModule("chainedhotstuff", func() consensus.Rules { return chainedhotstuff.New() })
Types ¶
type Acceptor ¶
type Acceptor interface { // Accept returns true if the replica should accept the command, false otherwise. Accept(consbench.Command) bool // Proposed tells the acceptor that the propose phase for the given command succeeded, and it should no longer be // accepted in the future. Proposed(consbench.Command) }
Acceptor decides if a replica should accept a command.
type BlockChain ¶
type BlockChain interface { // Store stores a block in the blockchain. Store(*consbench.Block) // Get retrieves a block given its hash, attempting to fetching it from other replicas if necessary. Get(consbench.Hash) (*consbench.Block, bool) // LocalGet retrieves a block given its hash, without fetching it from other replicas. LocalGet(consbench.Hash) (*consbench.Block, bool) // Extends checks if the given block extends the branch of the target hash. Extends(block, target *consbench.Block) bool // Prunes blocks from the in-memory tree up to the specified height. // Returns a set of forked blocks (blocks that were on a different branch, and thus not committed). PruneToHeight(height consbench.View) (forkedBlocks []*consbench.Block) }
BlockChain is a datastructure that stores a chain of blocks. It is not required that a block is stored forever, but a block must be stored until at least one of its children have been committed.
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder is a helper for setting up client modules.
func NewBuilder ¶
func NewBuilder(id consbench.ID, pk consbench.PrivateKey) Builder
NewBuilder returns a new builder.
type CommandQueue ¶
type CommandQueue interface { // Get returns the next command to be proposed. // It may run until the context is canceled. // If no command is available, the 'ok' return value should be false. Get(ctx context.Context) (cmd consbench.Command, ok bool) }
CommandQueue is a queue of commands to be proposed.
type Configuration ¶
type Configuration interface { // Replicas returns all of the replicas in the configuration. Replicas() map[consbench.ID]Replica // Replica returns a replica if present in the configuration. Replica(consbench.ID) (replica Replica, ok bool) // Len returns the number of replicas in the configuration. Len() int // QuorumSize returns the size of a quorum. QuorumSize() int // Propose sends the block to all replicas in the configuration. Propose(proposal consbench.ProposeMsg) // Timeout sends the timeout message to all replicas. Timeout(msg consbench.TimeoutMsg) // Fetch requests a block from all the replicas in the configuration. Fetch(ctx context.Context, hash consbench.Hash) (block *consbench.Block, ok bool) // SubConfig returns a subconfiguration containing the replicas specified in the ids slice. SubConfig(ids []consbench.ID) (sub Configuration, err error) }
Configuration holds information about the current configuration of replicas that participate in the protocol, It provides methods to send messages to the other replicas.
type Consensus ¶
type Consensus interface { // StopVoting ensures that no voting happens in a view earlier than `view`. StopVoting(view consbench.View) // Propose starts a new proposal. The command is fetched from the command queue. Propose(cert consbench.SyncInfo) // CommittedBlock returns the most recently committed block. CommittedBlock() *consbench.Block // ChainLength returns the number of blocks that need to be chained together in order to commit. ChainLength() int }
Consensus implements a byzantine consensus protocol, such as HotStuff. It contains the protocol data for a single replica. The methods OnPropose, OnVote, OnNewView, and OnDeliver should be called upon receiving a corresponding message.
type Core ¶
type Core struct {
// contains filtered or unexported fields
}
Core is the base of the module system. It contains only a few core modules that are shared between replicas and clients.
func (*Core) Get ¶
Get finds compatible modules for the given pointers.
NOTE: pointers must only contain non-nil pointers to types that have been provided to the module system. Get panics if one of the given arguments is not a pointer, or if a compatible module is not found.
Example:
builder := modules.New() builder.Add(MyModuleImpl{}) mods = builder.Build() var module MyModule mods.Get(&module)
func (Core) TryGet ¶
TryGet attempts to find a module for ptr. TryGet returns true if a module was stored in ptr, false otherwise.
NOTE: ptr must be a non-nil pointer to a type that has been provided to the module system.
Example:
builder := modules.New() builder.Add(MyModuleImpl{}) mods = builder.Build() var module MyModule if mods.TryGet(&module) { // success }
type Crypto ¶
type Crypto interface { CryptoBase // CreatePartialCert signs a single block and returns the partial certificate. CreatePartialCert(block *consbench.Block) (cert consbench.PartialCert, err error) // CreateQuorumCert creates a quorum certificate from a list of partial certificates. CreateQuorumCert(block *consbench.Block, signatures []consbench.PartialCert) (cert consbench.QuorumCert, err error) // CreateTimeoutCert creates a timeout certificate from a list of timeout messages. CreateTimeoutCert(view consbench.View, timeouts []consbench.TimeoutMsg) (cert consbench.TimeoutCert, err error) // CreateAggregateQC creates an AggregateQC from the given timeout messages. CreateAggregateQC(view consbench.View, timeouts []consbench.TimeoutMsg) (aggQC consbench.AggregateQC, err error) // VerifyPartialCert verifies a single partial certificate. VerifyPartialCert(cert consbench.PartialCert) bool // VerifyQuorumCert verifies a quorum certificate. VerifyQuorumCert(qc consbench.QuorumCert) bool // VerifyTimeoutCert verifies a timeout certificate. VerifyTimeoutCert(tc consbench.TimeoutCert) bool // VerifyAggregateQC verifies an AggregateQC. VerifyAggregateQC(aggQC consbench.AggregateQC) (highQC consbench.QuorumCert, ok bool) }
Crypto implements the methods required to create and verify signatures and certificates. This is a higher level interface that is implemented by the crypto package itself.
type CryptoBase ¶
type CryptoBase interface { // Sign creates a cryptographic signature of the given message. Sign(message []byte) (signature consbench.QuorumSignature, err error) // Combine combines multiple signatures into a single signature. Combine(signatures ...consbench.QuorumSignature) (signature consbench.QuorumSignature, err error) // Verify verifies the given quorum signature against the message. Verify(signature consbench.QuorumSignature, message []byte) bool // BatchVerify verifies the given quorum signature against the batch of messages. BatchVerify(signature consbench.QuorumSignature, batch map[consbench.ID][]byte) bool }
CryptoBase provides the basic cryptographic methods needed to create, verify, and combine signatures.
type Executor ¶
Executor is responsible for executing the commands that are committed by the consensus protocol.
type ExecutorExt ¶
type ExecutorExt interface { // Exec executes the command in the block. Exec(block *consbench.Block) }
ExecutorExt is responsible for executing the commands that are committed by the consensus protocol.
This interface is similar to the Executor interface, except it takes a block as an argument, instead of a command, making it more flexible than the alternative interface.
func ExtendedExecutor ¶
func ExtendedExecutor(executor Executor) ExecutorExt
ExtendedExecutor turns the given Executor into an ExecutorExt.
type ForkHandler ¶
type ForkHandler interface { // Fork handles the command from a forked block. Fork(cmd consbench.Command) }
ForkHandler handles commands that do not get committed due to a forked blockchain.
TODO: think of a better name/interface
type ForkHandlerExt ¶
ForkHandlerExt handles blocks that do not get committed due to a fork of the blockchain.
This interface is similar to the ForkHandler interface, except it takes a block as an argument, instead of a command.
func ExtendedForkHandler ¶
func ExtendedForkHandler(forkHandler ForkHandler) ForkHandlerExt
ExtendedForkHandler turns the given ForkHandler into a ForkHandlerExt.
type Handel ¶
type Handel interface { // Begin commissions the aggregation of a new signature. Begin(s consbench.PartialCert) }
Handel is an implementation of the Handel signature aggregation protocol.
type LeaderRotation ¶
type LeaderRotation interface { // GetLeader returns the id of the leader in the given view. GetLeader(consbench.View) consbench.ID }
LeaderRotation implements a leader rotation scheme.
type Module ¶
type Module interface {
InitModule(mods *Core)
}
Module is an interface for initializing modules.
type Options ¶
type Options struct {
// contains filtered or unexported fields
}
Options stores runtime configuration settings.
func (*Options) ConnectionMetadata ¶
ConnectionMetadata returns the metadata map that is sent when connecting to other replicas.
func (*Options) PrivateKey ¶
func (opts *Options) PrivateKey() consbench.PrivateKey
PrivateKey returns the private key.
func (*Options) SetConnectionMetadata ¶
SetConnectionMetadata sets the value of a key in the connection metadata map.
NOTE: if the value contains binary data, the key must have the "-bin" suffix. This is to make it compatible with GRPC metadata. See: https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#storing-binary-data-in-metadata
func (*Options) SetSharedRandomSeed ¶
SetSharedRandomSeed sets the shared random seed.
func (*Options) SetShouldUseAggQC ¶
func (opts *Options) SetShouldUseAggQC()
SetShouldUseAggQC sets the ShouldUseAggQC setting to true.
func (*Options) SetShouldUseHandel ¶
func (opts *Options) SetShouldUseHandel()
SetShouldUseHandel sets the ShouldUseHandel setting to true.
func (*Options) SetShouldVerifyVotesSync ¶
func (opts *Options) SetShouldVerifyVotesSync()
SetShouldVerifyVotesSync sets the ShouldVerifyVotesSync setting to true.
func (*Options) SharedRandomSeed ¶
SharedRandomSeed returns a random number that is shared between all replicas.
func (*Options) ShouldUseAggQC ¶
ShouldUseAggQC returns true if aggregated quorum certificates should be used. This is true for Fast-Hotstuff: https://arxiv.org/abs/2010.11454
func (*Options) ShouldUseHandel ¶
ShouldUseHandel returns true if the Handel signature aggregation protocol should be used.
func (*Options) ShouldVerifyVotesSync ¶
ShouldVerifyVotesSync returns true if votes should be verified synchronously. Enabling this should make the voting machine process votes synchronously.
type Replica ¶
type Replica interface { // ID returns the replica's id. ID() consbench.ID // PublicKey returns the replica's public key. PublicKey() consbench.PublicKey // Vote sends the partial certificate to the other replica. Vote(cert consbench.PartialCert) // NewView sends the quorum certificate to the other replica. NewView(consbench.SyncInfo) // Metadata returns the connection metadata sent by this replica. Metadata() map[string]string }
Replica represents a remote replica participating in the consensus protocol. The methods Vote, NewView, and Deliver must send the respective arguments to the remote replica.
type Synchronizer ¶
type Synchronizer interface { // AdvanceView attempts to advance to the next view using the given QC. // qc must be either a regular quorum certificate, or a timeout certificate. AdvanceView(consbench.SyncInfo) // View returns the current view. View() consbench.View // HighQC returns the highest known QC. HighQC() consbench.QuorumCert // Start starts the synchronizer with the given context. Start(context.Context) }
Synchronizer synchronizes replicas to the same view.