mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 14:47:26 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			324 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			324 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package keeper
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
 | 
						|
	errorsmod "cosmossdk.io/errors"
 | 
						|
	"github.com/coniks-sys/coniks-go/crypto/vrf"
 | 
						|
	"github.com/cosmos/cosmos-sdk/codec"
 | 
						|
	"github.com/cosmos/cosmos-sdk/store/prefix"
 | 
						|
	storetypes "github.com/cosmos/cosmos-sdk/store/types"
 | 
						|
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						|
	"github.com/tendermint/tendermint/libs/log"
 | 
						|
 | 
						|
	"github.com/0glabs/0g-chain/x/council/v1/types"
 | 
						|
)
 | 
						|
 | 
						|
// Keeper of the inflation store
 | 
						|
type Keeper struct {
 | 
						|
	storeKey      storetypes.StoreKey
 | 
						|
	cdc           codec.BinaryCodec
 | 
						|
	stakingKeeper types.StakingKeeper
 | 
						|
}
 | 
						|
 | 
						|
// NewKeeper creates a new mint Keeper instance
 | 
						|
func NewKeeper(
 | 
						|
	storeKey storetypes.StoreKey,
 | 
						|
	cdc codec.BinaryCodec,
 | 
						|
	stakingKeeper types.StakingKeeper,
 | 
						|
) Keeper {
 | 
						|
	return Keeper{
 | 
						|
		storeKey:      storeKey,
 | 
						|
		cdc:           cdc,
 | 
						|
		stakingKeeper: stakingKeeper,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Logger returns a module-specific logger.
 | 
						|
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
 | 
						|
	return ctx.Logger().With("module", "x/"+types.ModuleName)
 | 
						|
}
 | 
						|
 | 
						|
// ------------------------------------------
 | 
						|
//				Councils
 | 
						|
// ------------------------------------------
 | 
						|
 | 
						|
func (k Keeper) SetCurrentCouncilID(ctx sdk.Context, id uint64) {
 | 
						|
	store := ctx.KVStore(k.storeKey)
 | 
						|
	store.Set(types.CurrentCouncilIDKey, types.GetKeyFromID(id))
 | 
						|
}
 | 
						|
 | 
						|
func (k Keeper) GetCurrentCouncilID(ctx sdk.Context) (uint64, error) {
 | 
						|
	store := ctx.KVStore(k.storeKey)
 | 
						|
	bz := store.Get(types.CurrentCouncilIDKey)
 | 
						|
	if bz == nil {
 | 
						|
		return 0, errorsmod.Wrap(types.ErrInvalidGenesis, "current council ID not set at genesis")
 | 
						|
	}
 | 
						|
	return types.Uint64FromBytes(bz), nil
 | 
						|
}
 | 
						|
 | 
						|
func (k Keeper) IncrementCurrentCouncilID(ctx sdk.Context) error {
 | 
						|
	id, err := k.GetCurrentCouncilID(ctx)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	k.SetCurrentCouncilID(ctx, id+1)
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (k Keeper) SetVotingStartHeight(ctx sdk.Context, votingStartHeight uint64) {
 | 
						|
	store := ctx.KVStore(k.storeKey)
 | 
						|
	store.Set(types.VotingStartHeightKey, types.GetKeyFromID(votingStartHeight))
 | 
						|
}
 | 
						|
 | 
						|
func (k Keeper) GetVotingStartHeight(ctx sdk.Context) (uint64, error) {
 | 
						|
	store := ctx.KVStore(k.storeKey)
 | 
						|
	bz := store.Get(types.VotingStartHeightKey)
 | 
						|
	if bz == nil {
 | 
						|
		return 0, errorsmod.Wrap(types.ErrInvalidGenesis, "voting start height not set at genesis")
 | 
						|
	}
 | 
						|
	return types.Uint64FromBytes(bz), nil
 | 
						|
}
 | 
						|
 | 
						|
func (k Keeper) SetVotingPeriod(ctx sdk.Context, votingPeriod uint64) {
 | 
						|
	store := ctx.KVStore(k.storeKey)
 | 
						|
	store.Set(types.VotingPeriodKey, types.GetKeyFromID(votingPeriod))
 | 
						|
}
 | 
						|
 | 
						|
func (k Keeper) GetVotingPeriod(ctx sdk.Context) (uint64, error) {
 | 
						|
	store := ctx.KVStore(k.storeKey)
 | 
						|
	bz := store.Get(types.VotingPeriodKey)
 | 
						|
	if bz == nil {
 | 
						|
		return 0, errorsmod.Wrap(types.ErrInvalidGenesis, "voting period not set at genesis")
 | 
						|
	}
 | 
						|
	return types.Uint64FromBytes(bz), nil
 | 
						|
}
 | 
						|
 | 
						|
// StoreNewCouncil stores a council, adding a new ID
 | 
						|
func (k Keeper) StoreNewCouncil(ctx sdk.Context, votingStartHeight uint64) error {
 | 
						|
	currentCouncilID, err := k.GetCurrentCouncilID(ctx)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	votingPeriod, err := k.GetVotingPeriod(ctx)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	com := types.Council{
 | 
						|
		ID:                currentCouncilID + 1,
 | 
						|
		VotingStartHeight: votingStartHeight,
 | 
						|
		StartHeight:       votingStartHeight + votingPeriod,
 | 
						|
		EndHeight:         votingStartHeight + votingPeriod*2,
 | 
						|
		Votes:             []types.Vote{},
 | 
						|
		Members:           []sdk.ValAddress{},
 | 
						|
	}
 | 
						|
	k.SetCouncil(ctx, com)
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (k Keeper) GetCouncil(ctx sdk.Context, councilID uint64) (types.Council, bool) {
 | 
						|
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.CouncilKeyPrefix)
 | 
						|
	bz := store.Get(types.GetKeyFromID(councilID))
 | 
						|
	if bz == nil {
 | 
						|
		return types.Council{}, false
 | 
						|
	}
 | 
						|
	var com types.Council
 | 
						|
	k.cdc.MustUnmarshal(bz, &com)
 | 
						|
	return com, true
 | 
						|
}
 | 
						|
 | 
						|
// SetCouncil puts a council into the store.
 | 
						|
func (k Keeper) SetCouncil(ctx sdk.Context, council types.Council) {
 | 
						|
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.CouncilKeyPrefix)
 | 
						|
	bz := k.cdc.MustMarshal(&council)
 | 
						|
	store.Set(types.GetKeyFromID(council.ID), bz)
 | 
						|
}
 | 
						|
 | 
						|
// // DeleteProposal removes a proposal from the store.
 | 
						|
// func (k Keeper) DeleteProposal(ctx sdk.Context, proposalID uint64) {
 | 
						|
// 	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ProposalKeyPrefix)
 | 
						|
// 	store.Delete(types.GetKeyFromID(proposalID))
 | 
						|
// }
 | 
						|
 | 
						|
// IterateProposals provides an iterator over all stored proposals.
 | 
						|
// For each proposal, cb will be called. If cb returns true, the iterator will close and stop.
 | 
						|
func (k Keeper) IterateCouncil(ctx sdk.Context, cb func(proposal types.Council) (stop bool)) {
 | 
						|
	iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.storeKey), types.CouncilKeyPrefix)
 | 
						|
 | 
						|
	defer iterator.Close()
 | 
						|
	for ; iterator.Valid(); iterator.Next() {
 | 
						|
		var council types.Council
 | 
						|
		k.cdc.MustUnmarshal(iterator.Value(), &council)
 | 
						|
		if cb(council) {
 | 
						|
			break
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (k Keeper) GetCouncils(ctx sdk.Context) types.Councils {
 | 
						|
	results := types.Councils{}
 | 
						|
	k.IterateCouncil(ctx, func(prop types.Council) bool {
 | 
						|
		results = append(results, prop)
 | 
						|
		return false
 | 
						|
	})
 | 
						|
	return results
 | 
						|
}
 | 
						|
 | 
						|
// // DeleteProposalAndVotes removes a proposal and its associated votes.
 | 
						|
// func (k Keeper) DeleteProposalAndVotes(ctx sdk.Context, proposalID uint64) {
 | 
						|
// 	votes := k.GetVotesByProposal(ctx, proposalID)
 | 
						|
// 	k.DeleteProposal(ctx, proposalID)
 | 
						|
// 	for _, v := range votes {
 | 
						|
// 		k.DeleteVote(ctx, v.ProposalID, v.Voter)
 | 
						|
// 	}
 | 
						|
// }
 | 
						|
 | 
						|
// ------------------------------------------
 | 
						|
//				Votes
 | 
						|
// ------------------------------------------
 | 
						|
 | 
						|
// GetVote gets a vote from the store.
 | 
						|
func (k Keeper) GetVote(ctx sdk.Context, epochID uint64, voter sdk.ValAddress) (types.Vote, bool) {
 | 
						|
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.VoteKeyPrefix)
 | 
						|
	bz := store.Get(types.GetVoteKey(epochID, voter))
 | 
						|
	if bz == nil {
 | 
						|
		return types.Vote{}, false
 | 
						|
	}
 | 
						|
	var vote types.Vote
 | 
						|
	k.cdc.MustUnmarshal(bz, &vote)
 | 
						|
	return vote, true
 | 
						|
}
 | 
						|
 | 
						|
// SetVote puts a vote into the store.
 | 
						|
func (k Keeper) SetVote(ctx sdk.Context, vote types.Vote) {
 | 
						|
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.VoteKeyPrefix)
 | 
						|
	bz := k.cdc.MustMarshal(&vote)
 | 
						|
	store.Set(types.GetVoteKey(vote.CouncilID, vote.Voter), bz)
 | 
						|
}
 | 
						|
 | 
						|
