Skip to content

Commit

Permalink
Merge pull request #115 from ExocoreNetwork/dogfood-part2
Browse files Browse the repository at this point in the history
 feat(dogfood): add parameters
  • Loading branch information
MaxMustermann2 authored Feb 28, 2024
2 parents 92be565 + 5203fcd commit 728c580
Show file tree
Hide file tree
Showing 30 changed files with 4,348 additions and 74 deletions.
10 changes: 7 additions & 3 deletions proto/buf.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ deps:
owner: cosmos
repository: cosmos-proto
commit: 1935555c206d4afb9e94615dfd0fad31
digest: shake256:c74d91a3ac7ae07d579e90eee33abf9b29664047ac8816500cf22c081fec0d72d62c89ce0bebafc1f6fec7aa5315be72606717740ca95007248425102c365377
- remote: buf.build
owner: cosmos
repository: cosmos-sdk
commit: 508e19f5f37549e3a471a2a59b903c00
commit: 954f7b05f38440fc8250134b15adec47
digest: shake256:2ab4404fd04a7d1d52df0e2d0f2d477a3d83ffd88d876957bf3fedfd702c8e52833d65b3ce1d89a3c5adf2aab512616b0e4f51d8463f07eda9a8a3317ee3ac54
- remote: buf.build
owner: cosmos
repository: gogo-proto
commit: 34d970b699f84aa382f3c29773a60836
commit: 88ef6483f90f478fb938c37dde52ece3
digest: shake256:89c45df2aa11e0cff97b0d695436713db3d993d76792e9f8dc1ae90e6ab9a9bec55503d48ceedd6b86069ab07d3041b32001b2bfe0227fa725dd515ff381e5ba
- remote: buf.build
owner: googleapis
repository: googleapis
commit: 783e4b5374fa488ab068d08af9658438
commit: e874a0be2bf140a5a4c7d4122c635823
digest: shake256:4fe3036b4d706f6ee2b13c730bd04777f021dfd02ed27e6e40480acfe664a7548238312ee0727fd77648a38d227e296d43f4a38a34cdd46068156211016d9657
2 changes: 1 addition & 1 deletion proto/buf.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: v1
name: buf.build/evmos/evmos
deps:
- buf.build/cosmos/cosmos-sdk
- buf.build/cosmos/cosmos-sdk:v0.47.0
- buf.build/cosmos/cosmos-proto
- buf.build/cosmos/gogo-proto
- buf.build/googleapis/googleapis
Expand Down
108 changes: 108 additions & 0 deletions proto/exocore/dogfood/v1/dogfood.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
syntax = "proto3";

package exocore.dogfood.v1;

import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";

import "cosmos_proto/cosmos.proto";
import "tendermint/crypto/keys.proto";
import "cosmos/staking/v1beta1/staking.proto";

option go_package = "github.com/ExocoreNetwork/exocore/x/dogfood/types";

// ExocoreValidator is a validator that is part of the Exocore network. It is
// used to validate and sign blocks and transactions.
message ExocoreValidator {
// The address, as derived from the consensus key. It has no relation
// with the operator's account address.
bytes address = 1;
// Last known power
int64 power = 2;
// pubkey is the consensus public key of the validator, as a Protobuf Any.
google.protobuf.Any pubkey = 3 [
(cosmos_proto.accepts_interface) = "cosmos.crypto.PubKey",
(gogoproto.moretags) = "yaml:\"consensus_pubkey\""
];
}

// OperationType is used to indicate the type of operation that is being
// cached by the module to create the updated validator set.
enum OperationType {
option (gogoproto.goproto_enum_prefix) = false;
// KeyOpUnspecified is used to indicate that the operation type is not specified.
// This should never be used.
OPERATION_TYPE_UNSPECIFIED = 0 [ (gogoproto.enumvalue_customname) = "KeyOpUnspecified" ];
// KeyAddition is used to indicate that the operation is a key addition.
OPERATION_TYPE_ADDITION_OR_UPDATE = 1 [ (gogoproto.enumvalue_customname) = "KeyAdditionOrUpdate" ];
// KeyRemoval is used to indicate that the operation is a key removal. Typically
// this is done due to key replacement mechanism and not directly.
OPERATION_TYPE_REMOVAL = 2 [ (gogoproto.enumvalue_customname) = "KeyRemoval" ];
}

