Skip to content

Commit

Permalink
feat: add node genesis deliver handler
Browse files Browse the repository at this point in the history
Signed-off-by: gfanton <[email protected]>
  • Loading branch information
gfanton committed Mar 18, 2024
1 parent 01e91be commit ecd1109
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 39 deletions.
53 changes: 41 additions & 12 deletions contribs/gnodev/pkg/dev/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,29 @@ import (
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/crypto"
tm2events "github.com/gnolang/gno/tm2/pkg/events"
"github.com/gnolang/gno/tm2/pkg/sdk"
"github.com/gnolang/gno/tm2/pkg/std"
// backup "github.com/gnolang/tx-archive/backup/client"
// restore "github.com/gnolang/tx-archive/restore/client"
)

type NodeConfig struct {
PackagesPathList []string
TMConfig *tmcfg.Config
SkipFailingGenesisTxs bool
NoReplay bool
MaxGasPerBlock int64
ChainID string
PackagesPathList []string
TMConfig *tmcfg.Config
NoReplay bool
MaxGasPerBlock int64
ChainID string
}

func DefaultNodeConfig(rootdir string) *NodeConfig {
tmc := gnoland.NewDefaultTMConfig(rootdir)
tmc.Consensus.SkipTimeoutCommit = false // avoid time drifting, see issue #1507

return &NodeConfig{
ChainID: tmc.ChainID(),
PackagesPathList: []string{},
TMConfig: tmc,
SkipFailingGenesisTxs: true,
MaxGasPerBlock: 10_000_000_000,
ChainID: tmc.ChainID(),
PackagesPathList: []string{},
TMConfig: tmc,
MaxGasPerBlock: 10_000_000_000,
}
}

Expand Down Expand Up @@ -230,6 +229,36 @@ func (d *Node) Reload(ctx context.Context) error {
return nil
}

func (d *Node) genesisTxHandler(ctx sdk.Context, tx std.Tx, res sdk.Result) {
if res.IsErr() {
// XXX: for now, this is only way to catch the error
before, after, found := strings.Cut(res.Log, "\n")
if !found {
d.logger.Error("unable to send tx", "err", res.Error, "log", res.Log)
return
}

var attrs []slog.Attr

// Add error
attrs = append(attrs, slog.Any("err", res.Error))

// Fetch first line as error message
msg := strings.TrimFunc(before, func(r rune) bool {
return unicode.IsSpace(r) || r == ':'
})
attrs = append(attrs, slog.String("err", msg))

// If debug is enable, also append stack
if d.logger.Enabled(context.Background(), slog.LevelDebug) {
attrs = append(attrs, slog.String("stack", after))

}

d.logger.LogAttrs(context.Background(), slog.LevelError, "unable to deliver tx", attrs...)
}
}

