Documentation ¶
Overview ¶
package cmtLog is responsible for producing a log of chain's block decisions for a particular committee. The main tasks for this module are:
- Track the head of the chain log for a committee.
- Track which blocks are approved, pending or reverted.
- Handle startup and recovery scenarios.
The algorithm at a high level:
> ON Startup: > Let prevLI <- TRY restoring the last started LogIndex ELSE 0 > MinLI <- prevLI + 1 > LogIndex.Start(prevLI) > TryProposeConsensus() > UPON AliasOutput (AO) {Confirmed | Rejected} by L1: > LocalView.Update(AO) > IF LocalView changed THEN > LogIndex.L1ReplacedBaseAliasOutput() > TryProposeConsensus() > ON ConsensusOutput/DONE (CD) > LocalView.Update(CD) > IF LocalView changed THEN > LogIndex.ConsensusOutput(CD.LogIndex) > TryProposeConsensus() > ON ConsensusOutput/SKIP (CS) > LogIndex.ConsensusOutput(CS.LogIndex) > TryProposeConsensus() > ON ConsensusTimeout (CT) > LogIndex.ConsensusTimeout(CT.LogIndex) > TryProposeConsensus() > ON Suspend: > Suspended <- TRUE > TryProposeConsensus() > ON Reception of ⟨NextLI, •⟩ message: > LogIndex.Receive(⟨NextLI, •⟩ message). > TryProposeConsensus() > PROCEDURE TryProposeConsensus: > IF ∧ LocalView.BaseAO ≠ NIL > ∧ LogIndex > ConsensusLI > ∧ LogIndex ≥ MinLI // ⇒ LogIndex ≠ NIL > ∧ ¬ Suspended > THEN > Persist LogIndex > ConsensusLI <- LogIndex > Propose LocalView.BaseAO for LogIndex > ELSE > Don't propose any consensus.
See `WaspChainRecovery.tla` for more precise specification.
Notes and invariants:
- Here only a single consensus instance will be considered needed for this node at a time. Other instances may continue running, but their results will be ignored. That's because a consensus takes an input from the previous consensus output (the base alias ID and other parts that depend on it).
- A consensus is started when we have new log index greater than that we have crashed with, and there is an alias output received.
## Summary.
Inputs expected:
- Consensus: Start -> Done | Timeout.
- AliasOutput: Confirmed | Rejected -> {}.
- Suspend.
Messages exchanged:
- NextLogIndex (private, between cmtLog instances).
Index ¶
- Variables
- func NewInputAliasOutputConfirmed(aliasOutput *isc.AliasOutputWithID) gpa.Input
- func NewInputAliasOutputRejected(aliasOutput *isc.AliasOutputWithID) gpa.Input
- func NewInputConsensusOutputDone(logIndex LogIndex, baseAliasOutputID iotago.OutputID, ...) gpa.Input
- func NewInputConsensusOutputSkip(logIndex LogIndex, baseAliasOutputID iotago.OutputID) gpa.Input
- func NewInputConsensusTimeout(logIndex LogIndex) gpa.Input
- func NewInputSuspend() gpa.Input
- func UnmarshalMessage(data []byte) (gpa.Message, error)
- type CmtLog
- type ConsensusStateRegistry
- type LogIndex
- type Output
- type State
- type VarLocalView
- type VarLogIndex
Constants ¶
This section is empty.
Variables ¶
var ErrCmtLogStateNotFound = errors.New("errCmtLogStateNotFound")
Functions ¶
func NewInputAliasOutputConfirmed ¶
func NewInputAliasOutputConfirmed(aliasOutput *isc.AliasOutputWithID) gpa.Input
func NewInputAliasOutputRejected ¶
func NewInputAliasOutputRejected(aliasOutput *isc.AliasOutputWithID) gpa.Input
func NewInputConsensusOutputDone ¶
func NewInputConsensusOutputDone( logIndex LogIndex, baseAliasOutputID iotago.OutputID, nextAliasOutput *isc.AliasOutputWithID, ) gpa.Input
This message is internal one, but should be sent by other components (e.g. consensus or the chain).
func NewInputConsensusOutputSkip ¶
This message is internal one, but should be sent by other components (e.g. consensus or the chain).
func NewInputConsensusTimeout ¶
This message is internal one, but should be sent by other components (e.g. consensus or the chain).
func NewInputSuspend ¶
Types ¶
type CmtLog ¶
Public interface for this algorithm.
func New ¶
func New( me gpa.NodeID, chainID isc.ChainID, dkShare tcrypto.DKShare, consensusStateRegistry ConsensusStateRegistry, nodeIDFromPubKey func(pubKey *cryptolib.PublicKey) gpa.NodeID, log *logger.Logger, ) (CmtLog, error)
Construct new node instance for this protocol.
> ON Startup: > Let prevLI <- TRY restoring the last started LogIndex ELSE 0 > MinLI <- prevLI + 1 > ...
type ConsensusStateRegistry ¶
type ConsensusStateRegistry interface { Get(chainID isc.ChainID, committeeAddress iotago.Address) (*State, error) // Can return ErrCmtLogStateNotFound. Set(chainID isc.ChainID, committeeAddress iotago.Address, state *State) error }
Interface used to store and recover the existing persistent state. To be implemented by the registry.
type LogIndex ¶
type LogIndex uint32
LogIndex starts from 1. 0 is used as a nil value.
func MaxLogIndex ¶
func NilLogIndex ¶
func NilLogIndex() LogIndex
type Output ¶
type Output struct {
// contains filtered or unexported fields
}
Output for this protocol indicates, what instance of a consensus is currently required to be run. The unique identifier here is the logIndex (there will be no different baseAliasOutputs for the same logIndex).
func (*Output) GetBaseAliasOutput ¶
func (o *Output) GetBaseAliasOutput() *isc.AliasOutputWithID
func (*Output) GetLogIndex ¶
type VarLocalView ¶
type VarLocalView interface { // // Returns alias output to produce next transaction on, or nil if we should wait. // In the case of nil, we either wait for the first AO to receive, or we are // still recovering from a TX rejection. GetBaseAliasOutput() *isc.AliasOutputWithID // // Corresponds to the `ao_received` event in the specification. // Returns true, if the proposed BaseAliasOutput has changed. AliasOutputConfirmed(confirmed *isc.AliasOutputWithID) bool // // Corresponds to the `tx_rejected` event in the specification. // Returns true, if the proposed BaseAliasOutput has changed. AliasOutputRejected(rejected *isc.AliasOutputWithID) bool // // Corresponds to the `tx_posted` event in the specification. // Returns true, if the proposed BaseAliasOutput has changed. ConsensusOutputDone(consumed iotago.OutputID, published *isc.AliasOutputWithID) bool // // Support functions. StatusString() string }
func NewVarLocalView ¶
func NewVarLocalView() VarLocalView
type VarLogIndex ¶
type VarLogIndex interface { // Returns the latest agreed LI/AO. // There is no output value, if LogIndex=⊥. Value() (LogIndex, *isc.AliasOutputWithID) // Consensus terminated with either with DONE or SKIP. // NextAO is the same as before for the SKIP case. // NextAO = nil means we don't know the latest AO from L1 (either startup or reject of a chain is happening). ConsensusOutputReceived(consensusLI LogIndex, consensusStatus cons.OutputStatus, nextBaseAO *isc.AliasOutputWithID) gpa.OutMessages // Consensus decided, that its maybe time to attempt another run. // The timeout-ed consensus will be still running, so they will race for the result. ConsensusTimeoutReceived(consensusLI LogIndex) gpa.OutMessages // This might get a nil alias output in the case when a TX gets rejected and it was not the latest TX in the active chain. // NextAO = nil means we don't know the latest AO from L1 (either startup or reject of a chain is happening). L1ReplacedBaseAliasOutput(nextBaseAO *isc.AliasOutputWithID) gpa.OutMessages // Messages are exchanged, so this function handles them. MsgNextLogIndexReceived(msg *msgNextLogIndex) gpa.OutMessages }
func NewVarLogIndex ¶
func NewVarLogIndex( nodeIDs []gpa.NodeID, n int, f int, persistedLI LogIndex, outputCB func(li LogIndex, ao *isc.AliasOutputWithID), log *logger.Logger, ) VarLogIndex
> ON Init(persistedLI): > latestAO ← ⊥ > proposedLI, agreedLI ← 0 > minLI ← persistedLI + 1 > maxPeerLIs ← ∅