diff --git a/gno.land/pkg/integration/testdata/addpkg_import_testdep_gas.txtar b/gno.land/pkg/integration/testdata/addpkg_import_testdep_gas.txtar index e17eae47980..95b7efc0f03 100644 --- a/gno.land/pkg/integration/testdata/addpkg_import_testdep_gas.txtar +++ b/gno.land/pkg/integration/testdata/addpkg_import_testdep_gas.txtar @@ -12,9 +12,10 @@ # On the pre-split single-blob layout, depb's mempackage included its _test.gno, # so type-checking useb decoded those extra bytes and useb cost MORE than usea. # -# Measured: on this branch usea == useb == 3172401 (equal => the win). On master -# (pre-split) usea == 3172364 but useb == 3212984 -- importing depb costs +40620 -# gas for its _test.gno bytes. The split removes that import penalty. +# Measured: on this branch usea == useb == 3277401 (equal => the win; includes the +# PreprocessGasPerByte addpkg charge). On master (pre-split, pre-charge) usea == 3172364 +# but useb == 3212984 -- importing depb costs +40620 gas for its _test.gno bytes. The +# split removes that import penalty. # # The two GAS USED assertions below MUST stay equal to each other; that equality # is the regression guard for the split (the absolute value is an ordinary pin). @@ -22,12 +23,12 @@ gnoland start gnokey maketx addpkg -pkgdir $WORK/depa -pkgpath gno.land/p/demo/depa -gas-fee 1000000ugnot -gas-wanted 5000000 -chainid=tendermint_test test1 -gnokey maketx addpkg -pkgdir $WORK/depb -pkgpath gno.land/p/demo/depb -gas-fee 1000000ugnot -gas-wanted 5000000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/depb -pkgpath gno.land/p/demo/depb -gas-fee 1000000ugnot -gas-wanted 8000000 -chainid=tendermint_test test1 gnokey maketx addpkg -pkgdir $WORK/usea -pkgpath gno.land/p/demo/usea -gas-fee 1000000ugnot -gas-wanted 5000000 -chainid=tendermint_test test1 -stdout 'GAS USED:\s+3172401' +stdout 'GAS USED:\s+3277401' gnokey maketx addpkg -pkgdir $WORK/useb -pkgpath gno.land/p/demo/useb -gas-fee 1000000ugnot -gas-wanted 5000000 -chainid=tendermint_test test1 -stdout 'GAS USED:\s+3172401' +stdout 'GAS USED:\s+3277401' -- depa/gnomod.toml -- module = "gno.land/p/demo/depa" diff --git a/gno.land/pkg/integration/testdata/addpkg_private.txtar b/gno.land/pkg/integration/testdata/addpkg_private.txtar index cd8bd080614..4048dd59f4d 100644 --- a/gno.land/pkg/integration/testdata/addpkg_private.txtar +++ b/gno.land/pkg/integration/testdata/addpkg_private.txtar @@ -7,11 +7,11 @@ loadpkg gno.land/p/nt/avl/v0 gnoland start # add the public realm first -gnokey maketx addpkg -pkgdir $WORK/publicrealm -pkgpath gno.land/r/foobar/publicrealm -gas-fee 820001ugnot -gas-wanted 8_200_000 -chainid=tendermint_test $test1_user_addr +gnokey maketx addpkg -pkgdir $WORK/publicrealm -pkgpath gno.land/r/foobar/publicrealm -gas-fee 820001ugnot -gas-wanted 11_000_000 -chainid=tendermint_test $test1_user_addr stdout OK! # add the private realm -gnokey maketx addpkg -pkgdir $WORK/privaterealm -pkgpath gno.land/r/foobar/privaterealm -gas-fee 1100001ugnot -gas-wanted 11_000_000 -chainid=tendermint_test $test1_user_addr +gnokey maketx addpkg -pkgdir $WORK/privaterealm -pkgpath gno.land/r/foobar/privaterealm -gas-fee 1100001ugnot -gas-wanted 24_000_000 -chainid=tendermint_test $test1_user_addr stdout OK! ! gnokey maketx call -pkgpath gno.land/r/foobar/privaterealm -func SaveTreeToPublicRealm -gas-fee 5000000ugnot -gas-wanted 50000000 -chainid=tendermint_test $test1_user_addr diff --git a/gno.land/pkg/integration/testdata/addpkg_public.txtar b/gno.land/pkg/integration/testdata/addpkg_public.txtar index c6134662a3a..231dd3601e8 100644 --- a/gno.land/pkg/integration/testdata/addpkg_public.txtar +++ b/gno.land/pkg/integration/testdata/addpkg_public.txtar @@ -7,11 +7,11 @@ loadpkg gno.land/p/nt/avl/v0 gnoland start # add the public realm first -gnokey maketx addpkg -pkgdir $WORK/publicrealm -pkgpath gno.land/r/foobar/publicrealm -gas-fee 750001ugnot -gas-wanted 7_500_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/publicrealm -pkgpath gno.land/r/foobar/publicrealm -gas-fee 750001ugnot -gas-wanted 11_000_000 -chainid=tendermint_test test1 stdout OK! # add the normal realm (not marked as private) -gnokey maketx addpkg -pkgdir $WORK/normalrealm -pkgpath gno.land/r/foobar/normalrealm -gas-fee 910001ugnot -gas-wanted 9_100_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/normalrealm -pkgpath gno.land/r/foobar/normalrealm -gas-fee 910001ugnot -gas-wanted 13_000_000 -chainid=tendermint_test test1 stdout OK! gnokey maketx call -pkgpath gno.land/r/foobar/normalrealm -func SaveTreeToPublicRealm -gas-fee 570001ugnot -gas-wanted 5_700_000 -chainid=tendermint_test test1 diff --git a/gno.land/pkg/integration/testdata/adduser.txtar b/gno.land/pkg/integration/testdata/adduser.txtar index 234fec123ca..d970f5cd579 100644 --- a/gno.land/pkg/integration/testdata/adduser.txtar +++ b/gno.land/pkg/integration/testdata/adduser.txtar @@ -7,12 +7,12 @@ gnoland start gnokey maketx addpkg -pkgdir $WORK/bar -pkgpath gno.land/r/foobar/bar -gas-fee 350001ugnot -gas-wanted 3_500_000 -chainid=tendermint_test test8 ## execute Render -gnokey maketx run -gas-fee 150001ugnot -gas-wanted 1_500_000 -chainid=tendermint_test test8 $WORK/script/script.gno +gnokey maketx run -gas-fee 150001ugnot -gas-wanted 2_000_000 -chainid=tendermint_test test8 $WORK/script/script.gno ## compare render stdout 'main: --- hello from foo ---' stdout 'OK!' -stdout 'GAS WANTED: 1500000' +stdout 'GAS WANTED: 2000000' stdout 'GAS USED: ' stdout 'TX HASH: ' diff --git a/gno.land/pkg/integration/testdata/assertorigincall.txtar b/gno.land/pkg/integration/testdata/assertorigincall.txtar index f6833470151..cddf4661ba8 100644 --- a/gno.land/pkg/integration/testdata/assertorigincall.txtar +++ b/gno.land/pkg/integration/testdata/assertorigincall.txtar @@ -77,7 +77,7 @@ stderr 'invalid non-origin call' stderr 'invalid non-origin call' ## 11. MsgRun -> run.main -> myrlm.B: PASS -gnokey maketx run -gas-fee 150001ugnot -gas-wanted 1_500_000 -chainid tendermint_test test1 $WORK/run/myrlm-b.gno +gnokey maketx run -gas-fee 150001ugnot -gas-wanted 2_000_000 -chainid tendermint_test test1 $WORK/run/myrlm-b.gno stdout 'OK!' ## 12. MsgRun -> run.main -> myrlm.C: PANIC diff --git a/gno.land/pkg/integration/testdata/banker_security.txtar b/gno.land/pkg/integration/testdata/banker_security.txtar index 2713546cdc5..88f61fd0a01 100644 --- a/gno.land/pkg/integration/testdata/banker_security.txtar +++ b/gno.land/pkg/integration/testdata/banker_security.txtar @@ -21,7 +21,7 @@ gnokey query bank/balances/${attacker_user_addr} stdout '1000000000ugnot' ## Deploy the malicious realm that attempts to steal coins -gnokey maketx addpkg -pkgdir $WORK/malicious -pkgpath gno.land/r/test/malicious -gas-fee 380001ugnot -gas-wanted 3_800_000 -chainid=tendermint_test attacker +gnokey maketx addpkg -pkgdir $WORK/malicious -pkgpath gno.land/r/test/malicious -gas-fee 380001ugnot -gas-wanted 5_200_000 -chainid=tendermint_test attacker stdout OK! ## ============================================ diff --git a/gno.land/pkg/integration/testdata/crossrealm_assign_recover.txtar b/gno.land/pkg/integration/testdata/crossrealm_assign_recover.txtar index cae47fb21ca..0bc7399ae45 100644 --- a/gno.land/pkg/integration/testdata/crossrealm_assign_recover.txtar +++ b/gno.land/pkg/integration/testdata/crossrealm_assign_recover.txtar @@ -28,14 +28,14 @@ adduser attacker gnoland start ## deploy vault realm -gnokey maketx addpkg -pkgdir $WORK/vault -pkgpath gno.land/r/test/vault -gas-fee 390001ugnot -gas-wanted 3_900_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/vault -pkgpath gno.land/r/test/vault -gas-fee 390001ugnot -gas-wanted 5_200_000 -chainid=tendermint_test test1 ## verify initial owner is the DAO address gnokey query "vm/qrender" --data "gno.land/r/test/vault:" stdout 'owner: g1dao0000000000000000000000000000000000' ## deploy attack realm -gnokey maketx addpkg -pkgdir $WORK/attack -pkgpath gno.land/r/test/attack -gas-fee 420001ugnot -gas-wanted 4_200_000 -chainid=tendermint_test attacker +gnokey maketx addpkg -pkgdir $WORK/attack -pkgpath gno.land/r/test/attack -gas-fee 420001ugnot -gas-wanted 5_600_000 -chainid=tendermint_test attacker ## FOOTGUN 1: assign+recover via exported non-crossing setter. ## Under interrealm v2, borrow rule #1 makes SetOwner's owner=o write a same- diff --git a/gno.land/pkg/integration/testdata/escape_oid_persistence.txtar b/gno.land/pkg/integration/testdata/escape_oid_persistence.txtar index 86a8e72bafa..a9016598d4d 100644 --- a/gno.land/pkg/integration/testdata/escape_oid_persistence.txtar +++ b/gno.land/pkg/integration/testdata/escape_oid_persistence.txtar @@ -22,7 +22,7 @@ adduser alice gnoland start ## deploy registry -gnokey maketx addpkg -pkgdir $WORK/registry -pkgpath gno.land/r/test/escbug/registry -gas-fee 2000000ugnot -gas-wanted 6_000_000 -chainid=tendermint_test alice +gnokey maketx addpkg -pkgdir $WORK/registry -pkgpath gno.land/r/test/escbug/registry -gas-fee 2000000ugnot -gas-wanted 8_000_000 -chainid=tendermint_test alice ## deploy holder — its init(cur) cross-constructs and cross-registers X gnokey maketx addpkg -pkgdir $WORK/holder -pkgpath gno.land/r/test/escbug/holder -gas-fee 2000000ugnot -gas-wanted 8_000_000 -chainid=tendermint_test alice diff --git a/gno.land/pkg/integration/testdata/gnokey_gasfee.txtar b/gno.land/pkg/integration/testdata/gnokey_gasfee.txtar index 5c04d1347e0..bd4dd23adcd 100644 --- a/gno.land/pkg/integration/testdata/gnokey_gasfee.txtar +++ b/gno.land/pkg/integration/testdata/gnokey_gasfee.txtar @@ -13,8 +13,8 @@ stdout '"coins": "10000000000000ugnot"' # gas-wanted/gas-fee on the simulate call are generous; simulate reports # the actual gas the real tx would consume. gnokey maketx addpkg -pkgdir $WORK/hello -pkgpath gno.land/r/hello -gas-wanted 3_500_000 -gas-fee 350001ugnot -chainid tendermint_test -simulate only test1 -stdout 'GAS USED:\s+2815609' -stdout 'INFO: estimated gas usage: 2815609 \(suggested, with 5% margin: 2956390\), gas fee: 2956ugnot, current gas price: 1ugnot/1000gas' +stdout 'GAS USED:\s+2909359' +stdout 'INFO: estimated gas usage: 2909359 \(suggested, with 5% margin: 3054827\), gas fee: 3055ugnot, current gas price: 1ugnot/1000gas' ## No fee was charged, and the sequence number did not change. gnokey query auth/accounts/$test1_user_addr @@ -25,14 +25,14 @@ stdout '"coins": "10000000000000ugnot"' # This is the documented simulate->broadcast workflow; the values on this # line MUST match the simulate output above (modulo a small gas-wanted # headroom). -gnokey maketx addpkg -pkgdir $WORK/hello -pkgpath gno.land/r/hello -gas-wanted 2_816_000 -gas-fee 2956ugnot -chainid tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/hello -pkgpath gno.land/r/hello -gas-wanted 2_910_000 -gas-fee 3055ugnot -chainid tendermint_test test1 stdout 'OK' stdout 'EVENTS: \[.*"fee_delta":\{"denom":"ugnot","amount":206900\}.*\]' ## fee + storage deposit were charged; sequence number increased. gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "1"' -stdout '"coins": "9999999790144ugnot"' +stdout '"coins": "9999999790045ugnot"' # Tx Call -simulate only, estimate gas used and gas fee. gnokey maketx call -pkgpath gno.land/r/hello -func Hello -gas-wanted 1_800_000 -gas-fee 180001ugnot -chainid tendermint_test -simulate only test1 @@ -42,7 +42,7 @@ stdout 'INFO: estimated gas usage: 1271011 \(suggested, with 5% margin: 13 ## No additional fee was charged, and the sequence number did not change. gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "1"' -stdout '"coins": "9999999790144ugnot"' +stdout '"coins": "9999999790045ugnot"' # Using the simulated gas and estimated gas fee should ensure the transaction executes successfully. gnokey maketx call -pkgpath gno.land/r/hello -func Hello -gas-wanted 1_335_000 -gas-fee 1335ugnot -chainid tendermint_test test1 @@ -51,7 +51,7 @@ stdout 'OK' ## fee is charged and sequence number increased gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "2"' -stdout '"coins": "9999999788809ugnot"' +stdout '"coins": "9999999788710ugnot"' -- hello/gnomod.toml -- module = "gno.land/r/hello" diff --git a/gno.land/pkg/integration/testdata/govdao_proposal_add_member.txtar b/gno.land/pkg/integration/testdata/govdao_proposal_add_member.txtar index 40c66f13788..fe84edd88a3 100644 --- a/gno.land/pkg/integration/testdata/govdao_proposal_add_member.txtar +++ b/gno.land/pkg/integration/testdata/govdao_proposal_add_member.txtar @@ -18,7 +18,7 @@ stdout 'data: # GovDAO' # add the proposal (temporarily comment out to debug) # First run a debug script to understand the addresses -gnokey maketx run -gas-fee 110001ugnot -gas-wanted 1_100_000 -chainid=tendermint_test member $WORK/debug/check_addresses.gno +gnokey maketx run -gas-fee 110001ugnot -gas-wanted 1_500_000 -chainid=tendermint_test member $WORK/debug/check_addresses.gno stdout '=== Debug info ===' stdout 'Origin caller: g1c0j899h88nwyvnzvh5jagpq6fkkyuj76nld6t0' stdout 'Current realm: CodeRealm{ g1c0j899h88nwyvnzvh5jagpq6fkkyuj76nld6t0, gno.land/e/g1c0j899h88nwyvnzvh5jagpq6fkkyuj76nld6t0/run }' diff --git a/gno.land/pkg/integration/testdata/interrealm_final.txtar b/gno.land/pkg/integration/testdata/interrealm_final.txtar index c3e6a03b5fe..02574aeb100 100644 --- a/gno.land/pkg/integration/testdata/interrealm_final.txtar +++ b/gno.land/pkg/integration/testdata/interrealm_final.txtar @@ -16,10 +16,10 @@ loadpkg gno.land/p/nt/ufmt/v0 gnoland start ## load packages -gnokey maketx addpkg -pkgdir $WORK/bob -pkgpath gno.land/r/test/bob -gas-fee 570001ugnot -gas-wanted 5_700_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/bob -pkgpath gno.land/r/test/bob -gas-fee 570001ugnot -gas-wanted 7_700_000 -chainid=tendermint_test test1 gnokey maketx addpkg -pkgdir $WORK/alice -pkgpath gno.land/r/test/alice -gas-fee 530001ugnot -gas-wanted 5_300_000 -chainid=tendermint_test test1 -gnokey maketx addpkg -pkgdir $WORK/peter -pkgpath gno.land/p/test/peter -gas-fee 360001ugnot -gas-wanted 3_600_000 -chainid=tendermint_test test1 -gnokey maketx addpkg -pkgdir $WORK/callerrealm -pkgpath gno.land/r/test/callerrealm -gas-fee 730001ugnot -gas-wanted 7_300_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/peter -pkgpath gno.land/p/test/peter -gas-fee 360001ugnot -gas-wanted 5_000_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/callerrealm -pkgpath gno.land/r/test/callerrealm -gas-fee 730001ugnot -gas-wanted 18_000_000 -chainid=tendermint_test test1 ## test CASE_rA1 ## interrealm v2: bob.Do is /r/bob-declared → borrow rule #1 borrows m.Realm = /r/bob. diff --git a/gno.land/pkg/integration/testdata/interrealm_mix_call.txtar b/gno.land/pkg/integration/testdata/interrealm_mix_call.txtar index a31eeca8daa..dee6681a770 100644 --- a/gno.land/pkg/integration/testdata/interrealm_mix_call.txtar +++ b/gno.land/pkg/integration/testdata/interrealm_mix_call.txtar @@ -6,9 +6,9 @@ loadpkg gno.land/p/nt/ufmt/v0 gnoland start ## load packages -gnokey maketx addpkg -pkgdir $WORK/utils -pkgpath gno.land/p/test/utils -gas-fee 360001ugnot -gas-wanted 3_600_000 -chainid=tendermint_test test1 -gnokey maketx addpkg -pkgdir $WORK/borrowrealm -pkgpath gno.land/r/test/borrowrealm -gas-fee 620001ugnot -gas-wanted 6_200_000 -chainid=tendermint_test test1 -gnokey maketx addpkg -pkgdir $WORK/callerrealm -pkgpath gno.land/r/test/callerrealm -gas-fee 700001ugnot -gas-wanted 7_000_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/utils -pkgpath gno.land/p/test/utils -gas-fee 360001ugnot -gas-wanted 5_000_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/borrowrealm -pkgpath gno.land/r/test/borrowrealm -gas-fee 620001ugnot -gas-wanted 8_500_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/callerrealm -pkgpath gno.land/r/test/callerrealm -gas-fee 700001ugnot -gas-wanted 9_500_000 -chainid=tendermint_test test1 ## validate initial state gnokey query "vm/qrender" --data "gno.land/r/test/borrowrealm:" diff --git a/gno.land/pkg/integration/testdata/interrealm_mix_run.txtar b/gno.land/pkg/integration/testdata/interrealm_mix_run.txtar index 06f95004e08..95485f5585e 100644 --- a/gno.land/pkg/integration/testdata/interrealm_mix_run.txtar +++ b/gno.land/pkg/integration/testdata/interrealm_mix_run.txtar @@ -7,8 +7,8 @@ loadpkg gno.land/p/nt/ufmt/v0 gnoland start ## load packages -gnokey maketx addpkg -pkgdir $WORK/utils -pkgpath gno.land/p/test/utils -gas-fee 360001ugnot -gas-wanted 3_600_000 -chainid=tendermint_test test1 -gnokey maketx addpkg -pkgdir $WORK/borrowrealm -pkgpath gno.land/r/test/borrowrealm -gas-fee 620001ugnot -gas-wanted 6_200_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/utils -pkgpath gno.land/p/test/utils -gas-fee 360001ugnot -gas-wanted 4_800_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/borrowrealm -pkgpath gno.land/r/test/borrowrealm -gas-fee 620001ugnot -gas-wanted 8_300_000 -chainid=tendermint_test test1 ## validate initial state gnokey query "vm/qrender" --data "gno.land/r/test/borrowrealm:" diff --git a/gno.land/pkg/integration/testdata/interrealm_v2.txtar b/gno.land/pkg/integration/testdata/interrealm_v2.txtar index 2c5244960c4..4c489821d27 100644 --- a/gno.land/pkg/integration/testdata/interrealm_v2.txtar +++ b/gno.land/pkg/integration/testdata/interrealm_v2.txtar @@ -57,7 +57,7 @@ gnoland start ## Setup ## ============================================================ -gnokey maketx addpkg -pkgdir $WORK/lib -pkgpath gno.land/p/test/v2lib -gas-fee 360001ugnot -gas-wanted 3_600_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/lib -pkgpath gno.land/p/test/v2lib -gas-fee 360001ugnot -gas-wanted 4_800_000 -chainid=tendermint_test test1 stdout OK! gnokey maketx addpkg -pkgdir $WORK/owned -pkgpath gno.land/r/test/owned -gas-fee 1000001ugnot -gas-wanted 10_000_000 -chainid=tendermint_test test1 diff --git a/gno.land/pkg/integration/testdata/loadpkg_work.txtar b/gno.land/pkg/integration/testdata/loadpkg_work.txtar index b340365214b..ade86296b76 100644 --- a/gno.land/pkg/integration/testdata/loadpkg_work.txtar +++ b/gno.land/pkg/integration/testdata/loadpkg_work.txtar @@ -5,12 +5,12 @@ loadpkg gno.land/r/foobar/bar $WORK/bar gnoland start ## execute Render -gnokey maketx run -gas-fee 150001ugnot -gas-wanted 1_500_000 -chainid=tendermint_test test1 $WORK/script/script.gno +gnokey maketx run -gas-fee 150001ugnot -gas-wanted 2_000_000 -chainid=tendermint_test test1 $WORK/script/script.gno ## compare render stdout 'main: --- hello from foo ---' stdout 'OK!' -stdout 'GAS WANTED: 1500000' +stdout 'GAS WANTED: 2000000' stdout 'GAS USED: ' stdout 'TX HASH: ' diff --git a/gno.land/pkg/integration/testdata/maketx_run.txtar b/gno.land/pkg/integration/testdata/maketx_run.txtar index 9c4ffaa5bb1..96f2c62ec02 100644 --- a/gno.land/pkg/integration/testdata/maketx_run.txtar +++ b/gno.land/pkg/integration/testdata/maketx_run.txtar @@ -4,12 +4,12 @@ loadpkg gno.land/r/foobar/bar $WORK/bar gnoland start ## execute Render -gnokey maketx run -gas-fee 150001ugnot -gas-wanted 1_500_000 -chainid=tendermint_test test1 $WORK/script/script.gno +gnokey maketx run -gas-fee 150001ugnot -gas-wanted 2_000_000 -chainid=tendermint_test test1 $WORK/script/script.gno ## compare render stdout 'main: --- hello from foo ---' stdout 'OK!' -stdout 'GAS WANTED: 1500000' +stdout 'GAS WANTED: 2000000' stdout 'GAS USED: ' stdout 'TX HASH: ' diff --git a/gno.land/pkg/integration/testdata/params.txtar b/gno.land/pkg/integration/testdata/params.txtar index 531f7db88b3..0fe89b99df1 100644 --- a/gno.land/pkg/integration/testdata/params.txtar +++ b/gno.land/pkg/integration/testdata/params.txtar @@ -13,7 +13,7 @@ gnokey query params/vm:gno.land/r/myrealm:baz stdout 'data: $' # add params to gno.land/r/myrealm -gnokey maketx addpkg -pkgdir $WORK/params -pkgpath gno.land/r/myrealm -gas-fee 380001ugnot -gas-wanted 3_800_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/params -pkgpath gno.land/r/myrealm -gas-fee 380001ugnot -gas-wanted 5_200_000 -chainid=tendermint_test test1 # query after adding the package, but before setting values gnokey query params/vm:gno.land/r/myrealm:foo diff --git a/gno.land/pkg/integration/testdata/params_sysparams2.txtar b/gno.land/pkg/integration/testdata/params_sysparams2.txtar index c93b670145a..745902b87fc 100644 --- a/gno.land/pkg/integration/testdata/params_sysparams2.txtar +++ b/gno.land/pkg/integration/testdata/params_sysparams2.txtar @@ -4,7 +4,7 @@ gnoland start # ---- 1 Test sys/params.SetSysParamXXX when called from gno.land/r/sys/params -gnokey maketx addpkg -pkgdir $WORK/params -pkgpath gno.land/r/sys/params -gas-fee 390001ugnot -gas-wanted 3_900_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/params -pkgpath gno.land/r/sys/params -gas-fee 390001ugnot -gas-wanted 6_700_000 -chainid=tendermint_test test1 ## lock transfer gnokey maketx call -pkgpath gno.land/r/sys/params -func SetLockTransfer -args "ugnot" -gas-fee 180001ugnot -gas-wanted 1_800_000 -chainid=tendermint_test test1 @@ -38,7 +38,7 @@ gnokey query params/bank:p:restricted_denoms stdout 'data: \[\]' # still the same, value was not written. # ---- 2 Test sys/params.SetSysParamXXX when called outside of gno.land/r/sys/params -gnokey maketx addpkg -pkgdir $WORK/params -pkgpath gno.land/r/myrealm -gas-fee 390001ugnot -gas-wanted 3_900_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/params -pkgpath gno.land/r/myrealm -gas-fee 390001ugnot -gas-wanted 5_200_000 -chainid=tendermint_test test1 ## can not call SetSysParamXXX out side of gno.land/r/params ! gnokey maketx call -pkgpath gno.land/r/myrealm -func SetSysParamString -args "foo" -gas-fee 5000000ugnot -gas-wanted 50000000 -chainid=tendermint_test test1 diff --git a/gno.land/pkg/integration/testdata/prevrealm.txtar b/gno.land/pkg/integration/testdata/prevrealm.txtar index eb71c025123..1a4b71e43d5 100644 --- a/gno.land/pkg/integration/testdata/prevrealm.txtar +++ b/gno.land/pkg/integration/testdata/prevrealm.txtar @@ -59,7 +59,7 @@ stdout ${RFOO_USER_ADDR} ## stdout ${test1_user_addr} ## 7. MsgRun -> myrlm.A: user address -gnokey maketx run -gas-fee 160001ugnot -gas-wanted 1_600_000 -chainid tendermint_test test1 $WORK/run/myrlm-a.gno +gnokey maketx run -gas-fee 160001ugnot -gas-wanted 2_100_000 -chainid tendermint_test test1 $WORK/run/myrlm-a.gno stdout ${test1_user_addr} ## 8. MsgRun -> myrealm.B -> myrlm.A: user address @@ -89,7 +89,7 @@ stdout ${RFOO_USER_ADDR} ## stdout ${test1_user_addr} ## 14. MsgRun -> std.PreviousRealm(): user address -gnokey maketx run -gas-fee 100001ugnot -gas-wanted 1_000_000 -chainid tendermint_test test1 $WORK/run/baz.gno +gnokey maketx run -gas-fee 100001ugnot -gas-wanted 1_400_000 -chainid tendermint_test test1 $WORK/run/baz.gno stdout ${test1_user_addr} -- r/myrlm/myrlm.gno -- diff --git a/gno.land/pkg/integration/testdata/realm_banker_issued_coin_denom.txtar b/gno.land/pkg/integration/testdata/realm_banker_issued_coin_denom.txtar index bf1a0123069..c65c9831e4b 100644 --- a/gno.land/pkg/integration/testdata/realm_banker_issued_coin_denom.txtar +++ b/gno.land/pkg/integration/testdata/realm_banker_issued_coin_denom.txtar @@ -10,7 +10,7 @@ gnoland start gnokey maketx addpkg -pkgdir $WORK/short -pkgpath gno.land/r/test/realm_banker -gas-fee 370001ugnot -gas-wanted 3_700_000 -chainid=tendermint_test test1 ## add realm_banker with long package_name -gnokey maketx addpkg -pkgdir $WORK/long -pkgpath gno.land/r/test/package89_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_1234567890 -gas-fee 370001ugnot -gas-wanted 3_700_000 -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/long -pkgpath gno.land/r/test/package89_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_1234567890 -gas-fee 450001ugnot -gas-wanted 4_500_000 -chainid=tendermint_test test1 ## add invalid realm_denom gnokey maketx addpkg -pkgdir $WORK/invalid_realm_denom -pkgpath gno.land/r/test/invalid_realm_denom -gas-fee 360001ugnot -gas-wanted 3_600_000 -chainid=tendermint_test test1 diff --git a/gno.land/pkg/integration/testdata/restart_gas.txtar b/gno.land/pkg/integration/testdata/restart_gas.txtar index 5942aa2432e..b04c0d03027 100644 --- a/gno.land/pkg/integration/testdata/restart_gas.txtar +++ b/gno.land/pkg/integration/testdata/restart_gas.txtar @@ -10,15 +10,15 @@ gnoland start gnokey maketx addpkg -pkgdir $WORK/bar -pkgpath gno.land/r/$test1_user_addr/bar -gas-fee 360001ugnot -gas-wanted 3_600_000 -chainid=tendermint_test test1 -stdout 'GAS USED:\s+2839205' +stdout 'GAS USED:\s+2996705' gnokey maketx addpkg -pkgdir $WORK/bar -pkgpath gno.land/r/$test1_user_addr/foo -gas-fee 360001ugnot -gas-wanted 3_600_000 -chainid=tendermint_test test1 -stdout 'GAS USED:\s+2841534' +stdout 'GAS USED:\s+2999034' gnoland restart gnokey maketx addpkg -pkgdir $WORK/baz -pkgpath gno.land/r/$test1_user_addr/baz -gas-fee 360001ugnot -gas-wanted 3_600_000 -chainid=tendermint_test test1 -stdout 'GAS USED:\s+2841548' +stdout 'GAS USED:\s+2999048' -- bar/gnomod.toml -- module = "bar" diff --git a/gno.land/pkg/integration/testdata/storage_deposit_bank_send.txtar b/gno.land/pkg/integration/testdata/storage_deposit_bank_send.txtar index e98f11ffa4f..3ff63b10fe5 100644 --- a/gno.land/pkg/integration/testdata/storage_deposit_bank_send.txtar +++ b/gno.land/pkg/integration/testdata/storage_deposit_bank_send.txtar @@ -3,7 +3,7 @@ ## start a new node gnoland start -gnokey maketx addpkg -pkgdir $WORK/contracts -pkgpath gno.land/r/foo -gas-fee 420001ugnot -gas-wanted 4_200_000 -max-deposit 1500000ugnot -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/contracts -pkgpath gno.land/r/foo -gas-fee 420001ugnot -gas-wanted 5_700_000 -max-deposit 1500000ugnot -chainid=tendermint_test test1 stdout OK! diff --git a/gno.land/pkg/integration/testdata/storage_deposit_collector.txtar b/gno.land/pkg/integration/testdata/storage_deposit_collector.txtar index dde8cb10bfb..f1c38aad57d 100644 --- a/gno.land/pkg/integration/testdata/storage_deposit_collector.txtar +++ b/gno.land/pkg/integration/testdata/storage_deposit_collector.txtar @@ -39,7 +39,7 @@ stdout 'OK!' gnokey query bank/balances/$storage_collector_user_addr stdout '1000000000ugnot' -gnokey maketx addpkg -pkgdir $WORK/bytesbank -pkgpath gno.land/r/bytesbank -gas-fee 370001ugnot -gas-wanted 3_700_000 -max-deposit 900000ugnot -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/bytesbank -pkgpath gno.land/r/bytesbank -gas-fee 370001ugnot -gas-wanted 4_800_000 -max-deposit 900000ugnot -chainid=tendermint_test test1 stdout 'EVENTS: \[{\"bytes_delta\":\d+,\"fee_delta\":{\"denom\":\"ugnot\",\"amount\":\d+},\"pkg_path\":\"gno.land/r/bytesbank\"}]' stdout 'STORAGE DELTA: \d+ bytes' stdout 'STORAGE FEE: \d+ugnot' diff --git a/gno.land/pkg/integration/testdata/user_journey.txtar b/gno.land/pkg/integration/testdata/user_journey.txtar index c065d0d5930..df3e17afb4e 100644 --- a/gno.land/pkg/integration/testdata/user_journey.txtar +++ b/gno.land/pkg/integration/testdata/user_journey.txtar @@ -184,7 +184,7 @@ gnokey maketx call -pkgpath gno.land/r/sys/names -func Enable -gas-fee 260001ugn stdout 'OK!' # user2 publishes a custom home package to its address namespace -gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$user2_user_addr/home -gas-fee 540001ugnot -gas-wanted 5_400_000 -chainid=tendermint_test user2 +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$user2_user_addr/home -gas-fee 540001ugnot -gas-wanted 7_100_000 -chainid=tendermint_test user2 stdout 'OK!' # Render user2's home package diff --git a/gno.land/pkg/sdk/vm/apphash_crossrealm38_test.go b/gno.land/pkg/sdk/vm/apphash_crossrealm38_test.go index 6497ede0b7b..539143e4251 100644 --- a/gno.land/pkg/sdk/vm/apphash_crossrealm38_test.go +++ b/gno.land/pkg/sdk/vm/apphash_crossrealm38_test.go @@ -73,7 +73,10 @@ import ( // store production files under pkg: (typed MP*Prod) and test/filetest files // under a pkg:#allbutprod sibling, changing stored package bytes and the // iavlStore Merkle root. Behavior is unchanged; only the storage encoding shifted. -const expectedCrossrealm38Hash = "adef42a3fcc41839fb59faf81e0190fd1f51fe7afba82f717d4def275c84c977" +// Hash bumped 2026-06-24: added the PreprocessGasPerByte vm param (default 1250); its +// non-zero default is serialized into the genesis vm params state, shifting the +// iavlStore Merkle root. Behavior is unchanged; only the genesis params encoding shifted. +const expectedCrossrealm38Hash = "d10607d7236645c1b803ebdf1bde1d79db682d2026e42bb306c5f5830b65e50f" func TestAppHashCrossrealm38(t *testing.T) { env := setupTestEnv() diff --git a/gno.land/pkg/sdk/vm/genesis.go b/gno.land/pkg/sdk/vm/genesis.go index c508a9ff6f4..444ff6aeab0 100644 --- a/gno.land/pkg/sdk/vm/genesis.go +++ b/gno.land/pkg/sdk/vm/genesis.go @@ -33,7 +33,11 @@ func ValidateGenesis(gs GenesisState) error { if amino.DeepEqual(gs, GenesisState{}) { return fmt.Errorf("vm genesis state cannot be empty") } - err := gs.Params.Validate() + // Tolerate a genesis that predates PreprocessGasPerByte (an old-binary + // export omits the field, decoding it as zero); applyLegacyDefaults fills + // it so validation matches GetParams' runtime behavior. InitGenesis stores + // the defaulted value. + err := gs.Params.applyLegacyDefaults().Validate() if err != nil { return err } @@ -45,6 +49,7 @@ func ValidateGenesis(gs GenesisState) error { // InitGenesis - Init store state from genesis data func (vm *VMKeeper) InitGenesis(ctx sdk.Context, gs GenesisState) { + gs.Params = gs.Params.applyLegacyDefaults() if err := ValidateGenesis(gs); err != nil { panic(err) } diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 41b72d17157..89f7d9ba0d0 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -579,6 +579,40 @@ func (vm *VMKeeper) checkCLASignature(ctx sdk.Context, creator crypto.Address) e return nil } +// chargePreprocessGas charges PreprocessGasPerByte gas per byte of every .gno +// source file (prod, _test, and _filetest) in mpkg: the native type-check +// pass processes all of them and the preprocess pass the prod subset, both +// otherwise unmetered. AddPackage and Run call it immediately before their +// type-check so an oversized package is rejected by the gas meter instead of +// consuming unmetered validator CPU. Params.Validate rejects a non-positive +// PreprocessGasPerByte, and GetParams defaults the field when reading a +// legacy params blob that predates it, so the charge is always active. +func chargePreprocessGas(ctx sdk.Context, params Params, mpkg *std.MemPackage, descriptor string) { + var srcBytes int64 + for _, f := range mpkg.Files { + if strings.HasSuffix(f.Name, ".gno") { + srcBytes += int64(len(f.Body)) + } + } + ctx.GasMeter().ConsumeGas(overflow.Mulp(params.PreprocessGasPerByte, srcBytes), descriptor) +} + +// hasProdGnoFile reports whether mpkg contains at least one production +// (non-test) .gno file. It applies MPFProd's own per-file predicate so it +// cannot drift from what the storage split (store.go splitProdAllButProd) +// treats as prod, but without allocating a filtered copy of the package. +// FilterGno panics on non-.gno files and returns true to EXCLUDE a file, so a +// prod .gno file is a .gno file it does not exclude. +func hasProdGnoFile(mpkg *std.MemPackage) bool { + pname := gno.Name(mpkg.Name) + for _, f := range mpkg.Files { + if strings.HasSuffix(f.Name, ".gno") && !gno.MPFProd.FilterGno(f, pname) { + return true + } + } + return false +} + // AddPackage adds a package with given fileset. func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { // Defense-in-depth spend check. MsgAddPackage is currently blocked @@ -620,7 +654,7 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { // splitProdAllButProd), so a restarted node would rebuild no PackageNode // while a non-restarted node still holds the deploy-time node in RAM — // making call gas depend on restart history. - if gno.MPFProd.FilterMemPackage(memPkg).IsEmpty() { + if !hasProdGnoFile(memPkg) { return ErrInvalidPackage("package has no production .gno files") } @@ -660,6 +694,10 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { if ctx.BlockHeight() == 0 { opts.Mode = gno.TCGenesisStrict // genesis time, waive blocking rules for importing draft packages. } + // use the parameters before executing the message, as they may change during execution. + // The message should not fail due to parameter changes in the same transaction. + params := vm.GetParams(ctx) + chargePreprocessGas(ctx, params, memPkg, "AddPackagePreprocess") // Validate Gno syntax and type check. _, err = gno.TypeCheckMemPackage(memPkg, opts) if err != nil { @@ -767,11 +805,8 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { preAlloc.SetGasMeter(ctx.GasMeter()) gnostore.SetPreprocessAllocator(preAlloc) defer gnostore.SetPreprocessAllocator(nil) - params := vm.GetParams(ctx) m2.RunMemPackage(memPkg, true) - // use the parameters before executing the message, as they may change during execution. - // The message should not fail due to parameter changes in the same transaction. err = vm.processStorageDeposit(ctx, creator, maxDeposit, gnostore, params) if err != nil { return err @@ -1043,6 +1078,7 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { return "", ErrInvalidPkgPath(err.Error()) } + chargePreprocessGas(ctx, params, memPkg, "RunPreprocess") // Validate Gno syntax and type check. _, err = gno.TypeCheckMemPackage(memPkg, gno.TypeCheckOptions{ Getter: gnostore, diff --git a/gno.land/pkg/sdk/vm/keeper_test.go b/gno.land/pkg/sdk/vm/keeper_test.go index 1c774264829..082e8aeb649 100644 --- a/gno.land/pkg/sdk/vm/keeper_test.go +++ b/gno.land/pkg/sdk/vm/keeper_test.go @@ -189,7 +189,7 @@ func TestVMKeeperAddPackage_ImportTestDepGasEqual(t *testing.T) { ctx := env.vmk.MakeGnoTransactionStore(env.ctx.WithGasMeter(gm)) require.NoError(t, env.vmk.AddPackage(ctx, NewMsgAddPackage(addr, pkgPath, files))) env.vmk.CommitGnoTransactionStore(ctx) - return int64(gm.GasConsumed()) + return gm.GasConsumed() } // depa and depb have byte-identical production code (a<->b only); depb diff --git a/gno.land/pkg/sdk/vm/params.go b/gno.land/pkg/sdk/vm/params.go index 09d66c29a7f..ccf386b15d9 100644 --- a/gno.land/pkg/sdk/vm/params.go +++ b/gno.land/pkg/sdk/vm/params.go @@ -25,9 +25,17 @@ const ( // Depth floors calibrated for B+32 at 100M items with 10K cache, batched 1000 muts. minGetReadDepth100Default = int64(300) // 3.0 GET read ops minSetReadDepth100Default = int64(200) // 2.0 SET read ops - minWriteDepth100Default = int64(440) // 4.4 write ops (batched) + minWriteDepth100Default = 440 // 4.4 write ops (batched) // Iterator step flat cost; mirrors store.DefaultGasConfig().IterNextCostFlat. - iterNextCostFlatDefault = int64(1_000) + iterNextCostFlatDefault = 1_000 + // PreprocessGasPerByte: gas charged per .gno source byte at MsgAddPackage + // and MsgRun for the native type-check + preprocess passes, which are + // otherwise unmetered. Measured ~1250 gas/byte on realistic example + // realms/packages (type-check ~920 + preprocess ~330, own compile only — + // dependency re-type-checking excluded; 1 gas == 1ns on the reference + // machine, and the host-machine calibration factor is the dominant + // uncertainty). + preprocessGasPerByteDefault = 1_250 ) var ASCIIDomain = regexp.MustCompile(`^(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,}$`) @@ -51,10 +59,16 @@ type Params struct { // "no floor / use tree estimate") because zero iter-step cost // would effectively disable iteration gas charging. IterNextCostFlat int64 `json:"iter_next_cost_flat" yaml:"iter_next_cost_flat"` + // PreprocessGasPerByte must be > 0; Validate rejects zero (like + // IterNextCostFlat) because a zero per-byte cost would silently disable + // the type-check/preprocess gas charge. Charged per .gno source byte at + // MsgAddPackage and MsgRun; it is NOT part of store.GasConfig (charged + // directly in the keeper), so it has no ApplyToGasConfig entry. + PreprocessGasPerByte int64 `json:"preprocess_gas_per_byte" yaml:"preprocess_gas_per_byte"` } // NewParams creates a new Params object -func NewParams(namesPkgPath, claPkgPath, chainDomain, defaultDeposit, storagePrice string, storageFeeCollector crypto.Address, minGetReadDepth100, minSetReadDepth100, minWriteDepth100, iterNextCostFlat int64) Params { +func NewParams(namesPkgPath, claPkgPath, chainDomain, defaultDeposit, storagePrice string, storageFeeCollector crypto.Address, minGetReadDepth100, minSetReadDepth100, minWriteDepth100, iterNextCostFlat, preprocessGasPerByte int64) Params { return Params{ SysNamesPkgPath: namesPkgPath, SysCLAPkgPath: claPkgPath, @@ -69,6 +83,7 @@ func NewParams(namesPkgPath, claPkgPath, chainDomain, defaultDeposit, storagePri FixedSetReadDepth100: minSetReadDepth100, FixedWriteDepth100: minWriteDepth100, IterNextCostFlat: iterNextCostFlat, + PreprocessGasPerByte: preprocessGasPerByte, } } @@ -77,7 +92,7 @@ func DefaultParams() Params { return NewParams(sysNamesPkgDefault, sysCLAPkgDefault, chainDomainDefault, depositDefault, storagePriceDefault, crypto.AddressFromPreimage([]byte(storageFeeCollectorNameDefault)), minGetReadDepth100Default, minSetReadDepth100Default, minWriteDepth100Default, - iterNextCostFlatDefault) + iterNextCostFlatDefault, preprocessGasPerByteDefault) } // String implements the stringer interface. @@ -97,6 +112,7 @@ func (p Params) String() string { sb.WriteString(fmt.Sprintf("FixedSetReadDepth100: %d\n", p.FixedSetReadDepth100)) sb.WriteString(fmt.Sprintf("FixedWriteDepth100: %d\n", p.FixedWriteDepth100)) sb.WriteString(fmt.Sprintf("IterNextCostFlat: %d\n", p.IterNextCostFlat)) + sb.WriteString(fmt.Sprintf("PreprocessGasPerByte: %d\n", p.PreprocessGasPerByte)) return sb.String() } @@ -152,13 +168,23 @@ func (p Params) Validate() error { // realistic per-step cost while far below the block gas limit // (~3B) so that a single adversarial proposal can't make one // iterator step drain an entire block's gas budget. - const maxIterNextCostFlat = int64(100_000) + const maxIterNextCostFlat = 100_000 if p.IterNextCostFlat <= 0 { return fmt.Errorf("IterNextCostFlat must be positive, got %d", p.IterNextCostFlat) } if p.IterNextCostFlat > maxIterNextCostFlat { return fmt.Errorf("IterNextCostFlat must be <= %d, got %d", maxIterNextCostFlat, p.IterNextCostFlat) } + // Cap PreprocessGasPerByte at 100_000 (80x the default, far above the + // measured cost) to give governance headroom while preventing an absurd + // proposal from making deploys impossibly expensive. + const maxPreprocessGasPerByte = 100_000 + if p.PreprocessGasPerByte <= 0 { + return fmt.Errorf("PreprocessGasPerByte must be positive, got %d", p.PreprocessGasPerByte) + } + if p.PreprocessGasPerByte > maxPreprocessGasPerByte { + return fmt.Errorf("PreprocessGasPerByte must be <= %d, got %d", maxPreprocessGasPerByte, p.PreprocessGasPerByte) + } return nil } @@ -195,10 +221,25 @@ func (vm *VMKeeper) SetParams(ctx sdk.Context, params Params) error { return nil } +// applyLegacyDefaults fills fields absent from a params blob written before +// they existed (GetStruct leaves an absent key zero; a genesis predating the +// field decodes it as zero too). A zero PreprocessGasPerByte is otherwise +// unrepresentable — Validate rejects it on every write path — so a zero here +// can only mean pre-field legacy state. Defaulting it keeps the type-check/ +// preprocess charge active on legacy chains, keeps WillSetParam's whole-struct +// re-validation from rejecting an unrelated param update on such state, and +// lets a relaunch genesis that predates the field still pass ValidateGenesis. +func (p Params) applyLegacyDefaults() Params { + if p.PreprocessGasPerByte == 0 { + p.PreprocessGasPerByte = preprocessGasPerByteDefault + } + return p +} + func (vm *VMKeeper) GetParams(ctx sdk.Context) Params { params := Params{} vm.prmk.GetStruct(ctx, "vm:p", ¶ms) // prmk is root. - return params + return params.applyLegacyDefaults() } const ( @@ -261,6 +302,8 @@ func (vm *VMKeeper) WillSetParam(ctx sdk.Context, key string, value any) { params.FixedWriteDepth100 = sdkparams.MustParamInt64("fixed_write_depth_100", value) case "p:iter_next_cost_flat": params.IterNextCostFlat = sdkparams.MustParamInt64("iter_next_cost_flat", value) + case "p:preprocess_gas_per_byte": + params.PreprocessGasPerByte = sdkparams.MustParamInt64("preprocess_gas_per_byte", value) default: if strings.HasPrefix(key, "p:") { panic(fmt.Sprintf("unknown vm param key: %q", key)) diff --git a/gno.land/pkg/sdk/vm/params_test.go b/gno.land/pkg/sdk/vm/params_test.go index 5971cebd2c1..b70d499837f 100644 --- a/gno.land/pkg/sdk/vm/params_test.go +++ b/gno.land/pkg/sdk/vm/params_test.go @@ -31,7 +31,8 @@ func TestParamsString(t *testing.T) { fmt.Sprintf("FixedGetReadDepth100: %d\n", p.FixedGetReadDepth100) + fmt.Sprintf("FixedSetReadDepth100: %d\n", p.FixedSetReadDepth100) + fmt.Sprintf("FixedWriteDepth100: %d\n", p.FixedWriteDepth100) + - fmt.Sprintf("IterNextCostFlat: %d\n", p.IterNextCostFlat) + fmt.Sprintf("IterNextCostFlat: %d\n", p.IterNextCostFlat) + + fmt.Sprintf("PreprocessGasPerByte: %d\n", p.PreprocessGasPerByte) // Assert: check if the result matches the expected string. if result != expected { @@ -240,6 +241,50 @@ func TestWillSetParamExhaustive(t *testing.T) { } } +// A vm params blob written before PreprocessGasPerByte existed decodes with +// the field zero (simulated here by writing 0 directly, past Validate). +// GetParams must default it so that (a) the type-check/preprocess charge +// stays active on legacy state, and (b) WillSetParam's whole-struct +// re-validation does not reject updates of unrelated params on such state. +func TestGetParamsDefaultsPreprocessGasPerByte(t *testing.T) { + env := setupTestEnv() + ctx := env.vmk.MakeGnoTransactionStore(env.ctx) + + legacy := DefaultParams() + legacy.PreprocessGasPerByte = 0 + env.prmk.SetStruct(ctx, "vm:p", legacy) // direct write: no Validate, no hooks + + assert.Equal(t, preprocessGasPerByteDefault, env.vmk.GetParams(ctx).PreprocessGasPerByte) + + // The trap the defaulting closes: a params-keeper write of an unrelated + // param runs WillSetParam, which re-validates the whole struct read via + // GetParams and would panic on a zero PreprocessGasPerByte. + assert.NotPanics(t, func() { + env.prmk.SetString(ctx, "vm:p:chain_domain", "example.com") + }) +} + +// A relaunch genesis exported by a binary predating PreprocessGasPerByte omits +// the field, so it decodes as zero. ValidateGenesis and InitGenesis must +// tolerate that (defaulting it) rather than rejecting the genesis — matching +// GetParams' runtime behavior — while a genesis with an explicitly invalid +// value still fails. +func TestGenesisToleratesLegacyPreprocessGasPerByte(t *testing.T) { + legacy := DefaultParams() + legacy.PreprocessGasPerByte = 0 // field absent in a pre-field export + assert.NoError(t, ValidateGenesis(NewGenesisState(legacy))) + + env := setupTestEnv() + ctx := env.vmk.MakeGnoTransactionStore(env.ctx) + assert.NotPanics(t, func() { env.vmk.InitGenesis(ctx, NewGenesisState(legacy)) }) + assert.Equal(t, preprocessGasPerByteDefault, env.vmk.GetParams(ctx).PreprocessGasPerByte) + + // An explicitly out-of-range value is still rejected (not treated as legacy). + bad := DefaultParams() + bad.PreprocessGasPerByte = -1 + assert.Error(t, ValidateGenesis(NewGenesisState(bad))) +} + func TestParamsValidate(t *testing.T) { valid := DefaultParams() diff --git a/gno.land/pkg/sdk/vm/pb3_gen.go b/gno.land/pkg/sdk/vm/pb3_gen.go index 29ce0c7b0b9..f3747e58fd6 100644 --- a/gno.land/pkg/sdk/vm/pb3_gen.go +++ b/gno.land/pkg/sdk/vm/pb3_gen.go @@ -1169,6 +1169,18 @@ func (goo *GenesisState) UnmarshalBinary2(cdc *amino.Codec, bz []byte, anyDepth func (goo Params) MarshalBinary2(cdc *amino.Codec, buf []byte, offset int) (int, error) { var err error + if goo.PreprocessGasPerByte != 0 { + { + before := offset + offset = amino.PrependVarint(buf, offset, int64(goo.PreprocessGasPerByte)) + valueLen := before - offset + if valueLen > 1 || (valueLen == 1 && buf[offset] != 0x00) { + offset = amino.PrependFieldNumberAndTyp3(buf, offset, 14, amino.Typ3Varint) + } else { + offset = before + } + } + } if goo.IterNextCostFlat != 0 { { before := offset @@ -1381,6 +1393,9 @@ func (goo Params) SizeBinary2(cdc *amino.Codec) (int, error) { if goo.IterNextCostFlat != 0 { s += 1 + amino.VarintSize(int64(goo.IterNextCostFlat)) } + if goo.PreprocessGasPerByte != 0 { + s += 1 + amino.VarintSize(int64(goo.PreprocessGasPerByte)) + } return s, nil } @@ -1533,6 +1548,16 @@ func (goo *Params) UnmarshalBinary2(cdc *amino.Codec, bz []byte, anyDepth int) e } bz = bz[n:] goo.IterNextCostFlat = int64(v) + case 14: + if typ3 != amino.Typ3Varint { + return fmt.Errorf("field 14: expected typ3 %v, got %v", amino.Typ3Varint, typ3) + } + v, n, err := amino.DecodeVarint(bz) + if err != nil { + return err + } + bz = bz[n:] + goo.PreprocessGasPerByte = int64(v) default: return fmt.Errorf("unknown field number %d for Params", fnum) } diff --git a/gno.land/pkg/sdk/vm/vm.proto b/gno.land/pkg/sdk/vm/vm.proto index ff638171984..53585710b68 100644 --- a/gno.land/pkg/sdk/vm/vm.proto +++ b/gno.land/pkg/sdk/vm/vm.proto @@ -81,4 +81,5 @@ message Params { sint64 fixed_set_read_depth100 = 11 [json_name = "fixed_set_read_depth_100"]; sint64 fixed_write_depth100 = 12 [json_name = "fixed_write_depth_100"]; sint64 iter_next_cost_flat = 13; + sint64 preprocess_gas_per_byte = 14; } \ No newline at end of file