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 Kauri
- 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() hotstuff.ID
- func (opts *Options) PrivateKey() hotstuff.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) SetShouldUseTree()
- func (opts *Options) SetShouldVerifyVotesSync()
- func (opts *Options) SetTree(t tree.Tree)
- func (opts *Options) SharedRandomSeed() int64
- func (opts *Options) ShouldUseAggQC() bool
- func (opts *Options) ShouldUseTree() bool
- func (opts *Options) ShouldVerifyVotesSync() bool
- func (opts *Options) Tree() tree.Tree
- type Replica
- type Synchronizer
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetModule ¶ added in v0.4.0
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 ¶ added in v0.5.0
GetModuleUntyped returns a new instance of the named module, if it exists.
func ListModules ¶ added in v0.5.0
ListModules returns a map of interface names to module names.
func RegisterModule ¶ added in v0.4.0
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 ¶ added in v0.5.0
type Acceptor interface {
// Accept returns true if the replica should accept the command, false otherwise.
Accept(hotstuff.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(hotstuff.Command)
}
Acceptor decides if a replica should accept a command.
type BlockChain ¶ added in v0.5.0
type BlockChain interface {
// Store stores a block in the blockchain.
Store(*hotstuff.Block)
// Get retrieves a block given its hash, attempting to fetching it from other replicas if necessary.
Get(hotstuff.Hash) (*hotstuff.Block, bool)
// LocalGet retrieves a block given its hash, without fetching it from other replicas.
LocalGet(hotstuff.Hash) (*hotstuff.Block, bool)
// Extends checks if the given block extends the branch of the target hash.
Extends(block, target *hotstuff.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 hotstuff.View) (forkedBlocks []*hotstuff.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 hotstuff.ID, pk hotstuff.PrivateKey) Builder
NewBuilder returns a new builder.
type CommandQueue ¶ added in v0.5.0
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 hotstuff.Command, ok bool)
}
CommandQueue is a queue of commands to be proposed.
type Configuration ¶ added in v0.5.0
type Configuration interface {
// Replicas returns all of the replicas in the configuration.
Replicas() map[hotstuff.ID]Replica
// Replica returns a replica if present in the configuration.
Replica(hotstuff.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 hotstuff.ProposeMsg)
// Timeout sends the timeout message to all replicas.
Timeout(msg hotstuff.TimeoutMsg)
// Fetch requests a block from all the replicas in the configuration.
Fetch(ctx context.Context, hash hotstuff.Hash) (block *hotstuff.Block, ok bool)
// SubConfig returns a subconfiguration containing the replicas specified in the ids slice.
SubConfig(ids []hotstuff.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 ¶ added in v0.5.0
type Consensus interface {
// StopVoting ensures that no voting happens in a view earlier than `view`.
StopVoting(view hotstuff.View)
// Propose starts a new proposal. The command is fetched from the command queue.
Propose(cert hotstuff.SyncInfo)
// CommittedBlock returns the most recently committed block.
CommittedBlock() *hotstuff.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 ¶ added in v0.5.0
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 ¶ added in v0.5.0
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 ¶ added in v0.5.0
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 ¶ added in v0.5.0
type Crypto interface {
CryptoBase
// CreatePartialCert signs a single block and returns the partial certificate.
CreatePartialCert(block *hotstuff.Block) (cert hotstuff.PartialCert, err error)
// CreateQuorumCert creates a quorum certificate from a list of partial certificates.
CreateQuorumCert(block *hotstuff.Block, signatures []hotstuff.PartialCert) (cert hotstuff.QuorumCert, err error)
// CreateTimeoutCert creates a timeout certificate from a list of timeout messages.
CreateTimeoutCert(view hotstuff.View, timeouts []hotstuff.TimeoutMsg) (cert hotstuff.TimeoutCert, err error)
// CreateAggregateQC creates an AggregateQC from the given timeout messages.
CreateAggregateQC(view hotstuff.View, timeouts []hotstuff.TimeoutMsg) (aggQC hotstuff.AggregateQC, err error)
// VerifyPartialCert verifies a single partial certificate.
VerifyPartialCert(cert hotstuff.PartialCert) bool
// VerifyQuorumCert verifies a quorum certificate.
VerifyQuorumCert(qc hotstuff.QuorumCert) bool
// VerifyTimeoutCert verifies a timeout certificate.
VerifyTimeoutCert(tc hotstuff.TimeoutCert) bool
// VerifyAggregateQC verifies an AggregateQC.
VerifyAggregateQC(aggQC hotstuff.AggregateQC) (highQC hotstuff.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 ¶ added in v0.5.0
type CryptoBase interface {
// Sign creates a cryptographic signature of the given message.
Sign(message []byte) (signature hotstuff.QuorumSignature, err error)
// Combine combines multiple signatures into a single signature.
Combine(signatures ...hotstuff.QuorumSignature) (signature hotstuff.QuorumSignature, err error)
// Verify verifies the given quorum signature against the message.
Verify(signature hotstuff.QuorumSignature, message []byte) bool
// BatchVerify verifies the given quorum signature against the batch of messages.
BatchVerify(signature hotstuff.QuorumSignature, batch map[hotstuff.ID][]byte) bool
}
CryptoBase provides the basic cryptographic methods needed to create, verify, and combine signatures.
type Executor ¶ added in v0.5.0
Executor is responsible for executing the commands that are committed by the consensus protocol.
type ExecutorExt ¶ added in v0.5.0
type ExecutorExt interface {
// Exec executes the command in the block.
Exec(block *hotstuff.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 ¶ added in v0.5.0
func ExtendedExecutor(executor Executor) ExecutorExt
ExtendedExecutor turns the given Executor into an ExecutorExt.
type ForkHandler ¶ added in v0.5.0
type ForkHandler interface {
// Fork handles the command from a forked block.
Fork(cmd hotstuff.Command)
}
ForkHandler handles commands that do not get committed due to a forked blockchain.
TODO: think of a better name/interface
type ForkHandlerExt ¶ added in v0.5.0
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 ¶ added in v0.5.0
func ExtendedForkHandler(forkHandler ForkHandler) ForkHandlerExt
ExtendedForkHandler turns the given ForkHandler into a ForkHandlerExt.
type Kauri ¶ added in v0.5.0
type Kauri interface {
Begin(s hotstuff.PartialCert, p hotstuff.ProposeMsg)
}
Kauri module implements the Kauri protocol
type LeaderRotation ¶ added in v0.5.0
type LeaderRotation interface {
// GetLeader returns the id of the leader in the given view.
GetLeader(hotstuff.View) hotstuff.ID
}
LeaderRotation implements a leader rotation scheme.
type Module ¶
type Module interface {
InitModule(mods *Core)
}
Module is an interface for initializing modules.
type Options ¶ added in v0.5.0
type Options struct {
// contains filtered or unexported fields
}
Options stores runtime configuration settings.
func (*Options) ConnectionMetadata ¶ added in v0.5.0
ConnectionMetadata returns the metadata map that is sent when connecting to other replicas.
func (*Options) PrivateKey ¶ added in v0.5.0
func (opts *Options) PrivateKey() hotstuff.PrivateKey
PrivateKey returns the private key.
func (*Options) SetConnectionMetadata ¶ added in v0.5.0
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 ¶ added in v0.5.0
SetSharedRandomSeed sets the shared random seed.
func (*Options) SetShouldUseAggQC ¶ added in v0.5.0
func (opts *Options) SetShouldUseAggQC()
SetShouldUseAggQC sets the ShouldUseAggQC setting to true.
func (*Options) SetShouldUseTree ¶ added in v0.5.0
func (opts *Options) SetShouldUseTree()
SetShouldUseTree sets the ShouldUseTree setting to true.
func (*Options) SetShouldVerifyVotesSync ¶ added in v0.5.0
func (opts *Options) SetShouldVerifyVotesSync()
SetShouldVerifyVotesSync sets the ShouldVerifyVotesSync setting to true.
func (*Options) SharedRandomSeed ¶ added in v0.5.0
SharedRandomSeed returns a random number that is shared between all replicas.
func (*Options) ShouldUseAggQC ¶ added in v0.5.0
ShouldUseAggQC returns true if aggregated quorum certificates should be used. This is true for Fast-Hotstuff: https://arxiv.org/abs/2010.11454
func (*Options) ShouldUseTree ¶ added in v0.5.0
func (*Options) ShouldVerifyVotesSync ¶ added in v0.5.0
ShouldVerifyVotesSync returns true if votes should be verified synchronously. Enabling this should make the voting machine process votes synchronously.
type Replica ¶ added in v0.5.0
type Replica interface {
// ID returns the replica's id.
ID() hotstuff.ID
// PublicKey returns the replica's public key.
PublicKey() hotstuff.PublicKey
// Vote sends the partial certificate to the other replica.
Vote(cert hotstuff.PartialCert)
// NewView sends the quorum certificate to the other replica.
NewView(hotstuff.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 ¶ added in v0.5.0
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(hotstuff.SyncInfo)
// View returns the current view.
View() hotstuff.View
// HighQC returns the highest known QC.
HighQC() hotstuff.QuorumCert
// Start starts the synchronizer with the given context.
Start(context.Context)
}
Synchronizer synchronizes replicas to the same view.