From 15e58960326612bb7943197e5307fd109b6742f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20=C5=BDivkovi=C4=87?= Date: Fri, 10 Jan 2025 00:13:30 +0100 Subject: [PATCH 1/3] fix: add support for signing lazily loaded transactions in genesis (#3468) ## Description This PR fixes an issue where genesis transactions added to `genesis.json` through `--lazy` fail, since the signatures are missing. It also introduces support for disabling genesis sig verification altogether. Why this was needed: - Portal Loop transactions are signed with a valid account number and sequence (not 0), and when they are replayed (they are shoved into a new aggregated `genesis.json`), their signatures are also migrated. Upon initializing the chain, this would cause the signature verification to fail (the sig verification process for genesis txs expects account number and sequence values of 0, but this is not the case) @moul, the transaction signatures in `gno.land/genesis/genesis_txs.jsonl` are invalid, and will always fail when being verified --------- Co-authored-by: Nathan Toups <612924+n2p5@users.noreply.github.com> --- .github/workflows/portal-loop.yml | 1 + .../internal/txs/txs_add_packages.go | 1 - gno.land/cmd/gnoland/start.go | 104 +++++++++++++----- gno.land/pkg/gnoland/app.go | 22 +++- gno.land/pkg/gnoland/app_test.go | 2 +- gno.land/pkg/gnoland/genesis.go | 9 +- gno.land/pkg/gnoland/types.go | 29 +++++ gno.land/pkg/gnoland/types_test.go | 27 +++++ gno.land/pkg/integration/node_testing.go | 2 +- gno.land/pkg/integration/pkgloader.go | 3 +- gno.land/pkg/integration/signer.go | 33 ------ .../testdata/event_multi_msg.txtar | 23 ++-- .../pkg/integration/testdata/gnokey.txtar | 10 +- .../testdata/gnoweb_airgapped.txtar | 21 ++-- .../testdata/restart_missing_type.txtar | 16 ++- .../integration/testdata/simulate_gas.txtar | 4 +- misc/loop/scripts/start.sh | 3 +- tm2/pkg/sdk/auth/ante.go | 6 +- tm2/pkg/sdk/auth/ante_test.go | 4 +- 19 files changed, 207 insertions(+), 113 deletions(-) delete mode 100644 gno.land/pkg/integration/signer.go diff --git a/.github/workflows/portal-loop.yml b/.github/workflows/portal-loop.yml index b5cafa459a7..aeb59d4dc77 100644 --- a/.github/workflows/portal-loop.yml +++ b/.github/workflows/portal-loop.yml @@ -45,6 +45,7 @@ jobs: labels: ${{ steps.meta.outputs.labels }} test-portal-loop-docker-compose: + if: ${{ false }} runs-on: ubuntu-latest timeout-minutes: 10 steps: diff --git a/contribs/gnogenesis/internal/txs/txs_add_packages.go b/contribs/gnogenesis/internal/txs/txs_add_packages.go index 0ab5724154e..53c0bb4b686 100644 --- a/contribs/gnogenesis/internal/txs/txs_add_packages.go +++ b/contribs/gnogenesis/internal/txs/txs_add_packages.go @@ -18,7 +18,6 @@ import ( const ( defaultAccount_Name = "test1" - defaultAccount_Address = "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5" defaultAccount_Seed = "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast" defaultAccount_publicKey = "gpub1pgfj7ard9eg82cjtv4u4xetrwqer2dntxyfzxz3pq0skzdkmzu0r9h6gny6eg8c9dc303xrrudee6z4he4y7cs5rnjwmyf40yaj" ) diff --git a/gno.land/cmd/gnoland/start.go b/gno.land/cmd/gnoland/start.go index cb5d54a513a..4f380031be4 100644 --- a/gno.land/cmd/gnoland/start.go +++ b/gno.land/cmd/gnoland/start.go @@ -45,22 +45,20 @@ var startGraphic = strings.ReplaceAll(` /___/ `, "'", "`") -var ( - // Keep in sync with contribs/gnogenesis/internal/txs/txs_add_packages.go - genesisDeployAddress = crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // test1 - genesisDeployFee = std.NewFee(50000, std.MustParseCoin(ugnot.ValueString(1000000))) -) +// Keep in sync with contribs/gnogenesis/internal/txs/txs_add_packages.go +var genesisDeployFee = std.NewFee(50000, std.MustParseCoin(ugnot.ValueString(1000000))) type startCfg struct { - gnoRootDir string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 - skipFailingGenesisTxs bool // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 - genesisBalancesFile string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 - genesisTxsFile string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 - genesisRemote string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 - genesisFile string - chainID string - dataDir string - lazyInit bool + gnoRootDir string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 + skipFailingGenesisTxs bool // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 + skipGenesisSigVerification bool // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 + genesisBalancesFile string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 + genesisTxsFile string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 + genesisRemote string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 + genesisFile string + chainID string + dataDir string + lazyInit bool logLevel string logFormat string @@ -86,7 +84,6 @@ func newStartCmd(io commands.IO) *commands.Command { func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { gnoroot := gnoenv.RootDir() defaultGenesisBalancesFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt") - defaultGenesisTxsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.jsonl") fs.BoolVar( &c.skipFailingGenesisTxs, @@ -95,6 +92,13 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { "don't panic when replaying invalid genesis txs", ) + fs.BoolVar( + &c.skipGenesisSigVerification, + "skip-genesis-sig-verification", + false, + "don't panic when replaying invalidly signed genesis txs", + ) + fs.StringVar( &c.genesisBalancesFile, "genesis-balances-file", @@ -105,7 +109,7 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { fs.StringVar( &c.genesisTxsFile, "genesis-txs-file", - defaultGenesisTxsFile, + "", "initial txs to replay", ) @@ -218,7 +222,7 @@ func execStart(ctx context.Context, c *startCfg, io commands.IO) error { ) // Init a new genesis.json - if err := lazyInitGenesis(io, c, genesisPath, privateKey.GetPubKey()); err != nil { + if err := lazyInitGenesis(io, c, genesisPath, privateKey.Key.PrivKey); err != nil { return fmt.Errorf("unable to initialize genesis.json, %w", err) } } @@ -238,7 +242,16 @@ func execStart(ctx context.Context, c *startCfg, io commands.IO) error { minGasPrices := cfg.Application.MinGasPrices // Create application and node - cfg.LocalApp, err = gnoland.NewApp(nodeDir, c.skipFailingGenesisTxs, evsw, logger, minGasPrices) + cfg.LocalApp, err = gnoland.NewApp( + nodeDir, + gnoland.GenesisAppConfig{ + SkipFailingTxs: c.skipFailingGenesisTxs, + SkipSigVerification: c.skipGenesisSigVerification, + }, + evsw, + logger, + minGasPrices, + ) if err != nil { return fmt.Errorf("unable to create the Gnoland app, %w", err) } @@ -334,7 +347,7 @@ func lazyInitGenesis( io commands.IO, c *startCfg, genesisPath string, - publicKey crypto.PubKey, + privateKey crypto.PrivKey, ) error { // Check if the genesis.json is present if osm.FileExists(genesisPath) { @@ -342,7 +355,7 @@ func lazyInitGenesis( } // Generate the new genesis.json file - if err := generateGenesisFile(genesisPath, publicKey, c); err != nil { + if err := generateGenesisFile(genesisPath, privateKey, c); err != nil { return fmt.Errorf("unable to generate genesis file, %w", err) } @@ -367,7 +380,21 @@ func initializeLogger(io io.WriteCloser, logLevel, logFormat string) (*zap.Logge return log.GetZapLoggerFn(format)(io, level), nil } -func generateGenesisFile(genesisFile string, pk crypto.PubKey, c *startCfg) error { +func generateGenesisFile(genesisFile string, privKey crypto.PrivKey, c *startCfg) error { + var ( + pubKey = privKey.PubKey() + // There is an active constraint for gno.land transactions: + // + // All transaction messages' (MsgSend, MsgAddPkg...) "author" field, + // specific to the message type ("creator", "sender"...), must match + // the signature address contained in the transaction itself. + // This means that if MsgSend is originating from address A, + // the owner of the private key for address A needs to sign the transaction + // containing the message. Every message in a transaction needs to + // originate from the same account that signed the transaction + txSender = pubKey.Address() + ) + gen := &bft.GenesisDoc{} gen.GenesisTime = time.Now() gen.ChainID = c.chainID @@ -383,8 +410,8 @@ func generateGenesisFile(genesisFile string, pk crypto.PubKey, c *startCfg) erro gen.Validators = []bft.GenesisValidator{ { - Address: pk.Address(), - PubKey: pk, + Address: pubKey.Address(), + PubKey: pubKey, Power: 10, Name: "testvalidator", }, @@ -398,22 +425,43 @@ func generateGenesisFile(genesisFile string, pk crypto.PubKey, c *startCfg) erro // Load examples folder examplesDir := filepath.Join(c.gnoRootDir, "examples") - pkgsTxs, err := gnoland.LoadPackagesFromDir(examplesDir, genesisDeployAddress, genesisDeployFee) + pkgsTxs, err := gnoland.LoadPackagesFromDir(examplesDir, txSender, genesisDeployFee) if err != nil { return fmt.Errorf("unable to load examples folder: %w", err) } // Load Genesis TXs - genesisTxs, err := gnoland.LoadGenesisTxsFile(c.genesisTxsFile, c.chainID, c.genesisRemote) - if err != nil { - return fmt.Errorf("unable to load genesis txs file: %w", err) + var genesisTxs []gnoland.TxWithMetadata + + if c.genesisTxsFile != "" { + genesisTxs, err = gnoland.LoadGenesisTxsFile(c.genesisTxsFile, c.chainID, c.genesisRemote) + if err != nil { + return fmt.Errorf("unable to load genesis txs file: %w", err) + } } genesisTxs = append(pkgsTxs, genesisTxs...) + // Sign genesis transactions, with the default key (test1) + if err = gnoland.SignGenesisTxs(genesisTxs, privKey, c.chainID); err != nil { + return fmt.Errorf("unable to sign genesis txs: %w", err) + } + + // Make sure the genesis transaction author has sufficient + // balance to cover transaction deployments in genesis. + // + // During the init-chainer process, the account that authors the + // genesis transactions needs to have a sufficient balance + // to cover outstanding transaction costs. + // Since the cost can't be estimated upfront at this point, the balance + // set is an arbitrary value based on a "best guess" basis. + // There should be a larger discussion if genesis transactions should consume gas, at all + deployerBalance := int64(len(genesisTxs)) * 10_000_000 // ~10 GNOT per tx + balances.Set(txSender, std.NewCoins(std.NewCoin("ugnot", deployerBalance))) + // Construct genesis AppState. defaultGenState := gnoland.DefaultGenState() - defaultGenState.Balances = balances + defaultGenState.Balances = balances.List() defaultGenState.Txs = genesisTxs gen.AppState = defaultGenState diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index 80c58e9e982..0826071b9f5 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -182,10 +182,25 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) { return baseApp, nil } +// GenesisAppConfig wraps the most important +// genesis params relating to the App +type GenesisAppConfig struct { + SkipFailingTxs bool // does not stop the chain from starting if any tx fails + SkipSigVerification bool // does not verify the transaction signatures in genesis +} + +// NewTestGenesisAppConfig returns a testing genesis app config +func NewTestGenesisAppConfig() GenesisAppConfig { + return GenesisAppConfig{ + SkipFailingTxs: true, + SkipSigVerification: true, + } +} + // NewApp creates the gno.land application. func NewApp( dataRootDir string, - skipFailingGenesisTxs bool, + genesisCfg GenesisAppConfig, evsw events.EventSwitch, logger *slog.Logger, minGasPrices string, @@ -199,9 +214,10 @@ func NewApp( GenesisTxResultHandler: PanicOnFailingTxResultHandler, StdlibDir: filepath.Join(gnoenv.RootDir(), "gnovm", "stdlibs"), }, - MinGasPrices: minGasPrices, + MinGasPrices: minGasPrices, + SkipGenesisVerification: genesisCfg.SkipSigVerification, } - if skipFailingGenesisTxs { + if genesisCfg.SkipFailingTxs { cfg.GenesisTxResultHandler = NoopGenesisTxResultHandler } diff --git a/gno.land/pkg/gnoland/app_test.go b/gno.land/pkg/gnoland/app_test.go index 56a15fed5a9..361d7505157 100644 --- a/gno.land/pkg/gnoland/app_test.go +++ b/gno.land/pkg/gnoland/app_test.go @@ -134,7 +134,7 @@ func TestNewApp(t *testing.T) { // NewApp should have good defaults and manage to run InitChain. td := t.TempDir() - app, err := NewApp(td, true, events.NewEventSwitch(), log.NewNoopLogger(), "") + app, err := NewApp(td, NewTestGenesisAppConfig(), events.NewEventSwitch(), log.NewNoopLogger(), "") require.NoError(t, err, "NewApp should be successful") resp := app.InitChain(abci.RequestInitChain{ diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go index d7844d77b57..a754e7a4644 100644 --- a/gno.land/pkg/gnoland/genesis.go +++ b/gno.land/pkg/gnoland/genesis.go @@ -20,7 +20,7 @@ import ( const initGasPrice = "1ugnot/1000gas" // LoadGenesisBalancesFile loads genesis balances from the provided file path. -func LoadGenesisBalancesFile(path string) ([]Balance, error) { +func LoadGenesisBalancesFile(path string) (Balances, error) { // each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot content, err := osm.ReadFile(path) if err != nil { @@ -28,7 +28,7 @@ func LoadGenesisBalancesFile(path string) ([]Balance, error) { } lines := strings.Split(string(content), "\n") - balances := make([]Balance, 0, len(lines)) + balances := make(Balances, len(lines)) for _, line := range lines { line = strings.TrimSpace(line) @@ -56,10 +56,7 @@ func LoadGenesisBalancesFile(path string) ([]Balance, error) { return nil, fmt.Errorf("invalid balance coins %s: %w", parts[1], err) } - balances = append(balances, Balance{ - Address: addr, - Amount: coins, - }) + balances.Set(addr, coins) } return balances, nil diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go index ed35c4141f4..66fb2f54e8a 100644 --- a/gno.land/pkg/gnoland/types.go +++ b/gno.land/pkg/gnoland/types.go @@ -8,6 +8,7 @@ import ( "os" "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/sdk/auth" "github.com/gnolang/gno/tm2/pkg/std" ) @@ -86,3 +87,31 @@ func ReadGenesisTxs(ctx context.Context, path string) ([]TxWithMetadata, error) return txs, nil } + +// SignGenesisTxs will sign all txs passed as argument using the private key. +// This signature is only valid for genesis transactions as the account number and sequence are 0 +func SignGenesisTxs(txs []TxWithMetadata, privKey crypto.PrivKey, chainID string) error { + for index, tx := range txs { + // Upon verifying genesis transactions, the account number and sequence are considered to be 0. + // The reason for this is that it is not possible to know the account number (or sequence!) in advance + // when generating the genesis transaction signature + bytes, err := tx.Tx.GetSignBytes(chainID, 0, 0) + if err != nil { + return fmt.Errorf("unable to get sign bytes for transaction, %w", err) + } + + signature, err := privKey.Sign(bytes) + if err != nil { + return fmt.Errorf("unable to sign genesis transaction, %w", err) + } + + txs[index].Tx.Signatures = []std.Signature{ + { + PubKey: privKey.PubKey(), + Signature: signature, + }, + } + } + + return nil +} diff --git a/gno.land/pkg/gnoland/types_test.go b/gno.land/pkg/gnoland/types_test.go index b4625d6d7d6..c501325bc3e 100644 --- a/gno.land/pkg/gnoland/types_test.go +++ b/gno.land/pkg/gnoland/types_test.go @@ -11,6 +11,7 @@ import ( "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/crypto" + "github.com/gnolang/gno/tm2/pkg/crypto/secp256k1" "github.com/gnolang/gno/tm2/pkg/sdk/bank" "github.com/gnolang/gno/tm2/pkg/std" "github.com/stretchr/testify/assert" @@ -129,3 +130,29 @@ func TestReadGenesisTxs(t *testing.T) { } }) } + +func TestSignGenesisTx(t *testing.T) { + t.Parallel() + + var ( + txs = generateTxs(t, 100) + privKey = secp256k1.GenPrivKey() + pubKey = privKey.PubKey() + chainID = "testing" + ) + + // Make sure the transactions are properly signed + require.NoError(t, SignGenesisTxs(txs, privKey, chainID)) + + // Make sure the signatures are valid + for _, tx := range txs { + payload, err := tx.Tx.GetSignBytes(chainID, 0, 0) + require.NoError(t, err) + + sigs := tx.Tx.GetSignatures() + require.Len(t, sigs, 1) + + assert.True(t, pubKey.Equals(sigs[0].PubKey)) + assert.True(t, pubKey.VerifyBytes(payload, sigs[0].Signature)) + } +} diff --git a/gno.land/pkg/integration/node_testing.go b/gno.land/pkg/integration/node_testing.go index 7965f228fc2..edcf53de5d3 100644 --- a/gno.land/pkg/integration/node_testing.go +++ b/gno.land/pkg/integration/node_testing.go @@ -148,7 +148,7 @@ func LoadDefaultGenesisBalanceFile(t TestingTS, gnoroot string) []gnoland.Balanc genesisBalances, err := gnoland.LoadGenesisBalancesFile(balanceFile) require.NoError(t, err) - return genesisBalances + return genesisBalances.List() } // LoadDefaultGenesisParamFile loads the default genesis balance file for testing. diff --git a/gno.land/pkg/integration/pkgloader.go b/gno.land/pkg/integration/pkgloader.go index e40e8ff1eb5..71b1491b2a8 100644 --- a/gno.land/pkg/integration/pkgloader.go +++ b/gno.land/pkg/integration/pkgloader.go @@ -77,8 +77,7 @@ func (pl *PkgsLoader) LoadPackages(creatorKey crypto.PrivKey, fee std.Fee, depos } } - err = SignTxs(txs, creatorKey, "tendermint_test") - if err != nil { + if err = gnoland.SignGenesisTxs(txs, creatorKey, "tendermint_test"); err != nil { return nil, fmt.Errorf("unable to sign txs: %w", err) } diff --git a/gno.land/pkg/integration/signer.go b/gno.land/pkg/integration/signer.go deleted file mode 100644 index b32cd9c59bc..00000000000 --- a/gno.land/pkg/integration/signer.go +++ /dev/null @@ -1,33 +0,0 @@ -package integration - -import ( - "fmt" - - "github.com/gnolang/gno/gno.land/pkg/gnoland" - - "github.com/gnolang/gno/tm2/pkg/crypto" - "github.com/gnolang/gno/tm2/pkg/std" -) - -// SignTxs will sign all txs passed as argument using the private key -// this signature is only valid for genesis transactions as accountNumber and sequence are 0 -func SignTxs(txs []gnoland.TxWithMetadata, privKey crypto.PrivKey, chainID string) error { - for index, tx := range txs { - bytes, err := tx.Tx.GetSignBytes(chainID, 0, 0) - if err != nil { - return fmt.Errorf("unable to get sign bytes for transaction, %w", err) - } - signature, err := privKey.Sign(bytes) - if err != nil { - return fmt.Errorf("unable to sign transaction, %w", err) - } - - txs[index].Tx.Signatures = []std.Signature{ - { - PubKey: privKey.PubKey(), - Signature: signature, - }, - } - } - return nil -} diff --git a/gno.land/pkg/integration/testdata/event_multi_msg.txtar b/gno.land/pkg/integration/testdata/event_multi_msg.txtar index 13a448e7f8c..4c8de856f03 100644 --- a/gno.land/pkg/integration/testdata/event_multi_msg.txtar +++ b/gno.land/pkg/integration/testdata/event_multi_msg.txtar @@ -1,29 +1,30 @@ # load the package from $WORK directory loadpkg gno.land/r/demo/simple_event $WORK/event +# add a random user +adduserfrom user1 'success myself purchase tray reject demise scene little legend someone lunar hope media goat regular test area smart save flee surround attack rapid smoke' +stdout 'g1c0j899h88nwyvnzvh5jagpq6fkkyuj76nld6t0' + # start a new node gnoland start -## test1 account should be available on default -gnokey query auth/accounts/${USER_ADDR_test1} +## account should be available since it has an initial balance +gnokey query auth/accounts/g1c0j899h88nwyvnzvh5jagpq6fkkyuj76nld6t0 stdout 'height: 0' stdout 'data: {' stdout ' "BaseAccount": {' -stdout ' "address": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",' +stdout ' "address": "g1c0j899h88nwyvnzvh5jagpq6fkkyuj76nld6t0",' stdout ' "coins": "[0-9]*ugnot",' # dynamic -stdout ' "public_key": {' -stdout ' "@type": "/tm.PubKeySecp256k1",' -stdout ' "value": "A\+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"' -stdout ' },' -stdout ' "account_number": "0",' -stdout ' "sequence": "1"' +stdout ' "public_key": null,' +stdout ' "account_number": "57",' +stdout ' "sequence": "0"' stdout ' }' stdout '}' ! stderr '.+' # empty ## sign -gnokey sign -tx-path $WORK/multi/multi_msg.tx -chainid=tendermint_test -account-number 0 -account-sequence 1 test1 +gnokey sign -tx-path $WORK/multi/multi_msg.tx -chainid=tendermint_test -account-number 57 -account-sequence 0 user1 stdout 'Tx successfully signed and saved to ' ## broadcast @@ -49,5 +50,5 @@ func Event(value string) { } -- multi/multi_msg.tx -- -{"msg":[{"@type":"/vm.m_call","caller":"g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5","send":"","pkg_path":"gno.land/r/demo/simple_event","func":"Event","args":["value11"]},{"@type":"/vm.m_call","caller":"g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5","send":"","pkg_path":"gno.land/r/demo/simple_event","func":"Event","args":["value22"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":null,"memo":""} +{"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 123a0ce291c..35759fa25dd 100644 --- a/gno.land/pkg/integration/testdata/gnokey.txtar +++ b/gno.land/pkg/integration/testdata/gnokey.txtar @@ -1,18 +1,22 @@ # test basic gnokey integrations commands # 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' + # start gnoland gnoland start ## test1 account should be available on default -gnokey query auth/accounts/${USER_ADDR_test1} +gnokey query auth/accounts/g16v6rp3f4vehjspcu0g0xwz9xvehdkac9kslk5m stdout 'height: 0' stdout 'data: {' stdout ' "BaseAccount": {' -stdout ' "address": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",' +stdout ' "address": "g16v6rp3f4vehjspcu0g0xwz9xvehdkac9kslk5m",' stdout ' "coins": "[0-9]*ugnot",' # dynamic stdout ' "public_key": null,' -stdout ' "account_number": "0",' +stdout ' "account_number": "57",' stdout ' "sequence": "0"' stdout ' }' stdout '}' diff --git a/gno.land/pkg/integration/testdata/gnoweb_airgapped.txtar b/gno.land/pkg/integration/testdata/gnoweb_airgapped.txtar index 02bd8058214..838db121442 100644 --- a/gno.land/pkg/integration/testdata/gnoweb_airgapped.txtar +++ b/gno.land/pkg/integration/testdata/gnoweb_airgapped.txtar @@ -4,32 +4,33 @@ # load the package from $WORK directory loadpkg gno.land/r/demo/echo +# add a random user +adduserfrom user1 'lamp any denial pulse used shoot gap error denial mansion hurry foot solution grab winner congress drastic cat bamboo chicken color digital coffee unknown' +stdout 'g1meuazsmy8ztaz2xpuyraqq4axy6s00ycl07zva' + # start the node gnoland start # Query account -gnokey query auth/accounts/${USER_ADDR_test1} +gnokey query auth/accounts/g1meuazsmy8ztaz2xpuyraqq4axy6s00ycl07zva stdout 'height: 0' stdout 'data: {' stdout ' "BaseAccount": {' -stdout ' "address": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",' +stdout ' "address": "g1meuazsmy8ztaz2xpuyraqq4axy6s00ycl07zva",' stdout ' "coins": "[0-9]*ugnot",' # dynamic -stdout ' "public_key": {' -stdout ' "@type": "/tm.PubKeySecp256k1",' -stdout ' "value": "A\+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"' -stdout ' },' -stdout ' "account_number": "0",' -stdout ' "sequence": "4"' +stdout ' "public_key": null,' +stdout ' "account_number": "57",' +stdout ' "sequence": "0"' stdout ' }' stdout '}' ! stderr '.+' # empty # Create transaction -gnokey maketx call -pkgpath "gno.land/r/demo/echo" -func "Render" -gas-fee 1000000ugnot -gas-wanted 2000000 -send "" -args "HELLO" test1 +gnokey maketx call -pkgpath "gno.land/r/demo/echo" -func "Render" -gas-fee 1000000ugnot -gas-wanted 2000000 -send "" -args "HELLO" user1 cp stdout call.tx # Sign -gnokey sign -tx-path $WORK/call.tx -chainid "tendermint_test" -account-number 0 -account-sequence 4 test1 +gnokey sign -tx-path $WORK/call.tx -chainid "tendermint_test" -account-number 57 -account-sequence 0 user1 cmpenv stdout sign.stdout.golden gnokey broadcast $WORK/call.tx diff --git a/gno.land/pkg/integration/testdata/restart_missing_type.txtar b/gno.land/pkg/integration/testdata/restart_missing_type.txtar index 09e1a27d6f4..cc8ed702734 100644 --- a/gno.land/pkg/integration/testdata/restart_missing_type.txtar +++ b/gno.land/pkg/integration/testdata/restart_missing_type.txtar @@ -1,3 +1,7 @@ +# add a random user +adduserfrom user1 'bone make joy hospital hawk crew civil relief maple alter always frozen category emerge fun inflict room sphere casino vital scheme basket omit wrap' +stdout 'g1lmgyf29g6zqgpln5pq05zzt7qkz2wga7xgagv4' + # This txtar is a regression test for a bug, whereby a type is committed to # the defaultStore.cacheTypes map, but not to the underlying store (due to a # failing transaction). @@ -5,15 +9,15 @@ loadpkg gno.land/p/demo/avl gnoland start -gnokey sign -tx-path $WORK/tx1.tx -chainid tendermint_test -account-sequence 1 test1 +gnokey sign -tx-path $WORK/tx1.tx -chainid tendermint_test -account-sequence 0 -account-number 57 user1 ! gnokey broadcast $WORK/tx1.tx stderr 'out of gas' -gnokey sign -tx-path $WORK/tx2.tx -chainid tendermint_test -account-sequence 2 test1 +gnokey sign -tx-path $WORK/tx2.tx -chainid tendermint_test -account-sequence 1 -account-number 57 user1 gnokey broadcast $WORK/tx2.tx stdout 'OK!' -gnokey sign -tx-path $WORK/tx3.tx -chainid tendermint_test -account-sequence 3 test1 +gnokey sign -tx-path $WORK/tx3.tx -chainid tendermint_test -account-sequence 2 -account-number 57 user1 gnokey broadcast $WORK/tx3.tx stdout 'OK!' @@ -24,7 +28,7 @@ gnoland restart "msg": [ { "@type": "/vm.m_addpkg", - "creator": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", + "creator": "g1lmgyf29g6zqgpln5pq05zzt7qkz2wga7xgagv4", "package": { "name": "zentasktic", "path": "gno.land/p/g17ernafy6ctpcz6uepfsq2js8x2vz0wladh5yc3/zentasktic", @@ -99,7 +103,7 @@ gnoland restart "msg": [ { "@type": "/vm.m_addpkg", - "creator": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", + "creator": "g1lmgyf29g6zqgpln5pq05zzt7qkz2wga7xgagv4", "package": { "name": "zentasktic", "path": "gno.land/p/g17ernafy6ctpcz6uepfsq2js8x2vz0wladh5yc3/zentasktic", @@ -174,7 +178,7 @@ gnoland restart "msg": [ { "@type": "/vm.m_addpkg", - "creator": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", + "creator": "g1lmgyf29g6zqgpln5pq05zzt7qkz2wga7xgagv4", "package": { "name": "zentasktic_core", "path": "gno.land/r/g17ernafy6ctpcz6uepfsq2js8x2vz0wladh5yc3/zentasktic_core", diff --git a/gno.land/pkg/integration/testdata/simulate_gas.txtar b/gno.land/pkg/integration/testdata/simulate_gas.txtar index 4c5213da345..57be82b75ff 100644 --- a/gno.land/pkg/integration/testdata/simulate_gas.txtar +++ b/gno.land/pkg/integration/testdata/simulate_gas.txtar @@ -6,11 +6,11 @@ gnoland start # simulate only gnokey maketx call -pkgpath gno.land/r/simulate -func Hello -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -simulate only test1 -stdout 'GAS USED: 99015' +stdout 'GAS USED: 99339' # simulate skip gnokey maketx call -pkgpath gno.land/r/simulate -func Hello -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -simulate skip test1 -stdout 'GAS USED: 99015' # same as simulate only +stdout 'GAS USED: 99339' # same as simulate only -- package/package.gno -- diff --git a/misc/loop/scripts/start.sh b/misc/loop/scripts/start.sh index db36de39f2a..fd753324f5d 100755 --- a/misc/loop/scripts/start.sh +++ b/misc/loop/scripts/start.sh @@ -36,4 +36,5 @@ gnoland config set p2p.persistent_peers "${PERSISTENT_PEERS}" exec gnoland start \ --chainid="${CHAIN_ID}" \ --lazy \ - --skip-failing-genesis-txs + --skip-failing-genesis-txs \ + --skip-genesis-sig-verification diff --git a/tm2/pkg/sdk/auth/ante.go b/tm2/pkg/sdk/auth/ante.go index f05a8eff0a7..f941f398b17 100644 --- a/tm2/pkg/sdk/auth/ante.go +++ b/tm2/pkg/sdk/auth/ante.go @@ -215,7 +215,7 @@ func processSig( ctx sdk.Context, acc std.Account, sig std.Signature, signBytes []byte, simulate bool, params Params, sigGasConsumer SignatureVerificationGasConsumer, ) (updatedAcc std.Account, res sdk.Result) { - pubKey, res := ProcessPubKey(acc, sig, simulate) + pubKey, res := ProcessPubKey(acc, sig) if !res.IsOK() { return nil, res } @@ -243,7 +243,7 @@ func processSig( // ProcessPubKey verifies that the given account address matches that of the // std.Signature. In addition, it will set the public key of the account if it // has not been set. -func ProcessPubKey(acc std.Account, sig std.Signature, simulate bool) (crypto.PubKey, sdk.Result) { +func ProcessPubKey(acc std.Account, sig std.Signature) (crypto.PubKey, sdk.Result) { // If pubkey is not known for account, set it from the std.Signature. pubKey := acc.GetPubKey() if pubKey == nil { @@ -271,7 +271,7 @@ func DefaultSigVerificationGasConsumer( switch pubkey := pubkey.(type) { case ed25519.PubKeyEd25519: meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519") - return abciResult(std.ErrInvalidPubKey("ED25519 public keys are unsupported")) + return sdk.Result{} case secp256k1.PubKeySecp256k1: meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1") diff --git a/tm2/pkg/sdk/auth/ante_test.go b/tm2/pkg/sdk/auth/ante_test.go index 7c6ace51e4e..430954a0867 100644 --- a/tm2/pkg/sdk/auth/ante_test.go +++ b/tm2/pkg/sdk/auth/ante_test.go @@ -623,7 +623,7 @@ func TestProcessPubKey(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - _, err := ProcessPubKey(tt.args.acc, tt.args.sig, tt.args.simulate) + _, err := ProcessPubKey(tt.args.acc, tt.args.sig) require.Equal(t, tt.wantErr, !err.IsOK()) }) } @@ -655,7 +655,7 @@ func TestConsumeSignatureVerificationGas(t *testing.T) { gasConsumed int64 shouldErr bool }{ - {"PubKeyEd25519", args{store.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, DefaultSigVerifyCostED25519, true}, + {"PubKeyEd25519", args{store.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, DefaultSigVerifyCostED25519, false}, {"PubKeySecp256k1", args{store.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, DefaultSigVerifyCostSecp256k1, false}, {"Multisig", args{store.NewInfiniteGasMeter(), amino.MustMarshal(multisignature1), multisigKey1, params}, expectedCost1, false}, {"unknown key", args{store.NewInfiniteGasMeter(), nil, nil, params}, 0, true}, From a57311bd67984628eaec5206698e26d7f58b27b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20=C5=BDivkovi=C4=87?= Date: Fri, 10 Jan 2025 00:27:24 +0100 Subject: [PATCH 2/3] fix: re-enable the portal loop CI (#3474) ## Description This PR re-enables the portal loop "CI". I won't go into details on why this was needed in the first place, with the intention to not lose absolutely all credibility for our deployment and testing workflows --- .github/workflows/portal-loop.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/portal-loop.yml b/.github/workflows/portal-loop.yml index aeb59d4dc77..b5cafa459a7 100644 --- a/.github/workflows/portal-loop.yml +++ b/.github/workflows/portal-loop.yml @@ -45,7 +45,6 @@ jobs: labels: ${{ steps.meta.outputs.labels }} test-portal-loop-docker-compose: - if: ${{ false }} runs-on: ubuntu-latest timeout-minutes: 10 steps: From 1b89166af37dd2ee63f5a30b81769532fd0bb1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20=C5=BDivkovi=C4=87?= Date: Fri, 10 Jan 2025 00:40:28 +0100 Subject: [PATCH 3/3] fix: use the `genesis/genesis_txs.jsonl` for the portal loop (#3475) ## Description This PR specifies the base file for the Portal Loop genesis transactions, as it is empty by default. --- misc/loop/scripts/start.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/misc/loop/scripts/start.sh b/misc/loop/scripts/start.sh index fd753324f5d..bdabd2ac40f 100755 --- a/misc/loop/scripts/start.sh +++ b/misc/loop/scripts/start.sh @@ -11,10 +11,11 @@ GENESIS_BALANCES_FILE=${GENESIS_BALANCES_FILE:-""} SEEDS=${SEEDS:-""} PERSISTENT_PEERS=${PERSISTENT_PEERS:-""} +FINAL_GENESIS_TXS_SHEET="/gnoroot/gno.land/genesis/genesis_txs.jsonl" -echo "" >> /gnoroot/gno.land/genesis/genesis_txs.jsonl +echo "" >> $FINAL_GENESIS_TXS_SHEET echo "" >> /gnoroot/gno.land/genesis/genesis_balances.jsonl -cat "${GENESIS_BACKUP_FILE}" >> /gnoroot/gno.land/genesis/genesis_txs.jsonl +cat "${GENESIS_BACKUP_FILE}" >> $FINAL_GENESIS_TXS_SHEET cat "${GENESIS_BALANCES_FILE}" >> /gnoroot/gno.land/genesis/genesis_balances.jsonl # Initialize the secrets @@ -35,6 +36,7 @@ gnoland config set p2p.persistent_peers "${PERSISTENT_PEERS}" # reading and piping to the gnoland genesis commands exec gnoland start \ --chainid="${CHAIN_ID}" \ + --genesis-txs-file="${FINAL_GENESIS_TXS_SHEET}" \ --lazy \ --skip-failing-genesis-txs \ --skip-genesis-sig-verification