Skip to content

Commit

Permalink
feat: added toml parser for configuration (#358)
Browse files Browse the repository at this point in the history
  • Loading branch information
mtsitrin authored Jun 19, 2023
1 parent e7543de commit d31da1a
Show file tree
Hide file tree
Showing 10 changed files with 810 additions and 196 deletions.
157 changes: 80 additions & 77 deletions block/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ func (m *Manager) ProduceBlockLoop(ctx context.Context) {
return
//Empty blocks timeout
case <-tickerEmptyBlocksMaxTimeCh:
m.logger.Error("No transactions for too long, allowing to produce empty block")
m.logger.Debug("No transactions for too long, allowing to produce empty block")
produceEmptyBlock = true
//Produce block
case <-ticker.C:
Expand Down Expand Up @@ -463,96 +463,98 @@ func (m *Manager) syncUntilTarget(ctx context.Context, syncTarget uint64) {
// In case the following doesn't hold true, it means we crashed after the commit and before updating the store height.
// In that case we'll want to align the store with the app state and continue to the next block.
func (m *Manager) applyBlock(ctx context.Context, block *types.Block, commit *types.Commit, blockMetaData blockMetaData) error {
//TODO: make it more go idiomatic, indent left the main logic
if block.Header.Height == m.store.Height()+1 {
m.logger.Info("Applying block", "height", block.Header.Height, "source", blockMetaData.source)

// Check if alignment is needed due to incosistencies between the store and the app.
isAlignRequired, err := m.alignStoreWithApp(ctx, block)
if err != nil {
return err
}
if isAlignRequired {
m.logger.Info("Aligned with app state required. Skipping to next block", "height", block.Header.Height)
return nil
}
// Start applying the block assuming no inconsistency was found.
_, err = m.store.SaveBlock(block, commit, nil)
if err != nil {
m.logger.Error("Failed to save block", "error", err)
return err
}
if block.Header.Height != m.store.Height()+1 {
// We crashed after the commit and before updating the store height.
return nil
}

responses, err := m.executeBlock(ctx, block, commit)
if err != nil {
m.logger.Error("Failed to execute block", "error", err)
return err
}
m.logger.Debug("Applying block", "height", block.Header.Height, "source", blockMetaData.source)

newState, err := m.executor.UpdateStateFromResponses(responses, m.lastState, block)
if err != nil {
return err
}
// Check if alignment is needed due to incosistencies between the store and the app.
isAlignRequired, err := m.alignStoreWithApp(ctx, block)
if err != nil {
return err
}
if isAlignRequired {
m.logger.Debug("Aligned with app state required. Skipping to next block", "height", block.Header.Height)
return nil
}
// Start applying the block assuming no inconsistency was found.
_, err = m.store.SaveBlock(block, commit, nil)
if err != nil {
m.logger.Error("Failed to save block", "error", err)
return err
}

batch := m.store.NewBatch()
responses, err := m.executeBlock(ctx, block, commit)
if err != nil {
m.logger.Error("Failed to execute block", "error", err)
return err
}

batch, err = m.store.SaveBlockResponses(block.Header.Height, responses, batch)
if err != nil {
batch.Discard()
return err
}
newState, err := m.executor.UpdateStateFromResponses(responses, m.lastState, block)
if err != nil {
return err
}

m.lastState = newState
batch, err = m.store.UpdateState(m.lastState, batch)
if err != nil {
batch.Discard()
return err
}
batch, err = m.store.SaveValidators(block.Header.Height, m.lastState.Validators, batch)
if err != nil {
batch.Discard()
return err
}
batch := m.store.NewBatch()

err = batch.Commit()
if err != nil {
m.logger.Error("Failed to persist batch to disk", "error", err)
return err
}
batch, err = m.store.SaveBlockResponses(block.Header.Height, responses, batch)
if err != nil {
batch.Discard()
return err
}

// Commit block to app
retainHeight, err := m.executor.Commit(ctx, &newState, block, responses)
if err != nil {
m.logger.Error("Failed to commit to the block", "error", err)
return err
}
m.lastState = newState
batch, err = m.store.UpdateState(m.lastState, batch)
if err != nil {
batch.Discard()
return err
}
batch, err = m.store.SaveValidators(block.Header.Height, m.lastState.Validators, batch)
if err != nil {
batch.Discard()
return err
}

// Prune old heights, if requested by ABCI app.
if retainHeight > 0 {
pruned, err := m.pruneBlocks(retainHeight)
if err != nil {
m.logger.Error("failed to prune blocks", "retain_height", retainHeight, "err", err)
} else {
m.logger.Debug("pruned blocks", "pruned", pruned, "retain_height", retainHeight)
}
}
err = batch.Commit()
if err != nil {
m.logger.Error("Failed to persist batch to disk", "error", err)
return err
}

// Update the state with the new app hash, last validators and store height from the commit.
// Every one of those, if happens before commit, prevents us from re-executing the block in case failed during commit.
newState.LastValidators = m.lastState.Validators.Copy()
newState.LastStoreHeight = block.Header.Height
newState.BaseHeight = m.store.Base()
// Commit block to app
retainHeight, err := m.executor.Commit(ctx, &newState, block, responses)
if err != nil {
m.logger.Error("Failed to commit to the block", "error", err)
return err
}

_, err = m.store.UpdateState(newState, nil)
// Prune old heights, if requested by ABCI app.
if retainHeight > 0 {
pruned, err := m.pruneBlocks(retainHeight)
if err != nil {
m.logger.Error("Failed to update state", "error", err)
return err
m.logger.Error("failed to prune blocks", "retain_height", retainHeight, "err", err)
} else {
m.logger.Debug("pruned blocks", "pruned", pruned, "retain_height", retainHeight)
}
m.lastState = newState
}

m.store.SetHeight(block.Header.Height)
// Update the state with the new app hash, last validators and store height from the commit.
// Every one of those, if happens before commit, prevents us from re-executing the block in case failed during commit.
newState.LastValidators = m.lastState.Validators.Copy()
newState.LastStoreHeight = block.Header.Height
newState.BaseHeight = m.store.Base()

_, err = m.store.UpdateState(newState, nil)
if err != nil {
m.logger.Error("Failed to update state", "error", err)
return err
}
m.lastState = newState

m.store.SetHeight(block.Header.Height)

return nil
}

Expand Down Expand Up @@ -686,7 +688,6 @@ func (m *Manager) produceBlock(ctx context.Context, allowEmpty bool) error {
if !allowEmpty && len(block.Data.Txs) == 0 {
return types.ErrSkippedEmptyBlock
}
m.logger.Info("block created", "height", newHeight, "num_tx", len(block.Data.Txs))

abciHeaderPb := abciconv.ToABCIHeaderPB(&block.Header)
abciHeaderBytes, err := abciHeaderPb.Marshal()
Expand Down Expand Up @@ -714,6 +715,8 @@ func (m *Manager) produceBlock(ctx context.Context, allowEmpty bool) error {
return err
}

m.logger.Info("block created", "height", newHeight, "num_tx", len(block.Data.Txs))

//TODO: move to separate function
lastSubmissionTime := atomic.LoadInt64(&m.lastSubmissionTime)
requiredByTime := time.Since(time.Unix(0, lastSubmissionTime)) > m.conf.BatchSubmitMaxTime
Expand Down
11 changes: 5 additions & 6 deletions cmd/dymint/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ func ParseConfig(cmd *cobra.Command) (*cfg.Config, error) {
return nil, fmt.Errorf("error in config file: %v", err)
}

cfg := config.DefaultConfig(home, "")
config.EnsureRoot(conf.RootDir, cfg)
return conf, nil
}

Expand All @@ -64,12 +66,9 @@ var RootCmd = &cobra.Command{
Short: "ABCI-client implementation for dymension's autonomous rollapps",
PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) {
v := viper.GetViper()
err = v.BindPFlags(cmd.Flags())
if err != nil {
return err
}
err = dymconfig.GetViperConfig(v)
if err != nil {

// cmd.Flags() includes flags from this command and all persistent flags from the parent
if err := v.BindPFlags(cmd.Flags()); err != nil {
return err
}

Expand Down
66 changes: 11 additions & 55 deletions cmd/dymint/commands/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import (
"github.com/dymensionxyz/dymint/node"
"github.com/dymensionxyz/dymint/rpc"
"github.com/spf13/cobra"
"github.com/spf13/viper"
tmcfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/libs/cli"
"github.com/tendermint/tendermint/libs/log"
tmos "github.com/tendermint/tendermint/libs/os"
tmnode "github.com/tendermint/tendermint/node"
Expand All @@ -25,66 +27,21 @@ var (
genesisHash []byte
)

// AddNodeFlags exposes some common configuration options on the command-line
// These are exposed for convenience of commands embedding a dymint node
func AddNodeFlags(cmd *cobra.Command) {
// bind flags
cmd.Flags().String("moniker", tmconfig.Moniker, "node name")

// priv val flags
cmd.Flags().String(
"priv_validator_laddr",
tmconfig.PrivValidatorListenAddr,
"socket address to listen on for connections from external priv_validator process")

// node flags
cmd.Flags().BytesHexVar(
&genesisHash,
"genesis_hash",
[]byte{},
"optional SHA-256 hash of the genesis file")

// abci flags
cmd.Flags().String(
"proxy_app",
tmconfig.ProxyApp,
"proxy app address, or one of: 'kvstore',"+
" 'persistent_kvstore' or 'noop' for local testing.")
cmd.Flags().String("abci", tmconfig.ABCI, "specify abci transport (socket | grpc)")

// rpc flags
cmd.Flags().String("rpc.laddr", tmconfig.RPC.ListenAddress, "RPC listen address. Port required")
cmd.Flags().String(
"rpc.grpc_laddr",
tmconfig.RPC.GRPCListenAddress,
"GRPC listen address (BroadcastTx only). Port required")
cmd.Flags().Bool("rpc.unsafe", tmconfig.RPC.Unsafe, "enabled unsafe rpc methods")
cmd.Flags().String("rpc.pprof_laddr", tmconfig.RPC.PprofListenAddress, "pprof listen address (https://golang.org/pkg/net/http/pprof)")

// p2p flags
cmd.Flags().String(
"p2p.laddr",
tmconfig.P2P.ListenAddress,
"node listen address. (0.0.0.0:0 means any interface, any port)")
cmd.Flags().String("p2p.external-address", tmconfig.P2P.ExternalAddress, "ip:port address to advertise to peers for them to dial")
cmd.Flags().String("p2p.seeds", tmconfig.P2P.Seeds, "comma-delimited ID@host:port seed nodes")
cmd.Flags().String("p2p.persistent_peers", tmconfig.P2P.PersistentPeers, "comma-delimited ID@host:port persistent peers")
cmd.Flags().String("p2p.unconditional_peer_ids",
tmconfig.P2P.UnconditionalPeerIDs, "comma-delimited IDs of unconditional peers")
cmd.Flags().Bool("p2p.upnp", tmconfig.P2P.UPNP, "enable/disable UPNP port forwarding")
cmd.Flags().Bool("p2p.pex", tmconfig.P2P.PexReactor, "enable/disable Peer-Exchange")
cmd.Flags().Bool("p2p.seed_mode", tmconfig.P2P.SeedMode, "enable/disable seed mode")
cmd.Flags().String("p2p.private_peer_ids", tmconfig.P2P.PrivatePeerIDs, "comma-delimited private peer IDs")

}

// NewRunNodeCmd returns the command that allows the CLI to start a node.
// It can be used with a custom PrivValidator and in-process ABCI application.
func NewRunNodeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "start",
Aliases: []string{"node", "run"},
Short: "Run the dymint node",
PreRunE: func(cmd *cobra.Command, args []string) error {
homeDir := viper.GetString(cli.HomeFlag)
err := dymconfig.GetViperConfig(cmd, homeDir)
if err != nil {
return err
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
if err := checkGenesisHash(tmconfig); err != nil {
return err
Expand All @@ -98,8 +55,7 @@ func NewRunNodeCmd() *cobra.Command {
},
}

cfg.AddFlags(cmd)
AddNodeFlags(cmd)
cfg.AddNodeFlags(cmd)
return cmd
}

Expand Down
Loading

0 comments on commit d31da1a

Please sign in to comment.