// GetBlockTransactions returns the transactions contained
// within the specified block, if any
func (d *Node) GetBlockTransactions(blockNum uint64) ([]std.Tx, error) {
Expand Down Expand Up @@ -325,7 +354,7 @@ func (n *Node) stopIfRunning() error {
func (n *Node) reset(ctx context.Context, genesis gnoland.GnoGenesisState) error {
// Setup node config
nodeConfig := newNodeConfig(n.config.TMConfig, n.config.ChainID, genesis)
nodeConfig.SkipFailingGenesisTxs = n.config.SkipFailingGenesisTxs
nodeConfig.GenesisTxHandler = n.genesisTxHandler
nodeConfig.Genesis.ConsensusParams.Block.MaxGas = n.config.MaxGasPerBlock

var recoverErr error
Expand Down
42 changes: 27 additions & 15 deletions gno.land/pkg/gnoland/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,18 @@ type AppOptions struct {
DB dbm.DB
// `gnoRootDir` should point to the local location of the gno repository.
// It serves as the gno equivalent of GOROOT.
GnoRootDir string
SkipFailingGenesisTxs bool
Logger *slog.Logger
MaxCycles int64
GnoRootDir string
GenesisTxHandler GenesisTxHandler
Logger *slog.Logger
MaxCycles int64
}

func NewAppOptions() *AppOptions {
return &AppOptions{
Logger: log.NewNoopLogger(),
DB: memdb.NewMemDB(),
GnoRootDir: gnoenv.RootDir(),
GenesisTxHandler: PanicOnFailingTxHandler,
Logger: log.NewNoopLogger(),
DB: memdb.NewMemDB(),
GnoRootDir: gnoenv.RootDir(),
}
}

Expand Down Expand Up @@ -81,7 +82,7 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) {
vmKpr := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr, stdlibsDir, cfg.MaxCycles)

// Set InitChainer
baseApp.SetInitChainer(InitChainer(baseApp, acctKpr, bankKpr, cfg.SkipFailingGenesisTxs))
baseApp.SetInitChainer(InitChainer(baseApp, acctKpr, bankKpr, cfg.GenesisTxHandler))

// Set AnteHandler
authOptions := auth.AnteOptions{
Expand Down Expand Up @@ -127,7 +128,9 @@ func NewApp(dataRootDir string, skipFailingGenesisTxs bool, logger *slog.Logger,
var err error

cfg := NewAppOptions()
cfg.SkipFailingGenesisTxs = skipFailingGenesisTxs
if skipFailingGenesisTxs {
cfg.GenesisTxHandler = NoopGenesisTxHandler
}

// Get main DB.
cfg.DB, err = dbm.NewDB("gnolang", dbm.GoLevelDBBackend, filepath.Join(dataRootDir, "data"))
Expand All @@ -140,8 +143,18 @@ func NewApp(dataRootDir string, skipFailingGenesisTxs bool, logger *slog.Logger,
return NewAppWithOptions(cfg)
}

type GenesisTxHandler func(ctx sdk.Context, tx std.Tx, res sdk.Result)

func NoopGenesisTxHandler(ctx sdk.Context, tx std.Tx, res sdk.Result) {}

func PanicOnFailingTxHandler(ctx sdk.Context, tx std.Tx, res sdk.Result) {
if res.IsErr() {
panic(res.Log)
}
}

// InitChainer returns a function that can initialize the chain with genesis.
func InitChainer(baseApp *sdk.BaseApp, acctKpr auth.AccountKeeperI, bankKpr bank.BankKeeperI, skipFailingGenesisTxs bool) func(sdk.Context, abci.RequestInitChain) abci.ResponseInitChain {
func InitChainer(baseApp *sdk.BaseApp, acctKpr auth.AccountKeeperI, bankKpr bank.BankKeeperI, resHandler GenesisTxHandler) func(sdk.Context, abci.RequestInitChain) abci.ResponseInitChain {
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
// Get genesis state.
genState := req.AppState.(GnoGenesisState)
Expand All @@ -154,21 +167,20 @@ func InitChainer(baseApp *sdk.BaseApp, acctKpr auth.AccountKeeperI, bankKpr bank
panic(err)
}
}

// Run genesis txs.
for i, tx := range genState.Txs {
res := baseApp.Deliver(tx)
if res.IsErr() {
ctx.Logger().Error("LOG", "log", res.Log)
ctx.Logger().Error(fmt.Sprintf("#%d", i), "value", string(amino.MustMarshalJSON(tx)))

// NOTE: comment out to ignore.
if !skipFailingGenesisTxs {
panic(res.Log)
}
} else {
ctx.Logger().Info("SUCCESS:", "value", string(amino.MustMarshalJSON(tx)))
}

resHandler(ctx, tx, res)
}

// Done!
return abci.ResponseInitChain{
Validators: req.Validators,
Expand Down
27 changes: 15 additions & 12 deletions gno.land/pkg/gnoland/node_inmemory.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ import (
)

type InMemoryNodeConfig struct {
PrivValidator bft.PrivValidator // identity of the validator
Genesis *bft.GenesisDoc
TMConfig *tmcfg.Config
SkipFailingGenesisTxs bool
GenesisMaxVMCycles int64
PrivValidator bft.PrivValidator // identity of the validator
Genesis *bft.GenesisDoc
TMConfig *tmcfg.Config
GenesisTxHandler GenesisTxHandler
GenesisMaxVMCycles int64
}

// NewMockedPrivValidator generate a new key
Expand Down Expand Up @@ -82,6 +82,7 @@ func NewDefaultInMemoryNodeConfig(rootdir string) *InMemoryNodeConfig {
PrivValidator: pv,
TMConfig: tm,
Genesis: genesis,
GenesisTxHandler: PanicOnFailingTxHandler,
GenesisMaxVMCycles: 10_000_000,
}
}
Expand Down Expand Up @@ -110,14 +111,16 @@ func NewInMemoryNode(logger *slog.Logger, cfg *InMemoryNodeConfig) (*node.Node,
return nil, fmt.Errorf("validate config error: %w", err)
}

// Setup options
opts := NewAppOptions()
opts.Logger = logger
opts.GnoRootDir = cfg.TMConfig.RootDir
opts.MaxCycles = cfg.GenesisMaxVMCycles
opts.GenesisTxHandler = cfg.GenesisTxHandler
opts.DB = memdb.NewMemDB()

// Initialize the application with the provided options
gnoApp, err := NewAppWithOptions(&AppOptions{
Logger: logger,
GnoRootDir: cfg.TMConfig.RootDir,
SkipFailingGenesisTxs: cfg.SkipFailingGenesisTxs,
MaxCycles: cfg.GenesisMaxVMCycles,
DB: memdb.NewMemDB(),
})
gnoApp, err := NewAppWithOptions(opts)
if err != nil {
return nil, fmt.Errorf("error initializing new app: %w", err)
}
Expand Down

0 comments on commit ecd1109

Please sign in to comment.