mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 10:27:26 +08:00
191 lines
4.8 KiB
Go
191 lines
4.8 KiB
Go
package app
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"math/big"
|
|
"slices"
|
|
|
|
"github.com/iden3/go-iden3-crypto/poseidon"
|
|
"github.com/pkg/errors"
|
|
"source.quilibrium.com/quilibrium/monorepo/consensus/models"
|
|
tconsensus "source.quilibrium.com/quilibrium/monorepo/types/consensus"
|
|
)
|
|
|
|
type ConsensusWeightedIdentity struct {
|
|
prover *tconsensus.ProverInfo
|
|
}
|
|
|
|
// Identity implements models.WeightedIdentity.
|
|
func (c *ConsensusWeightedIdentity) Identity() models.Identity {
|
|
return models.Identity(c.prover.Address)
|
|
}
|
|
|
|
// PublicKey implements models.WeightedIdentity.
|
|
func (c *ConsensusWeightedIdentity) PublicKey() []byte {
|
|
return c.prover.PublicKey
|
|
}
|
|
|
|
// Weight implements models.WeightedIdentity.
|
|
func (c *ConsensusWeightedIdentity) Weight() uint64 {
|
|
return c.prover.Seniority
|
|
}
|
|
|
|
// IdentitiesByRank implements consensus.DynamicCommittee.
|
|
func (e *AppConsensusEngine) IdentitiesByRank(
|
|
rank uint64,
|
|
) ([]models.WeightedIdentity, error) {
|
|
proverInfo, err := e.proverRegistry.GetActiveProvers(e.appAddress)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "identities by rank")
|
|
}
|
|
|
|
return internalProversToWeightedIdentity(proverInfo), nil
|
|
}
|
|
|
|
// IdentitiesByState implements consensus.DynamicCommittee.
|
|
func (e *AppConsensusEngine) IdentitiesByState(
|
|
stateID models.Identity,
|
|
) ([]models.WeightedIdentity, error) {
|
|
proverInfo, err := e.proverRegistry.GetActiveProvers(e.appAddress)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "identities by state")
|
|
}
|
|
|
|
return internalProversToWeightedIdentity(proverInfo), nil
|
|
}
|
|
|
|
// IdentityByRank implements consensus.DynamicCommittee.
|
|
func (e *AppConsensusEngine) IdentityByRank(
|
|
rank uint64,
|
|
participantID models.Identity,
|
|
) (models.WeightedIdentity, error) {
|
|
proverInfo, err := e.proverRegistry.GetActiveProvers(e.appAddress)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "identity by rank")
|
|
}
|
|
|
|
var found *tconsensus.ProverInfo
|
|
for _, p := range proverInfo {
|
|
if bytes.Equal(p.Address, []byte(participantID)) {
|
|
found = p
|
|
break
|
|
}
|
|
}
|
|
|
|
if found == nil {
|
|
return nil, errors.Wrap(errors.New("prover not found"), "identity by rank")
|
|
}
|
|
|
|
return internalProverToWeightedIdentity(found), nil
|
|
}
|
|
|
|
// IdentityByState implements consensus.DynamicCommittee.
|
|
func (e *AppConsensusEngine) IdentityByState(
|
|
stateID models.Identity,
|
|
participantID models.Identity,
|
|
) (models.WeightedIdentity, error) {
|
|
proverInfo, err := e.proverRegistry.GetActiveProvers(e.appAddress)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "identity by state")
|
|
}
|
|
|
|
var found *tconsensus.ProverInfo
|
|
for _, p := range proverInfo {
|
|
if bytes.Equal(p.Address, []byte(participantID)) {
|
|
found = p
|
|
break
|
|
}
|
|
}
|
|
|
|
if found == nil {
|
|
return nil, errors.Wrap(errors.New("prover not found"), "identity by state")
|
|
}
|
|
|
|
return internalProverToWeightedIdentity(found), nil
|
|
}
|
|
|
|
// LeaderForRank implements consensus.DynamicCommittee.
|
|
func (e *AppConsensusEngine) LeaderForRank(rank uint64) (
|
|
models.Identity,
|
|
error,
|
|
) {
|
|
// TODO(2.2): revisit this
|
|
inputBI, err := poseidon.HashBytes(slices.Concat(
|
|
binary.BigEndian.AppendUint64(slices.Clone(e.appAddress), rank),
|
|
))
|
|
if err != nil {
|
|
return "", errors.Wrap(err, "leader for rank")
|
|
}
|
|
|
|
proverSet, err := e.proverRegistry.GetActiveProvers(e.appAddress)
|
|
if err != nil {
|
|
return "", errors.Wrap(err, "leader for rank")
|
|
}
|
|
|
|
// Handle condition where prover cannot be yet known due to lack of sync:
|
|
if len(proverSet) == 0 {
|
|
return models.Identity(make([]byte, 32)), nil
|
|
}
|
|
|
|
inputBI.Mod(inputBI, big.NewInt(int64(len(proverSet))))
|
|
index := inputBI.Int64()
|
|
return models.Identity(proverSet[int(index)].Address), nil
|
|
}
|
|
|
|
// QuorumThresholdForRank implements consensus.DynamicCommittee.
|
|
func (e *AppConsensusEngine) QuorumThresholdForRank(
|
|
rank uint64,
|
|
) (uint64, error) {
|
|
proverInfo, err := e.proverRegistry.GetActiveProvers(e.appAddress)
|
|
if err != nil {
|
|
return 0, errors.Wrap(err, "quorum threshold for rank")
|
|
}
|
|
|
|
total := uint64(0)
|
|
for _, p := range proverInfo {
|
|
total += p.Seniority
|
|
}
|
|
|
|
return (total * 2) / 3, nil
|
|
}
|
|
|
|
// Self implements consensus.DynamicCommittee.
|
|
func (e *AppConsensusEngine) Self() models.Identity {
|
|
return e.getPeerID().Identity()
|
|
}
|
|
|
|
// TimeoutThresholdForRank implements consensus.DynamicCommittee.
|
|
func (e *AppConsensusEngine) TimeoutThresholdForRank(
|
|
rank uint64,
|
|
) (uint64, error) {
|
|
proverInfo, err := e.proverRegistry.GetActiveProvers(e.appAddress)
|
|
if err != nil {
|
|
return 0, errors.Wrap(err, "quorum threshold for rank")
|
|
}
|
|
|
|
total := uint64(0)
|
|
for _, p := range proverInfo {
|
|
total += p.Seniority
|
|
}
|
|
|
|
return (total * 2) / 3, nil
|
|
}
|
|
|
|
func internalProversToWeightedIdentity(
|
|
provers []*tconsensus.ProverInfo,
|
|
) []models.WeightedIdentity {
|
|
wis := []models.WeightedIdentity{}
|
|
for _, p := range provers {
|
|
wis = append(wis, internalProverToWeightedIdentity(p))
|
|
}
|
|
|
|
return wis
|
|
}
|
|
|
|
func internalProverToWeightedIdentity(
|
|
prover *tconsensus.ProverInfo,
|
|
) models.WeightedIdentity {
|
|
return &ConsensusWeightedIdentity{prover}
|
|
}
|