Skip to content

Commit

Permalink
Merge branch 'main' into fix/query-interface-conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
milapsheth authored Oct 7, 2024
2 parents 6412854 + bc0ae8f commit 8ba9e03
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 19 deletions.
2 changes: 2 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,8 @@ func initMessageRouter(keepers *KeeperCache) nexusTypes.MessageRouter {
if IsWasmEnabled() {
messageRouter.AddRoute(wasm.ModuleName, nexusKeeper.NewMessageRoute(
GetKeeper[nexusKeeper.Keeper](keepers),
GetKeeper[axelarnetKeeper.IBCKeeper](keepers),
GetKeeper[bankkeeper.BaseKeeper](keepers),
GetKeeper[authkeeper.AccountKeeper](keepers),
GetKeeper[wasmkeeper.PermissionedKeeper](keepers),
))
Expand Down
2 changes: 1 addition & 1 deletion app/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func initWasmKeeper(encodingConfig axelarParams.EncodingConfig, keys map[string]
encoders,
initMessageAnteDecorators(encodingConfig, keepers),
// for security reasons we disallow some msg types that can be used for arbitrary calls
wasmkeeper.NewMessageHandlerChain(NewMsgTypeBlacklistMessenger(), old, nexusKeeper.NewMessenger(nexusK)))
wasmkeeper.NewMessageHandlerChain(NewMsgTypeBlacklistMessenger(), old, nexusKeeper.NewMessenger(nexusK, GetKeeper[axelarnetKeeper.IBCKeeper](keepers), GetKeeper[bankkeeper.BaseKeeper](keepers), GetKeeper[authkeeper.AccountKeeper](keepers))))
}),
wasmkeeper.WithWasmEngineDecorator(func(old wasmtypes.WasmerEngine) wasmtypes.WasmerEngine {
return nexusKeeper.NewWasmerEngine(old, nexusK)
Expand Down
5 changes: 5 additions & 0 deletions x/nexus/exported/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ func FromGeneralMessage(msg GeneralMessage) WasmMessage {
SourceTxID: msg.SourceTxID,
SourceTxIndex: msg.SourceTxIndex,
ID: msg.ID,
Asset: msg.Asset,
}
}

Expand Down Expand Up @@ -398,6 +399,10 @@ func (m WasmMessage) ValidateBasic() error {
return fmt.Errorf("invalid wasm message source tx id")
}

if m.Asset != nil {
return m.Asset.Validate()
}

return nil
}

Expand Down
File renamed without changes.
File renamed without changes.
31 changes: 27 additions & 4 deletions x/nexus/keeper/msg_dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ var _ wasmkeeper.Messenger = (*Messenger)(nil)

type Messenger struct {
types.Nexus
ibc types.IBCKeeper
bank types.BankKeeper
account types.AccountKeeper
}

