Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement txs generate and txs clear command #1988

Closed
wants to merge 15 commits into from
3 changes: 3 additions & 0 deletions gno.land/cmd/gnoland/genesis.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package main

import (
"errors"
"flag"

"github.com/gnolang/gno/tm2/pkg/commands"
)

var errUnableToLoadGenesis = errors.New("unable to load genesis")

func newGenesisCmd(io commands.IO) *commands.Command {
cmd := commands.NewCommand(
commands.Metadata{
Expand Down
3 changes: 3 additions & 0 deletions gno.land/cmd/gnoland/genesis_balances.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package main

import (
"errors"
"flag"

"github.com/gnolang/gno/tm2/pkg/commands"
)

var errBalanceNotFound = errors.New("genesis balances entry does not exist")

type balancesCfg struct {
commonCfg
}
Expand Down
6 changes: 0 additions & 6 deletions gno.land/cmd/gnoland/genesis_balances_remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"context"
"errors"
"flag"
"fmt"

Expand All @@ -12,11 +11,6 @@ import (
"github.com/gnolang/gno/tm2/pkg/crypto"
)

var (
errUnableToLoadGenesis = errors.New("unable to load genesis")
errBalanceNotFound = errors.New("genesis balances entry does not exist")
)

type balancesRemoveCfg struct {
rootCfg *balancesCfg

Expand Down
2 changes: 2 additions & 0 deletions gno.land/cmd/gnoland/genesis_txs.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ func newTxsCmd(io commands.IO) *commands.Command {

cmd.AddSubCommands(
newTxsAddCmd(cfg, io),
newTxsGenerateCmd(cfg, io),
newTxsRemoveCmd(cfg, io),
newTxsClearCmd(cfg, io),
newTxsExportCmd(cfg, io),
)

Expand Down
34 changes: 22 additions & 12 deletions gno.land/cmd/gnoland/genesis_txs_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,26 @@
parsedTxs = append(parsedTxs, txs...)
}

// append file txs to genesis
if err := appendTxs(genesis, parsedTxs); err != nil {
return err

Check warning on line 74 in gno.land/cmd/gnoland/genesis_txs_add.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_txs_add.go#L74

Added line #L74 was not covered by tests
}

// Save the updated genesis
if err := genesis.SaveAs(cfg.genesisPath); err != nil {
return fmt.Errorf("unable to save genesis.json, %w", err)

Check warning on line 79 in gno.land/cmd/gnoland/genesis_txs_add.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_txs_add.go#L79

Added line #L79 was not covered by tests
}

io.Printfln(
"Saved %d transactions to genesis.json",
len(parsedTxs),
)

return nil
}

// appendTxs appends the txs to GenesisDoc
func appendTxs(genesis *types.GenesisDoc, txs []std.Tx) error {
// Initialize the app state if it's not present
if genesis.AppState == nil {
genesis.AppState = gnoland.GnoGenesisState{}
Expand All @@ -77,29 +97,19 @@
state := genesis.AppState.(gnoland.GnoGenesisState)

// Left merge the transactions
fileTxStore := txStore(parsedTxs)
inTxStore := txStore(txs)
genesisTxStore := txStore(state.Txs)

// The genesis transactions have preference with the order
// in the genesis.json
if err := genesisTxStore.leftMerge(fileTxStore); err != nil {
if err := genesisTxStore.leftMerge(inTxStore); err != nil {
return err
}

// Save the state
state.Txs = genesisTxStore
genesis.AppState = state

// Save the updated genesis
if err := genesis.SaveAs(cfg.genesisPath); err != nil {
return fmt.Errorf("unable to save genesis.json, %w", err)
}

io.Printfln(
"Saved %d transactions to genesis.json",
len(parsedTxs),
)

return nil
}

Expand Down
58 changes: 58 additions & 0 deletions gno.land/cmd/gnoland/genesis_txs_clear.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"context"
"flag"
"fmt"

"github.com/gnolang/gno/gno.land/pkg/gnoland"
"github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/commands"
)

// newTxsClearCmd creates the genesis txs clear subcommand
func newTxsClearCmd(txsCfg *txsCfg, io commands.IO) *commands.Command {
return commands.NewCommand(
commands.Metadata{
Name: "clear",
ShortUsage: "txs clear",
ShortHelp: "clears all the transactions from the genesis.json",
},
commands.NewEmptyConfig(),
func(ctx context.Context, args []string) error {
return execTxsClear(txsCfg, args, io)
},
)
}

func execTxsClear(cfg *txsCfg, args []string, io commands.IO) error {
if len(args) > 0 {
return flag.ErrHelp
}

// Load the genesis
genesis, err := types.GenesisDocFromFile(cfg.genesisPath)
if err != nil {
return fmt.Errorf("unable to load genesis, %w", err)
}

state := genesis.AppState.(gnoland.GnoGenesisState)

totalTxs := len(state.Txs)

// Remove all txs
state.Txs = nil
genesis.AppState = state

// Save the updated genesis
if err := genesis.SaveAs(cfg.genesisPath); err != nil {
return fmt.Errorf("unable to save genesis.json, %w", err)

Check warning on line 49 in gno.land/cmd/gnoland/genesis_txs_clear.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_txs_clear.go#L49

Added line #L49 was not covered by tests
}

io.Printfln(
"%d txs removed!",
totalTxs,
)

return nil
}
109 changes: 109 additions & 0 deletions gno.land/cmd/gnoland/genesis_txs_clear_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package main

import (
"context"
"flag"
"testing"

"github.com/gnolang/gno/gno.land/pkg/gnoland"
vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm"
"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/require"
)

func TestGenesis_Txs_Clear(t *testing.T) {
t.Parallel()

t.Run("invalid genesis", func(t *testing.T) {
t.Parallel()

// Create the command
cmd := newRootCmd(commands.NewTestIO())
args := []string{
"genesis",
"txs",
"clear",
"--genesis-path",
"dummy-path",
}

// Run the command
cmdErr := cmd.ParseAndRun(context.Background(), args)
require.ErrorContains(t, cmdErr, errUnableToLoadGenesis.Error())
})

t.Run("too many arg", func(t *testing.T) {
t.Parallel()

// Create the command
cmd := newRootCmd(commands.NewTestIO())
args := []string{
"genesis",
"txs",
"clear",
"arg",
"--genesis-path",
"dummy-path",
}

// Run the command
cmdErr := cmd.ParseAndRun(context.Background(), args)
require.ErrorContains(t, cmdErr, flag.ErrHelp.Error())
})

t.Run("clear genesis packages", func(t *testing.T) {
t.Parallel()

tempGenesis, cleanup := testutils.NewTestFile(t)
t.Cleanup(cleanup)

genesis := getDefaultGenesis()
state := gnoland.GnoGenesisState{
// Set an initial addpkg tx
Txs: []std.Tx{
{
Msgs: []std.Msg{
vmm.MsgAddPackage{
Creator: getDummyKey(t).Address(),
Package: &std.MemPackage{
Name: "dummy",
Path: "gno.land/r/demo/dummy",
},
},
},
},
},
}
genesis.AppState = state
require.NoError(t, genesis.SaveAs(tempGenesis.Name()))
require.Equal(t, 1, len(state.Txs))

// Create the command
cmd := newRootCmd(commands.NewTestIO())
args := []string{
"genesis",
"txs",
"clear",
"--genesis-path",
tempGenesis.Name(),
}

// Run the command
cmdErr := cmd.ParseAndRun(context.Background(), args)
require.NoError(t, cmdErr)

// Validate the genesis was updated
genesis, loadErr := types.GenesisDocFromFile(tempGenesis.Name())
require.NoError(t, loadErr)

require.NotNil(t, genesis.AppState)

state, ok := genesis.AppState.(gnoland.GnoGenesisState)
require.True(t, ok)

require.Equal(t, 0, len(state.Txs))
})
}
70 changes: 70 additions & 0 deletions gno.land/cmd/gnoland/genesis_txs_generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package main

import (
"context"
"errors"
"flag"
"fmt"

"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/crypto"
"github.com/gnolang/gno/tm2/pkg/std"
)

var (
test1 = crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
defaultFee = std.NewFee(50000, std.MustParseCoin("1000000ugnot"))
)

var errUnableToLoadPackages = errors.New("unable to load packages")

// newTxsGenerateCmd creates the genesis txs generate subcommand
func newTxsGenerateCmd(txsCfg *txsCfg, io commands.IO) *commands.Command {
return commands.NewCommand(
commands.Metadata{
Name: "generate",
ShortUsage: "txs generate <path> [<path>...]",
ShortHelp: "generates addpkg txs from dir and add them to genesis.json",
},
commands.NewEmptyConfig(),
func(ctx context.Context, args []string) error {
return execTxsGenerate(txsCfg, args, io)
},
)
}

func execTxsGenerate(cfg *txsCfg, args []string, io commands.IO) error {
if len(args) < 1 {
return flag.ErrHelp
}

// Load the genesis
genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath)
if loadErr != nil {
return fmt.Errorf("unable to load genesis, %w", loadErr)
}

txs, err := gnoland.LoadPackagesFromDirs(args, test1, defaultFee, nil)
if err != nil {
return fmt.Errorf("%w: %w", errUnableToLoadPackages, err)
}

// append generated addpkg txs to genesis
if err := appendTxs(genesis, txs); err != nil {
return err

Check warning on line 56 in gno.land/cmd/gnoland/genesis_txs_generate.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_txs_generate.go#L56

Added line #L56 was not covered by tests
}

// Save the updated genesis
if err := genesis.SaveAs(cfg.genesisPath); err != nil {
return fmt.Errorf("unable to save genesis.json, %w", err)

Check warning on line 61 in gno.land/cmd/gnoland/genesis_txs_generate.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_txs_generate.go#L61

Added line #L61 was not covered by tests
}

io.Printfln(
"Saved %d transactions to genesis.json",
len(txs),
)

return nil
}
Loading
Loading