Test external query gas limits are still enforced

This commit is contained in:
Ethan Frey 2020-07-27 14:10:04 +02:00
parent 8af0c88e34
commit e088aecde1
1 changed files with 114 additions and 0 deletions

View File

@ -2,6 +2,7 @@ package keeper
import (
"encoding/json"
abci "github.com/tendermint/tendermint/abci/types"
"io/ioutil"
"os"
"testing"
@ -81,6 +82,7 @@ func TestGasCostOnQuery(t *testing.T) {
Depth: 4,
Work: 50,
},
// this is (currently) 244_708 gas
expectedGas: 5*GasWork50 + 4*GasReturnHashed,
},
}
@ -116,6 +118,9 @@ func TestGasCostOnQuery(t *testing.T) {
for name, tc := range cases {
tc := tc
t.Run(name, func(t *testing.T) {
// external limit has no effect (we get a panic if this is enforced)
keeper.queryGasLimit = 1000
// make sure we set a limit before calling
ctx = ctx.WithGasMeter(sdk.NewGasMeter(tc.gasLimit))
require.Equal(t, uint64(0), ctx.GasMeter().GasConsumed())
@ -143,3 +148,112 @@ func TestGasCostOnQuery(t *testing.T) {
})
}
}
func TestGasOnExternalQuery(t *testing.T) {
const (
GasWork50 uint64 = InstanceCost + 8_464
GasReturnHashed uint64 = 597
)
cases := map[string]struct {
gasLimit uint64
msg Recurse
expectPanic bool
}{
"no recursion, plenty gas": {
gasLimit: 400_000,
msg: Recurse{
Work: 50, // 50 rounds of sha256 inside the contract
},
},
"recursion 4, plenty gas": {
// this uses 244708 gas
gasLimit: 400_000,
msg: Recurse{
Depth: 4,
Work: 50,
},
},
"no recursion, external gas limit": {
gasLimit: 5000, // this is not enough
msg: Recurse{
Work: 50,
},
expectPanic: true,
},
"recursion 4, external gas limit": {
// this uses 244708 gas but give less
gasLimit: 4 * GasWork50,
msg: Recurse{
Depth: 4,
Work: 50,
},
expectPanic: true,
},
}
// we do one basic setup before all test cases (which are read-only and don't change state)
tempDir, err := ioutil.TempDir("", "wasm")
require.NoError(t, err)
defer os.RemoveAll(tempDir)
ctx, keepers := CreateTestInput(t, false, tempDir, SupportedFeatures, nil, nil)
accKeeper, keeper := keepers.AccountKeeper, keepers.WasmKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := createFakeFundedAccount(ctx, accKeeper, deposit.Add(deposit...))
// store the code
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
require.NoError(t, err)
codeID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
require.NoError(t, err)
// instantiate the contract
_, _, bob := keyPubAddr()
_, _, fred := keyPubAddr()
initMsg := InitMsg{
Verifier: fred,
Beneficiary: bob,
}
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
contractAddr, err := keeper.Instantiate(ctx, codeID, creator, nil, initMsgBz, "recursive contract", deposit)
require.NoError(t, err)
for name, tc := range cases {
tc := tc
t.Run(name, func(t *testing.T) {
// set the external gas limit (normally from config file)
keeper.queryGasLimit = tc.gasLimit
recurse := tc.msg
recurse.Contract = contractAddr
msg := buildQuery(t, recurse)
// do the query
path := []string{QueryGetContractState, contractAddr.String(), QueryMethodContractStateSmart}
req := abci.RequestQuery{Data: msg}
if tc.expectPanic {
require.Panics(t, func() {
// this should run out of gas
_, _ = NewQuerier(keeper)(ctx, path, req)
})
return
}
// otherwise, make sure we get a good success
data, err := NewQuerier(keeper)(ctx, path, req)
require.NoError(t, err)
var resp recurseResponse
err = json.Unmarshal(data, &resp)
require.NoError(t, err)
// assert result is 32 byte sha256 hash (if hashed), or contractAddr if not
if recurse.Work == 0 {
assert.Equal(t, len(resp.Hashed), len(creator.String()))
} else {
assert.Equal(t, len(resp.Hashed), 32)
}
})
}
}