Skip to content

Commit

Permalink
feat(genesis bridge): genesis transfers (#449)
Browse files Browse the repository at this point in the history
  • Loading branch information
danwt authored Jun 19, 2024
1 parent 6aaf3c7 commit b3343e1
Show file tree
Hide file tree
Showing 26 changed files with 523 additions and 1,562 deletions.
14 changes: 1 addition & 13 deletions proto/hub-genesis/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,6 @@ import "gogoproto/gogo.proto";
// Params holds parameters for the hub-genesis module.
message Params {
option (gogoproto.goproto_stringer) = false;

// genesis_triggerer_allowlist is a list of the
// accounts that are allowed to trigger a genesis event on the rollapp.
// In the case of an empty list, there are no restrictions
repeated GenesisTriggererParams genesis_triggerer_allowlist = 1 [
(gogoproto.moretags) = "yaml:\"genesis_triggerer_allowlist\"",
(gogoproto.nullable) = false
];
reserved 1;
}

message GenesisTriggererParams {
// address is a bech32-encoded address of the
// accounts that are allowed to trigger a rollapp genesis event.
string address = 1 [ (gogoproto.moretags) = "yaml:\"address\"" ];
}
23 changes: 15 additions & 8 deletions proto/hub-genesis/state.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ option go_package = "github.com/dymensionxyz/dymension-rdk/x/hub-genesis/types";

// State holds the state of the genesis event
message State {
// is_locked is a boolean that indicates if the genesis event has occured
bool is_locked = 1;

// genesis_tokens is the list of tokens that are expected to be locked on genesis event
repeated cosmos.base.v1beta1.Coin genesis_tokens = 2 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
reserved 1;
reserved 2;
// accounts on the Hub to fund with some bootstrapping transfers
repeated GenesisAccount genesis_accounts = 3 [(gogoproto.nullable) = false];
}
/*
TODO: the below is copy pasted, clean up
*/

// GenesisAccount is a struct for the genesis account for the rollapp
message GenesisAccount {
// amount of coins to be sent to the genesis address
cosmos.base.v1beta1.Coin amount = 1 [(gogoproto.nullable) = false];
// address is a bech-32 address of the genesis account
string address = 2;
}
22 changes: 0 additions & 22 deletions proto/hub-genesis/tx.proto

This file was deleted.

36 changes: 3 additions & 33 deletions testutil/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ var (
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
govtypes.ModuleName: {authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
hubgentypes.ModuleName: {authtypes.Burner},
hubgentypes.ModuleName: {authtypes.Minter},
gaslesstypes.ModuleName: nil,
wasmtypes.ModuleName: {authtypes.Burner},
}
Expand Down Expand Up @@ -443,8 +443,6 @@ func NewRollapp(
appCodec,
keys[hubgentypes.StoreKey],
app.GetSubspace(hubgentypes.ModuleName),
app.IBCKeeper.ChannelKeeper,
app.BankKeeper,
app.AccountKeeper,
)

Expand Down Expand Up @@ -525,7 +523,7 @@ func NewRollapp(
ibc.NewAppModule(app.IBCKeeper),
ibctransfer.NewAppModule(app.TransferKeeper),
upgrade.NewAppModule(app.UpgradeKeeper),
hubgenesis.NewAppModule(appCodec, app.HubGenesisKeeper, app.AccountKeeper),
hubgenesis.NewAppModule(appCodec, app.HubGenesisKeeper),
gasless.NewAppModule(appCodec, app.GaslessKeeper),
}

Expand Down Expand Up @@ -684,25 +682,6 @@ func NewRollapp(
return app
}

// func (app *App) setAnteHandler(txConfig client.TxConfig) {
// anteHandler, err := rollappapp.NewAnteHandler(
// rollappapp.HandlerOptions{
// HandlerOptions: ante.HandlerOptions{
// AccountKeeper: app.AccountKeeper,
// BankKeeper: app.BankKeeper,
// SignModeHandler: txConfig.SignModeHandler(),
// SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
// },
// IBCKeeper: app.IBCKeeper,
// },
// )
// if err != nil {
// panic(err)
// }

// app.SetAnteHandler(anteHandler)
// }

func (app *App) setPostHandler() {
postHandler, err := posthandler.NewPostHandler(
posthandler.HandlerOptions{},
Expand Down Expand Up @@ -874,7 +853,7 @@ func (app *App) GetStakingKeeper() ibctestingtypes.StakingKeeper {
return app.StakingKeeper
}

// GetStakingKeeper implements the TestingApp interface.
// GetStakingKeeperSDK implements the TestingApp interface.
func (app *App) GetStakingKeeperSDK() stakingkeeper.Keeper {
return app.StakingKeeper
}
Expand Down Expand Up @@ -906,15 +885,6 @@ func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) {
rtr.PathPrefix("/swagger/").Handler(http.StripPrefix("/swagger/", staticServer))
}

// GetMaccPerms returns a copy of the module account permissions
func GetMaccPerms() map[string][]string {
dupMaccPerms := make(map[string][]string)
for k, v := range maccPerms {
dupMaccPerms[k] = v
}
return dupMaccPerms
}

// initParamsKeeper init params keeper and its subspaces
func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey storetypes.StoreKey) paramskeeper.Keeper {
paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey)
Expand Down
59 changes: 0 additions & 59 deletions x/hub-genesis/client/cli/tx.go

This file was deleted.

15 changes: 0 additions & 15 deletions x/hub-genesis/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,6 @@ import (
// InitGenesis new hub-genesis genesis.
func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) {
k.SetParams(ctx, genState.Params)

modAddress := k.accountKeeper.GetModuleAddress(types.ModuleName)
if !k.accountKeeper.HasAccount(ctx, modAddress) {
k.accountKeeper.GetModuleAccount(ctx, types.ModuleName)
}

// if tokens provided and waiting to be locked, verify the balance
if !genState.State.IsLocked && !genState.State.GenesisTokens.IsZero() {
// get spendable coins in the module account
spendable := k.bankKeeper.SpendableCoins(ctx, modAddress)
// we expect the genesis balance of the module account to be equal to required genesis tokens
if !spendable.IsEqual(genState.State.GenesisTokens) {
panic(types.ErrWrongGenesisBalance)
}
}
k.SetState(ctx, genState.State)
}

Expand Down
1 change: 1 addition & 0 deletions x/hub-genesis/keeper/genesis_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keeper_test

import (
_ "embed"
"testing"

testkeepers "github.com/dymensionxyz/dymension-rdk/testutil/keepers"
Expand Down
120 changes: 120 additions & 0 deletions x/hub-genesis/keeper/ibc_module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package keeper

import (
"fmt"
"time"

errorsmod "cosmossdk.io/errors"

sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
transfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v6/modules/core/02-client/types"
porttypes "github.com/cosmos/ibc-go/v6/modules/core/05-port/types"
"github.com/dymensionxyz/dymension-rdk/x/hub-genesis/types"
)

const (
transferTimeout = time.Hour * 24 * 365
)

type IBCModule struct {
porttypes.IBCModule
k Keeper
transfer Transfer
getDenom GetDenomMetaData
mintCoins MintCoins
}

type (
Transfer func(ctx sdk.Context, transfer *transfertypes.MsgTransfer) error
GetDenomMetaData func(ctx sdk.Context, denom string) (banktypes.Metadata, bool)
MintCoins func(ctx sdk.Context, moduleName string, amt sdk.Coins) error
)

func NewIBCModule(next porttypes.IBCModule, t Transfer, k Keeper, d GetDenomMetaData, m MintCoins) *IBCModule {
return &IBCModule{next, k, t, d, m}
}

// OnChanOpenConfirm will send any unsent genesis account transfers over the channel.
// It is ASSUMED that the channel is for the Hub. This can be ensured by not exposing
// the sequencer API until after genesis is complete.
// Since transfers are only sent once, it does not matter if someone else tries to open
// a channel in future (it will no-op).
func (w IBCModule) OnChanOpenConfirm(
ctx sdk.Context,
portID,
channelID string,
) error {
l := ctx.Logger().With("module", "hubgenesis OnChanOpenConfirm middleware", "port id", portID, "channelID", channelID)

err := w.IBCModule.OnChanOpenConfirm(ctx, portID, channelID)
if err != nil {
l.Error("Next middleware.", "err", err)
return err
}

state := w.k.GetState(ctx)

srcAccount := w.k.accountKeeper.GetModuleAccount(ctx, types.ModuleName)
srcAddr := srcAccount.GetAddress().String()

for i, a := range state.GetGenesisAccounts() {
if err := w.mintAndTransfer(ctx, len(state.GetGenesisAccounts()), a, srcAddr, portID, channelID); err != nil {
// there is no feasible way to recover
panic(fmt.Errorf("mint and transfer: %w", err))
}
l.Info("Sent genesis transfer.", "index", i, "receiver", a.GetAddress(), "coin", a)
}

state.GenesisAccounts = nil

w.k.SetState(ctx, state)

l.Info("Sent all genesis transfers.")

return nil
}

func (w IBCModule) mintAndTransfer(
ctx sdk.Context,
n int,
a types.GenesisAccount,
srcAddr string,
portID string,
channelID string,
) error {
coin := a.GetAmount()
err := w.mintCoins(ctx, types.ModuleName, sdk.Coins{coin})
if err != nil {
return errorsmod.Wrap(err, "mint coins")
}

// NOTE: for simplicity we don't optimize to avoid sending duplicate metadata
// we assume the hub will deduplicate. We expect to eventually get a timeout
// or commit anyway, so the packet will be cleared up.
// (Actually, since transfers may arrive out of order, we must include the
// denom metadata anyway).
memo, err := w.createMemo(ctx, a.Amount.Denom, n)
if err != nil {
return errorsmod.Wrap(err, "create memo")
}

m := transfertypes.MsgTransfer{
SourcePort: portID,
SourceChannel: channelID,
Token: a.Amount,
Sender: srcAddr,
Receiver: a.GetAddress(),
TimeoutHeight: clienttypes.Height{},
TimeoutTimestamp: uint64(ctx.BlockTime().Add(transferTimeout).UnixNano()),
Memo: memo,
}

err = w.transfer(skipContext(ctx), &m)
if err != nil {
return errorsmod.Wrap(err, "transfer")
}

return nil
}
Loading

0 comments on commit b3343e1

Please sign in to comment.