Skip to content

Commit

Permalink
Merge pull request #29 from MaxMustermann2/refactor/dogfood-compat
Browse files Browse the repository at this point in the history
refactor(dogfood): prepare for `app` addition
  • Loading branch information
MaxMustermann2 authored Apr 11, 2024
2 parents 3eb094d + d5a9aed commit a6705f3
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 581 deletions.
13 changes: 0 additions & 13 deletions proto/exocore/dogfood/v1/dogfood.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package exocore.dogfood.v1;

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

import "cosmos/staking/v1beta1/staking.proto";
import "cosmos_proto/cosmos.proto";
Expand Down Expand Up @@ -53,15 +52,3 @@ message Validators {
// list is the list of 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: 3 additions & 5 deletions x/dogfood/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ import (
)

func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate {
id, _ := k.getValidatorSetID(ctx, ctx.BlockHeight())
if !k.IsEpochEnd(ctx) {
// save the same id for the next block height.
k.setValidatorSetID(ctx, ctx.BlockHeight()+1, id)
return []abci.ValidatorUpdate{}
}
defer k.ClearEpochEnd(ctx)
Expand Down Expand Up @@ -114,6 +111,7 @@ func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate {
}
// the remaining validators in prevMap have been removed.
// we need to queue a change in power to 0 for them.
// we cannot iterate over the map to retain determinism, so we iterate over the list.
for _, validator := range prevList { // O(N)
// #nosec G703 // already checked in the previous iteration over prevList.
pubKey, _ := validator.ConsPubKey()
Expand All @@ -130,9 +128,9 @@ func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate {
})
}
}

// 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)
return k.ApplyValidatorChanges(ctx, res)
}

// sortByPower sorts operators, their pubkeys, and their powers by the powers.
Expand Down
2 changes: 1 addition & 1 deletion x/dogfood/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (k Keeper) InitGenesis(

// ApplyValidatorChanges will sort it internally
return k.ApplyValidatorChanges(
ctx, out, types.InitialValidatorSetID,
ctx, out,
)
}

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

import (
"github.com/ExocoreNetwork/exocore/utils"
sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
erc20types "github.com/evmos/evmos/v14/x/erc20/types"
evmtypes "github.com/evmos/evmos/v14/x/evm/types"
)

// interface guards
var (
_ erc20types.StakingKeeper = Keeper{}
_ evmtypes.StakingKeeper = Keeper{}
)

// GetValidatorByConsAddr is an implementation of the StakingKeeper interface
// expected by the EVM module. It returns a validator given a consensus address.
// The EVM module uses it to determine the proposer's AccAddress for the block.
// ConsAddress -> lookup AccAddress -> convert to ValAddress -> bech32ify.
// ValAddress string is then decoded back by the EVM module to get bytes, which
// make the 0x address of the coinbase.
func (k Keeper) GetValidatorByConsAddr(
ctx sdk.Context, consAddr sdk.ConsAddress,
) (validator stakingtypes.Validator, found bool) {
val := k.ValidatorByConsAddr(ctx, consAddr)
if val == nil {
return stakingtypes.Validator{}, false
}
return val.(stakingtypes.Validator), true
}

// BondDenom is an implementation of the StakingKeeper interface expected by the
// ERC20 module. It returns the bond denom for the module. The ERC20 module uses
// this function to determine whether a token sent (or received) over IBC is the
// staking (==native) token. If it is, then the module lets the token through.
// That is the behavior we wish to retain with our chain as well.
func (k Keeper) BondDenom(sdk.Context) string {
return utils.BaseDenom
}
103 changes: 100 additions & 3 deletions x/dogfood/keeper/impl_sdk.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package keeper

