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

Fix reorg on init flags #2538

Merged
merged 5 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions cmd/conf/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ type InitConfig struct {
PruneBloomSize uint64 `koanf:"prune-bloom-size"`
PruneThreads int `koanf:"prune-threads"`
PruneTrieCleanCache int `koanf:"prune-trie-clean-cache"`
ResetToMessage int64 `koanf:"reset-to-message"`
RecreateMissingStateFrom uint64 `koanf:"recreate-missing-state-from"`
RebuildLocalWasm bool `koanf:"rebuild-local-wasm"`
ReorgToBatch int64 `koanf:"reorg-to-batch"`
ReorgToMessageBatch int64 `koanf:"reorg-to-message-batch"`
ReorgToBlockBatch int64 `koanf:"reorg-to-block-batch"`
}

var InitConfigDefault = InitConfig{
Expand All @@ -54,9 +56,11 @@ var InitConfigDefault = InitConfig{
PruneBloomSize: 2048,
PruneThreads: runtime.NumCPU(),
PruneTrieCleanCache: gethexec.DefaultCachingConfig.TrieCleanCache,
ResetToMessage: -1,
RecreateMissingStateFrom: 0, // 0 = disabled
RebuildLocalWasm: true,
ReorgToBatch: -1,
ReorgToMessageBatch: -1,
ReorgToBlockBatch: -1,
}

func InitConfigAddOptions(prefix string, f *pflag.FlagSet) {
Expand All @@ -78,9 +82,11 @@ func InitConfigAddOptions(prefix string, f *pflag.FlagSet) {
f.Uint64(prefix+".prune-bloom-size", InitConfigDefault.PruneBloomSize, "the amount of memory in megabytes to use for the pruning bloom filter (higher values prune better)")
f.Int(prefix+".prune-threads", InitConfigDefault.PruneThreads, "the number of threads to use when pruning")
f.Int(prefix+".prune-trie-clean-cache", InitConfigDefault.PruneTrieCleanCache, "amount of memory in megabytes to cache unchanged state trie nodes with when traversing state database during pruning")
f.Int64(prefix+".reset-to-message", InitConfigDefault.ResetToMessage, "forces a reset to an old message height. Also set max-reorg-resequence-depth=0 to force re-reading messages")
f.Uint64(prefix+".recreate-missing-state-from", InitConfigDefault.RecreateMissingStateFrom, "block number to start recreating missing states from (0 = disabled)")
f.Bool(prefix+".rebuild-local-wasm", InitConfigDefault.RebuildLocalWasm, "rebuild local wasm database on boot if needed (otherwise-will be done lazily)")
f.Int64(prefix+".reorg-to-batch", InitConfigDefault.ReorgToBatch, "rolls back the blockchain to a specified batch number")
f.Int64(prefix+".reorg-to-message-batch", InitConfigDefault.ReorgToMessageBatch, "rolls back the blockchain to the first batch at or before a given message index")
f.Int64(prefix+".reorg-to-block-batch", InitConfigDefault.ReorgToBlockBatch, "rolls back the blockchain to the first batch at or before a given block number")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add to Validate() a test that at most one of those is >= 0

}

func (c *InitConfig) Validate() error {
Expand All @@ -96,9 +102,22 @@ func (c *InitConfig) Validate() error {
if c.PruneTrieCleanCache < 0 {
return fmt.Errorf("invalid trie clean cache size: %d, has to be greater or equal 0", c.PruneTrieCleanCache)
}
numReorgOptionsSpecified := 0
for _, reorgOption := range []int64{c.ReorgToBatch, c.ReorgToMessageBatch, c.ReorgToBlockBatch} {
if reorgOption >= 0 {
numReorgOptionsSpecified++
if numReorgOptionsSpecified > 1 {
return fmt.Errorf("at most one init reorg option can be specified")
}
}
}
return nil
}

func (c *InitConfig) IsReorgRequested() bool {
return c.ReorgToBatch >= 0 || c.ReorgToBlockBatch >= 0 || c.ReorgToMessageBatch >= 0
}

var (
acceptedSnapshotKinds = []string{"archive", "pruned", "genesis"}
acceptedSnapshotKindsStr = "(accepted values: \"" + strings.Join(acceptedSnapshotKinds, "\" | \"") + "\")"
Expand Down
69 changes: 54 additions & 15 deletions cmd/nitro/nitro.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/metrics/exp"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"

"github.com/offchainlabs/nitro/arbnode"
"github.com/offchainlabs/nitro/arbnode/resourcemanager"
Expand Down Expand Up @@ -513,7 +514,7 @@ func mainImpl() int {
}
}

if nodeConfig.Init.ThenQuit && nodeConfig.Init.ResetToMessage < 0 {
if nodeConfig.Init.ThenQuit && !nodeConfig.Init.IsReorgRequested() {
return 0
}

Expand Down Expand Up @@ -669,29 +670,34 @@ func mainImpl() int {
sigint := make(chan os.Signal, 1)
signal.Notify(sigint, os.Interrupt, syscall.SIGTERM)

exitCode := 0

if err == nil && nodeConfig.Init.ResetToMessage > 0 {
err = currentNode.TxStreamer.ReorgTo(arbutil.MessageIndex(nodeConfig.Init.ResetToMessage))
if err == nil && nodeConfig.Init.IsReorgRequested() {
err = initReorg(nodeConfig.Init, chainInfo.ChainConfig, currentNode.InboxTracker)
if err != nil {
fatalErrChan <- fmt.Errorf("error reseting message: %w", err)
exitCode = 1
}
if nodeConfig.Init.ThenQuit {
return exitCode
fatalErrChan <- fmt.Errorf("error reorging per init config: %w", err)
} else if nodeConfig.Init.ThenQuit {
return 0
}
}

err = nil
select {
case err := <-fatalErrChan:
case err = <-fatalErrChan:
case <-sigint:
// If there was both a sigint and a fatal error, we want to log the fatal error
select {
case err = <-fatalErrChan:
default:
log.Info("shutting down because of sigint")
}
}

if err != nil {
log.Error("shutting down due to fatal error", "err", err)
defer log.Error("shut down due to fatal error", "err", err)
exitCode = 1
case <-sigint:
log.Info("shutting down because of sigint")
return 1
}

return exitCode
return 0
}

type NodeConfig struct {
Expand Down Expand Up @@ -1003,6 +1009,39 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c
return nil
}

func initReorg(initConfig conf.InitConfig, chainConfig *params.ChainConfig, inboxTracker *arbnode.InboxTracker) error {
var batchCount uint64
if initConfig.ReorgToBatch >= 0 {
batchCount = uint64(initConfig.ReorgToBatch) + 1
} else {
var messageIndex arbutil.MessageIndex
if initConfig.ReorgToMessageBatch >= 0 {
messageIndex = arbutil.MessageIndex(initConfig.ReorgToMessageBatch)
} else if initConfig.ReorgToBlockBatch > 0 {
genesis := chainConfig.ArbitrumChainParams.GenesisBlockNum
blockNum := uint64(initConfig.ReorgToBlockBatch)
if blockNum < genesis {
return fmt.Errorf("ReorgToBlockBatch %d before genesis %d", blockNum, genesis)
}
messageIndex = arbutil.MessageIndex(blockNum - genesis)
} else {
log.Warn("Tried to do init reorg, but no init reorg options specified")
return nil
}
// Reorg out the batch containing the next message
var missing bool
var err error
batchCount, missing, err = inboxTracker.FindInboxBatchContainingMessage(messageIndex + 1)
if err != nil {
return err
}
if missing {
return fmt.Errorf("cannot reorg to unknown message index %v", messageIndex)
}
}
return inboxTracker.ReorgBatchesTo(batchCount)
}

type NodeConfigFetcher struct {
*genericconf.LiveConfig[*NodeConfig]
}
Expand Down
15 changes: 0 additions & 15 deletions execution/gethexec/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,6 @@ import (
flag "github.com/spf13/pflag"
)

type DangerousConfig struct {
ReorgToBlock int64 `koanf:"reorg-to-block"`
}

var DefaultDangerousConfig = DangerousConfig{
ReorgToBlock: -1,
}

func DangerousConfigAddOptions(prefix string, f *flag.FlagSet) {
f.Int64(prefix+".reorg-to-block", DefaultDangerousConfig.ReorgToBlock, "DANGEROUS! forces a reorg to an old block height. To be used for testing only. -1 to disable")
}

type Config struct {
ParentChainReader headerreader.Config `koanf:"parent-chain-reader" reload:"hot"`
Sequencer SequencerConfig `koanf:"sequencer" reload:"hot"`
Expand All @@ -49,7 +37,6 @@ type Config struct {
Caching CachingConfig `koanf:"caching"`
RPC arbitrum.Config `koanf:"rpc"`
TxLookupLimit uint64 `koanf:"tx-lookup-limit"`
Dangerous DangerousConfig `koanf:"dangerous"`
EnablePrefetchBlock bool `koanf:"enable-prefetch-block"`
SyncMonitor SyncMonitorConfig `koanf:"sync-monitor"`

Expand Down Expand Up @@ -89,7 +76,6 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) {
CachingConfigAddOptions(prefix+".caching", f)
SyncMonitorConfigAddOptions(prefix+".sync-monitor", f)
f.Uint64(prefix+".tx-lookup-limit", ConfigDefault.TxLookupLimit, "retain the ability to lookup transactions by hash for the past N blocks (0 = all blocks)")
DangerousConfigAddOptions(prefix+".dangerous", f)
f.Bool(prefix+".enable-prefetch-block", ConfigDefault.EnablePrefetchBlock, "enable prefetching of blocks")
}

Expand All @@ -103,7 +89,6 @@ var ConfigDefault = Config{
TxPreChecker: DefaultTxPreCheckerConfig,
TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second
Caching: DefaultCachingConfig,
Dangerous: DefaultDangerousConfig,
Forwarder: DefaultNodeForwarderConfig,
EnablePrefetchBlock: true,
}
Expand Down
Loading