forked from CosmWasm/wasmd
-
Notifications
You must be signed in to change notification settings - Fork 9
/
api.go
132 lines (110 loc) · 4.08 KB
/
api.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
package keeper
import (
"fmt"
sdk "github.com/Finschia/finschia-sdk/types"
"github.com/Finschia/wasmd/x/wasm/types"
wasmvm "github.com/Finschia/wasmvm"
wasmvmtypes "github.com/Finschia/wasmvm/types"
)
const (
// DefaultGasCostHumanAddress is how moch SDK gas we charge to convert to a human address format
DefaultGasCostHumanAddress = 5
// DefaultGasCostCanonicalAddress is how moch SDK gas we charge to convert to a canonical address format
DefaultGasCostCanonicalAddress = 4
// DefaultDeserializationCostPerByte The formular should be `len(data) * deserializationCostPerByte`
DefaultDeserializationCostPerByte = 1
)
var (
costHumanize = DefaultGasCostHumanAddress * DefaultGasMultiplier
costCanonical = DefaultGasCostCanonicalAddress * DefaultGasMultiplier
costJSONDeserialization = wasmvmtypes.UFraction{
Numerator: DefaultDeserializationCostPerByte * DefaultGasMultiplier,
Denominator: 1,
}
)
type CosmwasmAPIImpl struct {
keeper *Keeper
ctx *sdk.Context
}
type cosmwasmAPIGeneratorImpl struct {
keeper *Keeper
}
type CosmwasmAPIGenerator interface {
Generate(ctx *sdk.Context) wasmvm.GoAPI
}
func humanAddress(canon []byte) (string, uint64, error) {
if err := sdk.VerifyAddressFormat(canon); err != nil {
return "", costHumanize, err
}
return sdk.AccAddress(canon).String(), costHumanize, nil
}
func canonicalAddress(human string) ([]byte, uint64, error) {
bz, err := sdk.AccAddressFromBech32(human)
return bz, costCanonical, err
}
// callCallablePoint is a wrapper function of `wasmvm`
// returns result, gas used, error
func (a CosmwasmAPIImpl) callCallablePoint(contractAddrStr string, name []byte, args []byte, isReadonly bool, callstack []byte, gasLimit uint64) ([]byte, uint64, error) {
contractAddr := sdk.MustAccAddressFromBech32(contractAddrStr)
contractInfo, codeInfo, prefixStore, err := a.keeper.contractInstance(*a.ctx, contractAddr)
if err != nil {
return nil, 0, err
}
env := types.NewEnv(*a.ctx, contractAddr)
wasmStore := types.NewWasmStore(prefixStore)
gasRegister := a.keeper.GetGasRegister()
querier := NewQueryHandler(*a.ctx, a.keeper.wasmVMQueryHandler, contractAddr, gasRegister)
gasMeter := a.keeper.gasMeter(*a.ctx)
api := a.keeper.cosmwasmAPIGenerator.Generate(a.ctx)
instantiateCost := gasRegister.ToWasmVMGas(gasRegister.InstantiateContractCosts(a.keeper.IsPinnedCode(*a.ctx, contractInfo.CodeID), len(args)))
if gasLimit < instantiateCost {
return nil, 0, fmt.Errorf("lack of gas for calling callable point")
}
wasmGasLimit := gasLimit - instantiateCost
result, events, attrs, gas, err := a.keeper.wasmVM.CallCallablePoint(name, codeInfo.CodeHash, isReadonly, callstack, env, args, wasmStore, api, querier, gasMeter, wasmGasLimit, costJSONDeserialization)
gas += instantiateCost
if err != nil {
return nil, gas, err
}
if !isReadonly {
// issue events and attrs
if len(attrs) != 0 {
eventsByAttr, err := newCallablePointEvent(attrs, contractAddr, callstack)
if err != nil {
return nil, gas, err
}
a.ctx.EventManager().EmitEvents(eventsByAttr)
}
if len(events) != 0 {
customEvents, err := newCustomCallablePointEvents(events, contractAddr, callstack)
if err != nil {
return nil, gas, err
}
a.ctx.EventManager().EmitEvents(customEvents)
}
}
return result, gas, err
}
// validateInterface is a wrapper function of `wasmvm`
// returns result, gas used, error
func (a CosmwasmAPIImpl) validateInterface(contractAddrStr string, expectedInterface []byte) ([]byte, uint64, error) {
contractAddr := sdk.MustAccAddressFromBech32(contractAddrStr)
_, codeInfo, _, err := a.keeper.contractInstance(*a.ctx, contractAddr)
if err != nil {
return nil, 0, err
}
result, err := a.keeper.wasmVM.ValidateDynamicLinkInterface(codeInfo.CodeHash, expectedInterface)
return result, 0, err
}
func (c cosmwasmAPIGeneratorImpl) Generate(ctx *sdk.Context) wasmvm.GoAPI {
x := CosmwasmAPIImpl{
keeper: c.keeper,
ctx: ctx,
}
return wasmvm.GoAPI{
HumanAddress: humanAddress,
CanonicalAddress: canonicalAddress,
CallCallablePoint: x.callCallablePoint,
ValidateInterface: x.validateInterface,
}
}