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

feat(genesis_bridge): revised genesis bridge impl #565

Merged
merged 25 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions proto/hub-genesis/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package rollapp.hub_genesis;

import "gogoproto/gogo.proto";
import "hub-genesis/params.proto";
import "hub-genesis/state.proto";
import "hub-genesis/genesis_info.proto";

option go_package = "github.com/dymensionxyz/dymension-rdk/x/hub-genesis/types";

// GenesisState defines the hub-genesis module's genesis state.
message GenesisState {
// params defines all the parameters of the module.
Params params = 1 [ (gogoproto.nullable) = false ];
State state = 2 [(gogoproto.nullable) = false];
repeated uint64 unacked_transfer_seq_nums = 3 [(gogoproto.nullable) = false];

// accounts on the Hub to fund with some bootstrapping transfers
repeated GenesisAccount genesis_accounts = 2 [ (gogoproto.nullable) = false ];
}
22 changes: 22 additions & 0 deletions proto/hub-genesis/genesis_bridge_data.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

syntax = "proto3";
package rollapp.hub_genesis;

import "gogoproto/gogo.proto";
import "cosmos/bank/v1beta1/bank.proto";
import "ibc/applications/transfer/v2/packet.proto";
import "hub-genesis/genesis_info.proto";

option go_package = "github.com/dymensionxyz/dymension-rdk/x/hub-genesis/types";

// GenesisBridgeData is the data struct that is passed to the hub for the
// genesis bridge flow
message GenesisBridgeData {
// genesis_info is the genesis info of the rollapp. used for hub validation
GenesisInfo genesis_info = 1 [ (gogoproto.nullable) = false ];
// native_denom is the native denom of the rollapp. registered on the hub
cosmos.bank.v1beta1.Metadata native_denom = 2
[ (gogoproto.nullable) = false ];
// optional genesis transfer packet data
ibc.applications.transfer.v2.FungibleTokenPacketData genesis_transfer = 3;
}
45 changes: 45 additions & 0 deletions proto/hub-genesis/genesis_info.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

syntax = "proto3";
package rollapp.hub_genesis;

import "gogoproto/gogo.proto";
import "cosmos/bank/v1beta1/bank.proto";
import "hub-genesis/state.proto";

option go_package = "github.com/dymensionxyz/dymension-rdk/x/hub-genesis/types";

// The genesis info of the rollapp, that is passed to the hub for validation.
// it's populated on the InitGenesis of the rollapp
message GenesisInfo {
// checksum used to verify integrity of the genesis file. currently unused
string genesis_checksum = 1;
// unique bech32 prefix
string bech32_prefix = 2;
// native_denom is the base denom for the native token
DenomMetadata native_denom = 3;
// initial_supply is the initial supply of the native token
string initial_supply = 4 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// accounts on the Hub to fund with some bootstrapping transfers
repeated GenesisAccount genesis_accounts = 5 [ (gogoproto.nullable) = false ];
}

message DenomMetadata {
string display = 1;
string base = 2;
uint32 exponent = 3;
}


// GenesisAccount is a struct for the genesis account for the rollapp
message GenesisAccount {
// amount of coins to be sent to the genesis address
string amount = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// address is a bech-32 address of the genesis account
string address = 2;
}
24 changes: 21 additions & 3 deletions proto/hub-genesis/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "hub-genesis/params.proto";
import "hub-genesis/state.proto";
import "hub-genesis/genesis_info.proto";

option go_package = "github.com/dymensionxyz/dymension-rdk/x/hub-genesis/types";

Expand All @@ -16,11 +17,17 @@ service Query {
"/dymensionxyz/dymension-rdk/hub-genesis/params";
}

// State returns the state of the genesis event.
rpc State(QueryStateRequest) returns (QueryStateResponse) {
// State returns the state of the genesis event.
rpc State(QueryStateRequest) returns (QueryStateResponse) {
option (google.api.http).get =
"/dymensionxyz/dymension-rdk/hub-genesis/state";
}

// GenesisInfo returns the genesis info of the rollapp.
rpc GenesisInfo(QueryGenesisInfoRequest) returns (QueryGenesisInfoResponse) {
option (google.api.http).get =
"/dymensionxyz/dymension-rdk/hub-genesis/genesis_info";
}
}

// QueryParamsRequest is the request type for the Query/Params RPC method.
Expand All @@ -38,5 +45,16 @@ message QueryStateRequest {}
// QueryStateResponse is the response type for the Query/State RPC method.
message QueryStateResponse {
// state holds the state of the genesis event
State state = 1 [(gogoproto.nullable) = false];
State state = 1 [ (gogoproto.nullable) = false ];
}

// QueryGenesisInfoRequest is the request type for the Query/GenesisInfo RPC
// method.
message QueryGenesisInfoRequest {}

