forked from axelarnetwork/axelar-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwasm.go
176 lines (145 loc) · 5.62 KB
/
wasm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package app
import (
"encoding/json"
"fmt"
"strconv"
"github.com/CosmWasm/wasmd/x/wasm"
wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported"
"golang.org/x/exp/maps"
"github.com/axelarnetwork/axelar-core/x/ante"
nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported"
nexusKeeper "github.com/axelarnetwork/axelar-core/x/nexus/keeper"
nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types"
"github.com/axelarnetwork/utils/funcs"
)
//go:generate moq -pkg mock -out ./mock/ibchooks.go . PacketI
type PacketI ibcexported.PacketI
type AnteHandlerMessenger struct {
anteHandle ante.MessageAnteHandler
encoders wasm.MessageEncoders
messenger wasmkeeper.Messenger
}
func (m AnteHandlerMessenger) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) {
if err := assertSingleMessageIsSet(msg); err != nil {
return nil, nil, err
}
// burn and ibc send packet cannot be converted into sdk.Msg and are irrelevant for ante handler checks
if !isBankBurnMsg(msg) && !isIBCSendPacketMsg(msg) {
sdkMsgs, err := m.encoders.Encode(ctx, contractAddr, contractIBCPortID, msg)
if err != nil {
return nil, nil, err
}
// we can't know if this is a simulation or not at this stage, so we treat it as a regular execution
ctx, err = m.anteHandle(ctx, sdkMsgs, false)
if err != nil {
return nil, nil, err
}
}
return m.messenger.DispatchMsg(ctx, contractAddr, contractIBCPortID, msg)
}
func assertSingleMessageIsSet(msg wasmvmtypes.CosmosMsg) error {
bz, err := json.Marshal(msg)
if err != nil {
return err
}
var msgs map[string]interface{}
err = json.Unmarshal(bz, &msgs)
if err != nil {
return err
}
msgCount := 0
for msgType, typedMsgs := range msgs {
// custom and stargate msgs are not categorized in CosmosMsg, so the next lower structural level would be message fields and not individual messages,
// so we can safely assume that there is only one message
if msgType == "custom" || msgType == "stargate" {
msgCount++
} else if typedMsgs, ok := typedMsgs.(map[string]interface{}); ok {
msgCount += len(maps.Keys(typedMsgs))
}
}
if msgCount == 0 {
return fmt.Errorf("no message set")
} else if msgCount > 1 {
return fmt.Errorf("only one message can be set, got %d", msgCount)
} else {
return nil
}
}
func WithAnteHandlers(encoders wasmkeeper.MessageEncoders, anteHandler ante.MessageAnteHandler, messenger wasmkeeper.Messenger) wasmkeeper.Messenger {
return AnteHandlerMessenger{
encoders: encoders,
anteHandle: anteHandler,
messenger: messenger,
}
}
type MsgTypeBlacklistMessenger struct {
}
func NewMsgTypeBlacklistMessenger() MsgTypeBlacklistMessenger {
return MsgTypeBlacklistMessenger{}
}
func (m MsgTypeBlacklistMessenger) DispatchMsg(_ sdk.Context, _ sdk.AccAddress, _ string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) {
if isIBCSendPacketMsg(msg) || isStargateMsg(msg) {
return nil, nil, fmt.Errorf("ibc send packet and stargate messages are not supported")
}
// this means that this message handler doesn't know how to deal with these messages (i.e. they can pass through),
// other handlers might be able to deal with them
return nil, nil, wasmtypes.ErrUnknownMsg
}
func isBankBurnMsg(msg wasmvmtypes.CosmosMsg) bool {
return msg.Bank != nil && msg.Bank.Burn != nil
}
func isStargateMsg(msg wasmvmtypes.CosmosMsg) bool {
return msg.Stargate != nil
}
func isIBCSendPacketMsg(msg wasmvmtypes.CosmosMsg) bool {
return msg.IBC != nil && msg.IBC.SendPacket != nil
}
type WasmAppModuleBasicOverride struct {
wasm.AppModuleBasic
}
func NewWasmAppModuleBasicOverride(wasmModule wasm.AppModuleBasic) WasmAppModuleBasicOverride {
// Both the server and the cosmwasm client use this parameter to validate MsgStoreCode.
// Because the AppModuleBasic provides server and client commands, it's sufficient to do the override here to set it for both.
if MaxWasmSize != "" {
// Override the default max wasm code size
wasmtypes.MaxWasmSize = funcs.Must(strconv.Atoi(MaxWasmSize))
}
return WasmAppModuleBasicOverride{
AppModuleBasic: wasmModule,
}
}
// DefaultGenesis returns an override for the wasm module's DefaultGenesis,
// because as soon as the module is initialized the restriction to contract upload and instantiation must hold
func (m WasmAppModuleBasicOverride) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
return cdc.MustMarshalJSON(&wasm.GenesisState{
Params: wasmtypes.Params{
CodeUploadAccess: wasmtypes.AllowNobody,
InstantiateDefaultPermission: wasmtypes.AccessTypeNobody,
},
})
}
// QueryRequest is the custom queries wasm contracts can make for the core modules
type QueryRequest struct {
Nexus *nexus.WasmQueryRequest
}
// NewQueryPlugins returns a new instance of the custom query plugins
func NewQueryPlugins(nexus nexustypes.Nexus) *wasmkeeper.QueryPlugins {
nexusWasmQuerier := nexusKeeper.NewWasmQuerier(nexus)
return &wasmkeeper.QueryPlugins{
Custom: func(ctx sdk.Context, request json.RawMessage) ([]byte, error) {
req := QueryRequest{}
if err := json.Unmarshal(request, &req); err != nil {
return nil, wasmvmtypes.InvalidRequest{Err: "invalid Custom query request", Request: request}
}
if req.Nexus != nil {
return nexusWasmQuerier.Query(ctx, *req.Nexus)
}
return nil, wasmvmtypes.UnsupportedRequest{Kind: "unknown Custom query request"}
},
}
}