forked from cerc-io/laconicd-deprecated
473 lines
12 KiB
Go
473 lines
12 KiB
Go
package keeper
|
|
|
|
import (
|
|
"math"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/cerc-io/laconicd/x/wasm/types"
|
|
|
|
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
|
|
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestCompileCosts(t *testing.T) {
|
|
specs := map[string]struct {
|
|
srcLen int
|
|
srcConfig WasmGasRegisterConfig
|
|
exp sdk.Gas
|
|
expPanic bool
|
|
}{
|
|
"one byte": {
|
|
srcLen: 1,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: sdk.Gas(3), // DefaultCompileCost
|
|
},
|
|
"zero byte": {
|
|
srcLen: 0,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: sdk.Gas(0),
|
|
},
|
|
"negative len": {
|
|
srcLen: -1,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
expPanic: true,
|
|
},
|
|
}
|
|
for name, spec := range specs {
|
|
t.Run(name, func(t *testing.T) {
|
|
if spec.expPanic {
|
|
assert.Panics(t, func() {
|
|
NewWasmGasRegister(spec.srcConfig).CompileCosts(spec.srcLen)
|
|
})
|
|
return
|
|
}
|
|
gotGas := NewWasmGasRegister(spec.srcConfig).CompileCosts(spec.srcLen)
|
|
assert.Equal(t, spec.exp, gotGas)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewContractInstanceCosts(t *testing.T) {
|
|
specs := map[string]struct {
|
|
srcLen int
|
|
srcConfig WasmGasRegisterConfig
|
|
pinned bool
|
|
exp sdk.Gas
|
|
expPanic bool
|
|
}{
|
|
"small msg - pinned": {
|
|
srcLen: 1,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
pinned: true,
|
|
exp: DefaultContractMessageDataCost,
|
|
},
|
|
"big msg - pinned": {
|
|
srcLen: math.MaxUint32,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
pinned: true,
|
|
exp: DefaultContractMessageDataCost * sdk.Gas(math.MaxUint32),
|
|
},
|
|
"empty msg - pinned": {
|
|
srcLen: 0,
|
|
pinned: true,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: sdk.Gas(0),
|
|
},
|
|
"small msg - unpinned": {
|
|
srcLen: 1,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: DefaultContractMessageDataCost + DefaultInstanceCost,
|
|
},
|
|
"big msg - unpinned": {
|
|
srcLen: math.MaxUint32,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: sdk.Gas(DefaultContractMessageDataCost*math.MaxUint32 + DefaultInstanceCost),
|
|
},
|
|
"empty msg - unpinned": {
|
|
srcLen: 0,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: sdk.Gas(DefaultInstanceCost),
|
|
},
|
|
|
|
"negative len": {
|
|
srcLen: -1,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
expPanic: true,
|
|
},
|
|
}
|
|
for name, spec := range specs {
|
|
t.Run(name, func(t *testing.T) {
|
|
if spec.expPanic {
|
|
assert.Panics(t, func() {
|
|
NewWasmGasRegister(spec.srcConfig).NewContractInstanceCosts(spec.pinned, spec.srcLen)
|
|
})
|
|
return
|
|
}
|
|
gotGas := NewWasmGasRegister(spec.srcConfig).NewContractInstanceCosts(spec.pinned, spec.srcLen)
|
|
assert.Equal(t, spec.exp, gotGas)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestContractInstanceCosts(t *testing.T) {
|
|
// same as TestNewContractInstanceCosts currently
|
|
specs := map[string]struct {
|
|
srcLen int
|
|
srcConfig WasmGasRegisterConfig
|
|
pinned bool
|
|
exp sdk.Gas
|
|
expPanic bool
|
|
}{
|
|
"small msg - pinned": {
|
|
srcLen: 1,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
pinned: true,
|
|
exp: DefaultContractMessageDataCost,
|
|
},
|
|
"big msg - pinned": {
|
|
srcLen: math.MaxUint32,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
pinned: true,
|
|
exp: sdk.Gas(DefaultContractMessageDataCost * math.MaxUint32),
|
|
},
|
|
"empty msg - pinned": {
|
|
srcLen: 0,
|
|
pinned: true,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: sdk.Gas(0),
|
|
},
|
|
"small msg - unpinned": {
|
|
srcLen: 1,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: DefaultContractMessageDataCost + DefaultInstanceCost,
|
|
},
|
|
"big msg - unpinned": {
|
|
srcLen: math.MaxUint32,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: sdk.Gas(DefaultContractMessageDataCost*math.MaxUint32 + DefaultInstanceCost),
|
|
},
|
|
"empty msg - unpinned": {
|
|
srcLen: 0,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: sdk.Gas(DefaultInstanceCost),
|
|
},
|
|
|
|
"negative len": {
|
|
srcLen: -1,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
expPanic: true,
|
|
},
|
|
}
|
|
for name, spec := range specs {
|
|
t.Run(name, func(t *testing.T) {
|
|
if spec.expPanic {
|
|
assert.Panics(t, func() {
|
|
NewWasmGasRegister(spec.srcConfig).InstantiateContractCosts(spec.pinned, spec.srcLen)
|
|
})
|
|
return
|
|
}
|
|
gotGas := NewWasmGasRegister(spec.srcConfig).InstantiateContractCosts(spec.pinned, spec.srcLen)
|
|
assert.Equal(t, spec.exp, gotGas)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestReplyCost(t *testing.T) {
|
|
specs := map[string]struct {
|
|
src wasmvmtypes.Reply
|
|
srcConfig WasmGasRegisterConfig
|
|
pinned bool
|
|
exp sdk.Gas
|
|
expPanic bool
|
|
}{
|
|
"subcall response with events and data - pinned": {
|
|
src: wasmvmtypes.Reply{
|
|
Result: wasmvmtypes.SubMsgResult{
|
|
Ok: &wasmvmtypes.SubMsgResponse{
|
|
Events: []wasmvmtypes.Event{
|
|
{Type: "foo", Attributes: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myData"}}},
|
|
},
|
|
Data: []byte{0x1},
|
|
},
|
|
},
|
|
},
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
pinned: true,
|
|
exp: sdk.Gas(3*DefaultEventAttributeDataCost + DefaultPerAttributeCost + DefaultContractMessageDataCost), // 3 == len("foo")
|
|
},
|
|
"subcall response with events - pinned": {
|
|
src: wasmvmtypes.Reply{
|
|
Result: wasmvmtypes.SubMsgResult{
|
|
Ok: &wasmvmtypes.SubMsgResponse{
|
|
Events: []wasmvmtypes.Event{
|
|
{Type: "foo", Attributes: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myData"}}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
pinned: true,
|
|
exp: sdk.Gas(3*DefaultEventAttributeDataCost + DefaultPerAttributeCost), // 3 == len("foo")
|
|
},
|
|
"subcall response with events exceeds free tier- pinned": {
|
|
src: wasmvmtypes.Reply{
|
|
Result: wasmvmtypes.SubMsgResult{
|
|
Ok: &wasmvmtypes.SubMsgResponse{
|
|
Events: []wasmvmtypes.Event{
|
|
{Type: "foo", Attributes: []wasmvmtypes.EventAttribute{{Key: strings.Repeat("x", DefaultEventAttributeDataFreeTier), Value: "myData"}}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
pinned: true,
|
|
exp: sdk.Gas((3+6)*DefaultEventAttributeDataCost + DefaultPerAttributeCost), // 3 == len("foo"), 6 == len("myData")
|
|
},
|
|
"subcall response error - pinned": {
|
|
src: wasmvmtypes.Reply{
|
|
Result: wasmvmtypes.SubMsgResult{
|
|
Err: "foo",
|
|
},
|
|
},
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
pinned: true,
|
|
exp: 3 * DefaultContractMessageDataCost,
|
|
},
|
|
"subcall response with events and data - unpinned": {
|
|
src: wasmvmtypes.Reply{
|
|
Result: wasmvmtypes.SubMsgResult{
|
|
Ok: &wasmvmtypes.SubMsgResponse{
|
|
Events: []wasmvmtypes.Event{
|
|
{Type: "foo", Attributes: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myData"}}},
|
|
},
|
|
Data: []byte{0x1},
|
|
},
|
|
},
|
|
},
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: sdk.Gas(DefaultInstanceCost + 3*DefaultEventAttributeDataCost + DefaultPerAttributeCost + DefaultContractMessageDataCost),
|
|
},
|
|
"subcall response with events - unpinned": {
|
|
src: wasmvmtypes.Reply{
|
|
Result: wasmvmtypes.SubMsgResult{
|
|
Ok: &wasmvmtypes.SubMsgResponse{
|
|
Events: []wasmvmtypes.Event{
|
|
{Type: "foo", Attributes: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myData"}}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: sdk.Gas(DefaultInstanceCost + 3*DefaultEventAttributeDataCost + DefaultPerAttributeCost),
|
|
},
|
|
"subcall response with events exceeds free tier- unpinned": {
|
|
src: wasmvmtypes.Reply{
|
|
Result: wasmvmtypes.SubMsgResult{
|
|
Ok: &wasmvmtypes.SubMsgResponse{
|
|
Events: []wasmvmtypes.Event{
|
|
{Type: "foo", Attributes: []wasmvmtypes.EventAttribute{{Key: strings.Repeat("x", DefaultEventAttributeDataFreeTier), Value: "myData"}}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: sdk.Gas(DefaultInstanceCost + (3+6)*DefaultEventAttributeDataCost + DefaultPerAttributeCost), // 3 == len("foo"), 6 == len("myData")
|
|
},
|
|
"subcall response error - unpinned": {
|
|
src: wasmvmtypes.Reply{
|
|
Result: wasmvmtypes.SubMsgResult{
|
|
Err: "foo",
|
|
},
|
|
},
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: sdk.Gas(DefaultInstanceCost + 3*DefaultContractMessageDataCost),
|
|
},
|
|
"subcall response with empty events": {
|
|
src: wasmvmtypes.Reply{
|
|
Result: wasmvmtypes.SubMsgResult{
|
|
Ok: &wasmvmtypes.SubMsgResponse{
|
|
Events: make([]wasmvmtypes.Event, 10),
|
|
},
|
|
},
|
|
},
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: DefaultInstanceCost,
|
|
},
|
|
"subcall response with events unset": {
|
|
src: wasmvmtypes.Reply{
|
|
Result: wasmvmtypes.SubMsgResult{
|
|
Ok: &wasmvmtypes.SubMsgResponse{},
|
|
},
|
|
},
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
exp: DefaultInstanceCost,
|
|
},
|
|
}
|
|
for name, spec := range specs {
|
|
t.Run(name, func(t *testing.T) {
|
|
if spec.expPanic {
|
|
assert.Panics(t, func() {
|
|
NewWasmGasRegister(spec.srcConfig).ReplyCosts(spec.pinned, spec.src)
|
|
})
|
|
return
|
|
}
|
|
gotGas := NewWasmGasRegister(spec.srcConfig).ReplyCosts(spec.pinned, spec.src)
|
|
assert.Equal(t, spec.exp, gotGas)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEventCosts(t *testing.T) {
|
|
// most cases are covered in TestReplyCost already. This ensures some edge cases
|
|
specs := map[string]struct {
|
|
srcAttrs []wasmvmtypes.EventAttribute
|
|
srcEvents wasmvmtypes.Events
|
|
expGas sdk.Gas
|
|
}{
|
|
"empty events": {
|
|
srcEvents: make([]wasmvmtypes.Event, 1),
|
|
expGas: DefaultPerCustomEventCost,
|
|
},
|
|
"empty attributes": {
|
|
srcAttrs: make([]wasmvmtypes.EventAttribute, 1),
|
|
expGas: DefaultPerAttributeCost,
|
|
},
|
|
"both nil": {
|
|
expGas: 0,
|
|
},
|
|
}
|
|
for name, spec := range specs {
|
|
t.Run(name, func(t *testing.T) {
|
|
gotGas := NewDefaultWasmGasRegister().EventCosts(spec.srcAttrs, spec.srcEvents)
|
|
assert.Equal(t, spec.expGas, gotGas)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestToWasmVMGasConversion(t *testing.T) {
|
|
specs := map[string]struct {
|
|
src storetypes.Gas
|
|
srcConfig WasmGasRegisterConfig
|
|
exp uint64
|
|
expPanic bool
|
|
}{
|
|
"0": {
|
|
src: 0,
|
|
exp: 0,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
},
|
|
"max": {
|
|
srcConfig: WasmGasRegisterConfig{
|
|
GasMultiplier: 1,
|
|
},
|
|
src: math.MaxUint64,
|
|
exp: math.MaxUint64,
|
|
},
|
|
"overflow": {
|
|
srcConfig: WasmGasRegisterConfig{
|
|
GasMultiplier: 2,
|
|
},
|
|
src: math.MaxUint64,
|
|
expPanic: true,
|
|
},
|
|
}
|
|
for name, spec := range specs {
|
|
t.Run(name, func(t *testing.T) {
|
|
if spec.expPanic {
|
|
assert.Panics(t, func() {
|
|
r := NewWasmGasRegister(spec.srcConfig)
|
|
_ = r.ToWasmVMGas(spec.src)
|
|
})
|
|
return
|
|
}
|
|
r := NewWasmGasRegister(spec.srcConfig)
|
|
got := r.ToWasmVMGas(spec.src)
|
|
assert.Equal(t, spec.exp, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFromWasmVMGasConversion(t *testing.T) {
|
|
specs := map[string]struct {
|
|
src uint64
|
|
exp storetypes.Gas
|
|
srcConfig WasmGasRegisterConfig
|
|
expPanic bool
|
|
}{
|
|
"0": {
|
|
src: 0,
|
|
exp: 0,
|
|
srcConfig: DefaultGasRegisterConfig(),
|
|
},
|
|
"max": {
|
|
srcConfig: WasmGasRegisterConfig{
|
|
GasMultiplier: 1,
|
|
},
|
|
src: math.MaxUint64,
|
|
exp: math.MaxUint64,
|
|
},
|
|
"missconfigured": {
|
|
srcConfig: WasmGasRegisterConfig{
|
|
GasMultiplier: 0,
|
|
},
|
|
src: 1,
|
|
expPanic: true,
|
|
},
|
|
}
|
|
for name, spec := range specs {
|
|
t.Run(name, func(t *testing.T) {
|
|
if spec.expPanic {
|
|
assert.Panics(t, func() {
|
|
r := NewWasmGasRegister(spec.srcConfig)
|
|
_ = r.FromWasmVMGas(spec.src)
|
|
})
|
|
return
|
|
}
|
|
r := NewWasmGasRegister(spec.srcConfig)
|
|
got := r.FromWasmVMGas(spec.src)
|
|
assert.Equal(t, spec.exp, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUncompressCosts(t *testing.T) {
|
|
specs := map[string]struct {
|
|
lenIn int
|
|
exp sdk.Gas
|
|
expPanic bool
|
|
}{
|
|
"0": {
|
|
exp: 0,
|
|
},
|
|
"even": {
|
|
lenIn: 100,
|
|
exp: 15,
|
|
},
|
|
"round down when uneven": {
|
|
lenIn: 19,
|
|
exp: 2,
|
|
},
|
|
"max len": {
|
|
lenIn: types.MaxWasmSize,
|
|
exp: 122880,
|
|
},
|
|
"invalid len": {
|
|
lenIn: -1,
|
|
expPanic: true,
|
|
},
|
|
}
|
|
for name, spec := range specs {
|
|
t.Run(name, func(t *testing.T) {
|
|
if spec.expPanic {
|
|
assert.Panics(t, func() { NewDefaultWasmGasRegister().UncompressCosts(spec.lenIn) })
|
|
return
|
|
}
|
|
got := NewDefaultWasmGasRegister().UncompressCosts(spec.lenIn)
|
|
assert.Equal(t, spec.exp, got)
|
|
})
|
|
}
|
|
}
|