Skip to content

Commit 6e44d92

Browse files
authored
Merge branch 'main' into refactor/gsw-2085
2 parents 55ddfb4 + 723e2c7 commit 6e44d92

File tree

15 files changed

+2652
-0
lines changed

15 files changed

+2652
-0
lines changed

go.mod

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
module github.com/gnoswap-labs/gnoswap
2+
3+
go 1.23.5
4+
5+
require (
6+
github.com/gnolang/gno v0.0.0-20250204100358-df14762147e9
7+
github.com/rogpeppe/go-internal v1.13.1
8+
github.com/stretchr/testify v1.10.0
9+
)
10+
11+
require (
12+
dario.cat/mergo v1.0.1 // indirect
13+
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
14+
github.com/btcsuite/btcd/btcutil v1.1.6 // indirect
15+
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
16+
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
17+
github.com/cosmos/ledger-cosmos-go v0.14.0 // indirect
18+
github.com/davecgh/go-spew v1.1.1 // indirect
19+
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
20+
github.com/go-logr/logr v1.4.2 // indirect
21+
github.com/go-logr/stdr v1.2.2 // indirect
22+
github.com/golang/protobuf v1.5.4 // indirect
23+
github.com/golang/snappy v0.0.4 // indirect
24+
github.com/google/uuid v1.6.0 // indirect
25+
github.com/gorilla/websocket v1.5.3 // indirect
26+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
27+
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
28+
github.com/pelletier/go-toml v1.9.5 // indirect
29+
github.com/peterbourgon/ff/v3 v3.4.0 // indirect
30+
github.com/pkg/errors v0.9.1 // indirect
31+
github.com/pmezard/go-difflib v1.0.0 // indirect
32+
github.com/rs/cors v1.11.1 // indirect
33+
github.com/rs/xid v1.6.0 // indirect
34+
github.com/sig-0/insertion-queue v0.0.0-20241004125609-6b3ca841346b // indirect
35+
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
36+
github.com/zondax/hid v0.9.2 // indirect
37+
github.com/zondax/ledger-go v0.14.3 // indirect
38+
go.etcd.io/bbolt v1.3.11 // indirect
39+
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
40+
go.opentelemetry.io/otel v1.34.0 // indirect
41+
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect
42+
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 // indirect
43+
go.opentelemetry.io/otel/metric v1.34.0 // indirect
44+
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
45+
go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect
46+
go.opentelemetry.io/otel/trace v1.34.0 // indirect
47+
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
48+
go.uber.org/multierr v1.11.0 // indirect
49+
golang.org/x/crypto v0.32.0 // indirect
50+
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
51+
golang.org/x/mod v0.22.0 // indirect
52+
golang.org/x/net v0.34.0 // indirect
53+
golang.org/x/sync v0.10.0 // indirect
54+
golang.org/x/sys v0.29.0 // indirect
55+
golang.org/x/term v0.28.0 // indirect
56+
golang.org/x/text v0.21.0 // indirect
57+
golang.org/x/tools v0.29.0 // indirect
58+
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
59+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
60+
google.golang.org/grpc v1.69.4 // indirect
61+
google.golang.org/protobuf v1.36.3 // indirect
62+
gopkg.in/yaml.v3 v3.0.1 // indirect
63+
)

go.sum

Lines changed: 234 additions & 0 deletions
Large diffs are not rendered by default.