// QueueResultType is used to indicate the result of the queue operation.
enum QueueResultType {
option (gogoproto.goproto_enum_prefix) = false;
// QueueResultUnspecified is used to indicate that the queue result type is not specified.
QUEUE_RESULT_TYPE_UNSPECIFIED = 0 [ (gogoproto.enumvalue_customname) = "QueueResultUnspecified" ];
// QueueResultSuccess is used to indicate that the queue operation was successful.
QUEUE_RESULT_TYPE_SUCCESS = 1 [ (gogoproto.enumvalue_customname) = "QueueResultSuccess" ];
// QueueResultExists is used to indicate that the queue operation failed because the
// operation already exists in the queue.
QUEUE_RESULT_TYPE_EXISTS = 2 [ (gogoproto.enumvalue_customname) = "QueueResultExists" ];
// QueueResultRemoved is used to indicate that the queue operation resulted in an existing
// operation being removed from the queue.
QUEUE_RESULT_TYPE_REMOVED = 3 [ (gogoproto.enumvalue_customname) = "QueueResultRemoved" ];
}

// Operation is used to indicate the operation that is being cached by the module
// to create the updated validator set.
message Operation {
// OperationType is the type of the operation (addition / removal).
OperationType operation_type = 1;
// OperatorAddress is the sdk.AccAddress of the operator.
bytes operator_address = 2;
// PubKey is the public key for which the operation is being applied.
tendermint.crypto.PublicKey pub_key = 3 [(gogoproto.nullable) = false];
}

// Operations is a collection of Operation.
message Operations {
repeated Operation list = 1 [(gogoproto.nullable) = false];
}

// AccountAddresses represents a list of account addresses. It is used to store the list of
// operator addresses whose operations are maturing at an epoch.
message AccountAddresses {
repeated bytes list = 1;
}

// ConsensusAddresses represents a list of account addresses. It is used to store the list of
// addresses (which correspond to operator public keys) to delete at the end of an epoch.
message ConsensusAddresses {
repeated bytes list = 1;
}

// UndelegationRecordKeys is a collection of undelegation record keys. This is used to store a
// list of undelegation records to mature in the delegation module at the end of the epoch.
message UndelegationRecordKeys {
repeated bytes list = 1;
}

// Validators is a list of validators stored according to the staking module.
message Validators {
repeated cosmos.staking.v1beta1.Validator list = 1 [(gogoproto.nullable) = false];
}

// HeaderSubset is a subset of the block header that is relevant to the IBC codebase. It is
// stored for each height and then converted to the `tm.Header` object after queried. It is
// pruned when the information is no longer needed according to the `HistoricalEntries` param.
message HeaderSubset {
// timestamp of the block
google.protobuf.Timestamp time = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
// validators for the next block
bytes next_validators_hash = 2;
// state after txs from the previous block
bytes app_hash = 3;
}
8 changes: 8 additions & 0 deletions proto/exocore/dogfood/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@ syntax = "proto3";
package exocore.dogfood.v1;

import "gogoproto/gogo.proto";

import "tendermint/abci/types.proto";

import "exocore/dogfood/v1/params.proto";

option go_package = "github.com/ExocoreNetwork/exocore/x/dogfood/types";

// GenesisState defines the dogfood module's genesis state.
message GenesisState {
// Parameters of the module.
Params params = 1 [(gogoproto.nullable) = false];

// Validator set, stored by ExocoreValidatorKey.
repeated .tendermint.abci.ValidatorUpdate val_set = 2
[ (gogoproto.nullable) = false ];
}
12 changes: 11 additions & 1 deletion proto/exocore/dogfood/v1/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,15 @@ option go_package = "github.com/ExocoreNetwork/exocore/x/dogfood/types";
// Params defines the parameters for the module.
message Params {
option (gogoproto.goproto_stringer) = false;

// EpochsUntilUnbonded is the number of epochs after which an unbonding
// is released. Note that it starts from the beginning of the next epoch
// in which the unbonding request was received. At that point, the vote
// power is reduced by the amount of the unbonding operation.
uint32 epochs_until_unbonded = 1;
// EpochIdentifier is the identifier of the epoch (week, hour, day).
string epoch_identifier = 2;
// MaxValidators is the maximum number of validators.
uint32 max_validators = 3;
// HistoricalEntries is the number of historical entries to persist.
uint32 historical_entries = 4;
}
20 changes: 0 additions & 20 deletions x/dogfood/genesis.go

This file was deleted.

67 changes: 67 additions & 0 deletions x/dogfood/keeper/abci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package keeper

