0g-chain/x/dasigners/v1/keeper/abci.go

117 lines
3.3 KiB
Go
Raw Normal View History

2024-05-09 18:54:47 +00:00
package keeper
import (
"bytes"
2024-06-07 07:47:56 +00:00
"math/big"
2024-05-09 18:54:47 +00:00
"sort"
"github.com/0glabs/0g-chain/x/dasigners/v1/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/crypto"
abci "github.com/tendermint/tendermint/abci/types"
)
type Ballot struct {
account string
content []byte
}
func (k Keeper) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
epochNumber, err := k.GetEpochNumber(ctx)
if err != nil {
k.Logger(ctx).Error("[BeginBlock] cannot get epoch number")
panic(err)
}
params := k.GetParams(ctx)
expectedEpoch := uint64(ctx.BlockHeight()) / params.EpochBlocks
if expectedEpoch == epochNumber {
return
}
if expectedEpoch > epochNumber+1 || expectedEpoch < epochNumber {
panic("block height is not continuous")
}
// new epoch
registrations := []Ballot{}
k.IterateRegistrations(ctx, expectedEpoch, func(account string, signature []byte) (stop bool) {
registrations = append(registrations, Ballot{
account: account,
content: signature,
})
return false
})
ballots := []Ballot{}
tokensPerVote, ok := sdk.NewIntFromString(params.TokensPerVote)
if !ok {
panic("failed to load params tokens_per_vote")
}
for _, registration := range registrations {
// get validator
2024-06-07 07:47:56 +00:00
accAddr, err := sdk.AccAddressFromHexUnsafe(registration.account)
2024-05-09 18:54:47 +00:00
if err != nil {
k.Logger(ctx).Error("[BeginBlock] invalid account")
continue
}
2024-06-07 07:47:56 +00:00
bonded := k.GetDelegatorBonded(ctx, accAddr)
num := bonded.Quo(sdk.NewInt(1_000_000_000_000_000_000)).Quo(tokensPerVote).Abs().BigInt()
if num.Cmp(big.NewInt(int64(params.MaxVotesPerSigner))) > 0 {
num = big.NewInt(int64(params.MaxVotesPerSigner))
2024-05-09 18:54:47 +00:00
}
content := registration.content
ballotNum := num.Int64()
for j := 0; j < int(ballotNum); j += 1 {
ballots = append(ballots, Ballot{
account: registration.account,
content: content,
})
content = crypto.Keccak256(content)
}
}
sort.Slice(ballots, func(i, j int) bool {
return bytes.Compare(ballots[i].content, ballots[j].content) < 0
})
2024-05-16 14:49:29 +00:00
quorums := types.Quorums{
Quorums: make([]*types.Quorum, 0),
2024-05-09 18:54:47 +00:00
}
2024-05-16 14:49:29 +00:00
if len(ballots) >= int(params.EncodedSlices) {
2024-05-16 15:46:12 +00:00
for i := 0; i+int(params.EncodedSlices) <= len(ballots); i += int(params.EncodedSlices) {
2024-05-16 15:39:07 +00:00
if int(params.MaxQuorums) < len(quorums.Quorums) {
break
}
2024-05-16 14:49:29 +00:00
quorum := types.Quorum{
Signers: make([]string, params.EncodedSlices),
}
for j := 0; j < int(params.EncodedSlices); j += 1 {
quorum.Signers[j] = ballots[i+j].account
}
quorums.Quorums = append(quorums.Quorums, &quorum)
}
2024-05-16 15:46:12 +00:00
if len(ballots)%int(params.EncodedSlices) != 0 && int(params.MaxQuorums) > len(quorums.Quorums) {
2024-05-16 15:39:07 +00:00
quorum := types.Quorum{
Signers: make([]string, 0),
}
for j := len(ballots) - int(params.EncodedSlices); j < len(ballots); j += 1 {
quorum.Signers = append(quorum.Signers, ballots[j].account)
}
quorums.Quorums = append(quorums.Quorums, &quorum)
}
2024-05-16 15:25:43 +00:00
} else if len(ballots) > 0 {
2024-05-16 14:49:29 +00:00
quorum := types.Quorum{
Signers: make([]string, params.EncodedSlices),
2024-05-09 18:54:47 +00:00
}
2024-05-16 14:49:29 +00:00
n := len(ballots)
for i := 0; i < int(params.EncodedSlices); i += 1 {
quorum.Signers[i] = ballots[i%n].account
}
quorums.Quorums = append(quorums.Quorums, &quorum)
2024-05-16 15:25:43 +00:00
} else {
quorums.Quorums = append(quorums.Quorums, &types.Quorum{
Signers: make([]string, 0),
})
2024-05-09 18:54:47 +00:00
}
2024-05-16 14:49:29 +00:00
2024-05-09 18:54:47 +00:00
// save to store
2024-05-16 14:49:29 +00:00
k.SetEpochQuorums(ctx, expectedEpoch, quorums)
2024-05-09 18:54:47 +00:00
k.SetEpochNumber(ctx, expectedEpoch)
}