// DeleteVote removes a Vote from the store.
 | 
						|
func (k Keeper) DeleteVote(ctx sdk.Context, councilID uint64, voter sdk.ValAddress) {
 | 
						|
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.VoteKeyPrefix)
 | 
						|
	store.Delete(types.GetVoteKey(councilID, voter))
 | 
						|
}
 | 
						|
 | 
						|
// IterateVotes provides an iterator over all stored votes.
 | 
						|
// For each vote, cb will be called. If cb returns true, the iterator will close and stop.
 | 
						|
func (k Keeper) IterateVotes(ctx sdk.Context, cb func(vote types.Vote) (stop bool)) {
 | 
						|
	iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.storeKey), types.VoteKeyPrefix)
 | 
						|
 | 
						|
	defer iterator.Close()
 | 
						|
	for ; iterator.Valid(); iterator.Next() {
 | 
						|
		var vote types.Vote
 | 
						|
		k.cdc.MustUnmarshal(iterator.Value(), &vote)
 | 
						|
 | 
						|
		if cb(vote) {
 | 
						|
			break
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// GetVotes returns all stored votes.
 | 
						|
func (k Keeper) GetVotes(ctx sdk.Context) []types.Vote {
 | 
						|
	results := []types.Vote{}
 | 
						|
	k.IterateVotes(ctx, func(vote types.Vote) bool {
 | 
						|
		results = append(results, vote)
 | 
						|
		return false
 | 
						|
	})
 | 
						|
	return results
 | 
						|
}
 | 
						|
 | 
						|
// GetVotesByProposal returns all votes for one proposal.
 | 
						|
func (k Keeper) GetVotesByCouncil(ctx sdk.Context, councilID uint64) []types.Vote {
 | 
						|
	results := []types.Vote{}
 | 
						|
	iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.storeKey), append(types.VoteKeyPrefix, types.GetKeyFromID(councilID)...))
 | 
						|
 | 
						|
	defer iterator.Close()
 | 
						|
	for ; iterator.Valid(); iterator.Next() {
 | 
						|
		var vote types.Vote
 | 
						|
		k.cdc.MustUnmarshal(iterator.Value(), &vote)
 | 
						|
		results = append(results, vote)
 | 
						|
	}
 | 
						|
 | 
						|
	return results
 | 
						|
}
 | 
						|
 | 
						|
