mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 18:37:26 +08:00
179 lines
5.1 KiB
Go
179 lines
5.1 KiB
Go
package global
|
|
|
|
import (
|
|
"context"
|
|
"slices"
|
|
"sort"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
"go.uber.org/zap"
|
|
"source.quilibrium.com/quilibrium/monorepo/consensus"
|
|
"source.quilibrium.com/quilibrium/monorepo/consensus/models"
|
|
"source.quilibrium.com/quilibrium/monorepo/consensus/verification"
|
|
"source.quilibrium.com/quilibrium/monorepo/protobufs"
|
|
)
|
|
|
|
// GlobalVotingProvider implements VotingProvider
|
|
type GlobalVotingProvider struct {
|
|
engine *GlobalConsensusEngine
|
|
}
|
|
|
|
// FinalizeQuorumCertificate implements consensus.VotingProvider.
|
|
func (p *GlobalVotingProvider) FinalizeQuorumCertificate(
|
|
ctx context.Context,
|
|
state *models.State[*protobufs.GlobalFrame],
|
|
aggregatedSignature models.AggregatedSignature,
|
|
) (models.QuorumCertificate, error) {
|
|
return &protobufs.QuorumCertificate{
|
|
Rank: (*state.State).GetRank(),
|
|
FrameNumber: (*state.State).Header.FrameNumber,
|
|
Selector: []byte((*state.State).Identity()),
|
|
Timestamp: uint64(time.Now().UnixMilli()),
|
|
AggregateSignature: &protobufs.BLS48581AggregateSignature{
|
|
Signature: aggregatedSignature.GetSignature(),
|
|
PublicKey: &protobufs.BLS48581G2PublicKey{
|
|
KeyValue: aggregatedSignature.GetPubKey(),
|
|
},
|
|
Bitmask: aggregatedSignature.GetBitmask(),
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
// FinalizeTimeout implements consensus.VotingProvider.
|
|
func (p *GlobalVotingProvider) FinalizeTimeout(
|
|
ctx context.Context,
|
|
rank uint64,
|
|
latestQuorumCertificate models.QuorumCertificate,
|
|
latestQuorumCertificateRanks []consensus.TimeoutSignerInfo,
|
|
aggregatedSignature models.AggregatedSignature,
|
|
) (models.TimeoutCertificate, error) {
|
|
ranksInProverOrder := slices.Clone(latestQuorumCertificateRanks)
|
|
provers, err := p.engine.proverRegistry.GetActiveProvers(nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
proverIndexes := map[models.Identity]int{}
|
|
for i, p := range provers {
|
|
proverIndexes[models.Identity(p.Address)] = i
|
|
}
|
|
|
|
sort.Slice(ranksInProverOrder, func(i, j int) bool {
|
|
return proverIndexes[ranksInProverOrder[i].Signer]-
|
|
proverIndexes[ranksInProverOrder[j].Signer] < 0
|
|
})
|
|
|
|
ranks := []uint64{}
|
|
for _, r := range ranksInProverOrder {
|
|
ranks = append(ranks, r.NewestQCRank)
|
|
}
|
|
|
|
return &protobufs.TimeoutCertificate{
|
|
Rank: rank,
|
|
LatestRanks: ranks,
|
|
LatestQuorumCertificate: latestQuorumCertificate.(*protobufs.QuorumCertificate),
|
|
Timestamp: uint64(time.Now().UnixMilli()),
|
|
AggregateSignature: &protobufs.BLS48581AggregateSignature{
|
|
Signature: aggregatedSignature.GetSignature(),
|
|
PublicKey: &protobufs.BLS48581G2PublicKey{
|
|
KeyValue: aggregatedSignature.GetPubKey(),
|
|
},
|
|
Bitmask: aggregatedSignature.GetBitmask(),
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
// SignTimeoutVote implements consensus.VotingProvider.
|
|
func (p *GlobalVotingProvider) SignTimeoutVote(
|
|
ctx context.Context,
|
|
filter []byte,
|
|
currentRank uint64,
|
|
newestQuorumCertificateRank uint64,
|
|
) (**protobufs.ProposalVote, error) {
|
|
// Get signing key
|
|
signer, _, publicKey, _ := p.engine.GetProvingKey(p.engine.config.Engine)
|
|
if publicKey == nil {
|
|
p.engine.logger.Error("no proving key available")
|
|
return nil, errors.Wrap(
|
|
errors.New("no proving key available for voting"),
|
|
"sign vote",
|
|
)
|
|
}
|
|
|
|
// Create vote (signature)
|
|
signatureData := verification.MakeTimeoutMessage(
|
|
nil,
|
|
currentRank,
|
|
newestQuorumCertificateRank,
|
|
)
|
|
|
|
sig, err := signer.SignWithDomain(signatureData, []byte("globaltimeout"))
|
|
if err != nil {
|
|
p.engine.logger.Error("could not sign vote", zap.Error(err))
|
|
return nil, errors.Wrap(err, "sign vote")
|
|
}
|
|
|
|
voterAddress := p.engine.getAddressFromPublicKey(publicKey)
|
|
|
|
// Create vote message
|
|
vote := &protobufs.ProposalVote{
|
|
FrameNumber: 0,
|
|
Rank: currentRank,
|
|
Selector: nil,
|
|
Timestamp: uint64(time.Now().UnixMilli()),
|
|
PublicKeySignatureBls48581: &protobufs.BLS48581AddressedSignature{
|
|
Address: voterAddress,
|
|
Signature: sig,
|
|
},
|
|
}
|
|
|
|
return &vote, nil
|
|
}
|
|
|
|
// SignVote implements consensus.VotingProvider.
|
|
func (p *GlobalVotingProvider) SignVote(
|
|
ctx context.Context,
|
|
state *models.State[*protobufs.GlobalFrame],
|
|
) (**protobufs.ProposalVote, error) {
|
|
// Get signing key
|
|
signer, _, publicKey, _ := p.engine.GetProvingKey(p.engine.config.Engine)
|
|
if publicKey == nil {
|
|
p.engine.logger.Error("no proving key available")
|
|
return nil, errors.Wrap(
|
|
errors.New("no proving key available for voting"),
|
|
"sign vote",
|
|
)
|
|
}
|
|
|
|
// Create vote (signature)
|
|
signatureData := verification.MakeVoteMessage(
|
|
nil,
|
|
state.Rank,
|
|
state.Identifier,
|
|
)
|
|
sig, err := signer.SignWithDomain(signatureData, []byte("global"))
|
|
if err != nil {
|
|
p.engine.logger.Error("could not sign vote", zap.Error(err))
|
|
return nil, errors.Wrap(err, "sign vote")
|
|
}
|
|
|
|
voterAddress := p.engine.getAddressFromPublicKey(publicKey)
|
|
|
|
// Create vote message
|
|
vote := &protobufs.ProposalVote{
|
|
FrameNumber: (*state.State).Header.FrameNumber,
|
|
Rank: (*state.State).Header.Rank,
|
|
Selector: []byte((*state.State).Identity()),
|
|
Timestamp: uint64(time.Now().UnixMilli()),
|
|
PublicKeySignatureBls48581: &protobufs.BLS48581AddressedSignature{
|
|
Address: voterAddress,
|
|
Signature: sig,
|
|
},
|
|
}
|
|
|
|
return &vote, nil
|
|
}
|
|
|
|
var _ consensus.VotingProvider[*protobufs.GlobalFrame, *protobufs.ProposalVote, GlobalPeerID] = (*GlobalVotingProvider)(nil)
|