Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(dogfood): prepare for app addition #29

Merged
13 changes: 0 additions & 13 deletions proto/exocore/dogfood/v1/dogfood.proto
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
syntax = "proto3";

Check failure on line 1 in proto/exocore/dogfood/v1/dogfood.proto

View workflow job for this annotation

GitHub Actions / break-check

Previously present message "HeaderSubset" was deleted from file.

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 @@
// 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
Loading