tests/integration/doc.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// Package integration offers utilities to run txtar-based tests against the gnoland system
2+
// by extending the functionalities provided by the standard testscript package. This package is
3+
// currently in an experimental phase and may undergo significant changes in the future.
4+
//
5+
// SetupGnolandTestScript, sets up the environment for running txtar tests, introducing additional
6+
// commands like "gnoland" and "gnokey" into the test script ecosystem. Specifically, it allows the
7+
// user to initiate an in-memory gnoland node and interact with it via the `gnokey` command.
8+
//
9+
// Additional Command Overview:
10+
//
11+
// 1. `gnoland [start|stop|restart]`:
12+
// - The gnoland node doesn't start automatically. This enables the user to do some
13+
// pre-configuration or pass custom arguments to the start command.
14+
// - `gnoland restart` will simulate restarting a node, as in stopping and
15+
// starting it again, recovering state from the persisted database data.
16+
// - `gnoland start -non-validator` can be used to start a node as a non-validator node.
17+
//
18+
// 2. `gnokey`:
19+
// - Supports most of the common commands.
20+
// - `--remote`, `--insecure-password-stdin`, and `--home` flags are set automatically to
21+
// communicate with the gnoland node.
22+
// - In order to handle escape sequences like `\n` within arguments, you can enclose the argument
23+
// in `"`
24+
//
25+
// 3. `adduser`:
26+
// - Must be run before `gnoland start`.
27+
// - Creates a new user in the default keybase directory.
28+
//
29+
// 4. `adduserfrom`:
30+
// - Must be run before `gnoland start`.
31+
// - Creates a new user in the default keybase directory from a given seed. ( Optionally, account and index can be provided )
32+
//
33+
// 5. `loadpkg`:
34+
// - Must be run before `gnoland start`.
35+
// - Loads a specific package from the 'examples' directory or from the working ($WORK) directory.
36+
// - Can be used to load a single package or all packages within a directory.
37+
// - If the target package has a `gno.mod`, all its dependencies (and their respective
38+
// dependencies) will also be loaded.
39+
// - The command takes either one or two arguments. The first argument is the name of the package(s),
40+
// and the second (optional) argument is the path to the package(s).
41+
// Examples:
42+
// -- # Load a package from the 'examples' directory:
43+
// -- loadpkg gno.land/p/demo/ufmt
44+
// -- # Load a package `./bar` from the testscript's working directory with the name `gno.land/r/foobar/bar`:
45+
// -- loadpkg gno.land/r/foobar/bar $WORK/bar
46+
// - If the path is not prefixed with the working directory, it is assumed to be relative to the
47+
// examples directory.
48+
// - It's important to note that the load order is significant when using multiple `loadpkg`
49+
// command; packages should be loaded in the order they are dependent upon.
50+
//
51+
// 6. `patchpkg`:
52+
// - Patches any loaded files by package by replacing all occurrences of the first argument with the second.
53+
// - This is mostly used to replace hardcoded addresses from loaded packages.
54+
// - NOTE: this command may only be temporary, as it's not best approach to
55+
// solve the above problem
56+
//
57+
// Logging:
58+
//
59+
// Gnoland logs aren't forwarded to stdout to avoid overwhelming the tests with too much
60+
// information. Instead, a log directory can be specified with `LOG_DIR`, or you
61+
// can set `TESTWORK=true`
62+
// to persist logs in the txtar working directory. In any case, the log file should be printed
63+
// on start if one of these environment variables is set.
64+
//
65+
// Accounts:
66+
//
67+
// By default, only the test1 user will be created in the default keybase directory,
68+
// with no password set. The default gnoland genesis balance file and the genesis
69+
// transaction file are also registered by default.
70+
//
71+
// Examples:
72+
//
73+
// Examples can be found in the `testdata` directory of this package.
74+
//
75+
// Environment Variables:
76+
//
77+
// Input:
78+
//
79+
// - TESTWORK:
80+
// A boolean that, when enabled, retains working directories after tests for
81+
// inspection. If enabled, gnoland logs will be persisted inside this
82+
// folder.
83+
//
84+
// - UPDATE_SCRIPTS:
85+
// A boolean that, when enabled, updates the test scripts if a `cmp` command
86+
// fails and its second argument refers to a file inside the testscript
87+
// file. The content will be quoted with txtar.Quote if needed, requiring
88+
// manual edits if it's not unquoted in the script.
89+
//
90+
// Output (available inside testscripts files):
91+
//
92+
// - WORK:
93+
// The path to the temporary work directory tree created for each script.
94+
//
95+
// - GNOROOT:
96+
// Points to the local location of the gno repository, serving as the GOROOT equivalent for gno.
97+
//
98+
// - GNOHOME:
99+
// Refers to the local directory where gnokey stores its keys.
100+
//
101+
// - GNODATA:
102+
// The path where the gnoland node stores its configuration and data. It's
103+
// set only if the node has started.
104+
//
105+
// - xxx_user_seed:
106+
// Where `xxx` is the account name; Contains the seed for the test1 account.
107+
//
108+
// - xxx_user_addr:
109+
// Where `xxx` is the account name; Contains the address for the test1 account.
110+
//
111+
// - xxx_account_num:
112+
// Where `xxx` is the account name; Contains the account number for the test1 account.
113+
//
114+
// - xxx_account_seq:
115+
// Where `xxx` is the account name; Contains the address for the test1 account.
116+
//
117+
// - RPC_ADDR:
118+
// Points to the gnoland node's remote address. It's set only if the node has started.
119+
//
120+
// For a more comprehensive guide on original behaviors, additional commands and environment
121+
// variables, refer to the original documentation of testscripts available here:
122+
// https://github.com/rogpeppe/go-internal/blob/master/testscript/doc.go
123+
package integration