// QueryGenesisInfoResponse is the response type for the Query/GenesisInfo RPC
// method.
message QueryGenesisInfoResponse {
// genesis_info holds the genesis info of the rollapp
GenesisInfo genesis_info = 1 [ (gogoproto.nullable) = false ];
}
22 changes: 5 additions & 17 deletions proto/hub-genesis/state.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,18 @@ syntax = "proto3";
package rollapp.hub_genesis;

import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";

option go_package = "github.com/dymensionxyz/dymension-rdk/x/hub-genesis/types";

// State holds the state of the genesis event
message State {
reserved 1;
reserved 2;
// accounts on the Hub to fund with some bootstrapping transfers
repeated GenesisAccount genesis_accounts = 3 [(gogoproto.nullable) = false];
// the number of genesis transfers for which an ack has not yet been received
uint64 num_unacked_transfers = 5;
// are outboundTransfersEnabled? This is only true if the genesis protocol has finished
reserved 1 to 5;

// are outboundTransfersEnabled? This is only true if the genesis protocol has
// finished
bool outbound_transfers_enabled = 6;
// the canonical transfer port and channel for the hub
PortAndChannel hub_port_and_channel= 7;
PortAndChannel hub_port_and_channel = 7;
}

message PortAndChannel {
Expand All @@ -26,11 +22,3 @@ message PortAndChannel {
// channel
string channel = 2;
}

// 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;
}
25 changes: 15 additions & 10 deletions testutil/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,28 +454,33 @@ func NewRollapp(
keys[hubtypes.StoreKey],
)

denomMetadataMiddleware := denommetadata.NewICS4Wrapper(
app.IBCKeeper.ChannelKeeper,
app.HubKeeper,
app.BankKeeper,
app.HubGenesisKeeper.GetState,
)

app.HubGenesisKeeper = hubgenkeeper.NewKeeper(
appCodec,
keys[hubgentypes.StoreKey],
app.GetSubspace(hubgentypes.ModuleName),
app.AccountKeeper,
app.BankKeeper,
app.MintKeeper,
)

genesisTransfersBlocker := hubgenkeeper.NewICS4Wrapper(denomMetadataMiddleware, app.HubGenesisKeeper)
// The IBC tranfer submit is wrapped with:
var ics4Wrapper ibcporttypes.ICS4Wrapper
// - denom metadata middleware
ics4Wrapper = denommetadata.NewICS4Wrapper(
app.IBCKeeper.ChannelKeeper,
app.HubKeeper,
app.BankKeeper,
app.HubGenesisKeeper.GetState,
)
// - transfer rejecter until genesis bridge phase is finished
ics4Wrapper = hubgenkeeper.NewICS4Wrapper(ics4Wrapper, app.HubGenesisKeeper)

