Skip to content

Commit

Permalink
Make StoreCode return gas cost
Browse files Browse the repository at this point in the history
  • Loading branch information
chipshort committed Jan 24, 2024
1 parent 4eed00c commit f8b899a
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 16 deletions.
2 changes: 1 addition & 1 deletion cmd/demo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func main() {
panic(err)
}

checksum, err := vm.StoreCode(bz)
checksum, _, err := vm.StoreCode(bz)
if err != nil {
panic(err)
}
Expand Down
6 changes: 3 additions & 3 deletions ibc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestIBC(t *testing.T) {
wasm, err := os.ReadFile(IBC_TEST_CONTRACT)
require.NoError(t, err)

checksum, err := vm.StoreCode(wasm)
checksum, _, err := vm.StoreCode(wasm)
require.NoError(t, err)

code, err := vm.GetCode(checksum)
Expand Down Expand Up @@ -295,7 +295,7 @@ func TestAnalyzeCode(t *testing.T) {
// Store non-IBC contract
wasm, err := os.ReadFile(HACKATOM_TEST_CONTRACT)
require.NoError(t, err)
checksum, err := vm.StoreCode(wasm)
checksum, _, err := vm.StoreCode(wasm)
require.NoError(t, err)
// and analyze
report, err := vm.AnalyzeCode(checksum)
Expand All @@ -307,7 +307,7 @@ func TestAnalyzeCode(t *testing.T) {
// Store IBC contract
wasm2, err := os.ReadFile(IBC_TEST_CONTRACT)
require.NoError(t, err)
checksum2, err := vm.StoreCode(wasm2)
checksum2, _, err := vm.StoreCode(wasm2)
require.NoError(t, err)
// and analyze
report2, err := vm.AnalyzeCode(checksum2)
Expand Down
16 changes: 13 additions & 3 deletions lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ func (vm *VM) Cleanup() {
// This function stores the code for that contract only once, but it can
// be instantiated with custom inputs in the future.
//
// TODO: return gas cost? Add gas limit??? there is no metering here...
func (vm *VM) StoreCode(code WasmCode) (Checksum, error) {
return api.StoreCode(vm.cache, code)
// Returns both the checksum, as well as the gas cost of compilation (in CosmWasm Gas) or an error.
func (vm *VM) StoreCode(code WasmCode) (Checksum, uint64, error) {
checksum, err := api.StoreCode(vm.cache, code)
return checksum, compileCosts(code), err
}

// StoreCodeUnchecked is the same as StoreCode but skips static validation checks.
Expand Down Expand Up @@ -525,6 +526,15 @@ func (vm *VM) IBCPacketTimeout(
return &result, gasReport.UsedInternally, nil
}

func compileCosts(code WasmCode) uint64 {
// CostPerByte is how much CosmWasm gas is charged *per byte* for compiling WASM code.
// Benchmarks and numbers (in SDK Gas) were discussed in:
// https://github.com/CosmWasm/wasmd/pull/634#issuecomment-938056803
const CostPerByte uint64 = 3 * 140_000

return CostPerByte * uint64(len(code))
}

func DeserializeResponse(gasLimit uint64, deserCost types.UFraction, gasReport *types.GasReport, data []byte, response any) error {
gasForDeserialization := deserCost.Mul(uint64(len(data))).Floor()
if gasLimit < gasForDeserialization+gasReport.UsedInternally {
Expand Down
18 changes: 9 additions & 9 deletions lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func withVM(t *testing.T) *VM {
func createTestContract(t *testing.T, vm *VM, path string) Checksum {
wasm, err := os.ReadFile(path)
require.NoError(t, err)
checksum, err := vm.StoreCode(wasm)
checksum, _, err := vm.StoreCode(wasm)
require.NoError(t, err)
return checksum
}
Expand All @@ -56,15 +56,15 @@ func TestStoreCode(t *testing.T) {
{
wasm, err := os.ReadFile(HACKATOM_TEST_CONTRACT)
require.NoError(t, err)
_, err = vm.StoreCode(wasm)
_, _, err = vm.StoreCode(wasm)
require.NoError(t, err)
}

// Valid cyberpunk contract
{
wasm, err := os.ReadFile(CYBERPUNK_TEST_CONTRACT)
require.NoError(t, err)
_, err = vm.StoreCode(wasm)
_, _, err = vm.StoreCode(wasm)
require.NoError(t, err)
}

Expand All @@ -74,28 +74,28 @@ func TestStoreCode(t *testing.T) {
// hexdump -C < empty.wasm

wasm := []byte{0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00}
_, err := vm.StoreCode(wasm)
_, _, err := vm.StoreCode(wasm)
require.ErrorContains(t, err, "Error during static Wasm validation: Wasm contract must contain exactly one memory")
}

// No Wasm
{
wasm := []byte("foobar")
_, err := vm.StoreCode(wasm)
_, _, err := vm.StoreCode(wasm)
require.ErrorContains(t, err, "Wasm bytecode could not be deserialized")
}

// Empty
{
wasm := []byte("")
_, err := vm.StoreCode(wasm)
_, _, err := vm.StoreCode(wasm)
require.ErrorContains(t, err, "Wasm bytecode could not be deserialized")
}

// Nil
{
var wasm []byte = nil
_, err := vm.StoreCode(wasm)
_, _, err := vm.StoreCode(wasm)
require.ErrorContains(t, err, "Null/Nil argument: wasm")
}
}
Expand All @@ -106,7 +106,7 @@ func TestStoreCodeAndGet(t *testing.T) {
wasm, err := os.ReadFile(HACKATOM_TEST_CONTRACT)
require.NoError(t, err)

checksum, err := vm.StoreCode(wasm)
checksum, _, err := vm.StoreCode(wasm)
require.NoError(t, err)

code, err := vm.GetCode(checksum)
Expand All @@ -120,7 +120,7 @@ func TestRemoveCode(t *testing.T) {
wasm, err := os.ReadFile(HACKATOM_TEST_CONTRACT)
require.NoError(t, err)

checksum, err := vm.StoreCode(wasm)
checksum, _, err := vm.StoreCode(wasm)
require.NoError(t, err)

err = vm.RemoveCode(checksum)
Expand Down

0 comments on commit f8b899a

Please sign in to comment.