From 36c8f0e643c82fa157fe373d9a0442dfa7e67afb Mon Sep 17 00:00:00 2001 From: Guilhem Fanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 13 Jan 2025 00:10:04 +0100 Subject: [PATCH] feat: add account number / sequence as env in txtar (#3477) --- gno.land/pkg/integration/doc.go | 14 +- .../pkg/integration/testdata/addpkg.txtar | 4 +- .../testdata/addpkg_namespace.txtar | 12 +- .../integration/testdata/adduserfrom.txtar | 4 +- .../testdata/event_multi_msg.txtar | 9 +- .../pkg/integration/testdata/gnokey.txtar | 11 +- .../testdata/gnokey_simulate.txtar | 20 +- .../pkg/integration/testdata/patchpkg.txtar | 4 +- .../pkg/integration/testdata/prevrealm.txtar | 30 +-- .../realm_banker_issued_coin_denom.txtar | 16 +- .../pkg/integration/testscript_gnoland.go | 205 +++++++++--------- gno.land/pkg/integration/utils.go | 73 +++++++ ...stscript_gnoland_test.go => utils_test.go} | 0 13 files changed, 236 insertions(+), 166 deletions(-) create mode 100644 gno.land/pkg/integration/utils.go rename gno.land/pkg/integration/{testscript_gnoland_test.go => utils_test.go} (100%) diff --git a/gno.land/pkg/integration/doc.go b/gno.land/pkg/integration/doc.go index 3e09d627c9a..d93d4607a59 100644 --- a/gno.land/pkg/integration/doc.go +++ b/gno.land/pkg/integration/doc.go @@ -102,11 +102,17 @@ // The path where the gnoland node stores its configuration and data. It's // set only if the node has started. // -// - USER_SEED_test1: -// Contains the seed for the test1 account. +// - xxx_user_seed: +// Where `xxx` is the account name; Contains the seed for the test1 account. // -// - USER_ADDR_test1: -// Contains the address for the test1 account. +// - xxx_user_addr: +// Where `xxx` is the account name; Contains the address for the test1 account. +// +// - xxx_account_num: +// Where `xxx` is the account name; Contains the account number for the test1 account. +// +// - xxx_account_seq: +// Where `xxx` is the account name; Contains the address for the test1 account. // // - RPC_ADDR: // Points to the gnoland node's remote address. It's set only if the node has started. diff --git a/gno.land/pkg/integration/testdata/addpkg.txtar b/gno.land/pkg/integration/testdata/addpkg.txtar index 8594e6596ce..15e8ad222f2 100644 --- a/gno.land/pkg/integration/testdata/addpkg.txtar +++ b/gno.land/pkg/integration/testdata/addpkg.txtar @@ -4,7 +4,7 @@ gnoland start ## deploy realm -gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/hello -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$test1_user_addr/hello -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test test1 ## check output stdout OK! @@ -15,7 +15,7 @@ stdout 'EVENTS: \[\]' stdout 'TX HASH: ' ## call added realm -gnokey maketx call -pkgpath gno.land/r/$USER_ADDR_test1/hello -chainid=tendermint_test -func SayHello -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast test1 +gnokey maketx call -pkgpath gno.land/r/$test1_user_addr/hello -chainid=tendermint_test -func SayHello -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast test1 ## check output stdout '\("hello world!" string\)' diff --git a/gno.land/pkg/integration/testdata/addpkg_namespace.txtar b/gno.land/pkg/integration/testdata/addpkg_namespace.txtar index 89da8a51820..f529c176f36 100644 --- a/gno.land/pkg/integration/testdata/addpkg_namespace.txtar +++ b/gno.land/pkg/integration/testdata/addpkg_namespace.txtar @@ -4,7 +4,7 @@ loadpkg gno.land/r/sys/users adduser admin adduser gui -patchpkg "g1manfred47kzduec920z88wfr64ylksmdcedlf5" $USER_ADDR_admin # use our custom admin +patchpkg "g1manfred47kzduec920z88wfr64ylksmdcedlf5" $admin_user_addr # use our custom admin gnoland start @@ -20,7 +20,7 @@ stdout 'false' # Gui should be able to addpkg on test1 addr # gui addpkg -> gno.land/r//mysuperpkg -gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/mysuperpkg -gas-fee 1000000ugnot -gas-wanted 400000 -broadcast -chainid=tendermint_test gui +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$test1_user_addr/mysuperpkg -gas-fee 1000000ugnot -gas-wanted 400000 -broadcast -chainid=tendermint_test gui stdout 'OK!' # Gui should be able to addpkg on random name @@ -43,12 +43,12 @@ stdout 'true' # Try to add a pkg an with unregistered user # gui addpkg -> gno.land/r//one -! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/one -gas-fee 1000000ugnot -gas-wanted 1000000 -broadcast -chainid=tendermint_test gui +! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$test1_user_addr/one -gas-fee 1000000ugnot -gas-wanted 1000000 -broadcast -chainid=tendermint_test gui stderr 'unauthorized user' # Try to add a pkg with an unregistered user, on their own address as namespace # gui addpkg -> gno.land/r//one -gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_gui/one -gas-fee 1000000ugnot -gas-wanted 1000000 -broadcast -chainid=tendermint_test gui +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$gui_user_addr/one -gas-fee 1000000ugnot -gas-wanted 1000000 -broadcast -chainid=tendermint_test gui stdout 'OK!' ## Test unregistered namespace @@ -63,12 +63,12 @@ stderr 'unauthorized user' # Test admin invites gui # admin call -> demo/users.Invite -gnokey maketx call -pkgpath gno.land/r/demo/users -func Invite -gas-fee 1000000ugnot -gas-wanted 2500000 -broadcast -chainid=tendermint_test -args $USER_ADDR_gui admin +gnokey maketx call -pkgpath gno.land/r/demo/users -func Invite -gas-fee 1000000ugnot -gas-wanted 2500000 -broadcast -chainid=tendermint_test -args $gui_user_addr admin stdout 'OK!' # test gui register namespace # gui call -> demo/users.Register -gnokey maketx call -pkgpath gno.land/r/demo/users -func Register -gas-fee 1000000ugnot -gas-wanted 2500000 -broadcast -chainid=tendermint_test -args $USER_ADDR_admin -args 'guiland' -args 'im gui' gui +gnokey maketx call -pkgpath gno.land/r/demo/users -func Register -gas-fee 1000000ugnot -gas-wanted 2500000 -broadcast -chainid=tendermint_test -args $admin_user_addr -args 'guiland' -args 'im gui' gui stdout 'OK!' # Test gui publishing on guiland/one diff --git a/gno.land/pkg/integration/testdata/adduserfrom.txtar b/gno.land/pkg/integration/testdata/adduserfrom.txtar index 47ec70b00e6..8bbfaa738fd 100644 --- a/gno.land/pkg/integration/testdata/adduserfrom.txtar +++ b/gno.land/pkg/integration/testdata/adduserfrom.txtar @@ -14,13 +14,13 @@ stdout 'g1mtmrdmqfu0aryqfl4aw65n35haw2wdjkh5p4cp' gnoland start ## check users initial balance -gnokey query bank/balances/${USER_ADDR_user1} +gnokey query bank/balances/$user1_user_addr stdout '10000000ugnot' gnokey query bank/balances/g18e22n23g462drp4pyszyl6e6mwxkaylthgeeq4 stdout '10000000ugnot' -gnokey query auth/accounts/${USER_ADDR_user3} +gnokey query auth/accounts/$user3_user_addr stdout 'height: 0' stdout 'data: {' stdout ' "BaseAccount": {' diff --git a/gno.land/pkg/integration/testdata/event_multi_msg.txtar b/gno.land/pkg/integration/testdata/event_multi_msg.txtar index 4c8de856f03..3c5667b73b0 100644 --- a/gno.land/pkg/integration/testdata/event_multi_msg.txtar +++ b/gno.land/pkg/integration/testdata/event_multi_msg.txtar @@ -13,18 +13,18 @@ gnokey query auth/accounts/g1c0j899h88nwyvnzvh5jagpq6fkkyuj76nld6t0 stdout 'height: 0' stdout 'data: {' stdout ' "BaseAccount": {' -stdout ' "address": "g1c0j899h88nwyvnzvh5jagpq6fkkyuj76nld6t0",' +stdout ' "address": "'${user1_user_addr}'",' stdout ' "coins": "[0-9]*ugnot",' # dynamic stdout ' "public_key": null,' -stdout ' "account_number": "57",' -stdout ' "sequence": "0"' +stdout ' "account_number": "'${user1_account_num}'",' +stdout ' "sequence": "'${user1_account_seq}'"' stdout ' }' stdout '}' ! stderr '.+' # empty ## sign -gnokey sign -tx-path $WORK/multi/multi_msg.tx -chainid=tendermint_test -account-number 57 -account-sequence 0 user1 +gnokey sign -tx-path $WORK/multi/multi_msg.tx -chainid=tendermint_test -account-number $user1_account_num -account-sequence $user1_account_seq user1 stdout 'Tx successfully signed and saved to ' ## broadcast @@ -51,4 +51,3 @@ func Event(value string) { -- multi/multi_msg.tx -- {"msg":[{"@type":"/vm.m_call","caller":"g1c0j899h88nwyvnzvh5jagpq6fkkyuj76nld6t0","send":"","pkg_path":"gno.land/r/demo/simple_event","func":"Event","args":["value11"]},{"@type":"/vm.m_call","caller":"g1c0j899h88nwyvnzvh5jagpq6fkkyuj76nld6t0","send":"","pkg_path":"gno.land/r/demo/simple_event","func":"Event","args":["value22"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":null,"memo":""} - diff --git a/gno.land/pkg/integration/testdata/gnokey.txtar b/gno.land/pkg/integration/testdata/gnokey.txtar index 35759fa25dd..3268782b1ca 100644 --- a/gno.land/pkg/integration/testdata/gnokey.txtar +++ b/gno.land/pkg/integration/testdata/gnokey.txtar @@ -2,22 +2,21 @@ # golden files have been generated using UPDATE_SCRIPTS=true # add a random user -adduserfrom user1 'alpha ability feed thrive color fee grace message chief helmet laundry inmate index brave luxury toddler spawn vague index able zone shoe collect escape' -stdout 'g16v6rp3f4vehjspcu0g0xwz9xvehdkac9kslk5m' +adduser user1 # start gnoland gnoland start ## test1 account should be available on default -gnokey query auth/accounts/g16v6rp3f4vehjspcu0g0xwz9xvehdkac9kslk5m +gnokey query auth/accounts/$user1_user_addr stdout 'height: 0' stdout 'data: {' stdout ' "BaseAccount": {' -stdout ' "address": "g16v6rp3f4vehjspcu0g0xwz9xvehdkac9kslk5m",' +stdout ' "address": "'${user1_user_addr}'",' stdout ' "coins": "[0-9]*ugnot",' # dynamic stdout ' "public_key": null,' -stdout ' "account_number": "57",' -stdout ' "sequence": "0"' +stdout ' "account_number": "'${user1_account_num}'",' +stdout ' "sequence": "'${user1_account_seq}'"' stdout ' }' stdout '}' ! stderr '.+' # empty diff --git a/gno.land/pkg/integration/testdata/gnokey_simulate.txtar b/gno.land/pkg/integration/testdata/gnokey_simulate.txtar index db3cd527eb3..31b2249f8bb 100644 --- a/gno.land/pkg/integration/testdata/gnokey_simulate.txtar +++ b/gno.land/pkg/integration/testdata/gnokey_simulate.txtar @@ -6,41 +6,41 @@ loadpkg gno.land/r/hello $WORK/hello gnoland start # Initial state: assert that sequence == 0. -gnokey query auth/accounts/$USER_ADDR_test1 +gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "1"' # attempt adding the "test" package. # the package has a syntax error; simulation should catch this ahead of time and prevent the tx. # -simulate test ! gnokey maketx addpkg -pkgdir $WORK/test -pkgpath gno.land/r/test -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -simulate test test1 -gnokey query auth/accounts/$USER_ADDR_test1 +gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "1"' # -simulate only ! gnokey maketx addpkg -pkgdir $WORK/test -pkgpath gno.land/r/test -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -simulate only test1 -gnokey query auth/accounts/$USER_ADDR_test1 +gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "1"' # -simulate skip ! gnokey maketx addpkg -pkgdir $WORK/test -pkgpath gno.land/r/test -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -simulate skip test1 -gnokey query auth/accounts/$USER_ADDR_test1 +gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "2"' # attempt calling hello.SetName correctly. # -simulate test and skip should do it successfully, -simulate only should not. # -simulate test gnokey maketx call -pkgpath gno.land/r/hello -func SetName -args John -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate test test1 -gnokey query auth/accounts/$USER_ADDR_test1 +gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "3"' gnokey query vm/qeval --data "gno.land/r/hello.Hello()" stdout 'Hello, John!' # -simulate only gnokey maketx call -pkgpath gno.land/r/hello -func SetName -args Paul -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate only test1 -gnokey query auth/accounts/$USER_ADDR_test1 +gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "3"' gnokey query vm/qeval --data "gno.land/r/hello.Hello()" stdout 'Hello, John!' # -simulate skip gnokey maketx call -pkgpath gno.land/r/hello -func SetName -args George -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate skip test1 -gnokey query auth/accounts/$USER_ADDR_test1 +gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "4"' gnokey query vm/qeval --data "gno.land/r/hello.Hello()" stdout 'Hello, George!' @@ -50,19 +50,19 @@ stdout 'Hello, George!' # none should change the name (ie. panic rollbacks). # -simulate test ! gnokey maketx call -pkgpath gno.land/r/hello -func Grumpy -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate test test1 -gnokey query auth/accounts/$USER_ADDR_test1 +gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "4"' gnokey query vm/qeval --data "gno.land/r/hello.Hello()" stdout 'Hello, George!' # -simulate only ! gnokey maketx call -pkgpath gno.land/r/hello -func Grumpy -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate only test1 -gnokey query auth/accounts/$USER_ADDR_test1 +gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "4"' gnokey query vm/qeval --data "gno.land/r/hello.Hello()" stdout 'Hello, George!' # -simulate skip ! gnokey maketx call -pkgpath gno.land/r/hello -func Grumpy -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate skip test1 -gnokey query auth/accounts/$USER_ADDR_test1 +gnokey query auth/accounts/$test1_user_addr stdout '"sequence": "5"' gnokey query vm/qeval --data "gno.land/r/hello.Hello()" stdout 'Hello, George!' diff --git a/gno.land/pkg/integration/testdata/patchpkg.txtar b/gno.land/pkg/integration/testdata/patchpkg.txtar index c5962709625..0a1a7fa993d 100644 --- a/gno.land/pkg/integration/testdata/patchpkg.txtar +++ b/gno.land/pkg/integration/testdata/patchpkg.txtar @@ -2,13 +2,13 @@ loadpkg gno.land/r/dev/admin $WORK adduser dev -patchpkg "g1abcde" $USER_ADDR_dev +patchpkg "g1abcde" $dev_user_addr gnoland start gnokey maketx call -pkgpath gno.land/r/dev/admin -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 ! stdout g1abcde -stdout $USER_ADDR_dev +stdout $dev_user_addr -- admin.gno -- package admin diff --git a/gno.land/pkg/integration/testdata/prevrealm.txtar b/gno.land/pkg/integration/testdata/prevrealm.txtar index 20317d87345..4bbe16c3205 100644 --- a/gno.land/pkg/integration/testdata/prevrealm.txtar +++ b/gno.land/pkg/integration/testdata/prevrealm.txtar @@ -30,65 +30,65 @@ loadpkg gno.land/p/demo/bar $WORK/p/demo/bar ## start a new node gnoland start -env RFOO_ADDR=g1evezrh92xaucffmtgsaa3rvmz5s8kedffsg469 +env RFOO_USER_ADDR=g1evezrh92xaucffmtgsaa3rvmz5s8kedffsg469 # Test cases ## 1. MsgCall -> myrlm.A: user address gnokey maketx call -pkgpath gno.land/r/myrlm -func A -gas-fee 100000ugnot -gas-wanted 700000 -broadcast -chainid tendermint_test test1 -stdout ${USER_ADDR_test1} +stdout ${test1_user_addr} ## 2. MsgCall -> myrealm.B -> myrlm.A: user address gnokey maketx call -pkgpath gno.land/r/myrlm -func B -gas-fee 100000ugnot -gas-wanted 800000 -broadcast -chainid tendermint_test test1 -stdout ${USER_ADDR_test1} +stdout ${test1_user_addr} ## 3. MsgCall -> r/foo.A -> myrlm.A: r/foo gnokey maketx call -pkgpath gno.land/r/foo -func A -gas-fee 100000ugnot -gas-wanted 800000 -broadcast -chainid tendermint_test test1 -stdout ${RFOO_ADDR} +stdout ${RFOO_USER_ADDR} ## 4. MsgCall -> r/foo.B -> myrlm.B -> r/foo.A: r/foo gnokey maketx call -pkgpath gno.land/r/foo -func B -gas-fee 100000ugnot -gas-wanted 800000 -broadcast -chainid tendermint_test test1 -stdout ${RFOO_ADDR} +stdout ${RFOO_USER_ADDR} ## remove due to update to maketx call can only call realm (case 5, 6, 13) ## 5. MsgCall -> p/demo/bar.A: user address ## gnokey maketx call -pkgpath gno.land/p/demo/bar -func A -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 -## stdout ${USER_ADDR_test1} +## stdout ${test1_user_addr} ## 6. MsgCall -> p/demo/bar.B: user address ## gnokey maketx call -pkgpath gno.land/p/demo/bar -func B -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 -## stdout ${USER_ADDR_test1} +## stdout ${test1_user_addr} ## 7. MsgRun -> myrlm.A: user address gnokey maketx run -gas-fee 100000ugnot -gas-wanted 12000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmA.gno -stdout ${USER_ADDR_test1} +stdout ${test1_user_addr} ## 8. MsgRun -> myrealm.B -> myrlm.A: user address gnokey maketx run -gas-fee 100000ugnot -gas-wanted 12000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmB.gno -stdout ${USER_ADDR_test1} +stdout ${test1_user_addr} ## 9. MsgRun -> r/foo.A -> myrlm.A: r/foo gnokey maketx run -gas-fee 100000ugnot -gas-wanted 12000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooA.gno -stdout ${RFOO_ADDR} +stdout ${RFOO_USER_ADDR} ## 10. MsgRun -> r/foo.B -> myrlm.B -> r/foo.A: r/foo gnokey maketx run -gas-fee 100000ugnot -gas-wanted 12000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooB.gno -stdout ${RFOO_ADDR} +stdout ${RFOO_USER_ADDR} ## 11. MsgRun -> p/demo/bar.A -> myrlm.A: user address gnokey maketx run -gas-fee 100000ugnot -gas-wanted 12000000 -broadcast -chainid tendermint_test test1 $WORK/run/barA.gno -stdout ${USER_ADDR_test1} +stdout ${test1_user_addr} ## 12. MsgRun -> p/demo/bar.B -> myrlm.B -> r/foo.A: user address gnokey maketx run -gas-fee 100000ugnot -gas-wanted 12000000 -broadcast -chainid tendermint_test test1 $WORK/run/barB.gno -stdout ${USER_ADDR_test1} +stdout ${test1_user_addr} ## 13. MsgCall -> std.PrevRealm(): user address ## gnokey maketx call -pkgpath std -func PrevRealm -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 -## stdout ${USER_ADDR_test1} +## stdout ${test1_user_addr} ## 14. MsgRun -> std.PrevRealm(): user address gnokey maketx run -gas-fee 100000ugnot -gas-wanted 12000000 -broadcast -chainid tendermint_test test1 $WORK/run/baz.gno -stdout ${USER_ADDR_test1} +stdout ${test1_user_addr} -- r/myrlm/myrlm.gno -- package myrlm 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 be9a686bac6..a55604267ae 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 @@ -19,31 +19,31 @@ gnokey maketx addpkg -pkgdir $WORK/invalid_realm_denom -pkgpath gno.land/r/test/ gnokey maketx send -send "9999999ugnot" -to g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5 -gas-fee 1ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test2 ## check test2 balance -gnokey query bank/balances/${USER_ADDR_test2} +gnokey query bank/balances/${test2_user_addr} stdout '' ## mint coin from banker -gnokey maketx call -pkgpath gno.land/r/test/realm_banker -func Mint -args ${USER_ADDR_test2} -args "ugnot" -args "31337" -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/test/realm_banker -func Mint -args ${test2_user_addr} -args "ugnot" -args "31337" -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 ## check balance after minting, without patching banker will return '31337ugnot' -gnokey query bank/balances/${USER_ADDR_test2} +gnokey query bank/balances/${test2_user_addr} stdout '"31337/gno.land/r/test/realm_banker:ugnot"' ## burn coin -gnokey maketx call -pkgpath gno.land/r/test/realm_banker -func Burn -args ${USER_ADDR_test2} -args "ugnot" -args "7" -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/test/realm_banker -func Burn -args ${test2_user_addr} -args "ugnot" -args "7" -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 ## check balance after burning -gnokey query bank/balances/${USER_ADDR_test2} +gnokey query bank/balances/${test2_user_addr} stdout '"31330/gno.land/r/test/realm_banker:ugnot"' ## transfer 1ugnot to test2 for gas-fee of below tx -gnokey maketx send -send "1ugnot" -to ${USER_ADDR_test2} -gas-fee 1ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx send -send "1ugnot" -to ${test2_user_addr} -gas-fee 1ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 ## transfer coin gnokey maketx send -send "1330/gno.land/r/test/realm_banker:ugnot" -to g1yr0dpfgthph7y6mepdx8afuec4q3ga2lg8tjt0 -gas-fee 1ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test2 ## check sender balance -gnokey query bank/balances/${USER_ADDR_test2} +gnokey query bank/balances/${test2_user_addr} stdout '"30000/gno.land/r/test/realm_banker:ugnot"' ## check receiver balance @@ -121,4 +121,4 @@ func Mint(addr std.Address, denom string, amount int64) { func Burn(addr std.Address, denom string, amount int64) { banker := std.GetBanker(std.BankerTypeRealmIssue) banker.RemoveCoin(addr, denom, amount) -} \ No newline at end of file +} diff --git a/gno.land/pkg/integration/testscript_gnoland.go b/gno.land/pkg/integration/testscript_gnoland.go index 9781799ea7d..1531b83dfef 100644 --- a/gno.land/pkg/integration/testscript_gnoland.go +++ b/gno.land/pkg/integration/testscript_gnoland.go @@ -20,6 +20,9 @@ import ( "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" "github.com/gnolang/gno/gno.land/pkg/keyscli" "github.com/gnolang/gno/gnovm/pkg/gnoenv" + "github.com/gnolang/gno/tm2/pkg/amino" + rpcclient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" + ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" bft "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/crypto" @@ -45,6 +48,7 @@ const ( envKeyPrivValKey envKeyExecCommand envKeyExecBin + envKeyBase ) type commandkind int @@ -158,13 +162,18 @@ func SetupGnolandTestscript(t *testing.T, p *testscript.Params) error { } kb.ImportPrivKey(DefaultAccount_Name, defaultPK, "") - env.Setenv("USER_SEED_"+DefaultAccount_Name, DefaultAccount_Seed) - env.Setenv("USER_ADDR_"+DefaultAccount_Name, DefaultAccount_Address) + env.Setenv(DefaultAccount_Name+"_user_seed", DefaultAccount_Seed) + env.Setenv(DefaultAccount_Name+"_user_addr", DefaultAccount_Address) // New private key env.Values[envKeyPrivValKey] = ed25519.GenPrivKey() + + // Set gno dbdir env.Setenv("GNO_DBDIR", dbdir) + // Setup account store + env.Values[envKeyBase] = kb + // Generate node short id var sid string { @@ -215,6 +224,7 @@ func SetupGnolandTestscript(t *testing.T, p *testscript.Params) error { "adduserfrom": adduserfromCmd(nodesManager), "patchpkg": patchpkgCmd(), "loadpkg": loadpkgCmd(gnoRootDir), + "scanf": loadpkgCmd(gnoRootDir), } // Initialize cmds map if needed @@ -305,8 +315,11 @@ func gnolandCmd(t *testing.T, nodesManager *NodesManager, gnoRootDir string) fun }) nodesManager.Set(sid, &tNodeProcess{NodeProcess: nodep, cfg: cfg}) - ts.Setenv("RPC_ADDR", nodep.Address()) + + // Load user infos + loadUserEnv(ts, nodep.Address()) + fmt.Fprintln(ts.Stdout(), "node started successfully") case "restart": @@ -337,6 +350,9 @@ func gnolandCmd(t *testing.T, nodesManager *NodesManager, gnoRootDir string) fun ts.Setenv("RPC_ADDR", nodep.Address()) nodesManager.Set(sid, &tNodeProcess{NodeProcess: nodep, cfg: node.cfg}) + // Load user infos + loadUserEnv(ts, nodep.Address()) + fmt.Fprintln(ts.Stdout(), "node restarted successfully") case "stop": @@ -534,6 +550,64 @@ func loadpkgCmd(gnoRootDir string) func(ts *testscript.TestScript, neg bool, arg } } +func loadUserEnv(ts *testscript.TestScript, remote string) error { + const path = "auth/accounts" + + // List all accounts + kb := ts.Value(envKeyBase).(keys.Keybase) + accounts, err := kb.List() + if err != nil { + ts.Fatalf("query accounts: unable to list keys: %s", err) + } + + cli, err := rpcclient.NewHTTPClient(remote) + if err != nil { + return fmt.Errorf("unable create rpc client %q: %w", remote, err) + } + + batch := cli.NewBatch() + for _, account := range accounts { + accountPath := filepath.Join(path, account.GetAddress().String()) + if err := batch.ABCIQuery(accountPath, []byte{}); err != nil { + return fmt.Errorf("unable to create query request: %w", err) + } + } + + batchRes, err := batch.Send(context.Background()) + if err != nil { + return fmt.Errorf("unable to query accounts: %w", err) + } + + if len(batchRes) != len(accounts) { + ts.Fatalf("query accounts: len(res) != len(accounts)") + } + + for i, res := range batchRes { + account := accounts[i] + name := account.GetName() + qres := res.(*ctypes.ResultABCIQuery) + + if err := qres.Response.Error; err != nil { + ts.Fatalf("query account %q error: %s", account.GetName(), err.Error()) + } + + var qret struct{ BaseAccount std.BaseAccount } + if err = amino.UnmarshalJSON(qres.Response.Data, &qret); err != nil { + ts.Fatalf("query account %q unarmshal error: %s", account.GetName(), err.Error()) + } + + strAccountNumber := strconv.Itoa(int(qret.BaseAccount.GetAccountNumber())) + ts.Setenv(name+"_account_num", strAccountNumber) + ts.Logf("[%q] account number: %s", name, strAccountNumber) + + strAccountSequence := strconv.Itoa(int(qret.BaseAccount.GetSequence())) + ts.Setenv(name+"_account_seq", strAccountSequence) + ts.Logf("[%q] account sequence: %s", name, strAccountNumber) + } + + return nil +} + type tsLogWriter struct { ts *testscript.TestScript } @@ -589,94 +663,8 @@ func setupNode(ts *testscript.TestScript, ctx context.Context, cfg *ProcessNodeC return nil } -// `unquote` takes a slice of strings, resulting from splitting a string block by spaces, and -// processes them. The function handles quoted phrases and escape characters within these strings. -func unquote(args []string) ([]string, error) { - const quote = '"' - - parts := []string{} - var inQuote bool - - var part strings.Builder - for _, arg := range args { - var escaped bool - for _, c := range arg { - if escaped { - // If the character is meant to be escaped, it is processed with Unquote. - // We use `Unquote` here for two main reasons: - // 1. It will validate that the escape sequence is correct - // 2. It converts the escaped string to its corresponding raw character. - // For example, "\\t" becomes '\t'. - uc, err := strconv.Unquote(`"\` + string(c) + `"`) - if err != nil { - return nil, fmt.Errorf("unhandled escape sequence `\\%c`: %w", c, err) - } - - part.WriteString(uc) - escaped = false - continue - } - - // If we are inside a quoted string and encounter an escape character, - // flag the next character as `escaped` - if inQuote && c == '\\' { - escaped = true - continue - } - - // Detect quote and toggle inQuote state - if c == quote { - inQuote = !inQuote - continue - } - - // Handle regular character - part.WriteRune(c) - } - - // If we're inside a quote, add a single space. - // It reflects one or multiple spaces between args in the original string. - if inQuote { - part.WriteRune(' ') - continue - } - - // Finalize part, add to parts, and reset for next part - parts = append(parts, part.String()) - part.Reset() - } - - // Check if a quote is left open - if inQuote { - return nil, errors.New("unfinished quote") - } - - return parts, nil -} - -func getNodeSID(ts *testscript.TestScript) string { - return ts.Getenv("SID") -} - -func tsValidateError(ts *testscript.TestScript, cmd string, neg bool, err error) { - if err != nil { - fmt.Fprintf(ts.Stderr(), "%q error: %+v\n", cmd, err) - if !neg { - ts.Fatalf("unexpected %q command failure: %s", cmd, err) - } - } else { - if neg { - ts.Fatalf("unexpected %q command success", cmd) - } - } -} - -type envSetter interface { - Setenv(key, value string) -} - // createAccount creates a new account with the given name and adds it to the keybase. -func createAccount(env envSetter, kb keys.Keybase, accountName string) (gnoland.Balance, error) { +func createAccount(ts *testscript.TestScript, kb keys.Keybase, accountName string) (gnoland.Balance, error) { var balance gnoland.Balance entropy, err := bip39.NewEntropy(256) if err != nil { @@ -688,23 +676,11 @@ func createAccount(env envSetter, kb keys.Keybase, accountName string) (gnoland. return balance, fmt.Errorf("error generating mnemonic: %w", err) } - var keyInfo keys.Info - if keyInfo, err = kb.CreateAccount(accountName, mnemonic, "", "", 0, 0); err != nil { - return balance, fmt.Errorf("unable to create account: %w", err) - } - - address := keyInfo.GetAddress() - env.Setenv("USER_SEED_"+accountName, mnemonic) - env.Setenv("USER_ADDR_"+accountName, address.String()) - - return gnoland.Balance{ - Address: address, - Amount: std.Coins{std.NewCoin(ugnot.Denom, 10e6)}, - }, nil + return createAccountFrom(ts, kb, accountName, mnemonic, 0, 0) } // createAccountFrom creates a new account with the given metadata and adds it to the keybase. -func createAccountFrom(env envSetter, kb keys.Keybase, accountName, mnemonic string, account, index uint32) (gnoland.Balance, error) { +func createAccountFrom(ts *testscript.TestScript, kb keys.Keybase, accountName, mnemonic string, account, index uint32) (gnoland.Balance, error) { var balance gnoland.Balance // check if mnemonic is valid @@ -718,8 +694,8 @@ func createAccountFrom(env envSetter, kb keys.Keybase, accountName, mnemonic str } address := keyInfo.GetAddress() - env.Setenv("USER_SEED_"+accountName, mnemonic) - env.Setenv("USER_ADDR_"+accountName, address.String()) + ts.Setenv(accountName+"_user_seed", mnemonic) + ts.Setenv(accountName+"_user_addr", address.String()) return gnoland.Balance{ Address: address, @@ -787,3 +763,20 @@ func GeneratePrivKeyFromMnemonic(mnemonic, bip39Passphrase string, account, inde privKey := secp256k1.PrivKeySecp256k1(derivedPriv) return privKey, nil } + +func getNodeSID(ts *testscript.TestScript) string { + return ts.Getenv("SID") +} + +func tsValidateError(ts *testscript.TestScript, cmd string, neg bool, err error) { + if err != nil { + fmt.Fprintf(ts.Stderr(), "%q error: %+v\n", cmd, err) + if !neg { + ts.Fatalf("unexpected %q command failure: %s", cmd, err) + } + } else { + if neg { + ts.Fatalf("unexpected %q command success", cmd) + } + } +} diff --git a/gno.land/pkg/integration/utils.go b/gno.land/pkg/integration/utils.go new file mode 100644 index 00000000000..bc9e7f1e220 --- /dev/null +++ b/gno.land/pkg/integration/utils.go @@ -0,0 +1,73 @@ +package integration + +import ( + "errors" + "fmt" + "strconv" + "strings" +) + +// `unquote` takes a slice of strings, resulting from splitting a string block by spaces, and +// processes them. The function handles quoted phrases and escape characters within these strings. +func unquote(args []string) ([]string, error) { + const quote = '"' + + parts := []string{} + var inQuote bool + + var part strings.Builder + for _, arg := range args { + var escaped bool + for _, c := range arg { + if escaped { + // If the character is meant to be escaped, it is processed with Unquote. + // We use `Unquote` here for two main reasons: + // 1. It will validate that the escape sequence is correct + // 2. It converts the escaped string to its corresponding raw character. + // For example, "\\t" becomes '\t'. + uc, err := strconv.Unquote(`"\` + string(c) + `"`) + if err != nil { + return nil, fmt.Errorf("unhandled escape sequence `\\%c`: %w", c, err) + } + + part.WriteString(uc) + escaped = false + continue + } + + // If we are inside a quoted string and encounter an escape character, + // flag the next character as `escaped` + if inQuote && c == '\\' { + escaped = true + continue + } + + // Detect quote and toggle inQuote state + if c == quote { + inQuote = !inQuote + continue + } + + // Handle regular character + part.WriteRune(c) + } + + // If we're inside a quote, add a single space. + // It reflects one or multiple spaces between args in the original string. + if inQuote { + part.WriteRune(' ') + continue + } + + // Finalize part, add to parts, and reset for next part + parts = append(parts, part.String()) + part.Reset() + } + + // Check if a quote is left open + if inQuote { + return nil, errors.New("unfinished quote") + } + + return parts, nil +} diff --git a/gno.land/pkg/integration/testscript_gnoland_test.go b/gno.land/pkg/integration/utils_test.go similarity index 100% rename from gno.land/pkg/integration/testscript_gnoland_test.go rename to gno.land/pkg/integration/utils_test.go