From f01ad7695258b6e7593cc8a25a02ae1426608c03 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Tue, 10 Oct 2023 20:32:08 +0200
Subject: [PATCH 01/38] wip: gnoland inmemory
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/gnoland/app.go | 55 ++++-
gno.land/pkg/gnoland/inmemory.go | 326 ++++++++++++++++++++++++++
gno.land/pkg/gnoland/inmemory_test.go | 16 ++
gno.land/pkg/gnoland/types.go | 22 ++
4 files changed, 410 insertions(+), 9 deletions(-)
create mode 100644 gno.land/pkg/gnoland/inmemory.go
create mode 100644 gno.land/pkg/gnoland/inmemory_test.go
diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go
index 3585f99d7de..fab57472fcd 100644
--- a/gno.land/pkg/gnoland/app.go
+++ b/gno.land/pkg/gnoland/app.go
@@ -1,11 +1,14 @@
package gnoland
import (
+ "errors"
"fmt"
"os"
"os/exec"
"path/filepath"
+ "runtime"
"strings"
+ "sync"
"github.com/gnolang/gno/gno.land/pkg/sdk/vm"
"github.com/gnolang/gno/tm2/pkg/amino"
@@ -36,7 +39,7 @@ func NewAppOptions() *AppOptions {
return &AppOptions{
Logger: log.NewNopLogger(),
DB: dbm.NewMemDB(),
- GnoRootDir: GuessGnoRootDir(),
+ GnoRootDir: MustGuessGnoRootDir(),
}
}
@@ -73,6 +76,8 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) {
// Construct keepers.
acctKpr := auth.NewAccountKeeper(mainKey, ProtoGnoAccount)
bankKpr := bank.NewBankKeeper(acctKpr)
+
+ // XXX: Embed this ?
stdlibsDir := filepath.Join(cfg.GnoRootDir, "gnovm", "stdlibs")
vmKpr := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr, stdlibsDir, cfg.MaxCycles)
@@ -195,24 +200,56 @@ func EndBlocker(vmk vm.VMKeeperI) func(ctx sdk.Context, req abci.RequestEndBlock
}
}
-func GuessGnoRootDir() string {
- var rootdir string
+var (
+ guessOnce sync.Once
+ gnoroot string
+)
+
+func MustGuessGnoRootDir() string {
+ root, err := guessGnoRootDir()
+ if err != nil {
+ panic(err)
+ }
+
+ return root
+}
+
+func GuessGnoRootDir() (string, error) {
+ var err error
+ guessOnce.Do(func() {
+ gnoroot, err = guessGnoRootDir()
+ })
+
+ return gnoroot, err
+}
+func guessGnoRootDir() (string, error) {
// First try to get the root directory from the GNOROOT environment variable.
- if rootdir = os.Getenv("GNOROOT"); rootdir != "" {
- return filepath.Clean(rootdir)
+ if rootdir := os.Getenv("GNOROOT"); rootdir != "" {
+ return filepath.Clean(rootdir), nil
}
+ // Try to guess GNOROOT using the nearest go.mod.
if gobin, err := exec.LookPath("go"); err == nil {
// If GNOROOT is not set, try to guess the root directory using the `go list` command.
cmd := exec.Command(gobin, "list", "-m", "-mod=mod", "-f", "{{.Dir}}", "github.com/gnolang/gno")
out, err := cmd.CombinedOutput()
- if err != nil {
- panic(fmt.Errorf("invalid gno directory %q: %w", rootdir, err))
+ if err == nil {
+ return strings.TrimSpace(string(out)), nil
}
+ }
- return strings.TrimSpace(string(out))
+ // Try to guess GNOROOT using caller stack.
+ if _, filename, _, ok := runtime.Caller(1); ok && filepath.IsAbs(filename) {
+ if currentDir := filepath.Dir(filename); currentDir != "" {
+ // Gno root directory relative from `app.go` path:
+ // gno/ .. /gno.land/ .. /pkg/ .. /gnoland/app.go
+ rootdir, err := filepath.Abs(filepath.Join(currentDir, "..", "..", ".."))
+ if err == nil {
+ return rootdir, nil
+ }
+ }
}
- panic("no go binary available, unable to determine gno root-dir path")
+ return "", errors.New("unable to guess gno's root-directory")
}
diff --git a/gno.land/pkg/gnoland/inmemory.go b/gno.land/pkg/gnoland/inmemory.go
new file mode 100644
index 00000000000..d1971ad0c8b
--- /dev/null
+++ b/gno.land/pkg/gnoland/inmemory.go
@@ -0,0 +1,326 @@
+package gnoland
+
+import (
+ "errors"
+ "fmt"
+ "time"
+
+ vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm"
+ gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
+ "github.com/gnolang/gno/gnovm/pkg/gnomod"
+ abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
+ "github.com/gnolang/gno/tm2/pkg/bft/config"
+ "github.com/gnolang/gno/tm2/pkg/bft/node"
+ "github.com/gnolang/gno/tm2/pkg/bft/proxy"
+ "github.com/gnolang/gno/tm2/pkg/bft/types"
+ bft "github.com/gnolang/gno/tm2/pkg/bft/types"
+ "github.com/gnolang/gno/tm2/pkg/crypto/ed25519"
+ "github.com/gnolang/gno/tm2/pkg/db"
+ "github.com/gnolang/gno/tm2/pkg/log"
+ "github.com/gnolang/gno/tm2/pkg/p2p"
+ "github.com/gnolang/gno/tm2/pkg/std"
+)
+
+type InMemoryConfig struct {
+ RootDir string
+ ConsensusParams abci.ConsensusParams
+ GenesisValidator []bft.GenesisValidator
+ Packages []PackagePath
+ Balances []Balance
+ GenesisTXs []std.Tx
+ SkipFailingGenesisTxs bool
+ GenesisMaxVMCycles int64
+}
+
+func (im *InMemoryConfig) loadPackages() ([]std.Tx, error) {
+ txs := []std.Tx{}
+ for _, pkg := range im.Packages {
+ tx, err := pkg.load()
+ if err != nil {
+ return nil, fmt.Errorf("unable to load packages: %w", err)
+ }
+ txs = append(txs, tx...)
+
+ }
+ return txs, nil
+}
+
+func NewInMemory(logger log.Logger, icfg InMemoryConfig) (*node.Node, error) {
+ if icfg.RootDir == "" {
+ // XXX: Should return an error here ?
+ icfg.RootDir = MustGuessGnoRootDir()
+ }
+
+ // Setup testing config
+ cfg := config.TestConfig().SetRootDir(icfg.RootDir)
+ {
+ cfg.EnsureDirs()
+ cfg.Consensus.CreateEmptyBlocks = true
+ cfg.Consensus.CreateEmptyBlocksInterval = time.Duration(0)
+ cfg.RPC.ListenAddress = "tcp://127.0.0.1:0"
+ cfg.P2P.ListenAddress = "tcp://127.0.0.1:0"
+ }
+
+ // use mocked pv
+ nodekey := &p2p.NodeKey{
+ PrivKey: ed25519.GenPrivKey(),
+ }
+ priv := bft.NewMockPVWithParams(nodekey.PrivKey, false, false)
+
+ // setup geeneis
+ gen := &bft.GenesisDoc{}
+ {
+
+ gen.GenesisTime = time.Now()
+
+ // cfg.chainID = "tendermint_test"
+ gen.ChainID = cfg.ChainID()
+
+ // XXX(gfanton): Is some a default needed here ?
+ // if icfg.ConsensusParams.Block == nil {
+ // icfg.ConsensusParams.Block = &abci.BlockParams{
+ // // TODO: update limits based on config
+ // MaxTxBytes: 1000000, // 1MB,
+ // MaxDataBytes: 2000000, // 2MB,
+ // MaxGas: 10000000, // 10M gas
+ // TimeIotaMS: 100, // 100ms
+ // }
+ // }
+ gen.ConsensusParams = icfg.ConsensusParams
+
+ pk := priv.GetPubKey()
+ gen.Validators = []bft.GenesisValidator{
+ {
+ Address: pk.Address(),
+ PubKey: pk,
+ Power: 10,
+ Name: "testvalidator",
+ },
+ }
+
+ for _, validator := range icfg.GenesisValidator {
+ gen.Validators = append(gen.Validators, validator)
+ }
+ }
+
+ txs, err := icfg.loadPackages()
+ if err != nil {
+ return nil, fmt.Errorf("uanble to load genesis packages: %w", err)
+ }
+
+ txs = append(txs, icfg.GenesisTXs...)
+
+ gen.AppState = GnoGenesisState{
+ Balances: Balances(icfg.Balances).Strings(),
+ Txs: txs,
+ }
+
+ gnoApp, err := NewAppWithOptions(&AppOptions{
+ Logger: logger,
+ GnoRootDir: icfg.RootDir,
+ SkipFailingGenesisTxs: icfg.SkipFailingGenesisTxs,
+ MaxCycles: icfg.GenesisMaxVMCycles,
+ DB: db.NewMemDB(),
+ })
+ if err != nil {
+ return nil, fmt.Errorf("error in creating new app: %w", err)
+ }
+
+ cfg.LocalApp = gnoApp
+
+ // Get app client creator.
+ appClientCreator := proxy.DefaultClientCreator(
+ cfg.LocalApp,
+ cfg.ProxyApp,
+ cfg.ABCI,
+ cfg.DBDir(),
+ )
+
+ // Create genesis factory.
+ genProvider := func() (*types.GenesisDoc, error) {
+ return gen, nil
+ }
+
+ return node.NewNode(cfg,
+ priv, nodekey,
+ appClientCreator,
+ genProvider,
+ node.DefaultDBProvider,
+ logger,
+ )
+}
+
+type PackagePath struct {
+ Creator bft.Address
+ Deposit std.Coins
+ Fee std.Fee
+ Path string
+}
+
+func (p PackagePath) load() ([]std.Tx, error) {
+ if p.Creator.IsZero() {
+ return nil, errors.New("empty creator address")
+ }
+
+ if p.Path == "" {
+ return nil, errors.New("empty package path")
+ }
+
+ // list all packages from target path
+ pkgs, err := gnomod.ListPkgs(p.Path)
+ if err != nil {
+ return nil, fmt.Errorf("listing gno packages: %w", err)
+ }
+
+ // Sort packages by dependencies.
+ sortedPkgs, err := pkgs.Sort()
+ if err != nil {
+ return nil, fmt.Errorf("sorting packages: %w", err)
+ }
+
+ // Filter out draft packages.
+ nonDraftPkgs := sortedPkgs.GetNonDraftPkgs()
+ txs := []std.Tx{}
+ for _, pkg := range nonDraftPkgs {
+ // open files in directory as MemPackage.
+ memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name)
+
+ // create transaction
+ tx := std.Tx{
+ Fee: p.Fee,
+ Msgs: []std.Msg{
+ vmm.MsgAddPackage{
+ Creator: p.Creator,
+ Package: memPkg,
+ // XXX: add deposit option
+ Deposit: p.Deposit,
+ },
+ },
+ }
+
+ tx.Signatures = make([]std.Signature, len(tx.GetSigners()))
+ txs = append(txs, tx)
+ }
+
+ return txs, nil
+}
+
+func WaitForReadiness(n *node.Node) <-chan struct{} {
+ go func() {
+
+ }()
+}
+
+// func loadGenesisTxs(
+// path string,
+// chainID string,
+// genesisRemote string,
+// ) []std.Tx {
+// txs := []std.Tx{}
+// txsBz := osm.MustReadFile(path)
+// txsLines := strings.Split(string(txsBz), "\n")
+// for _, txLine := range txsLines {
+// if txLine == "" {
+// continue // skip empty line
+// }
+
+// // patch the TX
+// txLine = strings.ReplaceAll(txLine, "%%CHAINID%%", chainID)
+// txLine = strings.ReplaceAll(txLine, "%%REMOTE%%", genesisRemote)
+
+// var tx std.Tx
+// amino.MustUnmarshalJSON([]byte(txLine), &tx)
+// txs = append(txs, tx)
+// }
+
+// return txs
+// }
+
+// func setupTestingGenesis(gnoDataDir string, cfg *config.Config, icfg *IntegrationConfig) error {
+// genesisFilePath := filepath.Join(gnoDataDir, cfg.Genesis)
+// osm.EnsureDir(filepath.Dir(genesisFilePath), 0o700)
+// if !osm.FileExists(genesisFilePath) {
+// genesisTxs := loadGenesisTxs(icfg.GenesisTxsFile, icfg.ChainID, icfg.GenesisRemote)
+// pvPub := priv.GetPubKey()
+
+// gen := &bft.GenesisDoc{
+// GenesisTime: time.Now(),
+// ChainID: icfg.ChainID,
+// ConsensusParams: abci.ConsensusParams{
+// Block: &abci.BlockParams{
+// // TODO: update limits.
+// MaxTxBytes: 1000000, // 1MB,
+// MaxDataBytes: 2000000, // 2MB,
+// MaxGas: 10000000, // 10M gas
+// TimeIotaMS: 100, // 100ms
+// },
+// },
+// Validators: []bft.GenesisValidator{
+// {
+// Address: pvPub.Address(),
+// PubKey: pvPub,
+// Power: 10,
+// Name: "testvalidator",
+// },
+// },
+// }
+
+// // Load distribution.
+// balances := loadGenesisBalances(icfg.GenesisBalancesFile)
+
+// // Load initial packages from examples.
+// // XXX: we should be able to config this
+// test1 := crypto.MustAddressFromString(test1Addr)
+// txs := []std.Tx{}
+
+// // List initial packages to load from examples.
+// // println(filepath.Join(gnoRootDir, "examples"))
+
+// // load genesis txs from file.
+// txs = append(txs, genesisTxs...)
+
+// // construct genesis AppState.
+// gen.AppState = GnoGenesisState{
+// Balances: balances,
+// Txs: txs,
+// }
+
+// writeGenesisFile(gen, genesisFilePath)
+// }
+
+// return nil
+// }
+
+// func loadGenesisBalances(path string) []string {
+// // each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot
+// balances := []string{}
+// content := osm.MustReadFile(path)
+// lines := strings.Split(string(content), "\n")
+// for _, line := range lines {
+// line = strings.TrimSpace(line)
+
+// // remove comments.
+// line = strings.Split(line, "#")[0]
+// line = strings.TrimSpace(line)
+
+// // skip empty lines.
+// if line == "" {
+// continue
+// }
+
+// parts := strings.Split(line, "=")
+// if len(parts) != 2 {
+// panic("invalid genesis_balance line: " + line)
+// }
+
+// balances = append(balances, line)
+// }
+// return balances
+// }
+
+// func writeGenesisFile(gen *bft.GenesisDoc, filePath string) {
+// err := gen.SaveAs(filePath)
+// if err != nil {
+// panic(err)
+// }
+// }
diff --git a/gno.land/pkg/gnoland/inmemory_test.go b/gno.land/pkg/gnoland/inmemory_test.go
new file mode 100644
index 00000000000..9c2b79dab7d
--- /dev/null
+++ b/gno.land/pkg/gnoland/inmemory_test.go
@@ -0,0 +1,16 @@
+package gnoland
+
+import (
+ "testing"
+
+ "github.com/gnolang/gno/tm2/pkg/log"
+ "github.com/jaekwon/testify/require"
+)
+
+func TestNewInMemory(t *testing.T) {
+ logger := log.TestingLogger()
+
+ node, err := NewInMemory(logger, InMemoryConfig{})
+ require.NoError(t, err)
+ require.NotNil(t, node)
+}
diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go
index 1c762366ae9..463638d5901 100644
--- a/gno.land/pkg/gnoland/types.go
+++ b/gno.land/pkg/gnoland/types.go
@@ -1,6 +1,9 @@
package gnoland
import (
+ "fmt"
+
+ bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/std"
)
@@ -16,3 +19,22 @@ type GnoGenesisState struct {
Balances []string `json:"balances"`
Txs []std.Tx `json:"txs"`
}
+
+type Balance struct {
+ Address bft.Address
+ Value std.Coin
+}
+
+func (b Balance) String() string {
+ return fmt.Sprintf("%s=%s", b.Address.String(), b.Value.String())
+}
+
+type Balances []Balance
+
+func (bs Balances) Strings() []string {
+ bss := make([]string, len(bs))
+ for i, balance := range bs {
+ bss[i] = balance.String()
+ }
+ return bss
+}
From db5a4c2fae7370bc067a836f2b3f586d27fa9311 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Wed, 11 Oct 2023 22:20:31 +0200
Subject: [PATCH 02/38] Revert "fix(make): disable _test.gnoweb temporarily
(#1223)"
This reverts commit dce345f31b8fc6be3e831778983345d36f01e31f.
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
.github/workflows/gnoland.yml | 8 +++-----
gno.land/Makefile | 4 +---
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/gnoland.yml b/.github/workflows/gnoland.yml
index 95cb5fa8ce0..2b38f254a13 100644
--- a/.github/workflows/gnoland.yml
+++ b/.github/workflows/gnoland.yml
@@ -60,9 +60,7 @@ jobs:
- _test.gnoland
- _test.gnokey
- _test.pkgs
- # XXX: test broken, should be rewritten to run an inmemory localnode
- # Re-add to makefile when fixed. Tracked here: https://github.com/gnolang/gno/issues/1222
- #- _test.gnoweb
+ #- _test.gnoweb # this test should be rewritten to run an inmemory localnode
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
@@ -78,7 +76,7 @@ jobs:
export LOG_DIR="${{ runner.temp }}/logs/test-${{ matrix.goversion }}-gnoland"
make ${{ matrix.args }}
- name: Upload Test Log
- if: always()
+ if: always()
uses: actions/upload-artifact@v3
with:
name: logs-test-gnoland-go${{ matrix.goversion }}
@@ -101,7 +99,7 @@ jobs:
uses: codecov/codecov-action@v3
with:
directory: ${{ runner.temp }}/coverage
- token: ${{ secrets.CODECOV_TOKEN }}
+ token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: ${{ github.repository == 'gnolang/gno' }}
docker-integration:
diff --git a/gno.land/Makefile b/gno.land/Makefile
index 1fd1aaa1f78..e794bb58174 100644
--- a/gno.land/Makefile
+++ b/gno.land/Makefile
@@ -43,9 +43,7 @@ fmt:
########################################
# Test suite
.PHONY: test
-test: _test.gnoland _test.gnokey _test.pkgs
-# XXX: _test.gnoweb is currently disabled. If fixed, re-enable here and in CI.
-# https://github.com/gnolang/gno/issues/1222
+test: _test.gnoland _test.gnoweb _test.gnokey _test.pkgs
GOTEST_FLAGS ?= -v -p 1 -timeout=30m
From 3b71cc6acd2ec44c916c0ab6c7b3338f751bfd75 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 12 Oct 2023 17:26:24 +0200
Subject: [PATCH 03/38] feat: add integration node
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/gnoland/app.go | 5 +-
gno.land/pkg/gnoland/genesis.go | 79 ++++
gno.land/pkg/gnoland/inmemory.go | 326 -----------------
gno.land/pkg/gnoland/node.go | 115 ++++++
gno.land/pkg/gnoland/types.go | 53 ++-
gno.land/pkg/integration/gnoland.go | 336 ------------------
gno.land/pkg/integration/node.go | 206 +++++++++++
gno.land/pkg/integration/node_inmemory.go | 5 +
.../node_test.go} | 4 +-
.../pkg/integration/testing_integration.go | 81 ++++-
10 files changed, 526 insertions(+), 684 deletions(-)
create mode 100644 gno.land/pkg/gnoland/genesis.go
delete mode 100644 gno.land/pkg/gnoland/inmemory.go
create mode 100644 gno.land/pkg/gnoland/node.go
delete mode 100644 gno.land/pkg/integration/gnoland.go
create mode 100644 gno.land/pkg/integration/node.go
create mode 100644 gno.land/pkg/integration/node_inmemory.go
rename gno.land/pkg/{gnoland/inmemory_test.go => integration/node_test.go} (76%)
diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go
index fab57472fcd..6ac13d4ff99 100644
--- a/gno.land/pkg/gnoland/app.go
+++ b/gno.land/pkg/gnoland/app.go
@@ -147,10 +147,9 @@ func InitChainer(baseApp *sdk.BaseApp, acctKpr auth.AccountKeeperI, bankKpr bank
genState := req.AppState.(GnoGenesisState)
// Parse and set genesis state balances.
for _, bal := range genState.Balances {
- addr, coins := parseBalance(bal)
- acc := acctKpr.NewAccountWithAddress(ctx, addr)
+ acc := acctKpr.NewAccountWithAddress(ctx, bal.Address)
acctKpr.SetAccount(ctx, acc)
- err := bankKpr.SetCoins(ctx, addr, coins)
+ err := bankKpr.SetCoins(ctx, bal.Address, bal.Value)
if err != nil {
panic(err)
}
diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go
new file mode 100644
index 00000000000..b155b212219
--- /dev/null
+++ b/gno.land/pkg/gnoland/genesis.go
@@ -0,0 +1,79 @@
+package gnoland
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+
+ "github.com/gnolang/gno/tm2/pkg/amino"
+ "github.com/gnolang/gno/tm2/pkg/crypto"
+ osm "github.com/gnolang/gno/tm2/pkg/os"
+ "github.com/gnolang/gno/tm2/pkg/std"
+)
+
+func LoadGenesisBalancesFile(path string) ([]Balance, error) {
+ // each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot
+ content := osm.MustReadFile(path)
+ lines := strings.Split(string(content), "\n")
+
+ balances := make([]Balance, 0, len(lines))
+ for _, line := range lines {
+ line = strings.TrimSpace(line)
+
+ // remove comments.
+ line = strings.Split(line, "#")[0]
+ line = strings.TrimSpace(line)
+
+ // skip empty lines.
+ if line == "" {
+ continue
+ }
+
+ parts := strings.Split(line, "=") //
=
+ if len(parts) != 2 {
+ return nil, errors.New("invalid genesis_balance line: " + line)
+ }
+
+ addr, err := crypto.AddressFromBech32(parts[0])
+ if err != nil {
+ return nil, fmt.Errorf("invalid balance addr %s: %w", parts[0], err)
+ }
+
+ coins, err := std.ParseCoins(parts[1])
+ if err != nil {
+ return nil, fmt.Errorf("invalid balance coins %s: %w", parts[1], err)
+ }
+
+ balances = append(balances, Balance{
+ Address: addr,
+ Value: coins,
+ })
+ }
+
+ return balances, nil
+}
+
+// XXX: we can do something better here
+func LoadGenesisTxsFile(path string, chainID string, genesisRemote string) ([]std.Tx, error) {
+ txs := []std.Tx{}
+ txsBz := osm.MustReadFile(path)
+ txsLines := strings.Split(string(txsBz), "\n")
+ for _, txLine := range txsLines {
+ if txLine == "" {
+ continue // Skip empty line.
+ }
+
+ // Patch the TX.
+ txLine = strings.ReplaceAll(txLine, "%%CHAINID%%", chainID)
+ txLine = strings.ReplaceAll(txLine, "%%REMOTE%%", genesisRemote)
+
+ var tx std.Tx
+ if err := amino.UnmarshalJSON([]byte(txLine), &tx); err != nil {
+ return nil, fmt.Errorf("unable to Unmarshall txs file: %w", err)
+ }
+
+ txs = append(txs, tx)
+ }
+
+ return txs, nil
+}
diff --git a/gno.land/pkg/gnoland/inmemory.go b/gno.land/pkg/gnoland/inmemory.go
deleted file mode 100644
index d1971ad0c8b..00000000000
--- a/gno.land/pkg/gnoland/inmemory.go
+++ /dev/null
@@ -1,326 +0,0 @@
-package gnoland
-
-import (
- "errors"
- "fmt"
- "time"
-
- vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm"
- gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
- "github.com/gnolang/gno/gnovm/pkg/gnomod"
- abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
- "github.com/gnolang/gno/tm2/pkg/bft/config"
- "github.com/gnolang/gno/tm2/pkg/bft/node"
- "github.com/gnolang/gno/tm2/pkg/bft/proxy"
- "github.com/gnolang/gno/tm2/pkg/bft/types"
- bft "github.com/gnolang/gno/tm2/pkg/bft/types"
- "github.com/gnolang/gno/tm2/pkg/crypto/ed25519"
- "github.com/gnolang/gno/tm2/pkg/db"
- "github.com/gnolang/gno/tm2/pkg/log"
- "github.com/gnolang/gno/tm2/pkg/p2p"
- "github.com/gnolang/gno/tm2/pkg/std"
-)
-
-type InMemoryConfig struct {
- RootDir string
- ConsensusParams abci.ConsensusParams
- GenesisValidator []bft.GenesisValidator
- Packages []PackagePath
- Balances []Balance
- GenesisTXs []std.Tx
- SkipFailingGenesisTxs bool
- GenesisMaxVMCycles int64
-}
-
-func (im *InMemoryConfig) loadPackages() ([]std.Tx, error) {
- txs := []std.Tx{}
- for _, pkg := range im.Packages {
- tx, err := pkg.load()
- if err != nil {
- return nil, fmt.Errorf("unable to load packages: %w", err)
- }
- txs = append(txs, tx...)
-
- }
- return txs, nil
-}
-
-func NewInMemory(logger log.Logger, icfg InMemoryConfig) (*node.Node, error) {
- if icfg.RootDir == "" {
- // XXX: Should return an error here ?
- icfg.RootDir = MustGuessGnoRootDir()
- }
-
- // Setup testing config
- cfg := config.TestConfig().SetRootDir(icfg.RootDir)
- {
- cfg.EnsureDirs()
- cfg.Consensus.CreateEmptyBlocks = true
- cfg.Consensus.CreateEmptyBlocksInterval = time.Duration(0)
- cfg.RPC.ListenAddress = "tcp://127.0.0.1:0"
- cfg.P2P.ListenAddress = "tcp://127.0.0.1:0"
- }
-
- // use mocked pv
- nodekey := &p2p.NodeKey{
- PrivKey: ed25519.GenPrivKey(),
- }
- priv := bft.NewMockPVWithParams(nodekey.PrivKey, false, false)
-
- // setup geeneis
- gen := &bft.GenesisDoc{}
- {
-
- gen.GenesisTime = time.Now()
-
- // cfg.chainID = "tendermint_test"
- gen.ChainID = cfg.ChainID()
-
- // XXX(gfanton): Is some a default needed here ?
- // if icfg.ConsensusParams.Block == nil {
- // icfg.ConsensusParams.Block = &abci.BlockParams{
- // // TODO: update limits based on config
- // MaxTxBytes: 1000000, // 1MB,
- // MaxDataBytes: 2000000, // 2MB,
- // MaxGas: 10000000, // 10M gas
- // TimeIotaMS: 100, // 100ms
- // }
- // }
- gen.ConsensusParams = icfg.ConsensusParams
-
- pk := priv.GetPubKey()
- gen.Validators = []bft.GenesisValidator{
- {
- Address: pk.Address(),
- PubKey: pk,
- Power: 10,
- Name: "testvalidator",
- },
- }
-
- for _, validator := range icfg.GenesisValidator {
- gen.Validators = append(gen.Validators, validator)
- }
- }
-
- txs, err := icfg.loadPackages()
- if err != nil {
- return nil, fmt.Errorf("uanble to load genesis packages: %w", err)
- }
-
- txs = append(txs, icfg.GenesisTXs...)
-
- gen.AppState = GnoGenesisState{
- Balances: Balances(icfg.Balances).Strings(),
- Txs: txs,
- }
-
- gnoApp, err := NewAppWithOptions(&AppOptions{
- Logger: logger,
- GnoRootDir: icfg.RootDir,
- SkipFailingGenesisTxs: icfg.SkipFailingGenesisTxs,
- MaxCycles: icfg.GenesisMaxVMCycles,
- DB: db.NewMemDB(),
- })
- if err != nil {
- return nil, fmt.Errorf("error in creating new app: %w", err)
- }
-
- cfg.LocalApp = gnoApp
-
- // Get app client creator.
- appClientCreator := proxy.DefaultClientCreator(
- cfg.LocalApp,
- cfg.ProxyApp,
- cfg.ABCI,
- cfg.DBDir(),
- )
-
- // Create genesis factory.
- genProvider := func() (*types.GenesisDoc, error) {
- return gen, nil
- }
-
- return node.NewNode(cfg,
- priv, nodekey,
- appClientCreator,
- genProvider,
- node.DefaultDBProvider,
- logger,
- )
-}
-
-type PackagePath struct {
- Creator bft.Address
- Deposit std.Coins
- Fee std.Fee
- Path string
-}
-
-func (p PackagePath) load() ([]std.Tx, error) {
- if p.Creator.IsZero() {
- return nil, errors.New("empty creator address")
- }
-
- if p.Path == "" {
- return nil, errors.New("empty package path")
- }
-
- // list all packages from target path
- pkgs, err := gnomod.ListPkgs(p.Path)
- if err != nil {
- return nil, fmt.Errorf("listing gno packages: %w", err)
- }
-
- // Sort packages by dependencies.
- sortedPkgs, err := pkgs.Sort()
- if err != nil {
- return nil, fmt.Errorf("sorting packages: %w", err)
- }
-
- // Filter out draft packages.
- nonDraftPkgs := sortedPkgs.GetNonDraftPkgs()
- txs := []std.Tx{}
- for _, pkg := range nonDraftPkgs {
- // open files in directory as MemPackage.
- memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name)
-
- // create transaction
- tx := std.Tx{
- Fee: p.Fee,
- Msgs: []std.Msg{
- vmm.MsgAddPackage{
- Creator: p.Creator,
- Package: memPkg,
- // XXX: add deposit option
- Deposit: p.Deposit,
- },
- },
- }
-
- tx.Signatures = make([]std.Signature, len(tx.GetSigners()))
- txs = append(txs, tx)
- }
-
- return txs, nil
-}
-
-func WaitForReadiness(n *node.Node) <-chan struct{} {
- go func() {
-
- }()
-}
-
-// func loadGenesisTxs(
-// path string,
-// chainID string,
-// genesisRemote string,
-// ) []std.Tx {
-// txs := []std.Tx{}
-// txsBz := osm.MustReadFile(path)
-// txsLines := strings.Split(string(txsBz), "\n")
-// for _, txLine := range txsLines {
-// if txLine == "" {
-// continue // skip empty line
-// }
-
-// // patch the TX
-// txLine = strings.ReplaceAll(txLine, "%%CHAINID%%", chainID)
-// txLine = strings.ReplaceAll(txLine, "%%REMOTE%%", genesisRemote)
-
-// var tx std.Tx
-// amino.MustUnmarshalJSON([]byte(txLine), &tx)
-// txs = append(txs, tx)
-// }
-
-// return txs
-// }
-
-// func setupTestingGenesis(gnoDataDir string, cfg *config.Config, icfg *IntegrationConfig) error {
-// genesisFilePath := filepath.Join(gnoDataDir, cfg.Genesis)
-// osm.EnsureDir(filepath.Dir(genesisFilePath), 0o700)
-// if !osm.FileExists(genesisFilePath) {
-// genesisTxs := loadGenesisTxs(icfg.GenesisTxsFile, icfg.ChainID, icfg.GenesisRemote)
-// pvPub := priv.GetPubKey()
-
-// gen := &bft.GenesisDoc{
-// GenesisTime: time.Now(),
-// ChainID: icfg.ChainID,
-// ConsensusParams: abci.ConsensusParams{
-// Block: &abci.BlockParams{
-// // TODO: update limits.
-// MaxTxBytes: 1000000, // 1MB,
-// MaxDataBytes: 2000000, // 2MB,
-// MaxGas: 10000000, // 10M gas
-// TimeIotaMS: 100, // 100ms
-// },
-// },
-// Validators: []bft.GenesisValidator{
-// {
-// Address: pvPub.Address(),
-// PubKey: pvPub,
-// Power: 10,
-// Name: "testvalidator",
-// },
-// },
-// }
-
-// // Load distribution.
-// balances := loadGenesisBalances(icfg.GenesisBalancesFile)
-
-// // Load initial packages from examples.
-// // XXX: we should be able to config this
-// test1 := crypto.MustAddressFromString(test1Addr)
-// txs := []std.Tx{}
-
-// // List initial packages to load from examples.
-// // println(filepath.Join(gnoRootDir, "examples"))
-
-// // load genesis txs from file.
-// txs = append(txs, genesisTxs...)
-
-// // construct genesis AppState.
-// gen.AppState = GnoGenesisState{
-// Balances: balances,
-// Txs: txs,
-// }
-
-// writeGenesisFile(gen, genesisFilePath)
-// }
-
-// return nil
-// }
-
-// func loadGenesisBalances(path string) []string {
-// // each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot
-// balances := []string{}
-// content := osm.MustReadFile(path)
-// lines := strings.Split(string(content), "\n")
-// for _, line := range lines {
-// line = strings.TrimSpace(line)
-
-// // remove comments.
-// line = strings.Split(line, "#")[0]
-// line = strings.TrimSpace(line)
-
-// // skip empty lines.
-// if line == "" {
-// continue
-// }
-
-// parts := strings.Split(line, "=")
-// if len(parts) != 2 {
-// panic("invalid genesis_balance line: " + line)
-// }
-
-// balances = append(balances, line)
-// }
-// return balances
-// }
-
-// func writeGenesisFile(gen *bft.GenesisDoc, filePath string) {
-// err := gen.SaveAs(filePath)
-// if err != nil {
-// panic(err)
-// }
-// }
diff --git a/gno.land/pkg/gnoland/node.go b/gno.land/pkg/gnoland/node.go
new file mode 100644
index 00000000000..d9e54f35cd7
--- /dev/null
+++ b/gno.land/pkg/gnoland/node.go
@@ -0,0 +1,115 @@
+package gnoland
+
+// func loadGenesisTxs(
+// path string,
+// chainID string,
+// genesisRemote string,
+// ) []std.Tx {
+// txs := []std.Tx{}
+// txsBz := osm.MustReadFile(path)
+// txsLines := strings.Split(string(txsBz), "\n")
+// for _, txLine := range txsLines {
+// if txLine == "" {
+// continue // skip empty line
+// }
+
+// // patch the TX
+// txLine = strings.ReplaceAll(txLine, "%%CHAINID%%", chainID)
+// txLine = strings.ReplaceAll(txLine, "%%REMOTE%%", genesisRemote)
+
+// var tx std.Tx
+// amino.MustUnmarshalJSON([]byte(txLine), &tx)
+// txs = append(txs, tx)
+// }
+
+// return txs
+// }
+
+// func setupTestingGenesis(gnoDataDir string, cfg *config.Config, icfg *IntegrationConfig) error {
+// genesisFilePath := filepath.Join(gnoDataDir, cfg.Genesis)
+// osm.EnsureDir(filepath.Dir(genesisFilePath), 0o700)
+// if !osm.FileExists(genesisFilePath) {
+// genesisTxs := loadGenesisTxs(icfg.GenesisTxsFile, icfg.ChainID, icfg.GenesisRemote)
+// pvPub := priv.GetPubKey()
+
+// gen := &bft.GenesisDoc{
+// GenesisTime: time.Now(),
+// ChainID: icfg.ChainID,
+// ConsensusParams: abci.ConsensusParams{
+// Block: &abci.BlockParams{
+// // TODO: update limits.
+// MaxTxBytes: 1000000, // 1MB,
+// MaxDataBytes: 2000000, // 2MB,
+// MaxGas: 10000000, // 10M gas
+// TimeIotaMS: 100, // 100ms
+// },
+// },
+// Validators: []bft.GenesisValidator{
+// {
+// Address: pvPub.Address(),
+// PubKey: pvPub,
+// Power: 10,
+// Name: "testvalidator",
+// },
+// },
+// }
+
+// // Load distribution.
+// balances := loadGenesisBalances(icfg.GenesisBalancesFile)
+
+// // Load initial packages from examples.
+// // XXX: we should be able to config this
+// test1 := crypto.MustAddressFromString(test1Addr)
+// txs := []std.Tx{}
+
+// // List initial packages to load from examples.
+// // println(filepath.Join(gnoRootDir, "examples"))
+
+// // load genesis txs from file.
+// txs = append(txs, genesisTxs...)
+
+// // construct genesis AppState.
+// gen.AppState = GnoGenesisState{
+// Balances: balances,
+// Txs: txs,
+// }
+
+// writeGenesisFile(gen, genesisFilePath)
+// }
+
+// return nil
+// }
+
+// func loadGenesisBalances(path string) []string {
+// // each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot
+// balances := []string{}
+// content := osm.MustReadFile(path)
+// lines := strings.Split(string(content), "\n")
+// for _, line := range lines {
+// line = strings.TrimSpace(line)
+
+// // remove comments.
+// line = strings.Split(line, "#")[0]
+// line = strings.TrimSpace(line)
+
+// // skip empty lines.
+// if line == "" {
+// continue
+// }
+
+// parts := strings.Split(line, "=")
+// if len(parts) != 2 {
+// panic("invalid genesis_balance line: " + line)
+// }
+
+// balances = append(balances, line)
+// }
+// return balances
+// }
+
+// func writeGenesisFile(gen *bft.GenesisDoc, filePath string) {
+// err := gen.SaveAs(filePath)
+// if err != nil {
+// panic(err)
+// }
+// }
diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go
index 463638d5901..721f2c726f2 100644
--- a/gno.land/pkg/gnoland/types.go
+++ b/gno.land/pkg/gnoland/types.go
@@ -1,9 +1,12 @@
package gnoland
import (
+ "errors"
"fmt"
+ "strings"
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
+ "github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/std"
)
@@ -16,25 +19,53 @@ func ProtoGnoAccount() std.Account {
}
type GnoGenesisState struct {
- Balances []string `json:"balances"`
- Txs []std.Tx `json:"txs"`
+ Balances []Balance `json:"balances"`
+ Txs []std.Tx `json:"txs"`
}
type Balance struct {
Address bft.Address
- Value std.Coin
+ Value std.Coins
+}
+
+func (b *Balance) Parse(line string) error {
+ parts := strings.Split(strings.TrimSpace(line), "=") // =
+ if len(parts) != 2 {
+ return errors.New("invalid genesis_balance line: " + line)
+ }
+
+ var err error
+
+ b.Address, err = crypto.AddressFromBech32(parts[0])
+ if err != nil {
+ return fmt.Errorf("invalid balance addr %s: %w", parts[0], err)
+ }
+
+ b.Value, err = std.ParseCoins(parts[1])
+ if err != nil {
+ return fmt.Errorf("invalid balance coins %s: %w", parts[1], err)
+ }
+
+ return nil
+}
+
+func (b *Balance) UnmarshalJSON(data []byte) error {
+ return b.Parse(string(data))
+}
+func (b *Balance) Marshaljson() ([]byte, error) {
+ return []byte(b.String()), nil
}
func (b Balance) String() string {
return fmt.Sprintf("%s=%s", b.Address.String(), b.Value.String())
}
-type Balances []Balance
+// type Balances []Balance
-func (bs Balances) Strings() []string {
- bss := make([]string, len(bs))
- for i, balance := range bs {
- bss[i] = balance.String()
- }
- return bss
-}
+// func (bs Balances) Strings() []string {
+// bss := make([]string, len(bs))
+// for i, balance := range bs {
+// bss[i] = balance.String()
+// }
+// return bss
+// }
diff --git a/gno.land/pkg/integration/gnoland.go b/gno.land/pkg/integration/gnoland.go
deleted file mode 100644
index c4fee341bfc..00000000000
--- a/gno.land/pkg/integration/gnoland.go
+++ /dev/null
@@ -1,336 +0,0 @@
-package integration
-
-import (
- "flag"
- "fmt"
- "path/filepath"
- "strings"
- "testing"
- "time"
-
- "github.com/gnolang/gno/gno.land/pkg/gnoland"
- vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm"
- gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
- "github.com/gnolang/gno/gnovm/pkg/gnomod"
- "github.com/gnolang/gno/tm2/pkg/amino"
- abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
- "github.com/gnolang/gno/tm2/pkg/bft/config"
- "github.com/gnolang/gno/tm2/pkg/bft/node"
- "github.com/gnolang/gno/tm2/pkg/bft/privval"
- bft "github.com/gnolang/gno/tm2/pkg/bft/types"
- "github.com/gnolang/gno/tm2/pkg/crypto"
- "github.com/gnolang/gno/tm2/pkg/db"
- "github.com/gnolang/gno/tm2/pkg/log"
- osm "github.com/gnolang/gno/tm2/pkg/os"
- "github.com/gnolang/gno/tm2/pkg/std"
- "github.com/rogpeppe/go-internal/testscript"
-)
-
-type IntegrationConfig struct {
- SkipFailingGenesisTxs bool
- SkipStart bool
- GenesisBalancesFile string
- GenesisTxsFile string
- ChainID string
- GenesisRemote string
- RootDir string
- GenesisMaxVMCycles int64
- Config string
-}
-
-// NOTE: This is a copy of gnoland actual flags.
-// XXX: A lot this make no sense for integration.
-func (c *IntegrationConfig) RegisterFlags(fs *flag.FlagSet) {
- fs.BoolVar(
- &c.SkipFailingGenesisTxs,
- "skip-failing-genesis-txs",
- false,
- "don't panic when replaying invalid genesis txs",
- )
- fs.BoolVar(
- &c.SkipStart,
- "skip-start",
- false,
- "quit after initialization, don't start the node",
- )
-
- fs.StringVar(
- &c.GenesisBalancesFile,
- "genesis-balances-file",
- "./genesis/genesis_balances.txt",
- "initial distribution file",
- )
-
- fs.StringVar(
- &c.GenesisTxsFile,
- "genesis-txs-file",
- "./genesis/genesis_txs.txt",
- "initial txs to replay",
- )
-
- fs.StringVar(
- &c.ChainID,
- "chainid",
- "dev",
- "the ID of the chain",
- )
-
- fs.StringVar(
- &c.RootDir,
- "root-dir",
- "testdir",
- "directory for config and data",
- )
-
- fs.StringVar(
- &c.GenesisRemote,
- "genesis-remote",
- "localhost:26657",
- "replacement for '%%REMOTE%%' in genesis",
- )
-
- fs.Int64Var(
- &c.GenesisMaxVMCycles,
- "genesis-max-vm-cycles",
- 10_000_000,
- "set maximum allowed vm cycles per operation. Zero means no limit.",
- )
-}
-
-func execTestingGnoland(t *testing.T, logger log.Logger, gnoDataDir, gnoRootDir string, args []string) (*node.Node, error) {
- t.Helper()
-
- // Setup start config.
- icfg := &IntegrationConfig{}
- {
- fs := flag.NewFlagSet("start", flag.ExitOnError)
- icfg.RegisterFlags(fs)
-
- // Override default value for flags.
- fs.VisitAll(func(f *flag.Flag) {
- switch f.Name {
- case "root-dir":
- f.DefValue = gnoDataDir
- case "chainid":
- f.DefValue = "tendermint_test"
- case "genesis-balances-file":
- f.DefValue = filepath.Join(gnoRootDir, "gno.land", "genesis", "genesis_balances.txt")
- case "genesis-txs-file":
- f.DefValue = filepath.Join(gnoRootDir, "gno.land", "genesis", "genesis_txs.txt")
- default:
- return
- }
-
- f.Value.Set(f.DefValue)
- })
-
- if err := fs.Parse(args); err != nil {
- return nil, fmt.Errorf("unable to parse flags: %w", err)
- }
- }
-
- // Setup testing config.
- cfg := config.TestConfig().SetRootDir(gnoDataDir)
- {
- cfg.EnsureDirs()
- cfg.Consensus.CreateEmptyBlocks = true
- cfg.Consensus.CreateEmptyBlocksInterval = time.Duration(0)
- cfg.RPC.ListenAddress = "tcp://127.0.0.1:0"
- cfg.P2P.ListenAddress = "tcp://127.0.0.1:0"
- }
-
- // Prepare genesis.
- if err := setupTestingGenesis(gnoDataDir, cfg, icfg, gnoRootDir); err != nil {
- return nil, err
- }
-
- // Create application and node.
- return createAppAndNode(cfg, logger, gnoRootDir, icfg)
-}
-
-func setupTestingGenesis(gnoDataDir string, cfg *config.Config, icfg *IntegrationConfig, gnoRootDir string) error {
- newPrivValKey := cfg.PrivValidatorKeyFile()
- newPrivValState := cfg.PrivValidatorStateFile()
- priv := privval.LoadOrGenFilePV(newPrivValKey, newPrivValState)
-
- genesisFilePath := filepath.Join(gnoDataDir, cfg.Genesis)
- genesisDirPath := filepath.Dir(genesisFilePath)
- if err := osm.EnsureDir(genesisDirPath, 0o700); err != nil {
- return fmt.Errorf("unable to ensure directory %q: %w", genesisDirPath, err)
- }
-
- genesisTxs := loadGenesisTxs(icfg.GenesisTxsFile, icfg.ChainID, icfg.GenesisRemote)
- pvPub := priv.GetPubKey()
-
- gen := &bft.GenesisDoc{
- GenesisTime: time.Now(),
- ChainID: icfg.ChainID,
- ConsensusParams: abci.ConsensusParams{
- Block: &abci.BlockParams{
- // TODO: update limits.
- MaxTxBytes: 1000000, // 1MB,
- MaxDataBytes: 2000000, // 2MB,
- MaxGas: 10000000, // 10M gas
- TimeIotaMS: 100, // 100ms
- },
- },
- Validators: []bft.GenesisValidator{
- {
- Address: pvPub.Address(),
- PubKey: pvPub,
- Power: 10,
- Name: "testvalidator",
- },
- },
- }
-
- // Load distribution.
- balances := loadGenesisBalances(icfg.GenesisBalancesFile)
-
- // Load initial packages from examples.
- // XXX: We should be able to config this.
- test1 := crypto.MustAddressFromString(test1Addr)
- txs := []std.Tx{}
-
- // List initial packages to load from examples.
- // println(filepath.Join(gnoRootDir, "examples"))
- pkgs, err := gnomod.ListPkgs(filepath.Join(gnoRootDir, "examples"))
- if err != nil {
- return fmt.Errorf("listing gno packages: %w", err)
- }
-
- // Sort packages by dependencies.
- sortedPkgs, err := pkgs.Sort()
- if err != nil {
- return fmt.Errorf("sorting packages: %w", err)
- }
-
- // Filter out draft packages.
- nonDraftPkgs := sortedPkgs.GetNonDraftPkgs()
-
- for _, pkg := range nonDraftPkgs {
- // Open files in directory as MemPackage.
- memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name)
-
- var tx std.Tx
- tx.Msgs = []std.Msg{
- vmm.MsgAddPackage{
- Creator: test1,
- Package: memPkg,
- Deposit: nil,
- },
- }
-
- // XXX: Add fee flag ?
- // Or maybe reduce fee to the minimum ?
- tx.Fee = std.NewFee(50000, std.MustParseCoin("1000000ugnot"))
- tx.Signatures = make([]std.Signature, len(tx.GetSigners()))
- txs = append(txs, tx)
- }
-
- // Load genesis txs from file.
- txs = append(txs, genesisTxs...)
-
- // Construct genesis AppState.
- gen.AppState = gnoland.GnoGenesisState{
- Balances: balances,
- Txs: txs,
- }
-
- writeGenesisFile(gen, genesisFilePath)
-
- return nil
-}
-
-func createAppAndNode(cfg *config.Config, logger log.Logger, gnoRootDir string, icfg *IntegrationConfig) (*node.Node, error) {
- gnoApp, err := gnoland.NewAppWithOptions(&gnoland.AppOptions{
- Logger: logger,
- GnoRootDir: gnoRootDir,
- SkipFailingGenesisTxs: icfg.SkipFailingGenesisTxs,
- MaxCycles: icfg.GenesisMaxVMCycles,
- DB: db.NewMemDB(),
- })
- if err != nil {
- return nil, fmt.Errorf("error in creating new app: %w", err)
- }
-
- cfg.LocalApp = gnoApp
- node, err := node.DefaultNewNode(cfg, logger)
- if err != nil {
- return nil, fmt.Errorf("error in creating node: %w", err)
- }
-
- return node, node.Start()
-}
-
-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 %s command success", cmd)
- }
- }
-}
-
-func loadGenesisTxs(
- path string,
- chainID string,
- genesisRemote string,
-) []std.Tx {
- txs := []std.Tx{}
- txsBz := osm.MustReadFile(path)
- txsLines := strings.Split(string(txsBz), "\n")
- for _, txLine := range txsLines {
- if txLine == "" {
- continue // Skip empty line.
- }
-
- // Patch the TX.
- txLine = strings.ReplaceAll(txLine, "%%CHAINID%%", chainID)
- txLine = strings.ReplaceAll(txLine, "%%REMOTE%%", genesisRemote)
-
- var tx std.Tx
- amino.MustUnmarshalJSON([]byte(txLine), &tx)
- txs = append(txs, tx)
- }
-
- return txs
-}
-
-func loadGenesisBalances(path string) []string {
- // Each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot.
- balances := []string{}
- content := osm.MustReadFile(path)
- lines := strings.Split(string(content), "\n")
- for _, line := range lines {
- line = strings.TrimSpace(line)
-
- // Remove comments.
- line = strings.Split(line, "#")[0]
- line = strings.TrimSpace(line)
-
- // Skip empty lines.
- if line == "" {
- continue
- }
-
- parts := strings.Split(line, "=")
- if len(parts) != 2 {
- panic("invalid genesis_balance line: " + line)
- }
-
- balances = append(balances, line)
- }
- return balances
-}
-
-func writeGenesisFile(gen *bft.GenesisDoc, filePath string) {
- err := gen.SaveAs(filePath)
- if err != nil {
- panic(err)
- }
-}
diff --git a/gno.land/pkg/integration/node.go b/gno.land/pkg/integration/node.go
new file mode 100644
index 00000000000..a0ee63a0780
--- /dev/null
+++ b/gno.land/pkg/integration/node.go
@@ -0,0 +1,206 @@
+package integration
+
+import (
+ "errors"
+ "fmt"
+ "time"
+
+ "github.com/gnolang/gno/gno.land/pkg/gnoland"
+ vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm"
+ gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
+ "github.com/gnolang/gno/gnovm/pkg/gnomod"
+ abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
+ "github.com/gnolang/gno/tm2/pkg/bft/config"
+ "github.com/gnolang/gno/tm2/pkg/bft/node"
+ "github.com/gnolang/gno/tm2/pkg/bft/proxy"
+ "github.com/gnolang/gno/tm2/pkg/bft/types"
+ bft "github.com/gnolang/gno/tm2/pkg/bft/types"
+ "github.com/gnolang/gno/tm2/pkg/crypto/ed25519"
+ "github.com/gnolang/gno/tm2/pkg/db"
+ "github.com/gnolang/gno/tm2/pkg/log"
+ "github.com/gnolang/gno/tm2/pkg/p2p"
+ "github.com/gnolang/gno/tm2/pkg/std"
+)
+
+type NodeConfig struct {
+ BFTConfig *config.Config
+ ConsensusParams abci.ConsensusParams
+ GenesisValidator []bft.GenesisValidator
+ Packages []PackagePath
+ Balances []gnoland.Balance
+ GenesisTXs []std.Tx
+ SkipFailingGenesisTxs bool
+ GenesisMaxVMCycles int64
+}
+
+func NewNode(logger log.Logger, icfg NodeConfig) (*node.Node, error) {
+ bftconfig := icfg.BFTConfig
+ {
+ // Setup setup testing config
+ if bftconfig == nil {
+ bftconfig = config.TestConfig()
+ bftconfig.RPC.ListenAddress = "tcp://127.0.0.1:0"
+ bftconfig.P2P.ListenAddress = "tcp://127.0.0.1:0"
+ }
+
+ // XXX: we need to get ride of this, for now needed because of stdlib
+ if bftconfig.RootDir == "" {
+ gnoRootDir := gnoland.MustGuessGnoRootDir()
+ bftconfig.SetRootDir(gnoRootDir)
+ }
+ }
+
+ nodekey := &p2p.NodeKey{PrivKey: ed25519.GenPrivKey()}
+ priv := bft.NewMockPVWithParams(nodekey.PrivKey, false, false)
+
+ // Setup geeneis
+ gen := &bft.GenesisDoc{}
+ {
+
+ gen.GenesisTime = time.Now()
+
+ // cfg.chainID = "tendermint_test"
+ gen.ChainID = bftconfig.ChainID()
+
+ // XXX(gfanton): Do we need some default here ?
+ // if icfg.ConsensusParams.Block == nil {
+ // icfg.ConsensusParams.Block = &abci.BlockParams{
+ // MaxTxBytes: 1000000, // 1MB,
+ // MaxDataBytes: 2000000, // 2MB,
+ // MaxGas: 10000000, // 10M gas
+ // TimeIotaMS: 100, // 100ms
+ // }
+ // }
+ gen.ConsensusParams = icfg.ConsensusParams
+
+ pk := priv.GetPubKey()
+
+ // start with self validator
+ gen.Validators = []bft.GenesisValidator{
+ {
+ Address: pk.Address(),
+ PubKey: pk,
+ Power: 10,
+ Name: "rootValidator",
+ },
+ }
+
+ for _, validator := range icfg.GenesisValidator {
+ gen.Validators = append(gen.Validators, validator)
+ }
+ }
+
+ // XXX: maybe let the user do this manually and pass it to genesisTXs
+ txs, err := LoadPackages(icfg.Packages)
+ if err != nil {
+ return nil, fmt.Errorf("uanble to load genesis packages: %w", err)
+ }
+
+ txs = append(txs, icfg.GenesisTXs...)
+
+ gen.AppState = gnoland.GnoGenesisState{
+ Balances: icfg.Balances,
+ Txs: txs,
+ }
+
+ gnoApp, err := gnoland.NewAppWithOptions(&gnoland.AppOptions{
+ Logger: logger,
+ GnoRootDir: bftconfig.RootDir,
+ SkipFailingGenesisTxs: icfg.SkipFailingGenesisTxs,
+ MaxCycles: icfg.GenesisMaxVMCycles,
+ DB: db.NewMemDB(),
+ })
+ if err != nil {
+ return nil, fmt.Errorf("error in creating new app: %w", err)
+ }
+
+ bftconfig.LocalApp = gnoApp
+
+ // Get app client creator.
+ appClientCreator := proxy.DefaultClientCreator(
+ bftconfig.LocalApp,
+ bftconfig.ProxyApp,
+ bftconfig.ABCI,
+ bftconfig.DBDir(),
+ )
+
+ // Create genesis factory.
+ genProvider := func() (*types.GenesisDoc, error) {
+ return gen, nil
+ }
+
+ return node.NewNode(bftconfig,
+ priv, nodekey,
+ appClientCreator,
+ genProvider,
+ node.DefaultDBProvider,
+ logger,
+ )
+}
+
+func LoadPackages(pkgs []PackagePath) ([]std.Tx, error) {
+ txs := []std.Tx{}
+ for _, pkg := range pkgs {
+ tx, err := pkg.Load()
+ if err != nil {
+ return nil, fmt.Errorf("unable to load packages: %w", err)
+ }
+ txs = append(txs, tx...)
+
+ }
+ return txs, nil
+}
+
+type PackagePath struct {
+ Creator bft.Address
+ Deposit std.Coins
+ Fee std.Fee
+ Path string
+}
+
+func (p PackagePath) Load() ([]std.Tx, error) {
+ if p.Creator.IsZero() {
+ return nil, errors.New("empty creator address")
+ }
+
+ if p.Path == "" {
+ return nil, errors.New("empty package path")
+ }
+
+ // list all packages from target path
+ pkgs, err := gnomod.ListPkgs(p.Path)
+ if err != nil {
+ return nil, fmt.Errorf("listing gno packages: %w", err)
+ }
+
+ // Sort packages by dependencies.
+ sortedPkgs, err := pkgs.Sort()
+ if err != nil {
+ return nil, fmt.Errorf("sorting packages: %w", err)
+ }
+
+ // Filter out draft packages.
+ nonDraftPkgs := sortedPkgs.GetNonDraftPkgs()
+ txs := []std.Tx{}
+ for _, pkg := range nonDraftPkgs {
+ // Open files in directory as MemPackage.
+ memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name)
+
+ // Create transaction
+ tx := std.Tx{
+ Fee: p.Fee,
+ Msgs: []std.Msg{
+ vmm.MsgAddPackage{
+ Creator: p.Creator,
+ Package: memPkg,
+ Deposit: p.Deposit,
+ },
+ },
+ }
+
+ tx.Signatures = make([]std.Signature, len(tx.GetSigners()))
+ txs = append(txs, tx)
+ }
+
+ return txs, nil
+}
diff --git a/gno.land/pkg/integration/node_inmemory.go b/gno.land/pkg/integration/node_inmemory.go
new file mode 100644
index 00000000000..01ef25ea061
--- /dev/null
+++ b/gno.land/pkg/integration/node_inmemory.go
@@ -0,0 +1,5 @@
+package integration
+
+import "github.com/gnolang/gno/tm2/pkg/log"
+
+}
diff --git a/gno.land/pkg/gnoland/inmemory_test.go b/gno.land/pkg/integration/node_test.go
similarity index 76%
rename from gno.land/pkg/gnoland/inmemory_test.go
rename to gno.land/pkg/integration/node_test.go
index 9c2b79dab7d..b327117c897 100644
--- a/gno.land/pkg/gnoland/inmemory_test.go
+++ b/gno.land/pkg/integration/node_test.go
@@ -1,4 +1,4 @@
-package gnoland
+package integration
import (
"testing"
@@ -10,7 +10,7 @@ import (
func TestNewInMemory(t *testing.T) {
logger := log.TestingLogger()
- node, err := NewInMemory(logger, InMemoryConfig{})
+ node, err := NewNode(logger, NodeConfig{})
require.NoError(t, err)
require.NotNil(t, node)
}
diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go
index f0a696ddd85..aa653f1db66 100644
--- a/gno.land/pkg/integration/testing_integration.go
+++ b/gno.land/pkg/integration/testing_integration.go
@@ -13,13 +13,17 @@ import (
"time"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
+ abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
+ "github.com/gnolang/gno/tm2/pkg/bft/config"
"github.com/gnolang/gno/tm2/pkg/bft/node"
"github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/commands"
+ "github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/crypto/keys"
"github.com/gnolang/gno/tm2/pkg/crypto/keys/client"
"github.com/gnolang/gno/tm2/pkg/events"
"github.com/gnolang/gno/tm2/pkg/log"
+ "github.com/gnolang/gno/tm2/pkg/std"
"github.com/rogpeppe/go-internal/testscript"
)
@@ -51,14 +55,14 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
// `gnoRootDir` should point to the local location of the gno repository.
// It serves as the gno equivalent of GOROOT.
- gnoRootDir := gnoland.GuessGnoRootDir()
+ gnoRootDir := gnoland.MustGuessGnoRootDir()
// `gnoHomeDir` should be the local directory where gnokey stores keys.
gnoHomeDir := filepath.Join(tmpdir, "gno")
// `gnoDataDir` should refer to the local location where the gnoland node
// stores its configuration and data.
- gnoDataDir := filepath.Join(tmpdir, "data")
+ // gnoDataDir := filepath.Join(tmpdir, "data")
// Testscripts run concurrently by default, so we need to be prepared for that.
var muNodes sync.Mutex
@@ -115,9 +119,8 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
logger = getTestingLogger(ts, logname)
}
- dataDir := filepath.Join(gnoDataDir, sid)
var node *node.Node
- if node, err = execTestingGnoland(t, logger, dataDir, gnoRootDir, args); err == nil {
+ if node, err = execInMemoryGnoland(logger, gnoRootDir); err == nil {
nodes[sid] = &testNode{
Node: node,
logger: logger,
@@ -139,7 +142,7 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
// Add default environements.
ts.Setenv("RPC_ADDR", laddr)
- ts.Setenv("GNODATA", gnoDataDir)
+ // ts.Setenv("GNODATA", gnoDataDir)
const listenerID = "testing_listener"
@@ -178,7 +181,7 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
// Unset gnoland environements.
ts.Setenv("RPC_ADDR", "")
- ts.Setenv("GNODATA", "")
+ // ts.Setenv("GNODATA", "")
fmt.Fprintln(ts.Stdout(), "node stopped successfully")
}
default:
@@ -280,3 +283,69 @@ func getTestingLogger(ts *testscript.TestScript, logname string) log.Logger {
ts.Logf("starting logger: %q", path)
return logger
}
+
+func execInMemoryGnoland(logger log.Logger, gnoroot string) (*node.Node, error) {
+ txsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.txt")
+ balanceFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt")
+ exampleDir := filepath.Join(gnoroot, "examples")
+
+ genesisBalances, err := gnoland.LoadGenesisBalancesFile(balanceFile)
+ if err != nil {
+ return nil, fmt.Errorf("unableo to laod genesis balance file: %w", err)
+ }
+
+ bftconfig := config.TestConfig().SetRootDir(gnoroot)
+ bftconfig.Consensus.CreateEmptyBlocks = true
+ bftconfig.Consensus.CreateEmptyBlocksInterval = time.Duration(0)
+ bftconfig.RPC.ListenAddress = "tcp://127.0.0.1:0"
+ bftconfig.P2P.ListenAddress = "tcp://127.0.0.1:0"
+
+ // NOTE: we dont care about giving a correct address here, as it's only visual
+ // XXX: do we care loading this file ?
+ genesisTXs, err := gnoland.LoadGenesisTxsFile(txsFile, bftconfig.ChainID(), bftconfig.RPC.ListenAddress)
+ if err != nil {
+ return nil, fmt.Errorf("unableo to laod genesis balance file: %w", err)
+ }
+
+ // Load example packages
+ pkgs := PackagePath{
+ Creator: crypto.MustAddressFromString(test1Addr),
+ Fee: std.NewFee(50000, std.MustParseCoin("1000000ugnot")),
+ Path: exampleDir,
+ }
+
+ config := NodeConfig{
+ Balances: genesisBalances,
+ GenesisTXs: genesisTXs,
+ BFTConfig: bftconfig,
+ Packages: []PackagePath{pkgs},
+ }
+
+ // XXX: make this configurable
+ config.ConsensusParams.Block = &abci.BlockParams{
+ MaxTxBytes: 1000000, // 1MB,
+ MaxDataBytes: 2000000, // 2MB,
+ MaxGas: 10000000, // 10M gas
+ TimeIotaMS: 100, // 100ms
+ }
+
+ node, err := NewNode(logger, config)
+ if err != nil {
+ return nil, fmt.Errorf("unable to start the node: %w", err)
+ }
+
+ return node, node.Start()
+}
+
+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 %s command success", cmd)
+ }
+ }
+}
From 9077ca12a8a392f1bfe52df809263bf16994d420 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 12 Oct 2023 17:35:52 +0200
Subject: [PATCH 04/38] chore: cleanup
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/integration/node.go | 48 +++++++++++------------
gno.land/pkg/integration/node_inmemory.go | 5 ---
2 files changed, 24 insertions(+), 29 deletions(-)
delete mode 100644 gno.land/pkg/integration/node_inmemory.go
diff --git a/gno.land/pkg/integration/node.go b/gno.land/pkg/integration/node.go
index a0ee63a0780..527b227f8e2 100644
--- a/gno.land/pkg/integration/node.go
+++ b/gno.land/pkg/integration/node.go
@@ -33,23 +33,23 @@ type NodeConfig struct {
GenesisMaxVMCycles int64
}
-func NewNode(logger log.Logger, icfg NodeConfig) (*node.Node, error) {
- bftconfig := icfg.BFTConfig
+func NewNode(logger log.Logger, cfg NodeConfig) (*node.Node, error) {
+ // Setup setup testing config
{
- // Setup setup testing config
- if bftconfig == nil {
- bftconfig = config.TestConfig()
- bftconfig.RPC.ListenAddress = "tcp://127.0.0.1:0"
- bftconfig.P2P.ListenAddress = "tcp://127.0.0.1:0"
+ if cfg.BFTConfig == nil {
+ cfg.BFTConfig = config.TestConfig()
+ cfg.BFTConfig.RPC.ListenAddress = "tcp://127.0.0.1:0"
+ cfg.BFTConfig.P2P.ListenAddress = "tcp://127.0.0.1:0"
}
// XXX: we need to get ride of this, for now needed because of stdlib
- if bftconfig.RootDir == "" {
+ if cfg.BFTConfig.RootDir == "" {
gnoRootDir := gnoland.MustGuessGnoRootDir()
- bftconfig.SetRootDir(gnoRootDir)
+ cfg.BFTConfig.SetRootDir(gnoRootDir)
}
}
+ // generate node identity
nodekey := &p2p.NodeKey{PrivKey: ed25519.GenPrivKey()}
priv := bft.NewMockPVWithParams(nodekey.PrivKey, false, false)
@@ -60,7 +60,7 @@ func NewNode(logger log.Logger, icfg NodeConfig) (*node.Node, error) {
gen.GenesisTime = time.Now()
// cfg.chainID = "tendermint_test"
- gen.ChainID = bftconfig.ChainID()
+ gen.ChainID = cfg.BFTConfig.ChainID()
// XXX(gfanton): Do we need some default here ?
// if icfg.ConsensusParams.Block == nil {
@@ -71,7 +71,7 @@ func NewNode(logger log.Logger, icfg NodeConfig) (*node.Node, error) {
// TimeIotaMS: 100, // 100ms
// }
// }
- gen.ConsensusParams = icfg.ConsensusParams
+ gen.ConsensusParams = cfg.ConsensusParams
pk := priv.GetPubKey()
@@ -85,43 +85,43 @@ func NewNode(logger log.Logger, icfg NodeConfig) (*node.Node, error) {
},
}
- for _, validator := range icfg.GenesisValidator {
+ for _, validator := range cfg.GenesisValidator {
gen.Validators = append(gen.Validators, validator)
}
}
// XXX: maybe let the user do this manually and pass it to genesisTXs
- txs, err := LoadPackages(icfg.Packages)
+ txs, err := LoadPackages(cfg.Packages)
if err != nil {
return nil, fmt.Errorf("uanble to load genesis packages: %w", err)
}
- txs = append(txs, icfg.GenesisTXs...)
+ txs = append(txs, cfg.GenesisTXs...)
gen.AppState = gnoland.GnoGenesisState{
- Balances: icfg.Balances,
+ Balances: cfg.Balances,
Txs: txs,
}
gnoApp, err := gnoland.NewAppWithOptions(&gnoland.AppOptions{
Logger: logger,
- GnoRootDir: bftconfig.RootDir,
- SkipFailingGenesisTxs: icfg.SkipFailingGenesisTxs,
- MaxCycles: icfg.GenesisMaxVMCycles,
+ GnoRootDir: cfg.BFTConfig.RootDir,
+ SkipFailingGenesisTxs: cfg.SkipFailingGenesisTxs,
+ MaxCycles: cfg.GenesisMaxVMCycles,
DB: db.NewMemDB(),
})
if err != nil {
return nil, fmt.Errorf("error in creating new app: %w", err)
}
- bftconfig.LocalApp = gnoApp
+ cfg.BFTConfig.LocalApp = gnoApp
// Get app client creator.
appClientCreator := proxy.DefaultClientCreator(
- bftconfig.LocalApp,
- bftconfig.ProxyApp,
- bftconfig.ABCI,
- bftconfig.DBDir(),
+ cfg.BFTConfig.LocalApp,
+ cfg.BFTConfig.ProxyApp,
+ cfg.BFTConfig.ABCI,
+ cfg.BFTConfig.DBDir(),
)
// Create genesis factory.
@@ -129,7 +129,7 @@ func NewNode(logger log.Logger, icfg NodeConfig) (*node.Node, error) {
return gen, nil
}
- return node.NewNode(bftconfig,
+ return node.NewNode(cfg.BFTConfig,
priv, nodekey,
appClientCreator,
genProvider,
diff --git a/gno.land/pkg/integration/node_inmemory.go b/gno.land/pkg/integration/node_inmemory.go
deleted file mode 100644
index 01ef25ea061..00000000000
--- a/gno.land/pkg/integration/node_inmemory.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package integration
-
-import "github.com/gnolang/gno/tm2/pkg/log"
-
-}
From 3a3133c214584d4a4b96d66a38d7c1cc986106ec Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 12 Oct 2023 17:44:33 +0200
Subject: [PATCH 05/38] wip: gnoweb
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoweb/main_test.go | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go
index 579e1bcd06b..4e0175deea3 100644
--- a/gno.land/cmd/gnoweb/main_test.go
+++ b/gno.land/cmd/gnoweb/main_test.go
@@ -8,6 +8,8 @@ import (
"strings"
"testing"
+ "github.com/gnolang/gno/gno.land/pkg/integration"
+ "github.com/gnolang/gno/tm2/pkg/log"
"github.com/gotuna/gotuna/test/assert"
)
@@ -40,6 +42,13 @@ func TestRoutes(t *testing.T) {
} else {
panic("os.Getwd() -> err: " + err.Error())
}
+
+ node := integration.TestingInMemoryNode(t, log.NewNopLogger(), nil)
+ defer node.Stop()
+
+ // XXX: this is ugly :(
+ flags.remoteAddr = node.Config().RPC.ListenAddress
+
app := makeApp()
for _, r := range routes {
From 06ecc62893ef67dd47a731d6b93b38fec67faac4 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 12 Oct 2023 17:47:55 +0200
Subject: [PATCH 06/38] chore: lint
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/gnoland/node.go | 115 -------------------------------
gno.land/pkg/integration/node.go | 2 +-
2 files changed, 1 insertion(+), 116 deletions(-)
delete mode 100644 gno.land/pkg/gnoland/node.go
diff --git a/gno.land/pkg/gnoland/node.go b/gno.land/pkg/gnoland/node.go
deleted file mode 100644
index d9e54f35cd7..00000000000
--- a/gno.land/pkg/gnoland/node.go
+++ /dev/null
@@ -1,115 +0,0 @@
-package gnoland
-
-// func loadGenesisTxs(
-// path string,
-// chainID string,
-// genesisRemote string,
-// ) []std.Tx {
-// txs := []std.Tx{}
-// txsBz := osm.MustReadFile(path)
-// txsLines := strings.Split(string(txsBz), "\n")
-// for _, txLine := range txsLines {
-// if txLine == "" {
-// continue // skip empty line
-// }
-
-// // patch the TX
-// txLine = strings.ReplaceAll(txLine, "%%CHAINID%%", chainID)
-// txLine = strings.ReplaceAll(txLine, "%%REMOTE%%", genesisRemote)
-
-// var tx std.Tx
-// amino.MustUnmarshalJSON([]byte(txLine), &tx)
-// txs = append(txs, tx)
-// }
-
-// return txs
-// }
-
-// func setupTestingGenesis(gnoDataDir string, cfg *config.Config, icfg *IntegrationConfig) error {
-// genesisFilePath := filepath.Join(gnoDataDir, cfg.Genesis)
-// osm.EnsureDir(filepath.Dir(genesisFilePath), 0o700)
-// if !osm.FileExists(genesisFilePath) {
-// genesisTxs := loadGenesisTxs(icfg.GenesisTxsFile, icfg.ChainID, icfg.GenesisRemote)
-// pvPub := priv.GetPubKey()
-
-// gen := &bft.GenesisDoc{
-// GenesisTime: time.Now(),
-// ChainID: icfg.ChainID,
-// ConsensusParams: abci.ConsensusParams{
-// Block: &abci.BlockParams{
-// // TODO: update limits.
-// MaxTxBytes: 1000000, // 1MB,
-// MaxDataBytes: 2000000, // 2MB,
-// MaxGas: 10000000, // 10M gas
-// TimeIotaMS: 100, // 100ms
-// },
-// },
-// Validators: []bft.GenesisValidator{
-// {
-// Address: pvPub.Address(),
-// PubKey: pvPub,
-// Power: 10,
-// Name: "testvalidator",
-// },
-// },
-// }
-
-// // Load distribution.
-// balances := loadGenesisBalances(icfg.GenesisBalancesFile)
-
-// // Load initial packages from examples.
-// // XXX: we should be able to config this
-// test1 := crypto.MustAddressFromString(test1Addr)
-// txs := []std.Tx{}
-
-// // List initial packages to load from examples.
-// // println(filepath.Join(gnoRootDir, "examples"))
-
-// // load genesis txs from file.
-// txs = append(txs, genesisTxs...)
-
-// // construct genesis AppState.
-// gen.AppState = GnoGenesisState{
-// Balances: balances,
-// Txs: txs,
-// }
-
-// writeGenesisFile(gen, genesisFilePath)
-// }
-
-// return nil
-// }
-
-// func loadGenesisBalances(path string) []string {
-// // each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot
-// balances := []string{}
-// content := osm.MustReadFile(path)
-// lines := strings.Split(string(content), "\n")
-// for _, line := range lines {
-// line = strings.TrimSpace(line)
-
-// // remove comments.
-// line = strings.Split(line, "#")[0]
-// line = strings.TrimSpace(line)
-
-// // skip empty lines.
-// if line == "" {
-// continue
-// }
-
-// parts := strings.Split(line, "=")
-// if len(parts) != 2 {
-// panic("invalid genesis_balance line: " + line)
-// }
-
-// balances = append(balances, line)
-// }
-// return balances
-// }
-
-// func writeGenesisFile(gen *bft.GenesisDoc, filePath string) {
-// err := gen.SaveAs(filePath)
-// if err != nil {
-// panic(err)
-// }
-// }
diff --git a/gno.land/pkg/integration/node.go b/gno.land/pkg/integration/node.go
index 527b227f8e2..69a013f4572 100644
--- a/gno.land/pkg/integration/node.go
+++ b/gno.land/pkg/integration/node.go
@@ -34,7 +34,7 @@ type NodeConfig struct {
}
func NewNode(logger log.Logger, cfg NodeConfig) (*node.Node, error) {
- // Setup setup testing config
+ // Setup setup testing config if needed
{
if cfg.BFTConfig == nil {
cfg.BFTConfig = config.TestConfig()
From 84907d13144939850f524f48de7c9ed932720bc2 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 12 Oct 2023 17:55:30 +0200
Subject: [PATCH 07/38] chore: add some comments
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/gnoland/app.go | 1 +
gno.land/pkg/integration/testing_integration.go | 1 +
2 files changed, 2 insertions(+)
diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go
index 6ac13d4ff99..9a7a0f91d3b 100644
--- a/gno.land/pkg/gnoland/app.go
+++ b/gno.land/pkg/gnoland/app.go
@@ -199,6 +199,7 @@ func EndBlocker(vmk vm.VMKeeperI) func(ctx sdk.Context, req abci.RequestEndBlock
}
}
+// XXX: should be removed in favor of https://github.com/gnolang/gno/pull/1233
var (
guessOnce sync.Once
gnoroot string
diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go
index aa653f1db66..035c1879169 100644
--- a/gno.land/pkg/integration/testing_integration.go
+++ b/gno.land/pkg/integration/testing_integration.go
@@ -144,6 +144,7 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
ts.Setenv("RPC_ADDR", laddr)
// ts.Setenv("GNODATA", gnoDataDir)
+ // XXX: This should be replace by https://github.com/gnolang/gno/pull/1216
const listenerID = "testing_listener"
// Wait for first block by waiting for `EventNewBlock` event.
From 8e8bed2214e0e115ea9f55d6892f7024a8734aa0 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 12 Oct 2023 18:50:12 +0200
Subject: [PATCH 08/38] fix: gnoweb tests
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoweb/main_test.go | 4 +-
.../pkg/integration/testing_integration.go | 56 ++-----------------
2 files changed, 8 insertions(+), 52 deletions(-)
diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go
index 4e0175deea3..4ef6e3e6dac 100644
--- a/gno.land/cmd/gnoweb/main_test.go
+++ b/gno.land/cmd/gnoweb/main_test.go
@@ -8,6 +8,7 @@ import (
"strings"
"testing"
+ "github.com/gnolang/gno/gno.land/pkg/gnoland"
"github.com/gnolang/gno/gno.land/pkg/integration"
"github.com/gnolang/gno/tm2/pkg/log"
"github.com/gotuna/gotuna/test/assert"
@@ -43,7 +44,8 @@ func TestRoutes(t *testing.T) {
panic("os.Getwd() -> err: " + err.Error())
}
- node := integration.TestingInMemoryNode(t, log.NewNopLogger(), nil)
+ config := integration.DefaultTestingConfig(t, gnoland.MustGuessGnoRootDir())
+ node := integration.TestingInMemoryNode(t, log.NewNopLogger(), config)
defer node.Stop()
// XXX: this is ugly :(
diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go
index 035c1879169..9ddc57fc7a1 100644
--- a/gno.land/pkg/integration/testing_integration.go
+++ b/gno.land/pkg/integration/testing_integration.go
@@ -13,17 +13,13 @@ import (
"time"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
- abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
- "github.com/gnolang/gno/tm2/pkg/bft/config"
"github.com/gnolang/gno/tm2/pkg/bft/node"
"github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/commands"
- "github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/crypto/keys"
"github.com/gnolang/gno/tm2/pkg/crypto/keys/client"
"github.com/gnolang/gno/tm2/pkg/events"
"github.com/gnolang/gno/tm2/pkg/log"
- "github.com/gnolang/gno/tm2/pkg/std"
"github.com/rogpeppe/go-internal/testscript"
)
@@ -68,6 +64,8 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
var muNodes sync.Mutex
nodes := map[string]*testNode{}
+ nodeConfig := DefaultTestingConfig(t, gnoRootDir)
+
updateScripts, _ := strconv.ParseBool(os.Getenv("UPDATE_SCRIPTS"))
persistWorkDir, _ := strconv.ParseBool(os.Getenv("TESTWORK"))
return testscript.Params{
@@ -120,7 +118,7 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
}
var node *node.Node
- if node, err = execInMemoryGnoland(logger, gnoRootDir); err == nil {
+ if node, err = execInMemoryGnoland(logger, nodeConfig); err == nil {
nodes[sid] = &testNode{
Node: node,
logger: logger,
@@ -285,52 +283,8 @@ func getTestingLogger(ts *testscript.TestScript, logname string) log.Logger {
return logger
}
-func execInMemoryGnoland(logger log.Logger, gnoroot string) (*node.Node, error) {
- txsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.txt")
- balanceFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt")
- exampleDir := filepath.Join(gnoroot, "examples")
-
- genesisBalances, err := gnoland.LoadGenesisBalancesFile(balanceFile)
- if err != nil {
- return nil, fmt.Errorf("unableo to laod genesis balance file: %w", err)
- }
-
- bftconfig := config.TestConfig().SetRootDir(gnoroot)
- bftconfig.Consensus.CreateEmptyBlocks = true
- bftconfig.Consensus.CreateEmptyBlocksInterval = time.Duration(0)
- bftconfig.RPC.ListenAddress = "tcp://127.0.0.1:0"
- bftconfig.P2P.ListenAddress = "tcp://127.0.0.1:0"
-
- // NOTE: we dont care about giving a correct address here, as it's only visual
- // XXX: do we care loading this file ?
- genesisTXs, err := gnoland.LoadGenesisTxsFile(txsFile, bftconfig.ChainID(), bftconfig.RPC.ListenAddress)
- if err != nil {
- return nil, fmt.Errorf("unableo to laod genesis balance file: %w", err)
- }
-
- // Load example packages
- pkgs := PackagePath{
- Creator: crypto.MustAddressFromString(test1Addr),
- Fee: std.NewFee(50000, std.MustParseCoin("1000000ugnot")),
- Path: exampleDir,
- }
-
- config := NodeConfig{
- Balances: genesisBalances,
- GenesisTXs: genesisTXs,
- BFTConfig: bftconfig,
- Packages: []PackagePath{pkgs},
- }
-
- // XXX: make this configurable
- config.ConsensusParams.Block = &abci.BlockParams{
- MaxTxBytes: 1000000, // 1MB,
- MaxDataBytes: 2000000, // 2MB,
- MaxGas: 10000000, // 10M gas
- TimeIotaMS: 100, // 100ms
- }
-
- node, err := NewNode(logger, config)
+func execInMemoryGnoland(logger log.Logger, config *NodeConfig) (*node.Node, error) {
+ node, err := NewNode(logger, *config)
if err != nil {
return nil, fmt.Errorf("unable to start the node: %w", err)
}
From d5101408efd002b062466e349b11dfad33fd8418 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 12 Oct 2023 18:54:42 +0200
Subject: [PATCH 09/38] fix: enable gnoweb test on the CI
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
.github/workflows/gnoland.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/gnoland.yml b/.github/workflows/gnoland.yml
index 2b38f254a13..949151e42be 100644
--- a/.github/workflows/gnoland.yml
+++ b/.github/workflows/gnoland.yml
@@ -60,7 +60,7 @@ jobs:
- _test.gnoland
- _test.gnokey
- _test.pkgs
- #- _test.gnoweb # this test should be rewritten to run an inmemory localnode
+ - _test.gnoweb # this test should be rewritten to run an inmemory localnode
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
From 3221a1ca5f915151cf33e9a4536d3d35b76affba Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 12 Oct 2023 19:02:28 +0200
Subject: [PATCH 10/38] feat: add testing node
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/integration/testing_node.go | 96 ++++++++++++++++++++++++
1 file changed, 96 insertions(+)
create mode 100644 gno.land/pkg/integration/testing_node.go
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
new file mode 100644
index 00000000000..760e6201cdd
--- /dev/null
+++ b/gno.land/pkg/integration/testing_node.go
@@ -0,0 +1,96 @@
+package integration
+
+import (
+ "path/filepath"
+ "testing"
+ "time"
+
+ "github.com/gnolang/gno/gno.land/pkg/gnoland"
+ abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
+ "github.com/gnolang/gno/tm2/pkg/bft/config"
+ "github.com/gnolang/gno/tm2/pkg/bft/node"
+ "github.com/gnolang/gno/tm2/pkg/bft/types"
+ "github.com/gnolang/gno/tm2/pkg/crypto"
+ "github.com/gnolang/gno/tm2/pkg/events"
+ "github.com/gnolang/gno/tm2/pkg/log"
+ "github.com/gnolang/gno/tm2/pkg/std"
+ "github.com/jaekwon/testify/require"
+)
+
+func DefaultTestingConfig(t *testing.T, gnoroot string) *NodeConfig {
+ txsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.txt")
+ balanceFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt")
+ exampleDir := filepath.Join(gnoroot, "examples")
+
+ genesisBalances, err := gnoland.LoadGenesisBalancesFile(balanceFile)
+ require.NoError(t, err)
+
+ bftconfig := config.TestConfig().SetRootDir(gnoroot)
+ bftconfig.Consensus.CreateEmptyBlocks = true
+ bftconfig.Consensus.CreateEmptyBlocksInterval = time.Duration(0)
+ bftconfig.RPC.ListenAddress = "tcp://127.0.0.1:0"
+ bftconfig.P2P.ListenAddress = "tcp://127.0.0.1:0"
+
+ // NOTE: we dont care about giving a correct address here, as it's only visual
+ // XXX: do we care loading this file ?
+ genesisTXs, err := gnoland.LoadGenesisTxsFile(txsFile, bftconfig.ChainID(), bftconfig.RPC.ListenAddress)
+ require.NoError(t, err)
+
+ // Load example packages
+ pkgs := PackagePath{
+ Creator: crypto.MustAddressFromString(test1Addr),
+ Fee: std.NewFee(50000, std.MustParseCoin("1000000ugnot")),
+ Path: exampleDir,
+ }
+
+ config := NodeConfig{
+ Balances: genesisBalances,
+ GenesisTXs: genesisTXs,
+ BFTConfig: bftconfig,
+ Packages: []PackagePath{pkgs},
+ }
+
+ config.ConsensusParams.Block = &abci.BlockParams{
+ MaxTxBytes: 1000000, // 1MB,
+ MaxDataBytes: 2000000, // 2MB,
+ MaxGas: 10000000, // 10M gas
+ TimeIotaMS: 100, // 100ms
+ }
+
+ return &config
+}
+
+// Should return an already starting node
+func TestingInMemoryNode(t *testing.T, logger log.Logger, config *NodeConfig) *node.Node {
+ node, err := NewNode(logger, *config)
+ require.NoError(t, err)
+
+ err = node.Start()
+ require.NoError(t, err)
+
+ // XXX: This should be replace by https://github.com/gnolang/gno/pull/1216
+ const listenerID = "testing_listener"
+
+ // Wait for first block by waiting for `EventNewBlock` event.
+ nb := make(chan struct{}, 1)
+ node.EventSwitch().AddListener(listenerID, func(ev events.Event) {
+ if _, ok := ev.(types.EventNewBlock); ok {
+ select {
+ case nb <- struct{}{}:
+ default:
+ }
+ }
+ })
+
+ if node.BlockStore().Height() == 0 {
+ select {
+ case <-nb: // ok
+ case <-time.After(time.Second * 6):
+ t.Fatal("timeout while waiting for the node to start")
+ }
+ }
+
+ node.EventSwitch().RemoveListener(listenerID)
+
+ return node
+}
From 92de25630c913d1801ada95abcc04624dff71ea8 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 12 Oct 2023 20:33:38 +0200
Subject: [PATCH 11/38] chore: remove useless comment
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
.github/workflows/gnoland.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/gnoland.yml b/.github/workflows/gnoland.yml
index 949151e42be..d305bed2dcd 100644
--- a/.github/workflows/gnoland.yml
+++ b/.github/workflows/gnoland.yml
@@ -60,7 +60,7 @@ jobs:
- _test.gnoland
- _test.gnokey
- _test.pkgs
- - _test.gnoweb # this test should be rewritten to run an inmemory localnode
+ - _test.gnoweb
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
From 2003899c919c596f42f8077ce1ec1cfbf55bc07a Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 12 Oct 2023 21:04:46 +0200
Subject: [PATCH 12/38] feat: add testing helper
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoweb/main_test.go | 4 +-
.../pkg/integration/testing_integration.go | 2 +-
gno.land/pkg/integration/testing_node.go | 124 +++++++++++-------
3 files changed, 82 insertions(+), 48 deletions(-)
diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go
index 4ef6e3e6dac..66e35f28b5b 100644
--- a/gno.land/cmd/gnoweb/main_test.go
+++ b/gno.land/cmd/gnoweb/main_test.go
@@ -44,8 +44,8 @@ func TestRoutes(t *testing.T) {
panic("os.Getwd() -> err: " + err.Error())
}
- config := integration.DefaultTestingConfig(t, gnoland.MustGuessGnoRootDir())
- node := integration.TestingInMemoryNode(t, log.NewNopLogger(), config)
+ config := integration.DefaultTestingNodeConfig(t, gnoland.MustGuessGnoRootDir())
+ node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNopLogger(), config)
defer node.Stop()
// XXX: this is ugly :(
diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go
index 9ddc57fc7a1..1092230cf5e 100644
--- a/gno.land/pkg/integration/testing_integration.go
+++ b/gno.land/pkg/integration/testing_integration.go
@@ -64,7 +64,7 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
var muNodes sync.Mutex
nodes := map[string]*testNode{}
- nodeConfig := DefaultTestingConfig(t, gnoRootDir)
+ nodeConfig := DefaultTestingNodeConfig(t, gnoRootDir)
updateScripts, _ := strconv.ParseBool(os.Getenv("UPDATE_SCRIPTS"))
persistWorkDir, _ := strconv.ParseBool(os.Getenv("TESTWORK"))
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
index 760e6201cdd..8cfe5171e7c 100644
--- a/gno.land/pkg/integration/testing_node.go
+++ b/gno.land/pkg/integration/testing_node.go
@@ -10,6 +10,7 @@ import (
"github.com/gnolang/gno/tm2/pkg/bft/config"
"github.com/gnolang/gno/tm2/pkg/bft/node"
"github.com/gnolang/gno/tm2/pkg/bft/types"
+ bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/events"
"github.com/gnolang/gno/tm2/pkg/log"
@@ -17,51 +18,8 @@ import (
"github.com/jaekwon/testify/require"
)
-func DefaultTestingConfig(t *testing.T, gnoroot string) *NodeConfig {
- txsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.txt")
- balanceFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt")
- exampleDir := filepath.Join(gnoroot, "examples")
-
- genesisBalances, err := gnoland.LoadGenesisBalancesFile(balanceFile)
- require.NoError(t, err)
-
- bftconfig := config.TestConfig().SetRootDir(gnoroot)
- bftconfig.Consensus.CreateEmptyBlocks = true
- bftconfig.Consensus.CreateEmptyBlocksInterval = time.Duration(0)
- bftconfig.RPC.ListenAddress = "tcp://127.0.0.1:0"
- bftconfig.P2P.ListenAddress = "tcp://127.0.0.1:0"
-
- // NOTE: we dont care about giving a correct address here, as it's only visual
- // XXX: do we care loading this file ?
- genesisTXs, err := gnoland.LoadGenesisTxsFile(txsFile, bftconfig.ChainID(), bftconfig.RPC.ListenAddress)
- require.NoError(t, err)
-
- // Load example packages
- pkgs := PackagePath{
- Creator: crypto.MustAddressFromString(test1Addr),
- Fee: std.NewFee(50000, std.MustParseCoin("1000000ugnot")),
- Path: exampleDir,
- }
-
- config := NodeConfig{
- Balances: genesisBalances,
- GenesisTXs: genesisTXs,
- BFTConfig: bftconfig,
- Packages: []PackagePath{pkgs},
- }
-
- config.ConsensusParams.Block = &abci.BlockParams{
- MaxTxBytes: 1000000, // 1MB,
- MaxDataBytes: 2000000, // 2MB,
- MaxGas: 10000000, // 10M gas
- TimeIotaMS: 100, // 100ms
- }
-
- return &config
-}
-
// Should return an already starting node
-func TestingInMemoryNode(t *testing.T, logger log.Logger, config *NodeConfig) *node.Node {
+func TestingInMemoryNode(t *testing.T, logger log.Logger, config *NodeConfig) (*node.Node, string) {
node, err := NewNode(logger, *config)
require.NoError(t, err)
@@ -92,5 +50,81 @@ func TestingInMemoryNode(t *testing.T, logger log.Logger, config *NodeConfig) *n
node.EventSwitch().RemoveListener(listenerID)
- return node
+ return node, node.Config().RPC.ListenAddress
+}
+
+func DefaultTestingNodeConfig(t *testing.T, gnoroot string) *NodeConfig {
+ t.Helper()
+
+ bftconfig := DefaultTestingBFTConfig(t, gnoroot)
+
+ return &NodeConfig{
+ Balances: LoadDefaultGenesisBalanceFile(t, gnoroot),
+ GenesisTXs: LoadDefaultGenesisTXsFile(t, bftconfig.ChainID(), gnoroot),
+ BFTConfig: bftconfig,
+ Packages: LoadDefaultPackages(t, crypto.MustAddressFromString(test1Addr), gnoroot),
+ }
+}
+
+func LoadDefaultPackages(t *testing.T, creator bft.Address, gnoroot string) []PackagePath {
+ t.Helper()
+
+ exampleDir := filepath.Join(gnoroot, "examples")
+
+ pkgs := PackagePath{
+ // Creator: crypto.MustAddressFromString(test1Addr),
+ Creator: creator,
+ Fee: std.NewFee(50000, std.MustParseCoin("1000000ugnot")),
+ Path: exampleDir,
+ }
+
+ return []PackagePath{pkgs}
+}
+
+func LoadDefaultGenesisBalanceFile(t *testing.T, gnoroot string) []gnoland.Balance {
+ t.Helper()
+
+ balanceFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt")
+
+ genesisBalances, err := gnoland.LoadGenesisBalancesFile(balanceFile)
+ require.NoError(t, err)
+
+ return genesisBalances
+}
+
+func LoadDefaultGenesisTXsFile(t *testing.T, chainid string, gnoroot string) []std.Tx {
+ t.Helper()
+
+ txsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.txt")
+
+ // NOTE: we dont care about giving a correct address here, as it's only visual
+ // XXX: do we care loading this file ?
+ genesisTXs, err := gnoland.LoadGenesisTxsFile(txsFile, chainid, "https://127.0.0.1:26657")
+ require.NoError(t, err)
+
+ return genesisTXs
+}
+
+func DefaultConsensusParams(t *testing.T, gnoroot string) *abci.ConsensusParams {
+ t.Helper()
+
+ return &abci.ConsensusParams{
+ Block: &abci.BlockParams{
+ MaxTxBytes: 1000000, // 1MB,
+ MaxDataBytes: 2000000, // 2MB,
+ MaxGas: 10000000, // 10M gas
+ TimeIotaMS: 100, // 100ms
+ },
+ }
+}
+
+func DefaultTestingBFTConfig(t *testing.T, gnoroot string) *config.Config {
+ t.Helper()
+
+ bftconfig := config.TestConfig().SetRootDir(gnoroot)
+ bftconfig.Consensus.CreateEmptyBlocks = true
+ bftconfig.Consensus.CreateEmptyBlocksInterval = time.Duration(0)
+ bftconfig.RPC.ListenAddress = "tcp://127.0.0.1:0"
+ bftconfig.P2P.ListenAddress = "tcp://127.0.0.1:0"
+ return bftconfig
}
From e0b59fdff005a2e17cdd40eb908e993f163a854c Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 12 Oct 2023 21:12:10 +0200
Subject: [PATCH 13/38] chore: lint
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoland/root.go | 3 +--
gno.land/cmd/gnoweb/main_test.go | 4 ++--
gno.land/pkg/gnoland/app.go | 3 ++-
gno.land/pkg/gnoland/types.go | 16 +++-------------
gno.land/pkg/integration/node.go | 10 ++++------
gno.land/pkg/integration/testing_node.go | 9 +++++----
6 files changed, 17 insertions(+), 28 deletions(-)
diff --git a/gno.land/cmd/gnoland/root.go b/gno.land/cmd/gnoland/root.go
index cf2a6252478..5b2cbe0e4fe 100644
--- a/gno.land/cmd/gnoland/root.go
+++ b/gno.land/cmd/gnoland/root.go
@@ -11,8 +11,7 @@ import (
)
func main() {
- io := commands.NewDefaultIO()
- cmd := newRootCmd(io)
+ cmd := newRootCmd(commands.NewDefaultIO())
if err := cmd.ParseAndRun(context.Background(), os.Args[1:]); err != nil {
_, _ = fmt.Fprintf(os.Stderr, "%+v\n", err)
diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go
index 66e35f28b5b..d395c442fbf 100644
--- a/gno.land/cmd/gnoweb/main_test.go
+++ b/gno.land/cmd/gnoweb/main_test.go
@@ -48,8 +48,8 @@ func TestRoutes(t *testing.T) {
node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNopLogger(), config)
defer node.Stop()
- // XXX: this is ugly :(
- flags.remoteAddr = node.Config().RPC.ListenAddress
+ // set the `remoteAddr` of the client to the listening address of the node, which is randomly assigned.
+ flags.remoteAddr = remoteAddr
app := makeApp()
diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go
index 9a7a0f91d3b..757c5f2248c 100644
--- a/gno.land/pkg/gnoland/app.go
+++ b/gno.land/pkg/gnoland/app.go
@@ -199,7 +199,8 @@ func EndBlocker(vmk vm.VMKeeperI) func(ctx sdk.Context, req abci.RequestEndBlock
}
}
-// XXX: should be removed in favor of https://github.com/gnolang/gno/pull/1233
+// XXX: all the method bellow should be removed in favor of
+// https://github.com/gnolang/gno/pull/1233
var (
guessOnce sync.Once
gnoroot string
diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go
index 721f2c726f2..7dba82bc6a3 100644
--- a/gno.land/pkg/gnoland/types.go
+++ b/gno.land/pkg/gnoland/types.go
@@ -1,7 +1,6 @@
package gnoland
import (
- "errors"
"fmt"
"strings"
@@ -29,9 +28,9 @@ type Balance struct {
}
func (b *Balance) Parse(line string) error {
- parts := strings.Split(strings.TrimSpace(line), "=") // =
+ parts := strings.Split(strings.TrimSpace(line), "=") // =
if len(parts) != 2 {
- return errors.New("invalid genesis_balance line: " + line)
+ return fmt.Errorf("invalid balance line: %q", line)
}
var err error
@@ -52,6 +51,7 @@ func (b *Balance) Parse(line string) error {
func (b *Balance) UnmarshalJSON(data []byte) error {
return b.Parse(string(data))
}
+
func (b *Balance) Marshaljson() ([]byte, error) {
return []byte(b.String()), nil
}
@@ -59,13 +59,3 @@ func (b *Balance) Marshaljson() ([]byte, error) {
func (b Balance) String() string {
return fmt.Sprintf("%s=%s", b.Address.String(), b.Value.String())
}
-
-// type Balances []Balance
-
-// func (bs Balances) Strings() []string {
-// bss := make([]string, len(bs))
-// for i, balance := range bs {
-// bss[i] = balance.String()
-// }
-// return bss
-// }
diff --git a/gno.land/pkg/integration/node.go b/gno.land/pkg/integration/node.go
index 69a013f4572..10d44db2223 100644
--- a/gno.land/pkg/integration/node.go
+++ b/gno.land/pkg/integration/node.go
@@ -13,7 +13,6 @@ import (
"github.com/gnolang/gno/tm2/pkg/bft/config"
"github.com/gnolang/gno/tm2/pkg/bft/node"
"github.com/gnolang/gno/tm2/pkg/bft/proxy"
- "github.com/gnolang/gno/tm2/pkg/bft/types"
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/crypto/ed25519"
"github.com/gnolang/gno/tm2/pkg/db"
@@ -36,10 +35,11 @@ type NodeConfig struct {
func NewNode(logger log.Logger, cfg NodeConfig) (*node.Node, error) {
// Setup setup testing config if needed
{
+ const defaultListner = "tcp://127.0.0.1:0"
if cfg.BFTConfig == nil {
cfg.BFTConfig = config.TestConfig()
- cfg.BFTConfig.RPC.ListenAddress = "tcp://127.0.0.1:0"
- cfg.BFTConfig.P2P.ListenAddress = "tcp://127.0.0.1:0"
+ cfg.BFTConfig.RPC.ListenAddress = defaultListner
+ cfg.BFTConfig.P2P.ListenAddress = defaultListner
}
// XXX: we need to get ride of this, for now needed because of stdlib
@@ -56,7 +56,6 @@ func NewNode(logger log.Logger, cfg NodeConfig) (*node.Node, error) {
// Setup geeneis
gen := &bft.GenesisDoc{}
{
-
gen.GenesisTime = time.Now()
// cfg.chainID = "tendermint_test"
@@ -125,7 +124,7 @@ func NewNode(logger log.Logger, cfg NodeConfig) (*node.Node, error) {
)
// Create genesis factory.
- genProvider := func() (*types.GenesisDoc, error) {
+ genProvider := func() (*bft.GenesisDoc, error) {
return gen, nil
}
@@ -146,7 +145,6 @@ func LoadPackages(pkgs []PackagePath) ([]std.Tx, error) {
return nil, fmt.Errorf("unable to load packages: %w", err)
}
txs = append(txs, tx...)
-
}
return txs, nil
}
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
index 8cfe5171e7c..ea3ab667f91 100644
--- a/gno.land/pkg/integration/testing_node.go
+++ b/gno.land/pkg/integration/testing_node.go
@@ -9,7 +9,6 @@ import (
abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
"github.com/gnolang/gno/tm2/pkg/bft/config"
"github.com/gnolang/gno/tm2/pkg/bft/node"
- "github.com/gnolang/gno/tm2/pkg/bft/types"
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/events"
@@ -32,7 +31,7 @@ func TestingInMemoryNode(t *testing.T, logger log.Logger, config *NodeConfig) (*
// Wait for first block by waiting for `EventNewBlock` event.
nb := make(chan struct{}, 1)
node.EventSwitch().AddListener(listenerID, func(ev events.Event) {
- if _, ok := ev.(types.EventNewBlock); ok {
+ if _, ok := ev.(bft.EventNewBlock); ok {
select {
case nb <- struct{}{}:
default:
@@ -121,10 +120,12 @@ func DefaultConsensusParams(t *testing.T, gnoroot string) *abci.ConsensusParams
func DefaultTestingBFTConfig(t *testing.T, gnoroot string) *config.Config {
t.Helper()
+ const defaultListner = "tcp://127.0.0.1:0"
+
bftconfig := config.TestConfig().SetRootDir(gnoroot)
bftconfig.Consensus.CreateEmptyBlocks = true
bftconfig.Consensus.CreateEmptyBlocksInterval = time.Duration(0)
- bftconfig.RPC.ListenAddress = "tcp://127.0.0.1:0"
- bftconfig.P2P.ListenAddress = "tcp://127.0.0.1:0"
+ bftconfig.RPC.ListenAddress = defaultListner
+ bftconfig.P2P.ListenAddress = defaultListner
return bftconfig
}
From 6d761d731da65e9d22b05f3eb46951712d05566f Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Fri, 13 Oct 2023 12:56:06 +0200
Subject: [PATCH 14/38] wip: testing integration inmemory node
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoland/start.go | 214 +++++++-----------
gno.land/pkg/gnoland/types.go | 58 +++++
gno.land/pkg/integration/node.go | 121 +++-------
gno.land/pkg/integration/node_test.go | 16 --
.../pkg/integration/testing_integration.go | 96 +++-----
gno.land/pkg/integration/testing_node.go | 49 ++--
6 files changed, 217 insertions(+), 337 deletions(-)
delete mode 100644 gno.land/pkg/integration/node_test.go
diff --git a/gno.land/cmd/gnoland/start.go b/gno.land/cmd/gnoland/start.go
index b2134d86ea9..6564133eedc 100644
--- a/gno.land/cmd/gnoland/start.go
+++ b/gno.land/cmd/gnoland/start.go
@@ -5,14 +5,9 @@ import (
"flag"
"fmt"
"path/filepath"
- "strings"
"time"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
- vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm"
- gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
- "github.com/gnolang/gno/gnovm/pkg/gnomod"
- "github.com/gnolang/gno/tm2/pkg/amino"
abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
"github.com/gnolang/gno/tm2/pkg/bft/config"
"github.com/gnolang/gno/tm2/pkg/bft/node"
@@ -26,13 +21,14 @@ import (
)
type startCfg struct {
+ gnoRootDir string
skipFailingGenesisTxs bool
skipStart bool
genesisBalancesFile string
genesisTxsFile string
chainID string
genesisRemote string
- rootDir string
+ dataDir string
genesisMaxVMCycles int64
config string
}
@@ -54,6 +50,10 @@ func newStartCmd(io *commands.IO) *commands.Command {
}
func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
+ gnoroot := gnoland.MustGuessGnoRootDir()
+ defaultGenesisBalancesFile := filepath.Join(gnoroot, "gno.land/genesis/genesis_balances.txt")
+ defaultGenesisTxsFile := filepath.Join(gnoroot, "gno.land/genesis/genesis_txs.txt")
+
fs.BoolVar(
&c.skipFailingGenesisTxs,
"skip-failing-genesis-txs",
@@ -71,14 +71,14 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
fs.StringVar(
&c.genesisBalancesFile,
"genesis-balances-file",
- "./genesis/genesis_balances.txt",
+ defaultGenesisBalancesFile,
"initial distribution file",
)
fs.StringVar(
&c.genesisTxsFile,
"genesis-txs-file",
- "./genesis/genesis_txs.txt",
+ defaultGenesisTxsFile,
"initial txs to replay",
)
@@ -90,8 +90,16 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
)
fs.StringVar(
- &c.rootDir,
- "root-dir",
+ &c.gnoRootDir,
+ "gnoroot-dir",
+ gnoroot,
+ "the root directory of the gno repository",
+ )
+
+ // XXX: Use home directory for this
+ fs.StringVar(
+ &c.dataDir,
+ "data-dir",
"testdir",
"directory for config and data",
)
@@ -116,37 +124,43 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
"",
"config file (optional)",
)
+
+ // XXX(deprecated): use data-dir instead
+ fs.StringVar(
+ &c.dataDir,
+ "root-dir",
+ "testdir",
+ "deprecated: use data-dir instead - directory for config and data",
+ )
}
func execStart(c *startCfg, args []string, io *commands.IO) error {
logger := log.NewTMLogger(log.NewSyncWriter(io.Out))
- rootDir := c.rootDir
+ dataDir := c.dataDir
- cfg := config.LoadOrMakeConfigWithOptions(rootDir, func(cfg *config.Config) {
+ cfg := config.LoadOrMakeConfigWithOptions(dataDir, func(cfg *config.Config) {
cfg.Consensus.CreateEmptyBlocks = true
cfg.Consensus.CreateEmptyBlocksInterval = 0 * time.Second
})
- // create priv validator first.
- // need it to generate genesis.json
- newPrivValKey := cfg.PrivValidatorKeyFile()
- newPrivValState := cfg.PrivValidatorStateFile()
- priv := privval.LoadOrGenFilePV(newPrivValKey, newPrivValState)
-
- // write genesis file if missing.
- genesisFilePath := filepath.Join(rootDir, cfg.Genesis)
+ // Write genesis file if missing.
+ genesisFilePath := filepath.Join(dataDir, cfg.Genesis)
if !osm.FileExists(genesisFilePath) {
- genDoc := makeGenesisDoc(
- priv.GetPubKey(),
- c.chainID,
- c.genesisBalancesFile,
- loadGenesisTxs(c.genesisTxsFile, c.chainID, c.genesisRemote),
- )
- writeGenesisFile(genDoc, genesisFilePath)
+ // Create priv validator first.
+ // Need it to generate genesis.json
+ newPrivValKey := cfg.PrivValidatorKeyFile()
+ newPrivValState := cfg.PrivValidatorStateFile()
+ priv := privval.LoadOrGenFilePV(newPrivValKey, newPrivValState)
+ pk := priv.GetPubKey()
+
+ // Generate genesis.json file
+ if err := generateGenesisFile(genesisFilePath, pk, c); err != nil {
+ return fmt.Errorf("unable to generate genesis file: %w", err)
+ }
}
- // create application and node.
- gnoApp, err := gnoland.NewApp(rootDir, c.skipFailingGenesisTxs, logger, c.genesisMaxVMCycles)
+ // Create application and node.
+ gnoApp, err := gnoland.NewApp(dataDir, c.skipFailingGenesisTxs, logger, c.genesisMaxVMCycles)
if err != nil {
return fmt.Errorf("error in creating new app: %w", err)
}
@@ -158,11 +172,10 @@ func execStart(c *startCfg, args []string, io *commands.IO) error {
return fmt.Errorf("error in creating node: %w", err)
}
- fmt.Fprintln(io.Err, "Node created.")
+ io.ErrPrintln("Node created.")
if c.skipStart {
- fmt.Fprintln(io.Err, "'--skip-start' is set. Exiting.")
-
+ io.ErrPrintln("'--skip-start' is set. Exiting.")
return nil
}
@@ -170,27 +183,20 @@ func execStart(c *startCfg, args []string, io *commands.IO) error {
return fmt.Errorf("error in start node: %w", err)
}
- // run forever
osm.TrapSignal(func() {
if gnoNode.IsRunning() {
_ = gnoNode.Stop()
}
})
- select {} // run forever
+ // Run forever
+ select {}
}
-// Makes a local test genesis doc with local privValidator.
-func makeGenesisDoc(
- pvPub crypto.PubKey,
- chainID string,
- genesisBalancesFile string,
- genesisTxs []std.Tx,
-) *bft.GenesisDoc {
+func generateGenesisFile(genesisFile string, pk crypto.PubKey, c *startCfg) error {
gen := &bft.GenesisDoc{}
-
gen.GenesisTime = time.Now()
- gen.ChainID = chainID
+ gen.ChainID = c.chainID
gen.ConsensusParams = abci.ConsensusParams{
Block: &abci.BlockParams{
// TODO: update limits.
@@ -200,121 +206,55 @@ func makeGenesisDoc(
TimeIotaMS: 100, // 100ms
},
}
+
gen.Validators = []bft.GenesisValidator{
{
- Address: pvPub.Address(),
- PubKey: pvPub,
+ Address: pk.Address(),
+ PubKey: pk,
Power: 10,
Name: "testvalidator",
},
}
- // Load distribution.
- balances := loadGenesisBalances(genesisBalancesFile)
- // debug: for _, balance := range balances { fmt.Println(balance) }
+ // Load balances files
+ balances, err := gnoland.LoadGenesisBalancesFile(c.genesisBalancesFile)
+ if err != nil {
+ return fmt.Errorf("unable to load genesis balances file %q: %w", c.genesisBalancesFile, err)
+ }
- // Load initial packages from examples.
+ // Load examples folder
+ examplesDir := filepath.Join(c.gnoRootDir, "examples")
test1 := crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
- txs := []std.Tx{}
-
- // List initial packages to load from examples.
- pkgs, err := gnomod.ListPkgs(filepath.Join("..", "examples"))
- if err != nil {
- panic(fmt.Errorf("listing gno packages: %w", err))
+ examplePkgs := gnoland.PackagePath{
+ Path: examplesDir,
+ Creator: test1,
+ Fee: std.NewFee(50000, std.MustParseCoin("1000000ugnot")),
+ Deposit: nil,
}
- // Sort packages by dependencies.
- sortedPkgs, err := pkgs.Sort()
+ pkgsTxs, err := examplePkgs.Load()
if err != nil {
- panic(fmt.Errorf("sorting packages: %w", err))
+ return fmt.Errorf("unable to load examples folder: %w", err)
}
- // Filter out draft packages.
- nonDraftPkgs := sortedPkgs.GetNonDraftPkgs()
-
- for _, pkg := range nonDraftPkgs {
- // open files in directory as MemPackage.
- memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name)
-
- var tx std.Tx
- tx.Msgs = []std.Msg{
- vmm.MsgAddPackage{
- Creator: test1,
- Package: memPkg,
- Deposit: nil,
- },
- }
- tx.Fee = std.NewFee(50000, std.MustParseCoin("1000000ugnot"))
- tx.Signatures = make([]std.Signature, len(tx.GetSigners()))
- txs = append(txs, tx)
+ // 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)
}
- // load genesis txs from file.
- txs = append(txs, genesisTxs...)
+ genesisTxs = append(pkgsTxs, genesisTxs...)
- // construct genesis AppState.
+ // Construct genesis AppState.
gen.AppState = gnoland.GnoGenesisState{
Balances: balances,
- Txs: txs,
+ Txs: genesisTxs,
}
- return gen
-}
-func writeGenesisFile(gen *bft.GenesisDoc, filePath string) {
- err := gen.SaveAs(filePath)
- if err != nil {
- panic(err)
+ // Write genesis state
+ if err := gen.SaveAs(genesisFile); err != nil {
+ return fmt.Errorf("unable to write genesis file %q: %w", genesisFile, err)
}
-}
-
-func loadGenesisTxs(
- path string,
- chainID string,
- genesisRemote string,
-) []std.Tx {
- txs := []std.Tx{}
- txsBz := osm.MustReadFile(path)
- txsLines := strings.Split(string(txsBz), "\n")
- for _, txLine := range txsLines {
- if txLine == "" {
- continue // skip empty line
- }
-
- // patch the TX
- txLine = strings.ReplaceAll(txLine, "%%CHAINID%%", chainID)
- txLine = strings.ReplaceAll(txLine, "%%REMOTE%%", genesisRemote)
- var tx std.Tx
- amino.MustUnmarshalJSON([]byte(txLine), &tx)
- txs = append(txs, tx)
- }
-
- return txs
-}
-
-func loadGenesisBalances(path string) []string {
- // each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot
- balances := []string{}
- content := osm.MustReadFile(path)
- lines := strings.Split(string(content), "\n")
- for _, line := range lines {
- line = strings.TrimSpace(line)
-
- // remove comments.
- line = strings.Split(line, "#")[0]
- line = strings.TrimSpace(line)
-
- // skip empty lines.
- if line == "" {
- continue
- }
-
- parts := strings.Split(line, "=")
- if len(parts) != 2 {
- panic("invalid genesis_balance line: " + line)
- }
-
- balances = append(balances, line)
- }
- return balances
+ return nil
}
diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go
index 7dba82bc6a3..3101e5d7d40 100644
--- a/gno.land/pkg/gnoland/types.go
+++ b/gno.land/pkg/gnoland/types.go
@@ -1,9 +1,13 @@
package gnoland
import (
+ "errors"
"fmt"
"strings"
+ vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm"
+ gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
+ "github.com/gnolang/gno/gnovm/pkg/gnomod"
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/std"
@@ -59,3 +63,57 @@ func (b *Balance) Marshaljson() ([]byte, error) {
func (b Balance) String() string {
return fmt.Sprintf("%s=%s", b.Address.String(), b.Value.String())
}
+
+type PackagePath struct {
+ Creator bft.Address
+ Deposit std.Coins
+ Fee std.Fee
+ Path string
+}
+
+func (p PackagePath) Load() ([]std.Tx, error) {
+ if p.Creator.IsZero() {
+ return nil, errors.New("empty creator address")
+ }
+
+ if p.Path == "" {
+ return nil, errors.New("empty package path")
+ }
+
+ // list all packages from target path
+ pkgs, err := gnomod.ListPkgs(p.Path)
+ if err != nil {
+ return nil, fmt.Errorf("listing gno packages: %w", err)
+ }
+
+ // Sort packages by dependencies.
+ sortedPkgs, err := pkgs.Sort()
+ if err != nil {
+ return nil, fmt.Errorf("sorting packages: %w", err)
+ }
+
+ // Filter out draft packages.
+ nonDraftPkgs := sortedPkgs.GetNonDraftPkgs()
+ txs := []std.Tx{}
+ for _, pkg := range nonDraftPkgs {
+ // Open files in directory as MemPackage.
+ memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name)
+
+ // Create transaction
+ tx := std.Tx{
+ Fee: p.Fee,
+ Msgs: []std.Msg{
+ vmm.MsgAddPackage{
+ Creator: p.Creator,
+ Package: memPkg,
+ Deposit: p.Deposit,
+ },
+ },
+ }
+
+ tx.Signatures = make([]std.Signature, len(tx.GetSigners()))
+ txs = append(txs, tx)
+ }
+
+ return txs, nil
+}
diff --git a/gno.land/pkg/integration/node.go b/gno.land/pkg/integration/node.go
index 10d44db2223..546c2c0b90b 100644
--- a/gno.land/pkg/integration/node.go
+++ b/gno.land/pkg/integration/node.go
@@ -1,16 +1,12 @@
package integration
import (
- "errors"
"fmt"
"time"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
- vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm"
- gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
- "github.com/gnolang/gno/gnovm/pkg/gnomod"
abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
- "github.com/gnolang/gno/tm2/pkg/bft/config"
+ bftconfig "github.com/gnolang/gno/tm2/pkg/bft/config"
"github.com/gnolang/gno/tm2/pkg/bft/node"
"github.com/gnolang/gno/tm2/pkg/bft/proxy"
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
@@ -21,66 +17,57 @@ import (
"github.com/gnolang/gno/tm2/pkg/std"
)
-type NodeConfig struct {
- BFTConfig *config.Config
+type TestingNodeConfig struct {
+ BFTConfig *bftconfig.Config
ConsensusParams abci.ConsensusParams
GenesisValidator []bft.GenesisValidator
- Packages []PackagePath
+ Packages []gnoland.PackagePath
Balances []gnoland.Balance
GenesisTXs []std.Tx
SkipFailingGenesisTxs bool
GenesisMaxVMCycles int64
}
-func NewNode(logger log.Logger, cfg NodeConfig) (*node.Node, error) {
- // Setup setup testing config if needed
- {
- const defaultListner = "tcp://127.0.0.1:0"
- if cfg.BFTConfig == nil {
- cfg.BFTConfig = config.TestConfig()
- cfg.BFTConfig.RPC.ListenAddress = defaultListner
- cfg.BFTConfig.P2P.ListenAddress = defaultListner
- }
+func NewTestingNodeConfig() *TestingNodeConfig {
+ return &TestingNodeConfig{
+ BFTConfig: bftconfig.TestConfig(),
+ ConsensusParams: abci.ConsensusParams{
+ Block: &abci.BlockParams{
+ MaxTxBytes: 1_000_000, // 1MB,
+ MaxDataBytes: 2_000_000, // 2MB,
+ MaxGas: 10_0000_000, // 10M gas
+ TimeIotaMS: 100, // 100ms
+ },
+ },
+ GenesisMaxVMCycles: 10_000_000,
+ }
+}
- // XXX: we need to get ride of this, for now needed because of stdlib
- if cfg.BFTConfig.RootDir == "" {
- gnoRootDir := gnoland.MustGuessGnoRootDir()
- cfg.BFTConfig.SetRootDir(gnoRootDir)
- }
+func NewTestingNode(logger log.Logger, cfg *TestingNodeConfig) (*node.Node, error) {
+ if cfg.BFTConfig == nil {
+ return nil, fmt.Errorf("no BFTConfig given")
}
- // generate node identity
nodekey := &p2p.NodeKey{PrivKey: ed25519.GenPrivKey()}
- priv := bft.NewMockPVWithParams(nodekey.PrivKey, false, false)
+ pv := bft.NewMockPVWithParams(ed25519.GenPrivKey(), false, false)
// Setup geeneis
gen := &bft.GenesisDoc{}
{
gen.GenesisTime = time.Now()
- // cfg.chainID = "tendermint_test"
gen.ChainID = cfg.BFTConfig.ChainID()
- // XXX(gfanton): Do we need some default here ?
- // if icfg.ConsensusParams.Block == nil {
- // icfg.ConsensusParams.Block = &abci.BlockParams{
- // MaxTxBytes: 1000000, // 1MB,
- // MaxDataBytes: 2000000, // 2MB,
- // MaxGas: 10000000, // 10M gas
- // TimeIotaMS: 100, // 100ms
- // }
- // }
gen.ConsensusParams = cfg.ConsensusParams
- pk := priv.GetPubKey()
-
- // start with self validator
+ // Register self first
+ pk := pv.GetPubKey()
gen.Validators = []bft.GenesisValidator{
{
Address: pk.Address(),
PubKey: pk,
Power: 10,
- Name: "rootValidator",
+ Name: "self",
},
}
@@ -129,7 +116,7 @@ func NewNode(logger log.Logger, cfg NodeConfig) (*node.Node, error) {
}
return node.NewNode(cfg.BFTConfig,
- priv, nodekey,
+ pv, nodekey,
appClientCreator,
genProvider,
node.DefaultDBProvider,
@@ -137,7 +124,7 @@ func NewNode(logger log.Logger, cfg NodeConfig) (*node.Node, error) {
)
}
-func LoadPackages(pkgs []PackagePath) ([]std.Tx, error) {
+func LoadPackages(pkgs []gnoland.PackagePath) ([]std.Tx, error) {
txs := []std.Tx{}
for _, pkg := range pkgs {
tx, err := pkg.Load()
@@ -148,57 +135,3 @@ func LoadPackages(pkgs []PackagePath) ([]std.Tx, error) {
}
return txs, nil
}
-
-type PackagePath struct {
- Creator bft.Address
- Deposit std.Coins
- Fee std.Fee
- Path string
-}
-
-func (p PackagePath) Load() ([]std.Tx, error) {
- if p.Creator.IsZero() {
- return nil, errors.New("empty creator address")
- }
-
- if p.Path == "" {
- return nil, errors.New("empty package path")
- }
-
- // list all packages from target path
- pkgs, err := gnomod.ListPkgs(p.Path)
- if err != nil {
- return nil, fmt.Errorf("listing gno packages: %w", err)
- }
-
- // Sort packages by dependencies.
- sortedPkgs, err := pkgs.Sort()
- if err != nil {
- return nil, fmt.Errorf("sorting packages: %w", err)
- }
-
- // Filter out draft packages.
- nonDraftPkgs := sortedPkgs.GetNonDraftPkgs()
- txs := []std.Tx{}
- for _, pkg := range nonDraftPkgs {
- // Open files in directory as MemPackage.
- memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name)
-
- // Create transaction
- tx := std.Tx{
- Fee: p.Fee,
- Msgs: []std.Msg{
- vmm.MsgAddPackage{
- Creator: p.Creator,
- Package: memPkg,
- Deposit: p.Deposit,
- },
- },
- }
-
- tx.Signatures = make([]std.Signature, len(tx.GetSigners()))
- txs = append(txs, tx)
- }
-
- return txs, nil
-}
diff --git a/gno.land/pkg/integration/node_test.go b/gno.land/pkg/integration/node_test.go
deleted file mode 100644
index b327117c897..00000000000
--- a/gno.land/pkg/integration/node_test.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package integration
-
-import (
- "testing"
-
- "github.com/gnolang/gno/tm2/pkg/log"
- "github.com/jaekwon/testify/require"
-)
-
-func TestNewInMemory(t *testing.T) {
- logger := log.TestingLogger()
-
- node, err := NewNode(logger, NodeConfig{})
- require.NoError(t, err)
- require.NotNil(t, node)
-}
diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go
index 1092230cf5e..da6ac5ad826 100644
--- a/gno.land/pkg/integration/testing_integration.go
+++ b/gno.land/pkg/integration/testing_integration.go
@@ -10,25 +10,16 @@ import (
"strings"
"sync"
"testing"
- "time"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
"github.com/gnolang/gno/tm2/pkg/bft/node"
- "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/commands"
"github.com/gnolang/gno/tm2/pkg/crypto/keys"
"github.com/gnolang/gno/tm2/pkg/crypto/keys/client"
- "github.com/gnolang/gno/tm2/pkg/events"
"github.com/gnolang/gno/tm2/pkg/log"
"github.com/rogpeppe/go-internal/testscript"
)
-// XXX: This should be centralize somewhere.
-const (
- test1Addr = "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"
- test1Seed = "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast"
-)
-
type testNode struct {
*node.Node
logger log.Logger
@@ -64,8 +55,6 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
var muNodes sync.Mutex
nodes := map[string]*testNode{}
- nodeConfig := DefaultTestingNodeConfig(t, gnoRootDir)
-
updateScripts, _ := strconv.ParseBool(os.Getenv("UPDATE_SCRIPTS"))
persistWorkDir, _ := strconv.ParseBool(os.Getenv("TESTWORK"))
return testscript.Params{
@@ -79,9 +68,11 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
}
// XXX: Add a command to add custom account.
- kb.CreateAccount("test1", test1Seed, "", "", 0, 0)
- env.Setenv("USER_SEED_test1", test1Seed)
- env.Setenv("USER_ADDR_test1", test1Addr)
+
+ // Setup "test1" default account
+ kb.CreateAccount(DefaultAccountName, DefaultAccountSeed, "", "", 0, 0)
+ env.Setenv("USER_SEED_"+DefaultAccountName, DefaultAccountSeed)
+ env.Setenv("USER_ADDR_"+DefaultAccountName, DefaultAccountAddress)
env.Setenv("GNOROOT", gnoRootDir)
env.Setenv("GNOHOME", gnoHomeDir)
@@ -117,57 +108,32 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
logger = getTestingLogger(ts, logname)
}
- var node *node.Node
- if node, err = execInMemoryGnoland(logger, nodeConfig); err == nil {
- nodes[sid] = &testNode{
- Node: node,
- logger: logger,
- }
- ts.Defer(func() {
- muNodes.Lock()
- defer muNodes.Unlock()
-
- if n := nodes[sid]; n != nil {
- if err := n.Stop(); err != nil {
- panic(fmt.Errorf("node %q was unable to stop: %w", sid, err))
- }
- }
- })
-
- // Get listen address environment.
- // It should have been updated with the right port on start.
- laddr := node.Config().RPC.ListenAddress
-
- // Add default environements.
- ts.Setenv("RPC_ADDR", laddr)
- // ts.Setenv("GNODATA", gnoDataDir)
-
- // XXX: This should be replace by https://github.com/gnolang/gno/pull/1216
- const listenerID = "testing_listener"
-
- // Wait for first block by waiting for `EventNewBlock` event.
- nb := make(chan struct{}, 1)
- node.EventSwitch().AddListener(listenerID, func(ev events.Event) {
- if _, ok := ev.(types.EventNewBlock); ok {
- select {
- case nb <- struct{}{}:
- default:
- }
- }
- })
+ // Generate node config, we can't use a uniq config, because
+ nodeConfig := DefaultTestingNodeConfig(t, gnoRootDir)
+ node, remoteAddr := TestingInMemoryNode(t, logger, nodeConfig)
+
+ // Setup cleanup
+ ts.Defer(func() {
+ muNodes.Lock()
+ defer muNodes.Unlock()
- if node.BlockStore().Height() == 0 {
- select {
- case <-nb: // ok
- case <-time.After(time.Second * 6):
- ts.Fatalf("timeout while waiting for the node to start")
+ if n := nodes[sid]; n != nil {
+ if err := node.Stop(); err != nil {
+ panic(fmt.Errorf("node %q was unable to stop: %w", sid, err))
}
}
+ })
- node.EventSwitch().RemoveListener(listenerID)
-
- fmt.Fprintln(ts.Stdout(), "node started successfully")
+ // Register cleanup.
+ nodes[sid] = &testNode{
+ Node: node,
+ logger: logger,
}
+
+ // Add default environements.
+ ts.Setenv("RPC_ADDR", remoteAddr)
+
+ fmt.Fprintln(ts.Stdout(), "node started successfully")
case "stop":
n, ok := nodes[sid]
if !ok {
@@ -180,7 +146,6 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
// Unset gnoland environements.
ts.Setenv("RPC_ADDR", "")
- // ts.Setenv("GNODATA", "")
fmt.Fprintln(ts.Stdout(), "node stopped successfully")
}
default:
@@ -283,15 +248,6 @@ func getTestingLogger(ts *testscript.TestScript, logname string) log.Logger {
return logger
}
-func execInMemoryGnoland(logger log.Logger, config *NodeConfig) (*node.Node, error) {
- node, err := NewNode(logger, *config)
- if err != nil {
- return nil, fmt.Errorf("unable to start the node: %w", err)
- }
-
- return node, node.Start()
-}
-
func tsValidateError(ts *testscript.TestScript, cmd string, neg bool, err error) {
if err != nil {
fmt.Fprintf(ts.Stderr(), "%q error: %v\n", cmd, err)
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
index ea3ab667f91..c522e1c885c 100644
--- a/gno.land/pkg/integration/testing_node.go
+++ b/gno.land/pkg/integration/testing_node.go
@@ -17,18 +17,27 @@ import (
"github.com/jaekwon/testify/require"
)
+const (
+ DefaultAccountName = "test1"
+ DefaultAccountAddress = "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"
+ DefaultAccountSeed = "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast"
+)
+
// Should return an already starting node
-func TestingInMemoryNode(t *testing.T, logger log.Logger, config *NodeConfig) (*node.Node, string) {
- node, err := NewNode(logger, *config)
+func TestingInMemoryNode(t *testing.T, logger log.Logger, config *TestingNodeConfig) (*node.Node, string) {
+ t.Helper()
+
+ node, err := NewTestingNode(logger, config)
require.NoError(t, err)
err = node.Start()
require.NoError(t, err)
// XXX: This should be replace by https://github.com/gnolang/gno/pull/1216
+ //---
+ // Wait for first block by waiting for `EventNewBlock` event.
const listenerID = "testing_listener"
- // Wait for first block by waiting for `EventNewBlock` event.
nb := make(chan struct{}, 1)
node.EventSwitch().AddListener(listenerID, func(ev events.Event) {
if _, ok := ev.(bft.EventNewBlock); ok {
@@ -48,36 +57,36 @@ func TestingInMemoryNode(t *testing.T, logger log.Logger, config *NodeConfig) (*
}
node.EventSwitch().RemoveListener(listenerID)
+ // ---
return node, node.Config().RPC.ListenAddress
}
-func DefaultTestingNodeConfig(t *testing.T, gnoroot string) *NodeConfig {
+func DefaultTestingNodeConfig(t *testing.T, gnoroot string) *TestingNodeConfig {
t.Helper()
bftconfig := DefaultTestingBFTConfig(t, gnoroot)
-
- return &NodeConfig{
- Balances: LoadDefaultGenesisBalanceFile(t, gnoroot),
- GenesisTXs: LoadDefaultGenesisTXsFile(t, bftconfig.ChainID(), gnoroot),
- BFTConfig: bftconfig,
- Packages: LoadDefaultPackages(t, crypto.MustAddressFromString(test1Addr), gnoroot),
+ return &TestingNodeConfig{
+ Balances: LoadDefaultGenesisBalanceFile(t, gnoroot),
+ GenesisTXs: LoadDefaultGenesisTXsFile(t, bftconfig.ChainID(), gnoroot),
+ ConsensusParams: DefaultConsensusParams(t),
+ BFTConfig: bftconfig,
+ Packages: LoadDefaultPackages(t, crypto.MustAddressFromString(DefaultAccountAddress), gnoroot),
}
}
-func LoadDefaultPackages(t *testing.T, creator bft.Address, gnoroot string) []PackagePath {
+func LoadDefaultPackages(t *testing.T, creator bft.Address, gnoroot string) []gnoland.PackagePath {
t.Helper()
exampleDir := filepath.Join(gnoroot, "examples")
- pkgs := PackagePath{
- // Creator: crypto.MustAddressFromString(test1Addr),
+ pkgs := gnoland.PackagePath{
Creator: creator,
Fee: std.NewFee(50000, std.MustParseCoin("1000000ugnot")),
Path: exampleDir,
}
- return []PackagePath{pkgs}
+ return []gnoland.PackagePath{pkgs}
}
func LoadDefaultGenesisBalanceFile(t *testing.T, gnoroot string) []gnoland.Balance {
@@ -104,15 +113,15 @@ func LoadDefaultGenesisTXsFile(t *testing.T, chainid string, gnoroot string) []s
return genesisTXs
}
-func DefaultConsensusParams(t *testing.T, gnoroot string) *abci.ConsensusParams {
+func DefaultConsensusParams(t *testing.T) abci.ConsensusParams {
t.Helper()
- return &abci.ConsensusParams{
+ return abci.ConsensusParams{
Block: &abci.BlockParams{
- MaxTxBytes: 1000000, // 1MB,
- MaxDataBytes: 2000000, // 2MB,
- MaxGas: 10000000, // 10M gas
- TimeIotaMS: 100, // 100ms
+ MaxTxBytes: 1_000_000, // 1MB,
+ MaxDataBytes: 2_000_000, // 2MB,
+ MaxGas: 10_000_000, // 10M gas
+ TimeIotaMS: 100, // 100ms
},
}
}
From 19cfdb08ce41455254e680774ed8b241373f7232 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Mon, 16 Oct 2023 15:10:11 +0200
Subject: [PATCH 15/38] chore: lint
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoweb/main_test.go | 3 +-
.../node.go => gnoland/node_inmemory.go} | 58 ++++++------
.../pkg/integration/testing_integration.go | 27 ++++--
gno.land/pkg/integration/testing_node.go | 88 ++++++++++---------
4 files changed, 99 insertions(+), 77 deletions(-)
rename gno.land/pkg/{integration/node.go => gnoland/node_inmemory.go} (64%)
diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go
index d395c442fbf..e95c04dd1f6 100644
--- a/gno.land/cmd/gnoweb/main_test.go
+++ b/gno.land/cmd/gnoweb/main_test.go
@@ -48,7 +48,8 @@ func TestRoutes(t *testing.T) {
node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNopLogger(), config)
defer node.Stop()
- // set the `remoteAddr` of the client to the listening address of the node, which is randomly assigned.
+ // set the `remoteAddr` of the client to the listening address of the
+ // node, which is randomly assigned.
flags.remoteAddr = remoteAddr
app := makeApp()
diff --git a/gno.land/pkg/integration/node.go b/gno.land/pkg/gnoland/node_inmemory.go
similarity index 64%
rename from gno.land/pkg/integration/node.go
rename to gno.land/pkg/gnoland/node_inmemory.go
index 546c2c0b90b..fc422903bec 100644
--- a/gno.land/pkg/integration/node.go
+++ b/gno.land/pkg/gnoland/node_inmemory.go
@@ -1,12 +1,11 @@
-package integration
+package gnoland
import (
"fmt"
"time"
- "github.com/gnolang/gno/gno.land/pkg/gnoland"
abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
- bftconfig "github.com/gnolang/gno/tm2/pkg/bft/config"
+ tmcfg "github.com/gnolang/gno/tm2/pkg/bft/config"
"github.com/gnolang/gno/tm2/pkg/bft/node"
"github.com/gnolang/gno/tm2/pkg/bft/proxy"
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
@@ -17,20 +16,20 @@ import (
"github.com/gnolang/gno/tm2/pkg/std"
)
-type TestingNodeConfig struct {
- BFTConfig *bftconfig.Config
+type InMemoryNodeConfig struct {
+ TMConfig *tmcfg.Config
ConsensusParams abci.ConsensusParams
GenesisValidator []bft.GenesisValidator
- Packages []gnoland.PackagePath
- Balances []gnoland.Balance
+ Packages []PackagePath
+ Balances []Balance
GenesisTXs []std.Tx
SkipFailingGenesisTxs bool
GenesisMaxVMCycles int64
}
-func NewTestingNodeConfig() *TestingNodeConfig {
- return &TestingNodeConfig{
- BFTConfig: bftconfig.TestConfig(),
+func NewInMemoryNodeConfig(tmcfg *tmcfg.Config) *InMemoryNodeConfig {
+ return &InMemoryNodeConfig{
+ TMConfig: tmcfg,
ConsensusParams: abci.ConsensusParams{
Block: &abci.BlockParams{
MaxTxBytes: 1_000_000, // 1MB,
@@ -43,11 +42,16 @@ func NewTestingNodeConfig() *TestingNodeConfig {
}
}
-func NewTestingNode(logger log.Logger, cfg *TestingNodeConfig) (*node.Node, error) {
- if cfg.BFTConfig == nil {
- return nil, fmt.Errorf("no BFTConfig given")
+// NewInMemoryNode create an inMemeory gnoland node. In this mode, the node will
+// not persist any data using an InMemory Database. For now the only indirect
+// requirement is that `InMemoryNodeConfig.TMConfig.RootDir` is pointing to
+// correct gno repository so that the node can load stdlibs
+func NewInMemoryNode(logger log.Logger, cfg *InMemoryNodeConfig) (*node.Node, error) {
+ if cfg.TMConfig == nil {
+ return nil, fmt.Errorf("no TMConfig given")
}
+ // Create Identity
nodekey := &p2p.NodeKey{PrivKey: ed25519.GenPrivKey()}
pv := bft.NewMockPVWithParams(ed25519.GenPrivKey(), false, false)
@@ -56,7 +60,7 @@ func NewTestingNode(logger log.Logger, cfg *TestingNodeConfig) (*node.Node, erro
{
gen.GenesisTime = time.Now()
- gen.ChainID = cfg.BFTConfig.ChainID()
+ gen.ChainID = cfg.TMConfig.ChainID()
gen.ConsensusParams = cfg.ConsensusParams
@@ -76,7 +80,7 @@ func NewTestingNode(logger log.Logger, cfg *TestingNodeConfig) (*node.Node, erro
}
}
- // XXX: maybe let the user do this manually and pass it to genesisTXs
+ // XXX: Maybe let the user do this manually and pass it to genesisTXs
txs, err := LoadPackages(cfg.Packages)
if err != nil {
return nil, fmt.Errorf("uanble to load genesis packages: %w", err)
@@ -84,14 +88,14 @@ func NewTestingNode(logger log.Logger, cfg *TestingNodeConfig) (*node.Node, erro
txs = append(txs, cfg.GenesisTXs...)
- gen.AppState = gnoland.GnoGenesisState{
+ gen.AppState = GnoGenesisState{
Balances: cfg.Balances,
Txs: txs,
}
- gnoApp, err := gnoland.NewAppWithOptions(&gnoland.AppOptions{
+ gnoApp, err := NewAppWithOptions(&AppOptions{
Logger: logger,
- GnoRootDir: cfg.BFTConfig.RootDir,
+ GnoRootDir: cfg.TMConfig.RootDir,
SkipFailingGenesisTxs: cfg.SkipFailingGenesisTxs,
MaxCycles: cfg.GenesisMaxVMCycles,
DB: db.NewMemDB(),
@@ -100,22 +104,22 @@ func NewTestingNode(logger log.Logger, cfg *TestingNodeConfig) (*node.Node, erro
return nil, fmt.Errorf("error in creating new app: %w", err)
}
- cfg.BFTConfig.LocalApp = gnoApp
+ cfg.TMConfig.LocalApp = gnoApp
- // Get app client creator.
+ // Get app client creator
appClientCreator := proxy.DefaultClientCreator(
- cfg.BFTConfig.LocalApp,
- cfg.BFTConfig.ProxyApp,
- cfg.BFTConfig.ABCI,
- cfg.BFTConfig.DBDir(),
+ cfg.TMConfig.LocalApp,
+ cfg.TMConfig.ProxyApp,
+ cfg.TMConfig.ABCI,
+ cfg.TMConfig.DBDir(),
)
- // Create genesis factory.
+ // Create genesis factory
genProvider := func() (*bft.GenesisDoc, error) {
return gen, nil
}
- return node.NewNode(cfg.BFTConfig,
+ return node.NewNode(cfg.TMConfig,
pv, nodekey,
appClientCreator,
genProvider,
@@ -124,7 +128,7 @@ func NewTestingNode(logger log.Logger, cfg *TestingNodeConfig) (*node.Node, erro
)
}
-func LoadPackages(pkgs []gnoland.PackagePath) ([]std.Tx, error) {
+func LoadPackages(pkgs []PackagePath) ([]std.Tx, error) {
txs := []std.Tx{}
for _, pkg := range pkgs {
tx, err := pkg.Load()
diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go
index da6ac5ad826..be87ea1135a 100644
--- a/gno.land/pkg/integration/testing_integration.go
+++ b/gno.land/pkg/integration/testing_integration.go
@@ -12,6 +12,7 @@ import (
"testing"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
+ "github.com/gnolang/gno/tm2/pkg/bft/config"
"github.com/gnolang/gno/tm2/pkg/bft/node"
"github.com/gnolang/gno/tm2/pkg/commands"
"github.com/gnolang/gno/tm2/pkg/crypto/keys"
@@ -47,10 +48,6 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
// `gnoHomeDir` should be the local directory where gnokey stores keys.
gnoHomeDir := filepath.Join(tmpdir, "gno")
- // `gnoDataDir` should refer to the local location where the gnoland node
- // stores its configuration and data.
- // gnoDataDir := filepath.Join(tmpdir, "data")
-
// Testscripts run concurrently by default, so we need to be prepared for that.
var muNodes sync.Mutex
nodes := map[string]*testNode{}
@@ -108,9 +105,21 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
logger = getTestingLogger(ts, logname)
}
- // Generate node config, we can't use a uniq config, because
- nodeConfig := DefaultTestingNodeConfig(t, gnoRootDir)
- node, remoteAddr := TestingInMemoryNode(t, logger, nodeConfig)
+ // Generate node config
+ cfg := config.TestConfig().SetRootDir(gnoRootDir)
+
+ // Use random port be able to run test in parallel without conflict
+ cfg.P2P.ListenAddress = "tcp://127.0.0.1:0"
+ cfg.RPC.ListenAddress = "tcp://127.0.0.1:0"
+
+ // Create the Node
+ nodecfg := gnoland.NewInMemoryNodeConfig(cfg)
+
+ node, err := gnoland.NewInMemoryNode(logger, nodecfg)
+ if err != nil {
+ err = fmt.Errorf("unable to start node: %w", err)
+ break
+ }
// Setup cleanup
ts.Defer(func() {
@@ -130,6 +139,8 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
logger: logger,
}
+ remoteAddr := node.Config().RPC.ListenAddress
+
// Add default environements.
ts.Setenv("RPC_ADDR", remoteAddr)
@@ -256,7 +267,7 @@ func tsValidateError(ts *testscript.TestScript, cmd string, neg bool, err error)
}
} else {
if neg {
- ts.Fatalf("unexpected %s command success", cmd)
+ ts.Fatalf("unexpected %q command success", cmd)
}
}
}
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
index c522e1c885c..dcb9083e994 100644
--- a/gno.land/pkg/integration/testing_node.go
+++ b/gno.land/pkg/integration/testing_node.go
@@ -2,12 +2,13 @@ package integration
import (
"path/filepath"
+ "sync"
"testing"
"time"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
- "github.com/gnolang/gno/tm2/pkg/bft/config"
+ tmcfg "github.com/gnolang/gno/tm2/pkg/bft/config"
"github.com/gnolang/gno/tm2/pkg/bft/node"
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/crypto"
@@ -24,53 +25,33 @@ const (
)
// Should return an already starting node
-func TestingInMemoryNode(t *testing.T, logger log.Logger, config *TestingNodeConfig) (*node.Node, string) {
+func TestingInMemoryNode(t *testing.T, logger log.Logger, config *gnoland.InMemoryNodeConfig) (*node.Node, string) {
t.Helper()
- node, err := NewTestingNode(logger, config)
+ node, err := gnoland.NewInMemoryNode(logger, config)
require.NoError(t, err)
err = node.Start()
require.NoError(t, err)
- // XXX: This should be replace by https://github.com/gnolang/gno/pull/1216
- //---
- // Wait for first block by waiting for `EventNewBlock` event.
- const listenerID = "testing_listener"
-
- nb := make(chan struct{}, 1)
- node.EventSwitch().AddListener(listenerID, func(ev events.Event) {
- if _, ok := ev.(bft.EventNewBlock); ok {
- select {
- case nb <- struct{}{}:
- default:
- }
- }
- })
-
- if node.BlockStore().Height() == 0 {
- select {
- case <-nb: // ok
- case <-time.After(time.Second * 6):
- t.Fatal("timeout while waiting for the node to start")
- }
+ select {
+ case <-waitForNodeReadiness(node):
+ case <-time.After(time.Second * 6):
+ require.FailNow(t, "timeout while waiting for the node to start")
}
- node.EventSwitch().RemoveListener(listenerID)
- // ---
-
return node, node.Config().RPC.ListenAddress
}
-func DefaultTestingNodeConfig(t *testing.T, gnoroot string) *TestingNodeConfig {
+func DefaultTestingNodeConfig(t *testing.T, gnoroot string) *gnoland.InMemoryNodeConfig {
t.Helper()
- bftconfig := DefaultTestingBFTConfig(t, gnoroot)
- return &TestingNodeConfig{
+ tmconfig := DefaultTestingTMConfig(t, gnoroot)
+ return &gnoland.InMemoryNodeConfig{
Balances: LoadDefaultGenesisBalanceFile(t, gnoroot),
- GenesisTXs: LoadDefaultGenesisTXsFile(t, bftconfig.ChainID(), gnoroot),
+ GenesisTXs: LoadDefaultGenesisTXsFile(t, tmconfig.ChainID(), gnoroot),
ConsensusParams: DefaultConsensusParams(t),
- BFTConfig: bftconfig,
+ TMConfig: tmconfig,
Packages: LoadDefaultPackages(t, crypto.MustAddressFromString(DefaultAccountAddress), gnoroot),
}
}
@@ -105,8 +86,8 @@ func LoadDefaultGenesisTXsFile(t *testing.T, chainid string, gnoroot string) []s
txsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.txt")
- // NOTE: we dont care about giving a correct address here, as it's only visual
- // XXX: do we care loading this file ?
+ // NOTE: We dont care about giving a correct address here, as it's only for display
+ // XXX: Do we care loading this TXs for testing ?
genesisTXs, err := gnoland.LoadGenesisTxsFile(txsFile, chainid, "https://127.0.0.1:26657")
require.NoError(t, err)
@@ -126,15 +107,40 @@ func DefaultConsensusParams(t *testing.T) abci.ConsensusParams {
}
}
-func DefaultTestingBFTConfig(t *testing.T, gnoroot string) *config.Config {
+func DefaultTestingTMConfig(t *testing.T, gnoroot string) *tmcfg.Config {
t.Helper()
const defaultListner = "tcp://127.0.0.1:0"
- bftconfig := config.TestConfig().SetRootDir(gnoroot)
- bftconfig.Consensus.CreateEmptyBlocks = true
- bftconfig.Consensus.CreateEmptyBlocksInterval = time.Duration(0)
- bftconfig.RPC.ListenAddress = defaultListner
- bftconfig.P2P.ListenAddress = defaultListner
- return bftconfig
+ tmconfig := tmcfg.TestConfig().SetRootDir(gnoroot)
+ tmconfig.Consensus.CreateEmptyBlocks = true
+ tmconfig.Consensus.CreateEmptyBlocksInterval = time.Duration(0)
+ tmconfig.RPC.ListenAddress = defaultListner
+ tmconfig.P2P.ListenAddress = defaultListner
+ return tmconfig
+}
+
+// XXX: This should be replace by https://github.com/gnolang/gno/pull/1216
+func waitForNodeReadiness(n *node.Node) <-chan struct{} {
+ const listenerID = "first_block_listener"
+
+ var once sync.Once
+
+ nb := make(chan struct{})
+ ready := func() {
+ close(nb)
+ n.EventSwitch().RemoveListener(listenerID)
+ }
+
+ n.EventSwitch().AddListener(listenerID, func(ev events.Event) {
+ if _, ok := ev.(bft.EventNewBlock); ok {
+ once.Do(ready)
+ }
+ })
+
+ if n.BlockStore().Height() > 0 {
+ once.Do(ready)
+ }
+
+ return nb
}
From 7300c4e99fe47654d250eadfa3be2e4a825b0d2d Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 19 Oct 2023 09:01:49 -0400
Subject: [PATCH 16/38] fix(integration): waiting for node readiness
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoland/testdata/addpkg.txtar | 11 +-
.../pkg/integration/testing_integration.go | 120 +++++++++++-------
2 files changed, 79 insertions(+), 52 deletions(-)
diff --git a/gno.land/cmd/gnoland/testdata/addpkg.txtar b/gno.land/cmd/gnoland/testdata/addpkg.txtar
index 5e871b058ac..5f1ee0caf49 100644
--- a/gno.land/cmd/gnoland/testdata/addpkg.txtar
+++ b/gno.land/cmd/gnoland/testdata/addpkg.txtar
@@ -10,7 +10,11 @@ gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/foobar/bar -gas-fee 10000
gnokey maketx call -pkgpath gno.land/r/foobar/bar -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1
## compare render
-cmp stdout stdout.golden
+stdout '("hello from foo" string)'
+stdout 'OK!'
+stdout 'GAS WANTED: 2000000'
+stdout 'GAS USED: [0-9]+'
+
-- bar.gno --
package bar
@@ -19,8 +23,3 @@ func Render(path string) string {
return "hello from foo"
}
--- stdout.golden --
-("hello from foo" string)
-OK!
-GAS WANTED: 2000000
-GAS USED: 69163
\ No newline at end of file
diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go
index be87ea1135a..6c11838a45c 100644
--- a/gno.land/pkg/integration/testing_integration.go
+++ b/gno.land/pkg/integration/testing_integration.go
@@ -2,6 +2,7 @@ package integration
import (
"context"
+ "errors"
"fmt"
"hash/crc32"
"os"
@@ -10,20 +11,22 @@ import (
"strings"
"sync"
"testing"
+ "time"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
"github.com/gnolang/gno/tm2/pkg/bft/config"
"github.com/gnolang/gno/tm2/pkg/bft/node"
"github.com/gnolang/gno/tm2/pkg/commands"
+ "github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/crypto/keys"
"github.com/gnolang/gno/tm2/pkg/crypto/keys/client"
"github.com/gnolang/gno/tm2/pkg/log"
+ "github.com/gnolang/gno/tm2/pkg/std"
"github.com/rogpeppe/go-internal/testscript"
)
type testNode struct {
*node.Node
- logger log.Logger
nGnoKeyExec uint // Counter for execution of gnokey.
}
@@ -64,10 +67,33 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
return err
}
- // XXX: Add a command to add custom account.
+ // create sessions ID
+ var sid string
+ {
+ works := env.Getenv("WORK")
+ sum := crc32.ChecksumIEEE([]byte(works))
+ sid = strconv.FormatUint(uint64(sum), 16)
+ env.Setenv("SID", sid)
+ }
+
+ // setup logger
+ var logger log.Logger
+ {
+ logger = log.NewNopLogger()
+ if persistWorkDir || os.Getenv("LOG_DIR") != "" {
+ logname := fmt.Sprintf("gnoland-%s.log", sid)
+ logger, err = getTestingLogger(env, logname)
+ if err != nil {
+ return fmt.Errorf("unable to setup logger: %w", err)
+ }
+ }
+
+ env.Values["_logger"] = logger
+ }
// Setup "test1" default account
kb.CreateAccount(DefaultAccountName, DefaultAccountSeed, "", "", 0, 0)
+
env.Setenv("USER_SEED_"+DefaultAccountName, DefaultAccountSeed)
env.Setenv("USER_ADDR_"+DefaultAccountName, DefaultAccountAddress)
@@ -86,7 +112,8 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
return
}
- sid := getSessionID(ts)
+ logger := ts.Value("_logger").(log.Logger) // grab logger
+ sid := ts.Getenv("SID") // grab session id
var cmd string
cmd, args = args[0], args[1:]
@@ -99,12 +126,6 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
break
}
- logger := log.NewNopLogger()
- if persistWorkDir || os.Getenv("LOG_DIR") != "" {
- logname := fmt.Sprintf("gnoland-%s.log", sid)
- logger = getTestingLogger(ts, logname)
- }
-
// Generate node config
cfg := config.TestConfig().SetRootDir(gnoRootDir)
@@ -115,31 +136,21 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
// Create the Node
nodecfg := gnoland.NewInMemoryNodeConfig(cfg)
- node, err := gnoland.NewInMemoryNode(logger, nodecfg)
- if err != nil {
- err = fmt.Errorf("unable to start node: %w", err)
+ // Setup balance for default account
+ nodecfg.Balances = append(nodecfg.Balances, gnoland.Balance{
+ Address: crypto.MustAddressFromString(DefaultAccountAddress),
+ Value: std.MustParseCoins("10000000000000ugnot"),
+ })
+
+ var n *node.Node
+ if n, err = execInMemoryGnoland(ts, logger, nodecfg); err != nil {
break
}
- // Setup cleanup
- ts.Defer(func() {
- muNodes.Lock()
- defer muNodes.Unlock()
-
- if n := nodes[sid]; n != nil {
- if err := node.Stop(); err != nil {
- panic(fmt.Errorf("node %q was unable to stop: %w", sid, err))
- }
- }
- })
-
// Register cleanup.
- nodes[sid] = &testNode{
- Node: node,
- logger: logger,
- }
+ nodes[sid] = &testNode{Node: n}
- remoteAddr := node.Config().RPC.ListenAddress
+ remoteAddr := n.Config().RPC.ListenAddress
// Add default environements.
ts.Setenv("RPC_ADDR", remoteAddr)
@@ -169,7 +180,8 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
muNodes.Lock()
defer muNodes.Unlock()
- sid := getSessionID(ts)
+ logger := ts.Value("_logger").(log.Logger) // grab logger
+ sid := ts.Getenv("SID") // grab session id
// Setup IO command.
io := commands.NewTestIO()
@@ -190,9 +202,10 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
n.nGnoKeyExec++
headerlog := fmt.Sprintf("%.02d!EXEC_GNOKEY", n.nGnoKeyExec)
+
// Log the command inside gnoland logger, so we can better scope errors.
- n.logger.Info(headerlog, strings.Join(args, " "))
- defer n.logger.Info(headerlog, "END")
+ logger.Info(headerlog, strings.Join(args, " "))
+ defer logger.Info(headerlog, "END")
}
// Inject default argument, if duplicate
@@ -208,35 +221,50 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
}
}
-func getSessionID(ts *testscript.TestScript) string {
- works := ts.Getenv("WORK")
- sum := crc32.ChecksumIEEE([]byte(works))
- return strconv.FormatUint(uint64(sum), 16)
+func execInMemoryGnoland(ts *testscript.TestScript, logger log.Logger, nodecfg *gnoland.InMemoryNodeConfig) (*node.Node, error) {
+ n, err := gnoland.NewInMemoryNode(logger, nodecfg)
+ if err != nil {
+ return nil, fmt.Errorf("unable to create node: %w", err)
+ }
+
+ if err = n.Start(); err != nil {
+ return nil, fmt.Errorf("unable to start node: %w", err)
+ }
+
+ select {
+ case <-time.After(time.Second * 6):
+ return nil, errors.New("timeout while waiting for the node to start")
+ case <-waitForNodeReadiness(n): // ok
+ }
+
+ return n, nil
}
-func getTestingLogger(ts *testscript.TestScript, logname string) log.Logger {
+func getTestingLogger(env *testscript.Env, logname string) (log.Logger, error) {
var path string
+
if logdir := os.Getenv("LOG_DIR"); logdir != "" {
if err := os.MkdirAll(logdir, 0o755); err != nil {
- ts.Fatalf("unable to make log directory %q", logdir)
+ return nil, fmt.Errorf("unable to make log directory %q", logdir)
+
}
var err error
if path, err = filepath.Abs(filepath.Join(logdir, logname)); err != nil {
- ts.Fatalf("uanble to get absolute path of logdir %q", logdir)
+ return nil, fmt.Errorf("uanble to get absolute path of logdir %q", logdir)
}
- } else if workdir := ts.Getenv("WORK"); workdir != "" {
+ } else if workdir := env.Getenv("WORK"); workdir != "" {
path = filepath.Join(workdir, logname)
} else {
- return log.NewNopLogger()
+ return log.NewNopLogger(), nil
}
f, err := os.Create(path)
if err != nil {
- ts.Fatalf("unable to create log file %q: %s", path, err.Error())
+ return nil, fmt.Errorf("unable to create log file %q: %w", path, err)
}
- ts.Defer(func() {
+ env.Defer(func() {
if err := f.Close(); err != nil {
panic(fmt.Errorf("unable to close log file %q: %w", path, err))
}
@@ -252,11 +280,11 @@ func getTestingLogger(ts *testscript.TestScript, logname string) log.Logger {
logger.SetLevel(log.LevelInfo)
case "":
default:
- ts.Fatalf("invalid log level %q", level)
+ return nil, fmt.Errorf("invalid log level %q", level)
}
- ts.Logf("starting logger: %q", path)
- return logger
+ env.T().Log("starting logger: %q", path)
+ return logger, nil
}
func tsValidateError(ts *testscript.TestScript, cmd string, neg bool, err error) {
From 7ee015b16078bbacac32f2ef712d6355d366943e Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 19 Oct 2023 10:33:37 -0400
Subject: [PATCH 17/38] chore: lint
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/integration/testing_integration.go | 1 -
1 file changed, 1 deletion(-)
diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go
index 6c11838a45c..004bd9260da 100644
--- a/gno.land/pkg/integration/testing_integration.go
+++ b/gno.land/pkg/integration/testing_integration.go
@@ -246,7 +246,6 @@ func getTestingLogger(env *testscript.Env, logname string) (log.Logger, error) {
if logdir := os.Getenv("LOG_DIR"); logdir != "" {
if err := os.MkdirAll(logdir, 0o755); err != nil {
return nil, fmt.Errorf("unable to make log directory %q", logdir)
-
}
var err error
From aee3dd9cb6337b71d0774a16fc40fbecf279baa9 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Fri, 20 Oct 2023 10:08:29 -0400
Subject: [PATCH 18/38] chore: improve comments
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/gnoland/genesis.go | 2 +-
gno.land/pkg/gnoland/node_inmemory.go | 60 ++++++++++++------------
gno.land/pkg/integration/testing_node.go | 10 +++-
3 files changed, 39 insertions(+), 33 deletions(-)
diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go
index b155b212219..9b527590ae7 100644
--- a/gno.land/pkg/gnoland/genesis.go
+++ b/gno.land/pkg/gnoland/genesis.go
@@ -53,7 +53,7 @@ func LoadGenesisBalancesFile(path string) ([]Balance, error) {
return balances, nil
}
-// XXX: we can do something better here
+// XXX: Improve the way we generate and load this file
func LoadGenesisTxsFile(path string, chainID string, genesisRemote string) ([]std.Tx, error) {
txs := []std.Tx{}
txsBz := osm.MustReadFile(path)
diff --git a/gno.land/pkg/gnoland/node_inmemory.go b/gno.land/pkg/gnoland/node_inmemory.go
index fc422903bec..bb677188fee 100644
--- a/gno.land/pkg/gnoland/node_inmemory.go
+++ b/gno.land/pkg/gnoland/node_inmemory.go
@@ -27,6 +27,7 @@ type InMemoryNodeConfig struct {
GenesisMaxVMCycles int64
}
+// NewInMemoryNodeConfig creates a default configuration for an in-memory node.
func NewInMemoryNodeConfig(tmcfg *tmcfg.Config) *InMemoryNodeConfig {
return &InMemoryNodeConfig{
TMConfig: tmcfg,
@@ -42,57 +43,52 @@ func NewInMemoryNodeConfig(tmcfg *tmcfg.Config) *InMemoryNodeConfig {
}
}
-// NewInMemoryNode create an inMemeory gnoland node. In this mode, the node will
-// not persist any data using an InMemory Database. For now the only indirect
-// requirement is that `InMemoryNodeConfig.TMConfig.RootDir` is pointing to
-// correct gno repository so that the node can load stdlibs
+// NewInMemoryNode creates an in-memory gnoland node. In this mode, the node does not
+// persist any data and uses an in-memory database. The `InMemoryNodeConfig.TMConfig.RootDir`
+// should point to the correct gno repository to load the stdlibs.
func NewInMemoryNode(logger log.Logger, cfg *InMemoryNodeConfig) (*node.Node, error) {
if cfg.TMConfig == nil {
- return nil, fmt.Errorf("no TMConfig given")
+ return nil, fmt.Errorf("no `TMConfig` given")
+ }
+
+ if cfg.TMConfig.RootDir == "" {
+ return nil, fmt.Errorf("`TMConfig.RootDir` is required but not provided")
}
// Create Identity
nodekey := &p2p.NodeKey{PrivKey: ed25519.GenPrivKey()}
pv := bft.NewMockPVWithParams(ed25519.GenPrivKey(), false, false)
- // Setup geeneis
- gen := &bft.GenesisDoc{}
- {
- gen.GenesisTime = time.Now()
-
- gen.ChainID = cfg.TMConfig.ChainID()
-
- gen.ConsensusParams = cfg.ConsensusParams
-
- // Register self first
- pk := pv.GetPubKey()
- gen.Validators = []bft.GenesisValidator{
+ // Set up genesis with default values and additional validators
+ gen := &bft.GenesisDoc{
+ GenesisTime: time.Now(),
+ ChainID: cfg.TMConfig.ChainID(),
+ ConsensusParams: cfg.ConsensusParams,
+ Validators: []bft.GenesisValidator{
{
- Address: pk.Address(),
- PubKey: pk,
+ Address: pv.GetPubKey().Address(),
+ PubKey: pv.GetPubKey(),
Power: 10,
Name: "self",
},
- }
-
- for _, validator := range cfg.GenesisValidator {
- gen.Validators = append(gen.Validators, validator)
- }
+ },
}
+ gen.Validators = append(gen.Validators, cfg.GenesisValidator...)
// XXX: Maybe let the user do this manually and pass it to genesisTXs
txs, err := LoadPackages(cfg.Packages)
if err != nil {
- return nil, fmt.Errorf("uanble to load genesis packages: %w", err)
+ return nil, fmt.Errorf("error loading genesis packages: %w", err)
}
+ // Combine loaded packages with provided genesis transactions
txs = append(txs, cfg.GenesisTXs...)
-
gen.AppState = GnoGenesisState{
Balances: cfg.Balances,
Txs: txs,
}
+ // Initialize the application with the provided options
gnoApp, err := NewAppWithOptions(&AppOptions{
Logger: logger,
GnoRootDir: cfg.TMConfig.RootDir,
@@ -101,12 +97,12 @@ func NewInMemoryNode(logger log.Logger, cfg *InMemoryNodeConfig) (*node.Node, er
DB: db.NewMemDB(),
})
if err != nil {
- return nil, fmt.Errorf("error in creating new app: %w", err)
+ return nil, fmt.Errorf("error initializing new app: %w", err)
}
cfg.TMConfig.LocalApp = gnoApp
- // Get app client creator
+ // Setup app client creator
appClientCreator := proxy.DefaultClientCreator(
cfg.TMConfig.LocalApp,
cfg.TMConfig.ProxyApp,
@@ -119,21 +115,23 @@ func NewInMemoryNode(logger log.Logger, cfg *InMemoryNodeConfig) (*node.Node, er
return gen, nil
}
+ // Create and return the in-memory node instance
return node.NewNode(cfg.TMConfig,
pv, nodekey,
appClientCreator,
genProvider,
node.DefaultDBProvider,
- logger,
+ logger
)
}
+// LoadPackages loads and returns transactions from provided package paths.
func LoadPackages(pkgs []PackagePath) ([]std.Tx, error) {
- txs := []std.Tx{}
+ var txs []std.Tx
for _, pkg := range pkgs {
tx, err := pkg.Load()
if err != nil {
- return nil, fmt.Errorf("unable to load packages: %w", err)
+ return nil, fmt.Errorf("error loading package from path %s: %w", pkg.Path, err)
}
txs = append(txs, tx...)
}
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
index dcb9083e994..80de8ecc811 100644
--- a/gno.land/pkg/integration/testing_node.go
+++ b/gno.land/pkg/integration/testing_node.go
@@ -24,7 +24,8 @@ const (
DefaultAccountSeed = "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast"
)
-// Should return an already starting node
+// TestingInMemoryNode initializes and starts an in-memory node for testing.
+// It returns the node instance and its RPC remote address.
func TestingInMemoryNode(t *testing.T, logger log.Logger, config *gnoland.InMemoryNodeConfig) (*node.Node, string) {
t.Helper()
@@ -43,6 +44,7 @@ func TestingInMemoryNode(t *testing.T, logger log.Logger, config *gnoland.InMemo
return node, node.Config().RPC.ListenAddress
}
+// DefaultTestingNodeConfig constructs the default in-memory node configuration for testing.
func DefaultTestingNodeConfig(t *testing.T, gnoroot string) *gnoland.InMemoryNodeConfig {
t.Helper()
@@ -56,6 +58,7 @@ func DefaultTestingNodeConfig(t *testing.T, gnoroot string) *gnoland.InMemoryNod
}
}
+// LoadDefaultPackages loads the default packages for testing using a given creator address and gnoroot directory.
func LoadDefaultPackages(t *testing.T, creator bft.Address, gnoroot string) []gnoland.PackagePath {
t.Helper()
@@ -70,6 +73,7 @@ func LoadDefaultPackages(t *testing.T, creator bft.Address, gnoroot string) []gn
return []gnoland.PackagePath{pkgs}
}
+// LoadDefaultGenesisBalanceFile loads the default genesis balance file for testing.
func LoadDefaultGenesisBalanceFile(t *testing.T, gnoroot string) []gnoland.Balance {
t.Helper()
@@ -81,6 +85,7 @@ func LoadDefaultGenesisBalanceFile(t *testing.T, gnoroot string) []gnoland.Balan
return genesisBalances
}
+// LoadDefaultGenesisTXsFile loads the default genesis transactions file for testing.
func LoadDefaultGenesisTXsFile(t *testing.T, chainid string, gnoroot string) []std.Tx {
t.Helper()
@@ -94,6 +99,7 @@ func LoadDefaultGenesisTXsFile(t *testing.T, chainid string, gnoroot string) []s
return genesisTXs
}
+// DefaultConsensusParams constructs the default consensus parameters for testing.
func DefaultConsensusParams(t *testing.T) abci.ConsensusParams {
t.Helper()
@@ -107,6 +113,7 @@ func DefaultConsensusParams(t *testing.T) abci.ConsensusParams {
}
}
+// DefaultTestingTMConfig constructs the default Tendermint configuration for testing.
func DefaultTestingTMConfig(t *testing.T, gnoroot string) *tmcfg.Config {
t.Helper()
@@ -120,6 +127,7 @@ func DefaultTestingTMConfig(t *testing.T, gnoroot string) *tmcfg.Config {
return tmconfig
}
+// waitForNodeReadiness waits until the node is ready, signaling via the EventNewBlock event.
// XXX: This should be replace by https://github.com/gnolang/gno/pull/1216
func waitForNodeReadiness(n *node.Node) <-chan struct{} {
const listenerID = "first_block_listener"
From 2f8bc5070ffa8ca89c93902214279232538c1410 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Sat, 21 Oct 2023 14:55:37 -0400
Subject: [PATCH 19/38] fix: update InMemoryNodeConfig
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/gnoland/node_inmemory.go | 124 +++++++++---------
gno.land/pkg/gnoland/types.go | 13 ++
.../pkg/integration/testing_integration.go | 8 +-
gno.land/pkg/integration/testing_node.go | 81 ++++++++----
4 files changed, 135 insertions(+), 91 deletions(-)
diff --git a/gno.land/pkg/gnoland/node_inmemory.go b/gno.land/pkg/gnoland/node_inmemory.go
index bb677188fee..f8d6a924876 100644
--- a/gno.land/pkg/gnoland/node_inmemory.go
+++ b/gno.land/pkg/gnoland/node_inmemory.go
@@ -9,28 +9,31 @@ import (
"github.com/gnolang/gno/tm2/pkg/bft/node"
"github.com/gnolang/gno/tm2/pkg/bft/proxy"
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
+ "github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/crypto/ed25519"
"github.com/gnolang/gno/tm2/pkg/db"
"github.com/gnolang/gno/tm2/pkg/log"
"github.com/gnolang/gno/tm2/pkg/p2p"
- "github.com/gnolang/gno/tm2/pkg/std"
)
type InMemoryNodeConfig struct {
+ PrivValidator bft.PrivValidator
+ Genesis *bft.GenesisDoc
TMConfig *tmcfg.Config
- ConsensusParams abci.ConsensusParams
- GenesisValidator []bft.GenesisValidator
- Packages []PackagePath
- Balances []Balance
- GenesisTXs []std.Tx
SkipFailingGenesisTxs bool
GenesisMaxVMCycles int64
}
+// NewMockedPrivValidator generate a new key
+func NewMockedPrivValidator() bft.PrivValidator {
+ return bft.NewMockPVWithParams(ed25519.GenPrivKey(), false, false)
+}
+
// NewInMemoryNodeConfig creates a default configuration for an in-memory node.
-func NewInMemoryNodeConfig(tmcfg *tmcfg.Config) *InMemoryNodeConfig {
- return &InMemoryNodeConfig{
- TMConfig: tmcfg,
+func NewDefaultGenesisConfig(pk crypto.PubKey, chainid string) *bft.GenesisDoc {
+ return &bft.GenesisDoc{
+ GenesisTime: time.Now(),
+ ChainID: chainid,
ConsensusParams: abci.ConsensusParams{
Block: &abci.BlockParams{
MaxTxBytes: 1_000_000, // 1MB,
@@ -39,53 +42,61 @@ func NewInMemoryNodeConfig(tmcfg *tmcfg.Config) *InMemoryNodeConfig {
TimeIotaMS: 100, // 100ms
},
},
- GenesisMaxVMCycles: 10_000_000,
}
}
-// NewInMemoryNode creates an in-memory gnoland node. In this mode, the node does not
-// persist any data and uses an in-memory database. The `InMemoryNodeConfig.TMConfig.RootDir`
-// should point to the correct gno repository to load the stdlibs.
-func NewInMemoryNode(logger log.Logger, cfg *InMemoryNodeConfig) (*node.Node, error) {
- if cfg.TMConfig == nil {
- return nil, fmt.Errorf("no `TMConfig` given")
+func NewDefaultTMConfig(rootdir string) *tmcfg.Config {
+ return tmcfg.DefaultConfig().SetRootDir(rootdir)
+}
+
+// NewInMemoryNodeConfig creates a default configuration for an in-memory node.
+func NewDefaultInMemoryNodeConfig(rootdir string) *InMemoryNodeConfig {
+ tm := NewDefaultTMConfig(rootdir)
+
+ // Create Mocked Identity
+ pv := NewMockedPrivValidator()
+ genesis := NewDefaultGenesisConfig(pv.GetPubKey(), tm.ChainID())
+
+ self := pv.GetPubKey()
+ genesis.Validators = []bft.GenesisValidator{
+ {
+ Address: self.Address(),
+ PubKey: self,
+ Power: 10,
+ Name: "self",
+ },
}
- if cfg.TMConfig.RootDir == "" {
- return nil, fmt.Errorf("`TMConfig.RootDir` is required but not provided")
+ return &InMemoryNodeConfig{
+ PrivValidator: pv,
+ TMConfig: tm,
+ Genesis: genesis,
+ GenesisMaxVMCycles: 10_000_000,
}
+}
- // Create Identity
- nodekey := &p2p.NodeKey{PrivKey: ed25519.GenPrivKey()}
- pv := bft.NewMockPVWithParams(ed25519.GenPrivKey(), false, false)
-
- // Set up genesis with default values and additional validators
- gen := &bft.GenesisDoc{
- GenesisTime: time.Now(),
- ChainID: cfg.TMConfig.ChainID(),
- ConsensusParams: cfg.ConsensusParams,
- Validators: []bft.GenesisValidator{
- {
- Address: pv.GetPubKey().Address(),
- PubKey: pv.GetPubKey(),
- Power: 10,
- Name: "self",
- },
- },
+func (cfg *InMemoryNodeConfig) validate() error {
+ if cfg.PrivValidator == nil {
+ return fmt.Errorf("`PrivValidator` is required but not provided")
}
- gen.Validators = append(gen.Validators, cfg.GenesisValidator...)
- // XXX: Maybe let the user do this manually and pass it to genesisTXs
- txs, err := LoadPackages(cfg.Packages)
- if err != nil {
- return nil, fmt.Errorf("error loading genesis packages: %w", err)
+ if cfg.TMConfig == nil {
+ return fmt.Errorf("`TMConfig` is required but not provided")
}
- // Combine loaded packages with provided genesis transactions
- txs = append(txs, cfg.GenesisTXs...)
- gen.AppState = GnoGenesisState{
- Balances: cfg.Balances,
- Txs: txs,
+ if cfg.TMConfig.RootDir == "" {
+ return fmt.Errorf("`TMConfig.RootDir` is required to locate `stdlibs` directory")
+ }
+
+ return nil
+}
+
+// NewInMemoryNode creates an in-memory gnoland node. In this mode, the node does not
+// persist any data and uses an in-memory database. The `InMemoryNodeConfig.TMConfig.RootDir`
+// should point to the correct gno repository to load the stdlibs.
+func NewInMemoryNode(logger log.Logger, cfg *InMemoryNodeConfig) (*node.Node, error) {
+ if err := cfg.validate(); err != nil {
+ return nil, fmt.Errorf("validate config error: %w", err)
}
// Initialize the application with the provided options
@@ -112,28 +123,19 @@ func NewInMemoryNode(logger log.Logger, cfg *InMemoryNodeConfig) (*node.Node, er
// Create genesis factory
genProvider := func() (*bft.GenesisDoc, error) {
- return gen, nil
+ return cfg.Genesis, nil
}
+ // generate p2p node identity
+ // XXX: do we need to configur
+ nodekey := &p2p.NodeKey{PrivKey: ed25519.GenPrivKey()}
+
// Create and return the in-memory node instance
return node.NewNode(cfg.TMConfig,
- pv, nodekey,
+ cfg.PrivValidator, nodekey,
appClientCreator,
genProvider,
node.DefaultDBProvider,
- logger
+ logger,
)
}
-
-// LoadPackages loads and returns transactions from provided package paths.
-func LoadPackages(pkgs []PackagePath) ([]std.Tx, error) {
- var txs []std.Tx
- for _, pkg := range pkgs {
- tx, err := pkg.Load()
- if err != nil {
- return nil, fmt.Errorf("error loading package from path %s: %w", pkg.Path, err)
- }
- txs = append(txs, tx...)
- }
- return txs, nil
-}
diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go
index 3101e5d7d40..7ea199cfb39 100644
--- a/gno.land/pkg/gnoland/types.go
+++ b/gno.land/pkg/gnoland/types.go
@@ -117,3 +117,16 @@ func (p PackagePath) Load() ([]std.Tx, error) {
return txs, nil
}
+
+// LoadPackages loads and returns transactions from provided package paths.
+func LoadPackages(pkgs []PackagePath) ([]std.Tx, error) {
+ var txs []std.Tx
+ for _, pkg := range pkgs {
+ tx, err := pkg.Load()
+ if err != nil {
+ return nil, fmt.Errorf("error loading package from path %s: %w", pkg.Path, err)
+ }
+ txs = append(txs, tx...)
+ }
+ return txs, nil
+}
diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go
index 004bd9260da..9a161f9fe4e 100644
--- a/gno.land/pkg/integration/testing_integration.go
+++ b/gno.land/pkg/integration/testing_integration.go
@@ -92,10 +92,10 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
}
// Setup "test1" default account
- kb.CreateAccount(DefaultAccountName, DefaultAccountSeed, "", "", 0, 0)
+ kb.CreateAccount(DefaultAccount_Name,DefaultAccount_Seedd, "", "", 0, 0)
- env.Setenv("USER_SEED_"+DefaultAccountName, DefaultAccountSeed)
- env.Setenv("USER_ADDR_"+DefaultAccountName, DefaultAccountAddress)
+ env.Setenv("USER_SEED_"+DefaultAccount_Name,DefaultAccount_Seedd)
+ env.Setenv("USER_ADDR_"+DefaultAccount_Name,DefaultAccount_Addresss)
env.Setenv("GNOROOT", gnoRootDir)
env.Setenv("GNOHOME", gnoHomeDir)
@@ -138,7 +138,7 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
// Setup balance for default account
nodecfg.Balances = append(nodecfg.Balances, gnoland.Balance{
- Address: crypto.MustAddressFromString(DefaultAccountAddress),
+ Address: crypto.MustAddressFromString(DefaultAccount_Address),
Value: std.MustParseCoins("10000000000000ugnot"),
})
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
index 80de8ecc811..0c1938db6c1 100644
--- a/gno.land/pkg/integration/testing_node.go
+++ b/gno.land/pkg/integration/testing_node.go
@@ -19,9 +19,9 @@ import (
)
const (
- DefaultAccountName = "test1"
- DefaultAccountAddress = "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"
- DefaultAccountSeed = "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_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"
)
// TestingInMemoryNode initializes and starts an in-memory node for testing.
@@ -49,28 +49,71 @@ func DefaultTestingNodeConfig(t *testing.T, gnoroot string) *gnoland.InMemoryNod
t.Helper()
tmconfig := DefaultTestingTMConfig(t, gnoroot)
+
+ // Create Mocked Identity
+ pv := gnoland.NewMockedPrivValidator()
+
+ // Generate genesis config
+ genesis := DefaultTestingGenesisConfig(t, gnoroot, pv.GetPubKey(), tmconfig)
+
return &gnoland.InMemoryNodeConfig{
- Balances: LoadDefaultGenesisBalanceFile(t, gnoroot),
- GenesisTXs: LoadDefaultGenesisTXsFile(t, tmconfig.ChainID(), gnoroot),
- ConsensusParams: DefaultConsensusParams(t),
- TMConfig: tmconfig,
- Packages: LoadDefaultPackages(t, crypto.MustAddressFromString(DefaultAccountAddress), gnoroot),
+ PrivValidator: pv,
+ Genesis: genesis,
+ TMConfig: tmconfig,
+ }
+}
+
+func DefaultTestingGenesisConfig(t *testing.T, gnoroot string, self crypto.PubKey, tmconfig *tmcfg.Config) *bft.GenesisDoc {
+ pkgCreator := crypto.MustAddressFromString(DefaultAccount_Address) // test1
+
+ // Load genesis packages
+ genesisPackagesTxs := LoadDefaultPackages(t, pkgCreator, gnoroot)
+
+ return &bft.GenesisDoc{
+ GenesisTime: time.Now(),
+ ChainID: tmconfig.ChainID(),
+ ConsensusParams: abci.ConsensusParams{
+ Block: &abci.BlockParams{
+ MaxTxBytes: 1_000_000, // 1MB,
+ MaxDataBytes: 2_000_000, // 2MB,
+ MaxGas: 10_0000_000, // 10M gas
+ TimeIotaMS: 100, // 100ms
+ },
+ },
+ Validators: []bft.GenesisValidator{
+ {
+ Address: self.Address(),
+ PubKey: self,
+ Power: 10,
+ Name: "self",
+ },
+ },
+ AppState: gnoland.GnoGenesisState{
+ Balances: []gnoland.Balance{
+ {
+ Address: pkgCreator,
+ Value: std.MustParseCoins("10000000000000ugnot"),
+ },
+ },
+ Txs: genesisPackagesTxs,
+ },
}
}
// LoadDefaultPackages loads the default packages for testing using a given creator address and gnoroot directory.
-func LoadDefaultPackages(t *testing.T, creator bft.Address, gnoroot string) []gnoland.PackagePath {
+func LoadDefaultPackages(t *testing.T, creator bft.Address, gnoroot string) []std.Tx {
t.Helper()
exampleDir := filepath.Join(gnoroot, "examples")
- pkgs := gnoland.PackagePath{
+ txs, err := gnoland.LoadPackages(gnoland.PackagePath{
Creator: creator,
Fee: std.NewFee(50000, std.MustParseCoin("1000000ugnot")),
Path: exampleDir,
- }
+ })
+ require.NoError(t, err)
- return []gnoland.PackagePath{pkgs}
+ return txs
}
// LoadDefaultGenesisBalanceFile loads the default genesis balance file for testing.
@@ -99,20 +142,6 @@ func LoadDefaultGenesisTXsFile(t *testing.T, chainid string, gnoroot string) []s
return genesisTXs
}
-// DefaultConsensusParams constructs the default consensus parameters for testing.
-func DefaultConsensusParams(t *testing.T) abci.ConsensusParams {
- t.Helper()
-
- return abci.ConsensusParams{
- Block: &abci.BlockParams{
- MaxTxBytes: 1_000_000, // 1MB,
- MaxDataBytes: 2_000_000, // 2MB,
- MaxGas: 10_000_000, // 10M gas
- TimeIotaMS: 100, // 100ms
- },
- }
-}
-
// DefaultTestingTMConfig constructs the default Tendermint configuration for testing.
func DefaultTestingTMConfig(t *testing.T, gnoroot string) *tmcfg.Config {
t.Helper()
From ff0aef2aae65e97b35bde9c84fff28a08cd38e4c Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Wed, 25 Oct 2023 18:52:07 -0400
Subject: [PATCH 20/38] chore: fix & lint
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/gnoland/node_inmemory.go | 8 +-
gno.land/pkg/gnoland/types.go | 2 +-
gno.land/pkg/integration/testing.go | 39 ++++++++++
.../pkg/integration/testing_integration.go | 75 +++++++------------
gno.land/pkg/integration/testing_node.go | 29 ++-----
5 files changed, 82 insertions(+), 71 deletions(-)
create mode 100644 gno.land/pkg/integration/testing.go
diff --git a/gno.land/pkg/gnoland/node_inmemory.go b/gno.land/pkg/gnoland/node_inmemory.go
index f8d6a924876..a0ab6a51e82 100644
--- a/gno.land/pkg/gnoland/node_inmemory.go
+++ b/gno.land/pkg/gnoland/node_inmemory.go
@@ -14,10 +14,11 @@ import (
"github.com/gnolang/gno/tm2/pkg/db"
"github.com/gnolang/gno/tm2/pkg/log"
"github.com/gnolang/gno/tm2/pkg/p2p"
+ "github.com/gnolang/gno/tm2/pkg/std"
)
type InMemoryNodeConfig struct {
- PrivValidator bft.PrivValidator
+ PrivValidator bft.PrivValidator // identity of the validator
Genesis *bft.GenesisDoc
TMConfig *tmcfg.Config
SkipFailingGenesisTxs bool
@@ -42,6 +43,10 @@ func NewDefaultGenesisConfig(pk crypto.PubKey, chainid string) *bft.GenesisDoc {
TimeIotaMS: 100, // 100ms
},
},
+ AppState: &GnoGenesisState{
+ Balances: []Balance{},
+ Txs: []std.Tx{},
+ },
}
}
@@ -57,6 +62,7 @@ func NewDefaultInMemoryNodeConfig(rootdir string) *InMemoryNodeConfig {
pv := NewMockedPrivValidator()
genesis := NewDefaultGenesisConfig(pv.GetPubKey(), tm.ChainID())
+ // Add self as validator
self := pv.GetPubKey()
genesis.Validators = []bft.GenesisValidator{
{
diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go
index 7ea199cfb39..8830251cb0d 100644
--- a/gno.land/pkg/gnoland/types.go
+++ b/gno.land/pkg/gnoland/types.go
@@ -119,7 +119,7 @@ func (p PackagePath) Load() ([]std.Tx, error) {
}
// LoadPackages loads and returns transactions from provided package paths.
-func LoadPackages(pkgs []PackagePath) ([]std.Tx, error) {
+func LoadPackages(pkgs ...PackagePath) ([]std.Tx, error) {
var txs []std.Tx
for _, pkg := range pkgs {
tx, err := pkg.Load()
diff --git a/gno.land/pkg/integration/testing.go b/gno.land/pkg/integration/testing.go
new file mode 100644
index 00000000000..7803e213da1
--- /dev/null
+++ b/gno.land/pkg/integration/testing.go
@@ -0,0 +1,39 @@
+package integration
+
+import (
+ "errors"
+
+ "github.com/jaekwon/testify/assert"
+ "github.com/jaekwon/testify/require"
+ "github.com/rogpeppe/go-internal/testscript"
+)
+
+// This error is from testscript.Fatalf and is needed to correctly
+// handle the FailNow method.
+// see: https://github.com/rogpeppe/go-internal/blob/32ae33786eccde1672d4ba373c80e1bc282bfbf6/testscript/testscript.go#L799-L812
+var errFailNow = errors.New("fail now!") //nolint:stylecheck
+
+var (
+ _ require.TestingT = (*testingTS)(nil)
+ _ assert.TestingT = (*testingTS)(nil)
+)
+
+type TestingTS = require.TestingT
+
+type testingTS struct {
+ *testscript.TestScript
+}
+
+func TSTestingT(ts *testscript.TestScript) TestingTS {
+ return &testingTS{ts}
+}
+
+func (t *testingTS) Errorf(format string, args ...interface{}) {
+ defer recover() // we can ignore recover result, we just want to catch it up
+ t.Fatalf(format, args...)
+}
+
+func (t *testingTS) FailNow() {
+ // unfortunately we can't access underlying `t.t.FailNow` method
+ panic(errFailNow)
+}
diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go
index 9a161f9fe4e..d37a900cf96 100644
--- a/gno.land/pkg/integration/testing_integration.go
+++ b/gno.land/pkg/integration/testing_integration.go
@@ -2,7 +2,6 @@ package integration
import (
"context"
- "errors"
"fmt"
"hash/crc32"
"os"
@@ -11,17 +10,13 @@ import (
"strings"
"sync"
"testing"
- "time"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
- "github.com/gnolang/gno/tm2/pkg/bft/config"
"github.com/gnolang/gno/tm2/pkg/bft/node"
"github.com/gnolang/gno/tm2/pkg/commands"
- "github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/crypto/keys"
"github.com/gnolang/gno/tm2/pkg/crypto/keys/client"
"github.com/gnolang/gno/tm2/pkg/log"
- "github.com/gnolang/gno/tm2/pkg/std"
"github.com/rogpeppe/go-internal/testscript"
)
@@ -92,10 +87,10 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
}
// Setup "test1" default account
- kb.CreateAccount(DefaultAccount_Name,DefaultAccount_Seedd, "", "", 0, 0)
+ kb.CreateAccount(DefaultAccount_Name, DefaultAccount_Seed, "", "", 0, 0)
- env.Setenv("USER_SEED_"+DefaultAccount_Name,DefaultAccount_Seedd)
- env.Setenv("USER_ADDR_"+DefaultAccount_Name,DefaultAccount_Addresss)
+ env.Setenv("USER_SEED_"+DefaultAccount_Name, DefaultAccount_Seed)
+ env.Setenv("USER_ADDR_"+DefaultAccount_Name, DefaultAccount_Address)
env.Setenv("GNOROOT", gnoRootDir)
env.Setenv("GNOHOME", gnoHomeDir)
@@ -126,33 +121,17 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
break
}
- // Generate node config
- cfg := config.TestConfig().SetRootDir(gnoRootDir)
+ // Warp up `ts` so we can pass it to other testing method
+ t := TSTestingT(ts)
- // Use random port be able to run test in parallel without conflict
- cfg.P2P.ListenAddress = "tcp://127.0.0.1:0"
- cfg.RPC.ListenAddress = "tcp://127.0.0.1:0"
+ // Generate config and node
+ cfg := DefaultTestingNodeConfig(t, gnoRootDir)
+ n, remoteAddr := TestingInMemoryNode(t, logger, cfg)
- // Create the Node
- nodecfg := gnoland.NewInMemoryNodeConfig(cfg)
-
- // Setup balance for default account
- nodecfg.Balances = append(nodecfg.Balances, gnoland.Balance{
- Address: crypto.MustAddressFromString(DefaultAccount_Address),
- Value: std.MustParseCoins("10000000000000ugnot"),
- })
-
- var n *node.Node
- if n, err = execInMemoryGnoland(ts, logger, nodecfg); err != nil {
- break
- }
-
- // Register cleanup.
+ // Register cleanup
nodes[sid] = &testNode{Node: n}
- remoteAddr := n.Config().RPC.ListenAddress
-
- // Add default environements.
+ // Add default environements
ts.Setenv("RPC_ADDR", remoteAddr)
fmt.Fprintln(ts.Stdout(), "node started successfully")
@@ -166,7 +145,7 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
if err = n.Stop(); err == nil {
delete(nodes, sid)
- // Unset gnoland environements.
+ // Unset gnoland environements
ts.Setenv("RPC_ADDR", "")
fmt.Fprintln(ts.Stdout(), "node stopped successfully")
}
@@ -183,7 +162,7 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
logger := ts.Value("_logger").(log.Logger) // grab logger
sid := ts.Getenv("SID") // grab session id
- // Setup IO command.
+ // Setup IO command
io := commands.NewTestIO()
io.SetOut(commands.WriteNopCloser(ts.Stdout()))
io.SetErr(commands.WriteNopCloser(ts.Stderr()))
@@ -221,24 +200,24 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
}
}
-func execInMemoryGnoland(ts *testscript.TestScript, logger log.Logger, nodecfg *gnoland.InMemoryNodeConfig) (*node.Node, error) {
- n, err := gnoland.NewInMemoryNode(logger, nodecfg)
- if err != nil {
- return nil, fmt.Errorf("unable to create node: %w", err)
- }
+// func execInMemoryGnoland(ts *testscript.TestScript, logger log.Logger, nodecfg *gnoland.InMemoryNodeConfig) (*node.Node, error) {
+// n, err := gnoland.NewInMemoryNode(logger, nodecfg)
+// if err != nil {
+// return nil, fmt.Errorf("unable to create node: %w", err)
+// }
- if err = n.Start(); err != nil {
- return nil, fmt.Errorf("unable to start node: %w", err)
- }
+// if err = n.Start(); err != nil {
+// return nil, fmt.Errorf("unable to start node: %w", err)
+// }
- select {
- case <-time.After(time.Second * 6):
- return nil, errors.New("timeout while waiting for the node to start")
- case <-waitForNodeReadiness(n): // ok
- }
+// select {
+// case <-time.After(time.Second * 6):
+// return nil, errors.New("timeout while waiting for the node to start")
+// case <-waitForNodeReadiness(n): // ok
+// }
- return n, nil
-}
+// return n, nil
+// }
func getTestingLogger(env *testscript.Env, logname string) (log.Logger, error) {
var path string
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
index 0c1938db6c1..9e20790ba76 100644
--- a/gno.land/pkg/integration/testing_node.go
+++ b/gno.land/pkg/integration/testing_node.go
@@ -3,7 +3,6 @@ package integration
import (
"path/filepath"
"sync"
- "testing"
"time"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
@@ -26,9 +25,7 @@ const (
// TestingInMemoryNode initializes and starts an in-memory node for testing.
// It returns the node instance and its RPC remote address.
-func TestingInMemoryNode(t *testing.T, logger log.Logger, config *gnoland.InMemoryNodeConfig) (*node.Node, string) {
- t.Helper()
-
+func TestingInMemoryNode(t TestingTS, logger log.Logger, config *gnoland.InMemoryNodeConfig) (*node.Node, string) {
node, err := gnoland.NewInMemoryNode(logger, config)
require.NoError(t, err)
@@ -45,10 +42,8 @@ func TestingInMemoryNode(t *testing.T, logger log.Logger, config *gnoland.InMemo
}
// DefaultTestingNodeConfig constructs the default in-memory node configuration for testing.
-func DefaultTestingNodeConfig(t *testing.T, gnoroot string) *gnoland.InMemoryNodeConfig {
- t.Helper()
-
- tmconfig := DefaultTestingTMConfig(t, gnoroot)
+func DefaultTestingNodeConfig(t TestingTS, gnoroot string) *gnoland.InMemoryNodeConfig {
+ tmconfig := DefaultTestingTMConfig(gnoroot)
// Create Mocked Identity
pv := gnoland.NewMockedPrivValidator()
@@ -63,7 +58,7 @@ func DefaultTestingNodeConfig(t *testing.T, gnoroot string) *gnoland.InMemoryNod
}
}
-func DefaultTestingGenesisConfig(t *testing.T, gnoroot string, self crypto.PubKey, tmconfig *tmcfg.Config) *bft.GenesisDoc {
+func DefaultTestingGenesisConfig(t TestingTS, gnoroot string, self crypto.PubKey, tmconfig *tmcfg.Config) *bft.GenesisDoc {
pkgCreator := crypto.MustAddressFromString(DefaultAccount_Address) // test1
// Load genesis packages
@@ -101,9 +96,7 @@ func DefaultTestingGenesisConfig(t *testing.T, gnoroot string, self crypto.PubKe
}
// LoadDefaultPackages loads the default packages for testing using a given creator address and gnoroot directory.
-func LoadDefaultPackages(t *testing.T, creator bft.Address, gnoroot string) []std.Tx {
- t.Helper()
-
+func LoadDefaultPackages(t TestingTS, creator bft.Address, gnoroot string) []std.Tx {
exampleDir := filepath.Join(gnoroot, "examples")
txs, err := gnoland.LoadPackages(gnoland.PackagePath{
@@ -117,9 +110,7 @@ func LoadDefaultPackages(t *testing.T, creator bft.Address, gnoroot string) []st
}
// LoadDefaultGenesisBalanceFile loads the default genesis balance file for testing.
-func LoadDefaultGenesisBalanceFile(t *testing.T, gnoroot string) []gnoland.Balance {
- t.Helper()
-
+func LoadDefaultGenesisBalanceFile(t TestingTS, gnoroot string) []gnoland.Balance {
balanceFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt")
genesisBalances, err := gnoland.LoadGenesisBalancesFile(balanceFile)
@@ -129,9 +120,7 @@ func LoadDefaultGenesisBalanceFile(t *testing.T, gnoroot string) []gnoland.Balan
}
// LoadDefaultGenesisTXsFile loads the default genesis transactions file for testing.
-func LoadDefaultGenesisTXsFile(t *testing.T, chainid string, gnoroot string) []std.Tx {
- t.Helper()
-
+func LoadDefaultGenesisTXsFile(t TestingTS, chainid string, gnoroot string) []std.Tx {
txsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.txt")
// NOTE: We dont care about giving a correct address here, as it's only for display
@@ -143,9 +132,7 @@ func LoadDefaultGenesisTXsFile(t *testing.T, chainid string, gnoroot string) []s
}
// DefaultTestingTMConfig constructs the default Tendermint configuration for testing.
-func DefaultTestingTMConfig(t *testing.T, gnoroot string) *tmcfg.Config {
- t.Helper()
-
+func DefaultTestingTMConfig(gnoroot string) *tmcfg.Config {
const defaultListner = "tcp://127.0.0.1:0"
tmconfig := tmcfg.TestConfig().SetRootDir(gnoroot)
From 3584d866de6aab2bb810e6c46ad1e119d49cacef Mon Sep 17 00:00:00 2001
From: Guilhem Fanton <8671905+gfanton@users.noreply.github.com>
Date: Thu, 26 Oct 2023 08:45:32 -0400
Subject: [PATCH 21/38] Update gno.land/cmd/gnoland/start.go
Co-authored-by: Manfred Touron <94029+moul@users.noreply.github.com>
---
gno.land/cmd/gnoland/start.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gno.land/cmd/gnoland/start.go b/gno.land/cmd/gnoland/start.go
index 0e6bc6c06c7..938d4f9b4f3 100644
--- a/gno.land/cmd/gnoland/start.go
+++ b/gno.land/cmd/gnoland/start.go
@@ -60,7 +60,7 @@ func newStartCmd(io *commands.IO) *commands.Command {
func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
gnoroot := gnoland.MustGuessGnoRootDir()
- defaultGenesisBalancesFile := filepath.Join(gnoroot, "gno.land/genesis/genesis_balances.txt")
+ defaultGenesisBalancesFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt")
defaultGenesisTxsFile := filepath.Join(gnoroot, "gno.land/genesis/genesis_txs.txt")
fs.BoolVar(
From a580f54ae02c21c08d3f61c2cb911ca8de410623 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Fri, 27 Oct 2023 10:09:32 -0400
Subject: [PATCH 22/38] chore: cleanup
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoland/start.go | 13 ++--
gno.land/cmd/gnoweb/main_test.go | 34 +++++++--
gno.land/pkg/gnoland/genesis.go | 47 ++++++++++++
gno.land/pkg/gnoland/types.go | 71 -------------------
.../pkg/integration/testing_integration.go | 19 -----
gno.land/pkg/integration/testing_node.go | 10 ++-
6 files changed, 85 insertions(+), 109 deletions(-)
diff --git a/gno.land/cmd/gnoland/start.go b/gno.land/cmd/gnoland/start.go
index 938d4f9b4f3..64164c828ac 100644
--- a/gno.land/cmd/gnoland/start.go
+++ b/gno.land/cmd/gnoland/start.go
@@ -198,6 +198,7 @@ func execStart(c *startCfg, io *commands.IO) error {
// Write genesis file if missing.
genesisFilePath := filepath.Join(dataDir, cfg.Genesis)
+
if !osm.FileExists(genesisFilePath) {
// Create priv validator first.
// Need it to generate genesis.json
@@ -231,6 +232,8 @@ func execStart(c *startCfg, io *commands.IO) error {
return fmt.Errorf("error in creating node: %w", err)
}
+ fmt.Fprintln(io.Err, "Node created.")
+
if c.skipStart {
io.ErrPrintln("'--skip-start' is set. Exiting.")
return nil
@@ -282,14 +285,8 @@ func generateGenesisFile(genesisFile string, pk crypto.PubKey, c *startCfg) erro
// Load examples folder
examplesDir := filepath.Join(c.gnoRootDir, "examples")
test1 := crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
- examplePkgs := gnoland.PackagePath{
- Path: examplesDir,
- Creator: test1,
- Fee: std.NewFee(50000, std.MustParseCoin("1000000ugnot")),
- Deposit: nil,
- }
-
- pkgsTxs, err := examplePkgs.Load()
+ defaultFee := std.NewFee(50000, std.MustParseCoin("1000000ugnot"))
+ pkgsTxs, err := gnoland.LoadPackagesFromDir(examplesDir, test1, defaultFee, nil)
if err != nil {
return fmt.Errorf("unable to load examples folder: %w", err)
}
diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go
index dd7b28d72b2..e033a3b9014 100644
--- a/gno.land/cmd/gnoweb/main_test.go
+++ b/gno.land/cmd/gnoweb/main_test.go
@@ -5,6 +5,7 @@ import (
"net/http"
"net/http/httptest"
"os"
+ "path/filepath"
"strings"
"testing"
@@ -12,6 +13,7 @@ import (
"github.com/gnolang/gno/gno.land/pkg/integration"
"github.com/gnolang/gno/tm2/pkg/log"
"github.com/gotuna/gotuna/test/assert"
+ "github.com/jaekwon/testify/require"
)
func TestRoutes(t *testing.T) {
@@ -44,12 +46,20 @@ func TestRoutes(t *testing.T) {
{"/blog", found, "/r/gnoland/blog"},
{"/404-not-found", notFound, "/404-not-found"},
}
- if wd, err := os.Getwd(); err == nil {
- if strings.HasSuffix(wd, "cmd/gnoweb") {
- os.Chdir("../..")
+
+ // XXX: The following block is really bad and should be Replace by testscripts tests
+ {
+ if wd, err := os.Getwd(); err == nil {
+ if strings.HasSuffix(wd, "cmd/gnoweb") {
+
+ currentPwd, err := filepath.Abs(".")
+ require.NoError(t, err)
+ os.Chdir("../..")
+ defer os.Chdir(currentPwd)
+ }
+ } else {
+ panic("os.Getwd() -> err: " + err.Error())
}
- } else {
- panic("os.Getwd() -> err: " + err.Error())
}
config := integration.DefaultTestingNodeConfig(t, gnoland.MustGuessGnoRootDir())
@@ -96,9 +106,22 @@ func TestAnalytics(t *testing.T) {
"/404-not-found",
}
+ config := integration.DefaultTestingNodeConfig(t, gnoland.MustGuessGnoRootDir())
+ node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNopLogger(), config)
+ defer node.Stop()
+
+ // XXX: The following block is really bad and should be Replace by testscripts tests
+ {
+ currentPwd, err := filepath.Abs("../..")
+ require.NoError(t, err)
+ os.Chdir("../..")
+ defer os.Chdir(currentPwd)
+ }
+
t.Run("with", func(t *testing.T) {
for _, route := range routes {
t.Run(route, func(t *testing.T) {
+ flags.RemoteAddr = remoteAddr
flags.WithAnalytics = true
app := makeApp()
request := httptest.NewRequest(http.MethodGet, route, nil)
@@ -111,6 +134,7 @@ func TestAnalytics(t *testing.T) {
t.Run("without", func(t *testing.T) {
for _, route := range routes {
t.Run(route, func(t *testing.T) {
+ flags.RemoteAddr = remoteAddr
flags.WithAnalytics = false
app := makeApp()
request := httptest.NewRequest(http.MethodGet, route, nil)
diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go
index 9b527590ae7..94c9d6cbf03 100644
--- a/gno.land/pkg/gnoland/genesis.go
+++ b/gno.land/pkg/gnoland/genesis.go
@@ -5,12 +5,17 @@ import (
"fmt"
"strings"
+ vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm"
+ gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
+ "github.com/gnolang/gno/gnovm/pkg/gnomod"
"github.com/gnolang/gno/tm2/pkg/amino"
+ bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/crypto"
osm "github.com/gnolang/gno/tm2/pkg/os"
"github.com/gnolang/gno/tm2/pkg/std"
)
+// LoadGenesisBalancesFile loads genesis balances from the provided file path.
func LoadGenesisBalancesFile(path string) ([]Balance, error) {
// each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot
content := osm.MustReadFile(path)
@@ -53,6 +58,7 @@ func LoadGenesisBalancesFile(path string) ([]Balance, error) {
return balances, nil
}
+// LoadGenesisTxsFile loads genesis transactions from the provided file path.
// XXX: Improve the way we generate and load this file
func LoadGenesisTxsFile(path string, chainID string, genesisRemote string) ([]std.Tx, error) {
txs := []std.Tx{}
@@ -77,3 +83,44 @@ func LoadGenesisTxsFile(path string, chainID string, genesisRemote string) ([]st
return txs, nil
}
+
+// LoadPackagesFromDir loads gno packages from a directory.
+// It creates and returns a list of transactions based on these packages.
+func LoadPackagesFromDir(dir string, creator bft.Address, fee std.Fee, deposit std.Coins) ([]std.Tx, error) {
+ // list all packages from target path
+ pkgs, err := gnomod.ListPkgs(dir)
+ if err != nil {
+ return nil, fmt.Errorf("listing gno packages: %w", err)
+ }
+
+ // Sort packages by dependencies.
+ sortedPkgs, err := pkgs.Sort()
+ if err != nil {
+ return nil, fmt.Errorf("sorting packages: %w", err)
+ }
+
+ // Filter out draft packages.
+ nonDraftPkgs := sortedPkgs.GetNonDraftPkgs()
+ txs := []std.Tx{}
+ for _, pkg := range nonDraftPkgs {
+ // Open files in directory as MemPackage.
+ memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name)
+
+ // Create transaction
+ tx := std.Tx{
+ Fee: fee,
+ Msgs: []std.Msg{
+ vmm.MsgAddPackage{
+ Creator: creator,
+ Package: memPkg,
+ Deposit: deposit,
+ },
+ },
+ }
+
+ tx.Signatures = make([]std.Signature, len(tx.GetSigners()))
+ txs = append(txs, tx)
+ }
+
+ return txs, nil
+}
diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go
index 8830251cb0d..7dba82bc6a3 100644
--- a/gno.land/pkg/gnoland/types.go
+++ b/gno.land/pkg/gnoland/types.go
@@ -1,13 +1,9 @@
package gnoland
import (
- "errors"
"fmt"
"strings"
- vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm"
- gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
- "github.com/gnolang/gno/gnovm/pkg/gnomod"
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/std"
@@ -63,70 +59,3 @@ func (b *Balance) Marshaljson() ([]byte, error) {
func (b Balance) String() string {
return fmt.Sprintf("%s=%s", b.Address.String(), b.Value.String())
}
-
-type PackagePath struct {
- Creator bft.Address
- Deposit std.Coins
- Fee std.Fee
- Path string
-}
-
-func (p PackagePath) Load() ([]std.Tx, error) {
- if p.Creator.IsZero() {
- return nil, errors.New("empty creator address")
- }
-
- if p.Path == "" {
- return nil, errors.New("empty package path")
- }
-
- // list all packages from target path
- pkgs, err := gnomod.ListPkgs(p.Path)
- if err != nil {
- return nil, fmt.Errorf("listing gno packages: %w", err)
- }
-
- // Sort packages by dependencies.
- sortedPkgs, err := pkgs.Sort()
- if err != nil {
- return nil, fmt.Errorf("sorting packages: %w", err)
- }
-
- // Filter out draft packages.
- nonDraftPkgs := sortedPkgs.GetNonDraftPkgs()
- txs := []std.Tx{}
- for _, pkg := range nonDraftPkgs {
- // Open files in directory as MemPackage.
- memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name)
-
- // Create transaction
- tx := std.Tx{
- Fee: p.Fee,
- Msgs: []std.Msg{
- vmm.MsgAddPackage{
- Creator: p.Creator,
- Package: memPkg,
- Deposit: p.Deposit,
- },
- },
- }
-
- tx.Signatures = make([]std.Signature, len(tx.GetSigners()))
- txs = append(txs, tx)
- }
-
- return txs, nil
-}
-
-// LoadPackages loads and returns transactions from provided package paths.
-func LoadPackages(pkgs ...PackagePath) ([]std.Tx, error) {
- var txs []std.Tx
- for _, pkg := range pkgs {
- tx, err := pkg.Load()
- if err != nil {
- return nil, fmt.Errorf("error loading package from path %s: %w", pkg.Path, err)
- }
- txs = append(txs, tx...)
- }
- return txs, nil
-}
diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go
index d37a900cf96..c2847c9e129 100644
--- a/gno.land/pkg/integration/testing_integration.go
+++ b/gno.land/pkg/integration/testing_integration.go
@@ -200,25 +200,6 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
}
}
-// func execInMemoryGnoland(ts *testscript.TestScript, logger log.Logger, nodecfg *gnoland.InMemoryNodeConfig) (*node.Node, error) {
-// n, err := gnoland.NewInMemoryNode(logger, nodecfg)
-// if err != nil {
-// return nil, fmt.Errorf("unable to create node: %w", err)
-// }
-
-// if err = n.Start(); err != nil {
-// return nil, fmt.Errorf("unable to start node: %w", err)
-// }
-
-// select {
-// case <-time.After(time.Second * 6):
-// return nil, errors.New("timeout while waiting for the node to start")
-// case <-waitForNodeReadiness(n): // ok
-// }
-
-// return n, nil
-// }
-
func getTestingLogger(env *testscript.Env, logname string) (log.Logger, error) {
var path string
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
index 9e20790ba76..01d575b69ac 100644
--- a/gno.land/pkg/integration/testing_node.go
+++ b/gno.land/pkg/integration/testing_node.go
@@ -97,13 +97,11 @@ func DefaultTestingGenesisConfig(t TestingTS, gnoroot string, self crypto.PubKey
// LoadDefaultPackages loads the default packages for testing using a given creator address and gnoroot directory.
func LoadDefaultPackages(t TestingTS, creator bft.Address, gnoroot string) []std.Tx {
- exampleDir := filepath.Join(gnoroot, "examples")
+ examplesDir := filepath.Join(gnoroot, "examples")
- txs, err := gnoland.LoadPackages(gnoland.PackagePath{
- Creator: creator,
- Fee: std.NewFee(50000, std.MustParseCoin("1000000ugnot")),
- Path: exampleDir,
- })
+ defaultFee := std.NewFee(50000, std.MustParseCoin("1000000ugnot"))
+ defaultCreator := crypto.MustAddressFromString(DefaultAccount_Address) // test1
+ txs, err := gnoland.LoadPackagesFromDir(examplesDir, defaultCreator, defaultFee, nil)
require.NoError(t, err)
return txs
From d9bcf3537778d4d8ab04fe0e46367f47de6200ed Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Fri, 27 Oct 2023 10:35:22 -0400
Subject: [PATCH 23/38] chore: add back previous gnoweb flag
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoweb/main_test.go | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go
index e033a3b9014..5a35b906234 100644
--- a/gno.land/cmd/gnoweb/main_test.go
+++ b/gno.land/cmd/gnoweb/main_test.go
@@ -69,6 +69,10 @@ func TestRoutes(t *testing.T) {
// set the `remoteAddr` of the client to the listening address of the
// node, which is randomly assigned.
flags.RemoteAddr = remoteAddr
+ flags.HelpChainID = "dev"
+ flags.CaptchaSite = ""
+ flags.ViewsDir = "./cmd/gnoweb/views"
+ flags.WithAnalytics = false
app := makeApp()
for _, r := range routes {
From daaa7a37a02d110c5476b5baff2d3ad6a8c3a388 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Fri, 27 Oct 2023 13:40:30 -0400
Subject: [PATCH 24/38] fix: fix gnoweb analytics test
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoweb/main_test.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go
index 5a35b906234..58392e126f2 100644
--- a/gno.land/cmd/gnoweb/main_test.go
+++ b/gno.land/cmd/gnoweb/main_test.go
@@ -131,7 +131,7 @@ func TestAnalytics(t *testing.T) {
request := httptest.NewRequest(http.MethodGet, route, nil)
response := httptest.NewRecorder()
app.Router.ServeHTTP(response, request)
- assert.Contains(t, response.Body.String(), "simpleanalytics")
+ assert.Contains(t, response.Body.String(), "sa.gno.services")
})
}
})
@@ -144,7 +144,7 @@ func TestAnalytics(t *testing.T) {
request := httptest.NewRequest(http.MethodGet, route, nil)
response := httptest.NewRecorder()
app.Router.ServeHTTP(response, request)
- assert.Equal(t, strings.Contains(response.Body.String(), "simpleanalytics"), false)
+ assert.Equal(t, strings.Contains(response.Body.String(), "sa.gno.services"), false)
})
}
})
From 81afbf4c861408e49ca59750e1c5e0fdcf093da5 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Fri, 27 Oct 2023 14:11:12 -0400
Subject: [PATCH 25/38] chore: lint
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoweb/main_test.go | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go
index 58392e126f2..2ec45854595 100644
--- a/gno.land/cmd/gnoweb/main_test.go
+++ b/gno.land/cmd/gnoweb/main_test.go
@@ -47,19 +47,13 @@ func TestRoutes(t *testing.T) {
{"/404-not-found", notFound, "/404-not-found"},
}
- // XXX: The following block is really bad and should be Replace by testscripts tests
+ // XXX: The following block should be Replace by testscripts tests
{
- if wd, err := os.Getwd(); err == nil {
- if strings.HasSuffix(wd, "cmd/gnoweb") {
-
- currentPwd, err := filepath.Abs(".")
- require.NoError(t, err)
- os.Chdir("../..")
- defer os.Chdir(currentPwd)
- }
- } else {
- panic("os.Getwd() -> err: " + err.Error())
- }
+ currentPwd, err := filepath.Abs(".")
+ require.NoError(t, err)
+ err = os.Chdir("../..")
+ require.NoError(t, err)
+ defer os.Chdir(currentPwd)
}
config := integration.DefaultTestingNodeConfig(t, gnoland.MustGuessGnoRootDir())
@@ -118,7 +112,8 @@ func TestAnalytics(t *testing.T) {
{
currentPwd, err := filepath.Abs("../..")
require.NoError(t, err)
- os.Chdir("../..")
+ err = os.Chdir("../..")
+ require.NoError(t, err)
defer os.Chdir(currentPwd)
}
From 8df3622ab827ecfc10e0a9db9b68a57a75b18def Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Fri, 27 Oct 2023 15:33:21 -0400
Subject: [PATCH 26/38] fix: add minimal and full config
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoweb/main.go | 1 +
gno.land/cmd/gnoweb/main_test.go | 28 ++-----------
.../pkg/integration/testing_integration.go | 2 +-
gno.land/pkg/integration/testing_node.go | 39 ++++++++++++-------
4 files changed, 31 insertions(+), 39 deletions(-)
diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go
index 0d9398cb8e2..83d9664bb8e 100644
--- a/gno.land/cmd/gnoweb/main.go
+++ b/gno.land/cmd/gnoweb/main.go
@@ -486,6 +486,7 @@ func writeError(w http.ResponseWriter, err error) {
// XXX: writeError should return an error page template.
w.WriteHeader(500)
+ panic(err)
details := errors.Unwrap(err).Error()
main := err.Error()
diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go
index 2ec45854595..61650563405 100644
--- a/gno.land/cmd/gnoweb/main_test.go
+++ b/gno.land/cmd/gnoweb/main_test.go
@@ -4,8 +4,6 @@ import (
"fmt"
"net/http"
"net/http/httptest"
- "os"
- "path/filepath"
"strings"
"testing"
@@ -13,7 +11,6 @@ import (
"github.com/gnolang/gno/gno.land/pkg/integration"
"github.com/gnolang/gno/tm2/pkg/log"
"github.com/gotuna/gotuna/test/assert"
- "github.com/jaekwon/testify/require"
)
func TestRoutes(t *testing.T) {
@@ -47,16 +44,7 @@ func TestRoutes(t *testing.T) {
{"/404-not-found", notFound, "/404-not-found"},
}
- // XXX: The following block should be Replace by testscripts tests
- {
- currentPwd, err := filepath.Abs(".")
- require.NoError(t, err)
- err = os.Chdir("../..")
- require.NoError(t, err)
- defer os.Chdir(currentPwd)
- }
-
- config := integration.DefaultTestingNodeConfig(t, gnoland.MustGuessGnoRootDir())
+ config, _ := integration.TestingNodeConfig(t, gnoland.MustGuessGnoRootDir())
node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNopLogger(), config)
defer node.Stop()
@@ -65,7 +53,7 @@ func TestRoutes(t *testing.T) {
flags.RemoteAddr = remoteAddr
flags.HelpChainID = "dev"
flags.CaptchaSite = ""
- flags.ViewsDir = "./cmd/gnoweb/views"
+ flags.ViewsDir = "../../cmd/gnoweb/views"
flags.WithAnalytics = false
app := makeApp()
@@ -104,19 +92,11 @@ func TestAnalytics(t *testing.T) {
"/404-not-found",
}
- config := integration.DefaultTestingNodeConfig(t, gnoland.MustGuessGnoRootDir())
+ config, _ := integration.TestingNodeConfig(t, gnoland.MustGuessGnoRootDir())
node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNopLogger(), config)
defer node.Stop()
- // XXX: The following block is really bad and should be Replace by testscripts tests
- {
- currentPwd, err := filepath.Abs("../..")
- require.NoError(t, err)
- err = os.Chdir("../..")
- require.NoError(t, err)
- defer os.Chdir(currentPwd)
- }
-
+ flags.ViewsDir = "../../cmd/gnoweb/views"
t.Run("with", func(t *testing.T) {
for _, route := range routes {
t.Run(route, func(t *testing.T) {
diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go
index c2847c9e129..b773317513f 100644
--- a/gno.land/pkg/integration/testing_integration.go
+++ b/gno.land/pkg/integration/testing_integration.go
@@ -125,7 +125,7 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params {
t := TSTestingT(ts)
// Generate config and node
- cfg := DefaultTestingNodeConfig(t, gnoRootDir)
+ cfg := TestingMinimalNodeConfig(t, gnoRootDir)
n, remoteAddr := TestingInMemoryNode(t, logger, cfg)
// Register cleanup
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
index 01d575b69ac..93fb16f683c 100644
--- a/gno.land/pkg/integration/testing_node.go
+++ b/gno.land/pkg/integration/testing_node.go
@@ -41,8 +41,29 @@ func TestingInMemoryNode(t TestingTS, logger log.Logger, config *gnoland.InMemor
return node, node.Config().RPC.ListenAddress
}
-// DefaultTestingNodeConfig constructs the default in-memory node configuration for testing.
-func DefaultTestingNodeConfig(t TestingTS, gnoroot string) *gnoland.InMemoryNodeConfig {
+// TestingNodeConfig constructs an in-memory node configuration
+// with default packages and genesis transactions already loaded.
+// It will return the default creator address of the loaded packages.
+func TestingNodeConfig(t TestingTS, gnoroot string) (*gnoland.InMemoryNodeConfig, bft.Address) {
+ cfg := TestingMinimalNodeConfig(t, gnoroot)
+
+ creator := crypto.MustAddressFromString(DefaultAccount_Address) // test1
+
+ balances := LoadDefaultGenesisBalanceFile(t, gnoroot)
+ txs := []std.Tx{}
+ txs = append(txs, LoadDefaultPackages(t, creator, gnoroot)...)
+ txs = append(txs, LoadDefaultGenesisTXsFile(t, cfg.Genesis.ChainID, gnoroot)...)
+
+ cfg.Genesis.AppState = gnoland.GnoGenesisState{
+ Balances: balances,
+ Txs: txs,
+ }
+
+ return cfg, creator
+}
+
+// TestingMinimalNodeConfig constructs the default minimal in-memory node configuration for testing.
+func TestingMinimalNodeConfig(t TestingTS, gnoroot string) *gnoland.InMemoryNodeConfig {
tmconfig := DefaultTestingTMConfig(gnoroot)
// Create Mocked Identity
@@ -59,11 +80,6 @@ func DefaultTestingNodeConfig(t TestingTS, gnoroot string) *gnoland.InMemoryNode
}
func DefaultTestingGenesisConfig(t TestingTS, gnoroot string, self crypto.PubKey, tmconfig *tmcfg.Config) *bft.GenesisDoc {
- pkgCreator := crypto.MustAddressFromString(DefaultAccount_Address) // test1
-
- // Load genesis packages
- genesisPackagesTxs := LoadDefaultPackages(t, pkgCreator, gnoroot)
-
return &bft.GenesisDoc{
GenesisTime: time.Now(),
ChainID: tmconfig.ChainID(),
@@ -84,13 +100,8 @@ func DefaultTestingGenesisConfig(t TestingTS, gnoroot string, self crypto.PubKey
},
},
AppState: gnoland.GnoGenesisState{
- Balances: []gnoland.Balance{
- {
- Address: pkgCreator,
- Value: std.MustParseCoins("10000000000000ugnot"),
- },
- },
- Txs: genesisPackagesTxs,
+ Balances: []gnoland.Balance{},
+ Txs: []std.Tx{},
},
}
}
From f6d4b247b5fdebe219bb79b18621ea7caeea700e Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Fri, 27 Oct 2023 15:56:07 -0400
Subject: [PATCH 27/38] fix: creator balances
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/integration/testing_node.go | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
index 93fb16f683c..8c3f44c9308 100644
--- a/gno.land/pkg/integration/testing_node.go
+++ b/gno.land/pkg/integration/testing_node.go
@@ -100,10 +100,16 @@ func DefaultTestingGenesisConfig(t TestingTS, gnoroot string, self crypto.PubKey
},
},
AppState: gnoland.GnoGenesisState{
- Balances: []gnoland.Balance{},
- Txs: []std.Tx{},
+ Balances: []gnoland.Balance{
+ {
+ Address: crypto.MustAddressFromString(DefaultAccount_Address),
+ Value: std.MustParseCoins("10000000000000ugnot"),
+ },
+ },
+ Txs: []std.Tx{},
},
}
+
}
// LoadDefaultPackages loads the default packages for testing using a given creator address and gnoroot directory.
From fbe030018fa4a78a1a9b3d99eae76a23d1a02285 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Fri, 27 Oct 2023 15:58:50 -0400
Subject: [PATCH 28/38] fix: lint
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/integration/testing_node.go | 1 -
1 file changed, 1 deletion(-)
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
index 8c3f44c9308..4461a0af27a 100644
--- a/gno.land/pkg/integration/testing_node.go
+++ b/gno.land/pkg/integration/testing_node.go
@@ -109,7 +109,6 @@ func DefaultTestingGenesisConfig(t TestingTS, gnoroot string, self crypto.PubKey
Txs: []std.Tx{},
},
}
-
}
// LoadDefaultPackages loads the default packages for testing using a given creator address and gnoroot directory.
From f747694983a4067125432eb1cc17e6a3edcf28a7 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Fri, 27 Oct 2023 16:46:41 -0400
Subject: [PATCH 29/38] chore: lint
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoland/start.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gno.land/cmd/gnoland/start.go b/gno.land/cmd/gnoland/start.go
index 64164c828ac..618f4f87a09 100644
--- a/gno.land/cmd/gnoland/start.go
+++ b/gno.land/cmd/gnoland/start.go
@@ -61,7 +61,7 @@ func newStartCmd(io *commands.IO) *commands.Command {
func (c *startCfg) RegisterFlags(fs *flag.FlagSet) {
gnoroot := gnoland.MustGuessGnoRootDir()
defaultGenesisBalancesFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt")
- defaultGenesisTxsFile := filepath.Join(gnoroot, "gno.land/genesis/genesis_txs.txt")
+ defaultGenesisTxsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.txt")
fs.BoolVar(
&c.skipFailingGenesisTxs,
From 248b08389db0974f48f3a7a7435381515903da50 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Fri, 27 Oct 2023 19:59:35 -0400
Subject: [PATCH 30/38] fix: remove panic & fix potential nil error
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/gnoweb/main.go | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go
index 83d9664bb8e..b080e0b403d 100644
--- a/gno.land/cmd/gnoweb/main.go
+++ b/gno.land/cmd/gnoweb/main.go
@@ -486,12 +486,11 @@ func writeError(w http.ResponseWriter, err error) {
// XXX: writeError should return an error page template.
w.WriteHeader(500)
- panic(err)
- details := errors.Unwrap(err).Error()
- main := err.Error()
+ fmt.Println("main", err.Error())
- fmt.Println("main", main)
- fmt.Println("details", details)
+ if details := errors.Unwrap(err); details != nil {
+ fmt.Println("details", details.Error())
+ }
w.Write([]byte(err.Error()))
}
From 92ce8a81408c3591ceb1c787d74462ddc94f70a6 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Mon, 30 Oct 2023 15:43:31 +0100
Subject: [PATCH 31/38] chore: lint
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/gnoland/app.go | 13 +++++++------
gno.land/pkg/gnoland/types.go | 2 +-
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go
index 757c5f2248c..89fa597cd77 100644
--- a/gno.land/pkg/gnoland/app.go
+++ b/gno.land/pkg/gnoland/app.go
@@ -207,7 +207,7 @@ var (
)
func MustGuessGnoRootDir() string {
- root, err := guessGnoRootDir()
+ root, err := GuessGnoRootDir()
if err != nil {
panic(err)
}
@@ -217,6 +217,12 @@ func MustGuessGnoRootDir() string {
func GuessGnoRootDir() (string, error) {
var err error
+
+ // First try to get the root directory from the GNOROOT environment variable.
+ if rootdir := os.Getenv("GNOROOT"); rootdir != "" {
+ return filepath.Clean(rootdir), nil
+ }
+
guessOnce.Do(func() {
gnoroot, err = guessGnoRootDir()
})
@@ -225,11 +231,6 @@ func GuessGnoRootDir() (string, error) {
}
func guessGnoRootDir() (string, error) {
- // First try to get the root directory from the GNOROOT environment variable.
- if rootdir := os.Getenv("GNOROOT"); rootdir != "" {
- return filepath.Clean(rootdir), nil
- }
-
// Try to guess GNOROOT using the nearest go.mod.
if gobin, err := exec.LookPath("go"); err == nil {
// If GNOROOT is not set, try to guess the root directory using the `go list` command.
diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go
index 7dba82bc6a3..8e120136482 100644
--- a/gno.land/pkg/gnoland/types.go
+++ b/gno.land/pkg/gnoland/types.go
@@ -52,7 +52,7 @@ func (b *Balance) UnmarshalJSON(data []byte) error {
return b.Parse(string(data))
}
-func (b *Balance) Marshaljson() ([]byte, error) {
+func (b *Balance) MarshalJSON() ([]byte, error) {
return []byte(b.String()), nil
}
From 77b416b203a94bfecdc417f4aa696148628333d2 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Mon, 30 Oct 2023 19:24:01 +0100
Subject: [PATCH 32/38] fix: use gnoland.Balance in `genesis` command
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/genesis/balances_add.go | 131 ++++++-------------
gno.land/cmd/genesis/balances_add_test.go | 107 +++++++--------
gno.land/cmd/genesis/balances_export_test.go | 31 +++--
gno.land/cmd/genesis/balances_remove.go | 2 +-
gno.land/cmd/genesis/balances_remove_test.go | 15 +--
gno.land/cmd/genesis/types.go | 22 +---
gno.land/cmd/genesis/verify.go | 5 +-
gno.land/cmd/genesis/verify_test.go | 8 +-
gno.land/pkg/gnoland/types.go | 28 +++-
9 files changed, 143 insertions(+), 206 deletions(-)
diff --git a/gno.land/cmd/genesis/balances_add.go b/gno.land/cmd/genesis/balances_add.go
index 276e48690a8..8b569261dc0 100644
--- a/gno.land/cmd/genesis/balances_add.go
+++ b/gno.land/cmd/genesis/balances_add.go
@@ -8,32 +8,22 @@ import (
"fmt"
"io"
"os"
- "regexp"
- "strconv"
"strings"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
"github.com/gnolang/gno/tm2/pkg/amino"
"github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/commands"
- "github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/sdk/bank"
"github.com/gnolang/gno/tm2/pkg/std"
_ "github.com/gnolang/gno/gno.land/pkg/sdk/vm"
)
-var (
- balanceRegex = regexp.MustCompile(`^(\w+)=(\d+)ugnot$`)
- amountRegex = regexp.MustCompile(`^(\d+)ugnot$`)
-)
-
var (
errNoBalanceSource = errors.New("at least one balance source must be set")
errBalanceParsingAborted = errors.New("balance parsing aborted")
- errInvalidBalanceFormat = errors.New("invalid balance format encountered")
errInvalidAddress = errors.New("invalid address encountered")
- errInvalidAmount = errors.New("invalid amount encountered")
)
type balancesAddCfg struct {
@@ -152,7 +142,7 @@ func execBalancesAdd(ctx context.Context, cfg *balancesAddCfg, io *commands.IO)
// Construct the initial genesis balance sheet
state := genesis.AppState.(gnoland.GnoGenesisState)
- genesisBalances, err := extractGenesisBalances(state)
+ genesisBalances, err := mapGenesisBalancesFromState(state)
if err != nil {
return err
}
@@ -190,12 +180,11 @@ func getBalancesFromEntries(entries []string) (accountBalances, error) {
balances := make(accountBalances)
for _, entry := range entries {
- accountBalance, err := getBalanceFromEntry(entry)
- if err != nil {
- return nil, fmt.Errorf("unable to extract balance data, %w", err)
+ var balance gnoland.Balance
+ if err := balance.Parse(entry); err != nil {
+ return nil, fmt.Errorf("unable to parse balance entry: %w", err)
}
-
- balances[accountBalance.address] = accountBalance.amount
+ balances[balance.Address] = balance
}
return balances, nil
@@ -220,12 +209,12 @@ func getBalancesFromSheet(sheet io.Reader) (accountBalances, error) {
continue
}
- accountBalance, err := getBalanceFromEntry(entry)
- if err != nil {
+ var balance gnoland.Balance
+ if err := balance.Parse(entry); err != nil {
return nil, fmt.Errorf("unable to extract balance data, %w", err)
}
- balances[accountBalance.address] = accountBalance.amount
+ balances[balance.Address] = balance
}
if err := scanner.Err(); err != nil {
@@ -262,21 +251,19 @@ func getBalancesFromTransactions(
if err := amino.UnmarshalJSON(line, &tx); err != nil {
io.ErrPrintfln(
- "invalid amino JSON encountered: %s",
+ "invalid amino JSON encountered: %q",
string(line),
)
continue
}
- feeAmount, err := getAmountFromEntry(tx.Fee.GasFee.String())
- if err != nil {
+ feeAmount := std.NewCoins(tx.Fee.GasFee)
+ if feeAmount.AmountOf("ugnot") <= 0 {
io.ErrPrintfln(
- "invalid gas fee amount encountered: %s",
+ "invalid gas fee amount encountered: %q",
tx.Fee.GasFee.String(),
)
-
- continue
}
for _, msg := range tx.Msgs {
@@ -286,13 +273,12 @@ func getBalancesFromTransactions(
msgSend := msg.(bank.MsgSend)
- sendAmount, err := getAmountFromEntry(msgSend.Amount.String())
- if err != nil {
+ sendAmount := msgSend.Amount
+ if sendAmount.AmountOf("ugnot") <= 0 {
io.ErrPrintfln(
"invalid send amount encountered: %s",
msgSend.Amount.String(),
)
-
continue
}
@@ -304,27 +290,35 @@ func getBalancesFromTransactions(
// causes an accounts balance to go < 0. In these cases,
// we initialize the account (it is present in the balance sheet), but
// with the balance of 0
- from := balances[msgSend.FromAddress]
- to := balances[msgSend.ToAddress]
- to += sendAmount
+ from := balances[msgSend.FromAddress].Value
+ to := balances[msgSend.ToAddress].Value
+
+ to = to.Add(sendAmount)
- if from < sendAmount || from < feeAmount {
+ if from.IsAllLT(sendAmount) || from.IsAllLT(feeAmount) {
// Account cannot cover send amount / fee
// (see message above)
- from = 0
+ from = std.NewCoins(std.NewCoin("ugnot", 0))
}
- if from > sendAmount {
- from -= sendAmount
+ if from.IsAllGT(sendAmount) {
+ from = from.Sub(sendAmount)
}
- if from > feeAmount {
- from -= feeAmount
+ if from.IsAllGT(feeAmount) {
+ from = from.Sub(feeAmount)
}
- balances[msgSend.FromAddress] = from
- balances[msgSend.ToAddress] = to
+ // Set new balance
+ balances[msgSend.FromAddress] = gnoland.Balance{
+ Address: msgSend.FromAddress,
+ Value: from,
+ }
+ balances[msgSend.ToAddress] = gnoland.Balance{
+ Address: msgSend.ToAddress,
+ Value: to,
+ }
}
}
}
@@ -340,65 +334,14 @@ func getBalancesFromTransactions(
return balances, nil
}
-// getAmountFromEntry
-func getAmountFromEntry(entry string) (int64, error) {
- matches := amountRegex.FindStringSubmatch(entry)
-
- // Check if there is a match
- if len(matches) != 2 {
- return 0, fmt.Errorf(
- "invalid amount, %s",
- entry,
- )
- }
-
- amount, err := strconv.ParseInt(matches[1], 10, 64)
- if err != nil {
- return 0, fmt.Errorf("invalid amount, %s", matches[1])
- }
-
- return amount, nil
-}
-
-// getBalanceFromEntry extracts the account balance information
-// from a single line in the form of: =ugnot
-func getBalanceFromEntry(entry string) (*accountBalance, error) {
- matches := balanceRegex.FindStringSubmatch(entry)
- if len(matches) != 3 {
- return nil, fmt.Errorf("%w, %s", errInvalidBalanceFormat, entry)
- }
-
- // Validate the address
- address, err := crypto.AddressFromString(matches[1])
- if err != nil {
- return nil, fmt.Errorf("%w, %w", errInvalidAddress, err)
- }
-
- // Validate the amount
- amount, err := strconv.ParseInt(matches[2], 10, 64)
- if err != nil {
- return nil, fmt.Errorf("%w, %w", errInvalidAmount, err)
- }
-
- return &accountBalance{
- address: address,
- amount: amount,
- }, nil
-}
-
-// extractGenesisBalances extracts the initial account balances from the
+// mapGenesisBalancesFromState extracts the initial account balances from the
// genesis app state
-func extractGenesisBalances(state gnoland.GnoGenesisState) (accountBalances, error) {
+func mapGenesisBalancesFromState(state gnoland.GnoGenesisState) (accountBalances, error) {
// Construct the initial genesis balance sheet
genesisBalances := make(accountBalances)
- for _, entry := range state.Balances {
- accountBalance, err := getBalanceFromEntry(entry)
- if err != nil {
- return nil, fmt.Errorf("invalid genesis balance entry, %w", err)
- }
-
- genesisBalances[accountBalance.address] = accountBalance.amount
+ for _, balance := range state.Balances {
+ genesisBalances[balance.Address] = balance
}
return genesisBalances, nil
diff --git a/gno.land/cmd/genesis/balances_add_test.go b/gno.land/cmd/genesis/balances_add_test.go
index f986ee85274..78ecbd5bfd7 100644
--- a/gno.land/cmd/genesis/balances_add_test.go
+++ b/gno.land/cmd/genesis/balances_add_test.go
@@ -98,7 +98,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
tempGenesis.Name(),
}
- amount := int64(10)
+ amount := std.NewCoins(std.NewCoin("ugnot", 10))
for _, dummyKey := range dummyKeys {
args = append(args, "--single")
@@ -107,7 +107,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
fmt.Sprintf(
"%s=%dugnot",
dummyKey.Address().String(),
- amount,
+ amount.AmountOf("ugnot"),
),
)
}
@@ -127,16 +127,13 @@ func TestGenesis_Balances_Add(t *testing.T) {
require.Equal(t, len(dummyKeys), len(state.Balances))
- for _, entry := range state.Balances {
- accountBalance, err := getBalanceFromEntry(entry)
- require.NoError(t, err)
-
+ for _, balance := range state.Balances {
// Find the appropriate key
// (the genesis is saved with randomized balance order)
found := false
for _, dummyKey := range dummyKeys {
- if dummyKey.Address().String() == accountBalance.address.String() {
- assert.Equal(t, amount, accountBalance.amount)
+ if dummyKey.Address().String() == balance.Address.String() {
+ assert.Equal(t, amount, balance.Value)
found = true
break
@@ -144,7 +141,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
}
if !found {
- t.Fatalf("unexpected entry with address %s found", accountBalance.address.String())
+ t.Fatalf("unexpected entry with address %s found", balance.Address.String())
}
}
})
@@ -159,7 +156,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
require.NoError(t, genesis.SaveAs(tempGenesis.Name()))
dummyKeys := getDummyKeys(t, 10)
- amount := int64(10)
+ amount := std.NewCoins(std.NewCoin("ugnot", 10))
balances := make([]string, len(dummyKeys))
@@ -170,7 +167,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
balances[index] = fmt.Sprintf(
"%s=%dugnot",
key.Address().String(),
- amount,
+ amount.AmountOf("ugnot"),
)
}
@@ -207,16 +204,13 @@ func TestGenesis_Balances_Add(t *testing.T) {
require.Equal(t, len(dummyKeys), len(state.Balances))
- for _, entry := range state.Balances {
- accountBalance, err := getBalanceFromEntry(entry)
- require.NoError(t, err)
-
+ for _, balance := range state.Balances {
// Find the appropriate key
// (the genesis is saved with randomized balance order)
found := false
for _, dummyKey := range dummyKeys {
- if dummyKey.Address().String() == accountBalance.address.String() {
- assert.Equal(t, amount, accountBalance.amount)
+ if dummyKey.Address().String() == balance.Address.String() {
+ assert.Equal(t, amount, balance.Value)
found = true
break
@@ -224,7 +218,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
}
if !found {
- t.Fatalf("unexpected entry with address %s found", accountBalance.address.String())
+ t.Fatalf("unexpected entry with address %s found", balance.Address.String())
}
}
})
@@ -240,8 +234,8 @@ func TestGenesis_Balances_Add(t *testing.T) {
var (
dummyKeys = getDummyKeys(t, 10)
- amount = int64(10)
- amountCoins = std.NewCoins(std.NewCoin("ugnot", amount))
+ amount = std.NewCoins(std.NewCoin("ugnot", 10))
+ amountCoins = std.NewCoins(std.NewCoin("ugnot", 10))
gasFee = std.NewCoin("ugnot", 1000000)
txs = make([]std.Tx, 0)
)
@@ -309,10 +303,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
require.Equal(t, len(dummyKeys), len(state.Balances))
- for _, entry := range state.Balances {
- accountBalance, err := getBalanceFromEntry(entry)
- require.NoError(t, err)
-
+ for _, balance := range state.Balances {
// Find the appropriate key
// (the genesis is saved with randomized balance order)
found := false
@@ -321,11 +312,11 @@ func TestGenesis_Balances_Add(t *testing.T) {
if index == 0 {
// the first address should
// have a balance of 0
- checkAmount = 0
+ checkAmount = std.NewCoins(std.NewCoin("ugnot", 0))
}
- if dummyKey.Address().String() == accountBalance.address.String() {
- assert.Equal(t, checkAmount, accountBalance.amount)
+ if dummyKey.Address().String() == balance.Address.String() {
+ assert.True(t, balance.Value.IsEqual(checkAmount))
found = true
break
@@ -333,7 +324,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
}
if !found {
- t.Fatalf("unexpected entry with address %s found", accountBalance.address.String())
+ t.Fatalf("unexpected entry with address %s found", balance.Address.String())
}
}
})
@@ -349,12 +340,11 @@ func TestGenesis_Balances_Add(t *testing.T) {
genesis := getDefaultGenesis()
state := gnoland.GnoGenesisState{
// Set an initial balance value
- Balances: []string{
- fmt.Sprintf(
- "%s=%dugnot",
- dummyKeys[0].Address().String(),
- 100,
- ),
+ Balances: []gnoland.Balance{
+ {
+ Address: dummyKeys[0].Address(),
+ Value: std.NewCoins(std.NewCoin("ugnot", 100)),
+ },
},
}
genesis.AppState = state
@@ -369,7 +359,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
tempGenesis.Name(),
}
- amount := int64(10)
+ amount := std.NewCoins(std.NewCoin("ugnot", 10))
for _, dummyKey := range dummyKeys {
args = append(args, "--single")
@@ -378,7 +368,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
fmt.Sprintf(
"%s=%dugnot",
dummyKey.Address().String(),
- amount,
+ amount.AmountOf("ugnot"),
),
)
}
@@ -398,16 +388,13 @@ func TestGenesis_Balances_Add(t *testing.T) {
require.Equal(t, len(dummyKeys), len(state.Balances))
- for _, entry := range state.Balances {
- accountBalance, err := getBalanceFromEntry(entry)
- require.NoError(t, err)
-
+ for _, balance := range state.Balances {
// Find the appropriate key
// (the genesis is saved with randomized balance order)
found := false
for _, dummyKey := range dummyKeys {
- if dummyKey.Address().String() == accountBalance.address.String() {
- assert.Equal(t, amount, accountBalance.amount)
+ if dummyKey.Address().String() == balance.Address.String() {
+ assert.Equal(t, amount, balance.Value)
found = true
break
@@ -415,7 +402,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
}
if !found {
- t.Fatalf("unexpected entry with address %s found", accountBalance.address.String())
+ t.Fatalf("unexpected entry with address %s found", balance.Address.String())
}
}
})
@@ -429,7 +416,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) {
// Generate dummy keys
dummyKeys := getDummyKeys(t, 2)
- amount := int64(10)
+ amount := std.NewCoins(std.NewCoin("ugnot", 10))
balances := make([]string, len(dummyKeys))
@@ -437,7 +424,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) {
balances[index] = fmt.Sprintf(
"%s=%dugnot",
key.Address().String(),
- amount,
+ amount.AmountOf("ugnot"),
)
}
@@ -447,7 +434,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) {
// Validate the balance map
assert.Len(t, balanceMap, len(dummyKeys))
for _, key := range dummyKeys {
- assert.Equal(t, amount, balanceMap[key.Address()])
+ assert.Equal(t, amount, balanceMap[key.Address()].Value)
}
})
@@ -461,7 +448,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) {
balanceMap, err := getBalancesFromEntries(balances)
assert.Nil(t, balanceMap)
- assert.ErrorContains(t, err, errInvalidBalanceFormat.Error())
+ assert.ErrorContains(t, err, "malformed entry")
})
t.Run("malformed balance, invalid address", func(t *testing.T) {
@@ -474,7 +461,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) {
balanceMap, err := getBalancesFromEntries(balances)
assert.Nil(t, balanceMap)
- assert.ErrorContains(t, err, errInvalidAddress.Error())
+ assert.ErrorContains(t, err, "invalid address")
})
t.Run("malformed balance, invalid amount", func(t *testing.T) {
@@ -493,7 +480,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) {
balanceMap, err := getBalancesFromEntries(balances)
assert.Nil(t, balanceMap)
- assert.ErrorContains(t, err, errInvalidAmount.Error())
+ assert.ErrorContains(t, err, "invalid amount")
})
}
@@ -505,7 +492,7 @@ func TestBalances_GetBalancesFromSheet(t *testing.T) {
// Generate dummy keys
dummyKeys := getDummyKeys(t, 2)
- amount := int64(10)
+ amount := std.NewCoins(std.NewCoin("ugnot", 10))
balances := make([]string, len(dummyKeys))
@@ -513,7 +500,7 @@ func TestBalances_GetBalancesFromSheet(t *testing.T) {
balances[index] = fmt.Sprintf(
"%s=%dugnot",
key.Address().String(),
- amount,
+ amount.AmountOf("ugnot"),
)
}
@@ -524,7 +511,7 @@ func TestBalances_GetBalancesFromSheet(t *testing.T) {
// Validate the balance map
assert.Len(t, balanceMap, len(dummyKeys))
for _, key := range dummyKeys {
- assert.Equal(t, amount, balanceMap[key.Address()])
+ assert.Equal(t, amount, balanceMap[key.Address()].Value)
}
})
@@ -546,7 +533,7 @@ func TestBalances_GetBalancesFromSheet(t *testing.T) {
balanceMap, err := getBalancesFromSheet(reader)
assert.Nil(t, balanceMap)
- assert.ErrorContains(t, err, errInvalidAmount.Error())
+ assert.ErrorContains(t, err, "invalid amount")
})
}
@@ -558,8 +545,8 @@ func TestBalances_GetBalancesFromTransactions(t *testing.T) {
var (
dummyKeys = getDummyKeys(t, 10)
- amount = int64(10)
- amountCoins = std.NewCoins(std.NewCoin("ugnot", amount))
+ amount = std.NewCoins(std.NewCoin("ugnot", 10))
+ amountCoins = std.NewCoins(std.NewCoin("ugnot", 10))
gasFee = std.NewCoin("ugnot", 1000000)
txs = make([]std.Tx, 0)
)
@@ -605,10 +592,10 @@ func TestBalances_GetBalancesFromTransactions(t *testing.T) {
// Validate the balance map
assert.Len(t, balanceMap, len(dummyKeys))
for _, key := range dummyKeys[1:] {
- assert.Equal(t, amount, balanceMap[key.Address()])
+ assert.Equal(t, amount, balanceMap[key.Address()].Value)
}
- assert.Equal(t, int64(0), balanceMap[sender.Address()])
+ assert.Equal(t, std.Coins{}, balanceMap[sender.Address()].Value)
})
t.Run("malformed transaction, invalid fee amount", func(t *testing.T) {
@@ -616,8 +603,7 @@ func TestBalances_GetBalancesFromTransactions(t *testing.T) {
var (
dummyKeys = getDummyKeys(t, 10)
- amount = int64(10)
- amountCoins = std.NewCoins(std.NewCoin("ugnot", amount))
+ amountCoins = std.NewCoins(std.NewCoin("ugnot", 10))
gasFee = std.NewCoin("gnos", 1) // invalid fee
txs = make([]std.Tx, 0)
)
@@ -669,8 +655,7 @@ func TestBalances_GetBalancesFromTransactions(t *testing.T) {
var (
dummyKeys = getDummyKeys(t, 10)
- amount = int64(10)
- amountCoins = std.NewCoins(std.NewCoin("gnogno", amount)) // invalid send amount
+ amountCoins = std.NewCoins(std.NewCoin("gnogno", 10)) // invalid send amount
gasFee = std.NewCoin("ugnot", 1)
txs = make([]std.Tx, 0)
)
diff --git a/gno.land/cmd/genesis/balances_export_test.go b/gno.land/cmd/genesis/balances_export_test.go
index 33e4f7bc800..dd8a9038feb 100644
--- a/gno.land/cmd/genesis/balances_export_test.go
+++ b/gno.land/cmd/genesis/balances_export_test.go
@@ -3,31 +3,30 @@ package main
import (
"bufio"
"context"
- "fmt"
"testing"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
"github.com/gnolang/gno/tm2/pkg/commands"
+ "github.com/gnolang/gno/tm2/pkg/std"
"github.com/gnolang/gno/tm2/pkg/testutils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
-// getDummyBalanceLines generates dummy balance lines
-func getDummyBalanceLines(t *testing.T, count int) []string {
+// getDummyBalances generates dummy balance lines
+func getDummyBalances(t *testing.T, count int) []gnoland.Balance {
t.Helper()
dummyKeys := getDummyKeys(t, count)
- amount := int64(10)
+ amount := std.NewCoins(std.NewCoin("ugnot", 10))
- balances := make([]string, len(dummyKeys))
+ balances := make([]gnoland.Balance, len(dummyKeys))
for index, key := range dummyKeys {
- balances[index] = fmt.Sprintf(
- "%s=%dugnot",
- key.Address().String(),
- amount,
- )
+ balances[index] = gnoland.Balance{
+ Address: key.Address(),
+ Value: amount,
+ }
}
return balances
@@ -85,7 +84,7 @@ func TestGenesis_Balances_Export(t *testing.T) {
genesis := getDefaultGenesis()
genesis.AppState = gnoland.GnoGenesisState{
- Balances: getDummyBalanceLines(t, 1),
+ Balances: getDummyBalances(t, 1),
}
require.NoError(t, genesis.SaveAs(tempGenesis.Name()))
@@ -107,7 +106,7 @@ func TestGenesis_Balances_Export(t *testing.T) {
t.Parallel()
// Generate dummy balances
- balances := getDummyBalanceLines(t, 10)
+ balances := getDummyBalances(t, 10)
tempGenesis, cleanup := testutils.NewTestFile(t)
t.Cleanup(cleanup)
@@ -139,9 +138,13 @@ func TestGenesis_Balances_Export(t *testing.T) {
// Validate the transactions were written down
scanner := bufio.NewScanner(outputFile)
- outputBalances := make([]string, 0)
+ outputBalances := make([]gnoland.Balance, 0)
for scanner.Scan() {
- outputBalances = append(outputBalances, scanner.Text())
+ var balance gnoland.Balance
+ err := balance.Parse(scanner.Text())
+ require.NoError(t, err)
+
+ outputBalances = append(outputBalances, balance)
}
require.NoError(t, scanner.Err())
diff --git a/gno.land/cmd/genesis/balances_remove.go b/gno.land/cmd/genesis/balances_remove.go
index f7e9092dc3b..f4286d95ad2 100644
--- a/gno.land/cmd/genesis/balances_remove.go
+++ b/gno.land/cmd/genesis/balances_remove.go
@@ -71,7 +71,7 @@ func execBalancesRemove(cfg *balancesRemoveCfg, io *commands.IO) error {
// Construct the initial genesis balance sheet
state := genesis.AppState.(gnoland.GnoGenesisState)
- genesisBalances, err := extractGenesisBalances(state)
+ genesisBalances, err := mapGenesisBalancesFromState(state)
if err != nil {
return err
}
diff --git a/gno.land/cmd/genesis/balances_remove_test.go b/gno.land/cmd/genesis/balances_remove_test.go
index 29179c43604..b53131986ee 100644
--- a/gno.land/cmd/genesis/balances_remove_test.go
+++ b/gno.land/cmd/genesis/balances_remove_test.go
@@ -2,12 +2,12 @@ package main
import (
"context"
- "fmt"
"testing"
"github.com/gnolang/gno/gno.land/pkg/gnoland"
"github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/commands"
+ "github.com/gnolang/gno/tm2/pkg/std"
"github.com/gnolang/gno/tm2/pkg/testutils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -70,12 +70,11 @@ func TestGenesis_Balances_Remove(t *testing.T) {
genesis := getDefaultGenesis()
state := gnoland.GnoGenesisState{
// Set an initial balance value
- Balances: []string{
- fmt.Sprintf(
- "%s=%dugnot",
- dummyKey.Address().String(),
- 100,
- ),
+ Balances: []gnoland.Balance{
+ {
+ Address: dummyKey.Address(),
+ Value: std.NewCoins(std.NewCoin("ugnot", 100)),
+ },
},
}
genesis.AppState = state
@@ -118,7 +117,7 @@ func TestGenesis_Balances_Remove(t *testing.T) {
genesis := getDefaultGenesis()
state := gnoland.GnoGenesisState{
- Balances: []string{}, // Empty initial balance
+ Balances: []gnoland.Balance{}, // Empty initial balance
}
genesis.AppState = state
require.NoError(t, genesis.SaveAs(tempGenesis.Name()))
diff --git a/gno.land/cmd/genesis/types.go b/gno.land/cmd/genesis/types.go
index 208eaddb6da..dba39ea8ec1 100644
--- a/gno.land/cmd/genesis/types.go
+++ b/gno.land/cmd/genesis/types.go
@@ -1,8 +1,7 @@
package main
import (
- "fmt"
-
+ "github.com/gnolang/gno/gno.land/pkg/gnoland"
"github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/std"
)
@@ -39,23 +38,14 @@ func (i *txStore) leftMerge(b txStore) error {
return nil
}
-type (
- accountBalances map[types.Address]int64 // address -> balance (ugnot)
- accountBalance struct {
- address types.Address
- amount int64
- }
-)
+type accountBalances map[types.Address]gnoland.Balance // address -> balance (ugnot)
// toList linearizes the account balances map
-func (a accountBalances) toList() []string {
- balances := make([]string, 0, len(a))
+func (a accountBalances) toList() []gnoland.Balance {
+ balances := make([]gnoland.Balance, 0, len(a))
- for address, balance := range a {
- balances = append(
- balances,
- fmt.Sprintf("%s=%dugnot", address, balance),
- )
+ for _, balance := range a {
+ balances = append(balances, balance)
}
return balances
diff --git a/gno.land/cmd/genesis/verify.go b/gno.land/cmd/genesis/verify.go
index ba51f5801f6..6c877ca51ec 100644
--- a/gno.land/cmd/genesis/verify.go
+++ b/gno.land/cmd/genesis/verify.go
@@ -9,7 +9,6 @@ import (
"github.com/gnolang/gno/gno.land/pkg/gnoland"
"github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/commands"
- "github.com/gnolang/gno/tm2/pkg/std"
)
var errInvalidGenesisState = errors.New("invalid genesis state type")
@@ -68,8 +67,8 @@ func execVerify(cfg *verifyCfg, io *commands.IO) error {
// Validate the initial balances
for _, balance := range state.Balances {
- if _, parseErr := std.ParseCoins(balance); parseErr != nil {
- return fmt.Errorf("invalid balance %s, %w", balance, parseErr)
+ if err := balance.Verify(); err != nil {
+ return fmt.Errorf("invalid balance: %w", err)
}
}
}
diff --git a/gno.land/cmd/genesis/verify_test.go b/gno.land/cmd/genesis/verify_test.go
index fcc5305b9d0..8388949898b 100644
--- a/gno.land/cmd/genesis/verify_test.go
+++ b/gno.land/cmd/genesis/verify_test.go
@@ -44,7 +44,7 @@ func TestGenesis_Verify(t *testing.T) {
g := getValidTestGenesis()
g.AppState = gnoland.GnoGenesisState{
- Balances: []string{},
+ Balances: []gnoland.Balance{},
Txs: []std.Tx{
{},
},
@@ -74,8 +74,8 @@ func TestGenesis_Verify(t *testing.T) {
g := getValidTestGenesis()
g.AppState = gnoland.GnoGenesisState{
- Balances: []string{
- "dummybalance",
+ Balances: []gnoland.Balance{
+ {},
},
Txs: []std.Tx{},
}
@@ -103,7 +103,7 @@ func TestGenesis_Verify(t *testing.T) {
g := getValidTestGenesis()
g.AppState = gnoland.GnoGenesisState{
- Balances: []string{},
+ Balances: []gnoland.Balance{},
Txs: []std.Tx{},
}
diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go
index 8e120136482..4a1a68babe1 100644
--- a/gno.land/pkg/gnoland/types.go
+++ b/gno.land/pkg/gnoland/types.go
@@ -1,6 +1,7 @@
package gnoland
import (
+ "errors"
"fmt"
"strings"
@@ -9,6 +10,11 @@ import (
"github.com/gnolang/gno/tm2/pkg/std"
)
+var (
+ ErrBalanceEmptyAddress = errors.New("balance address is empty")
+ ErrBalanceEmptyAmount = errors.New("balance amount is empty")
+)
+
type GnoAccount struct {
std.BaseAccount
}
@@ -27,22 +33,34 @@ type Balance struct {
Value std.Coins
}
-func (b *Balance) Parse(line string) error {
- parts := strings.Split(strings.TrimSpace(line), "=") // =
+func (b *Balance) Verify() error {
+ if b.Address.IsZero() {
+ return ErrBalanceEmptyAddress
+ }
+
+ if b.Value.Len() == 0 {
+ return ErrBalanceEmptyAmount
+ }
+
+ return nil
+}
+
+func (b *Balance) Parse(entry string) error {
+ parts := strings.Split(strings.TrimSpace(entry), "=") // =
if len(parts) != 2 {
- return fmt.Errorf("invalid balance line: %q", line)
+ return fmt.Errorf("malformed entry: %q", entry)
}
var err error
b.Address, err = crypto.AddressFromBech32(parts[0])
if err != nil {
- return fmt.Errorf("invalid balance addr %s: %w", parts[0], err)
+ return fmt.Errorf("invalid address %q: %w", parts[0], err)
}
b.Value, err = std.ParseCoins(parts[1])
if err != nil {
- return fmt.Errorf("invalid balance coins %s: %w", parts[1], err)
+ return fmt.Errorf("invalid amount %q: %w", parts[1], err)
}
return nil
From cc3fe3e0cd69f1ac9b56ab0cfefef5b7fa679712 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Mon, 6 Nov 2023 22:32:33 +0100
Subject: [PATCH 33/38] fix: use amino marshaler
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/gnoland/types.go | 8 +--
gno.land/pkg/gnoland/types_test.go | 99 ++++++++++++++++++++++++++++++
2 files changed, 103 insertions(+), 4 deletions(-)
create mode 100644 gno.land/pkg/gnoland/types_test.go
diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go
index 4a1a68babe1..8d55fc122eb 100644
--- a/gno.land/pkg/gnoland/types.go
+++ b/gno.land/pkg/gnoland/types.go
@@ -66,12 +66,12 @@ func (b *Balance) Parse(entry string) error {
return nil
}
-func (b *Balance) UnmarshalJSON(data []byte) error {
- return b.Parse(string(data))
+func (b *Balance) UnmarshalAmino(rep string) error {
+ return b.Parse(rep)
}
-func (b *Balance) MarshalJSON() ([]byte, error) {
- return []byte(b.String()), nil
+func (b Balance) MarshalAmino() (string, error) {
+ return b.String(), nil
}
func (b Balance) String() string {
diff --git a/gno.land/pkg/gnoland/types_test.go b/gno.land/pkg/gnoland/types_test.go
new file mode 100644
index 00000000000..f70ccaa62a4
--- /dev/null
+++ b/gno.land/pkg/gnoland/types_test.go
@@ -0,0 +1,99 @@
+package gnoland
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/gnolang/gno/tm2/pkg/amino"
+ bft "github.com/gnolang/gno/tm2/pkg/bft/types"
+ "github.com/gnolang/gno/tm2/pkg/crypto"
+ "github.com/gnolang/gno/tm2/pkg/std"
+ "github.com/jaekwon/testify/assert"
+ "github.com/jaekwon/testify/require"
+)
+
+func TestBalance_Verify(t *testing.T) {
+ validAddress := crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
+ emptyCoins := std.Coins{}
+ nonEmptyCoins := std.NewCoins(std.NewCoin("test", 100))
+
+ tests := []struct {
+ name string
+ balance Balance
+ expectErr bool
+ }{
+ {"empty coins", Balance{Address: validAddress, Value: emptyCoins}, true},
+ {"empty address", Balance{Address: bft.Address{}, Value: nonEmptyCoins}, true},
+ {"valid balance", Balance{Address: validAddress, Value: nonEmptyCoins}, false},
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ err := tc.balance.Verify()
+ if tc.expectErr {
+ assert.Error(t, err, fmt.Sprintf("TestVerifyBalance: %s", tc.name))
+ } else {
+ assert.NoError(t, err, fmt.Sprintf("TestVerifyBalance: %s", tc.name))
+ }
+ })
+ }
+}
+
+func TestBalance_Parse(t *testing.T) {
+ validAddress := crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
+ validBalance := Balance{Address: validAddress, Value: std.NewCoins(std.NewCoin("test", 100))}
+
+ tests := []struct {
+ name string
+ entry string
+ expected Balance
+ expectErr bool
+ }{
+ {"valid entry", "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5=100test", validBalance, false},
+ {"invalid address", "invalid=100test", Balance{}, true},
+ {"empty amount", "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5=", Balance{}, true},
+ {"incomplete entry", "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", Balance{}, true},
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ balance := Balance{}
+ err := balance.Parse(tc.entry)
+ if tc.expectErr {
+ assert.Error(t, err)
+ } else {
+ assert.NoError(t, err)
+ assert.Equal(t, tc.expected, balance)
+ }
+ })
+ }
+}
+
+func TestBalance_AminoUnmarshalJSON(t *testing.T) {
+ expected := Balance{
+ Address: crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
+ Value: std.MustParseCoins("100ugnot"),
+ }
+ value := fmt.Sprintf("[%q]", expected.String())
+
+ var balances []Balance
+ err := amino.UnmarshalJSON([]byte(value), &balances)
+ require.NoError(t, err)
+ require.Len(t, balances, 1, "there should be one balance after unmarshaling")
+
+ balance := balances[0]
+ require.Equal(t, expected.Address, balance.Address)
+ require.True(t, expected.Value.IsEqual(balance.Value))
+}
+
+func TestBalance_AminoMarshalJSON(t *testing.T) {
+ expected := Balance{
+ Address: crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
+ Value: std.MustParseCoins("100ugnot"),
+ }
+ expectedJSON := fmt.Sprintf("[%q]", expected.String())
+
+ balancesJSON, err := amino.MarshalJSON([]Balance{expected})
+ require.NoError(t, err)
+ require.JSONEq(t, expectedJSON, string(balancesJSON))
+}
From 41ef47cfd805f20903ce3428af50c5a39c83ea5c Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Mon, 6 Nov 2023 22:34:14 +0100
Subject: [PATCH 34/38] fix: amount can be empty
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/gnoland/types_test.go | 1 -
1 file changed, 1 deletion(-)
diff --git a/gno.land/pkg/gnoland/types_test.go b/gno.land/pkg/gnoland/types_test.go
index f70ccaa62a4..63dd94075f7 100644
--- a/gno.land/pkg/gnoland/types_test.go
+++ b/gno.land/pkg/gnoland/types_test.go
@@ -51,7 +51,6 @@ func TestBalance_Parse(t *testing.T) {
}{
{"valid entry", "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5=100test", validBalance, false},
{"invalid address", "invalid=100test", Balance{}, true},
- {"empty amount", "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5=", Balance{}, true},
{"incomplete entry", "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", Balance{}, true},
}
From d80231c952d283dd83842132d51c535d1bc55bee Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Mon, 6 Nov 2023 22:36:14 +0100
Subject: [PATCH 35/38] fix: rename Balance.Value into Balance.Amount
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/genesis/balances_add.go | 8 ++++----
gno.land/cmd/genesis/balances_add_test.go | 18 +++++++++---------
gno.land/cmd/genesis/balances_export_test.go | 2 +-
gno.land/cmd/genesis/balances_remove_test.go | 2 +-
gno.land/pkg/gnoland/app.go | 2 +-
gno.land/pkg/gnoland/genesis.go | 2 +-
gno.land/pkg/gnoland/types.go | 8 ++++----
gno.land/pkg/gnoland/types_test.go | 14 +++++++-------
gno.land/pkg/integration/testing_node.go | 2 +-
9 files changed, 29 insertions(+), 29 deletions(-)
diff --git a/gno.land/cmd/genesis/balances_add.go b/gno.land/cmd/genesis/balances_add.go
index 8b569261dc0..8df193c770c 100644
--- a/gno.land/cmd/genesis/balances_add.go
+++ b/gno.land/cmd/genesis/balances_add.go
@@ -291,8 +291,8 @@ func getBalancesFromTransactions(
// we initialize the account (it is present in the balance sheet), but
// with the balance of 0
- from := balances[msgSend.FromAddress].Value
- to := balances[msgSend.ToAddress].Value
+ from := balances[msgSend.FromAddress].Amount
+ to := balances[msgSend.ToAddress].Amount
to = to.Add(sendAmount)
@@ -313,11 +313,11 @@ func getBalancesFromTransactions(
// Set new balance
balances[msgSend.FromAddress] = gnoland.Balance{
Address: msgSend.FromAddress,
- Value: from,
+ Amount: from,
}
balances[msgSend.ToAddress] = gnoland.Balance{
Address: msgSend.ToAddress,
- Value: to,
+ Amount: to,
}
}
}
diff --git a/gno.land/cmd/genesis/balances_add_test.go b/gno.land/cmd/genesis/balances_add_test.go
index 78ecbd5bfd7..bd66f0f446b 100644
--- a/gno.land/cmd/genesis/balances_add_test.go
+++ b/gno.land/cmd/genesis/balances_add_test.go
@@ -133,7 +133,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
found := false
for _, dummyKey := range dummyKeys {
if dummyKey.Address().String() == balance.Address.String() {
- assert.Equal(t, amount, balance.Value)
+ assert.Equal(t, amount, balance.Amount)
found = true
break
@@ -210,7 +210,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
found := false
for _, dummyKey := range dummyKeys {
if dummyKey.Address().String() == balance.Address.String() {
- assert.Equal(t, amount, balance.Value)
+ assert.Equal(t, amount, balance.Amount)
found = true
break
@@ -316,7 +316,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
}
if dummyKey.Address().String() == balance.Address.String() {
- assert.True(t, balance.Value.IsEqual(checkAmount))
+ assert.True(t, balance.Amount.IsEqual(checkAmount))
found = true
break
@@ -343,7 +343,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
Balances: []gnoland.Balance{
{
Address: dummyKeys[0].Address(),
- Value: std.NewCoins(std.NewCoin("ugnot", 100)),
+ Amount: std.NewCoins(std.NewCoin("ugnot", 100)),
},
},
}
@@ -394,7 +394,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
found := false
for _, dummyKey := range dummyKeys {
if dummyKey.Address().String() == balance.Address.String() {
- assert.Equal(t, amount, balance.Value)
+ assert.Equal(t, amount, balance.Amount)
found = true
break
@@ -434,7 +434,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) {
// Validate the balance map
assert.Len(t, balanceMap, len(dummyKeys))
for _, key := range dummyKeys {
- assert.Equal(t, amount, balanceMap[key.Address()].Value)
+ assert.Equal(t, amount, balanceMap[key.Address()].Amount)
}
})
@@ -511,7 +511,7 @@ func TestBalances_GetBalancesFromSheet(t *testing.T) {
// Validate the balance map
assert.Len(t, balanceMap, len(dummyKeys))
for _, key := range dummyKeys {
- assert.Equal(t, amount, balanceMap[key.Address()].Value)
+ assert.Equal(t, amount, balanceMap[key.Address()].Amount)
}
})
@@ -592,10 +592,10 @@ func TestBalances_GetBalancesFromTransactions(t *testing.T) {
// Validate the balance map
assert.Len(t, balanceMap, len(dummyKeys))
for _, key := range dummyKeys[1:] {
- assert.Equal(t, amount, balanceMap[key.Address()].Value)
+ assert.Equal(t, amount, balanceMap[key.Address()].Amount)
}
- assert.Equal(t, std.Coins{}, balanceMap[sender.Address()].Value)
+ assert.Equal(t, std.Coins{}, balanceMap[sender.Address()].Amount)
})
t.Run("malformed transaction, invalid fee amount", func(t *testing.T) {
diff --git a/gno.land/cmd/genesis/balances_export_test.go b/gno.land/cmd/genesis/balances_export_test.go
index dd8a9038feb..a5314339c86 100644
--- a/gno.land/cmd/genesis/balances_export_test.go
+++ b/gno.land/cmd/genesis/balances_export_test.go
@@ -25,7 +25,7 @@ func getDummyBalances(t *testing.T, count int) []gnoland.Balance {
for index, key := range dummyKeys {
balances[index] = gnoland.Balance{
Address: key.Address(),
- Value: amount,
+ Amount: amount,
}
}
diff --git a/gno.land/cmd/genesis/balances_remove_test.go b/gno.land/cmd/genesis/balances_remove_test.go
index b53131986ee..633399538b8 100644
--- a/gno.land/cmd/genesis/balances_remove_test.go
+++ b/gno.land/cmd/genesis/balances_remove_test.go
@@ -73,7 +73,7 @@ func TestGenesis_Balances_Remove(t *testing.T) {
Balances: []gnoland.Balance{
{
Address: dummyKey.Address(),
- Value: std.NewCoins(std.NewCoin("ugnot", 100)),
+ Amount: std.NewCoins(std.NewCoin("ugnot", 100)),
},
},
}
diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go
index 89fa597cd77..cc2f15ce1cc 100644
--- a/gno.land/pkg/gnoland/app.go
+++ b/gno.land/pkg/gnoland/app.go
@@ -149,7 +149,7 @@ func InitChainer(baseApp *sdk.BaseApp, acctKpr auth.AccountKeeperI, bankKpr bank
for _, bal := range genState.Balances {
acc := acctKpr.NewAccountWithAddress(ctx, bal.Address)
acctKpr.SetAccount(ctx, acc)
- err := bankKpr.SetCoins(ctx, bal.Address, bal.Value)
+ err := bankKpr.SetCoins(ctx, bal.Address, bal.Amount)
if err != nil {
panic(err)
}
diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go
index 94c9d6cbf03..ec098fffaf7 100644
--- a/gno.land/pkg/gnoland/genesis.go
+++ b/gno.land/pkg/gnoland/genesis.go
@@ -51,7 +51,7 @@ func LoadGenesisBalancesFile(path string) ([]Balance, error) {
balances = append(balances, Balance{
Address: addr,
- Value: coins,
+ Amount: coins,
})
}
diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go
index 8d55fc122eb..5d68064c9c5 100644
--- a/gno.land/pkg/gnoland/types.go
+++ b/gno.land/pkg/gnoland/types.go
@@ -30,7 +30,7 @@ type GnoGenesisState struct {
type Balance struct {
Address bft.Address
- Value std.Coins
+ Amount std.Coins
}
func (b *Balance) Verify() error {
@@ -38,7 +38,7 @@ func (b *Balance) Verify() error {
return ErrBalanceEmptyAddress
}
- if b.Value.Len() == 0 {
+ if b.Amount.Len() == 0 {
return ErrBalanceEmptyAmount
}
@@ -58,7 +58,7 @@ func (b *Balance) Parse(entry string) error {
return fmt.Errorf("invalid address %q: %w", parts[0], err)
}
- b.Value, err = std.ParseCoins(parts[1])
+ b.Amount, err = std.ParseCoins(parts[1])
if err != nil {
return fmt.Errorf("invalid amount %q: %w", parts[1], err)
}
@@ -75,5 +75,5 @@ func (b Balance) MarshalAmino() (string, error) {
}
func (b Balance) String() string {
- return fmt.Sprintf("%s=%s", b.Address.String(), b.Value.String())
+ return fmt.Sprintf("%s=%s", b.Address.String(), b.Amount.String())
}
diff --git a/gno.land/pkg/gnoland/types_test.go b/gno.land/pkg/gnoland/types_test.go
index 63dd94075f7..1124d1a07a4 100644
--- a/gno.land/pkg/gnoland/types_test.go
+++ b/gno.land/pkg/gnoland/types_test.go
@@ -22,9 +22,9 @@ func TestBalance_Verify(t *testing.T) {
balance Balance
expectErr bool
}{
- {"empty coins", Balance{Address: validAddress, Value: emptyCoins}, true},
- {"empty address", Balance{Address: bft.Address{}, Value: nonEmptyCoins}, true},
- {"valid balance", Balance{Address: validAddress, Value: nonEmptyCoins}, false},
+ {"empty coins", Balance{Address: validAddress, Amount: emptyCoins}, true},
+ {"empty address", Balance{Address: bft.Address{}, Amount: nonEmptyCoins}, true},
+ {"valid balance", Balance{Address: validAddress, Amount: nonEmptyCoins}, false},
}
for _, tc := range tests {
@@ -41,7 +41,7 @@ func TestBalance_Verify(t *testing.T) {
func TestBalance_Parse(t *testing.T) {
validAddress := crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
- validBalance := Balance{Address: validAddress, Value: std.NewCoins(std.NewCoin("test", 100))}
+ validBalance := Balance{Address: validAddress, Amount: std.NewCoins(std.NewCoin("test", 100))}
tests := []struct {
name string
@@ -71,7 +71,7 @@ func TestBalance_Parse(t *testing.T) {
func TestBalance_AminoUnmarshalJSON(t *testing.T) {
expected := Balance{
Address: crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
- Value: std.MustParseCoins("100ugnot"),
+ Amount: std.MustParseCoins("100ugnot"),
}
value := fmt.Sprintf("[%q]", expected.String())
@@ -82,13 +82,13 @@ func TestBalance_AminoUnmarshalJSON(t *testing.T) {
balance := balances[0]
require.Equal(t, expected.Address, balance.Address)
- require.True(t, expected.Value.IsEqual(balance.Value))
+ require.True(t, expected.Amount.IsEqual(balance.Amount))
}
func TestBalance_AminoMarshalJSON(t *testing.T) {
expected := Balance{
Address: crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
- Value: std.MustParseCoins("100ugnot"),
+ Amount: std.MustParseCoins("100ugnot"),
}
expectedJSON := fmt.Sprintf("[%q]", expected.String())
diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go
index 4461a0af27a..1ca7e11eb63 100644
--- a/gno.land/pkg/integration/testing_node.go
+++ b/gno.land/pkg/integration/testing_node.go
@@ -103,7 +103,7 @@ func DefaultTestingGenesisConfig(t TestingTS, gnoroot string, self crypto.PubKey
Balances: []gnoland.Balance{
{
Address: crypto.MustAddressFromString(DefaultAccount_Address),
- Value: std.MustParseCoins("10000000000000ugnot"),
+ Amount: std.MustParseCoins("10000000000000ugnot"),
},
},
Txs: []std.Tx{},
From 5b23e9f5fc52338c1df5581103d381329b2dc404 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Mon, 6 Nov 2023 22:38:05 +0100
Subject: [PATCH 36/38] chore: rename
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/gnoland/types_test.go | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/gno.land/pkg/gnoland/types_test.go b/gno.land/pkg/gnoland/types_test.go
index 1124d1a07a4..97222d0cdfd 100644
--- a/gno.land/pkg/gnoland/types_test.go
+++ b/gno.land/pkg/gnoland/types_test.go
@@ -14,17 +14,17 @@ import (
func TestBalance_Verify(t *testing.T) {
validAddress := crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
- emptyCoins := std.Coins{}
- nonEmptyCoins := std.NewCoins(std.NewCoin("test", 100))
+ emptyAmount := std.Coins{}
+ nonEmptyAmount := std.NewCoins(std.NewCoin("test", 100))
tests := []struct {
name string
balance Balance
expectErr bool
}{
- {"empty coins", Balance{Address: validAddress, Amount: emptyCoins}, true},
- {"empty address", Balance{Address: bft.Address{}, Amount: nonEmptyCoins}, true},
- {"valid balance", Balance{Address: validAddress, Amount: nonEmptyCoins}, false},
+ {"empty amount", Balance{Address: validAddress, Amount: emptyAmount}, true},
+ {"empty address", Balance{Address: bft.Address{}, Amount: nonEmptyAmount}, true},
+ {"valid balance", Balance{Address: validAddress, Amount: nonEmptyAmount}, false},
}
for _, tc := range tests {
From 6292f7bbc59a08db6221e392c335232afa81a004 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Mon, 6 Nov 2023 22:40:35 +0100
Subject: [PATCH 37/38] chore: remove gnoroot singleton
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/pkg/gnoland/app.go | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go
index cc2f15ce1cc..b5322325d0d 100644
--- a/gno.land/pkg/gnoland/app.go
+++ b/gno.land/pkg/gnoland/app.go
@@ -8,7 +8,6 @@ import (
"path/filepath"
"runtime"
"strings"
- "sync"
"github.com/gnolang/gno/gno.land/pkg/sdk/vm"
"github.com/gnolang/gno/tm2/pkg/amino"
@@ -201,11 +200,6 @@ func EndBlocker(vmk vm.VMKeeperI) func(ctx sdk.Context, req abci.RequestEndBlock
// XXX: all the method bellow should be removed in favor of
// https://github.com/gnolang/gno/pull/1233
-var (
- guessOnce sync.Once
- gnoroot string
-)
-
func MustGuessGnoRootDir() string {
root, err := GuessGnoRootDir()
if err != nil {
@@ -223,11 +217,7 @@ func GuessGnoRootDir() (string, error) {
return filepath.Clean(rootdir), nil
}
- guessOnce.Do(func() {
- gnoroot, err = guessGnoRootDir()
- })
-
- return gnoroot, err
+ return guessGnoRootDir()
}
func guessGnoRootDir() (string, error) {
From 844995a8540dfbbd9380ad5e8cc270bd36de15c0 Mon Sep 17 00:00:00 2001
From: gfanton <8671905+gfanton@users.noreply.github.com>
Date: Tue, 7 Nov 2023 09:23:52 +0100
Subject: [PATCH 38/38] chore: lint
Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com>
---
gno.land/cmd/genesis/balances_add_test.go | 2 +-
gno.land/cmd/genesis/balances_export_test.go | 2 +-
gno.land/cmd/genesis/balances_remove_test.go | 2 +-
gno.land/pkg/gnoland/app.go | 6 ------
gno.land/pkg/gnoland/genesis.go | 2 +-
5 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/gno.land/cmd/genesis/balances_add_test.go b/gno.land/cmd/genesis/balances_add_test.go
index bd66f0f446b..73e2fe148a2 100644
--- a/gno.land/cmd/genesis/balances_add_test.go
+++ b/gno.land/cmd/genesis/balances_add_test.go
@@ -343,7 +343,7 @@ func TestGenesis_Balances_Add(t *testing.T) {
Balances: []gnoland.Balance{
{
Address: dummyKeys[0].Address(),
- Amount: std.NewCoins(std.NewCoin("ugnot", 100)),
+ Amount: std.NewCoins(std.NewCoin("ugnot", 100)),
},
},
}
diff --git a/gno.land/cmd/genesis/balances_export_test.go b/gno.land/cmd/genesis/balances_export_test.go
index a5314339c86..d7441fd438f 100644
--- a/gno.land/cmd/genesis/balances_export_test.go
+++ b/gno.land/cmd/genesis/balances_export_test.go
@@ -25,7 +25,7 @@ func getDummyBalances(t *testing.T, count int) []gnoland.Balance {
for index, key := range dummyKeys {
balances[index] = gnoland.Balance{
Address: key.Address(),
- Amount: amount,
+ Amount: amount,
}
}
diff --git a/gno.land/cmd/genesis/balances_remove_test.go b/gno.land/cmd/genesis/balances_remove_test.go
index 633399538b8..b9d10d0db08 100644
--- a/gno.land/cmd/genesis/balances_remove_test.go
+++ b/gno.land/cmd/genesis/balances_remove_test.go
@@ -73,7 +73,7 @@ func TestGenesis_Balances_Remove(t *testing.T) {
Balances: []gnoland.Balance{
{
Address: dummyKey.Address(),
- Amount: std.NewCoins(std.NewCoin("ugnot", 100)),
+ Amount: std.NewCoins(std.NewCoin("ugnot", 100)),
},
},
}
diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go
index b5322325d0d..a8a2736c8d1 100644
--- a/gno.land/pkg/gnoland/app.go
+++ b/gno.land/pkg/gnoland/app.go
@@ -210,17 +210,11 @@ func MustGuessGnoRootDir() string {
}
func GuessGnoRootDir() (string, error) {
- var err error
-
// First try to get the root directory from the GNOROOT environment variable.
if rootdir := os.Getenv("GNOROOT"); rootdir != "" {
return filepath.Clean(rootdir), nil
}
- return guessGnoRootDir()
-}
-
-func guessGnoRootDir() (string, error) {
// Try to guess GNOROOT using the nearest go.mod.
if gobin, err := exec.LookPath("go"); err == nil {
// If GNOROOT is not set, try to guess the root directory using the `go list` command.
diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go
index ec098fffaf7..e809103469d 100644
--- a/gno.land/pkg/gnoland/genesis.go
+++ b/gno.land/pkg/gnoland/genesis.go
@@ -51,7 +51,7 @@ func LoadGenesisBalancesFile(path string) ([]Balance, error) {
balances = append(balances, Balance{
Address: addr,
- Amount: coins,
+ Amount: coins,
})
}