// Create Transfer Keepers
app.TransferKeeper = ibctransferkeeper.NewKeeper(
appCodec,
keys[ibctransfertypes.StoreKey],
app.GetSubspace(ibctransfertypes.ModuleName),
genesisTransfersBlocker,
ics4Wrapper,
app.IBCKeeper.ChannelKeeper,
&app.IBCKeeper.PortKeeper,
app.AccountKeeper,
Expand All @@ -494,9 +499,9 @@ func NewRollapp(
)
transferStack = hubgenkeeper.NewIBCModule(
transferStack,
app.TransferKeeper,
app.HubGenesisKeeper,
app.BankKeeper,
app.IBCKeeper.ChannelKeeper,
)

app.GaslessKeeper = gaslesskeeper.NewKeeper(
Expand Down
82 changes: 56 additions & 26 deletions testutil/utils/test_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import (
"github.com/dymensionxyz/dymension-rdk/x/hub-genesis/types"

app "github.com/dymensionxyz/dymension-rdk/testutil/app"
seqtypes "github.com/dymensionxyz/dymension-rdk/x/sequencers/types"

hubgenesistypes "github.com/dymensionxyz/dymension-rdk/x/hub-genesis/types"
rollappparamstypes "github.com/dymensionxyz/dymension-rdk/x/rollappparams/types"

"github.com/stretchr/testify/require"
Expand All @@ -33,9 +33,6 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"

// unnamed import of statik for swagger UI support
_ "github.com/cosmos/cosmos-sdk/client/docs/statik"
)

var DefaultConsensusParams = &abci.ConsensusParams{
Expand Down Expand Up @@ -92,34 +89,42 @@ func setup(withGenesis bool, invCheckPeriod uint) (*app.App, map[string]json.Raw
log.NewNopLogger(), db, nil, true, map[int64]bool{}, "/tmp", invCheckPeriod, encCdc, app.GetEnabledProposals(), EmptyAppOptions{}, emptyWasmOpts,
)
if withGenesis {
// override the rollapp version, so we'll have a valid default genesis
rollappparamstypes.Version = "5f8393904fb1e9c616fe89f013cafe7501a63f86"
return testApp, app.NewDefaultGenesisState(encCdc.Codec)
}
return testApp, map[string]json.RawMessage{}
}

// Setup initializes a new Rollapp. A Nop logger is set in Rollapp.
func Setup(t *testing.T, isCheckTx bool) *app.App {
// setGenesisAndInitChain contains the shared setup logic
func setGenesisAndInitChain(t *testing.T, app *app.App, genesisState map[string]json.RawMessage) {
t.Helper()

app, genesisState := setup(true, 5)

// setup for sequencer
seqGenesis := seqtypes.GenesisState{
Params: seqtypes.DefaultParams(),
}
genesisState[seqtypes.ModuleName] = app.AppCodec().MustMarshalJSON(&seqGenesis)

// setup for rollapp params

rollappParamsGenesis := rollappparamstypes.GenesisState{
Params: rollappparamstypes.NewParams("mock", "5f8393904fb1e9c616fe89f013cafe7501a63f86"),
// setting bank genesis as required for genesis bridge
nativeDenomMetadata := banktypes.Metadata{
DenomUnits: []*banktypes.DenomUnit{
{
Denom: "stake",
Exponent: 0,
},
{
Denom: "TST",
Exponent: 18,
},
},
Base: "stake",
Display: "TST",
}
genesisState[rollappparamstypes.ModuleName] = app.AppCodec().MustMarshalJSON(&rollappParamsGenesis)

// for now bank genesis won't be set here, funding accounts should be called with fund utils.FundModuleAccount
var bankGenesis banktypes.GenesisState
err := json.Unmarshal(genesisState[banktypes.ModuleName], &bankGenesis)
require.NoError(t, err)
bankGenesis.DenomMetadata = append(bankGenesis.DenomMetadata, nativeDenomMetadata)
genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(&bankGenesis)

stateBytes, err := json.MarshalIndent(genesisState, "", " ")
require.NoError(t, err)

// init chain will set the validator set and initialize the genesis accounts
app.InitChain(
abci.RequestInitChain{
Expand All @@ -133,22 +138,47 @@ func Setup(t *testing.T, isCheckTx bool) *app.App {
InitialHeight: 0,
},
)
}

func SetupWithGenesisBridge(t *testing.T, gbFunds sdk.Coin, genAcct []hubgenesistypes.GenesisAccount) *app.App {
t.Helper()
app, genesisState := setup(true, 5)

// Additional setup specific to SetupWithGenesisBridge
genesisBridgeFunds := []banktypes.Balance{
{
Address: authtypes.NewModuleAddress(hubgenesistypes.ModuleName).String(),
Coins: sdk.NewCoins(gbFunds),
},
}

bankGenesis := banktypes.DefaultGenesisState()
bankGenesis.Balances = append(bankGenesis.Balances, genesisBridgeFunds...)
bankGenesis.Supply = sdk.NewCoins(gbFunds)
genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis)

// set genesis transfer required accounts
genesisBridgeGenesisState := hubgenesistypes.DefaultGenesisState()
genesisBridgeGenesisState.GenesisAccounts = genAcct
genesisState[hubgenesistypes.ModuleName] = app.AppCodec().MustMarshalJSON(genesisBridgeGenesisState)

setGenesisAndInitChain(t, app, genesisState)
return app
}

func Setup(t *testing.T, isCheckTx bool) *app.App {
t.Helper()
app, genesisState := setup(true, 5)
setGenesisAndInitChain(t, app, genesisState)
return app
}

// TODO: tech debt - this is almost the same as in github.com/cosmos/ibc-go/v6/testing/app.go
// but unlike the other one, this one adds the sequencer to the genesis state on InitChain
func SetupWithGenesisValSet(t *testing.T, chainID, rollAppDenom string, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances []banktypes.Balance) *app.App {
t.Helper()

app, genesisState := setup(true, 5)

seqGenesis := seqtypes.GenesisState{
Params: seqtypes.DefaultParams(),
}
genesisState[seqtypes.ModuleName] = app.AppCodec().MustMarshalJSON(&seqGenesis)

authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis)

Expand Down
7 changes: 5 additions & 2 deletions x/denommetadata/ibc_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ import (
type ICS4Wrapper struct {
porttypes.ICS4Wrapper

hubKeeper types.HubKeeper
bankKeeper types.BankKeeper
hubKeeper types.HubKeeper
bankKeeper types.BankKeeper

// TODO: refactor to `IsCanonicalHubTransferChannel` directly
getHubGenState func(ctx sdk.Context) hgtypes.State
}

Expand Down Expand Up @@ -64,6 +66,7 @@ func (m *ICS4Wrapper) SendPacket(
return 0, errorsmod.Wrapf(errortypes.ErrJSONUnmarshal, "unmarshal ICS-20 transfer packet data: %s", err.Error())
}

// don't send metadata on non-canonical channels
if hubGenState := m.getHubGenState(ctx); !hubGenState.IsCanonicalHubTransferChannel(destinationPort, destinationChannel) {
return m.ICS4Wrapper.SendPacket(ctx, chanCap, destinationPort, destinationChannel, timeoutHeight, timeoutTimestamp, data)
}
Expand Down
Loading
Loading