Skip to content

Commit

Permalink
wip: poc fork node
Browse files Browse the repository at this point in the history
Signed-off-by: gfanton <[email protected]>
  • Loading branch information
gfanton committed Dec 20, 2024
1 parent 9586dfe commit bcb44c8
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 37 deletions.
4 changes: 2 additions & 2 deletions gno.land/pkg/gnoland/node_inmemory.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ type InMemoryNodeConfig struct {
PrivValidator bft.PrivValidator // identity of the validator
Genesis *bft.GenesisDoc
TMConfig *tmcfg.Config
DB *memdb.MemDB // will be initialized if nil
VMOutput io.Writer // optional
DB db.DB // will be initialized if nil
VMOutput io.Writer // optional

// If StdlibDir not set, then it's filepath.Join(TMConfig.RootDir, "gnovm", "stdlibs")
InitChainerConfig
Expand Down
10 changes: 7 additions & 3 deletions gno.land/pkg/integration/fork_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/gnolang/gno/tm2/pkg/amino"
tmcfg "github.com/gnolang/gno/tm2/pkg/bft/config"
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/crypto/ed25519"
)

type MarshalableGenesisDoc bft.GenesisDoc
Expand Down Expand Up @@ -42,9 +43,11 @@ func (m *MarshalableGenesisDoc) ToGenesisDoc() *bft.GenesisDoc {
}

type ForkConfig struct {
RootDir string `json:"rootdir"`
Genesis *MarshalableGenesisDoc `json:"genesis"`
TMConfig *tmcfg.Config `json:"tm"`
PrivValidator ed25519.PrivKeyEd25519 `json:"priv"`
DBDir string `json:"dbdir"`
RootDir string `json:"rootdir"`
Genesis *MarshalableGenesisDoc `json:"genesis"`
TMConfig *tmcfg.Config `json:"tm"`
}