tests/integration/node_testing.go

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
package integration
2+
3+
import (
4+
"log/slog"
5+
"path/filepath"
6+
"slices"
7+
"time"
8+
9+
"github.com/gnolang/gno/gno.land/pkg/gnoland"
10+
"github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot"
11+
abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
12+
tmcfg "github.com/gnolang/gno/tm2/pkg/bft/config"
13+
"github.com/gnolang/gno/tm2/pkg/bft/node"
14+
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
15+
"github.com/gnolang/gno/tm2/pkg/crypto"
16+
"github.com/gnolang/gno/tm2/pkg/db/memdb"
17+
"github.com/gnolang/gno/tm2/pkg/std"
18+
"github.com/stretchr/testify/require"
19+
)
20+
21+
const (
22+
DefaultAccount_Name = "test1"
23+
DefaultAccount_Address = "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"
24+
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"
25+
)
26+
27+
// TestingInMemoryNode initializes and starts an in-memory node for testing.
28+
// It returns the node instance and its RPC remote address.
29+
func TestingInMemoryNode(t TestingTS, logger *slog.Logger, config *gnoland.InMemoryNodeConfig) (*node.Node, string) {
30+
node, err := gnoland.NewInMemoryNode(logger, config)
31+
require.NoError(t, err)
32+
33+
err = node.Start()
34+
require.NoError(t, err)
35+
36+
ourAddress := config.PrivValidator.GetPubKey().Address()
37+
isValidator := slices.ContainsFunc(config.Genesis.Validators, func(val bft.GenesisValidator) bool {
38+
return val.Address == ourAddress
39+
})
40+
41+
// Wait for first block if we are a validator.
42+
// If we are not a validator, we don't produce blocks, so node.Ready() hangs.
43+
if isValidator {
44+
select {
45+
case <-node.Ready():
46+
case <-time.After(time.Second * 10):
47+
require.FailNow(t, "timeout while waiting for the node to start")
48+
}
49+
}
50+
51+
return node, node.Config().RPC.ListenAddress
52+
}
53+
54+
// TestingNodeConfig constructs an in-memory node configuration
55+
// with default packages and genesis transactions already loaded.
56+
// It will return the default creator address of the loaded packages.
57+
func TestingNodeConfig(t TestingTS, gnoroot string, additionalTxs ...gnoland.TxWithMetadata) (*gnoland.InMemoryNodeConfig, bft.Address) {
58+
cfg := TestingMinimalNodeConfig(gnoroot)
59+
cfg.SkipGenesisVerification = true
60+
61+
creator := crypto.MustAddressFromString(DefaultAccount_Address) // test1
62+
63+
params := LoadDefaultGenesisParamFile(t, gnoroot)
64+
balances := LoadDefaultGenesisBalanceFile(t, gnoroot)
65+
txs := make([]gnoland.TxWithMetadata, 0)
66+
txs = append(txs, LoadDefaultPackages(t, creator, gnoroot)...)
67+
txs = append(txs, additionalTxs...)
68+
69+
cfg.Genesis.AppState = gnoland.GnoGenesisState{
70+
Balances: balances,
71+
Txs: txs,
72+
Params: params,
73+
}
74+
75+
return cfg, creator
76+
}
77+
78+
// TestingMinimalNodeConfig constructs the default minimal in-memory node configuration for testing.
79+
func TestingMinimalNodeConfig(gnoroot string) *gnoland.InMemoryNodeConfig {
80+
tmconfig := DefaultTestingTMConfig(gnoroot)
81+
82+
// Create Mocked Identity
83+
pv := gnoland.NewMockedPrivValidator()
84+
85+
// Generate genesis config
86+
genesis := DefaultTestingGenesisConfig(gnoroot, pv.GetPubKey(), tmconfig)
87+
88+
return &gnoland.InMemoryNodeConfig{
89+
PrivValidator: pv,
90+
Genesis: genesis,
91+
TMConfig: tmconfig,
92+
DB: memdb.NewMemDB(),
93+
InitChainerConfig: gnoland.InitChainerConfig{
94+
GenesisTxResultHandler: gnoland.PanicOnFailingTxResultHandler,
95+
CacheStdlibLoad: true,
96+
},
97+
}
98+
}
99+
100+
func DefaultTestingGenesisConfig(gnoroot string, self crypto.PubKey, tmconfig *tmcfg.Config) *bft.GenesisDoc {
101+
return &bft.GenesisDoc{
102+
GenesisTime: time.Now(),
103+
ChainID: tmconfig.ChainID(),
104+
ConsensusParams: abci.ConsensusParams{
105+
Block: &abci.BlockParams{
106+
MaxTxBytes: 1_000_000, // 1MB,
107+
MaxDataBytes: 2_000_000, // 2MB,
108+
MaxGas: 3_000_000_000, // 3B gas
109+
TimeIotaMS: 100, // 100ms
110+
},
111+
},
112+
Validators: []bft.GenesisValidator{
113+
{
114+
Address: self.Address(),
115+
PubKey: self,
116+
Power: 10,
117+
Name: "self",
118+
},
119+
},
120+
AppState: gnoland.GnoGenesisState{
121+
Balances: []gnoland.Balance{
122+
{
123+
Address: crypto.MustAddressFromString(DefaultAccount_Address),
124+
Amount: std.MustParseCoins(ugnot.ValueString(10_000_000_000_000)),
125+
},
126+
},
127+
Txs: []gnoland.TxWithMetadata{},
128+
Params: []gnoland.Param{},
129+
},
130+
}
131+
}
132+
133+
// LoadDefaultPackages loads the default packages for testing using a given creator address and gnoroot directory.
134+
func LoadDefaultPackages(t TestingTS, creator bft.Address, gnoroot string) []gnoland.TxWithMetadata {
135+
examplesDir := filepath.Join(gnoroot, "examples")
136+
137+
defaultFee := std.NewFee(50000, std.MustParseCoin(ugnot.ValueString(1000000)))
138+
txs, err := gnoland.LoadPackagesFromDir(examplesDir, creator, defaultFee)
139+
require.NoError(t, err)
140+
141+
return txs
142+
}
143+
144+
// LoadDefaultGenesisBalanceFile loads the default genesis balance file for testing.
145+
func LoadDefaultGenesisBalanceFile(t TestingTS, gnoroot string) []gnoland.Balance {
146+
balanceFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt")
147+
148+
genesisBalances, err := gnoland.LoadGenesisBalancesFile(balanceFile)
149+
require.NoError(t, err)
150+
151+
return genesisBalances.List()
152+
}
153+
154+
// LoadDefaultGenesisParamFile loads the default genesis balance file for testing.
155+
func LoadDefaultGenesisParamFile(t TestingTS, gnoroot string) []gnoland.Param {
156+
paramFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_params.toml")
157+
158+
genesisParams, err := gnoland.LoadGenesisParamsFile(paramFile)
159+
require.NoError(t, err)
160+
161+
return genesisParams
162+
}
163+
164+
// LoadDefaultGenesisTXsFile loads the default genesis transactions file for testing.
165+
func LoadDefaultGenesisTXsFile(t TestingTS, chainid string, gnoroot string) []gnoland.TxWithMetadata {
166+
txsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.jsonl")
167+
168+
// NOTE: We dont care about giving a correct address here, as it's only for display
169+
// XXX: Do we care loading this TXs for testing ?
170+
genesisTXs, err := gnoland.LoadGenesisTxsFile(txsFile, chainid, "https://127.0.0.1:26657")
171+
require.NoError(t, err)
172+
173+
return genesisTXs
174+
}
175+
176+
// DefaultTestingTMConfig constructs the default Tendermint configuration for testing.
177+
func DefaultTestingTMConfig(gnoroot string) *tmcfg.Config {
178+
const defaultListner = "tcp://127.0.0.1:0"
179+
180+
tmconfig := tmcfg.TestConfig().SetRootDir(gnoroot)
181+
tmconfig.Consensus.WALDisabled = true
182+
tmconfig.Consensus.SkipTimeoutCommit = true
183+
tmconfig.Consensus.CreateEmptyBlocks = true
184+
tmconfig.Consensus.CreateEmptyBlocksInterval = time.Millisecond * 100
185+
tmconfig.RPC.ListenAddress = defaultListner
186+
tmconfig.P2P.ListenAddress = defaultListner
187+
return tmconfig
188+
}

0 commit comments

Comments
 (0)