Skip to content

Commit

Permalink
fix(operator,delegation): cross-module validation
Browse files Browse the repository at this point in the history
Assumptions:
- `assets` module genesis is only responsible for deposits
- `delegation` module genesis then locks up the assets based on its
  genesis state, from its own perspective as well as in the `assets`
  module.
- `operator` module genesis verifies that the delegated amount provided
  to it is the same as that provided to the delegation module.
  • Loading branch information
MaxMustermann2 committed Apr 2, 2024
1 parent db68878 commit bccb94a
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
16 changes: 14 additions & 2 deletions x/delegation/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
"fmt"

assetstype "github.com/ExocoreNetwork/exocore/x/assets/types"
delegationtype "github.com/ExocoreNetwork/exocore/x/delegation/types"
abci "github.com/cometbft/cometbft/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -22,7 +23,7 @@ func (k Keeper) InitGenesis(
operatorAddress := c.OperatorAddress
// #nosec G703 // already validated
accAddress, _ := sdk.AccAddressFromBech32(operatorAddress)
amount := c.Amount
amount := c.Amount // delegation amount
if !k.operatorKeeper.IsOperator(ctx, accAddress) {
// the operator must be registered first, so the
// genesis of the operator module comes before this module
Expand All @@ -33,7 +34,8 @@ func (k Keeper) InitGenesis(
),
)
}
// at genesis, the operator cannot be frozen so skip that.
// at genesis, the operator cannot be frozen so skip that check.
// validate that enough deposits exist before delegation.
info, err := k.assetsKeeper.GetStakerSpecifiedAssetInfo(ctx, stakerID, assetID)
if err != nil {
panic(err)
Expand All @@ -60,6 +62,16 @@ func (k Keeper) InitGenesis(
); err != nil {
panic(err)
}
// also tell the assetsKeeper to mark this as a delegation.
if err := k.assetsKeeper.UpdateStakerAssetState(
ctx, stakerID, assetID, assetstype.StakerSingleAssetChangeInfo{
WithdrawableAmount: amount.Neg(),
}); err != nil {
panic(err)
}
// we have checked that delegation amount > deposit amount for each asset.
// we don't need to check for the total amount, since this genesis only handles
// delegation amounts (others are implicitly zero).
}
}
}
Expand Down
30 changes: 29 additions & 1 deletion x/operator/keeper/genesis.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package keeper

import (
"fmt"

"cosmossdk.io/math"
delegationtypes "github.com/ExocoreNetwork/exocore/x/delegation/types"
"github.com/ExocoreNetwork/exocore/x/operator/types"
abci "github.com/cometbft/cometbft/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -37,10 +41,17 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state types.GenesisState) []abci.Va
}
}
// state_update.go
stakerAssetOperatorMap := make(map[string]map[string]map[string]math.Int)
for _, level1 := range state.StakerRecords {
stakerID := level1.StakerID
if _, ok := stakerAssetOperatorMap[stakerID]; !ok {
stakerAssetOperatorMap[stakerID] = make(map[string]map[string]math.Int)
}
for _, level2 := range level1.StakerDetails {
assetID := level2.AssetID
if _, ok := stakerAssetOperatorMap[stakerID][assetID]; !ok {
stakerAssetOperatorMap[stakerID][assetID] = make(map[string]math.Int)
}
for _, level3 := range level2.Details {
operatorAddress := level3.OperatorAddress
amount := level3.Amount
Expand All @@ -49,10 +60,27 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state types.GenesisState) []abci.Va
); err != nil {
panic(err)
}

if _, ok := stakerAssetOperatorMap[stakerID][assetID][operatorAddress]; !ok {
stakerAssetOperatorMap[stakerID][assetID][operatorAddress] = math.ZeroInt()
}
stakerAssetOperatorMap[stakerID][assetID][operatorAddress].Add(amount)
}
}
}
// validate the information in the delegation keeper,
// which has validated it in the assets keeper.
checkFunc := func(
stakerID, assetID, operatorAddress string, state *delegationtypes.DelegationAmounts,
) error {
valueHere := stakerAssetOperatorMap[stakerID][assetID][operatorAddress]
if !valueHere.Equal(state.UndelegatableAmount) {
panic(fmt.Sprintf("undelegatable amount mismatch: %s", operatorAddress))
}
return nil
}
// since this module only knows the delegated value (and not the deposit value),
// it cannot do any further validation with the data in the assets keeper.
k.delegationKeeper.IterateDelegationState(ctx, checkFunc)

Check failure on line 83 in x/operator/keeper/genesis.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

Error return value of `k.delegationKeeper.IterateDelegationState` is not checked (errcheck)

Check warning

Code scanning / gosec

Errors unhandled. Warning

Errors unhandled.
return []abci.ValidatorUpdate{}
}

Expand Down

0 comments on commit bccb94a

Please sign in to comment.