mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 10:27:26 +08:00
468 lines
11 KiB
Go
468 lines
11 KiB
Go
package helper
|
|
|
|
import (
|
|
crand "crypto/rand"
|
|
"fmt"
|
|
"math/rand"
|
|
"slices"
|
|
"strings"
|
|
"time"
|
|
|
|
"source.quilibrium.com/quilibrium/monorepo/consensus"
|
|
"source.quilibrium.com/quilibrium/monorepo/consensus/models"
|
|
)
|
|
|
|
type TestWeightedIdentity struct {
|
|
ID string
|
|
}
|
|
|
|
// Identity implements models.WeightedIdentity.
|
|
func (t *TestWeightedIdentity) Identity() models.Identity {
|
|
return t.ID
|
|
}
|
|
|
|
// PublicKey implements models.WeightedIdentity.
|
|
func (t *TestWeightedIdentity) PublicKey() []byte {
|
|
return make([]byte, 585)
|
|
}
|
|
|
|
// Weight implements models.WeightedIdentity.
|
|
func (t *TestWeightedIdentity) Weight() uint64 {
|
|
return 1000
|
|
}
|
|
|
|
var _ models.WeightedIdentity = (*TestWeightedIdentity)(nil)
|
|
|
|
type TestState struct {
|
|
Rank uint64
|
|
Signature []byte
|
|
Timestamp uint64
|
|
ID models.Identity
|
|
Prover models.Identity
|
|
}
|
|
|
|
// Clone implements models.Unique.
|
|
func (t *TestState) Clone() models.Unique {
|
|
return &TestState{
|
|
Rank: t.Rank,
|
|
Signature: slices.Clone(t.Signature),
|
|
Timestamp: t.Timestamp,
|
|
ID: t.ID,
|
|
Prover: t.Prover,
|
|
}
|
|
}
|
|
|
|
// GetRank implements models.Unique.
|
|
func (t *TestState) GetRank() uint64 {
|
|
return t.Rank
|
|
}
|
|
|
|
// GetSignature implements models.Unique.
|
|
func (t *TestState) GetSignature() []byte {
|
|
return t.Signature
|
|
}
|
|
|
|
// GetTimestamp implements models.Unique.
|
|
func (t *TestState) GetTimestamp() uint64 {
|
|
return t.Timestamp
|
|
}
|
|
|
|
// Identity implements models.Unique.
|
|
func (t *TestState) Identity() models.Identity {
|
|
return t.ID
|
|
}
|
|
|
|
// Source implements models.Unique.
|
|
func (t *TestState) Source() models.Identity {
|
|
return t.Prover
|
|
}
|
|
|
|
type TestVote struct {
|
|
Rank uint64
|
|
Signature []byte
|
|
Timestamp uint64
|
|
ID models.Identity
|
|
StateID models.Identity
|
|
}
|
|
|
|
// Clone implements models.Unique.
|
|
func (t *TestVote) Clone() models.Unique {
|
|
return &TestVote{
|
|
Rank: t.Rank,
|
|
Signature: slices.Clone(t.Signature),
|
|
Timestamp: t.Timestamp,
|
|
ID: t.ID,
|
|
StateID: t.StateID,
|
|
}
|
|
}
|
|
|
|
// GetRank implements models.Unique.
|
|
func (t *TestVote) GetRank() uint64 {
|
|
return t.Rank
|
|
}
|
|
|
|
// GetSignature implements models.Unique.
|
|
func (t *TestVote) GetSignature() []byte {
|
|
return t.Signature
|
|
}
|
|
|
|
// GetTimestamp implements models.Unique.
|
|
func (t *TestVote) GetTimestamp() uint64 {
|
|
return t.Timestamp
|
|
}
|
|
|
|
// Identity implements models.Unique.
|
|
func (t *TestVote) Identity() models.Identity {
|
|
return t.ID
|
|
}
|
|
|
|
// Source implements models.Unique.
|
|
func (t *TestVote) Source() models.Identity {
|
|
return t.StateID
|
|
}
|
|
|
|
type TestPeer struct {
|
|
PeerID string
|
|
}
|
|
|
|
// Clone implements models.Unique.
|
|
func (t *TestPeer) Clone() models.Unique {
|
|
return &TestPeer{
|
|
PeerID: t.PeerID,
|
|
}
|
|
}
|
|
|
|
// GetRank implements models.Unique.
|
|
func (t *TestPeer) GetRank() uint64 {
|
|
return 0
|
|
}
|
|
|
|
// GetSignature implements models.Unique.
|
|
func (t *TestPeer) GetSignature() []byte {
|
|
return []byte{}
|
|
}
|
|
|
|
// GetTimestamp implements models.Unique.
|
|
func (t *TestPeer) GetTimestamp() uint64 {
|
|
return 0
|
|
}
|
|
|
|
// Identity implements models.Unique.
|
|
func (t *TestPeer) Identity() models.Identity {
|
|
return t.PeerID
|
|
}
|
|
|
|
// Source implements models.Unique.
|
|
func (t *TestPeer) Source() models.Identity {
|
|
return t.PeerID
|
|
}
|
|
|
|
type TestCollected struct {
|
|
Rank uint64
|
|
TXs [][]byte
|
|
}
|
|
|
|
// Clone implements models.Unique.
|
|
func (t *TestCollected) Clone() models.Unique {
|
|
return &TestCollected{
|
|
Rank: t.Rank,
|
|
TXs: slices.Clone(t.TXs),
|
|
}
|
|
}
|
|
|
|
// GetRank implements models.Unique.
|
|
func (t *TestCollected) GetRank() uint64 {
|
|
return t.Rank
|
|
}
|
|
|
|
// GetSignature implements models.Unique.
|
|
func (t *TestCollected) GetSignature() []byte {
|
|
return []byte{}
|
|
}
|
|
|
|
// GetTimestamp implements models.Unique.
|
|
func (t *TestCollected) GetTimestamp() uint64 {
|
|
return 0
|
|
}
|
|
|
|
// Identity implements models.Unique.
|
|
func (t *TestCollected) Identity() models.Identity {
|
|
return fmt.Sprintf("%d", t.Rank)
|
|
}
|
|
|
|
// Source implements models.Unique.
|
|
func (t *TestCollected) Source() models.Identity {
|
|
return ""
|
|
}
|
|
|
|
var _ models.Unique = (*TestState)(nil)
|
|
var _ models.Unique = (*TestVote)(nil)
|
|
var _ models.Unique = (*TestPeer)(nil)
|
|
var _ models.Unique = (*TestCollected)(nil)
|
|
|
|
func MakeIdentity() models.Identity {
|
|
s := make([]byte, 32)
|
|
crand.Read(s)
|
|
return models.Identity(s)
|
|
}
|
|
|
|
func MakeState[StateT models.Unique](options ...func(*models.State[StateT])) *models.State[StateT] {
|
|
rank := rand.Uint64()
|
|
|
|
state := models.State[StateT]{
|
|
Rank: rank,
|
|
Identifier: MakeIdentity(),
|
|
ProposerID: MakeIdentity(),
|
|
Timestamp: uint64(time.Now().UnixMilli()),
|
|
ParentQuorumCertificate: MakeQC(WithQCRank(rank - 1)),
|
|
}
|
|
for _, option := range options {
|
|
option(&state)
|
|
}
|
|
return &state
|
|
}
|
|
|
|
func WithStateRank[StateT models.Unique](rank uint64) func(*models.State[StateT]) {
|
|
return func(state *models.State[StateT]) {
|
|
state.Rank = rank
|
|
}
|
|
}
|
|
|
|
func WithStateProposer[StateT models.Unique](proposerID models.Identity) func(*models.State[StateT]) {
|
|
return func(state *models.State[StateT]) {
|
|
state.ProposerID = proposerID
|
|
}
|
|
}
|
|
|
|
func WithParentState[StateT models.Unique](parent *models.State[StateT]) func(*models.State[StateT]) {
|
|
return func(state *models.State[StateT]) {
|
|
state.ParentQuorumCertificate.(*TestQuorumCertificate).Selector = parent.Identifier
|
|
state.ParentQuorumCertificate.(*TestQuorumCertificate).Rank = parent.Rank
|
|
}
|
|
}
|
|
|
|
func WithParentSigners[StateT models.Unique](signerIndices []byte) func(*models.State[StateT]) {
|
|
return func(state *models.State[StateT]) {
|
|
state.ParentQuorumCertificate.(*TestQuorumCertificate).AggregatedSignature.(*TestAggregatedSignature).Bitmask = signerIndices // buildutils:allow-slice-alias
|
|
}
|
|
}
|
|
|
|
func WithStateQC[StateT models.Unique](qc models.QuorumCertificate) func(*models.State[StateT]) {
|
|
return func(state *models.State[StateT]) {
|
|
state.ParentQuorumCertificate = qc
|
|
}
|
|
}
|
|
|
|
func MakeVote[VoteT models.Unique]() *VoteT {
|
|
return new(VoteT)
|
|
}
|
|
|
|
func MakeSignedProposal[StateT models.Unique, VoteT models.Unique](options ...func(*models.SignedProposal[StateT, VoteT])) *models.SignedProposal[StateT, VoteT] {
|
|
proposal := &models.SignedProposal[StateT, VoteT]{
|
|
Proposal: *MakeProposal[StateT](),
|
|
Vote: MakeVote[VoteT](),
|
|
}
|
|
for _, option := range options {
|
|
option(proposal)
|
|
}
|
|
return proposal
|
|
}
|
|
|
|
func MakeProposal[StateT models.Unique](options ...func(*models.Proposal[StateT])) *models.Proposal[StateT] {
|
|
proposal := &models.Proposal[StateT]{
|
|
State: MakeState[StateT](),
|
|
PreviousRankTimeoutCertificate: nil,
|
|
}
|
|
for _, option := range options {
|
|
option(proposal)
|
|
}
|
|
return proposal
|
|
}
|
|
|
|
func WithProposal[StateT models.Unique, VoteT models.Unique](proposal *models.Proposal[StateT]) func(*models.SignedProposal[StateT, VoteT]) {
|
|
return func(signedProposal *models.SignedProposal[StateT, VoteT]) {
|
|
signedProposal.Proposal = *proposal
|
|
}
|
|
}
|
|
|
|
func WithState[StateT models.Unique](state *models.State[StateT]) func(*models.Proposal[StateT]) {
|
|
return func(proposal *models.Proposal[StateT]) {
|
|
proposal.State = state
|
|
}
|
|
}
|
|
|
|
func WithVote[StateT models.Unique, VoteT models.Unique](vote *VoteT) func(*models.SignedProposal[StateT, VoteT]) {
|
|
return func(proposal *models.SignedProposal[StateT, VoteT]) {
|
|
proposal.Vote = vote
|
|
}
|
|
}
|
|
|
|
func WithPreviousRankTimeoutCertificate[StateT models.Unique](previousRankTimeoutCert models.TimeoutCertificate) func(*models.Proposal[StateT]) {
|
|
return func(proposal *models.Proposal[StateT]) {
|
|
proposal.PreviousRankTimeoutCertificate = previousRankTimeoutCert
|
|
}
|
|
}
|
|
|
|
func WithWeightedIdentityList(count int) []models.WeightedIdentity {
|
|
wi := []models.WeightedIdentity{}
|
|
for range count {
|
|
wi = append(wi, &TestWeightedIdentity{
|
|
ID: MakeIdentity(),
|
|
})
|
|
}
|
|
return wi
|
|
}
|
|
|
|
func VoteForStateFixture(state *models.State[*TestState], ops ...func(vote **TestVote)) *TestVote {
|
|
v := &TestVote{
|
|
Rank: state.Rank,
|
|
ID: MakeIdentity(),
|
|
StateID: state.Identifier,
|
|
Signature: make([]byte, 74),
|
|
}
|
|
for _, op := range ops {
|
|
op(&v)
|
|
}
|
|
return v
|
|
}
|
|
|
|
func VoteFixture(op func(vote **TestVote)) *TestVote {
|
|
v := &TestVote{
|
|
Rank: rand.Uint64(),
|
|
ID: MakeIdentity(),
|
|
StateID: MakeIdentity(),
|
|
Signature: make([]byte, 74),
|
|
}
|
|
op(&v)
|
|
return v
|
|
}
|
|
|
|
type FmtLog struct {
|
|
params []consensus.LogParam
|
|
}
|
|
|
|
// Error implements consensus.TraceLogger.
|
|
func (n *FmtLog) Error(message string, err error, params ...consensus.LogParam) {
|
|
b := strings.Builder{}
|
|
b.WriteString(fmt.Sprintf("ERROR: %s: %v\n", message, err))
|
|
for _, param := range n.params {
|
|
b.WriteString(fmt.Sprintf(
|
|
"\t%s: %s\n",
|
|
param.GetKey(),
|
|
stringFromValue(param),
|
|
))
|
|
}
|
|
for _, param := range params {
|
|
b.WriteString(fmt.Sprintf(
|
|
"\t%s: %s\n",
|
|
param.GetKey(),
|
|
stringFromValue(param),
|
|
))
|
|
}
|
|
fmt.Println(b.String())
|
|
}
|
|
|
|
// Trace implements consensus.TraceLogger.
|
|
func (n *FmtLog) Trace(message string, params ...consensus.LogParam) {
|
|
b := strings.Builder{}
|
|
b.WriteString(fmt.Sprintf("TRACE: %s\n", message))
|
|
b.WriteString(fmt.Sprintf("\t[%s]\n", time.Now().String()))
|
|
for _, param := range n.params {
|
|
b.WriteString(fmt.Sprintf(
|
|
"\t%s: %s\n",
|
|
param.GetKey(),
|
|
stringFromValue(param),
|
|
))
|
|
}
|
|
for _, param := range params {
|
|
b.WriteString(fmt.Sprintf(
|
|
"\t%s: %s\n",
|
|
param.GetKey(),
|
|
stringFromValue(param),
|
|
))
|
|
}
|
|
fmt.Println(b.String())
|
|
}
|
|
|
|
func (n *FmtLog) With(params ...consensus.LogParam) consensus.TraceLogger {
|
|
return &FmtLog{
|
|
params: slices.Concat(n.params, params),
|
|
}
|
|
}
|
|
|
|
func stringFromValue(param consensus.LogParam) string {
|
|
switch param.GetKind() {
|
|
case "string":
|
|
return param.GetValue().(string)
|
|
case "time":
|
|
return param.GetValue().(time.Time).String()
|
|
default:
|
|
return fmt.Sprintf("%v", param.GetValue())
|
|
}
|
|
}
|
|
|
|
func Logger() *FmtLog {
|
|
return &FmtLog{}
|
|
}
|
|
|
|
type BufferLog struct {
|
|
params []consensus.LogParam
|
|
b *strings.Builder
|
|
}
|
|
|
|
// Error implements consensus.TraceLogger.
|
|
func (n *BufferLog) Error(message string, err error, params ...consensus.LogParam) {
|
|
n.b.WriteString(fmt.Sprintf("ERROR: %s: %v\n", message, err))
|
|
for _, param := range n.params {
|
|
n.b.WriteString(fmt.Sprintf(
|
|
"\t%s: %s\n",
|
|
param.GetKey(),
|
|
stringFromValue(param),
|
|
))
|
|
}
|
|
for _, param := range params {
|
|
n.b.WriteString(fmt.Sprintf(
|
|
"\t%s: %s\n",
|
|
param.GetKey(),
|
|
stringFromValue(param),
|
|
))
|
|
}
|
|
}
|
|
|
|
// Trace implements consensus.TraceLogger.
|
|
func (n *BufferLog) Trace(message string, params ...consensus.LogParam) {
|
|
n.b.WriteString(fmt.Sprintf("TRACE: %s\n", message))
|
|
n.b.WriteString(fmt.Sprintf("\t[%s]\n", time.Now().String()))
|
|
for _, param := range n.params {
|
|
n.b.WriteString(fmt.Sprintf(
|
|
"\t%s: %s\n",
|
|
param.GetKey(),
|
|
stringFromValue(param),
|
|
))
|
|
}
|
|
for _, param := range params {
|
|
n.b.WriteString(fmt.Sprintf(
|
|
"\t%s: %s\n",
|
|
param.GetKey(),
|
|
stringFromValue(param),
|
|
))
|
|
}
|
|
}
|
|
|
|
func (n *BufferLog) Flush() {
|
|
fmt.Println(n.b.String())
|
|
}
|
|
|
|
func (n *BufferLog) With(params ...consensus.LogParam) consensus.TraceLogger {
|
|
return &BufferLog{
|
|
params: slices.Concat(n.params, params),
|
|
b: n.b,
|
|
}
|
|
}
|
|
|
|
func BufferLogger() *BufferLog {
|
|
return &BufferLog{
|
|
b: &strings.Builder{},
|
|
}
|
|
}
|