// ExecuteForkBinary runs the binary at the given path with the provided configuration.
Expand Down Expand Up @@ -107,6 +110,7 @@ func ExecuteForkBinary(ctx context.Context, binaryPath string, cfg *ForkConfig)
select {
case err := <-readyChan:
if err != nil {
fmt.Println("ERR", err)
cmd.Process.Kill()
return "", cmd, err
}
Expand Down
6 changes: 3 additions & 3 deletions gno.land/pkg/integration/fork_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package integration

import (
"context"
"fmt"
"path/filepath"
"testing"
"time"

"github.com/gnolang/gno/gnovm/pkg/gnoenv"
"github.com/gnolang/gno/tm2/pkg/bft/rpc/client"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

Expand All @@ -29,6 +29,7 @@ func TestForkGnoland(t *testing.T) {

gnoenv.RootDir()
remoteAddr, cmd, err := ExecuteForkBinary(ctx, gnolandBin, &ForkConfig{
// PrivValidator: ed25519.GenPrivKey(),
RootDir: gnoRootDir,
TMConfig: cfg.TMConfig,
Genesis: NewMarshalableGenesisDoc(cfg.Genesis),
Expand All @@ -42,6 +43,5 @@ func TestForkGnoland(t *testing.T) {

info, err := cli.ABCIInfo()
require.NoError(t, err)

fmt.Println(info)
assert.NotEmpty(t, info.Response.Data)
}
51 changes: 42 additions & 9 deletions gno.land/pkg/integration/forknode/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,56 @@ import (
"github.com/gnolang/gno/gno.land/pkg/gnoland"
"github.com/gnolang/gno/gno.land/pkg/integration"
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/db"
"github.com/gnolang/gno/tm2/pkg/db/goleveldb"
"github.com/gnolang/gno/tm2/pkg/db/memdb"
)

// isAllZero checks if all elements in the [64]byte array are zero.
func isAllZero(arr [64]byte) bool {
for _, v := range arr {
if v != 0 {
return false
}
}
return true
}

func ForkableNode(cfg *integration.ForkConfig) error {
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
// logger := slog.New(slog.NewTextHandler(os.Stdout, nil))

var data db.DB
var err error
if cfg.DBDir == "" {
data = memdb.NewMemDB()
} else {
data, err = goleveldb.NewGoLevelDB("testdb", cfg.DBDir)
if err != nil {
return fmt.Errorf("unable to init database in %q: %w", cfg.DBDir, err)
}
}

nodecfg := integration.TestingMinimalNodeConfig(cfg.RootDir)
pv := nodecfg.PrivValidator.GetPubKey()

if len(cfg.PrivValidator) > 0 && !isAllZero(cfg.PrivValidator) {
nodecfg.PrivValidator = bft.NewMockPVWithParams(cfg.PrivValidator, false, false)
pv := nodecfg.PrivValidator.GetPubKey()
nodecfg.Genesis.Validators = []bft.GenesisValidator{
{
Address: pv.Address(),
PubKey: pv,
Power: 10,
Name: "self",
},
}

}

Check failure on line 59 in gno.land/pkg/integration/forknode/main.go

View workflow job for this annotation

GitHub Actions / Run gno.land suite / Go Lint / lint

unnecessary trailing newline (whitespace)

nodecfg.DB = data
nodecfg.TMConfig.DBPath = cfg.DBDir
nodecfg.TMConfig = cfg.TMConfig
nodecfg.Genesis = cfg.Genesis.ToGenesisDoc()
nodecfg.Genesis.Validators = []bft.GenesisValidator{
{
Address: pv.Address(),
PubKey: pv,
Power: 10,
Name: "self",
},
}

node, err := gnoland.NewInMemoryNode(logger, nodecfg)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions gno.land/pkg/integration/testdata/adduserfrom.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ stdout ' "BaseAccount": {'
stdout ' "address": "g1mtmrdmqfu0aryqfl4aw65n35haw2wdjkh5p4cp",'
stdout ' "coins": "10000000ugnot",'
stdout ' "public_key": null,'
stdout ' "account_number": "58",'
stdout ' "account_number": "59",'
stdout ' "sequence": "0"'
stdout ' }'
stdout '}'
! stderr '.+' # empty
! stderr '.+' # empty
4 changes: 2 additions & 2 deletions gno.land/pkg/integration/testdata/loadpkg_example.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ loadpkg gno.land/p/demo/ufmt
## start a new node
gnoland start

gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/importtest -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1
gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/importtest -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1
stdout OK!

## execute Render
gnokey maketx call -pkgpath gno.land/r/importtest -func Render -gas-fee 1000000ugnot -gas-wanted 4000000 -args '' -broadcast -chainid=tendermint_test test1
gnokey maketx call -pkgpath gno.land/r/importtest -func Render -gas-fee 1000000ugnot -gas-wanted 10000000 -args '' -broadcast -chainid=tendermint_test test1
stdout '("92054" string)'
stdout OK!

Expand Down
5 changes: 2 additions & 3 deletions gno.land/pkg/integration/testdata/restart.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
loadpkg gno.land/r/demo/counter $WORK
gnoland start

gnokey maketx call -pkgpath gno.land/r/demo/counter -func Incr -gas-fee 1000000ugnot -gas-wanted 100000 -broadcast -chainid tendermint_test test1
gnokey maketx call -pkgpath gno.land/r/demo/counter -func Incr -gas-fee 1000000ugnot -gas-wanted 200000 -broadcast -chainid tendermint_test test1
stdout '\(1 int\)'

gnoland restart

gnokey maketx call -pkgpath gno.land/r/demo/counter -func Incr -gas-fee 1000000ugnot -gas-wanted 100000 -broadcast -chainid tendermint_test test1
gnokey maketx call -pkgpath gno.land/r/demo/counter -func Incr -gas-fee 1000000ugnot -gas-wanted 200000 -broadcast -chainid tendermint_test test1
stdout '\(2 int\)'

-- counter.gno --
Expand All @@ -21,4 +21,3 @@ func Incr() int {
counter++
return counter
}

50 changes: 37 additions & 13 deletions gno.land/pkg/integration/testscript_gnoland.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"strconv"
"strings"
"sync"
"syscall"
"testing"
"time"

Expand All @@ -25,6 +26,7 @@ import (
"github.com/gnolang/gno/tm2/pkg/commands"
"github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/crypto/bip39"
"github.com/gnolang/gno/tm2/pkg/crypto/ed25519"
"github.com/gnolang/gno/tm2/pkg/crypto/keys"
"github.com/gnolang/gno/tm2/pkg/crypto/keys/client"
tm2Log "github.com/gnolang/gno/tm2/pkg/log"
Expand Down Expand Up @@ -114,9 +116,14 @@ func SetupGnolandTestscript(t *testing.T, p *testscript.Params) error {
}
}

tmpdir := t.TempDir()
// XXX: rework this
tmpdir, dbdir := t.TempDir(), t.TempDir()
gnoHomeDir := filepath.Join(tmpdir, "gno")

env.Values["PK"] = ed25519.GenPrivKey()

env.Setenv("GNO_DBDIR", dbdir)

// Get `TESTWORK` environement variable from setup
persistWorkDir, _ := strconv.ParseBool(env.Getenv("TESTWORK"))

Expand Down Expand Up @@ -264,46 +271,63 @@ func gnolandCmd(t *testing.T, nodesManager *NodesManager, gnolandBin, gnoRootDir
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

dbdir := ts.Getenv("GNO_DBDIR")
priv := ts.Value("PK").(ed25519.PrivKeyEd25519)
remoteAddr, cmd, err := ExecuteForkBinary(ctx, gnolandBin, &ForkConfig{
RootDir: gnoRootDir,
TMConfig: cfg.TMConfig,
Genesis: NewMarshalableGenesisDoc(cfg.Genesis),
PrivValidator: priv,
DBDir: dbdir,
RootDir: gnoRootDir,
TMConfig: cfg.TMConfig,
Genesis: NewMarshalableGenesisDoc(cfg.Genesis),
})
if err != nil {
ts.Fatalf("unable to start the node: %s", err)
}

cfg.TMConfig.RPC.ListenAddress = remoteAddr
nodesManager.Set(sid, &testNode{Cmd: cmd, remoteAddr: remoteAddr, cfg: cfg})

ts.Setenv("RPC_ADDR", remoteAddr)

fmt.Fprintln(ts.Stdout(), "node started successfully")

case "restart":
node, exists := nodesManager.Get(sid)
if !exists {
err = fmt.Errorf("node must be started before being restarted")
break
}

if stopErr := node.Cmd.Process.Kill(); stopErr != nil {
err = fmt.Errorf("error stopping node: %w", stopErr)
fmt.Println("STOPING")

// Send SIGTERM to the process
if err := node.Cmd.Process.Signal(syscall.SIGTERM); err != nil {
err = fmt.Errorf("Error sending SIGTERM: %w\n", err)

Check failure on line 304 in gno.land/pkg/integration/testscript_gnoland.go

View workflow job for this annotation

GitHub Actions / Run gno.land suite / Go Lint / lint

ST1005: error strings should not end with punctuation or newlines (stylecheck)

Check failure on line 304 in gno.land/pkg/integration/testscript_gnoland.go

View workflow job for this annotation

GitHub Actions / Run gno.land suite / Go Lint / lint

ST1005: error strings should not be capitalized (stylecheck)
break
}

ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
// Optionally wait for the process to exit
if _, err := node.Cmd.Process.Wait(); err != nil {
err = fmt.Errorf("Process exited with error: %w", err)

Check failure on line 310 in gno.land/pkg/integration/testscript_gnoland.go

View workflow job for this annotation

GitHub Actions / Run gno.land suite / Go Lint / lint

ST1005: error strings should not be capitalized (stylecheck)
break
}

fmt.Println("STOP DONE")
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()

priv := ts.Value("PK").(ed25519.PrivKeyEd25519)
dbdir := ts.Getenv("GNO_DBDIR")
newRemoteAddr, cmd, err := ExecuteForkBinary(ctx, gnolandBin, &ForkConfig{
RootDir: gnoRootDir,
TMConfig: node.cfg.TMConfig,
Genesis: NewMarshalableGenesisDoc(node.cfg.Genesis),
PrivValidator: priv,
DBDir: dbdir,
RootDir: gnoRootDir,
TMConfig: node.cfg.TMConfig,
Genesis: NewMarshalableGenesisDoc(node.cfg.Genesis),
})
if err != nil {
ts.Fatalf("unable to start the node: %s", err)
}

node.cfg.TMConfig.RPC.ListenAddress = newRemoteAddr
nodesManager.Set(sid, &testNode{Cmd: cmd, remoteAddr: newRemoteAddr, cfg: node.cfg})

fmt.Fprintln(ts.Stdout(), "node restarted successfully")
Expand Down Expand Up @@ -355,7 +379,7 @@ func gnokeyCmd(nodes *NodesManager) func(ts *testscript.TestScript, neg bool, ar
}

if n, ok := nodes.Get(sid); ok {
if raddr := n.cfg.TMConfig.RPC.ListenAddress; raddr != "" {
if raddr := n.remoteAddr; raddr != "" {
defaultArgs = append(defaultArgs, "-remote", raddr)
}

Expand Down
4 changes: 4 additions & 0 deletions tm2/pkg/bft/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,10 @@ func (cfg BaseConfig) NodeKeyFile() string {

// DBDir returns the full path to the database directory
func (cfg BaseConfig) DBDir() string {
if filepath.IsAbs(cfg.DBPath) {
return cfg.DBPath
}

Check warning on line 377 in tm2/pkg/bft/config/config.go

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/bft/config/config.go#L376-L377

Added lines #L376 - L377 were not covered by tests

return filepath.Join(cfg.RootDir, cfg.DBPath)
}

Expand Down

0 comments on commit bcb44c8

Please sign in to comment.