mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-03-12 11:47:39 +08:00
102 lines
3.2 KiB
Go
102 lines
3.2 KiB
Go
package models
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
// State is the HotStuff algorithm's concept of a state, which - in the bigger
|
|
// picture - corresponds to the state header.
|
|
type State[StateT Unique] struct {
|
|
Rank uint64
|
|
Identifier Identity
|
|
ProposerID Identity
|
|
ParentQuorumCertificate QuorumCertificate
|
|
Timestamp uint64 // Unix milliseconds
|
|
State *StateT
|
|
}
|
|
|
|
// StateFrom combines external state with source parent quorum certificate.
|
|
func StateFrom[StateT Unique](
|
|
t *StateT,
|
|
parentCert QuorumCertificate,
|
|
) *State[StateT] {
|
|
state := State[StateT]{
|
|
Identifier: (*t).Identity(),
|
|
Rank: (*t).GetRank(),
|
|
ParentQuorumCertificate: parentCert,
|
|
ProposerID: (*t).Source(),
|
|
Timestamp: (*t).GetTimestamp(),
|
|
State: t,
|
|
}
|
|
|
|
return &state
|
|
}
|
|
|
|
// GenesisStateFrom returns a generic consensus model of genesis state.
|
|
func GenesisStateFrom[StateT Unique](internal *StateT) *State[StateT] {
|
|
genesis := &State[StateT]{
|
|
Identifier: (*internal).Identity(),
|
|
Rank: (*internal).GetRank(),
|
|
ProposerID: (*internal).Source(),
|
|
ParentQuorumCertificate: nil,
|
|
Timestamp: (*internal).GetTimestamp(),
|
|
State: internal,
|
|
}
|
|
return genesis
|
|
}
|
|
|
|
// CertifiedState holds a certified state, which is a state and a
|
|
// QuorumCertificate that is pointing to the state. A QuorumCertificate is the
|
|
// aggregated form of votes from a supermajority of HotStuff and
|
|
// therefore proves validity of the state. A certified state satisfies:
|
|
// State.Rank == QuorumCertificate.Rank and
|
|
// State.Identifier == QuorumCertificate.Identifier
|
|
type CertifiedState[StateT Unique] struct {
|
|
State *State[StateT]
|
|
CertifyingQuorumCertificate QuorumCertificate
|
|
}
|
|
|
|
// NewCertifiedState constructs a new certified state. It checks the consistency
|
|
// requirements and returns an exception otherwise:
|
|
//
|
|
// State.Rank == QuorumCertificate.Rank and State.Identifier ==
|
|
//
|
|
// QuorumCertificate.Identifier
|
|
func NewCertifiedState[StateT Unique](
|
|
state *State[StateT],
|
|
quorumCertificate QuorumCertificate,
|
|
) (*CertifiedState[StateT], error) {
|
|
if state.Rank != quorumCertificate.GetRank() {
|
|
return &CertifiedState[StateT]{},
|
|
fmt.Errorf(
|
|
"state's rank (%d) should equal the qc's rank (%d)",
|
|
state.Rank,
|
|
quorumCertificate.GetRank(),
|
|
)
|
|
}
|
|
if state.Identifier != quorumCertificate.Identity() {
|
|
return &CertifiedState[StateT]{},
|
|
fmt.Errorf(
|
|
"state's ID (%x) should equal the state referenced by the qc (%x)",
|
|
state.Identifier,
|
|
quorumCertificate.Identity(),
|
|
)
|
|
}
|
|
return &CertifiedState[StateT]{
|
|
State: state,
|
|
CertifyingQuorumCertificate: quorumCertificate,
|
|
}, nil
|
|
}
|
|
|
|
// Identifier returns a unique identifier for the state (the ID signed to
|
|
// produce a state vote). To avoid repeated computation, we use value from the
|
|
// QuorumCertificate.
|
|
func (b *CertifiedState[StateT]) Identifier() Identity {
|
|
return b.CertifyingQuorumCertificate.Identity()
|
|
}
|
|
|
|
// Rank returns rank where the state was proposed.
|
|
func (b *CertifiedState[StateT]) Rank() uint64 {
|
|
return b.State.Rank
|
|
}
|