Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.20
require (
github.com/99designs/keyring v1.1.6
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d
github.com/CosmWasm/wasmvm v1.0.0
github.com/CosmWasm/wasmvm v1.2.4
github.com/VictoriaMetrics/fastcache v1.8.0
github.com/Workiva/go-datastructures v1.0.53
github.com/alicebob/miniredis/v2 v2.17.0
Expand Down Expand Up @@ -73,7 +73,7 @@ require (
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.12.0
github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48
github.com/stretchr/testify v1.8.0
github.com/stretchr/testify v1.8.1
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
github.com/tendermint/btcd v0.1.1
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15
Expand Down Expand Up @@ -179,6 +179,7 @@ require (
)

replace (
github.com/CosmWasm/wasmvm => github.com/okx/wasmvm v1.2.4-0.20230726040355-85ad18b1d9d1
github.com/buger/jsonparser => github.com/buger/jsonparser v1.0.0 // imported by nacos-go-sdk, upgraded to v1.0.0 in case of a known vulnerable bug
github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
github.com/cosmos/gorocksdb => github.com/okx/grocksdb v1.6.45-okc2
Expand Down
10 changes: 6 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg=
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4=
github.com/CosmWasm/wasmvm v1.0.0 h1:NRmnHe3xXsKn2uEcB1F5Ha323JVAhON+BI6L177dlKc=
github.com/CosmWasm/wasmvm v1.0.0/go.mod h1:ei0xpvomwSdONsxDuONzV7bL1jSET1M8brEx0FCXc+A=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
Expand Down Expand Up @@ -636,6 +634,8 @@ github.com/okx/go-ethereum v1.10.26-0.20230605041300-9db59c1d91e6 h1:pXsdHnWHejH
github.com/okx/go-ethereum v1.10.26-0.20230605041300-9db59c1d91e6/go.mod h1:f9/CleoGkiU7NWF9tdpWGfEYmFbN7zUi17jGick31KM=
github.com/okx/grocksdb v1.6.45-okc2 h1:Dbmax+uY71YuGTkJftpF55dbGW7hfIVOfNz2mnFqXl0=
github.com/okx/grocksdb v1.6.45-okc2/go.mod h1:+/BHUY+mT0tbaVXwO2wTtD9eytazyw1W5n2O7AGyXZA=
github.com/okx/wasmvm v1.2.4-0.20230726040355-85ad18b1d9d1 h1:GkLSSyFqizXMbWcjK4xORA1vwceBP7fkKRIKwyixCb4=
github.com/okx/wasmvm v1.2.4-0.20230726040355-85ad18b1d9d1/go.mod h1:vW/E3h8j9xBQs9bCoijDuawKo9kCtxOaS8N8J7KFtkc=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
Expand Down Expand Up @@ -799,8 +799,9 @@ github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUW
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
Expand All @@ -810,8 +811,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs=
github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo=
Expand Down
13 changes: 13 additions & 0 deletions libs/cosmos-sdk/types/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type Context struct {
accountCache *AccountCache
paraMsg *ParaMsg
// txCount uint32
wasmCallDepth uint32
overridesBytes []byte // overridesBytes is used to save overrides info, passed from ethCall to x/evm
watcher *TxWatcher
feesplitInfo *FeeSplitInfo
Expand Down Expand Up @@ -416,6 +417,18 @@ func (c *Context) SetWatcher(w IWatcher) {
c.watcher.IWatcher = w
}

func (c *Context) IncrementCallDepth() {
c.wasmCallDepth++
}

func (c *Context) DecrementCallDepth() {
c.wasmCallDepth--
}

func (c *Context) CallDepth() uint32 {
return c.wasmCallDepth
}

func (c *Context) GetWatcher() IWatcher {
if c.watcher == nil {
return emptyWatcher
Expand Down
42 changes: 42 additions & 0 deletions x/wasm/keeper/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
wasmvm "github.com/CosmWasm/wasmvm"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
sdk "github.com/okx/okbchain/libs/cosmos-sdk/types"
sdkerrors "github.com/okx/okbchain/libs/cosmos-sdk/types/errors"
"github.com/okx/okbchain/x/wasm/types"
"strconv"
)

const (
Expand All @@ -14,6 +17,8 @@ const (

// DefaultDeserializationCostPerByte The formular should be `len(data) * deserializationCostPerByte`
DefaultDeserializationCostPerByte = 1

CallCreateDepth = 20
)

var (
Expand Down Expand Up @@ -41,3 +46,40 @@ var cosmwasmAPI = wasmvm.GoAPI{
HumanAddress: humanAddress,
CanonicalAddress: canonicalAddress,
}

func contractExternal(ctx sdk.Context, k Keeper) func(request wasmvmtypes.ContractCreateRequest, gasLimit uint64) (string, uint64, error) {
return func(request wasmvmtypes.ContractCreateRequest, gasLimit uint64) (string, uint64, error) {
ctx.IncrementCallDepth()
if ctx.CallDepth() >= CallCreateDepth {
return "", 0, sdkerrors.Wrap(types.ErrExceedCallDepth, strconv.Itoa(int(ctx.CallDepth())))
}

gasMeter := ctx.GasMeter()
ctx.SetGasMeter(sdk.NewGasMeter(k.gasRegister.FromWasmVMGas(gasLimit)))
gasBefore := ctx.GasMeter().GasConsumed()

defer func() {
ctx.DecrementCallDepth()

// reset gas meter
gasCost := ctx.GasMeter().GasConsumed() - gasBefore
ctx.SetGasMeter(gasMeter)
ctx.GasMeter().ConsumeGas(gasCost, "contract sub-create")
}()

creator, err := sdk.WasmAddressFromBech32(request.Creator)
if err != nil {
return "", 0, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, request.Creator)
}
admin, err := sdk.WasmAddressFromBech32(request.AdminAddr)
if err != nil {
return "", 0, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, request.AdminAddr)
}
addr, _, err := k.CreateByContract(ctx, creator, request.WasmCode, request.CodeID, request.InitMsg, admin, request.Label, request.IsCreate2, request.Salt, nil)
if err != nil {
return "", k.gasRegister.ToWasmVMGas(ctx.GasMeter().GasConsumed() - gasBefore), err
}

return addr.String(), k.gasRegister.ToWasmVMGas(ctx.GasMeter().GasConsumed() - gasBefore), nil
}
}
9 changes: 5 additions & 4 deletions x/wasm/keeper/contract_keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ var _ types.ContractOpsKeeper = PermissionedKeeper{}

// decoratedKeeper contains a subset of the wasm keeper that are already or can be guarded by an authorization policy in the future
type decoratedKeeper interface {
create(ctx sdk.Context, creator sdk.WasmAddress, wasmCode []byte, instantiateAccess *types.AccessConfig, authZ AuthorizationPolicy) (codeID uint64, err error)
instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.WasmAddress, initMsg []byte, label string, deposit sdk.Coins, authZ AuthorizationPolicy) (sdk.WasmAddress, []byte, error)
create(ctx sdk.Context, creator sdk.WasmAddress, wasmCode []byte, instantiateAccess *types.AccessConfig, authZ AuthorizationPolicy) (codeID uint64, codeHash []byte, err error)
instantiate(ctx sdk.Context, codeID uint64, creator, admin, contractAddress sdk.WasmAddress, initMsg []byte, label string, deposit sdk.Coins, authZ AuthorizationPolicy) (sdk.WasmAddress, []byte, error)
migrate(ctx sdk.Context, contractAddress sdk.WasmAddress, caller sdk.WasmAddress, newCodeID uint64, msg []byte, authZ AuthorizationPolicy) ([]byte, error)
setContractAdmin(ctx sdk.Context, contractAddress, caller, newAdmin sdk.WasmAddress, authZ AuthorizationPolicy) error
pinCode(ctx sdk.Context, codeID uint64) error
Expand Down Expand Up @@ -47,11 +47,12 @@ func NewDefaultPermissionKeeper(nested decoratedKeeper) *PermissionedKeeper {
}

func (p PermissionedKeeper) Create(ctx sdk.Context, creator sdk.WasmAddress, wasmCode []byte, instantiateAccess *types.AccessConfig) (codeID uint64, err error) {
return p.nested.create(ctx, creator, wasmCode, instantiateAccess, p.authZPolicy)
codeID, _, err = p.nested.create(ctx, creator, wasmCode, instantiateAccess, p.authZPolicy)
return
}

func (p PermissionedKeeper) Instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.WasmAddress, initMsg []byte, label string, deposit sdk.Coins) (sdk.WasmAddress, []byte, error) {
return p.nested.instantiate(ctx, codeID, creator, admin, initMsg, label, deposit, p.authZPolicy)
return p.nested.instantiate(ctx, codeID, creator, admin, nil, initMsg, label, deposit, p.authZPolicy)
}

func (p PermissionedKeeper) Execute(ctx sdk.Context, contractAddress sdk.WasmAddress, caller sdk.WasmAddress, msg []byte, coins sdk.Coins) ([]byte, error) {
Expand Down
87 changes: 87 additions & 0 deletions x/wasm/keeper/cross_contract_call.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package keeper

import (
"encoding/json"
wasmvm "github.com/CosmWasm/wasmvm"
sdk "github.com/okx/okbchain/libs/cosmos-sdk/types"
)

var (
wasmCache wasmvm.Cache
)

func SetWasmCache(cache wasmvm.Cache) {
wasmCache = cache
}

func GetWasmCacheInfo() wasmvm.Cache {
return wasmCache
}

func getCallerInfoFunc(ctx sdk.Context, keeper Keeper) func(contractAddress, storeAddress string) ([]byte, uint64, wasmvm.KVStore, wasmvm.Querier, wasmvm.GasMeter, error) {
return func(contractAddress, storeAddress string) ([]byte, uint64, wasmvm.KVStore, wasmvm.Querier, wasmvm.GasMeter, error) {
gasBefore := ctx.GasMeter().GasConsumed()
codeHash, store, querier, gasMeter, err := getCallerInfo(ctx, keeper, contractAddress, storeAddress)
gasAfter := ctx.GasMeter().GasConsumed()
return codeHash, keeper.gasRegister.ToWasmVMGas(gasAfter - gasBefore), store, querier, gasMeter, err
}
}

func getCallerInfo(ctx sdk.Context, keeper Keeper, contractAddress, storeAddress string) ([]byte, wasmvm.KVStore, wasmvm.Querier, wasmvm.GasMeter, error) {
cAddr, err := sdk.WasmAddressFromBech32(contractAddress)
if err != nil {
return nil, nil, nil, nil, err
}
// 1. get wasm code from contractAddress
_, codeInfo, prefixStore, err := keeper.contractInstance(ctx, cAddr)
if err != nil {
return nil, nil, nil, nil, err
}
// 2. contractAddress == storeAddress and direct return
if contractAddress == storeAddress {
queryHandler := keeper.newQueryHandler(ctx, cAddr)
return codeInfo.CodeHash, prefixStore, queryHandler, keeper.gasMeter(ctx), nil
}
// 3. get store from storeaddress
sAddr, err := sdk.WasmAddressFromBech32(storeAddress)
if err != nil {
return nil, nil, nil, nil, err
}
_, _, prefixStore, err = keeper.contractInstance(ctx, sAddr)
if err != nil {
return nil, nil, nil, nil, err
}
queryHandler := keeper.newQueryHandler(ctx, sAddr)
return codeInfo.CodeHash, prefixStore, queryHandler, keeper.gasMeter(ctx), nil
}

func transferCoinsFunc(ctx sdk.Context, keeper Keeper) func(contractAddress, caller string, coinsData []byte) (uint64, error) {
return func(contractAddress, caller string, coinsData []byte) (uint64, error) {
var coins sdk.Coins
err := json.Unmarshal(coinsData, &coins)
if err != nil {
return 0, err
}
gasBefore := ctx.GasMeter().GasConsumed()
err = transferCoins(ctx, keeper, contractAddress, caller, coins)
gasAfter := ctx.GasMeter().GasConsumed()
return keeper.gasRegister.ToWasmVMGas(gasAfter - gasBefore), err
}
}

func transferCoins(ctx sdk.Context, keeper Keeper, contractAddress, caller string, coins sdk.Coins) error {
if !coins.IsZero() {
contractAddr, err := sdk.WasmAddressFromBech32(contractAddress)
if err != nil {
return err
}
callerAddr, err := sdk.WasmAddressFromBech32(caller)
if err != nil {
return err
}
if err := keeper.bank.TransferCoins(ctx, callerAddr, contractAddr, coins); err != nil {
return err
}
}
return nil
}
55 changes: 55 additions & 0 deletions x/wasm/keeper/cross_contract_call_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package keeper

import (
"encoding/json"
sdk "github.com/okx/okbchain/libs/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"testing"
)

func TestGetWasmCallInfo(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, SupportedFeatures)
keeper := keepers.ContractKeeper

deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)

codeID, err := keeper.Create(ctx, creator, hackatomWasm, nil)
require.NoError(t, err)

_, _, bob := keyPubAddr()
_, _, fred := keyPubAddr()

initMsg := HackatomExampleInitMsg{
Verifier: fred,
Beneficiary: bob,
}
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)

em := sdk.NewEventManager()
// create with no balance is also legal
ctx.SetEventManager(em)
gotContractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, codeID, creator, nil, initMsgBz, "demo contract 1", nil)
require.NoError(t, err)

wasmkeeper := *keepers.WasmKeeper
// 1. contractAddress is equal to storeAddress
_, _, _, _, err = getCallerInfo(ctx, wasmkeeper, gotContractAddr.String(), gotContractAddr.String())
require.NoError(t, err)

// 2. contractAddress is not exist
_, _, _, _, err = getCallerInfo(ctx, wasmkeeper, "0xE70e7466a2f18FAd8C97c45Ba8fEc57d90F3435E", "0xE70e7466a2f18FAd8C97c45Ba8fEc57d90F3435E")
require.NotNil(t, err)

// 3. storeAddress is not exist
_, _, _, _, err = getCallerInfo(ctx, wasmkeeper, gotContractAddr.String(), "0xE70e7466a2f18FAd8C97c45Ba8fEc57d90F3435E")
require.NotNil(t, err)

// 4. contractAddress is not equal to storeAddress
gotContractAddr2, _, err := keepers.ContractKeeper.Instantiate(ctx, codeID, creator, nil, initMsgBz, "demo contract 1", nil)
_, kvs, q, _, err := getCallerInfo(ctx, wasmkeeper, gotContractAddr.String(), gotContractAddr2.String())
require.NoError(t, err)
require.NotNil(t, kvs)
require.NotNil(t, q)
}
Loading