// NewMessenger returns a new Messenger
func NewMessenger(nexus types.Nexus) Messenger {
return Messenger{nexus}
func NewMessenger(nexus types.Nexus, ibc types.IBCKeeper, bank types.BankKeeper, account types.AccountKeeper) Messenger {
return Messenger{nexus, ibc, bank, account}
}

// DispatchMsg decodes the messages from the cosmowasm gateway and routes them to the nexus module if possible
Expand Down Expand Up @@ -73,8 +76,8 @@ func (m Messenger) routeMsg(ctx sdk.Context, msg exported.WasmMessage) error {
return nil
}

if msg.Asset != nil && !m.IsAssetRegistered(ctx, destinationChain, msg.Asset.Denom) {
return fmt.Errorf("asset %s is not registered on chain %s", msg.Asset.Denom, destinationChain.Name)
if err := m.lockCoinIfAny(ctx, msg); err != nil {
return err
}

sourceChain := exported.Chain{Name: msg.SourceChain, SupportsForeignAssets: false, KeyType: tss.None, Module: wasmtypes.ModuleName}
Expand All @@ -94,6 +97,26 @@ func (m Messenger) routeMsg(ctx sdk.Context, msg exported.WasmMessage) error {
return nil
}

func (m Messenger) lockCoinIfAny(ctx sdk.Context, msg exported.WasmMessage) error {
if msg.Asset == nil {
return nil
}

// destination chain existence is already checked in routeMsg
destinationChain := funcs.MustOk(m.GetChain(ctx, msg.DestinationChain))

if !m.IsAssetRegistered(ctx, destinationChain, msg.Asset.Denom) {
return fmt.Errorf("asset %s is not registered on chain %s", msg.Asset.Denom, destinationChain.Name)
}

lockableAsset, err := m.NewLockableAsset(ctx, m.ibc, m.bank, *msg.Asset)
if err != nil {
return err
}

return lockableAsset.LockFrom(ctx, m.account.GetModuleAddress(types.ModuleName))
}

// EncodeRoutingMessage encodes the message from the wasm contract into a sdk.Msg
func EncodeRoutingMessage(sender sdk.AccAddress, msg json.RawMessage) ([]sdk.Msg, error) {
req, err := encodeRoutingMessage(sender, msg)
Expand Down
22 changes: 19 additions & 3 deletions x/nexus/keeper/msg_dispatcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
axelarnet "github.com/axelarnetwork/axelar-core/x/axelarnet/exported"
evm "github.com/axelarnetwork/axelar-core/x/evm/exported"
"github.com/axelarnetwork/axelar-core/x/nexus/exported"
exportedmock "github.com/axelarnetwork/axelar-core/x/nexus/exported/mock"
"github.com/axelarnetwork/axelar-core/x/nexus/keeper"
"github.com/axelarnetwork/axelar-core/x/nexus/types"
"github.com/axelarnetwork/axelar-core/x/nexus/types/mock"
Expand All @@ -28,6 +29,9 @@ func TestMessenger_DispatchMsg(t *testing.T) {
ctx sdk.Context
messenger keeper.Messenger
nexus *mock.NexusMock
ibc *mock.IBCKeeperMock
bank *mock.BankKeeperMock
account *mock.AccountKeeperMock
msg wasmvmtypes.CosmosMsg
)

Expand All @@ -39,8 +43,11 @@ func TestMessenger_DispatchMsg(t *testing.T) {
LoggerFunc: func(ctx sdk.Context) log.Logger { return ctx.Logger() },
IsWasmConnectionActivatedFunc: func(sdk.Context) bool { return true },
}
ibc = &mock.IBCKeeperMock{}
bank = &mock.BankKeeperMock{}
account = &mock.AccountKeeperMock{}

messenger = keeper.NewMessenger(nexus)
messenger = keeper.NewMessenger(nexus, ibc, bank, account)
})

givenMessenger.
Expand Down Expand Up @@ -133,7 +140,14 @@ func TestMessenger_DispatchMsg(t *testing.T) {
When("the asset is registered for the destination chain", func() {
nexus.IsAssetRegisteredFunc = func(_ sdk.Context, _ exported.Chain, _ string) bool { return true }
}).
Then("should set new message", func(t *testing.T) {
Then("should lock the coin and set new message", func(t *testing.T) {
moduleAccount := rand.AccAddr()
account.GetModuleAddressFunc = func(_ string) sdk.AccAddress { return moduleAccount }
lockableAsset := &exportedmock.LockableAssetMock{}
lockableAsset.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil }
nexus.NewLockableAssetFunc = func(ctx sdk.Context, ibc types.IBCKeeper, bank types.BankKeeper, coin sdk.Coin) (exported.LockableAsset, error) {
return lockableAsset, nil
}
nexus.SetNewMessageFunc = func(_ sdk.Context, msg exported.GeneralMessage) error {
return msg.ValidateBasic()
}
Expand All @@ -142,6 +156,8 @@ func TestMessenger_DispatchMsg(t *testing.T) {
_, _, err := messenger.DispatchMsg(ctx, contractAddr, "", msg)

assert.NoError(t, err)
assert.Len(t, lockableAsset.LockFromCalls(), 1)
assert.Equal(t, lockableAsset.LockFromCalls()[0].FromAddr, moduleAccount)
assert.Len(t, nexus.SetNewMessageCalls(), 1)
assert.Len(t, nexus.RouteMessageCalls(), 1)
assert.NotNil(t, nexus.SetNewMessageCalls()[0].Msg.Asset)
Expand Down Expand Up @@ -298,7 +314,7 @@ func TestMessenger_DispatchMsg_WasmConnectionNotActivated(t *testing.T) {
nexus = &mock.NexusMock{
LoggerFunc: func(ctx sdk.Context) log.Logger { return ctx.Logger() },
}
messenger = keeper.NewMessenger(nexus)
messenger = keeper.NewMessenger(nexus, &mock.IBCKeeperMock{}, &mock.BankKeeperMock{}, &mock.AccountKeeperMock{})
}).
When("wasm connection is not activated", func() {
nexus.IsWasmConnectionActivatedFunc = func(_ sdk.Context) bool { return false }
Expand Down
26 changes: 20 additions & 6 deletions x/nexus/keeper/wasm_message_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@ type request struct {
}

// NewMessageRoute creates a new message route
func NewMessageRoute(nexus types.Nexus, account types.AccountKeeper, wasm types.WasmKeeper) exported.MessageRoute {
func NewMessageRoute(nexus types.Nexus, ibc types.IBCKeeper, bank types.BankKeeper, account types.AccountKeeper, wasm types.WasmKeeper) exported.MessageRoute {
return func(ctx sdk.Context, _ exported.RoutingContext, msg exported.GeneralMessage) error {
if msg.Asset != nil {
return fmt.Errorf("asset transfer is not supported")
}

if !nexus.IsWasmConnectionActivated(ctx) {
return fmt.Errorf("wasm connection is not activated")
}
Expand All @@ -35,12 +31,17 @@ func NewMessageRoute(nexus types.Nexus, account types.AccountKeeper, wasm types.
return err
}

coins, err := unlockCoinIfAny(ctx, nexus, ibc, bank, account, wasmMsg)
if err != nil {
return err
}

bz, err := json.Marshal(request{RouteMessagesFromNexus: []exported.WasmMessage{wasmMsg}})
if err != nil {
return nil
}

if _, err := wasm.Execute(ctx, gateway, account.GetModuleAddress(types.ModuleName), bz, sdk.NewCoins()); err != nil {
if _, err := wasm.Execute(ctx, gateway, account.GetModuleAddress(types.ModuleName), bz, coins); err != nil {
return err
}

Expand All @@ -51,3 +52,16 @@ func NewMessageRoute(nexus types.Nexus, account types.AccountKeeper, wasm types.
return nil
}
}

func unlockCoinIfAny(ctx sdk.Context, nexus types.Nexus, ibc types.IBCKeeper, bank types.BankKeeper, account types.AccountKeeper, msg exported.WasmMessage) (sdk.Coins, error) {
if msg.Asset == nil {
return sdk.NewCoins(), nil
}

lockableAsset, err := nexus.NewLockableAsset(ctx, ibc, bank, *msg.Asset)
if err != nil {
return sdk.NewCoins(), err
}

return sdk.NewCoins(*msg.Asset), lockableAsset.UnlockTo(ctx, account.GetModuleAddress(types.ModuleName))
}
46 changes: 41 additions & 5 deletions x/nexus/keeper/wasm_message_route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/axelarnetwork/axelar-core/testutils/fake"
"github.com/axelarnetwork/axelar-core/testutils/rand"
"github.com/axelarnetwork/axelar-core/x/nexus/exported"
exportedmock "github.com/axelarnetwork/axelar-core/x/nexus/exported/mock"
"github.com/axelarnetwork/axelar-core/x/nexus/exported/testutils"
"github.com/axelarnetwork/axelar-core/x/nexus/keeper"
"github.com/axelarnetwork/axelar-core/x/nexus/types"
Expand All @@ -31,6 +32,8 @@ func TestNewMessageRoute(t *testing.T) {
msg exported.GeneralMessage

nexusK *mock.NexusMock
ibcK *mock.IBCKeeperMock
bankK *mock.BankKeeperMock
accountK *mock.AccountKeeperMock
wasmK *mock.WasmKeeperMock
gateway sdk.AccAddress
Expand All @@ -41,10 +44,12 @@ func TestNewMessageRoute(t *testing.T) {

nexusK = &mock.NexusMock{}
nexusK.IsWasmConnectionActivatedFunc = func(_ sdk.Context) bool { return true }
ibcK = &mock.IBCKeeperMock{}
bankK = &mock.BankKeeperMock{}
accountK = &mock.AccountKeeperMock{}
wasmK = &mock.WasmKeeperMock{}

route = keeper.NewMessageRoute(nexusK, accountK, wasmK)
route = keeper.NewMessageRoute(nexusK, ibcK, bankK, accountK, wasmK)
})

givenMessageRoute.
Expand Down Expand Up @@ -72,8 +77,36 @@ func TestNewMessageRoute(t *testing.T) {
When("the message has an asset", func() {
msg = randMsg(exported.Processing, true)
}).
Then("should return error", func(t *testing.T) {
assert.ErrorContains(t, route(ctx, exported.RoutingContext{}, msg), "asset transfer is not supported")
Then("should execute the wasm message with token sent to the gateway", func(t *testing.T) {
moduleAddr := rand.AccAddr()
accountK.GetModuleAddressFunc = func(_ string) sdk.AccAddress { return moduleAddr }

lockableAsset := &exportedmock.LockableAssetMock{}
nexusK.NewLockableAssetFunc = func(ctx sdk.Context, ibc types.IBCKeeper, bank types.BankKeeper, coin sdk.Coin) (exported.LockableAsset, error) {
return lockableAsset, nil
}
lockableAsset.UnlockToFunc = func(ctx sdk.Context, toAddr sdk.AccAddress) error { return nil }

wasmK.ExecuteFunc = func(_ sdk.Context, _, _ sdk.AccAddress, _ []byte, _ sdk.Coins) ([]byte, error) {
return nil, nil
}

assert.NoError(t, route(ctx, exported.RoutingContext{}, msg))

assert.Len(t, lockableAsset.UnlockToCalls(), 1)
assert.Equal(t, moduleAddr, lockableAsset.UnlockToCalls()[0].ToAddr)

assert.Len(t, wasmK.ExecuteCalls(), 1)
assert.Equal(t, gateway, wasmK.ExecuteCalls()[0].ContractAddress)
assert.Equal(t, moduleAddr, wasmK.ExecuteCalls()[0].Caller)
assert.Equal(t, sdk.NewCoins(*msg.Asset), wasmK.ExecuteCalls()[0].Coins)

var actual req
assert.NoError(t, json.Unmarshal(wasmK.ExecuteCalls()[0].Msg, &actual))
assert.Len(t, actual.RouteMessages, 1)
assert.Equal(t, exported.FromGeneralMessage(msg), actual.RouteMessages[0])

assert.Equal(t, len(nexusK.SetMessageExecutedCalls()), 1)
}),

When("the message has no asset", func() {
Expand Down Expand Up @@ -110,6 +143,8 @@ func TestMessageRoute_WasmConnectionNotActivated(t *testing.T) {
ctx sdk.Context
route exported.MessageRoute
nexusK *mock.NexusMock
ibcK *mock.IBCKeeperMock
bankK *mock.BankKeeperMock
accountK *mock.AccountKeeperMock
wasmK *mock.WasmKeeperMock
)
Expand All @@ -126,13 +161,14 @@ func TestMessageRoute_WasmConnectionNotActivated(t *testing.T) {
return params
}
nexusK.SetMessageExecutedFunc = func(_ sdk.Context, _ string) error { return nil }

ibcK = &mock.IBCKeeperMock{}
bankK = &mock.BankKeeperMock{}
accountK = &mock.AccountKeeperMock{}
accountK.GetModuleAddressFunc = func(_ string) sdk.AccAddress { return rand.AccAddr() }
wasmK = &mock.WasmKeeperMock{}
wasmK.ExecuteFunc = func(_ sdk.Context, _, _ sdk.AccAddress, _ []byte, _ sdk.Coins) ([]byte, error) { return nil, nil }

route = keeper.NewMessageRoute(nexusK, accountK, wasmK)
route = keeper.NewMessageRoute(nexusK, ibcK, bankK, accountK, wasmK)
}).
When("the wasm connection is not activated", func() {
nexusK.IsWasmConnectionActivatedFunc = func(_ sdk.Context) bool { return false }
Expand Down
1 change: 1 addition & 0 deletions x/nexus/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type Nexus interface {
IsAssetRegistered(ctx sdk.Context, chain exported.Chain, denom string) bool
GetChainByNativeAsset(ctx sdk.Context, asset string) (chain exported.Chain, ok bool)
CurrID(ctx sdk.Context) ([32]byte, uint64)
NewLockableAsset(ctx sdk.Context, ibc IBCKeeper, bank BankKeeper, coin sdk.Coin) (exported.LockableAsset, error)
}

// MsgIDGenerator provides functionality to generate msg IDs
Expand Down
Loading

0 comments on commit 8ba9e03

Please sign in to comment.