From d587c9fd66e089ffe6ac42f9618e538f73c4dab6 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Sun, 20 Aug 2023 17:25:45 -0700 Subject: [PATCH 1/6] Add stylus programSize and programMemoryFootprint precompiles --- arbos/programs/programs.go | 11 +++++++++++ contracts | 2 +- precompiles/ArbWasm.go | 12 +++++++++++- system_tests/program_test.go | 10 ++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/arbos/programs/programs.go b/arbos/programs/programs.go index 518a034d8..369ae96d9 100644 --- a/arbos/programs/programs.go +++ b/arbos/programs/programs.go @@ -332,6 +332,17 @@ func (p Programs) ProgramVersion(address common.Address) (uint16, error) { return program.version, err } +func (p Programs) ProgramSize(address common.Address) (uint32, error) { + program, err := p.deserializeProgram(address) + // wasmSize represents the number of half kb units, return as bytes + return uint32(program.wasmSize) * 512, err +} + +func (p Programs) ProgramMemoryFootprint(address common.Address) (uint16, error) { + program, err := p.deserializeProgram(address) + return program.footprint, err +} + type goParams struct { version uint16 maxDepth uint32 diff --git a/contracts b/contracts index 3dd01dab6..4a15b42b7 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 3dd01dab6479df2a0d4b4eab74bfdf6cebcf39fa +Subproject commit 4a15b42b7aeb24b50a46a03c18af0cf61e318312 diff --git a/precompiles/ArbWasm.go b/precompiles/ArbWasm.go index 2fadf1f53..00133142c 100644 --- a/precompiles/ArbWasm.go +++ b/precompiles/ArbWasm.go @@ -56,11 +56,21 @@ func (con ArbWasm) PageLimit(c ctx, _ mech) (uint16, error) { return c.State.Programs().PageLimit() } -// Gets the current program version +// ProgramVersion returns the stylus version that program at addr was most recently compiled against func (con ArbWasm) ProgramVersion(c ctx, _ mech, program addr) (uint16, error) { return c.State.Programs().ProgramVersion(program) } +// ProgramSize returns the uncompressed size of program at addr +func (con ArbWasm) ProgramSize(c ctx, _ mech, program addr) (uint32, error) { + return c.State.Programs().ProgramSize(program) +} + +// ProgramMemoryFootprint returns the footprint of program at addr +func (con ArbWasm) ProgramMemoryFootprint(c ctx, _ mech, program addr) (uint16, error) { + return c.State.Programs().ProgramMemoryFootprint(program) +} + // Gets the added wasm call cost paid per half kb uncompressed wasm func (con ArbWasm) CallScalar(c ctx, _ mech) (uint16, error) { return c.State.Programs().CallScalar() diff --git a/system_tests/program_test.go b/system_tests/program_test.go index 3ae5a45c7..8ef71c0cd 100644 --- a/system_tests/program_test.go +++ b/system_tests/program_test.go @@ -57,6 +57,16 @@ func keccakTest(t *testing.T, jit bool) { if programVersion != stylusVersion || stylusVersion == 0 { Fatal(t, "unexpected versions", stylusVersion, programVersion) } + programSize, err := arbWasm.ProgramSize(nil, programAddress) + Require(t, err) + if programSize < 20000 || programSize > 30000 { + Fatal(t, "unexpected size", programSize) + } + programMemoryFootprint, err := arbWasm.ProgramMemoryFootprint(nil, programAddress) + Require(t, err) + if programMemoryFootprint != 1 { + Fatal(t, "unexpected memory footprint", programMemoryFootprint) + } preimage := []byte("°º¤ø,¸,ø¤°º¤ø,¸,ø¤°º¤ø,¸ nyan nyan ~=[,,_,,]:3 nyan nyan") correct := crypto.Keccak256Hash(preimage) From 8e83c244e35c544a1ed4056a1c33ef40eb33b6aa Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Tue, 22 Aug 2023 17:01:37 -0700 Subject: [PATCH 2/6] Update contracts pin --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 4a15b42b7..4e257d7f0 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 4a15b42b7aeb24b50a46a03c18af0cf61e318312 +Subproject commit 4e257d7f02a203ba033a378dee39883edeb22b57 From 114483fc4119d4397b118c642fd08fe400e98310 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Tue, 5 Sep 2023 17:43:26 -0700 Subject: [PATCH 3/6] Fix merge error --- arbitrator/stylus/tests/create/Cargo.lock | 4 +--- arbitrator/stylus/tests/erc20/Cargo.lock | 4 +--- arbitrator/stylus/tests/evm-data/Cargo.lock | 4 +--- arbitrator/stylus/tests/fallible/Cargo.lock | 4 +--- arbitrator/stylus/tests/keccak-100/Cargo.lock | 4 +--- arbitrator/stylus/tests/keccak/Cargo.lock | 4 +--- arbitrator/stylus/tests/log/Cargo.lock | 4 +--- arbitrator/stylus/tests/multicall/Cargo.lock | 4 +--- arbitrator/stylus/tests/read-return-data/Cargo.lock | 4 +--- arbitrator/stylus/tests/sdk-storage/Cargo.lock | 4 +--- arbitrator/stylus/tests/storage/Cargo.lock | 4 +--- arbos/programs/programs.go | 8 ++++---- precompiles/ArbWasm.go | 12 ++++++++++-- system_tests/program_test.go | 2 +- 14 files changed, 26 insertions(+), 40 deletions(-) diff --git a/arbitrator/stylus/tests/create/Cargo.lock b/arbitrator/stylus/tests/create/Cargo.lock index 924fd6a28..69a54ed59 100644 --- a/arbitrator/stylus/tests/create/Cargo.lock +++ b/arbitrator/stylus/tests/create/Cargo.lock @@ -436,9 +436,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ed6e3a897eea8ef2e19836b622fde7a9b114009f7eeca00d26a232e70603d0" +version = "0.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/arbitrator/stylus/tests/erc20/Cargo.lock b/arbitrator/stylus/tests/erc20/Cargo.lock index f3a316a45..b06910e01 100644 --- a/arbitrator/stylus/tests/erc20/Cargo.lock +++ b/arbitrator/stylus/tests/erc20/Cargo.lock @@ -646,9 +646,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ed6e3a897eea8ef2e19836b622fde7a9b114009f7eeca00d26a232e70603d0" +version = "0.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/arbitrator/stylus/tests/evm-data/Cargo.lock b/arbitrator/stylus/tests/evm-data/Cargo.lock index 8191751e5..2108a6a7e 100644 --- a/arbitrator/stylus/tests/evm-data/Cargo.lock +++ b/arbitrator/stylus/tests/evm-data/Cargo.lock @@ -436,9 +436,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ed6e3a897eea8ef2e19836b622fde7a9b114009f7eeca00d26a232e70603d0" +version = "0.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/arbitrator/stylus/tests/fallible/Cargo.lock b/arbitrator/stylus/tests/fallible/Cargo.lock index 94e121d48..6015667eb 100644 --- a/arbitrator/stylus/tests/fallible/Cargo.lock +++ b/arbitrator/stylus/tests/fallible/Cargo.lock @@ -435,9 +435,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ed6e3a897eea8ef2e19836b622fde7a9b114009f7eeca00d26a232e70603d0" +version = "0.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/arbitrator/stylus/tests/keccak-100/Cargo.lock b/arbitrator/stylus/tests/keccak-100/Cargo.lock index 0b6090627..4dd3dbc58 100644 --- a/arbitrator/stylus/tests/keccak-100/Cargo.lock +++ b/arbitrator/stylus/tests/keccak-100/Cargo.lock @@ -436,9 +436,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ed6e3a897eea8ef2e19836b622fde7a9b114009f7eeca00d26a232e70603d0" +version = "0.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/arbitrator/stylus/tests/keccak/Cargo.lock b/arbitrator/stylus/tests/keccak/Cargo.lock index c4e01bb8d..b45423744 100644 --- a/arbitrator/stylus/tests/keccak/Cargo.lock +++ b/arbitrator/stylus/tests/keccak/Cargo.lock @@ -436,9 +436,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ed6e3a897eea8ef2e19836b622fde7a9b114009f7eeca00d26a232e70603d0" +version = "0.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/arbitrator/stylus/tests/log/Cargo.lock b/arbitrator/stylus/tests/log/Cargo.lock index ec0f38791..96d277207 100644 --- a/arbitrator/stylus/tests/log/Cargo.lock +++ b/arbitrator/stylus/tests/log/Cargo.lock @@ -436,9 +436,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ed6e3a897eea8ef2e19836b622fde7a9b114009f7eeca00d26a232e70603d0" +version = "0.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/arbitrator/stylus/tests/multicall/Cargo.lock b/arbitrator/stylus/tests/multicall/Cargo.lock index f9c9e9a79..b5f6448b9 100644 --- a/arbitrator/stylus/tests/multicall/Cargo.lock +++ b/arbitrator/stylus/tests/multicall/Cargo.lock @@ -436,9 +436,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ed6e3a897eea8ef2e19836b622fde7a9b114009f7eeca00d26a232e70603d0" +version = "0.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/arbitrator/stylus/tests/read-return-data/Cargo.lock b/arbitrator/stylus/tests/read-return-data/Cargo.lock index 6714df776..93aa43d18 100644 --- a/arbitrator/stylus/tests/read-return-data/Cargo.lock +++ b/arbitrator/stylus/tests/read-return-data/Cargo.lock @@ -436,9 +436,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ed6e3a897eea8ef2e19836b622fde7a9b114009f7eeca00d26a232e70603d0" +version = "0.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/arbitrator/stylus/tests/sdk-storage/Cargo.lock b/arbitrator/stylus/tests/sdk-storage/Cargo.lock index 596e64381..37fdf787c 100644 --- a/arbitrator/stylus/tests/sdk-storage/Cargo.lock +++ b/arbitrator/stylus/tests/sdk-storage/Cargo.lock @@ -449,9 +449,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ed6e3a897eea8ef2e19836b622fde7a9b114009f7eeca00d26a232e70603d0" +version = "0.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/arbitrator/stylus/tests/storage/Cargo.lock b/arbitrator/stylus/tests/storage/Cargo.lock index 7a967b751..81dbed9c5 100644 --- a/arbitrator/stylus/tests/storage/Cargo.lock +++ b/arbitrator/stylus/tests/storage/Cargo.lock @@ -435,9 +435,7 @@ dependencies = [ [[package]] name = "stylus-proc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ed6e3a897eea8ef2e19836b622fde7a9b114009f7eeca00d26a232e70603d0" +version = "0.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/arbos/programs/programs.go b/arbos/programs/programs.go index 21c6fcf08..771c77855 100644 --- a/arbos/programs/programs.go +++ b/arbos/programs/programs.go @@ -333,14 +333,14 @@ func (p Programs) CodehashVersion(codeHash common.Hash) (uint16, error) { return program.version, err } -func (p Programs) ProgramSize(address common.Address) (uint32, error) { - program, err := p.deserializeProgram(address) +func (p Programs) CodehashSize(codeHash common.Hash) (uint32, error) { + program, err := p.deserializeProgram(codeHash) // wasmSize represents the number of half kb units, return as bytes return uint32(program.wasmSize) * 512, err } -func (p Programs) ProgramMemoryFootprint(address common.Address) (uint16, error) { - program, err := p.deserializeProgram(address) +func (p Programs) CodehashMemoryFootprint(codeHash common.Hash) (uint16, error) { + program, err := p.deserializeProgram(codeHash) return program.footprint, err } diff --git a/precompiles/ArbWasm.go b/precompiles/ArbWasm.go index 46a5881e9..cca38d830 100644 --- a/precompiles/ArbWasm.go +++ b/precompiles/ArbWasm.go @@ -73,12 +73,20 @@ func (con ArbWasm) ProgramVersion(c ctx, evm mech, program addr) (uint16, error) // ProgramSize returns the uncompressed size of program at addr func (con ArbWasm) ProgramSize(c ctx, _ mech, program addr) (uint32, error) { - return c.State.Programs().ProgramSize(program) + codehash, err := c.GetCodeHash(program) + if err != nil { + return 0, err + } + return c.State.Programs().CodehashSize(codehash) } // ProgramMemoryFootprint returns the footprint of program at addr func (con ArbWasm) ProgramMemoryFootprint(c ctx, _ mech, program addr) (uint16, error) { - return c.State.Programs().ProgramMemoryFootprint(program) + codehash, err := c.GetCodeHash(program) + if err != nil { + return 0, err + } + return c.State.Programs().CodehashMemoryFootprint(codehash) } // Gets the added wasm call cost paid per half kb uncompressed wasm diff --git a/system_tests/program_test.go b/system_tests/program_test.go index 6480bf326..b04e4131f 100644 --- a/system_tests/program_test.go +++ b/system_tests/program_test.go @@ -86,7 +86,7 @@ func keccakTest(t *testing.T, jit bool) { } programSize, err := arbWasm.ProgramSize(nil, programAddress) Require(t, err) - if programSize < 20000 || programSize > 30000 { + if programSize < 5000 || programSize > 20000 { Fatal(t, "unexpected size", programSize) } programMemoryFootprint, err := arbWasm.ProgramMemoryFootprint(nil, programAddress) From e01da0a11dfc2e285e2ae686c013a7d437ef6cf7 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Tue, 5 Sep 2023 21:57:01 -0700 Subject: [PATCH 4/6] Improve unit tests --- arbos/programs/programs.go | 4 ++-- precompiles/ArbWasm.go | 4 ++-- system_tests/program_test.go | 20 ++++++++++++++------ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/arbos/programs/programs.go b/arbos/programs/programs.go index 771c77855..178b291e1 100644 --- a/arbos/programs/programs.go +++ b/arbos/programs/programs.go @@ -333,13 +333,13 @@ func (p Programs) CodehashVersion(codeHash common.Hash) (uint16, error) { return program.version, err } -func (p Programs) CodehashSize(codeHash common.Hash) (uint32, error) { +func (p Programs) ProgramSize(codeHash common.Hash) (uint32, error) { program, err := p.deserializeProgram(codeHash) // wasmSize represents the number of half kb units, return as bytes return uint32(program.wasmSize) * 512, err } -func (p Programs) CodehashMemoryFootprint(codeHash common.Hash) (uint16, error) { +func (p Programs) ProgramMemoryFootprint(codeHash common.Hash) (uint16, error) { program, err := p.deserializeProgram(codeHash) return program.footprint, err } diff --git a/precompiles/ArbWasm.go b/precompiles/ArbWasm.go index cca38d830..aeb61d082 100644 --- a/precompiles/ArbWasm.go +++ b/precompiles/ArbWasm.go @@ -77,7 +77,7 @@ func (con ArbWasm) ProgramSize(c ctx, _ mech, program addr) (uint32, error) { if err != nil { return 0, err } - return c.State.Programs().CodehashSize(codehash) + return c.State.Programs().ProgramSize(codehash) } // ProgramMemoryFootprint returns the footprint of program at addr @@ -86,7 +86,7 @@ func (con ArbWasm) ProgramMemoryFootprint(c ctx, _ mech, program addr) (uint16, if err != nil { return 0, err } - return c.State.Programs().CodehashMemoryFootprint(codehash) + return c.State.Programs().ProgramMemoryFootprint(codehash) } // Gets the added wasm call cost paid per half kb uncompressed wasm diff --git a/system_tests/program_test.go b/system_tests/program_test.go index b04e4131f..33c579bf6 100644 --- a/system_tests/program_test.go +++ b/system_tests/program_test.go @@ -86,13 +86,12 @@ func keccakTest(t *testing.T, jit bool) { } programSize, err := arbWasm.ProgramSize(nil, programAddress) Require(t, err) - if programSize < 5000 || programSize > 20000 { - Fatal(t, "unexpected size", programSize) - } - programMemoryFootprint, err := arbWasm.ProgramMemoryFootprint(nil, programAddress) + source, err := os.ReadFile(rustFile("keccak")) Require(t, err) - if programMemoryFootprint != 1 { - Fatal(t, "unexpected memory footprint", programMemoryFootprint) + wasmSize := len(source) + expectedWasmSize := ((wasmSize + 511) / 512) * 512 + if int(programSize) != expectedWasmSize { + Fatal(t, "found size", programSize, "expected size", wasmSize) } preimage := []byte("°º¤ø,¸,ø¤°º¤ø,¸,ø¤°º¤ø,¸ nyan nyan ~=[,,_,,]:3 nyan nyan") @@ -783,6 +782,8 @@ func testMemory(t *testing.T, jit bool) { arbOwner, err := precompilesgen.NewArbOwner(types.ArbOwnerAddress, l2client) Require(t, err) + arbWasm, err := precompilesgen.NewArbWasm(types.ArbWasmAddress, l2client) + Require(t, err) ensure(arbOwner.SetInkPrice(&auth, 1e4)) ensure(arbOwner.SetMaxTxGasLimit(&auth, 34000000)) @@ -846,6 +847,13 @@ func testMemory(t *testing.T, jit bool) { args = arbmath.ConcatByteSlices([]byte{60}, types.ArbWasmAddress[:], pack(activate(growHugeAddr))) expectFailure(growCallAddr, args) // consumes 64, then tries to compile something 120 + // check huge memory footprint + programMemoryFootprint, err := arbWasm.ProgramMemoryFootprint(nil, growHugeAddr) + Require(t, err) + if programMemoryFootprint != 120 { + Fatal(t, "unexpected memory footprint", programMemoryFootprint) + } + // check that compilation then succeeds args[0] = 0x00 tx = l2info.PrepareTxTo("Owner", &growCallAddr, 1e9, nil, args) From 9e98022767c2060eed66eb10c746d403792f0a6a Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Wed, 6 Sep 2023 08:23:06 -0700 Subject: [PATCH 5/6] Only check memory footprint after compiled --- system_tests/program_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/system_tests/program_test.go b/system_tests/program_test.go index 33c579bf6..4023e8f6a 100644 --- a/system_tests/program_test.go +++ b/system_tests/program_test.go @@ -847,13 +847,6 @@ func testMemory(t *testing.T, jit bool) { args = arbmath.ConcatByteSlices([]byte{60}, types.ArbWasmAddress[:], pack(activate(growHugeAddr))) expectFailure(growCallAddr, args) // consumes 64, then tries to compile something 120 - // check huge memory footprint - programMemoryFootprint, err := arbWasm.ProgramMemoryFootprint(nil, growHugeAddr) - Require(t, err) - if programMemoryFootprint != 120 { - Fatal(t, "unexpected memory footprint", programMemoryFootprint) - } - // check that compilation then succeeds args[0] = 0x00 tx = l2info.PrepareTxTo("Owner", &growCallAddr, 1e9, nil, args) @@ -873,6 +866,13 @@ func testMemory(t *testing.T, jit bool) { Fatal(t, "unexpected cost", gasCost, memCost) } + // check huge memory footprint + programMemoryFootprint, err := arbWasm.ProgramMemoryFootprint(nil, growHugeAddr) + Require(t, err) + if programMemoryFootprint != 120 { + Fatal(t, "unexpected memory footprint", programMemoryFootprint) + } + validateBlocks(t, 2, jit, ctx, node, l2client) } From 6c21383c633418ee08769772bf71ae40cfcae55d Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Wed, 6 Sep 2023 11:15:18 -0600 Subject: [PATCH 6/6] test all sizes --- system_tests/program_test.go | 47 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/system_tests/program_test.go b/system_tests/program_test.go index 4023e8f6a..ea4faa442 100644 --- a/system_tests/program_test.go +++ b/system_tests/program_test.go @@ -49,7 +49,7 @@ func keccakTest(t *testing.T, jit bool) { defer cleanup() programAddress := deployWasm(t, ctx, auth, l2client, rustFile("keccak")) - wasm := readWasmFile(t, rustFile("keccak")) + wasm, _ := readWasmFile(t, rustFile("keccak")) otherAddressSameCode := deployContract(t, ctx, auth, l2client, wasm) arbWasm, err := precompilesgen.NewArbWasm(types.ArbWasmAddress, l2client) Require(t, err) @@ -84,15 +84,6 @@ func keccakTest(t *testing.T, jit bool) { if otherVersion != programVersion { Fatal(t, "mismatched versions", stylusVersion, programVersion) } - programSize, err := arbWasm.ProgramSize(nil, programAddress) - Require(t, err) - source, err := os.ReadFile(rustFile("keccak")) - Require(t, err) - wasmSize := len(source) - expectedWasmSize := ((wasmSize + 511) / 512) * 512 - if int(programSize) != expectedWasmSize { - Fatal(t, "found size", programSize, "expected size", wasmSize) - } preimage := []byte("°º¤ø,¸,ø¤°º¤ø,¸,ø¤°º¤ø,¸ nyan nyan ~=[,,_,,]:3 nyan nyan") correct := crypto.Keccak256Hash(preimage) @@ -161,7 +152,7 @@ func testActivateTwice(t *testing.T, jit bool) { Require(t, err) ensure(arbOwner.SetInkPrice(&auth, 1)) - wasm := readWasmFile(t, rustFile("keccak")) + wasm, _ := readWasmFile(t, rustFile("keccak")) keccakA := deployContract(t, ctx, auth, l2client, wasm) keccakB := deployContract(t, ctx, auth, l2client, wasm) @@ -609,7 +600,7 @@ func testCreate(t *testing.T, jit bool) { return receipt } - deployWasm := readWasmFile(t, rustFile("storage")) + deployWasm, _ := readWasmFile(t, rustFile("storage")) deployCode := deployContractInitCode(deployWasm, false) startValue := testhelpers.RandomCallValue(1e12) salt := testhelpers.RandomHash() @@ -833,7 +824,7 @@ func testMemory(t *testing.T, jit bool) { expectFailure(multiAddr, args) // check that compilation fails when out of memory - wasm := readWasmFile(t, watFile("grow-120")) + wasm, _ := readWasmFile(t, watFile("grow-120")) growHugeAddr := deployContract(t, ctx, auth, l2client, wasm) colors.PrintGrey("memory.wat ", memoryAddr) colors.PrintGrey("multicall.rs ", multiAddr) @@ -888,7 +879,7 @@ func testActivateFails(t *testing.T, jit bool) { arbWasm, err := precompilesgen.NewArbWasm(types.ArbWasmAddress, l2client) Require(t, err) - badExportWasm := readWasmFile(t, watFile("bad-export")) + badExportWasm, _ := readWasmFile(t, watFile("bad-export")) auth.GasLimit = 32000000 // skip gas estimation badExportAddr := deployContract(t, ctx, auth, l2client, badExportWasm) @@ -1030,7 +1021,7 @@ func setupProgramTest(t *testing.T, jit bool) ( return ctx, node, l2info, l2client, auth, cleanup } -func readWasmFile(t *testing.T, file string) []byte { +func readWasmFile(t *testing.T, file string) ([]byte, []byte) { name := strings.TrimSuffix(filepath.Base(file), filepath.Ext(file)) source, err := os.ReadFile(file) Require(t, err) @@ -1044,18 +1035,30 @@ func readWasmFile(t *testing.T, file string) []byte { colors.PrintGrey(fmt.Sprintf("%v: len %.2fK vs %.2fK", name, toKb(wasm), toKb(wasmSource))) wasm = append(state.StylusPrefix, wasm...) - return wasm + return wasm, wasmSource } func deployWasm( t *testing.T, ctx context.Context, auth bind.TransactOpts, l2client *ethclient.Client, file string, ) common.Address { name := strings.TrimSuffix(filepath.Base(file), filepath.Ext(file)) - wasm := readWasmFile(t, file) + wasm, uncompressed := readWasmFile(t, file) auth.GasLimit = 32000000 // skip gas estimation - programAddress := deployContract(t, ctx, auth, l2client, wasm) - colors.PrintGrey(name, ": deployed to ", programAddress.Hex()) - return activateWasm(t, ctx, auth, l2client, programAddress, name) + program := deployContract(t, ctx, auth, l2client, wasm) + colors.PrintGrey(name, ": deployed to ", program.Hex()) + activateWasm(t, ctx, auth, l2client, program, name) + + // check that program size matches + arbWasm, err := precompilesgen.NewArbWasm(types.ArbWasmAddress, l2client) + Require(t, err) + programSize, err := arbWasm.ProgramSize(nil, program) + Require(t, err) + expected := (len(uncompressed) + 511) / 512 * 512 + if int(programSize) != expected { + Fatal(t, "unexpected program size", name, programSize, expected, len(wasm)) + } + + return program } func activateWasm( @@ -1065,8 +1068,7 @@ func activateWasm( l2client *ethclient.Client, program common.Address, name string, -) common.Address { - +) { arbWasm, err := precompilesgen.NewArbWasm(types.ArbWasmAddress, l2client) Require(t, err) @@ -1076,7 +1078,6 @@ func activateWasm( _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) }) - return program } func argsForStorageRead(key common.Hash) []byte {