// ------------------------------------------
 | 
						|
//				Voters
 | 
						|
// ------------------------------------------
 | 
						|
 | 
						|
func (k Keeper) SetVoter(ctx sdk.Context, voter sdk.ValAddress, pk vrf.PublicKey) {
 | 
						|
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.VoterKeyPrefix)
 | 
						|
	store.Set(types.GetVoterKey(voter), pk)
 | 
						|
	fmt.Printf("voterStoreKey: %v, publicKey: %v\n", types.GetVoterKey(voter), pk)
 | 
						|
}
 | 
						|
 | 
						|
func (k Keeper) IterateVoters(ctx sdk.Context, cb func(voter sdk.ValAddress, pk vrf.PublicKey) (stop bool)) {
 | 
						|
	iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.storeKey), types.VoterKeyPrefix)
 | 
						|
 | 
						|
	defer iterator.Close()
 | 
						|
	for ; iterator.Valid(); iterator.Next() {
 | 
						|
		if cb(sdk.ValAddress(iterator.Key()[1:]), vrf.PublicKey(iterator.Value())) {
 | 
						|
			break
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// GetVotes returns all stored voters
 | 
						|
func (k Keeper) GetVoters(ctx sdk.Context) []sdk.ValAddress {
 | 
						|
	results := []sdk.ValAddress{}
 | 
						|
	k.IterateVoters(ctx, func(voter sdk.ValAddress, _ vrf.PublicKey) bool {
 | 
						|
		results = append(results, voter)
 | 
						|
		return false
 | 
						|
	})
 | 
						|
	return results
 | 
						|
}
 | 
						|
 | 
						|
func (k Keeper) AddVoter(ctx sdk.Context, voter sdk.ValAddress, key []byte) error {
 | 
						|
	if len(key) != vrf.PublicKeySize {
 | 
						|
		return types.ErrInvalidPublicKey
 | 
						|
	}
 | 
						|
 | 
						|
	k.SetVoter(ctx, voter, vrf.PublicKey(key))
 | 
						|
 | 
						|
	ctx.EventManager().EmitEvent(
 | 
						|
		sdk.NewEvent(
 | 
						|
			types.EventTypeRegister,
 | 
						|
			sdk.NewAttribute(types.AttributeKeyVoter, voter.String()),
 | 
						|
			// TODO: types.AttributeKeyPublicKey
 | 
						|
		),
 | 
						|
	)
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (k Keeper) AddVote(ctx sdk.Context, councilID uint64, voter sdk.ValAddress, ballots []*types.Ballot) error {
 | 
						|
	// Validate
 | 
						|
	com, found := k.GetCouncil(ctx, councilID)
 | 
						|
	if !found {
 | 
						|
		return errorsmod.Wrapf(types.ErrUnknownCouncil, "%d", councilID)
 | 
						|
	}
 | 
						|
	if com.HasVotingEndedBy(ctx.BlockHeight()) {
 | 
						|
		return errorsmod.Wrapf(types.ErrProposalExpired, "%d ≥ %d", ctx.BlockHeight(), com.StartHeight)
 | 
						|
	}
 | 
						|
 | 
						|
	// TODO: verify if the voter is registered
 | 
						|
	// TODO: verify whether ballots are valid or not
 | 
						|
 | 
						|
	// Store vote, overwriting any prior vote
 | 
						|
	k.SetVote(ctx, types.NewVote(councilID, voter, ballots))
 | 
						|
 | 
						|
	ctx.EventManager().EmitEvent(
 | 
						|
		sdk.NewEvent(
 | 
						|
			types.EventTypeVote,
 | 
						|
			sdk.NewAttribute(types.AttributeKeyCouncilID, fmt.Sprintf("%d", com.ID)),
 | 
						|
			sdk.NewAttribute(types.AttributeKeyVoter, voter.String()),
 | 
						|
			// TODO: types.AttributeKeyBallots
 | 
						|
		),
 | 
						|
	)
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 |