import (
"sort"

"cosmossdk.io/math"
operatortypes "github.com/ExocoreNetwork/exocore/x/operator/types"
abci "github.com/cometbft/cometbft/abci/types"
tmtypes "github.com/cometbft/cometbft/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
Expand All @@ -17,6 +23,7 @@ var (
_ evidencetypes.StakingKeeper = Keeper{}
_ genutiltypes.StakingKeeper = Keeper{}
_ clienttypes.StakingKeeper = Keeper{} // implemented in `validators.go`
_ govtypes.StakingKeeper = Keeper{}
)

// GetParams is an implementation of the staking interface expected by the SDK's evidence
Expand Down Expand Up @@ -61,9 +68,7 @@ func (k Keeper) ValidatorByConsAddr(
ctx sdk.Context,
addr sdk.ConsAddress,
) stakingtypes.ValidatorI {
return stakingtypes.Validator{
Jailed: k.operatorKeeper.IsOperatorJailedForChainID(ctx, addr, ctx.ChainID()),
}
return k.operatorKeeper.ValidatorByConsAddrForChainID(ctx, addr, ctx.ChainID())
}

// Slash is an implementation of the staking interface expected by the SDK's slashing module.
Expand Down Expand Up @@ -158,3 +163,95 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(
) (updates []abci.ValidatorUpdate, err error) {
return
}

// IterateBondedValidatorsByPower is an implementation of the staking interface expected by
// the SDK's gov module. It is used to iterate through the validators by power. We do not
// implement this function intentionally, since our model of governance is not designed yet.
// Instead of staked tokens representing vote power for governance, the balance (or locked)
// balance of the native token (by operator or delegator) should be used.
// See interchain-security as a reference (although I did not understand some of it),
func (k Keeper) IterateBondedValidatorsByPower(
sdk.Context, func(int64, stakingtypes.ValidatorI) bool,
) {
// // we will have at most a 100 validators bonded.
// // so it is safe to load all of them up and then call.
// validators := k.GetAllExocoreValidators(ctx)
// sort.SliceStable(validators, func(i, j int) bool {
// return validators[i].Power > validators[j].Power
// })
// for i, v := range validators {
// pk, err := v.ConsPubKey()
// if err != nil {
// // since we stored the validator in the first place, something like this
// // should never happen, but if it does it is an extremely grave error
// // that will result in a block mismatch and hence that node will halt.
// continue
// }
// val, err := stakingtypes.NewValidator(nil, pk, stakingtypes.Description{})
// if err != nil {
// // same as above.
// continue
// }

// // Set validator to bonded status
// val.Status = stakingtypes.Bonded
// // Compute tokens from voting power
// val.Tokens = sdk.TokensFromConsensusPower(v.Power, sdk.DefaultPowerReduction)
// // #nosec G701 // ok on 64-bit systems.
// if f(int64(i), val) {
// break
// }
// }
panic("unimplemented on this keeper")
}

// TotalBondedTokens is an implementation of the staking interface expected by the SDK's
// gov module. See note above to understand why this is not implemented.
func (k Keeper) TotalBondedTokens(sdk.Context) math.Int {
panic("unimplemented on this keeper")
}

// IterateDelegations is an implementation of the staking interface expected by the SDK's
// gov module. See note above to understand why this is not implemented.
func (k Keeper) IterateDelegations(
sdk.Context, sdk.AccAddress,
func(int64, stakingtypes.DelegationI) bool,
) {
panic("unimplemented on this keeper")
}

func (k Keeper) WriteValidators(ctx sdk.Context) ([]tmtypes.GenesisValidator, error) {
validators := k.GetAllExocoreValidators(ctx)
sort.SliceStable(validators, func(i, j int) bool {
return validators[i].Power > validators[j].Power
})
vals := make([]tmtypes.GenesisValidator, len(validators))
var retErr error
for i, val := range validators {
pk, err := val.ConsPubKey()
if err != nil {
retErr = err
break
}
tmPk, err := cryptocodec.ToTmPubKeyInterface(pk)
if err != nil {
retErr = err
break
}
consAddress := sdk.GetConsAddress(pk)
found, addr := k.operatorKeeper.GetOperatorAddressForChainIDAndConsAddr(
ctx, ctx.ChainID(), consAddress,
)
if !found {
retErr = operatortypes.ErrNoKeyInTheStore
break
}
vals[i] = tmtypes.GenesisValidator{
Address: consAddress.Bytes(),
PubKey: tmPk,
Power: val.Power,
Name: addr.String(), // TODO
}
}
return vals, retErr
}
Loading

0 comments on commit a6705f3

Please sign in to comment.