import (
"github.com/ExocoreNetwork/exocore/x/dogfood/types"
abci "github.com/cometbft/cometbft/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)

func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate {
// start with clearing the hold on the undelegations.
undelegations := k.GetPendingUndelegations(ctx)
for _, undelegation := range undelegations.GetList() {
k.delegationKeeper.DecrementUndelegationHoldCount(ctx, undelegation)
}
k.ClearPendingUndelegations(ctx)
// then, let the operator module know that the opt out has finished.
optOuts := k.GetPendingOptOuts(ctx)
for _, addr := range optOuts.GetList() {
k.operatorKeeper.CompleteOperatorOptOutFromChainId(ctx, addr, ctx.ChainID())
}
k.ClearPendingOptOuts(ctx)
// for slashing, the operator module is required to store a mapping of chain id + cons addr
// to operator address. this information can now be pruned, since the opt out is considered
// complete.
consensusAddrs := k.GetPendingConsensusAddrs(ctx)
for _, consensusAddr := range consensusAddrs.GetList() {
k.operatorKeeper.DeleteOperatorAddressForChainIdAndConsAddr(
ctx, ctx.ChainID(), consensusAddr,
)
}
k.ClearPendingConsensusAddrs(ctx)
// finally, perform the actual operations of vote power changes.
operations := k.GetPendingOperations(ctx)
id, _ := k.GetValidatorSetID(ctx, ctx.BlockHeight())
if len(operations.GetList()) == 0 {
// there is no validator set change, so we just increment the block height
// and retain the same val set id mapping.
k.SetValidatorSetID(ctx, ctx.BlockHeight()+1, id)
return []abci.ValidatorUpdate{}
}
res := make([]abci.ValidatorUpdate, 0, len(operations.GetList()))
for _, operation := range operations.GetList() {
switch operation.OperationType {
case types.KeyAdditionOrUpdate:
power, err := k.restakingKeeper.GetOperatorAssetValue(
ctx, operation.OperatorAddress,
)
if err != nil {
panic(err)
}
res = append(res, abci.ValidatorUpdate{
PubKey: operation.PubKey,
Power: power,
})
case types.KeyRemoval:
res = append(res, abci.ValidatorUpdate{
PubKey: operation.PubKey,
Power: 0,
})
case types.KeyOpUnspecified:
panic("unspecified operation type")
}
}
// call via wrapper function so that validator info is stored.
// the id is incremented by 1 for the next block.
return k.ApplyValidatorChanges(ctx, res, id+1, false)
}
33 changes: 33 additions & 0 deletions x/dogfood/keeper/genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package keeper

import (
"github.com/ExocoreNetwork/exocore/x/dogfood/types"
abci "github.com/cometbft/cometbft/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)

// InitGenesis initializes the module's state from a provided genesis state.
func (k Keeper) InitGenesis(
ctx sdk.Context,
genState types.GenesisState,
) []abci.ValidatorUpdate {
k.SetParams(ctx, genState.Params)
// the `params` validator is not super useful to validate state level information
// so, it must be done here. by extension, the `InitGenesis` of the epochs module
// should be called before that of this module.
_, found := k.epochsKeeper.GetEpochInfo(ctx, genState.Params.EpochIdentifier)
if !found {
// the panic is suitable here because it is being done at genesis, when the node
// is not running. it means that the genesis file is malformed.
panic("epoch info not found")
}
return k.ApplyValidatorChanges(ctx, genState.ValSet, types.InitialValidatorSetID, true)
}

// ExportGenesis returns the module's exported genesis
func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {
genesis := types.DefaultGenesis()
genesis.Params = k.GetDogfoodParams(ctx)

return genesis
}
34 changes: 34 additions & 0 deletions x/dogfood/keeper/hooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package keeper

import (
"github.com/ExocoreNetwork/exocore/x/dogfood/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)

// interface guard
var _ types.DogfoodHooks = &MultiDogfoodHooks{}

// MultiDogfoodHooks is a collection of DogfoodHooks. It calls the hook for each element in the
// collection one-by-one. The hook is called in the order in which the collection is created.
type MultiDogfoodHooks []types.DogfoodHooks

// NewMultiDogfoodHooks is used to create a collective object of dogfood hooks from a list of
// the hooks. It follows the "accept interface, return concrete types" philosophy. Other modules
// may set the hooks by calling k := (*k).SetHooks(NewMultiDogfoodHooks(hookI))
func NewMultiDogfoodHooks(hooks ...types.DogfoodHooks) MultiDogfoodHooks {
return hooks
}

// AfterValidatorBonded is the implementation of types.DogfoodHooks for MultiDogfoodHooks.
func (hooks MultiDogfoodHooks) AfterValidatorBonded(
ctx sdk.Context,
consAddr sdk.ConsAddress,
operator sdk.ValAddress,
) error {
for _, hook := range hooks {
if err := hook.AfterValidatorBonded(ctx, consAddr, operator); err != nil {
return err
}
}
return nil
}
Loading

0 comments on commit 728c580

Please sign in to comment.