-
Notifications
You must be signed in to change notification settings - Fork 792
/
accesscontrol_wasm_dependency.go
121 lines (106 loc) · 3.73 KB
/
accesscontrol_wasm_dependency.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
package antedecorators
import (
"encoding/hex"
wasm "github.com/CosmWasm/wasmd/x/wasm"
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkacltypes "github.com/cosmos/cosmos-sdk/types/accesscontrol"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
acl "github.com/cosmos/cosmos-sdk/x/accesscontrol"
aclkeeper "github.com/cosmos/cosmos-sdk/x/accesscontrol/keeper"
acltypes "github.com/cosmos/cosmos-sdk/x/accesscontrol/types"
"github.com/cosmos/cosmos-sdk/x/authz"
)
type ACLWasmDependencyDecorator struct {
aclKeeper aclkeeper.Keeper
wasmKeeper wasm.Keeper
}
func NewACLWasmDependencyDecorator(aclKeeper aclkeeper.Keeper, wasmKeeper wasm.Keeper) ACLWasmDependencyDecorator {
return ACLWasmDependencyDecorator{aclKeeper: aclKeeper, wasmKeeper: wasmKeeper}
}
func (ad ACLWasmDependencyDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
for _, msg := range tx.GetMsgs() {
switch m := msg.(type) {
case *acltypes.MsgRegisterWasmDependency:
// check if the FromAddress for the contract matches up with the admin for the contract
matches, err := ad.SenderMatchesContractAdmin(ctx, m)
if err != nil {
return ctx, err
}
if !matches {
return ctx, sdkerrors.Wrap(acl.ErrWasmDependencyRegistrationFailed, "permission denied, sender doesn't match contract admin")
}
case *authz.MsgExec:
// find nested to check for wasm registration
valid, err := ad.CheckAuthzExecValid(ctx, m)
if err != nil {
return ctx, err
}
if !valid {
return ctx, sdkerrors.Wrap(acl.ErrWasmDependencyRegistrationFailed, "permission denied, sender doesn't match contract admin")
}
default:
continue
}
}
return next(ctx, tx, simulate)
}
func (ad ACLWasmDependencyDecorator) CheckAuthzExecValid(ctx sdk.Context, authzMsg *authz.MsgExec) (bool, error) {
msgs, err := authzMsg.GetMessages()
if err != nil {
return false, err
}
for _, msg := range msgs {
// check if message type is authz exec OR registerWasmDependency
switch m := msg.(type) {
case *acltypes.MsgRegisterWasmDependency:
matches, err := ad.SenderMatchesContractAdmin(ctx, m)
if err != nil {
return false, err
}
if !matches {
return false, nil
}
case *authz.MsgExec:
// find nested to check for wasm registration
valid, err := ad.CheckAuthzExecValid(ctx, m)
if err != nil || !valid {
return false, err
}
default:
continue
}
}
return true, nil
}
func (ad ACLWasmDependencyDecorator) SenderMatchesContractAdmin(ctx sdk.Context, msg *acltypes.MsgRegisterWasmDependency) (bool, error) {
contractAddr, err := sdk.AccAddressFromBech32(msg.WasmDependencyMapping.ContractAddress)
if err != nil {
return false, err
}
contractInfo := ad.wasmKeeper.GetContractInfo(ctx, contractAddr)
return contractInfo.Admin == msg.FromAddress, nil
}
func (ad ACLWasmDependencyDecorator) AnteDeps(txDeps []sdkacltypes.AccessOperation, tx sdk.Tx, txIndex int, next sdk.AnteDepGenerator) (newTxDeps []sdkacltypes.AccessOperation, err error) {
deps := []sdkacltypes.AccessOperation{}
for _, msg := range tx.GetMsgs() {
switch m := msg.(type) {
case *acltypes.MsgRegisterWasmDependency:
contractAddr, err := sdk.AccAddressFromBech32(m.WasmDependencyMapping.ContractAddress)
if err != nil {
return txDeps, err
}
dependencies := []sdkacltypes.AccessOperation{
{
AccessType: sdkacltypes.AccessType_READ,
ResourceType: sdkacltypes.ResourceType_KV_WASM_CONTRACT_ADDRESS,
IdentifierTemplate: hex.EncodeToString(wasmtypes.GetContractAddressKey(contractAddr)),
},
}
deps = append(deps, dependencies...)
default:
continue
}
}
return next(append(txDeps, deps...), tx, txIndex)
}