From 2afb28b61d882aee3c3d0a438b66edc35d4a88a2 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 9 Mar 2023 17:42:34 +0200 Subject: [PATCH 001/775] execnode - initial, only build passes --- arbnode/delayed_sequencer.go | 6 +- arbnode/execution/node.go | 89 ----- arbnode/inbox_test.go | 5 +- arbnode/node.go | 199 +++-------- arbnode/seq_coordinator.go | 7 +- arbnode/transaction_streamer.go | 8 +- cmd/nitro/init.go | 16 +- cmd/nitro/nitro.go | 37 +- .../execution => execution/gethclient}/api.go | 2 +- .../gethclient}/arb_interface.go | 2 +- .../gethclient}/block_recorder.go | 19 +- .../gethclient}/blockchain.go | 2 +- .../gethclient}/executionengine.go | 34 +- .../gethclient}/forwarder.go | 2 +- execution/gethclient/node.go | 333 ++++++++++++++++++ .../gethclient}/sequencer.go | 7 +- .../gethclient}/tx_pre_checker.go | 2 +- execution/interface.go | 77 ++++ go-ethereum | 2 +- nodeInterface/NodeInterface.go | 15 +- nodeInterface/virtual-contracts.go | 12 + staker/stateless_block_validator.go | 18 +- 22 files changed, 556 insertions(+), 338 deletions(-) delete mode 100644 arbnode/execution/node.go rename {arbnode/execution => execution/gethclient}/api.go (99%) rename {arbnode/execution => execution/gethclient}/arb_interface.go (98%) rename {arbnode/execution => execution/gethclient}/block_recorder.go (97%) rename {arbnode/execution => execution/gethclient}/blockchain.go (99%) rename {arbnode/execution => execution/gethclient}/executionengine.go (95%) rename {arbnode/execution => execution/gethclient}/forwarder.go (99%) create mode 100644 execution/gethclient/node.go rename {arbnode/execution => execution/gethclient}/sequencer.go (99%) rename {arbnode/execution => execution/gethclient}/tx_pre_checker.go (99%) create mode 100644 execution/interface.go diff --git a/arbnode/delayed_sequencer.go b/arbnode/delayed_sequencer.go index b308b464b..9a0cb2915 100644 --- a/arbnode/delayed_sequencer.go +++ b/arbnode/delayed_sequencer.go @@ -15,8 +15,8 @@ import ( "github.com/ethereum/go-ethereum/log" flag "github.com/spf13/pflag" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/arbos/arbostypes" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/stopwaiter" ) @@ -26,7 +26,7 @@ type DelayedSequencer struct { l1Reader *headerreader.HeaderReader bridge *DelayedBridge inbox *InboxTracker - exec *execution.ExecutionEngine + exec execution.ExecutionClient coordinator *SeqCoordinator waitingForFinalizedBlock uint64 mutex sync.Mutex @@ -63,7 +63,7 @@ var TestDelayedSequencerConfig = DelayedSequencerConfig{ UseMergeFinality: true, } -func NewDelayedSequencer(l1Reader *headerreader.HeaderReader, reader *InboxReader, exec *execution.ExecutionEngine, coordinator *SeqCoordinator, config DelayedSequencerConfigFetcher) (*DelayedSequencer, error) { +func NewDelayedSequencer(l1Reader *headerreader.HeaderReader, reader *InboxReader, exec execution.ExecutionClient, coordinator *SeqCoordinator, config DelayedSequencerConfigFetcher) (*DelayedSequencer, error) { d := &DelayedSequencer{ l1Reader: l1Reader, bridge: reader.DelayedBridge(), diff --git a/arbnode/execution/node.go b/arbnode/execution/node.go deleted file mode 100644 index e59a56876..000000000 --- a/arbnode/execution/node.go +++ /dev/null @@ -1,89 +0,0 @@ -package execution - -import ( - "errors" - - "github.com/ethereum/go-ethereum/arbitrum" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/eth/filters" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/node" - "github.com/offchainlabs/nitro/util/headerreader" -) - -type ExecutionNode struct { - ChainDB ethdb.Database - Backend *arbitrum.Backend - FilterSystem *filters.FilterSystem - ArbInterface *ArbInterface - ExecEngine *ExecutionEngine - Recorder *BlockRecorder - Sequencer *Sequencer // either nil or same as TxPublisher - TxPublisher TransactionPublisher -} - -func CreateExecutionNode( - stack *node.Node, - chainDB ethdb.Database, - l2BlockChain *core.BlockChain, - l1Reader *headerreader.HeaderReader, - syncMonitor arbitrum.SyncProgressBackend, - fwTarget string, - fwConfig *ForwarderConfig, - rpcConfig arbitrum.Config, - seqConfigFetcher SequencerConfigFetcher, - strictnessFetcher func() uint, -) (*ExecutionNode, error) { - execEngine, err := NewExecutionEngine(l2BlockChain) - if err != nil { - return nil, err - } - recorder := NewBlockRecorder(execEngine, chainDB) - var txPublisher TransactionPublisher - var sequencer *Sequencer - seqConfig := seqConfigFetcher() - if seqConfig.Enable { - if fwTarget != "" { - return nil, errors.New("sequencer and forwarding target both set") - } - sequencer, err = NewSequencer(execEngine, l1Reader, seqConfigFetcher) - if err != nil { - return nil, err - } - txPublisher = sequencer - } else { - if fwConfig.RedisUrl != "" { - txPublisher = NewRedisTxForwarder(fwTarget, fwConfig) - } else if fwTarget == "" { - txPublisher = NewTxDropper() - } else { - txPublisher = NewForwarder(fwTarget, fwConfig) - } - } - - txPublisher = NewTxPreChecker(txPublisher, l2BlockChain, strictnessFetcher) - arbInterface, err := NewArbInterface(execEngine, txPublisher) - if err != nil { - return nil, err - } - filterConfig := filters.Config{ - LogCacheSize: rpcConfig.FilterLogCacheSize, - Timeout: rpcConfig.FilterTimeout, - } - backend, filterSystem, err := arbitrum.NewBackend(stack, &rpcConfig, chainDB, arbInterface, syncMonitor, filterConfig) - if err != nil { - return nil, err - } - - return &ExecutionNode{ - chainDB, - backend, - filterSystem, - arbInterface, - execEngine, - recorder, - sequencer, - txPublisher, - }, nil - -} diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 8f67f83eb..037bbc294 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -11,10 +11,11 @@ import ( "testing" "time" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/execution" + "github.com/offchainlabs/nitro/execution/gethclient" "github.com/offchainlabs/nitro/statetransfer" nitroutil "github.com/offchainlabs/nitro/util" @@ -45,7 +46,7 @@ func NewTransactionStreamerForTest(t *testing.T, ownerAddress common.Address) (* arbDb := rawdb.NewMemoryDatabase() initReader := statetransfer.NewMemoryInitDataReader(&initData) - bc, err := execution.WriteOrTestBlockChain(chainDb, nil, initReader, chainConfig, ConfigDefaultL2Test().TxLookupLimit, 0) + bc, err := gethclient.WriteOrTestBlockChain(chainDb, nil, initReader, chainConfig, ConfigDefaultL2Test().TxLookupLimit, 0) if err != nil { Fail(t, err) diff --git a/arbnode/node.go b/arbnode/node.go index c7a38a4e5..b6c002a0e 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -14,25 +14,23 @@ import ( flag "github.com/spf13/pflag" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcastclient" "github.com/offchainlabs/nitro/broadcastclients" "github.com/offchainlabs/nitro/broadcaster" "github.com/offchainlabs/nitro/das" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/challengegen" "github.com/offchainlabs/nitro/solgen/go/ospgen" @@ -384,36 +382,26 @@ func DeployOnL1(ctx context.Context, l1client arbutil.L1Interface, deployAuth *b } type Config struct { - RPC arbitrum.Config `koanf:"rpc"` - Sequencer execution.SequencerConfig `koanf:"sequencer" reload:"hot"` - L1Reader headerreader.Config `koanf:"l1-reader" reload:"hot"` - InboxReader InboxReaderConfig `koanf:"inbox-reader" reload:"hot"` - DelayedSequencer DelayedSequencerConfig `koanf:"delayed-sequencer" reload:"hot"` - BatchPoster BatchPosterConfig `koanf:"batch-poster" reload:"hot"` - ForwardingTargetImpl string `koanf:"forwarding-target"` - Forwarder execution.ForwarderConfig `koanf:"forwarder"` - TxPreCheckerStrictness uint `koanf:"tx-pre-checker-strictness" reload:"hot"` - BlockValidator staker.BlockValidatorConfig `koanf:"block-validator" reload:"hot"` - Feed broadcastclient.FeedConfig `koanf:"feed" reload:"hot"` - Staker staker.L1ValidatorConfig `koanf:"staker"` - SeqCoordinator SeqCoordinatorConfig `koanf:"seq-coordinator"` - DataAvailability das.DataAvailabilityConfig `koanf:"data-availability"` - SyncMonitor SyncMonitorConfig `koanf:"sync-monitor"` - Dangerous DangerousConfig `koanf:"dangerous"` - Caching execution.CachingConfig `koanf:"caching"` - Archive bool `koanf:"archive"` - TxLookupLimit uint64 `koanf:"tx-lookup-limit"` - TransactionStreamer TransactionStreamerConfig `koanf:"transaction-streamer" reload:"hot"` - Maintenance MaintenanceConfig `koanf:"maintenance" reload:"hot"` + Sequencer bool `koanf:"sequencer"` + L1Reader headerreader.Config `koanf:"l1-reader" reload:"hot"` + InboxReader InboxReaderConfig `koanf:"inbox-reader" reload:"hot"` + DelayedSequencer DelayedSequencerConfig `koanf:"delayed-sequencer" reload:"hot"` + BatchPoster BatchPosterConfig `koanf:"batch-poster" reload:"hot"` + BlockValidator staker.BlockValidatorConfig `koanf:"block-validator" reload:"hot"` + Feed broadcastclient.FeedConfig `koanf:"feed" reload:"hot"` + Staker staker.L1ValidatorConfig `koanf:"staker"` + SeqCoordinator SeqCoordinatorConfig `koanf:"seq-coordinator"` + DataAvailability das.DataAvailabilityConfig `koanf:"data-availability"` + SyncMonitor SyncMonitorConfig `koanf:"sync-monitor"` + Dangerous DangerousConfig `koanf:"dangerous"` + TransactionStreamer TransactionStreamerConfig `koanf:"transaction-streamer" reload:"hot"` + Maintenance MaintenanceConfig `koanf:"maintenance" reload:"hot"` } func (c *Config) Validate() error { - if c.L1Reader.Enable && c.Sequencer.Enable && !c.DelayedSequencer.Enable { + if c.L1Reader.Enable && c.Sequencer && !c.DelayedSequencer.Enable { log.Warn("delayed sequencer is not enabled, despite sequencer and l1 reader being enabled") } - if err := c.Sequencer.Validate(); err != nil { - return err - } if err := c.Maintenance.Validate(); err != nil { return err } @@ -441,14 +429,6 @@ func (c *Config) Started() bool { return true } -func (c *Config) ForwardingTarget() string { - if c.ForwardingTargetImpl == "null" { - return "" - } - - return c.ForwardingTargetImpl -} - func (c *Config) ValidatorRequired() bool { if c.BlockValidator.Enable { return true @@ -460,18 +440,11 @@ func (c *Config) ValidatorRequired() bool { } func ConfigAddOptions(prefix string, f *flag.FlagSet, feedInputEnable bool, feedOutputEnable bool) { - arbitrum.ConfigAddOptions(prefix+".rpc", f) - execution.SequencerConfigAddOptions(prefix+".sequencer", f) + f.Bool(prefix+".sequencer", ConfigDefault.Sequencer, "enable sequencer") headerreader.AddOptions(prefix+".l1-reader", f) InboxReaderConfigAddOptions(prefix+".inbox-reader", f) DelayedSequencerConfigAddOptions(prefix+".delayed-sequencer", f) BatchPosterConfigAddOptions(prefix+".batch-poster", f) - f.String(prefix+".forwarding-target", ConfigDefault.ForwardingTargetImpl, "transaction forwarding target URL, or \"null\" to disable forwarding (iff not sequencer)") - execution.AddOptionsForNodeForwarderConfig(prefix+".forwarder", f) - txPreCheckerDescription := "how strict to be when checking txs before forwarding them. 0 = accept anything, " + - "10 = should never reject anything that'd succeed, 20 = likely won't reject anything that'd succeed, " + - "30 = full validation which may reject txs that would succeed" - f.Uint(prefix+".tx-pre-checker-strictness", ConfigDefault.TxPreCheckerStrictness, txPreCheckerDescription) staker.BlockValidatorConfigAddOptions(prefix+".block-validator", f) broadcastclient.FeedConfigAddOptions(prefix+".feed", f, feedInputEnable, feedOutputEnable) staker.L1ValidatorConfigAddOptions(prefix+".staker", f) @@ -479,40 +452,26 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet, feedInputEnable bool, feed das.DataAvailabilityConfigAddNodeOptions(prefix+".data-availability", f) SyncMonitorConfigAddOptions(prefix+".sync-monitor", f) DangerousConfigAddOptions(prefix+".dangerous", f) - execution.CachingConfigAddOptions(prefix+".caching", 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)") TransactionStreamerConfigAddOptions(prefix+".transaction-streamer", f) MaintenanceConfigAddOptions(prefix+".maintenance", f) - - archiveMsg := fmt.Sprintf("retain past block state (deprecated, please use %v.caching.archive)", prefix) - f.Bool(prefix+".archive", ConfigDefault.Archive, archiveMsg) } var ConfigDefault = Config{ - RPC: arbitrum.DefaultConfig, - Sequencer: execution.DefaultSequencerConfig, - L1Reader: headerreader.DefaultConfig, - InboxReader: DefaultInboxReaderConfig, - DelayedSequencer: DefaultDelayedSequencerConfig, - BatchPoster: DefaultBatchPosterConfig, - ForwardingTargetImpl: "", - TxPreCheckerStrictness: execution.TxPreCheckerStrictnessNone, - BlockValidator: staker.DefaultBlockValidatorConfig, - Feed: broadcastclient.FeedConfigDefault, - Staker: staker.DefaultL1ValidatorConfig, - SeqCoordinator: DefaultSeqCoordinatorConfig, - DataAvailability: das.DefaultDataAvailabilityConfig, - SyncMonitor: DefaultSyncMonitorConfig, - Dangerous: DefaultDangerousConfig, - Archive: false, - TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second - Caching: execution.DefaultCachingConfig, - TransactionStreamer: DefaultTransactionStreamerConfig, + L1Reader: headerreader.DefaultConfig, + InboxReader: DefaultInboxReaderConfig, + DelayedSequencer: DefaultDelayedSequencerConfig, + BatchPoster: DefaultBatchPosterConfig, + BlockValidator: staker.DefaultBlockValidatorConfig, + Feed: broadcastclient.FeedConfigDefault, + Staker: staker.DefaultL1ValidatorConfig, + SeqCoordinator: DefaultSeqCoordinatorConfig, + DataAvailability: das.DefaultDataAvailabilityConfig, + SyncMonitor: DefaultSyncMonitorConfig, + TransactionStreamer: DefaultTransactionStreamerConfig, } func ConfigDefaultL1Test() *Config { config := ConfigDefaultL1NonSequencerTest() - config.Sequencer = execution.TestSequencerConfig config.DelayedSequencer = TestDelayedSequencerConfig config.BatchPoster = TestBatchPosterConfig config.SeqCoordinator = TestSeqCoordinatorConfig @@ -524,19 +483,16 @@ func ConfigDefaultL1NonSequencerTest() *Config { config := ConfigDefault config.L1Reader = headerreader.TestConfig config.InboxReader = TestInboxReaderConfig - config.Sequencer.Enable = false config.DelayedSequencer.Enable = false config.BatchPoster.Enable = false config.SeqCoordinator.Enable = false config.BlockValidator = staker.TestBlockValidatorConfig - config.Forwarder = execution.DefaultTestForwarderConfig return &config } func ConfigDefaultL2Test() *Config { config := ConfigDefault - config.Sequencer = execution.TestSequencerConfig config.L1Reader.Enable = false config.SeqCoordinator = TestSeqCoordinatorConfig config.Feed.Input.Verifier.Dangerous.AcceptMissing = true @@ -548,24 +504,24 @@ func ConfigDefaultL2Test() *Config { } type DangerousConfig struct { - NoL1Listener bool `koanf:"no-l1-listener"` - ReorgToBlock int64 `koanf:"reorg-to-block"` + NoL1Listener bool `koanf:"no-l1-listener"` + NoCoordinator bool `koanf:"no-seq-coordinator"` } var DefaultDangerousConfig = DangerousConfig{ - NoL1Listener: false, - ReorgToBlock: -1, + NoL1Listener: false, + NoCoordinator: false, } func DangerousConfigAddOptions(prefix string, f *flag.FlagSet) { f.Bool(prefix+".no-l1-listener", DefaultDangerousConfig.NoL1Listener, "DANGEROUS! disables listening to L1. To be used in test nodes only") - 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") + f.Bool(prefix+".no-seq-coordinator", DefaultDangerousConfig.NoCoordinator, "DANGEROUS! allows sequencing without sequencer-coordinator") } type Node struct { ArbDB ethdb.Database Stack *node.Node - Execution *execution.ExecutionNode + Execution execution.ExecutionClient L1Reader *headerreader.HeaderReader TxStreamer *TransactionStreamer DeployInfo *RollupAddresses @@ -637,6 +593,7 @@ func checkArbDbSchemaVersion(arbDb ethdb.Database) error { func createNodeImpl( ctx context.Context, stack *node.Node, + exec execution.FullExecutionClient, chainDb ethdb.Database, arbDb ethdb.Database, configFetcher ConfigFetcher, @@ -659,12 +616,7 @@ func createNodeImpl( //TODO: // var reorgingToBlock *types.Block - if config.Dangerous.ReorgToBlock >= 0 { - _, err = execution.ReorgToBlock(l2BlockChain, uint64(config.Dangerous.ReorgToBlock)) - if err != nil { - return nil, err - } - } + // config.Dangerous.ReorgToBlock >= 0 { syncMonitor := NewSyncMonitor(&config.SyncMonitor) var classicOutbox *ClassicOutboxRetriever @@ -683,15 +635,6 @@ func createNodeImpl( l1Reader = headerreader.New(l1client, func() *headerreader.Config { return &configFetcher.Get().L1Reader }) } - sequencerConfigFetcher := func() *execution.SequencerConfig { return &configFetcher.Get().Sequencer } - txprecheckStrictFetcher := func() uint { return configFetcher.Get().TxPreCheckerStrictness } - exec, err := execution.CreateExecutionNode(stack, chainDb, l2BlockChain, l1Reader, syncMonitor, - config.ForwardingTarget(), &config.Forwarder, config.RPC, - sequencerConfigFetcher, txprecheckStrictFetcher) - if err != nil { - return nil, err - } - var broadcastServer *broadcaster.Broadcaster if config.Feed.Output.Enable { var maybeDataSigner signature.DataSignerFunc @@ -705,7 +648,7 @@ func createNodeImpl( } transactionStreamerConfigFetcher := func() *TransactionStreamerConfig { return &configFetcher.Get().TransactionStreamer } - txStreamer, err := NewTransactionStreamer(arbDb, l2Config, exec.ExecEngine, broadcastServer, fatalErrChan, transactionStreamerConfigFetcher) + txStreamer, err := NewTransactionStreamer(arbDb, l2Config, exec, broadcastServer, fatalErrChan, transactionStreamerConfigFetcher) if err != nil { return nil, err } @@ -721,16 +664,12 @@ func createNodeImpl( bpVerifier = contracts.NewBatchPosterVerifier(seqInboxCaller) } - if config.DelayedSequencer.Enable != (config.Sequencer.Enable && (l1Reader != nil)) { - return nil, errors.New("cannot have delayedsequencer without sequencer or vice versa") - } - if config.SeqCoordinator.Enable { - coordinator, err = NewSeqCoordinator(dataSigner, bpVerifier, txStreamer, exec.Sequencer, syncMonitor, config.SeqCoordinator) + coordinator, err = NewSeqCoordinator(dataSigner, bpVerifier, txStreamer, exec, syncMonitor, config.SeqCoordinator) if err != nil { return nil, err } - } else if config.Sequencer.Enable && (!config.Sequencer.Dangerous.NoCoordinator) { + } else if config.Sequencer && (!config.Dangerous.NoCoordinator) { return nil, errors.New("sequencer must be enabled with coordinator, unless dangerous.no-coordinator set") } dbs := []ethdb.Database{chainDb, arbDb} @@ -843,7 +782,7 @@ func createNodeImpl( inboxReader, inboxTracker, txStreamer, - exec.Recorder, + exec, rawdb.NewTable(arbDb, blockValidatorPrefix), daReader, &configFetcher.Get().BlockValidator, @@ -933,7 +872,7 @@ func createNodeImpl( } } // always create DelayedSequencer, it won't do anything if it is disabled - delayedSequencer, err = NewDelayedSequencer(l1Reader, inboxReader, exec.ExecEngine, coordinator, func() *DelayedSequencerConfig { return &configFetcher.Get().DelayedSequencer }) + delayedSequencer, err = NewDelayedSequencer(l1Reader, inboxReader, exec, coordinator, func() *DelayedSequencerConfig { return &configFetcher.Get().DelayedSequencer }) if err != nil { return nil, err } @@ -972,6 +911,7 @@ func (n *Node) OnConfigReload(_ *Config, _ *Config) error { func CreateNode( ctx context.Context, stack *node.Node, + exec execution.FullExecutionClient, chainDb ethdb.Database, arbDb ethdb.Database, configFetcher ConfigFetcher, @@ -982,7 +922,7 @@ func CreateNode( dataSigner signature.DataSignerFunc, fatalErrChan chan error, ) (*Node, error) { - currentNode, err := createNodeImpl(ctx, stack, chainDb, arbDb, configFetcher, l2BlockChain, l1client, deployInfo, txOpts, dataSigner, fatalErrChan) + currentNode, err := createNodeImpl(ctx, stack, exec, chainDb, arbDb, configFetcher, l2BlockChain, l1client, deployInfo, txOpts, dataSigner, fatalErrChan) if err != nil { return nil, err } @@ -1007,37 +947,6 @@ func CreateNode( }) } - apis = append(apis, rpc.API{ - Namespace: "arb", - Version: "1.0", - Service: execution.NewArbAPI(currentNode.Execution.TxPublisher), - Public: false, - }) - config := configFetcher.Get() - apis = append(apis, rpc.API{ - Namespace: "arbdebug", - Version: "1.0", - Service: execution.NewArbDebugAPI( - l2BlockChain, - config.RPC.ArbDebug.BlockRangeBound, - config.RPC.ArbDebug.TimeoutQueueBound, - ), - Public: false, - }) - apis = append(apis, rpc.API{ - Namespace: "arbtrace", - Version: "1.0", - Service: execution.NewArbTraceForwarderAPI( - config.RPC.ClassicRedirect, - config.RPC.ClassicRedirectTimeout, - ), - Public: false, - }) - apis = append(apis, rpc.API{ - Namespace: "debug", - Service: eth.NewDebugAPI(eth.NewArbEthereum(l2BlockChain, chainDb)), - Public: false, - }) stack.RegisterAPIs(apis) return currentNode, nil @@ -1045,19 +954,10 @@ func CreateNode( func (n *Node) Start(ctx context.Context) error { n.SyncMonitor.Initialize(n.InboxReader, n.TxStreamer, n.SeqCoordinator) - n.Execution.ArbInterface.Initialize(n) err := n.Stack.Start() if err != nil { return fmt.Errorf("error starting geth stack: %w", err) } - err = n.Execution.Backend.Start() - if err != nil { - return fmt.Errorf("error starting geth backend: %w", err) - } - err = n.Execution.TxPublisher.Initialize(ctx) - if err != nil { - return fmt.Errorf("error initializing transaction publisher: %w", err) - } if n.InboxTracker != nil { err = n.InboxTracker.Initialize() if err != nil { @@ -1074,14 +974,12 @@ func (n *Node) Start(ctx context.Context) error { if err != nil { return fmt.Errorf("error starting transaction streamer: %w", err) } - n.Execution.ExecEngine.Start(ctx) if n.InboxReader != nil { err = n.InboxReader.Start(ctx) if err != nil { return fmt.Errorf("error starting inbox reader: %w", err) } } - err = n.Execution.TxPublisher.Start(ctx) if err != nil { return fmt.Errorf("error starting transaction puiblisher: %w", err) } @@ -1168,9 +1066,6 @@ func (n *Node) StopAndWait() { n.SeqCoordinator.PrepareForShutdown() } n.Stack.StopRPC() // does nothing if not running - if n.Execution.TxPublisher.Started() { - n.Execution.TxPublisher.StopAndWait() - } if n.DelayedSequencer != nil && n.DelayedSequencer.Started() { n.DelayedSequencer.StopAndWait() } @@ -1192,7 +1087,6 @@ func (n *Node) StopAndWait() { if n.StatelessBlockValidator != nil { n.StatelessBlockValidator.Stop() } - n.Execution.Recorder.OrderlyShutdown() if n.InboxReader != nil && n.InboxReader.Started() { n.InboxReader.StopAndWait() } @@ -1202,17 +1096,10 @@ func (n *Node) StopAndWait() { if n.TxStreamer.Started() { n.TxStreamer.StopAndWait() } - if n.Execution.ExecEngine.Started() { - n.Execution.ExecEngine.StopAndWait() - } if n.SeqCoordinator != nil && n.SeqCoordinator.Started() { // Just stops the redis client (most other stuff was stopped earlier) n.SeqCoordinator.StopAndWait() } - n.Execution.ArbInterface.BlockChain().Stop() // does nothing if not running - if err := n.Execution.Backend.Stop(); err != nil { - log.Error("backend stop", "err", err) - } if n.DASLifecycleManager != nil { n.DASLifecycleManager.StopAndWaitUntil(2 * time.Second) } diff --git a/arbnode/seq_coordinator.go b/arbnode/seq_coordinator.go index 16df3153c..60a9616bf 100644 --- a/arbnode/seq_coordinator.go +++ b/arbnode/seq_coordinator.go @@ -20,9 +20,9 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/contracts" "github.com/offchainlabs/nitro/util/redisutil" @@ -41,7 +41,7 @@ type SeqCoordinator struct { sync *SyncMonitor streamer *TransactionStreamer - sequencer *execution.Sequencer + sequencer execution.ExecutionSequencer delayedSequencer *DelayedSequencer signer *signature.SignVerify config SeqCoordinatorConfig // warning: static, don't use for hot reloadable fields @@ -132,7 +132,8 @@ var TestSeqCoordinatorConfig = SeqCoordinatorConfig{ Signing: signature.DefaultSignVerifyConfig, } -func NewSeqCoordinator(dataSigner signature.DataSignerFunc, bpvalidator *contracts.BatchPosterVerifier, streamer *TransactionStreamer, sequencer *execution.Sequencer, sync *SyncMonitor, config SeqCoordinatorConfig) (*SeqCoordinator, error) { +func NewSeqCoordinator(dataSigner signature.DataSignerFunc, bpvalidator *contracts.BatchPosterVerifier, streamer *TransactionStreamer, sequencer execution.ExecutionSequencer, + sync *SyncMonitor, config SeqCoordinatorConfig) (*SeqCoordinator, error) { redisCoordinator, err := redisutil.NewRedisCoordinator(config.RedisUrl) if err != nil { return nil, err diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 0fa5e6886..f0228272b 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -26,10 +26,10 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcaster" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/sharedmetrics" "github.com/offchainlabs/nitro/util/stopwaiter" @@ -41,7 +41,7 @@ type TransactionStreamer struct { stopwaiter.StopWaiter chainConfig *params.ChainConfig - exec *execution.ExecutionEngine + exec execution.FullExecutionClient validator *staker.BlockValidator db ethdb.Database @@ -86,7 +86,7 @@ func TransactionStreamerConfigAddOptions(prefix string, f *flag.FlagSet) { func NewTransactionStreamer( db ethdb.Database, chainConfig *params.ChainConfig, - exec *execution.ExecutionEngine, + exec execution.FullExecutionClient, broadcastServer *broadcaster.Broadcaster, fatalErrChan chan<- error, config TransactionStreamerConfigFetcher, @@ -860,7 +860,7 @@ func (s *TransactionStreamer) ResultAtCount(count arbutil.MessageIndex) (*execut } // return value: true if should be called again -func (s *TransactionStreamer) executeNextMsg(ctx context.Context, exec *execution.ExecutionEngine) bool { +func (s *TransactionStreamer) executeNextMsg(ctx context.Context, exec execution.ExecutionClient) bool { if ctx.Err() != nil { return false } diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 8e50eabcb..c4d13c861 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -23,10 +23,10 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/arbos/arbosState" "github.com/offchainlabs/nitro/cmd/ipfshelper" + "github.com/offchainlabs/nitro/execution/gethclient" "github.com/offchainlabs/nitro/statetransfer" "github.com/pkg/errors" flag "github.com/spf13/pflag" @@ -176,13 +176,13 @@ func validateBlockChain(blockChain *core.BlockChain, expectedChainId *big.Int) e func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeConfig, chainId *big.Int, cacheConfig *core.CacheConfig) (ethdb.Database, *core.BlockChain, error) { if !config.Init.Force { if readOnlyDb, err := stack.OpenDatabaseWithFreezer("l2chaindata", 0, 0, "", "", true); err == nil { - if chainConfig := execution.TryReadStoredChainConfig(readOnlyDb); chainConfig != nil { + if chainConfig := gethclient.TryReadStoredChainConfig(readOnlyDb); chainConfig != nil { readOnlyDb.Close() - chainDb, err := stack.OpenDatabaseWithFreezer("l2chaindata", config.Node.Caching.DatabaseCache, config.Persistent.Handles, "", "", false) + chainDb, err := stack.OpenDatabaseWithFreezer("l2chaindata", config.Execution.Caching.DatabaseCache, config.Persistent.Handles, "", "", false) if err != nil { return chainDb, nil, err } - l2BlockChain, err := execution.GetBlockChain(chainDb, cacheConfig, chainConfig, config.Node.TxLookupLimit) + l2BlockChain, err := gethclient.GetBlockChain(chainDb, cacheConfig, chainConfig, config.Execution.TxLookupLimit) if err != nil { return chainDb, nil, err } @@ -219,7 +219,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo var initDataReader statetransfer.InitDataReader = nil - chainDb, err := stack.OpenDatabaseWithFreezer("l2chaindata", config.Node.Caching.DatabaseCache, config.Persistent.Handles, "", "", false) + chainDb, err := stack.OpenDatabaseWithFreezer("l2chaindata", config.Execution.Caching.DatabaseCache, config.Persistent.Handles, "", "", false) if err != nil { return chainDb, nil, err } @@ -261,11 +261,11 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo var l2BlockChain *core.BlockChain txIndexWg := sync.WaitGroup{} if initDataReader == nil { - chainConfig = execution.TryReadStoredChainConfig(chainDb) + chainConfig = gethclient.TryReadStoredChainConfig(chainDb) if chainConfig == nil { return chainDb, nil, errors.New("no --init.* mode supplied and chain data not in expected directory") } - l2BlockChain, err = execution.GetBlockChain(chainDb, cacheConfig, chainConfig, config.Node.TxLookupLimit) + l2BlockChain, err = gethclient.GetBlockChain(chainDb, cacheConfig, chainConfig, config.Execution.TxLookupLimit) if err != nil { return chainDb, nil, err } @@ -307,7 +307,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if config.Init.ThenQuit { cacheConfig.SnapshotWait = true } - l2BlockChain, err = execution.WriteOrTestBlockChain(chainDb, cacheConfig, initDataReader, chainConfig, config.Node.TxLookupLimit, config.Init.AccountsPerSync) + l2BlockChain, err = gethclient.WriteOrTestBlockChain(chainDb, cacheConfig, initDataReader, chainConfig, config.Execution.TxLookupLimit, config.Init.AccountsPerSync) if err != nil { return chainDb, nil, err } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 40271ab8a..a2f1cff2b 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -45,11 +45,11 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/cmd/conf" "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/cmd/util" "github.com/offchainlabs/nitro/cmd/util/confighelpers" + "github.com/offchainlabs/nitro/execution/gethclient" _ "github.com/offchainlabs/nitro/nodeInterface" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/colors" @@ -273,9 +273,9 @@ func mainImpl() int { fmt.Fprintf(os.Stderr, "Error initializing logging: %v\n", err) os.Exit(1) } - if nodeConfig.Node.Archive { + if nodeConfig.Execution.Archive { log.Warn("--node.archive has been deprecated. Please use --node.caching.archive instead.") - nodeConfig.Node.Caching.Archive = true + nodeConfig.Execution.Caching.Archive = true } log.Info("Running Arbitrum nitro node", "revision", vcsRevision, "vcs.time", vcsTime) @@ -288,8 +288,8 @@ func mainImpl() int { nodeConfig.Node.L1Reader.Enable = true } - if nodeConfig.Node.Sequencer.Enable { - if nodeConfig.Node.ForwardingTarget() != "" { + if nodeConfig.Execution.Sequencer.Enable { + if nodeConfig.Execution.ForwardingTarget() != "" { flag.Usage() log.Crit("forwarding-target cannot be set when sequencer is enabled") } @@ -297,14 +297,14 @@ func mainImpl() int { flag.Usage() log.Crit("hard reorgs cannot safely be enabled with sequencer mode enabled") } - } else if nodeConfig.Node.ForwardingTargetImpl == "" { + } else if nodeConfig.Execution.ForwardingTargetImpl == "" { flag.Usage() log.Crit("forwarding-target unset, and not sequencer (can set to \"null\" to disable forwarding)") } var l1TransactionOpts *bind.TransactOpts var dataSigner signature.DataSignerFunc - sequencerNeedsKey := nodeConfig.Node.Sequencer.Enable && !nodeConfig.Node.Feed.Output.DisableSigning + sequencerNeedsKey := nodeConfig.Node.Sequencer && !nodeConfig.Node.Feed.Output.DisableSigning setupNeedsKey := l1Wallet.OnlyCreateKey || nodeConfig.Node.Staker.OnlyCreateWalletContract validatorCanAct := nodeConfig.Node.Staker.Enable && !strings.EqualFold(nodeConfig.Node.Staker.Strategy, "watchtower") if sequencerNeedsKey || nodeConfig.Node.BatchPoster.Enable || setupNeedsKey || validatorCanAct { @@ -360,9 +360,9 @@ func mainImpl() int { return 0 } - if nodeConfig.Node.Caching.Archive && nodeConfig.Node.TxLookupLimit != 0 { + if nodeConfig.Execution.Caching.Archive && nodeConfig.Execution.TxLookupLimit != 0 { log.Info("retaining ability to lookup full transaction history as archive mode is enabled") - nodeConfig.Node.TxLookupLimit = 0 + nodeConfig.Execution.TxLookupLimit = 0 } stack, err := node.New(&stackConf) @@ -381,7 +381,7 @@ func mainImpl() int { } } - chainDb, l2BlockChain, err := openInitializeChainDb(ctx, stack, nodeConfig, new(big.Int).SetUint64(nodeConfig.L2.ChainID), execution.DefaultCacheConfigFor(stack, &nodeConfig.Node.Caching)) + chainDb, l2BlockChain, err := openInitializeChainDb(ctx, stack, nodeConfig, new(big.Int).SetUint64(nodeConfig.L2.ChainID), gethclient.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching)) defer closeDb(chainDb, "chainDb") if l2BlockChain != nil { // Calling Stop on the blockchain multiple times does nothing @@ -439,9 +439,23 @@ func mainImpl() int { log.Warn("couldn't init validation node", "err", err) } + execNode, err := gethclient.CreateExecutionNode( + stack, + chainDb, + l2BlockChain, + l1Client, + nil, // TODO + func() *gethclient.Config { return &liveNodeConfig.get().Execution }, + ) + if err != nil { + log.Error("failed to create execution node", "err", err) + return 1 + } + currentNode, err := arbnode.CreateNode( ctx, stack, + execNode, chainDb, arbDb, &NodeConfigFetcher{liveNodeConfig}, @@ -477,7 +491,7 @@ func mainImpl() int { } gqlConf := nodeConfig.GraphQL if gqlConf.Enable { - if err := graphql.New(stack, currentNode.Execution.Backend.APIBackend(), currentNode.Execution.FilterSystem, gqlConf.CORSDomain, gqlConf.VHosts); err != nil { + if err := graphql.New(stack, execNode.Backend.APIBackend(), execNode.FilterSystem, gqlConf.CORSDomain, gqlConf.VHosts); err != nil { log.Error("failed to register the GraphQL service", "err", err) return 1 } @@ -520,6 +534,7 @@ func mainImpl() int { type NodeConfig struct { Conf genericconf.ConfConfig `koanf:"conf" reload:"hot"` Node arbnode.Config `koanf:"node" reload:"hot"` + Execution gethclient.Config `koanf:"exec" reload:"hot"` Validation valnode.Config `koanf:"validation" reload:"hot"` L1 conf.L1Config `koanf:"l1"` L2 conf.L2Config `koanf:"l2"` diff --git a/arbnode/execution/api.go b/execution/gethclient/api.go similarity index 99% rename from arbnode/execution/api.go rename to execution/gethclient/api.go index 8f3c37b9b..d7f686baf 100644 --- a/arbnode/execution/api.go +++ b/execution/gethclient/api.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package execution +package gethclient import ( "context" diff --git a/arbnode/execution/arb_interface.go b/execution/gethclient/arb_interface.go similarity index 98% rename from arbnode/execution/arb_interface.go rename to execution/gethclient/arb_interface.go index c1e64db14..7585e2974 100644 --- a/arbnode/execution/arb_interface.go +++ b/execution/gethclient/arb_interface.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package execution +package gethclient import ( "context" diff --git a/arbnode/execution/block_recorder.go b/execution/gethclient/block_recorder.go similarity index 97% rename from arbnode/execution/block_recorder.go rename to execution/gethclient/block_recorder.go index 5152f33eb..c59d484ef 100644 --- a/arbnode/execution/block_recorder.go +++ b/execution/gethclient/block_recorder.go @@ -1,4 +1,4 @@ -package execution +package gethclient import ( "context" @@ -15,6 +15,7 @@ import ( "github.com/offchainlabs/nitro/arbos/arbosState" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/validator" ) @@ -39,13 +40,6 @@ type BlockRecorder struct { preparedLock sync.Mutex } -type RecordResult struct { - Pos arbutil.MessageIndex - BlockHash common.Hash - Preimages map[common.Hash][]byte - BatchInfo []validator.BatchInfo -} - func NewBlockRecorder(execEngine *ExecutionEngine, ethDb ethdb.Database) *BlockRecorder { recorder := &BlockRecorder{ execEngine: execEngine, @@ -77,7 +71,7 @@ func (r *BlockRecorder) RecordBlockCreation( ctx context.Context, pos arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, -) (*RecordResult, error) { +) (*execution.RecordResult, error) { blockNum := r.execEngine.MessageIndexToBlockNumber(pos) @@ -168,7 +162,12 @@ func (r *BlockRecorder) RecordBlockCreation( r.updateLastHdr(prevHeader) r.updateValidCandidateHdr(prevHeader) - return &RecordResult{pos, blockHash, preimages, readBatchInfo}, err + return &execution.RecordResult{ + Pos: pos, + BlockHash: blockHash, + Preimages: preimages, + BatchInfo: readBatchInfo, + }, err } func (r *BlockRecorder) updateLastHdr(hdr *types.Header) { diff --git a/arbnode/execution/blockchain.go b/execution/gethclient/blockchain.go similarity index 99% rename from arbnode/execution/blockchain.go rename to execution/gethclient/blockchain.go index 4c84467bb..2a953c5db 100644 --- a/arbnode/execution/blockchain.go +++ b/execution/gethclient/blockchain.go @@ -1,4 +1,4 @@ -package execution +package gethclient import ( "errors" diff --git a/arbnode/execution/executionengine.go b/execution/gethclient/executionengine.go similarity index 95% rename from arbnode/execution/executionengine.go rename to execution/gethclient/executionengine.go index f32aef49e..060d0cbb4 100644 --- a/arbnode/execution/executionengine.go +++ b/execution/gethclient/executionengine.go @@ -1,4 +1,4 @@ -package execution +package gethclient import ( "context" @@ -8,7 +8,6 @@ import ( "testing" "time" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -19,22 +18,17 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbos/l1pricing" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/util/sharedmetrics" "github.com/offchainlabs/nitro/util/stopwaiter" "github.com/pkg/errors" ) -type TransactionStreamerInterface interface { - WriteMessageFromSequencer(pos arbutil.MessageIndex, msgWithMeta arbostypes.MessageWithMetadata) error - ExpectChosenSequencer() error - FetchBatch(batchNum uint64) ([]byte, error) -} - type ExecutionEngine struct { stopwaiter.StopWaiter bc *core.BlockChain - streamer TransactionStreamerInterface + streamer execution.TransactionStreamer recorder *BlockRecorder resequenceChan chan []*arbostypes.MessageWithMetadata @@ -77,7 +71,7 @@ func (s *ExecutionEngine) EnableReorgSequencing() { s.reorgSequencing = true } -func (s *ExecutionEngine) SetTransactionStreamer(streamer TransactionStreamerInterface) { +func (s *ExecutionEngine) SetTransactionStreamer(streamer execution.TransactionStreamer) { if s.Started() { panic("trying to set transaction streamer after start") } @@ -225,15 +219,13 @@ func (s *ExecutionEngine) resequenceReorgedMessages(messages []*arbostypes.Messa } } -var ErrSequencerInsertLockTaken = errors.New("insert lock taken") - func (s *ExecutionEngine) SequenceTransactions(header *arbostypes.L1IncomingMessageHeader, txes types.Transactions, hooks *arbos.SequencingHooks) (*types.Block, error) { for { hooks.TxErrors = nil s.createBlocksMutex.Lock() block, err := s.sequenceTransactionsWithBlockMutex(header, txes, hooks) s.createBlocksMutex.Unlock() - if !errors.Is(err, ErrSequencerInsertLockTaken) { + if !errors.Is(err, execution.ErrSequencerInsertLockTaken) { return block, err } <-time.After(time.Millisecond * 100) @@ -322,7 +314,7 @@ func (s *ExecutionEngine) SequenceDelayedMessage(message *arbostypes.L1IncomingM s.createBlocksMutex.Lock() err := s.sequenceDelayedMessageWithBlockMutex(message, delayedSeqNum) s.createBlocksMutex.Unlock() - if !errors.Is(err, ErrSequencerInsertLockTaken) { + if !errors.Is(err, execution.ErrSequencerInsertLockTaken) { return err } <-time.After(time.Millisecond * 100) @@ -428,12 +420,7 @@ func (s *ExecutionEngine) appendBlock(block *types.Block, statedb *state.StateDB return nil } -type MessageResult struct { - BlockHash common.Hash - SendRoot common.Hash -} - -func (s *ExecutionEngine) resultFromHeader(header *types.Header) (*MessageResult, error) { +func (s *ExecutionEngine) resultFromHeader(header *types.Header) (*execution.MessageResult, error) { if header == nil { return nil, fmt.Errorf("result not found") } @@ -441,10 +428,13 @@ func (s *ExecutionEngine) resultFromHeader(header *types.Header) (*MessageResult if err != nil { return nil, err } - return &MessageResult{header.Hash(), info.SendRoot}, nil + return &execution.MessageResult{ + BlockHash: header.Hash(), + SendRoot: info.SendRoot, + }, nil } -func (s *ExecutionEngine) ResultAtPos(pos arbutil.MessageIndex) (*MessageResult, error) { +func (s *ExecutionEngine) ResultAtPos(pos arbutil.MessageIndex) (*execution.MessageResult, error) { return s.resultFromHeader(s.bc.GetHeaderByNumber(s.MessageIndexToBlockNumber(pos))) } diff --git a/arbnode/execution/forwarder.go b/execution/gethclient/forwarder.go similarity index 99% rename from arbnode/execution/forwarder.go rename to execution/gethclient/forwarder.go index f0ed7eec4..60dd4f4d8 100644 --- a/arbnode/execution/forwarder.go +++ b/execution/gethclient/forwarder.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package execution +package gethclient import ( "context" diff --git a/execution/gethclient/node.go b/execution/gethclient/node.go new file mode 100644 index 000000000..249fcfe25 --- /dev/null +++ b/execution/gethclient/node.go @@ -0,0 +1,333 @@ +package gethclient + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/ethereum/go-ethereum/arbitrum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/eth/filters" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/rpc" + "github.com/offchainlabs/nitro/arbos/arbostypes" + "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/execution" + "github.com/offchainlabs/nitro/util/headerreader" + 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 { + L1Reader headerreader.Config `koanf:"l1-reader" reload:"hot"` + Sequencer SequencerConfig `koanf:"sequencer" reload:"hot"` + TxPreCheckerStrictness uint `koanf:"tx-pre-checker-strictness" reload:"hot"` + Forwarder ForwarderConfig `koanf:"forwarder"` + ForwardingTargetImpl string `koanf:"forwarding-target"` + Caching CachingConfig `koanf:"caching"` + RPC arbitrum.Config `koanf:"rpc"` + Archive bool `koanf:"archive"` + TxLookupLimit uint64 `koanf:"tx-lookup-limit"` + Dangerous DangerousConfig `koanf:"dangerous"` +} + +func (c *Config) ForwardingTarget() string { + if c.ForwardingTargetImpl == "null" { + return "" + } + + return c.ForwardingTargetImpl +} + +func (c *Config) Validate() error { + if err := c.Sequencer.Validate(); err != nil { + return err + } + return nil +} + +func ConfigAddOptions(prefix string, f *flag.FlagSet, feedInputEnable bool, feedOutputEnable bool) { + arbitrum.ConfigAddOptions(prefix+".rpc", f) + SequencerConfigAddOptions(prefix+".sequencer", f) + f.String(prefix+".forwarding-target", ConfigDefault.ForwardingTargetImpl, "transaction forwarding target URL, or \"null\" to disable forwarding (iff not sequencer)") + AddOptionsForNodeForwarderConfig(prefix+".forwarder", f) + txPreCheckerDescription := "how strict to be when checking txs before forwarding them. 0 = accept anything, " + + "10 = should never reject anything that'd succeed, 20 = likely won't reject anything that'd succeed, " + + "30 = full validation which may reject txs that would succeed" + f.Uint(prefix+".tx-pre-checker-strictness", ConfigDefault.TxPreCheckerStrictness, txPreCheckerDescription) + CachingConfigAddOptions(prefix+".caching", 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)") + + archiveMsg := fmt.Sprintf("retain past block state (deprecated, please use %v.caching.archive)", prefix) + f.Bool(prefix+".archive", ConfigDefault.Archive, archiveMsg) + DangerousConfigAddOptions(prefix+".dangerous", f) +} + +var ConfigDefault = Config{ + RPC: arbitrum.DefaultConfig, + Sequencer: DefaultSequencerConfig, + ForwardingTargetImpl: "", + TxPreCheckerStrictness: TxPreCheckerStrictnessNone, + Archive: false, + TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second + Caching: DefaultCachingConfig, +} + +func ConfigDefaultL1Test() *Config { + config := ConfigDefaultL1NonSequencerTest() + config.Sequencer = TestSequencerConfig + + return config +} + +func ConfigDefaultL1NonSequencerTest() *Config { + config := ConfigDefault + config.Sequencer.Enable = false + config.Forwarder = DefaultTestForwarderConfig + + return &config +} + +func ConfigDefaultL2Test() *Config { + config := ConfigDefault + config.Sequencer = TestSequencerConfig + + return &config +} + +type ConfigFetcher func() *Config + +type ExecutionNode struct { + ChainDB ethdb.Database + Backend *arbitrum.Backend + FilterSystem *filters.FilterSystem + ArbInterface *ArbInterface + ExecEngine *ExecutionEngine + Recorder *BlockRecorder + Sequencer *Sequencer // either nil or same as TxPublisher + TxPublisher TransactionPublisher +} + +func CreateExecutionNode( + stack *node.Node, + chainDB ethdb.Database, + l2BlockChain *core.BlockChain, + l1client arbutil.L1Interface, + syncMonitor arbitrum.SyncProgressBackend, + configFetcher ConfigFetcher, +) (*ExecutionNode, error) { + config := configFetcher() + execEngine, err := NewExecutionEngine(l2BlockChain) + if err != nil { + return nil, err + } + recorder := NewBlockRecorder(execEngine, chainDB) + var txPublisher TransactionPublisher + var sequencer *Sequencer + + l1Reader := headerreader.New(l1client, func() *headerreader.Config { return &configFetcher().L1Reader }) + + fwTarget := config.ForwardingTarget() + if config.Sequencer.Enable { + if fwTarget != "" { + return nil, errors.New("sequencer and forwarding target both set") + } + seqConfigFetcher := func() *SequencerConfig { return &configFetcher().Sequencer } + sequencer, err = NewSequencer(execEngine, l1Reader, seqConfigFetcher) + if err != nil { + return nil, err + } + txPublisher = sequencer + } else { + if config.Forwarder.RedisUrl != "" { + txPublisher = NewRedisTxForwarder(fwTarget, &config.Forwarder) + } else if fwTarget == "" { + txPublisher = NewTxDropper() + } else { + txPublisher = NewForwarder(fwTarget, &config.Forwarder) + } + } + + strictnessFetcher := func() uint { return configFetcher().TxPreCheckerStrictness } + txPublisher = NewTxPreChecker(txPublisher, l2BlockChain, strictnessFetcher) + arbInterface, err := NewArbInterface(execEngine, txPublisher) + if err != nil { + return nil, err + } + filterConfig := filters.Config{ + LogCacheSize: config.RPC.FilterLogCacheSize, + Timeout: config.RPC.FilterTimeout, + } + backend, filterSystem, err := arbitrum.NewBackend(stack, &config.RPC, chainDB, arbInterface, syncMonitor, filterConfig) + if err != nil { + return nil, err + } + + apis := []rpc.API{{ + Namespace: "arb", + Version: "1.0", + Service: NewArbAPI(txPublisher), + Public: false, + }} + apis = append(apis, rpc.API{ + Namespace: "arbdebug", + Version: "1.0", + Service: NewArbDebugAPI( + l2BlockChain, + config.RPC.ArbDebug.BlockRangeBound, + config.RPC.ArbDebug.TimeoutQueueBound, + ), + Public: false, + }) + apis = append(apis, rpc.API{ + Namespace: "arbtrace", + Version: "1.0", + Service: NewArbTraceForwarderAPI( + config.RPC.ClassicRedirect, + config.RPC.ClassicRedirectTimeout, + ), + Public: false, + }) + apis = append(apis, rpc.API{ + Namespace: "debug", + Service: eth.NewDebugAPI(eth.NewArbEthereum(l2BlockChain, chainDB)), + Public: false, + }) + + stack.RegisterAPIs(apis) + + return &ExecutionNode{ + chainDB, + backend, + filterSystem, + arbInterface, + execEngine, + recorder, + sequencer, + txPublisher, + }, nil + +} + +func (n *ExecutionNode) Initialize(ctx context.Context, arbnode interface{}) error { + n.ArbInterface.Initialize(n) + err := n.Backend.Start() + if err != nil { + return fmt.Errorf("error starting geth backend: %w", err) + } + err = n.TxPublisher.Initialize(ctx) + if err != nil { + return fmt.Errorf("error initializing transaction publisher: %w", err) + } + return nil +} + +func (n *ExecutionNode) Start(ctx context.Context) error { + // TODO after separation + // err := n.Stack.Start() + // if err != nil { + // return fmt.Errorf("error starting geth stack: %w", err) + // } + n.ExecEngine.Start(ctx) + err := n.TxPublisher.Start(ctx) + if err != nil { + return fmt.Errorf("error starting transaction puiblisher: %w", err) + } + // TODO after separation + // if n.L1Reader != nil { + // n.L1Reader.Start(ctx) + // } + return nil +} + +func (n *ExecutionNode) StopAndWait() { + // TODO after separation + // n.Stack.StopRPC() // does nothing if not running + if n.TxPublisher.Started() { + n.TxPublisher.StopAndWait() + } + n.Recorder.OrderlyShutdown() + // TODO after separation + // if n.L1Reader != nil && n.L1Reader.Started() { + // n.L1Reader.StopAndWait() + // } + if n.ExecEngine.Started() { + n.ExecEngine.StopAndWait() + } + n.ArbInterface.BlockChain().Stop() // does nothing if not running + if err := n.Backend.Stop(); err != nil { + log.Error("backend stop", "err", err) + } + // TODO after separation + // if err := n.Stack.Close(); err != nil { + // log.Error("error on stak close", "err", err) + // } +} + +func (n *ExecutionNode) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata) error { + return n.ExecEngine.DigestMessage(num, msg) +} +func (n *ExecutionNode) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadata, oldMessages []*arbostypes.MessageWithMetadata) error { + return n.ExecEngine.Reorg(count, newMessages, oldMessages) +} +func (n *ExecutionNode) HeadMessageNumber() (arbutil.MessageIndex, error) { + return n.ExecEngine.HeadMessageNumber() +} +func (n *ExecutionNode) HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) { + return n.ExecEngine.HeadMessageNumberSync(t) +} +func (n *ExecutionNode) NextDelayedMessageNumber() (uint64, error) { + return n.ExecEngine.NextDelayedMessageNumber() +} +func (n *ExecutionNode) SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error { + return n.ExecEngine.SequenceDelayedMessage(message, delayedSeqNum) +} +func (n *ExecutionNode) ResultAtPos(pos arbutil.MessageIndex) (*execution.MessageResult, error) { + return n.ExecEngine.ResultAtPos(pos) +} + +func (n *ExecutionNode) RecordBlockCreation( + ctx context.Context, + pos arbutil.MessageIndex, + msg *arbostypes.MessageWithMetadata, +) (*execution.RecordResult, error) { + return n.Recorder.RecordBlockCreation(ctx, pos, msg) +} +func (n *ExecutionNode) MarkValid(pos arbutil.MessageIndex, resultHash common.Hash) { + n.Recorder.MarkValid(pos, resultHash) +} +func (n *ExecutionNode) PrepareForRecord(ctx context.Context, start, end arbutil.MessageIndex) error { + return n.Recorder.PrepareForRecord(ctx, start, end) +} + +func (n *ExecutionNode) Pause() { + n.Sequencer.Pause() +} +func (n *ExecutionNode) Activate() { + n.Sequencer.Activate() +} +func (n *ExecutionNode) ForwardTo(url string) error { + return n.Sequencer.ForwardTo(url) +} +func (n *ExecutionNode) SetTransactionStreamer(streamer execution.TransactionStreamer) { + n.ExecEngine.SetTransactionStreamer(streamer) +} +func (n *ExecutionNode) MessageIndexToBlockNumber(messageNum arbutil.MessageIndex) uint64 { + return n.ExecEngine.MessageIndexToBlockNumber(messageNum) +} diff --git a/arbnode/execution/sequencer.go b/execution/gethclient/sequencer.go similarity index 99% rename from arbnode/execution/sequencer.go rename to execution/gethclient/sequencer.go index 830ffd6a9..ddc70ac2b 100644 --- a/arbnode/execution/sequencer.go +++ b/execution/gethclient/sequencer.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package execution +package gethclient import ( "context" @@ -14,6 +14,7 @@ import ( "sync/atomic" "time" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/containers" "github.com/offchainlabs/nitro/util/headerreader" @@ -334,8 +335,6 @@ func (s *Sequencer) onNonceFailureEvict(_ addressAndNonce, failure *nonceFailure } } -var ErrRetrySequencer = errors.New("please retry transaction") - func (s *Sequencer) ctxWithQueueTimeout(inctx context.Context) (context.Context, context.CancelFunc) { timeout := s.config().QueueTimeout if timeout == time.Duration(0) { @@ -813,7 +812,7 @@ func (s *Sequencer) createBlock(ctx context.Context) (returnValue bool) { if err == nil && len(hooks.TxErrors) != len(txes) { err = fmt.Errorf("unexpected number of error results: %v vs number of txes %v", len(hooks.TxErrors), len(txes)) } - if errors.Is(err, ErrRetrySequencer) { + if errors.Is(err, execution.ErrRetrySequencer) { log.Warn("error sequencing transactions", "err", err) // we changed roles // forward if we have where to diff --git a/arbnode/execution/tx_pre_checker.go b/execution/gethclient/tx_pre_checker.go similarity index 99% rename from arbnode/execution/tx_pre_checker.go rename to execution/gethclient/tx_pre_checker.go index 8a41d6177..3c991343d 100644 --- a/arbnode/execution/tx_pre_checker.go +++ b/execution/gethclient/tx_pre_checker.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package execution +package gethclient import ( "context" diff --git a/execution/interface.go b/execution/interface.go new file mode 100644 index 000000000..eb929274d --- /dev/null +++ b/execution/interface.go @@ -0,0 +1,77 @@ +package execution + +import ( + "context" + "errors" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/offchainlabs/nitro/arbos/arbostypes" + "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/validator" +) + +type MessageResult struct { + BlockHash common.Hash + SendRoot common.Hash +} + +type RecordResult struct { + Pos arbutil.MessageIndex + BlockHash common.Hash + Preimages map[common.Hash][]byte + BatchInfo []validator.BatchInfo +} + +var ErrRetrySequencer = errors.New("please retry transaction") +var ErrSequencerInsertLockTaken = errors.New("insert lock taken") + +// always needed +type ExecutionClient interface { + DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata) error + Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadata, oldMessages []*arbostypes.MessageWithMetadata) error + HeadMessageNumber() (arbutil.MessageIndex, error) + HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) + NextDelayedMessageNumber() (uint64, error) + SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error + ResultAtPos(pos arbutil.MessageIndex) (*MessageResult, error) +} + +// needed for validators / stakers +type ExecutionRecorder interface { + RecordBlockCreation( + ctx context.Context, + pos arbutil.MessageIndex, + msg *arbostypes.MessageWithMetadata, + ) (*RecordResult, error) + MarkValid(pos arbutil.MessageIndex, resultHash common.Hash) + PrepareForRecord(ctx context.Context, start, end arbutil.MessageIndex) error +} + +// needed for sequencer +type ExecutionSequencer interface { + Pause() + Activate() + ForwardTo(url string) error + SetTransactionStreamer(streamer TransactionStreamer) +} + +type FullExecutionClient interface { + ExecutionClient + ExecutionRecorder + ExecutionSequencer + + // TODO: only used to get safe/finalized block numbers + MessageIndexToBlockNumber(messageNum arbutil.MessageIndex) uint64 +} + +// not implemented in execution, used as input +type BatchFetcher interface { + FetchBatch(batchNum uint64) ([]byte, error) +} + +type TransactionStreamer interface { + BatchFetcher + WriteMessageFromSequencer(pos arbutil.MessageIndex, msgWithMeta arbostypes.MessageWithMetadata) error + ExpectChosenSequencer() error +} diff --git a/go-ethereum b/go-ethereum index c9b451414..c3e683a62 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit c9b451414caba4ecacd8aac993e7bf49f16ad887 +Subproject commit c3e683a62a256a7f3aed280778e94862f74de700 diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index 5a5bbc5c8..097f0dcca 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -78,7 +78,10 @@ func (n NodeInterface) GetL1Confirmations(c ctx, evm mech, blockHash bytes32) (u if node.InboxReader == nil { return 0, nil } - bc := node.Execution.ArbInterface.BlockChain() + bc, err := blockchainFromNodeInterfaceBackend(n.backend) + if err != nil { + return 0, err + } header := bc.GetHeaderByHash(blockHash) if header == nil { return 0, errors.New("unknown block hash") @@ -486,16 +489,16 @@ func (n NodeInterface) GasEstimateL1Component( func (n NodeInterface) GasEstimateComponents( c ctx, evm mech, value huge, to addr, contractCreation bool, data []byte, ) (uint64, uint64, huge, huge, error) { - node, err := arbNodeFromNodeInterfaceBackend(n.backend) - if err != nil { - return 0, 0, nil, nil, err - } if to == types.NodeInterfaceAddress || to == types.NodeInterfaceDebugAddress { return 0, 0, nil, nil, errors.New("cannot estimate virtual contract") } + backend, ok := n.backend.(*arbitrum.APIBackend) + if !ok { + return 0, 0, nil, nil, errors.New("failed getting API backend") + } + context := n.context - backend := node.Execution.Backend.APIBackend() gasCap := backend.RPCGasCap() block := rpc.BlockNumberOrHashWithHash(n.header.Hash(), false) args := n.messageArgs(evm, value, to, contractCreation, data) diff --git a/nodeInterface/virtual-contracts.go b/nodeInterface/virtual-contracts.go index 3e7d78e66..50eb1f47b 100644 --- a/nodeInterface/virtual-contracts.go +++ b/nodeInterface/virtual-contracts.go @@ -181,3 +181,15 @@ func arbNodeFromNodeInterfaceBackend(backend BackendAPI) (*arbnode.Node, error) } return arbNode, nil } + +func blockchainFromNodeInterfaceBackend(backend BackendAPI) (*core.BlockChain, error) { + apiBackend, ok := backend.(*arbitrum.APIBackend) + if !ok { + return nil, errors.New("API backend isn't Arbitrum") + } + bc := apiBackend.BlockChain() + if bc == nil { + return nil, errors.New("failed to get Blockchain from backend") + } + return bc, nil +} diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index 2976b6b17..9ad3f3629 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -9,7 +9,7 @@ import ( "sync" "testing" - "github.com/offchainlabs/nitro/arbnode/execution" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/util/signature" "github.com/offchainlabs/nitro/validator/server_api" @@ -31,7 +31,7 @@ type StatelessBlockValidator struct { execSpawner validator.ExecutionSpawner validationSpawners []validator.ValidationSpawner - recorder BlockRecorder + recorder execution.ExecutionRecorder inboxReader InboxReaderInterface inboxTracker InboxTrackerInterface @@ -48,16 +48,6 @@ type BlockValidatorRegistrer interface { SetBlockValidator(*BlockValidator) } -type BlockRecorder interface { - RecordBlockCreation( - ctx context.Context, - pos arbutil.MessageIndex, - msg *arbostypes.MessageWithMetadata, - ) (*execution.RecordResult, error) - MarkValid(pos arbutil.MessageIndex, resultHash common.Hash) - PrepareForRecord(ctx context.Context, start, end arbutil.MessageIndex) error -} - type InboxTrackerInterface interface { BlockValidatorRegistrer GetDelayedMessageBytes(uint64) ([]byte, error) @@ -229,7 +219,7 @@ func NewStatelessBlockValidator( inboxReader InboxReaderInterface, inbox InboxTrackerInterface, streamer TransactionStreamerInterface, - recorder BlockRecorder, + recorder execution.ExecutionRecorder, arbdb ethdb.Database, das arbstate.DataAvailabilityReader, config *BlockValidatorConfig, @@ -434,7 +424,7 @@ func (v *StatelessBlockValidator) ValidateResult( return true, &entry.End, nil } -func (v *StatelessBlockValidator) OverrideRecorder(t *testing.T, recorder BlockRecorder) { +func (v *StatelessBlockValidator) OverrideRecorder(t *testing.T, recorder execution.ExecutionRecorder) { v.recorder = recorder } From 9b54f4954dc404e60bf750435cb869f5a1c63742 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 15 Mar 2023 10:48:48 +0200 Subject: [PATCH 002/775] move maintenance to gethclient --- arbnode/api.go | 4 +--- arbnode/maintenance.go | 15 ++++++++++++--- arbnode/node.go | 20 ++++++++------------ cmd/nitro/nitro.go | 3 +-- execution/gethclient/node.go | 4 ++++ execution/interface.go | 2 ++ 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/arbnode/api.go b/arbnode/api.go index 6c067329e..fe9b00ceb 100644 --- a/arbnode/api.go +++ b/arbnode/api.go @@ -7,7 +7,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/validator" @@ -23,8 +22,7 @@ func (a *BlockValidatorAPI) LatestValidatedMsgNum(ctx context.Context) (*staker. } type BlockValidatorDebugAPI struct { - val *staker.StatelessBlockValidator - blockchain *core.BlockChain + val *staker.StatelessBlockValidator } type ValidateBlockResult struct { diff --git a/arbnode/maintenance.go b/arbnode/maintenance.go index 1b059df48..339da45a3 100644 --- a/arbnode/maintenance.go +++ b/arbnode/maintenance.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/util/stopwaiter" flag "github.com/spf13/pflag" ) @@ -20,6 +21,7 @@ import ( type MaintenanceRunner struct { stopwaiter.StopWaiter + exec execution.FullExecutionClient config MaintenanceConfigFetcher seqCoordinator *SeqCoordinator dbs []ethdb.Database @@ -75,13 +77,14 @@ var DefaultMaintenanceConfig = MaintenanceConfig{ type MaintenanceConfigFetcher func() *MaintenanceConfig -func NewMaintenanceRunner(config MaintenanceConfigFetcher, seqCoordinator *SeqCoordinator, dbs []ethdb.Database) (*MaintenanceRunner, error) { +func NewMaintenanceRunner(config MaintenanceConfigFetcher, seqCoordinator *SeqCoordinator, dbs []ethdb.Database, exec execution.FullExecutionClient) (*MaintenanceRunner, error) { err := config().Validate() if err != nil { return nil, err } return &MaintenanceRunner{ config: config, + exec: exec, seqCoordinator: seqCoordinator, dbs: dbs, lastCheck: time.Now().UTC(), @@ -142,16 +145,22 @@ func (c *MaintenanceRunner) maybeRunMaintenance(ctx context.Context) time.Durati func (c *MaintenanceRunner) runMaintenance() { log.Info("compacting databases (this may take a while...)") results := make(chan error, len(c.dbs)) + expected := 0 for _, db := range c.dbs { + expected++ db := db go func() { results <- db.Compact(nil, nil) }() } - for range c.dbs { + expected++ + go func() { + results <- c.exec.Maintenance() + }() + for i := 0; i < expected; i++ { err := <-results if err != nil { - log.Warn("failed to compact database", "err", err) + log.Warn("maintenance error", "err", err) } } log.Info("done compacting databases") diff --git a/arbnode/node.go b/arbnode/node.go index b6c002a0e..f22b8ebdc 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -15,7 +15,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -31,6 +30,7 @@ import ( "github.com/offchainlabs/nitro/broadcaster" "github.com/offchainlabs/nitro/das" "github.com/offchainlabs/nitro/execution" + "github.com/offchainlabs/nitro/execution/gethclient" "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/challengegen" "github.com/offchainlabs/nitro/solgen/go/ospgen" @@ -594,10 +594,9 @@ func createNodeImpl( ctx context.Context, stack *node.Node, exec execution.FullExecutionClient, - chainDb ethdb.Database, arbDb ethdb.Database, configFetcher ConfigFetcher, - l2BlockChain *core.BlockChain, + l2Config *params.ChainConfig, l1client arbutil.L1Interface, deployInfo *RollupAddresses, txOpts *bind.TransactOpts, @@ -611,7 +610,6 @@ func createNodeImpl( return nil, err } - l2Config := l2BlockChain.Config() l2ChainId := l2Config.ChainID.Uint64() //TODO: @@ -672,8 +670,8 @@ func createNodeImpl( } else if config.Sequencer && (!config.Dangerous.NoCoordinator) { return nil, errors.New("sequencer must be enabled with coordinator, unless dangerous.no-coordinator set") } - dbs := []ethdb.Database{chainDb, arbDb} - maintenanceRunner, err := NewMaintenanceRunner(func() *MaintenanceConfig { return &configFetcher.Get().Maintenance }, coordinator, dbs) + dbs := []ethdb.Database{arbDb} + maintenanceRunner, err := NewMaintenanceRunner(func() *MaintenanceConfig { return &configFetcher.Get().Maintenance }, coordinator, dbs, exec) if err != nil { return nil, err } @@ -762,7 +760,7 @@ func createNodeImpl( } daReader = das.NewReaderPanicWrapper(daReader) } - } else if l2BlockChain.Config().ArbitrumChainParams.DataAvailabilityCommittee { + } else if l2Config.ArbitrumChainParams.DataAvailabilityCommittee { return nil, errors.New("a data availability service is required for this chain, but it was not configured") } @@ -912,17 +910,16 @@ func CreateNode( ctx context.Context, stack *node.Node, exec execution.FullExecutionClient, - chainDb ethdb.Database, arbDb ethdb.Database, configFetcher ConfigFetcher, - l2BlockChain *core.BlockChain, + l2Config *params.ChainConfig, l1client arbutil.L1Interface, deployInfo *RollupAddresses, txOpts *bind.TransactOpts, dataSigner signature.DataSignerFunc, fatalErrChan chan error, ) (*Node, error) { - currentNode, err := createNodeImpl(ctx, stack, exec, chainDb, arbDb, configFetcher, l2BlockChain, l1client, deployInfo, txOpts, dataSigner, fatalErrChan) + currentNode, err := createNodeImpl(ctx, stack, exec, arbDb, configFetcher, l2Config, l1client, deployInfo, txOpts, dataSigner, fatalErrChan) if err != nil { return nil, err } @@ -940,8 +937,7 @@ func CreateNode( Namespace: "arbvalidator", Version: "1.0", Service: &BlockValidatorDebugAPI{ - val: currentNode.StatelessBlockValidator, - blockchain: l2BlockChain, + val: currentNode.StatelessBlockValidator, }, Public: false, }) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index a2f1cff2b..11a4cbee0 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -456,10 +456,9 @@ func mainImpl() int { ctx, stack, execNode, - chainDb, arbDb, &NodeConfigFetcher{liveNodeConfig}, - l2BlockChain, + l2BlockChain.Config(), l1Client, &rollupAddrs, l1TransactionOpts, diff --git a/execution/gethclient/node.go b/execution/gethclient/node.go index 249fcfe25..a66920de2 100644 --- a/execution/gethclient/node.go +++ b/execution/gethclient/node.go @@ -331,3 +331,7 @@ func (n *ExecutionNode) SetTransactionStreamer(streamer execution.TransactionStr func (n *ExecutionNode) MessageIndexToBlockNumber(messageNum arbutil.MessageIndex) uint64 { return n.ExecEngine.MessageIndexToBlockNumber(messageNum) } + +func (n *ExecutionNode) Maintenance() error { + return n.ChainDB.Compact(nil, nil) +} diff --git a/execution/interface.go b/execution/interface.go index eb929274d..036f98f2b 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -61,6 +61,8 @@ type FullExecutionClient interface { ExecutionRecorder ExecutionSequencer + Maintenance() error + // TODO: only used to get safe/finalized block numbers MessageIndexToBlockNumber(messageNum arbutil.MessageIndex) uint64 } From 97ff2123b41b6d0ecc10d7b04ce5257b5ce71aa2 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 15 Mar 2023 11:01:28 +0200 Subject: [PATCH 003/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index c3e683a62..942746e4d 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit c3e683a62a256a7f3aed280778e94862f74de700 +Subproject commit 942746e4d6996ced8a5ce50f04a3d2c1c332c4f9 From 4a70e05a5bc5949c158f508b35dfd71b2df975eb Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 15 Mar 2023 14:41:25 +0200 Subject: [PATCH 004/775] improve execution-consensus separation --- arbnode/node.go | 24 ++++++++++++++++++++++-- arbnode/sync_monitor.go | 9 ++++++--- arbnode/transaction_streamer.go | 4 ++-- cmd/nitro/nitro.go | 1 - execution/gethclient/node.go | 20 ++++++++------------ execution/interface.go | 1 + 6 files changed, 39 insertions(+), 20 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index f22b8ebdc..6c1e4d535 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -521,7 +521,7 @@ func DangerousConfigAddOptions(prefix string, f *flag.FlagSet) { type Node struct { ArbDB ethdb.Database Stack *node.Node - Execution execution.ExecutionClient + Execution execution.FullExecutionClient L1Reader *headerreader.HeaderReader TxStreamer *TransactionStreamer DeployInfo *RollupAddresses @@ -949,11 +949,24 @@ func CreateNode( } func (n *Node) Start(ctx context.Context) error { - n.SyncMonitor.Initialize(n.InboxReader, n.TxStreamer, n.SeqCoordinator) + execClient, ok := n.Execution.(*gethclient.ExecutionNode) + if !ok { + execClient = nil + } + if execClient != nil { + execClient.Initialize(ctx, n, n.SyncMonitor) + } + n.SyncMonitor.Initialize(n.InboxReader, n.TxStreamer, n.SeqCoordinator, n.Execution) err := n.Stack.Start() if err != nil { return fmt.Errorf("error starting geth stack: %w", err) } + if execClient != nil { + err := execClient.Start(ctx) + if err != nil { + return fmt.Errorf("error starting exec client: %w", err) + } + } if n.InboxTracker != nil { err = n.InboxTracker.Initialize() if err != nil { @@ -1050,6 +1063,13 @@ func (n *Node) Start(ctx context.Context) error { } func (n *Node) StopAndWait() { + execClient, ok := n.Execution.(*gethclient.ExecutionNode) + if !ok { + execClient = nil + } + if execClient != nil { + execClient.StopAndWait() + } if n.MaintenanceRunner != nil && n.MaintenanceRunner.Started() { n.MaintenanceRunner.StopAndWait() } diff --git a/arbnode/sync_monitor.go b/arbnode/sync_monitor.go index 1afb41756..bd9b24529 100644 --- a/arbnode/sync_monitor.go +++ b/arbnode/sync_monitor.go @@ -6,6 +6,7 @@ import ( "sync/atomic" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/execution" flag "github.com/spf13/pflag" ) @@ -14,6 +15,7 @@ type SyncMonitor struct { inboxReader *InboxReader txStreamer *TransactionStreamer coordinator *SeqCoordinator + exec execution.FullExecutionClient initialized bool } @@ -41,10 +43,11 @@ func SyncMonitorConfigAddOptions(prefix string, f *flag.FlagSet) { f.Uint64(prefix+".coordinator-msg-lag", DefaultSyncMonitorConfig.CoordinatorMsgLag, "allowed lag between local and remote messages") } -func (s *SyncMonitor) Initialize(inboxReader *InboxReader, txStreamer *TransactionStreamer, coordinator *SeqCoordinator) { +func (s *SyncMonitor) Initialize(inboxReader *InboxReader, txStreamer *TransactionStreamer, coordinator *SeqCoordinator, exec execution.FullExecutionClient) { s.inboxReader = inboxReader s.txStreamer = txStreamer s.coordinator = coordinator + s.exec = exec s.initialized = true } @@ -148,7 +151,7 @@ func (s *SyncMonitor) SafeBlockNumber(ctx context.Context) (uint64, error) { if err != nil { return 0, err } - block := s.txStreamer.exec.MessageIndexToBlockNumber(msg - 1) + block := s.exec.MessageIndexToBlockNumber(msg - 1) return block, nil } @@ -160,7 +163,7 @@ func (s *SyncMonitor) FinalizedBlockNumber(ctx context.Context) (uint64, error) if err != nil { return 0, err } - block := s.txStreamer.exec.MessageIndexToBlockNumber(msg - 1) + block := s.exec.MessageIndexToBlockNumber(msg - 1) return block, nil } diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index f0228272b..6773f4d82 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -41,7 +41,7 @@ type TransactionStreamer struct { stopwaiter.StopWaiter chainConfig *params.ChainConfig - exec execution.FullExecutionClient + exec execution.ExecutionSequencer validator *staker.BlockValidator db ethdb.Database @@ -86,7 +86,7 @@ func TransactionStreamerConfigAddOptions(prefix string, f *flag.FlagSet) { func NewTransactionStreamer( db ethdb.Database, chainConfig *params.ChainConfig, - exec execution.FullExecutionClient, + exec execution.ExecutionSequencer, broadcastServer *broadcaster.Broadcaster, fatalErrChan chan<- error, config TransactionStreamerConfigFetcher, diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 11a4cbee0..9cef2136c 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -444,7 +444,6 @@ func mainImpl() int { chainDb, l2BlockChain, l1Client, - nil, // TODO func() *gethclient.Config { return &liveNodeConfig.get().Execution }, ) if err != nil { diff --git a/execution/gethclient/node.go b/execution/gethclient/node.go index a66920de2..598315544 100644 --- a/execution/gethclient/node.go +++ b/execution/gethclient/node.go @@ -89,14 +89,7 @@ var ConfigDefault = Config{ Caching: DefaultCachingConfig, } -func ConfigDefaultL1Test() *Config { - config := ConfigDefaultL1NonSequencerTest() - config.Sequencer = TestSequencerConfig - - return config -} - -func ConfigDefaultL1NonSequencerTest() *Config { +func ConfigDefaultNonSequencerTest() *Config { config := ConfigDefault config.Sequencer.Enable = false config.Forwarder = DefaultTestForwarderConfig @@ -104,7 +97,7 @@ func ConfigDefaultL1NonSequencerTest() *Config { return &config } -func ConfigDefaultL2Test() *Config { +func ConfigDefaultTest() *Config { config := ConfigDefault config.Sequencer = TestSequencerConfig @@ -129,7 +122,6 @@ func CreateExecutionNode( chainDB ethdb.Database, l2BlockChain *core.BlockChain, l1client arbutil.L1Interface, - syncMonitor arbitrum.SyncProgressBackend, configFetcher ConfigFetcher, ) (*ExecutionNode, error) { config := configFetcher() @@ -174,7 +166,7 @@ func CreateExecutionNode( LogCacheSize: config.RPC.FilterLogCacheSize, Timeout: config.RPC.FilterTimeout, } - backend, filterSystem, err := arbitrum.NewBackend(stack, &config.RPC, chainDB, arbInterface, syncMonitor, filterConfig) + backend, filterSystem, err := arbitrum.NewBackend(stack, &config.RPC, chainDB, arbInterface, filterConfig) if err != nil { return nil, err } @@ -225,7 +217,7 @@ func CreateExecutionNode( } -func (n *ExecutionNode) Initialize(ctx context.Context, arbnode interface{}) error { +func (n *ExecutionNode) Initialize(ctx context.Context, arbnode interface{}, sync arbitrum.SyncProgressBackend) error { n.ArbInterface.Initialize(n) err := n.Backend.Start() if err != nil { @@ -235,6 +227,10 @@ func (n *ExecutionNode) Initialize(ctx context.Context, arbnode interface{}) err if err != nil { return fmt.Errorf("error initializing transaction publisher: %w", err) } + err = n.Backend.APIBackend().SetSyncBackend(sync) + if err != nil { + return fmt.Errorf("error setting sync backend: %w", err) + } return nil } diff --git a/execution/interface.go b/execution/interface.go index 036f98f2b..dc1551d8c 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -50,6 +50,7 @@ type ExecutionRecorder interface { // needed for sequencer type ExecutionSequencer interface { + ExecutionClient Pause() Activate() ForwardTo(url string) error From 444cef110cedf181c66da3ebf5f061877f2fed84 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 15 Mar 2023 14:44:42 +0200 Subject: [PATCH 005/775] rename gethclient to gethexec --- arbnode/node.go | 6 +++--- cmd/nitro/init.go | 12 ++++++------ cmd/nitro/nitro.go | 10 +++++----- execution/{gethclient => gethexec}/api.go | 2 +- execution/{gethclient => gethexec}/arb_interface.go | 2 +- execution/{gethclient => gethexec}/block_recorder.go | 2 +- execution/{gethclient => gethexec}/blockchain.go | 2 +- .../{gethclient => gethexec}/executionengine.go | 2 +- execution/{gethclient => gethexec}/forwarder.go | 2 +- execution/{gethclient => gethexec}/node.go | 2 +- execution/{gethclient => gethexec}/sequencer.go | 2 +- execution/{gethclient => gethexec}/tx_pre_checker.go | 2 +- 12 files changed, 23 insertions(+), 23 deletions(-) rename execution/{gethclient => gethexec}/api.go (99%) rename execution/{gethclient => gethexec}/arb_interface.go (98%) rename execution/{gethclient => gethexec}/block_recorder.go (99%) rename execution/{gethclient => gethexec}/blockchain.go (99%) rename execution/{gethclient => gethexec}/executionengine.go (99%) rename execution/{gethclient => gethexec}/forwarder.go (99%) rename execution/{gethclient => gethexec}/node.go (99%) rename execution/{gethclient => gethexec}/sequencer.go (99%) rename execution/{gethclient => gethexec}/tx_pre_checker.go (99%) diff --git a/arbnode/node.go b/arbnode/node.go index 6c1e4d535..f7dad45e4 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -30,7 +30,7 @@ import ( "github.com/offchainlabs/nitro/broadcaster" "github.com/offchainlabs/nitro/das" "github.com/offchainlabs/nitro/execution" - "github.com/offchainlabs/nitro/execution/gethclient" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/challengegen" "github.com/offchainlabs/nitro/solgen/go/ospgen" @@ -949,7 +949,7 @@ func CreateNode( } func (n *Node) Start(ctx context.Context) error { - execClient, ok := n.Execution.(*gethclient.ExecutionNode) + execClient, ok := n.Execution.(*gethexec.ExecutionNode) if !ok { execClient = nil } @@ -1063,7 +1063,7 @@ func (n *Node) Start(ctx context.Context) error { } func (n *Node) StopAndWait() { - execClient, ok := n.Execution.(*gethclient.ExecutionNode) + execClient, ok := n.Execution.(*gethexec.ExecutionNode) if !ok { execClient = nil } diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index c4d13c861..b54c96935 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -26,7 +26,7 @@ import ( "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/arbos/arbosState" "github.com/offchainlabs/nitro/cmd/ipfshelper" - "github.com/offchainlabs/nitro/execution/gethclient" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/statetransfer" "github.com/pkg/errors" flag "github.com/spf13/pflag" @@ -176,13 +176,13 @@ func validateBlockChain(blockChain *core.BlockChain, expectedChainId *big.Int) e func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeConfig, chainId *big.Int, cacheConfig *core.CacheConfig) (ethdb.Database, *core.BlockChain, error) { if !config.Init.Force { if readOnlyDb, err := stack.OpenDatabaseWithFreezer("l2chaindata", 0, 0, "", "", true); err == nil { - if chainConfig := gethclient.TryReadStoredChainConfig(readOnlyDb); chainConfig != nil { + if chainConfig := gethexec.TryReadStoredChainConfig(readOnlyDb); chainConfig != nil { readOnlyDb.Close() chainDb, err := stack.OpenDatabaseWithFreezer("l2chaindata", config.Execution.Caching.DatabaseCache, config.Persistent.Handles, "", "", false) if err != nil { return chainDb, nil, err } - l2BlockChain, err := gethclient.GetBlockChain(chainDb, cacheConfig, chainConfig, config.Execution.TxLookupLimit) + l2BlockChain, err := gethexec.GetBlockChain(chainDb, cacheConfig, chainConfig, config.Execution.TxLookupLimit) if err != nil { return chainDb, nil, err } @@ -261,11 +261,11 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo var l2BlockChain *core.BlockChain txIndexWg := sync.WaitGroup{} if initDataReader == nil { - chainConfig = gethclient.TryReadStoredChainConfig(chainDb) + chainConfig = gethexec.TryReadStoredChainConfig(chainDb) if chainConfig == nil { return chainDb, nil, errors.New("no --init.* mode supplied and chain data not in expected directory") } - l2BlockChain, err = gethclient.GetBlockChain(chainDb, cacheConfig, chainConfig, config.Execution.TxLookupLimit) + l2BlockChain, err = gethexec.GetBlockChain(chainDb, cacheConfig, chainConfig, config.Execution.TxLookupLimit) if err != nil { return chainDb, nil, err } @@ -307,7 +307,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if config.Init.ThenQuit { cacheConfig.SnapshotWait = true } - l2BlockChain, err = gethclient.WriteOrTestBlockChain(chainDb, cacheConfig, initDataReader, chainConfig, config.Execution.TxLookupLimit, config.Init.AccountsPerSync) + l2BlockChain, err = gethexec.WriteOrTestBlockChain(chainDb, cacheConfig, initDataReader, chainConfig, config.Execution.TxLookupLimit, config.Init.AccountsPerSync) if err != nil { return chainDb, nil, err } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 9cef2136c..14d3f88ba 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -49,7 +49,7 @@ import ( "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/cmd/util" "github.com/offchainlabs/nitro/cmd/util/confighelpers" - "github.com/offchainlabs/nitro/execution/gethclient" + "github.com/offchainlabs/nitro/execution/gethexec" _ "github.com/offchainlabs/nitro/nodeInterface" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/colors" @@ -381,7 +381,7 @@ func mainImpl() int { } } - chainDb, l2BlockChain, err := openInitializeChainDb(ctx, stack, nodeConfig, new(big.Int).SetUint64(nodeConfig.L2.ChainID), gethclient.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching)) + chainDb, l2BlockChain, err := openInitializeChainDb(ctx, stack, nodeConfig, new(big.Int).SetUint64(nodeConfig.L2.ChainID), gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching)) defer closeDb(chainDb, "chainDb") if l2BlockChain != nil { // Calling Stop on the blockchain multiple times does nothing @@ -439,12 +439,12 @@ func mainImpl() int { log.Warn("couldn't init validation node", "err", err) } - execNode, err := gethclient.CreateExecutionNode( + execNode, err := gethexec.CreateExecutionNode( stack, chainDb, l2BlockChain, l1Client, - func() *gethclient.Config { return &liveNodeConfig.get().Execution }, + func() *gethexec.Config { return &liveNodeConfig.get().Execution }, ) if err != nil { log.Error("failed to create execution node", "err", err) @@ -532,7 +532,7 @@ func mainImpl() int { type NodeConfig struct { Conf genericconf.ConfConfig `koanf:"conf" reload:"hot"` Node arbnode.Config `koanf:"node" reload:"hot"` - Execution gethclient.Config `koanf:"exec" reload:"hot"` + Execution gethexec.Config `koanf:"exec" reload:"hot"` Validation valnode.Config `koanf:"validation" reload:"hot"` L1 conf.L1Config `koanf:"l1"` L2 conf.L2Config `koanf:"l2"` diff --git a/execution/gethclient/api.go b/execution/gethexec/api.go similarity index 99% rename from execution/gethclient/api.go rename to execution/gethexec/api.go index d7f686baf..fa8780a38 100644 --- a/execution/gethclient/api.go +++ b/execution/gethexec/api.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package gethclient +package gethexec import ( "context" diff --git a/execution/gethclient/arb_interface.go b/execution/gethexec/arb_interface.go similarity index 98% rename from execution/gethclient/arb_interface.go rename to execution/gethexec/arb_interface.go index 7585e2974..049dc4e24 100644 --- a/execution/gethclient/arb_interface.go +++ b/execution/gethexec/arb_interface.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package gethclient +package gethexec import ( "context" diff --git a/execution/gethclient/block_recorder.go b/execution/gethexec/block_recorder.go similarity index 99% rename from execution/gethclient/block_recorder.go rename to execution/gethexec/block_recorder.go index c59d484ef..745dc0d2f 100644 --- a/execution/gethclient/block_recorder.go +++ b/execution/gethexec/block_recorder.go @@ -1,4 +1,4 @@ -package gethclient +package gethexec import ( "context" diff --git a/execution/gethclient/blockchain.go b/execution/gethexec/blockchain.go similarity index 99% rename from execution/gethclient/blockchain.go rename to execution/gethexec/blockchain.go index 2a953c5db..9086ef10b 100644 --- a/execution/gethclient/blockchain.go +++ b/execution/gethexec/blockchain.go @@ -1,4 +1,4 @@ -package gethclient +package gethexec import ( "errors" diff --git a/execution/gethclient/executionengine.go b/execution/gethexec/executionengine.go similarity index 99% rename from execution/gethclient/executionengine.go rename to execution/gethexec/executionengine.go index 060d0cbb4..07a54d075 100644 --- a/execution/gethclient/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -1,4 +1,4 @@ -package gethclient +package gethexec import ( "context" diff --git a/execution/gethclient/forwarder.go b/execution/gethexec/forwarder.go similarity index 99% rename from execution/gethclient/forwarder.go rename to execution/gethexec/forwarder.go index 60dd4f4d8..e4e5686b3 100644 --- a/execution/gethclient/forwarder.go +++ b/execution/gethexec/forwarder.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package gethclient +package gethexec import ( "context" diff --git a/execution/gethclient/node.go b/execution/gethexec/node.go similarity index 99% rename from execution/gethclient/node.go rename to execution/gethexec/node.go index 598315544..06801bfb4 100644 --- a/execution/gethclient/node.go +++ b/execution/gethexec/node.go @@ -1,4 +1,4 @@ -package gethclient +package gethexec import ( "context" diff --git a/execution/gethclient/sequencer.go b/execution/gethexec/sequencer.go similarity index 99% rename from execution/gethclient/sequencer.go rename to execution/gethexec/sequencer.go index ddc70ac2b..e8333e544 100644 --- a/execution/gethclient/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package gethclient +package gethexec import ( "context" diff --git a/execution/gethclient/tx_pre_checker.go b/execution/gethexec/tx_pre_checker.go similarity index 99% rename from execution/gethclient/tx_pre_checker.go rename to execution/gethexec/tx_pre_checker.go index 3c991343d..2e92144d7 100644 --- a/execution/gethclient/tx_pre_checker.go +++ b/execution/gethexec/tx_pre_checker.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package gethclient +package gethexec import ( "context" From 8f6ef39321ccfc4f124ccb0ba171f98d8d1ba7e4 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 15 Mar 2023 17:27:31 +0200 Subject: [PATCH 006/775] execnode: small fixes --- arbnode/inbox_test.go | 21 +++++++++++++++------ arbnode/node.go | 5 ++++- execution/gethexec/node.go | 23 ++++++++++++++--------- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 037bbc294..2daa60161 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -14,8 +14,7 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbutil" - "github.com/offchainlabs/nitro/execution" - "github.com/offchainlabs/nitro/execution/gethclient" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/statetransfer" nitroutil "github.com/offchainlabs/nitro/util" @@ -30,7 +29,16 @@ import ( "github.com/offchainlabs/nitro/arbos" ) -func NewTransactionStreamerForTest(t *testing.T, ownerAddress common.Address) (*execution.ExecutionEngine, *TransactionStreamer, ethdb.Database, *core.BlockChain) { +type execClientWrapper struct { + *gethexec.ExecutionEngine + t *testing.T +} + +func (w *execClientWrapper) Pause() { w.t.Error("not supported") } +func (w *execClientWrapper) Activate() { w.t.Error("not supported") } +func (w *execClientWrapper) ForwardTo(url string) error { w.t.Error("not supported"); return nil } + +func NewTransactionStreamerForTest(t *testing.T, ownerAddress common.Address) (*gethexec.ExecutionEngine, *TransactionStreamer, ethdb.Database, *core.BlockChain) { chainConfig := params.ArbitrumDevTestChainConfig() initData := statetransfer.ArbosInitializationInfo{ @@ -46,18 +54,19 @@ func NewTransactionStreamerForTest(t *testing.T, ownerAddress common.Address) (* arbDb := rawdb.NewMemoryDatabase() initReader := statetransfer.NewMemoryInitDataReader(&initData) - bc, err := gethclient.WriteOrTestBlockChain(chainDb, nil, initReader, chainConfig, ConfigDefaultL2Test().TxLookupLimit, 0) + bc, err := gethexec.WriteOrTestBlockChain(chainDb, nil, initReader, chainConfig, gethexec.ConfigDefaultTest().TxLookupLimit, 0) if err != nil { Fail(t, err) } transactionStreamerConfigFetcher := func() *TransactionStreamerConfig { return &DefaultTransactionStreamerConfig } - execEngine, err := execution.NewExecutionEngine(bc) + execEngine, err := gethexec.NewExecutionEngine(bc) if err != nil { Fail(t, err) } - inbox, err := NewTransactionStreamer(arbDb, bc.Config(), execEngine, nil, make(chan error, 1), transactionStreamerConfigFetcher) + execSeq := &execClientWrapper{execEngine, t} + inbox, err := NewTransactionStreamer(arbDb, bc.Config(), execSeq, nil, make(chan error, 1), transactionStreamerConfigFetcher) if err != nil { Fail(t, err) } diff --git a/arbnode/node.go b/arbnode/node.go index f7dad45e4..822cbcbcc 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -954,7 +954,10 @@ func (n *Node) Start(ctx context.Context) error { execClient = nil } if execClient != nil { - execClient.Initialize(ctx, n, n.SyncMonitor) + err := execClient.Initialize(ctx, n, n.SyncMonitor) + if err != nil { + return fmt.Errorf("error initializing exec client: %w", err) + } } n.SyncMonitor.Initialize(n.InboxReader, n.TxStreamer, n.SeqCoordinator, n.Execution) err := n.Stack.Start() diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 06801bfb4..3d292730d 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -107,14 +107,15 @@ func ConfigDefaultTest() *Config { type ConfigFetcher func() *Config type ExecutionNode struct { - ChainDB ethdb.Database - Backend *arbitrum.Backend - FilterSystem *filters.FilterSystem - ArbInterface *ArbInterface - ExecEngine *ExecutionEngine - Recorder *BlockRecorder - Sequencer *Sequencer // either nil or same as TxPublisher - TxPublisher TransactionPublisher + ChainDB ethdb.Database + Backend *arbitrum.Backend + FilterSystem *filters.FilterSystem + ArbInterface *ArbInterface + ExecEngine *ExecutionEngine + Recorder *BlockRecorder + Sequencer *Sequencer // either nil or same as TxPublisher + TxPublisher TransactionPublisher + ConfigFetcher ConfigFetcher } func CreateExecutionNode( @@ -133,7 +134,10 @@ func CreateExecutionNode( var txPublisher TransactionPublisher var sequencer *Sequencer - l1Reader := headerreader.New(l1client, func() *headerreader.Config { return &configFetcher().L1Reader }) + var l1Reader *headerreader.HeaderReader + if l1client != nil { + l1Reader = headerreader.New(l1client, func() *headerreader.Config { return &configFetcher().L1Reader }) + } fwTarget := config.ForwardingTarget() if config.Sequencer.Enable { @@ -213,6 +217,7 @@ func CreateExecutionNode( recorder, sequencer, txPublisher, + configFetcher, }, nil } From bb797fd11d7a394782414181c237ac23b15e0e0c Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 15 Mar 2023 17:27:51 +0200 Subject: [PATCH 007/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 942746e4d..dcb407568 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 942746e4d6996ced8a5ce50f04a3d2c1c332c4f9 +Subproject commit dcb407568c3641278ce496c2576205719acf19c9 From caa4823cbe918a3670a331f84acd69ee95399a44 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 15 Mar 2023 17:29:42 +0200 Subject: [PATCH 008/775] execution service - fix tests --- cmd/nitro/config_test.go | 29 +++++----- cmd/nitro/nitro.go | 11 ++-- cmd/util/confighelpers/configuration.go | 2 +- execution/gethexec/node.go | 2 +- system_tests/arbtrace_test.go | 10 ++-- system_tests/batch_poster_test.go | 7 ++- system_tests/block_validator_test.go | 13 +++-- system_tests/bloom_test.go | 14 ++--- system_tests/common_test.go | 71 +++++++++++++++++++----- system_tests/contract_tx_test.go | 4 +- system_tests/das_test.go | 25 ++++++--- system_tests/debugapi_test.go | 2 +- system_tests/estimation_test.go | 3 +- system_tests/fees_test.go | 5 +- system_tests/forwarder_test.go | 30 +++++----- system_tests/full_challenge_impl_test.go | 21 ++++--- system_tests/infra_fee_test.go | 4 +- system_tests/initialization_test.go | 3 +- system_tests/ipc_test.go | 2 +- system_tests/meaningless_reorg_test.go | 5 +- system_tests/reorg_resequencing_test.go | 8 ++- system_tests/seq_coordinator_test.go | 2 +- system_tests/seq_nonce_test.go | 14 ++--- system_tests/seq_pause_test.go | 7 ++- system_tests/seq_reject_test.go | 4 +- system_tests/seq_whitelist_test.go | 6 +- system_tests/seqfeed_test.go | 29 ++++++---- system_tests/seqinbox_test.go | 7 ++- system_tests/staker_test.go | 13 +++-- system_tests/twonodes_test.go | 2 +- system_tests/twonodeslong_test.go | 2 +- system_tests/validation_mock_test.go | 2 +- testnode-scripts/config.ts | 12 ++-- 33 files changed, 229 insertions(+), 142 deletions(-) diff --git a/cmd/nitro/config_test.go b/cmd/nitro/config_test.go index c1ef5b3a8..47f74fe23 100644 --- a/cmd/nitro/config_test.go +++ b/cmd/nitro/config_test.go @@ -19,25 +19,25 @@ import ( ) func TestSeqConfig(t *testing.T) { - args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.l1-reader.enable=false --l1.chain-id 5 --l2.chain-id 421613 --l1.wallet.pathname /l1keystore --l1.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.sequencer.enable --node.feed.output.enable --node.feed.output.port 9642", " ") + args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.l1-reader.enable=false --l1.chain-id 5 --l2.chain-id 421613 --l1.wallet.pathname /l1keystore --l1.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.sequencer --execution.sequencer.enable --node.feed.output.enable --node.feed.output.port 9642", " ") _, _, _, _, _, err := ParseNode(context.Background(), args) Require(t, err) } func TestUnsafeStakerConfig(t *testing.T) { - args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.l1-reader.enable=false --l1.chain-id 5 --l2.chain-id 421613 --l1.wallet.pathname /l1keystore --l1.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.staker.enable --node.staker.strategy MakeNodes --node.staker.staker-interval 10s --node.forwarding-target null --node.staker.dangerous.without-block-validator", " ") + args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.l1-reader.enable=false --l1.chain-id 5 --l2.chain-id 421613 --l1.wallet.pathname /l1keystore --l1.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.staker.enable --node.staker.strategy MakeNodes --node.staker.staker-interval 10s --execution.forwarding-target null --node.staker.dangerous.without-block-validator", " ") _, _, _, _, _, err := ParseNode(context.Background(), args) Require(t, err) } func TestValidatorConfig(t *testing.T) { - args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.l1-reader.enable=false --l1.chain-id 5 --l2.chain-id 421613 --l1.wallet.pathname /l1keystore --l1.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.staker.enable --node.staker.strategy MakeNodes --node.staker.staker-interval 10s --node.forwarding-target null", " ") + args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.l1-reader.enable=false --l1.chain-id 5 --l2.chain-id 421613 --l1.wallet.pathname /l1keystore --l1.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.staker.enable --node.staker.strategy MakeNodes --node.staker.staker-interval 10s --execution.forwarding-target null", " ") _, _, _, _, _, err := ParseNode(context.Background(), args) Require(t, err) } func TestAggregatorConfig(t *testing.T) { - args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.l1-reader.enable=false --l1.chain-id 5 --l2.chain-id 421613 --l1.wallet.pathname /l1keystore --l1.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.sequencer.enable --node.feed.output.enable --node.feed.output.port 9642 --node.data-availability.enable --node.data-availability.rpc-aggregator.backends {[\"url\":\"http://localhost:8547\",\"pubkey\":\"abc==\",\"signerMask\":0x1]}", " ") + args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.l1-reader.enable=false --l1.chain-id 5 --l2.chain-id 421613 --l1.wallet.pathname /l1keystore --l1.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.sequencer --execution.sequencer.enable --node.feed.output.enable --node.feed.output.port 9642 --node.data-availability.enable --node.data-availability.rpc-aggregator.backends {[\"url\":\"http://localhost:8547\",\"pubkey\":\"abc==\",\"signerMask\":0x1]}", " ") _, _, _, _, _, err := ParseNode(context.Background(), args) Require(t, err) } @@ -68,13 +68,14 @@ func TestReloads(t *testing.T) { config := NodeConfigDefault update := NodeConfigDefault - update.Node.Sequencer.MaxBlockSpeed++ + update.Node.BatchPoster.BatchPollDelay++ check(reflect.ValueOf(config), false, "config") Require(t, config.CanReload(&config)) Require(t, config.CanReload(&update)) testUnsafe := func() { + t.Helper() if config.CanReload(&update) == nil { Fail(t, "failed to detect unsafe reload") } @@ -86,7 +87,7 @@ func TestReloads(t *testing.T) { testUnsafe() update.L2.ChainID++ testUnsafe() - update.Node.Sequencer.Forwarder.ConnectionTimeout++ + update.Node.Staker.Enable = !update.Node.Staker.Enable testUnsafe() } @@ -99,7 +100,7 @@ func TestLiveNodeConfig(t *testing.T) { jsonConfig := "{\"l2\":{\"chain-id\":421613}}" Require(t, WriteToConfigFile(configFile, jsonConfig)) - args := strings.Split("--file-logging.enable=false --persistent.chain /tmp/data --init.dev-init --node.l1-reader.enable=false --l1.chain-id 5 --l1.wallet.pathname /l1keystore --l1.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.sequencer.enable --node.feed.output.enable --node.feed.output.port 9642", " ") + args := strings.Split("--file-logging.enable=false --persistent.chain /tmp/data --init.dev-init --node.l1-reader.enable=false --l1.chain-id 5 --l1.wallet.pathname /l1keystore --l1.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.sequencer --execution.sequencer.enable --node.feed.output.enable --node.feed.output.port 9642", " ") args = append(args, []string{"--conf.file", configFile}...) config, _, _, _, _, err := ParseNode(context.Background(), args) Require(t, err) @@ -109,8 +110,8 @@ func TestLiveNodeConfig(t *testing.T) { // check updating the config update := config.ShallowClone() expected := config.ShallowClone() - update.Node.Sequencer.MaxBlockSpeed += 2 * time.Millisecond - expected.Node.Sequencer.MaxBlockSpeed += 2 * time.Millisecond + update.Node.BatchPoster.BatchPollDelay += 2 * time.Millisecond + expected.Node.BatchPoster.BatchPollDelay += 2 * time.Millisecond Require(t, liveConfig.set(update)) if !reflect.DeepEqual(liveConfig.get(), expected) { Fail(t, "failed to set config") @@ -145,19 +146,19 @@ func TestLiveNodeConfig(t *testing.T) { // change the config file expected = config.ShallowClone() - expected.Node.Sequencer.MaxBlockSpeed += time.Millisecond - jsonConfig = fmt.Sprintf("{\"node\":{\"sequencer\":{\"max-block-speed\":\"%s\"}}, \"l2\":{\"chain-id\":421613}}", expected.Node.Sequencer.MaxBlockSpeed.String()) + expected.Node.BatchPoster.BatchPollDelay += time.Millisecond + jsonConfig = fmt.Sprintf("{\"node\":{\"batch-poster\":{\"poll-delay\":\"%s\"}}, \"l2\":{\"chain-id\":421613}}", expected.Node.BatchPoster.BatchPollDelay.String()) Require(t, WriteToConfigFile(configFile, jsonConfig)) // trigger LiveConfig reload Require(t, syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)) if !PollLiveConfigUntilEqual(liveConfig, expected) { - Fail(t, "failed to update config", config.Node.Sequencer.MaxBlockSpeed, update.Node.Sequencer.MaxBlockSpeed) + Fail(t, "failed to update config", config.Node.BatchPoster.BatchPollDelay, update.Node.BatchPoster.BatchPollDelay) } // change l2.chain-id in the config file (currently non-reloadable) - jsonConfig = fmt.Sprintf("{\"node\":{\"sequencer\":{\"max-block-speed\":\"%s\"}}, \"l2\":{\"chain-id\":421703}}", expected.Node.Sequencer.MaxBlockSpeed.String()) + jsonConfig = fmt.Sprintf("{\"node\":{\"batch-poster\":{\"poll-delay\":\"%s\"}}, \"l2\":{\"chain-id\":421703}}", expected.Node.BatchPoster.BatchPollDelay.String()) Require(t, WriteToConfigFile(configFile, jsonConfig)) // trigger LiveConfig reload @@ -177,7 +178,7 @@ func TestPeriodicReloadOfLiveNodeConfig(t *testing.T) { jsonConfig := "{\"conf\":{\"reload-interval\":\"20ms\"}}" Require(t, WriteToConfigFile(configFile, jsonConfig)) - args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.l1-reader.enable=false --l1.chain-id 5 --l2.chain-id 421613 --l1.wallet.pathname /l1keystore --l1.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.sequencer.enable --node.feed.output.enable --node.feed.output.port 9642", " ") + args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.l1-reader.enable=false --l1.chain-id 5 --l2.chain-id 421613 --l1.wallet.pathname /l1keystore --l1.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.sequencer --execution.sequencer.enable --node.feed.output.enable --node.feed.output.port 9642", " ") args = append(args, []string{"--conf.file", configFile}...) config, _, _, _, _, err := ParseNode(context.Background(), args) Require(t, err) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 14d3f88ba..ec827c61d 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -532,7 +532,7 @@ func mainImpl() int { type NodeConfig struct { Conf genericconf.ConfConfig `koanf:"conf" reload:"hot"` Node arbnode.Config `koanf:"node" reload:"hot"` - Execution gethexec.Config `koanf:"exec" reload:"hot"` + Execution gethexec.Config `koanf:"execution" reload:"hot"` Validation valnode.Config `koanf:"validation" reload:"hot"` L1 conf.L1Config `koanf:"l1"` L2 conf.L2Config `koanf:"l2"` @@ -568,6 +568,7 @@ var NodeConfigDefault = NodeConfig{ func NodeConfigAddOptions(f *flag.FlagSet) { genericconf.ConfConfigAddOptions("conf", f) arbnode.ConfigAddOptions("node", f, true, true) + gethexec.ConfigAddOptions("execution", f) valnode.ValidationConfigAddOptions("validation", f) conf.L1ConfigAddOptions("l1", f) conf.L2ConfigAddOptions("l2", f) @@ -822,7 +823,7 @@ func ParseNode(ctx context.Context, args []string) (*NodeConfig, *genericconf.Wa func applyArbitrumOneParameters(k *koanf.Koanf) error { return k.Load(confmap.Provider(map[string]interface{}{ "persistent.chain": "arb1", - "node.forwarding-target": "https://arb1.arbitrum.io/rpc", + "execution.forwarding-target": "https://arb1.arbitrum.io/rpc", "node.feed.input.url": "wss://arb1.arbitrum.io/feed", "l1.rollup.bridge": "0x8315177ab297ba92a06054ce80a67ed4dbd7ed3a", "l1.rollup.inbox": "0x4dbd4fc535ac27206064b68ffcf827b0a60bab3f", @@ -838,7 +839,7 @@ func applyArbitrumOneParameters(k *koanf.Koanf) error { func applyArbitrumNovaParameters(k *koanf.Koanf) error { return k.Load(confmap.Provider(map[string]interface{}{ "persistent.chain": "nova", - "node.forwarding-target": "https://nova.arbitrum.io/rpc", + "execution.forwarding-target": "https://nova.arbitrum.io/rpc", "node.feed.input.url": "wss://nova.arbitrum.io/feed", "node.data-availability.enable": true, "node.data-availability.rest-aggregator.enable": true, @@ -858,7 +859,7 @@ func applyArbitrumNovaParameters(k *koanf.Koanf) error { func applyArbitrumRollupGoerliTestnetParameters(k *koanf.Koanf) error { return k.Load(confmap.Provider(map[string]interface{}{ "persistent.chain": "goerli-rollup", - "node.forwarding-target": "https://goerli-rollup.arbitrum.io/rpc", + "execution.forwarding-target": "https://goerli-rollup.arbitrum.io/rpc", "node.feed.input.url": "wss://goerli-rollup.arbitrum.io/feed", "l1.rollup.bridge": "0xaf4159a80b6cc41ed517db1c453d1ef5c2e4db72", "l1.rollup.inbox": "0x6bebc4925716945d46f0ec336d5c2564f419682c", @@ -875,7 +876,7 @@ func applyArbitrumRollupGoerliTestnetParameters(k *koanf.Koanf) error { func applyArbitrumRollupRinkebyTestnetParameters(k *koanf.Koanf) error { return k.Load(confmap.Provider(map[string]interface{}{ "persistent.chain": "rinkeby-nitro", - "node.forwarding-target": "https://rinkeby.arbitrum.io/rpc", + "execution.forwarding-target": "https://rinkeby.arbitrum.io/rpc", "node.feed.input.url": "wss://rinkeby.arbitrum.io/feed", "l1.rollup.bridge": "0x85c720444e436e1f9407e0c3895d3fe149f41168", "l1.rollup.inbox": "0x578BAde599406A8fE3d24Fd7f7211c0911F5B29e", diff --git a/cmd/util/confighelpers/configuration.go b/cmd/util/confighelpers/configuration.go index b86016505..179a6503f 100644 --- a/cmd/util/confighelpers/configuration.go +++ b/cmd/util/confighelpers/configuration.go @@ -150,7 +150,7 @@ func BeginCommonParse(f *flag.FlagSet, args []string) (*koanf.Koanf, error) { if f.NArg() != 0 { // Unexpected number of parameters - return nil, errors.New("unexpected number of parameters") + return nil, fmt.Errorf("unexpected parameter: %s", f.Arg(0)) } var k = koanf.New(".") diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 3d292730d..8114f9c62 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -62,7 +62,7 @@ func (c *Config) Validate() error { return nil } -func ConfigAddOptions(prefix string, f *flag.FlagSet, feedInputEnable bool, feedOutputEnable bool) { +func ConfigAddOptions(prefix string, f *flag.FlagSet) { arbitrum.ConfigAddOptions(prefix+".rpc", f) SequencerConfigAddOptions(prefix+".sequencer", f) f.String(prefix+".forwarding-target", ConfigDefault.ForwardingTargetImpl, "transaction forwarding target URL, or \"null\" to disable forwarding (iff not sequencer)") diff --git a/system_tests/arbtrace_test.go b/system_tests/arbtrace_test.go index b877e85df..407589228 100644 --- a/system_tests/arbtrace_test.go +++ b/system_tests/arbtrace_test.go @@ -11,7 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" - "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/testhelpers" ) @@ -145,10 +145,10 @@ func TestArbTraceForwarding(t *testing.T) { defer srv.Stop() defer listener.Close() - nodeConfig := arbnode.ConfigDefaultL1Test() - nodeConfig.RPC.ClassicRedirect = ipcPath - nodeConfig.RPC.ClassicRedirectTimeout = time.Second - _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil) + execConfig := gethexec.ConfigDefaultTest() + execConfig.RPC.ClassicRedirect = ipcPath + execConfig.RPC.ClassicRedirectTimeout = time.Second + _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, execConfig, nil, nil) defer requireClose(t, l1stack) defer requireClose(t, l2stack) diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 1e5451cdc..884ef2f80 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/redisutil" ) @@ -35,7 +36,7 @@ func TestBatchPosterParallel(t *testing.T) { conf := arbnode.ConfigDefaultL1Test() conf.BatchPoster.Enable = false conf.BatchPoster.RedisUrl = redisUrl - l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil) + l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil, nil) defer requireClose(t, l1stack) defer nodeA.StopAndWait() @@ -127,9 +128,9 @@ func TestBatchPosterLargeTx(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - conf := arbnode.ConfigDefaultL1Test() + conf := gethexec.ConfigDefaultTest() conf.Sequencer.MaxTxDataSize = 110000 - l2info, nodeA, l2clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil) + l2info, nodeA, l2clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, conf, nil, nil) defer requireClose(t, l1stack) defer nodeA.StopAndWait() diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index a20e7992d..c394dff94 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -18,6 +18,7 @@ import ( "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/execution/gethexec" ) func testBlockValidatorSimple(t *testing.T, dasModeString string, simpletxloops int, expensiveTx bool, arbitrator bool) { @@ -34,7 +35,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, simpletxloops delayEvery = simpletxloops / 3 } - l2info, nodeA, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, chainConfig, nil) + l2info, nodeA, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, nil, chainConfig, nil) defer requireClose(t, l1stack) defer nodeA.StopAndWait() @@ -45,7 +46,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, simpletxloops validatorConfig.DataAvailability = l1NodeConfigA.DataAvailability validatorConfig.DataAvailability.AggregatorConfig.Enable = false AddDefaultValNode(t, ctx, validatorConfig, !arbitrator) - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, validatorConfig, nil) + l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, validatorConfig, nil, nil) defer nodeB.StopAndWait() l2info.GenerateAccount("User2") @@ -134,8 +135,12 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, simpletxloops if !nodeB.BlockValidator.WaitForPos(t, ctx, arbutil.MessageIndex(lastBlock.NumberU64()), timeout) { Fail(t, "did not validate all blocks") } - nodeB.Execution.Recorder.TrimAllPrepared(t) - finalRefCount := nodeB.Execution.Recorder.RecordingDBReferenceCount() + gethExec, ok := nodeB.Execution.(*gethexec.ExecutionNode) + if !ok { + t.Fail() + } + gethExec.Recorder.TrimAllPrepared(t) + finalRefCount := gethExec.Recorder.RecordingDBReferenceCount() lastBlockNow, err := l2clientB.BlockByNumber(ctx, nil) Require(t, err) // up to 3 extra references: awaiting validation, recently valid, lastValidatedHeader diff --git a/system_tests/bloom_test.go b/system_tests/bloom_test.go index c932e0f18..600a468cc 100644 --- a/system_tests/bloom_test.go +++ b/system_tests/bloom_test.go @@ -17,7 +17,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/solgen/go/mocksgen" ) @@ -25,10 +25,10 @@ func TestBloom(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - nodeconfig := arbnode.ConfigDefaultL2Test() - nodeconfig.RPC.BloomBitsBlocks = 256 - nodeconfig.RPC.BloomConfirms = 1 - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, false) + execconfig := gethexec.ConfigDefaultTest() + execconfig.RPC.BloomBitsBlocks = 256 + execconfig.RPC.BloomConfirms = 1 + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, execconfig, false) defer node.StopAndWait() l2info.GenerateAccount("User2") @@ -80,9 +80,9 @@ func TestBloom(t *testing.T) { t.Log("counts: ", i, "/", countsNum) } } - + execNode := getExecNode(t, node) for { - sectionSize, sectionNum := node.Execution.Backend.APIBackend().BloomStatus() + sectionSize, sectionNum := execNode.Backend.APIBackend().BloomStatus() if sectionSize != 256 { Fail(t, "unexpected section size: ", sectionSize) } diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 07ee38a23..dd16b2081 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -12,12 +12,12 @@ import ( "testing" "time" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/arbos/util" "github.com/offchainlabs/nitro/arbstate" "github.com/offchainlabs/nitro/blsSignatures" "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/das" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/signature" @@ -388,7 +388,7 @@ func createL2BlockChainWithStackConfig( Require(t, err) initReader := statetransfer.NewMemoryInitDataReader(&l2info.ArbInitData) - blockchain, err := execution.WriteOrTestBlockChain(chainDb, nil, initReader, chainConfig, arbnode.ConfigDefaultL2Test().TxLookupLimit, 0) + blockchain, err := gethexec.WriteOrTestBlockChain(chainDb, nil, initReader, chainConfig, gethexec.ConfigDefaultTest().TxLookupLimit, 0) Require(t, err) return l2info, stack, chainDb, arbDb, blockchain @@ -409,7 +409,7 @@ func createTestNodeOnL1( l2info info, node *arbnode.Node, l2client *ethclient.Client, l1info info, l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node, ) { - return createTestNodeOnL1WithConfig(t, ctx, isSequencer, nil, nil, nil) + return createTestNodeOnL1WithConfig(t, ctx, isSequencer, nil, nil, nil, nil) } func createTestNodeOnL1WithConfig( @@ -417,13 +417,14 @@ func createTestNodeOnL1WithConfig( ctx context.Context, isSequencer bool, nodeConfig *arbnode.Config, + execConfig *gethexec.Config, chainConfig *params.ChainConfig, stackConfig *node.Config, ) ( l2info info, currentNode *arbnode.Node, l2client *ethclient.Client, l1info info, l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node, ) { - l2info, currentNode, l2client, _, l1info, l1backend, l1client, l1stack = createTestNodeOnL1WithConfigImpl(t, ctx, isSequencer, nodeConfig, chainConfig, stackConfig) + l2info, currentNode, l2client, _, l1info, l1backend, l1client, l1stack = createTestNodeOnL1WithConfigImpl(t, ctx, isSequencer, nodeConfig, execConfig, chainConfig, stackConfig) return } @@ -432,6 +433,7 @@ func createTestNodeOnL1WithConfigImpl( ctx context.Context, isSequencer bool, nodeConfig *arbnode.Config, + execConfig *gethexec.Config, chainConfig *params.ChainConfig, stackConfig *node.Config, ) ( @@ -441,6 +443,9 @@ func createTestNodeOnL1WithConfigImpl( if nodeConfig == nil { nodeConfig = arbnode.ConfigDefaultL1Test() } + if execConfig == nil { + execConfig = gethexec.ConfigDefaultTest() + } if chainConfig == nil { chainConfig = params.ArbitrumDevTestChainConfig() } @@ -461,15 +466,20 @@ func createTestNodeOnL1WithConfigImpl( if !isSequencer { nodeConfig.BatchPoster.Enable = false - nodeConfig.Sequencer.Enable = false + nodeConfig.Sequencer = false nodeConfig.DelayedSequencer.Enable = false + execConfig.Sequencer.Enable = false } AddDefaultValNode(t, ctx, nodeConfig, true) - var err error + Require(t, execConfig.Validate()) + execConfigFetcher := func() *gethexec.Config { return execConfig } + execNode, err := gethexec.CreateExecutionNode(l2stack, l2chainDb, l2blockchain, l1client, execConfigFetcher) + Require(t, err) + currentNode, err = arbnode.CreateNode( - ctx, l2stack, l2chainDb, l2arbDb, nodeConfig, l2blockchain, l1client, + ctx, l2stack, execNode, l2arbDb, nodeConfig, l2blockchain.Config(), l1client, addresses, sequencerTxOptsPtr, dataSigner, fatalErrChan, ) Require(t, err) @@ -486,18 +496,31 @@ func createTestNodeOnL1WithConfigImpl( // L2 -Only. Enough for tests that needs no interface to L1 // Requires precompiles.AllowDebugPrecompiles = true func CreateTestL2(t *testing.T, ctx context.Context) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { - return CreateTestL2WithConfig(t, ctx, nil, arbnode.ConfigDefaultL2Test(), true) + return CreateTestL2WithConfig(t, ctx, nil, nil, nil, true) } func CreateTestL2WithConfig( - t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, takeOwnership bool, + t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, execConfig *gethexec.Config, takeOwnership bool, ) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { + if nodeConfig == nil { + nodeConfig = arbnode.ConfigDefaultL2Test() + } + if execConfig == nil { + execConfig = gethexec.ConfigDefaultTest() + } + feedErrChan := make(chan error, 10) AddDefaultValNode(t, ctx, nodeConfig, true) l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, l2Info, "", params.ArbitrumDevTestChainConfig()) - currentNode, err := arbnode.CreateNode(ctx, stack, chainDb, arbDb, nodeConfig, blockchain, nil, nil, nil, nil, feedErrChan) + + Require(t, execConfig.Validate()) + execConfigFetcher := func() *gethexec.Config { return execConfig } + execNode, err := gethexec.CreateExecutionNode(stack, chainDb, blockchain, nil, execConfigFetcher) + Require(t, err) + + currentNode, err := arbnode.CreateNode(ctx, stack, execNode, arbDb, nodeConfig, blockchain.Config(), nil, nil, nil, nil, feedErrChan) Require(t, err) // Give the node an init message @@ -565,7 +588,7 @@ func Create2ndNode( } else { nodeConf.DataAvailability = *dasConfig } - return Create2ndNodeWithConfig(t, ctx, first, l1stack, l1info, l2InitData, nodeConf, nil) + return Create2ndNodeWithConfig(t, ctx, first, l1stack, l1info, l2InitData, nodeConf, nil, nil) } func Create2ndNodeWithConfig( @@ -576,8 +599,15 @@ func Create2ndNodeWithConfig( l1info *BlockchainTestInfo, l2InitData *statetransfer.ArbosInitializationInfo, nodeConfig *arbnode.Config, + execConfig *gethexec.Config, stackConfig *node.Config, ) (*ethclient.Client, *arbnode.Node) { + if nodeConfig == nil { + nodeConfig = arbnode.ConfigDefaultL1NonSequencerTest() + } + if execConfig == nil { + execConfig = gethexec.ConfigDefaultNonSequencerTest() + } feedErrChan := make(chan error, 10) l1rpcClient, err := l1stack.Attach() if err != nil { @@ -600,12 +630,18 @@ func Create2ndNodeWithConfig( dataSigner := signature.DataSignerFromPrivateKey(l1info.GetInfoWithPrivKey("Sequencer").PrivateKey) txOpts := l1info.GetDefaultTransactOpts("Sequencer", ctx) - l2blockchain, err := execution.WriteOrTestBlockChain(l2chainDb, nil, initReader, first.Execution.ArbInterface.BlockChain().Config(), arbnode.ConfigDefaultL2Test().TxLookupLimit, 0) + firstExec := getExecNode(t, first) + + l2blockchain, err := gethexec.WriteOrTestBlockChain(l2chainDb, nil, initReader, firstExec.ArbInterface.BlockChain().Config(), gethexec.ConfigDefaultTest().TxLookupLimit, 0) Require(t, err) AddDefaultValNode(t, ctx, nodeConfig, true) - currentNode, err := arbnode.CreateNode(ctx, l2stack, l2chainDb, l2arbDb, nodeConfig, l2blockchain, l1client, first.DeployInfo, &txOpts, dataSigner, feedErrChan) + configFetcher := func() *gethexec.Config { return execConfig } + currentExec, err := gethexec.CreateExecutionNode(l2stack, l2chainDb, l2blockchain, l1client, configFetcher) + Require(t, err) + + currentNode, err := arbnode.CreateNode(ctx, l2stack, currentExec, l2arbDb, nodeConfig, l2blockchain.Config(), l1client, first.DeployInfo, &txOpts, dataSigner, feedErrChan) Require(t, err) err = currentNode.Start(ctx) @@ -759,3 +795,12 @@ func deploySimple( Require(t, err) return addr, simple } + +func getExecNode(t *testing.T, node *arbnode.Node) *gethexec.ExecutionNode { + t.Helper() + gethExec, ok := node.Execution.(*gethexec.ExecutionNode) + if !ok { + t.Fatal("failed to get exec node from arbnode") + } + return gethExec +} diff --git a/system_tests/contract_tx_test.go b/system_tests/contract_tx_test.go index 9214884c2..084eada6e 100644 --- a/system_tests/contract_tx_test.go +++ b/system_tests/contract_tx_test.go @@ -16,7 +16,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/util/arbmath" @@ -26,8 +25,7 @@ func TestContractTxDeploy(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - nodeconfig := arbnode.ConfigDefaultL2Test() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, false) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, nil, false) defer node.StopAndWait() from := common.HexToAddress("0x123412341234") diff --git a/system_tests/das_test.go b/system_tests/das_test.go index 8fadf316b..430239fcc 100644 --- a/system_tests/das_test.go +++ b/system_tests/das_test.go @@ -22,11 +22,11 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/blsSignatures" "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/das" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/signature" @@ -137,8 +137,10 @@ func TestDASRekey(t *testing.T) { l1NodeConfigA.DataAvailability.RestfulClientAggregatorConfig.Enable = true l1NodeConfigA.DataAvailability.RestfulClientAggregatorConfig.Urls = []string{restServerUrlA} l1NodeConfigA.DataAvailability.L1NodeURL = "none" + execA, err := gethexec.CreateExecutionNode(l2stackA, l2chainDb, l2blockchain, l1client, gethexec.ConfigDefaultTest) + Require(t, err) - nodeA, err := arbnode.CreateNode(ctx, l2stackA, l2chainDb, l2arbDb, l1NodeConfigA, l2blockchain, l1client, addresses, sequencerTxOptsPtr, nil, feedErrChan) + nodeA, err := arbnode.CreateNode(ctx, l2stackA, execA, l2arbDb, l1NodeConfigA, l2blockchain.Config(), l1client, addresses, sequencerTxOptsPtr, nil, feedErrChan) Require(t, err) Require(t, nodeA.Start(ctx)) l2clientA := ClientForStack(t, l2stackA) @@ -151,7 +153,7 @@ func TestDASRekey(t *testing.T) { l1NodeConfigB.DataAvailability.L1NodeURL = "none" - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, l1NodeConfigB, nil) + l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, l1NodeConfigB, nil, nil) checkBatchPosting(t, ctx, l1client, l2clientA, l1info, l2info, big.NewInt(1e12), l2clientB) nodeA.StopAndWait() nodeB.StopAndWait() @@ -177,15 +179,19 @@ func TestDASRekey(t *testing.T) { l2arbDb, err := l2stackA.OpenDatabase("arbdb", 0, 0, "", false) Require(t, err) - l2blockchain, err := execution.GetBlockChain(l2chainDb, nil, chainConfig, arbnode.ConfigDefaultL2Test().TxLookupLimit) + l2blockchain, err := gethexec.GetBlockChain(l2chainDb, nil, chainConfig, gethexec.ConfigDefaultTest().TxLookupLimit) + Require(t, err) + + execA, err := gethexec.CreateExecutionNode(l2stackA, l2chainDb, l2blockchain, l1client, gethexec.ConfigDefaultTest) Require(t, err) + l1NodeConfigA.DataAvailability.AggregatorConfig = aggConfigForBackend(t, backendConfigB) - nodeA, err := arbnode.CreateNode(ctx, l2stackA, l2chainDb, l2arbDb, l1NodeConfigA, l2blockchain, l1client, addresses, sequencerTxOptsPtr, nil, feedErrChan) + nodeA, err := arbnode.CreateNode(ctx, l2stackA, execA, l2arbDb, l1NodeConfigA, l2blockchain.Config(), l1client, addresses, sequencerTxOptsPtr, nil, feedErrChan) Require(t, err) Require(t, nodeA.Start(ctx)) l2clientA := ClientForStack(t, l2stackA) - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, l1NodeConfigB, nil) + l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, l1NodeConfigB, nil, nil) checkBatchPosting(t, ctx, l1client, l2clientA, l1info, l2info, big.NewInt(2e12), l2clientB) nodeA.StopAndWait() @@ -306,9 +312,12 @@ func TestDASComplexConfigAndRestMirror(t *testing.T) { l2info, l2stackA, l2chainDb, l2arbDb, l2blockchain := createL2BlockChain(t, nil, "", chainConfig) l2info.GenerateAccount("User2") + execA, err := gethexec.CreateExecutionNode(l2stackA, l2chainDb, l2blockchain, l1client, gethexec.ConfigDefaultTest) + Require(t, err) + sequencerTxOpts := l1info.GetDefaultTransactOpts("Sequencer", ctx) sequencerTxOptsPtr := &sequencerTxOpts - nodeA, err := arbnode.CreateNode(ctx, l2stackA, l2chainDb, l2arbDb, l1NodeConfigA, l2blockchain, l1client, addresses, sequencerTxOptsPtr, dataSigner, feedErrChan) + nodeA, err := arbnode.CreateNode(ctx, l2stackA, execA, l2arbDb, l1NodeConfigA, l2blockchain.Config(), l1client, addresses, sequencerTxOptsPtr, dataSigner, feedErrChan) Require(t, err) Require(t, nodeA.Start(ctx)) l2clientA := ClientForStack(t, l2stackA) @@ -330,7 +339,7 @@ func TestDASComplexConfigAndRestMirror(t *testing.T) { l1NodeConfigB.DataAvailability.RestfulClientAggregatorConfig.Enable = true l1NodeConfigB.DataAvailability.RestfulClientAggregatorConfig.Urls = []string{"http://" + restLis.Addr().String()} l1NodeConfigB.DataAvailability.L1NodeURL = "none" - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, l1NodeConfigB, nil) + l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, l1NodeConfigB, nil, nil) checkBatchPosting(t, ctx, l1client, l2clientA, l1info, l2info, big.NewInt(1e12), l2clientB) diff --git a/system_tests/debugapi_test.go b/system_tests/debugapi_test.go index df954685d..03e3dfd40 100644 --- a/system_tests/debugapi_test.go +++ b/system_tests/debugapi_test.go @@ -14,7 +14,7 @@ import ( func TestDebugAPI(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, nil) + _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, nil, nil) defer requireClose(t, l1stack) defer requireClose(t, l2stack) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index c80492326..a1c411d7d 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -185,8 +185,9 @@ func TestComponentEstimate(t *testing.T) { baseFee, _ := outputs[2].(*big.Int) l1BaseFeeEstimate, _ := outputs[3].(*big.Int) + execNode := getExecNode(t, node) tx := l2info.SignTxAs("User", &types.DynamicFeeTx{ - ChainID: node.Execution.ArbInterface.BlockChain().Config().ChainID, + ChainID: execNode.ArbInterface.BlockChain().Config().ChainID, Nonce: 0, GasTipCap: maxPriorityFeePerGas, GasFeeCap: maxFeePerGas, diff --git a/system_tests/fees_test.go b/system_tests/fees_test.go index 734ccc752..3efe2bfdf 100644 --- a/system_tests/fees_test.go +++ b/system_tests/fees_test.go @@ -37,7 +37,8 @@ func TestSequencerFeePaid(t *testing.T) { defer requireClose(t, l1stack) defer l2node.StopAndWait() - version := l2node.Execution.ArbInterface.BlockChain().Config().ArbitrumChainParams.InitialArbOSVersion + execNode := getExecNode(t, l2node) + version := execNode.ArbInterface.BlockChain().Config().ArbitrumChainParams.InitialArbOSVersion callOpts := l2info.GetDefaultCallOpts("Owner", ctx) // get the network fee account @@ -133,7 +134,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { conf := arbnode.ConfigDefaultL1Test() conf.DelayedSequencer.FinalizeDistance = 1 - l2info, node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, chainConfig, nil) + l2info, node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, chainConfig, nil) defer requireClose(t, l1stack) defer node.StopAndWait() diff --git a/system_tests/forwarder_test.go b/system_tests/forwarder_test.go index 5ec897604..6595eefb6 100644 --- a/system_tests/forwarder_test.go +++ b/system_tests/forwarder_test.go @@ -17,8 +17,8 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/node" "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/cmd/genericconf" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/statetransfer" "github.com/offchainlabs/nitro/util/redisutil" "github.com/offchainlabs/nitro/util/testhelpers" @@ -35,18 +35,20 @@ func TestStaticForwarder(t *testing.T) { nodeConfigA := arbnode.ConfigDefaultL1Test() nodeConfigA.BatchPoster.Enable = false - l2info, nodeA, clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfigA, nil, stackConfig) + l2info, nodeA, clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfigA, nil, nil, stackConfig) defer requireClose(t, l1stack) defer nodeA.StopAndWait() nodeConfigB := arbnode.ConfigDefaultL1Test() - nodeConfigB.Sequencer.Enable = false + execConfigB := gethexec.ConfigDefaultTest() + execConfigB.Sequencer.Enable = false + nodeConfigB.Sequencer = false nodeConfigB.DelayedSequencer.Enable = false - nodeConfigB.Forwarder.RedisUrl = "" - nodeConfigB.ForwardingTargetImpl = ipcPath + execConfigB.Forwarder.RedisUrl = "" + execConfigB.ForwardingTargetImpl = ipcPath nodeConfigB.BatchPoster.Enable = false - clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, nodeConfigB, nil) + clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, nodeConfigB, execConfigB, nil) defer nodeB.StopAndWait() l2info.GenerateAccount("User2") @@ -93,7 +95,7 @@ func createFallbackSequencer( nodeConfig.SeqCoordinator.Enable = false nodeConfig.SeqCoordinator.RedisUrl = redisUrl nodeConfig.SeqCoordinator.MyUrlImpl = ipcPath - return createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, stackConfig) + return createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, nil, stackConfig) } func createForwardingNode( @@ -113,13 +115,15 @@ func createForwardingNode( ipcConfig.Apply(stackConfig) } nodeConfig := arbnode.ConfigDefaultL1Test() - nodeConfig.Sequencer.Enable = false + nodeConfig.Sequencer = false nodeConfig.DelayedSequencer.Enable = false - nodeConfig.Forwarder.RedisUrl = redisUrl - nodeConfig.ForwardingTargetImpl = fallbackPath + execConfig := gethexec.ConfigDefaultTest() + execConfig.Sequencer.Enable = false + execConfig.Forwarder.RedisUrl = redisUrl + execConfig.ForwardingTargetImpl = fallbackPath // nodeConfig.Feed.Output.Enable = false - return Create2ndNodeWithConfig(t, ctx, first, l1stack, l1info, l2InitData, nodeConfig, stackConfig) + return Create2ndNodeWithConfig(t, ctx, first, l1stack, l1info, l2InitData, nodeConfig, execConfig, stackConfig) } func createSequencer( @@ -141,7 +145,7 @@ func createSequencer( nodeConfig.SeqCoordinator.RedisUrl = redisUrl nodeConfig.SeqCoordinator.MyUrlImpl = ipcPath - return Create2ndNodeWithConfig(t, ctx, first, l1stack, l1info, l2InitData, nodeConfig, stackConfig) + return Create2ndNodeWithConfig(t, ctx, first, l1stack, l1info, l2InitData, nodeConfig, gethexec.ConfigDefaultTest(), stackConfig) } func TestRedisForwarder(t *testing.T) { @@ -210,7 +214,7 @@ func TestRedisForwarder(t *testing.T) { if err == nil { break } - time.Sleep(execution.DefaultTestForwarderConfig.UpdateInterval / 2) + time.Sleep(gethexec.DefaultTestForwarderConfig.UpdateInterval / 2) } testhelpers.RequireImpl(t, err) _, err = EnsureTxSucceeded(ctx, clients[i], tx) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index 24795f623..8b28832a3 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -27,6 +27,7 @@ import ( "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/arbstate" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/solgen/go/challengegen" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/ospgen" @@ -266,7 +267,9 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall asserterL2Info, asserterL2Stack, asserterL2ChainDb, asserterL2ArbDb, asserterL2Blockchain := createL2BlockChain(t, nil, "", chainConfig) asserterRollupAddresses.Bridge = asserterBridgeAddr asserterRollupAddresses.SequencerInbox = asserterSeqInboxAddr - asserterL2, err := arbnode.CreateNode(ctx, asserterL2Stack, asserterL2ChainDb, asserterL2ArbDb, conf, asserterL2Blockchain, l1Backend, asserterRollupAddresses, nil, nil, fatalErrChan) + asserterExec, err := gethexec.CreateExecutionNode(asserterL2Stack, asserterL2ChainDb, asserterL2Blockchain, l1Backend, gethexec.ConfigDefaultTest) + Require(t, err) + asserterL2, err := arbnode.CreateNode(ctx, asserterL2Stack, asserterExec, asserterL2ArbDb, conf, chainConfig, l1Backend, asserterRollupAddresses, nil, nil, fatalErrChan) Require(t, err) err = asserterL2.Start(ctx) Require(t, err) @@ -275,7 +278,9 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall challengerRollupAddresses := *asserterRollupAddresses challengerRollupAddresses.Bridge = challengerBridgeAddr challengerRollupAddresses.SequencerInbox = challengerSeqInboxAddr - challengerL2, err := arbnode.CreateNode(ctx, challengerL2Stack, challengerL2ChainDb, challengerL2ArbDb, conf, challengerL2Blockchain, l1Backend, &challengerRollupAddresses, nil, nil, fatalErrChan) + challengerExec, err := gethexec.CreateExecutionNode(challengerL2Stack, challengerL2ChainDb, challengerL2Blockchain, l1Backend, gethexec.ConfigDefaultTest) + Require(t, err) + challengerL2, err := arbnode.CreateNode(ctx, challengerL2Stack, challengerExec, challengerL2ArbDb, conf, chainConfig, l1Backend, &challengerRollupAddresses, nil, nil, fatalErrChan) Require(t, err) err = challengerL2.Start(ctx) Require(t, err) @@ -323,13 +328,13 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall } } - asserterGenesis := asserterL2.Execution.ArbInterface.BlockChain().Genesis() - challengerGenesis := challengerL2.Execution.ArbInterface.BlockChain().Genesis() + asserterGenesis := asserterExec.ArbInterface.BlockChain().Genesis() + challengerGenesis := challengerExec.ArbInterface.BlockChain().Genesis() if asserterGenesis.Hash() != challengerGenesis.Hash() { Fail(t, "asserter and challenger have different genesis hashes") } - asserterLatestBlock := asserterL2.Execution.ArbInterface.BlockChain().CurrentBlock() - challengerLatestBlock := challengerL2.Execution.ArbInterface.BlockChain().CurrentBlock() + asserterLatestBlock := asserterExec.ArbInterface.BlockChain().CurrentBlock() + challengerLatestBlock := challengerExec.ArbInterface.BlockChain().CurrentBlock() if asserterLatestBlock.Hash() == challengerLatestBlock.Hash() { Fail(t, "asserter and challenger have the same end block") } @@ -364,7 +369,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall confirmLatestBlock(ctx, t, l1Info, l1Backend) - asserterValidator, err := staker.NewStatelessBlockValidator(asserterL2.InboxReader, asserterL2.InboxTracker, asserterL2.TxStreamer, asserterL2.Execution.Recorder, asserterL2ArbDb, nil, &conf.BlockValidator) + asserterValidator, err := staker.NewStatelessBlockValidator(asserterL2.InboxReader, asserterL2.InboxTracker, asserterL2.TxStreamer, asserterExec.Recorder, asserterL2ArbDb, nil, &conf.BlockValidator) if err != nil { Fail(t, err) } @@ -381,7 +386,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall if err != nil { Fail(t, err) } - challengerValidator, err := staker.NewStatelessBlockValidator(challengerL2.InboxReader, challengerL2.InboxTracker, challengerL2.TxStreamer, challengerL2.Execution.Recorder, challengerL2ArbDb, nil, &conf.BlockValidator) + challengerValidator, err := staker.NewStatelessBlockValidator(challengerL2.InboxReader, challengerL2.InboxTracker, challengerL2.TxStreamer, challengerExec.Recorder, challengerL2ArbDb, nil, &conf.BlockValidator) if err != nil { Fail(t, err) } diff --git a/system_tests/infra_fee_test.go b/system_tests/infra_fee_test.go index fd10badd4..488c085fc 100644 --- a/system_tests/infra_fee_test.go +++ b/system_tests/infra_fee_test.go @@ -13,7 +13,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/arbmath" @@ -23,9 +22,8 @@ func TestInfraFee(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - nodeconfig := arbnode.ConfigDefaultL2Test() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, true) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, nil, true) defer node.StopAndWait() l2info.GenerateAccount("User2") diff --git a/system_tests/initialization_test.go b/system_tests/initialization_test.go index c7797d35e..0e055adc5 100644 --- a/system_tests/initialization_test.go +++ b/system_tests/initialization_test.go @@ -11,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/params" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/statetransfer" "github.com/offchainlabs/nitro/util/testhelpers" ) @@ -63,7 +62,7 @@ func TestInitContract(t *testing.T) { l2info.ArbInitData.Accounts = append(l2info.ArbInitData.Accounts, accountInfo) expectedSums[accountAddress] = sum } - _, node, client := CreateTestL2WithConfig(t, ctx, l2info, arbnode.ConfigDefaultL2Test(), true) + _, node, client := CreateTestL2WithConfig(t, ctx, l2info, nil, nil, true) defer node.StopAndWait() for accountAddress, sum := range expectedSums { diff --git a/system_tests/ipc_test.go b/system_tests/ipc_test.go index ad5a8fbc6..4fb6473fa 100644 --- a/system_tests/ipc_test.go +++ b/system_tests/ipc_test.go @@ -24,7 +24,7 @@ func TestIpcRpc(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, l2node, _, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, nil, stackConf) + _, l2node, _, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, nil, nil, stackConf) defer requireClose(t, l1stack) defer l2node.StopAndWait() diff --git a/system_tests/meaningless_reorg_test.go b/system_tests/meaningless_reorg_test.go index f9e9f6e57..6d4a98614 100644 --- a/system_tests/meaningless_reorg_test.go +++ b/system_tests/meaningless_reorg_test.go @@ -20,7 +20,7 @@ func TestMeaninglessBatchReorg(t *testing.T) { defer cancel() conf := arbnode.ConfigDefaultL1Test() conf.BatchPoster.Enable = false - l2Info, arbNode, l2Client, l1Info, l1Backend, l1Client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil) + l2Info, arbNode, l2Client, l1Info, l1Backend, l1Client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil, nil) defer requireClose(t, l1stack) defer arbNode.StopAndWait() @@ -33,11 +33,12 @@ func TestMeaninglessBatchReorg(t *testing.T) { batchReceipt, err := EnsureTxSucceeded(ctx, l1Client, tx) Require(t, err) + execNode := getExecNode(t, arbNode) for i := 0; ; i++ { if i >= 500 { Fail(t, "Failed to read batch from L1") } - msgNum, err := arbNode.Execution.ExecEngine.HeadMessageNumber() + msgNum, err := execNode.ExecEngine.HeadMessageNumber() Require(t, err) if msgNum == 1 { break diff --git a/system_tests/reorg_resequencing_test.go b/system_tests/reorg_resequencing_test.go index c56f91940..05ca0a25c 100644 --- a/system_tests/reorg_resequencing_test.go +++ b/system_tests/reorg_resequencing_test.go @@ -22,6 +22,8 @@ func TestReorgResequencing(t *testing.T) { l2info, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() + execNode := getExecNode(t, node) + startMsgCount, err := node.TxStreamer.GetMessageCount() Require(t, err) @@ -51,7 +53,7 @@ func TestReorgResequencing(t *testing.T) { err = node.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = node.Execution.ExecEngine.HeadMessageNumberSync(t) + _, err = execNode.ExecEngine.HeadMessageNumberSync(t) Require(t, err) verifyBalances("after empty reorg") @@ -76,7 +78,7 @@ func TestReorgResequencing(t *testing.T) { }}) Require(t, err) - _, err = node.Execution.ExecEngine.HeadMessageNumberSync(t) + _, err = execNode.ExecEngine.HeadMessageNumberSync(t) Require(t, err) accountsWithBalance = append(accountsWithBalance, "User4") @@ -85,7 +87,7 @@ func TestReorgResequencing(t *testing.T) { err = node.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = node.Execution.ExecEngine.HeadMessageNumberSync(t) + _, err = execNode.ExecEngine.HeadMessageNumberSync(t) Require(t, err) verifyBalances("after second empty reorg") diff --git a/system_tests/seq_coordinator_test.go b/system_tests/seq_coordinator_test.go index 51a61aec0..f395826f3 100644 --- a/system_tests/seq_coordinator_test.go +++ b/system_tests/seq_coordinator_test.go @@ -20,9 +20,9 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/util/redisutil" ) diff --git a/system_tests/seq_nonce_test.go b/system_tests/seq_nonce_test.go index 80de4cfa0..ec4d4365a 100644 --- a/system_tests/seq_nonce_test.go +++ b/system_tests/seq_nonce_test.go @@ -15,7 +15,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/arbmath" ) @@ -24,9 +24,9 @@ func TestSequencerParallelNonces(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - config := arbnode.ConfigDefaultL2Test() + config := gethexec.ConfigDefaultTest() config.Sequencer.NonceFailureCacheExpiry = time.Minute - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false) defer node.StopAndWait() l2info.GenerateAccount("Destination") @@ -62,8 +62,8 @@ func TestSequencerNonceTooHigh(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - config := arbnode.ConfigDefaultL2Test() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false) + config := gethexec.ConfigDefaultTest() + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false) defer node.StopAndWait() l2info.GetInfoWithPrivKey("Owner").Nonce++ @@ -88,10 +88,10 @@ func TestSequencerNonceTooHighQueueFull(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - config := arbnode.ConfigDefaultL2Test() + config := gethexec.ConfigDefaultTest() config.Sequencer.NonceFailureCacheSize = 5 config.Sequencer.NonceFailureCacheExpiry = time.Minute - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false) defer node.StopAndWait() count := 15 diff --git a/system_tests/seq_pause_test.go b/system_tests/seq_pause_test.go index 4b2c907d7..8ce76846a 100644 --- a/system_tests/seq_pause_test.go +++ b/system_tests/seq_pause_test.go @@ -8,7 +8,7 @@ import ( "time" "github.com/ethereum/go-ethereum/core/types" - "github.com/offchainlabs/nitro/arbnode/execution" + "github.com/offchainlabs/nitro/execution/gethexec" ) func TestSequencerPause(t *testing.T) { @@ -21,11 +21,12 @@ func TestSequencerPause(t *testing.T) { const numUsers = 100 - prechecker, ok := nodeA.Execution.TxPublisher.(*execution.TxPreChecker) + execA := getExecNode(t, nodeA) + prechecker, ok := execA.TxPublisher.(*gethexec.TxPreChecker) if !ok { t.Error("prechecker not found on node") } - sequencer, ok := prechecker.TransactionPublisher.(*execution.Sequencer) + sequencer, ok := prechecker.TransactionPublisher.(*gethexec.Sequencer) if !ok { t.Error("sequencer not found on node") } diff --git a/system_tests/seq_reject_test.go b/system_tests/seq_reject_test.go index 1e26c0182..5fbbda8d5 100644 --- a/system_tests/seq_reject_test.go +++ b/system_tests/seq_reject_test.go @@ -31,14 +31,14 @@ func TestSequencerRejection(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() feedErrChan := make(chan error, 10) - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true) + l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true) defer nodeA.StopAndWait() clientNodeConfig := arbnode.ConfigDefaultL2Test() port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false) + _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false) defer nodeB.StopAndWait() auth := l2info1.GetDefaultTransactOpts("Owner", ctx) diff --git a/system_tests/seq_whitelist_test.go b/system_tests/seq_whitelist_test.go index f24ce79c9..936745176 100644 --- a/system_tests/seq_whitelist_test.go +++ b/system_tests/seq_whitelist_test.go @@ -9,16 +9,16 @@ import ( "testing" "github.com/ethereum/go-ethereum/params" - "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/execution/gethexec" ) func TestSequencerWhitelist(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - config := arbnode.ConfigDefaultL2Test() + config := gethexec.ConfigDefaultTest() config.Sequencer.SenderWhitelist = GetTestAddressForAccountName(t, "Owner").String() + "," + GetTestAddressForAccountName(t, "User").String() - l2info, l2node, client := CreateTestL2WithConfig(t, ctx, nil, config, true) + l2info, l2node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, true) defer l2node.StopAndWait() l2info.GenerateAccount("User") diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index 0ae72e384..83a8fc064 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -13,6 +13,7 @@ import ( "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/broadcastclient" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/relay" "github.com/offchainlabs/nitro/util/signature" "github.com/offchainlabs/nitro/wsbroadcastserver" @@ -44,13 +45,13 @@ func TestSequencerFeed(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true) + l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true) defer nodeA.StopAndWait() clientNodeConfig := arbnode.ConfigDefaultL2Test() port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false) + _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false) defer nodeB.StopAndWait() l2info1.GenerateAccount("User2") @@ -79,7 +80,7 @@ func TestRelayedSequencerFeed(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true) + l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true) defer nodeA.StopAndWait() bigChainId, err := client1.ChainID(ctx) @@ -101,7 +102,7 @@ func TestRelayedSequencerFeed(t *testing.T) { clientNodeConfig := arbnode.ConfigDefaultL2Test() port = currentRelay.GetListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeC, client3 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false) + _, nodeC, client3 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false) defer nodeC.StopAndWait() StartWatchChanErr(t, ctx, feedErrChan, nodeC) @@ -135,7 +136,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigA.BatchPoster.Enable = true nodeConfigA.Feed.Output.Enable = false - l2infoA, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfigA, chainConfig, nil) + l2infoA, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfigA, nil, chainConfig, nil) defer requireClose(t, l1stack, "unable to close l1stack") defer nodeA.StopAndWait() @@ -147,7 +148,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigC.DataAvailability = nodeConfigA.DataAvailability nodeConfigC.DataAvailability.AggregatorConfig.Enable = false nodeConfigC.Feed.Output = *newBroadcasterConfigTest() - l2clientC, nodeC := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2infoA.ArbInitData, nodeConfigC, nil) + l2clientC, nodeC := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2infoA.ArbInitData, nodeConfigC, gethexec.ConfigDefaultTest(), nil) defer nodeC.StopAndWait() port := nodeC.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port @@ -158,7 +159,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigB.Feed.Input = *newBroadcastClientConfigTest(port) nodeConfigB.DataAvailability = nodeConfigA.DataAvailability nodeConfigB.DataAvailability.AggregatorConfig.Enable = false - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2infoA.ArbInitData, nodeConfigB, nil) + l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2infoA.ArbInitData, nodeConfigB, nil, nil) defer nodeB.StopAndWait() l2infoA.GenerateAccount("FraudUser") @@ -168,12 +169,18 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { l2infoA.GetInfoWithPrivKey("Owner").Nonce -= 1 // Use same l2info object for different l2s realTx := l2infoA.PrepareTx("Owner", "RealUser", l2infoA.TransferGas, big.NewInt(1e12), nil) - err := l2clientC.SendTransaction(ctx, fraudTx) - if err != nil { - t.Fatal("error sending fraud transaction:", err) + for i := 0; i < 10; i++ { + err := l2clientC.SendTransaction(ctx, fraudTx) + if err == nil { + break + } + <-time.After(time.Millisecond * 10) + if i == 9 { + t.Fatal("error sending fraud transaction:", err) + } } - _, err = EnsureTxSucceeded(ctx, l2clientC, fraudTx) + _, err := EnsureTxSucceeded(ctx, l2clientC, fraudTx) if err != nil { t.Fatal("error ensuring fraud transaction succeeded:", err) } diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index 30b51fcc2..36364ea76 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -47,8 +47,9 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { if validator { conf.BlockValidator.Enable = true } - l2Info, arbNode, _, l1Info, l1backend, l1Client, l1stack := createTestNodeOnL1WithConfig(t, ctx, false, conf, nil, nil) - l2Backend := arbNode.Execution.Backend + l2Info, arbNode, _, l1Info, l1backend, l1Client, l1stack := createTestNodeOnL1WithConfig(t, ctx, false, conf, nil, nil, nil) + execNode := getExecNode(t, arbNode) + l2Backend := execNode.Backend defer requireClose(t, l1stack) defer arbNode.StopAndWait() @@ -268,7 +269,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { if validator && i%15 == 0 { for i := 0; ; i++ { - expectedPos, err := arbNode.Execution.ExecEngine.BlockNumberToMessageIndex(expectedBlockNumber) + expectedPos, err := execNode.ExecEngine.BlockNumberToMessageIndex(expectedBlockNumber) Require(t, err) lastValidated := arbNode.BlockValidator.Validated(t) if lastValidated == expectedPos+1 { diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 3aee6074b..39b6169ad 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -23,6 +23,7 @@ import ( "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/colors" @@ -65,15 +66,17 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) l2info, l2nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) defer requireClose(t, l1stack) defer l2nodeA.StopAndWait() + execNodeA := getExecNode(t, l2nodeA) if faultyStaker { l2info.GenerateGenesisAccount("FaultyAddr", common.Big1) } - l2clientB, l2nodeB := Create2ndNodeWithConfig(t, ctx, l2nodeA, l1stack, l1info, &l2info.ArbInitData, arbnode.ConfigDefaultL1Test(), nil) + l2clientB, l2nodeB := Create2ndNodeWithConfig(t, ctx, l2nodeA, l1stack, l1info, &l2info.ArbInitData, arbnode.ConfigDefaultL1Test(), gethexec.ConfigDefaultTest(), nil) defer l2nodeB.StopAndWait() + execNodeB := getExecNode(t, l2nodeB) - nodeAGenesis := l2nodeA.Execution.Backend.APIBackend().CurrentHeader().Hash() - nodeBGenesis := l2nodeB.Execution.Backend.APIBackend().CurrentHeader().Hash() + nodeAGenesis := execNodeA.Backend.APIBackend().CurrentHeader().Hash() + nodeBGenesis := execNodeB.Backend.APIBackend().CurrentHeader().Hash() if faultyStaker { if nodeAGenesis == nodeBGenesis { Fail(t, "node A L2 genesis hash", nodeAGenesis, "== node B L2 genesis hash", nodeBGenesis) @@ -135,7 +138,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) l2nodeA.InboxReader, l2nodeA.InboxTracker, l2nodeA.TxStreamer, - l2nodeA.Execution.Recorder, + execNodeA, l2nodeA.ArbDB, nil, &blockValidatorConfig, @@ -161,7 +164,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) l2nodeB.InboxReader, l2nodeB.InboxTracker, l2nodeB.TxStreamer, - l2nodeB.Execution.Recorder, + execNodeB, l2nodeB.ArbDB, nil, &blockValidatorConfig, diff --git a/system_tests/twonodes_test.go b/system_tests/twonodes_test.go index 6fef8ce48..af6ac426b 100644 --- a/system_tests/twonodes_test.go +++ b/system_tests/twonodes_test.go @@ -20,7 +20,7 @@ func testTwoNodesSimple(t *testing.T, dasModeStr string) { chainConfig, l1NodeConfigA, lifecycleManager, _, dasSignerKey := setupConfigWithDAS(t, ctx, dasModeStr) defer lifecycleManager.StopAndWaitUntil(time.Second) - l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, chainConfig, nil) + l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, nil, chainConfig, nil) defer requireClose(t, l1stack) defer nodeA.StopAndWait() diff --git a/system_tests/twonodeslong_test.go b/system_tests/twonodeslong_test.go index 0c11c1fcb..2c3160308 100644 --- a/system_tests/twonodeslong_test.go +++ b/system_tests/twonodeslong_test.go @@ -42,7 +42,7 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { chainConfig, l1NodeConfigA, lifecycleManager, _, dasSignerKey := setupConfigWithDAS(t, ctx, dasModeStr) defer lifecycleManager.StopAndWaitUntil(time.Second) - l2info, nodeA, l2client, l1info, l1backend, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, chainConfig, nil) + l2info, nodeA, l2client, l1info, l1backend, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, nil, chainConfig, nil) defer requireClose(t, l1stack) authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) diff --git a/system_tests/validation_mock_test.go b/system_tests/validation_mock_test.go index 98db34c0e..f6023c5e4 100644 --- a/system_tests/validation_mock_test.go +++ b/system_tests/validation_mock_test.go @@ -12,9 +12,9 @@ import ( "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/containers" "github.com/offchainlabs/nitro/validator" diff --git a/testnode-scripts/config.ts b/testnode-scripts/config.ts index 2724401ba..4b94d5f63 100644 --- a/testnode-scripts/config.ts +++ b/testnode-scripts/config.ts @@ -180,9 +180,7 @@ function writeConfigs(argv: any) { "strategy": "MakeNodes", "target-machine-count": 4, }, - "sequencer": { - "enable": false - }, + "sequencer": false, "delayed-sequencer": { "enable": false }, @@ -207,6 +205,11 @@ function writeConfigs(argv: any) { } } }, + "execution" : { + "sequencer": { + "enable": false + }, + }, "init": { "dev-init": "true" }, @@ -238,7 +241,8 @@ function writeConfigs(argv: any) { fs.writeFileSync(path.join(consts.configpath, "unsafe_staker_config.json"), JSON.stringify(unsafeStakerConfig)) let sequencerConfig = JSON.parse(baseConfJSON) - sequencerConfig.node.sequencer.enable = true + sequencerConfig.execution.sequencer.enable = true + sequencerConfig.node.sequencer = true sequencerConfig.node["seq-coordinator"].enable = true sequencerConfig.node["delayed-sequencer"].enable = true fs.writeFileSync(path.join(consts.configpath, "sequencer_config.json"), JSON.stringify(sequencerConfig)) From f7c611fea6495633e36a6370b4e8d9e8c8b30133 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 15 Mar 2023 18:49:47 +0200 Subject: [PATCH 009/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index dcb407568..ce5c50156 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit dcb407568c3641278ce496c2576205719acf19c9 +Subproject commit ce5c50156406f408cc6fc80575c99db1d4d9b2f0 From a7984e2106734f754b5c114f9be7a5fc1d1eba4a Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Sat, 25 Mar 2023 09:05:02 -0600 Subject: [PATCH 010/775] gethexec: dont break if sequencer is nil --- execution/gethexec/node.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 8114f9c62..2791afb27 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -318,13 +318,21 @@ func (n *ExecutionNode) PrepareForRecord(ctx context.Context, start, end arbutil } func (n *ExecutionNode) Pause() { - n.Sequencer.Pause() + if n.Sequencer != nil { + n.Sequencer.Pause() + } } func (n *ExecutionNode) Activate() { - n.Sequencer.Activate() + if n.Sequencer != nil { + n.Sequencer.Activate() + } } func (n *ExecutionNode) ForwardTo(url string) error { - return n.Sequencer.ForwardTo(url) + if n.Sequencer != nil { + return n.Sequencer.ForwardTo(url) + } else { + return errors.New("forwardTo not supported - sequencer not acrtive") + } } func (n *ExecutionNode) SetTransactionStreamer(streamer execution.TransactionStreamer) { n.ExecEngine.SetTransactionStreamer(streamer) From b2e298f57813480459e8d9ac6eb7cda3b1ce3c8d Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Sat, 25 Mar 2023 09:05:22 -0600 Subject: [PATCH 011/775] fix redis tests compilation --- system_tests/seq_coordinator_test.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/system_tests/seq_coordinator_test.go b/system_tests/seq_coordinator_test.go index f395826f3..0167ed1aa 100644 --- a/system_tests/seq_coordinator_test.go +++ b/system_tests/seq_coordinator_test.go @@ -23,6 +23,7 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/execution" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/redisutil" ) @@ -65,7 +66,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { createStartNode := func(nodeNum int) { nodeConfig.SeqCoordinator.MyUrlImpl = nodeNames[nodeNum] - _, node, _ := CreateTestL2WithConfig(t, ctx, l2Info, nodeConfig, false) + _, node, _ := CreateTestL2WithConfig(t, ctx, l2Info, nodeConfig, nil, false) nodes[nodeNum] = node } @@ -149,7 +150,8 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { } nodeForwardTarget := func(nodeNum int) int { - fwTarget := nodes[nodeNum].Execution.TxPublisher.(*execution.TxPreChecker).TransactionPublisher.(*execution.Sequencer).ForwardTarget() + execNode := getExecNode(t, nodes[nodeNum]) + fwTarget := execNode.TxPublisher.(*gethexec.TxPreChecker).TransactionPublisher.(*gethexec.Sequencer).ForwardTarget() if fwTarget == "" { return -1 } @@ -283,7 +285,7 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { initRedisForTest(t, ctx, nodeConfig.SeqCoordinator.RedisUrl, nodeNames) nodeConfig.SeqCoordinator.MyUrlImpl = nodeNames[0] - l2Info, nodeA, clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, params.ArbitrumDevTestChainConfig(), nil) + l2Info, nodeA, clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, params.ArbitrumDevTestChainConfig(), nil) defer requireClose(t, l1stack) defer nodeA.StopAndWait() @@ -312,7 +314,7 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { nodeConfig.SeqCoordinator.Signing.ECDSA.AcceptSequencer = false nodeConfig.SeqCoordinator.Signing.ECDSA.AllowedAddresses = []string{l2Info.GetAddress("User2").Hex()} } - clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2Info.ArbInitData, nodeConfig, nil) + clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2Info.ArbInitData, nodeConfig, nil, nil) defer nodeB.StopAndWait() tx := l2Info.PrepareTx("Owner", "User2", l2Info.TransferGas, big.NewInt(1e12), nil) From c97fac33d78085b95fe073c0d055e716e230bc56 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 29 Mar 2023 14:20:24 +0000 Subject: [PATCH 012/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index f260155e2..b884ded52 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit f260155e26e54e8aa2add60d7c2628b39e2526b9 +Subproject commit b884ded52258c18eb4bcaf89b0d41fc3c91b30fe From 65aaa49062e2e1d4a62ad1cf4ccf594740d9006d Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 29 Mar 2023 17:45:54 +0000 Subject: [PATCH 013/775] add initial test for skipping saving states --- system_tests/common_test.go | 12 ++-- system_tests/forwarder_test.go | 8 +-- system_tests/ipc_test.go | 2 +- system_tests/recreatestate_rpc_test.go | 80 +++++++++++++++++++++----- 4 files changed, 80 insertions(+), 22 deletions(-) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 427807472..4888dea66 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -194,7 +194,7 @@ func createTestL1BlockChain(t *testing.T, l1info info) (info, *ethclient.Client, return createTestL1BlockChainWithConfig(t, l1info, nil) } -func getTestStackConfig(t *testing.T) *node.Config { +func getTestStackConfig(t *testing.T, dataDir string) *node.Config { stackConfig := node.DefaultConfig stackConfig.HTTPPort = 0 stackConfig.WSPort = 0 @@ -203,7 +203,11 @@ func getTestStackConfig(t *testing.T) *node.Config { stackConfig.P2P.NoDial = true stackConfig.P2P.NoDiscovery = true stackConfig.P2P.NAT = nil - stackConfig.DataDir = t.TempDir() + if dataDir != "" { + stackConfig.DataDir = dataDir + } else { + stackConfig.DataDir = t.TempDir() + } return &stackConfig } @@ -277,7 +281,7 @@ func createTestL1BlockChainWithConfig(t *testing.T, l1info info, stackConfig *no l1info = NewL1TestInfo(t) } if stackConfig == nil { - stackConfig = getTestStackConfig(t) + stackConfig = getTestStackConfig(t, "") } l1info.GenerateAccount("Faucet") @@ -587,7 +591,7 @@ func Create2ndNodeWithConfig( l1client := ethclient.NewClient(l1rpcClient) if stackConfig == nil { - stackConfig = getTestStackConfig(t) + stackConfig = getTestStackConfig(t, "") } l2stack, err := node.New(stackConfig) Require(t, err) diff --git a/system_tests/forwarder_test.go b/system_tests/forwarder_test.go index bd02efd2c..c23b664f0 100644 --- a/system_tests/forwarder_test.go +++ b/system_tests/forwarder_test.go @@ -29,7 +29,7 @@ func TestStaticForwarder(t *testing.T) { ipcPath := filepath.Join(t.TempDir(), "test.ipc") ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath - stackConfig := getTestStackConfig(t) + stackConfig := getTestStackConfig(t, "") ipcConfig.Apply(stackConfig) nodeConfigA := arbnode.ConfigDefaultL1Test() nodeConfigA.BatchPoster.Enable = false @@ -84,7 +84,7 @@ func createFallbackSequencer( t *testing.T, ctx context.Context, ipcPath string, redisUrl string, ) (l2info info, currentNode *arbnode.Node, l2client *ethclient.Client, l1info info, l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node) { - stackConfig := getTestStackConfig(t) + stackConfig := getTestStackConfig(t, "") ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath ipcConfig.Apply(stackConfig) @@ -105,7 +105,7 @@ func createForwardingNode( redisUrl string, fallbackPath string, ) (*ethclient.Client, *arbnode.Node) { - stackConfig := getTestStackConfig(t) + stackConfig := getTestStackConfig(t, "") if ipcPath != "" { ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath @@ -130,7 +130,7 @@ func createSequencer( ipcPath string, redisUrl string, ) (*ethclient.Client, *arbnode.Node) { - stackConfig := getTestStackConfig(t) + stackConfig := getTestStackConfig(t, "") ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath ipcConfig.Apply(stackConfig) diff --git a/system_tests/ipc_test.go b/system_tests/ipc_test.go index ad5a8fbc6..fc48d95fc 100644 --- a/system_tests/ipc_test.go +++ b/system_tests/ipc_test.go @@ -18,7 +18,7 @@ func TestIpcRpc(t *testing.T) { ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath - stackConf := getTestStackConfig(t) + stackConf := getTestStackConfig(t, "") ipcConfig.Apply(stackConf) ctx, cancel := context.WithCancel(context.Background()) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index 6e202ae17..fecce5485 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" "github.com/offchainlabs/nitro/arbnode" @@ -22,7 +23,7 @@ import ( "github.com/offchainlabs/nitro/util/testhelpers" ) -func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, txCount uint64) (node *arbnode.Node, bc *core.BlockChain, db ethdb.Database, l2client *ethclient.Client, l2info info, cancel func()) { +func prepareNode(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, dataDir string, skipBlocks uint32, skipGas uint64) (node *arbnode.Node, bc *core.BlockChain, db ethdb.Database, l2client *ethclient.Client, l2info info, cancel func(), stackDataDir string) { t.Helper() nodeConfig := arbnode.ConfigDefaultL1Test() nodeConfig.RPC.MaxRecreateStateDepth = maxRecreateStateDepth @@ -30,8 +31,10 @@ func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateD nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 cacheConfig := &core.CacheConfig{ // Arbitrum Config Options - TriesInMemory: 128, - TrieRetention: 30 * time.Minute, + TriesInMemory: 128, + TrieRetention: 30 * time.Minute, + MaxNumberOfBlocksToSkipStateSaving: skipBlocks, + MaxAmountOfGasToSkipStateSaving: skipGas, // disable caching of states in BlockChain.stateCache TrieCleanLimit: 0, @@ -43,11 +46,21 @@ func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateD SnapshotLimit: 256, SnapshotWait: true, } - l2info, node, l2client, _, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, cacheConfig) + stackConfig := getTestStackConfig(t, dataDir) + stackDataDir = stackConfig.DataDir + l2info, node, l2client, _, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, stackConfig, cacheConfig) cancel = func() { defer requireClose(t, l1stack) defer node.StopAndWait() } + bc = node.Backend.ArbInterface().BlockChain() + db = node.Backend.ChainDb() + return +} + +func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, txCount uint64, skipBlocks uint32, skipGas uint64) (node *arbnode.Node, bc *core.BlockChain, db ethdb.Database, l2client *ethclient.Client, l2info info, cancel func(), stackDataDir string) { + t.Helper() + node, bc, db, l2client, l2info, cancel, stackDataDir = prepareNode(t, ctx, maxRecreateStateDepth, "", skipBlocks, skipGas) l2info.GenerateAccount("User2") var txs []*types.Transaction for i := uint64(0); i < txCount; i++ { @@ -60,9 +73,6 @@ func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateD _, err := EnsureTxSucceeded(ctx, l2client, tx) testhelpers.RequireImpl(t, err) } - bc = node.Backend.ArbInterface().BlockChain() - db = node.Backend.ChainDb() - return } @@ -110,7 +120,7 @@ func removeStatesFromDb(t *testing.T, bc *core.BlockChain, db ethdb.Database, fr func TestRecreateStateForRPCNoDepthLimit(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, _, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32) + _, bc, db, l2client, _, cancelNode, _ := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -134,7 +144,7 @@ func TestRecreateStateForRPCBigEnoughDepthLimit(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() depthGasLimit := int64(256 * util.NormalizeL2GasForL1GasInitial(800_000, params.GWei)) - _, bc, db, l2client, _, cancelNode := prepareNodeWithHistory(t, ctx, depthGasLimit, 32) + _, bc, db, l2client, _, cancelNode, _ := prepareNodeWithHistory(t, ctx, depthGasLimit, 32, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -158,7 +168,7 @@ func TestRecreateStateForRPCDepthLimitExceeded(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() depthGasLimit := int64(200) - _, bc, db, l2client, _, cancelNode := prepareNodeWithHistory(t, ctx, depthGasLimit, 32) + _, bc, db, l2client, _, cancelNode, _ := prepareNodeWithHistory(t, ctx, depthGasLimit, 32, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -181,7 +191,7 @@ func TestRecreateStateForRPCMissingBlockParent(t *testing.T) { var headerCacheLimit uint64 = 512 ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, _, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, headerCacheLimit+5) + _, bc, db, l2client, _, cancelNode, _ := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, headerCacheLimit+5, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -214,7 +224,7 @@ func TestRecreateStateForRPCMissingBlockParent(t *testing.T) { func TestRecreateStateForRPCBeyondGenesis(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, _, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32) + _, bc, db, l2client, _, cancelNode, _ := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -238,7 +248,7 @@ func TestRecreateStateForRPCBlockNotFoundWhileRecreating(t *testing.T) { var blockCacheLimit uint64 = 256 ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, _, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, blockCacheLimit+4) + _, bc, db, l2client, _, cancelNode, _ := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, blockCacheLimit+4, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -265,3 +275,47 @@ func TestRecreateStateForRPCBlockNotFoundWhileRecreating(t *testing.T) { testhelpers.FailImpl(t, "Failed with unexpected error: \"", err, "\", at block:", lastBlock, "lastBlock:", lastBlock) } } + +func TestSkippingSavingStateAndRecreatingAfterRestart(t *testing.T) { + _ = testhelpers.InitTestLog(t, log.LvlTrace) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + _, bc, _, l2client, _, cancelNode, stackDataDir := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 101, 5, 0) + genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum + lastBlock, err := l2client.BlockNumber(ctx) + testhelpers.RequireImpl(t, err) + if lastBlock < genesis+100 { + testhelpers.FailImpl(t, "Internal test error - not enough blocks produced during preparation, want:", genesis+100, "have:", lastBlock) + } + expectedBalance, err := l2client.BalanceAt(ctx, GetTestAddressForAccountName(t, "User2"), new(big.Int).SetUint64(lastBlock)) + testhelpers.RequireImpl(t, err) + cancelNode() + _, bc, _, l2client, _, cancelNode, _ = prepareNode(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, stackDataDir, 0, 0) + defer cancelNode() + for i := genesis + 1; i <= genesis+100; i++ { + block := bc.GetBlockByNumber(i) + if block == nil { + Fail(t, "header not found for block number:", i) + } + _, err := bc.StateAt(block.Root()) + if (i-genesis-1)%5 == 0 { + Require(t, err, "state not found, root:", block.Root(), "blockNumber:", i, "blockHash", block.Hash(), "err:", err) + t.Log("have state for block:", i) + } else { + if err == nil { + Fail(t, "state shouldn't be available, root:", block.Root(), "blockNumber:", i, "blockHash", block.Hash()) + } + expectedErr := &trie.MissingNodeError{} + if !errors.As(err, &expectedErr) { + Fail(t, "getting state failed with unexpected error, root:", block.Root(), "blockNumber:", i, "blockHash", block.Hash()) + } + t.Log("no state for block:", i) + } + } + + balance, err := l2client.BalanceAt(ctx, GetTestAddressForAccountName(t, "User2"), new(big.Int).SetUint64(lastBlock)) + testhelpers.RequireImpl(t, err) + if balance.Cmp(expectedBalance) != 0 { + testhelpers.FailImpl(t, "unexpected balance result for last block, want: ", expectedBalance, " have: ", balance) + } +} From 92296a058aae931fd71da8c1e7aef21c7a815ccb Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 29 Mar 2023 17:12:29 -0600 Subject: [PATCH 014/775] delayed_seq uses ExecutionSequencer --- arbnode/delayed_sequencer.go | 4 ++-- execution/interface.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arbnode/delayed_sequencer.go b/arbnode/delayed_sequencer.go index 9a0cb2915..092b7d12d 100644 --- a/arbnode/delayed_sequencer.go +++ b/arbnode/delayed_sequencer.go @@ -26,7 +26,7 @@ type DelayedSequencer struct { l1Reader *headerreader.HeaderReader bridge *DelayedBridge inbox *InboxTracker - exec execution.ExecutionClient + exec execution.ExecutionSequencer coordinator *SeqCoordinator waitingForFinalizedBlock uint64 mutex sync.Mutex @@ -63,7 +63,7 @@ var TestDelayedSequencerConfig = DelayedSequencerConfig{ UseMergeFinality: true, } -func NewDelayedSequencer(l1Reader *headerreader.HeaderReader, reader *InboxReader, exec execution.ExecutionClient, coordinator *SeqCoordinator, config DelayedSequencerConfigFetcher) (*DelayedSequencer, error) { +func NewDelayedSequencer(l1Reader *headerreader.HeaderReader, reader *InboxReader, exec execution.ExecutionSequencer, coordinator *SeqCoordinator, config DelayedSequencerConfigFetcher) (*DelayedSequencer, error) { d := &DelayedSequencer{ l1Reader: l1Reader, bridge: reader.DelayedBridge(), diff --git a/execution/interface.go b/execution/interface.go index dc1551d8c..e6895bc14 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -32,8 +32,6 @@ type ExecutionClient interface { Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadata, oldMessages []*arbostypes.MessageWithMetadata) error HeadMessageNumber() (arbutil.MessageIndex, error) HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) - NextDelayedMessageNumber() (uint64, error) - SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error ResultAtPos(pos arbutil.MessageIndex) (*MessageResult, error) } @@ -54,6 +52,8 @@ type ExecutionSequencer interface { Pause() Activate() ForwardTo(url string) error + SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error + NextDelayedMessageNumber() (uint64, error) SetTransactionStreamer(streamer TransactionStreamer) } From 3f466283dfea2272ecd9610b06dad19af71aa7cb Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 30 Mar 2023 20:53:14 +0000 Subject: [PATCH 015/775] improve not saving states tests --- system_tests/recreatestate_rpc_test.go | 183 ++++++++++++++++++++----- 1 file changed, 145 insertions(+), 38 deletions(-) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index fecce5485..e0b98f652 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -15,21 +15,22 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util" "github.com/offchainlabs/nitro/util/testhelpers" ) -func prepareNode(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, dataDir string, skipBlocks uint32, skipGas uint64) (node *arbnode.Node, bc *core.BlockChain, db ethdb.Database, l2client *ethclient.Client, l2info info, cancel func(), stackDataDir string) { +func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, txCount uint64, skipBlocks uint32, skipGas uint64) (node *arbnode.Node, bc *core.BlockChain, db ethdb.Database, l2client *ethclient.Client, l2info info, l1info info, l1stack *node.Node, nodeConfig *arbnode.Config, cacheConfig *core.CacheConfig, cancel func()) { t.Helper() - nodeConfig := arbnode.ConfigDefaultL1Test() + nodeConfig = arbnode.ConfigDefaultL1Test() nodeConfig.RPC.MaxRecreateStateDepth = maxRecreateStateDepth nodeConfig.Sequencer.MaxBlockSpeed = 0 nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 - cacheConfig := &core.CacheConfig{ + cacheConfig = &core.CacheConfig{ // Arbitrum Config Options TriesInMemory: 128, TrieRetention: 30 * time.Minute, @@ -46,21 +47,11 @@ func prepareNode(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, SnapshotLimit: 256, SnapshotWait: true, } - stackConfig := getTestStackConfig(t, dataDir) - stackDataDir = stackConfig.DataDir - l2info, node, l2client, _, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, stackConfig, cacheConfig) + l2info, node, l2client, _, l1info, _, _, l1stack = createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, cacheConfig) cancel = func() { defer requireClose(t, l1stack) defer node.StopAndWait() } - bc = node.Backend.ArbInterface().BlockChain() - db = node.Backend.ChainDb() - return -} - -func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, txCount uint64, skipBlocks uint32, skipGas uint64) (node *arbnode.Node, bc *core.BlockChain, db ethdb.Database, l2client *ethclient.Client, l2info info, cancel func(), stackDataDir string) { - t.Helper() - node, bc, db, l2client, l2info, cancel, stackDataDir = prepareNode(t, ctx, maxRecreateStateDepth, "", skipBlocks, skipGas) l2info.GenerateAccount("User2") var txs []*types.Transaction for i := uint64(0); i < txCount; i++ { @@ -73,6 +64,9 @@ func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateD _, err := EnsureTxSucceeded(ctx, l2client, tx) testhelpers.RequireImpl(t, err) } + bc = node.Backend.ArbInterface().BlockChain() + db = node.Backend.ChainDb() + return } @@ -120,7 +114,7 @@ func removeStatesFromDb(t *testing.T, bc *core.BlockChain, db ethdb.Database, fr func TestRecreateStateForRPCNoDepthLimit(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, _, cancelNode, _ := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32, 0, 0) + _, bc, db, l2client, _, _, _, _, _, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -144,7 +138,7 @@ func TestRecreateStateForRPCBigEnoughDepthLimit(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() depthGasLimit := int64(256 * util.NormalizeL2GasForL1GasInitial(800_000, params.GWei)) - _, bc, db, l2client, _, cancelNode, _ := prepareNodeWithHistory(t, ctx, depthGasLimit, 32, 0, 0) + _, bc, db, l2client, _, _, _, _, _, cancelNode := prepareNodeWithHistory(t, ctx, depthGasLimit, 32, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -168,7 +162,7 @@ func TestRecreateStateForRPCDepthLimitExceeded(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() depthGasLimit := int64(200) - _, bc, db, l2client, _, cancelNode, _ := prepareNodeWithHistory(t, ctx, depthGasLimit, 32, 0, 0) + _, bc, db, l2client, _, _, _, _, _, cancelNode := prepareNodeWithHistory(t, ctx, depthGasLimit, 32, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -191,7 +185,7 @@ func TestRecreateStateForRPCMissingBlockParent(t *testing.T) { var headerCacheLimit uint64 = 512 ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, _, cancelNode, _ := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, headerCacheLimit+5, 0, 0) + _, bc, db, l2client, _, _, _, _, _, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, headerCacheLimit+5, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -224,7 +218,7 @@ func TestRecreateStateForRPCMissingBlockParent(t *testing.T) { func TestRecreateStateForRPCBeyondGenesis(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, _, cancelNode, _ := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32, 0, 0) + _, bc, db, l2client, _, _, _, _, _, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -248,7 +242,7 @@ func TestRecreateStateForRPCBlockNotFoundWhileRecreating(t *testing.T) { var blockCacheLimit uint64 = 256 ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, _, cancelNode, _ := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, blockCacheLimit+4, 0, 0) + _, bc, db, l2client, _, _, _, _, _, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, blockCacheLimit+4, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -276,46 +270,159 @@ func TestRecreateStateForRPCBlockNotFoundWhileRecreating(t *testing.T) { } } -func TestSkippingSavingStateAndRecreatingAfterRestart(t *testing.T) { - _ = testhelpers.InitTestLog(t, log.LvlTrace) +func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks uint32, skipGas uint64, txCount int) { + t.Helper() + maxRecreateStateDepth := int64(30 * 1000 * 1000) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, _, l2client, _, cancelNode, stackDataDir := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 101, 5, 0) + + ctx1, cancel1 := context.WithCancel(ctx) + nodeConfig := arbnode.ConfigDefaultL2Test() + nodeConfig.RPC.MaxRecreateStateDepth = maxRecreateStateDepth + nodeConfig.Sequencer.MaxBlockSpeed = 0 + nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 + cacheConfig := &core.CacheConfig{ + // Arbitrum Config Options + TriesInMemory: 128, + TrieRetention: 30 * time.Minute, + MaxNumberOfBlocksToSkipStateSaving: skipBlocks, + MaxAmountOfGasToSkipStateSaving: skipGas, + + // disable caching of states in BlockChain.stateCache + TrieCleanLimit: 0, + TrieDirtyLimit: 0, + + TrieDirtyDisabled: true, + + TrieTimeLimit: 5 * time.Minute, + SnapshotLimit: 256, + SnapshotWait: true, + } + + feedErrChan := make(chan error, 10) + AddDefaultValNode(t, ctx1, nodeConfig, true) + l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, nil, t.TempDir(), params.ArbitrumDevTestChainConfig(), cacheConfig) + + node, err := arbnode.CreateNode(ctx1, stack, chainDb, arbDb, nodeConfig, blockchain, nil, nil, nil, nil, feedErrChan) + Require(t, err) + err = node.TxStreamer.AddFakeInitMessage() + Require(t, err) + Require(t, node.Start(ctx1)) + client := ClientForStack(t, stack) + debugAuth := l2info.GetDefaultTransactOpts("Owner", ctx1) + // make auth a chain owner + arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) + Require(t, err, "failed to deploy ArbDebug") + tx, err := arbdebug.BecomeChainOwner(&debugAuth) + Require(t, err, "failed to deploy ArbDebug") + _, err = EnsureTxSucceeded(ctx1, client, tx) + Require(t, err) + + StartWatchChanErr(t, ctx, feedErrChan, node) + dataDir := node.Stack.DataDir() + + l2info.GenerateAccount("User2") + var txs []*types.Transaction + for i := 0; i < txCount; i++ { + tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, common.Big1, nil) + txs = append(txs, tx) + err := client.SendTransaction(ctx, tx) + testhelpers.RequireImpl(t, err) + } + for _, tx := range txs { + _, err := EnsureTxSucceeded(ctx, client, tx) + testhelpers.RequireImpl(t, err) + } + bc := node.Backend.ArbInterface().BlockChain() genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum - lastBlock, err := l2client.BlockNumber(ctx) - testhelpers.RequireImpl(t, err) - if lastBlock < genesis+100 { - testhelpers.FailImpl(t, "Internal test error - not enough blocks produced during preparation, want:", genesis+100, "have:", lastBlock) + lastBlock, err := client.BlockNumber(ctx) + Require(t, err) + if lastBlock < genesis+uint64(txCount) { + Fail(t, "internal test error - not enough blocks produced during preparation, want:", genesis+100, "have:", lastBlock) } - expectedBalance, err := l2client.BalanceAt(ctx, GetTestAddressForAccountName(t, "User2"), new(big.Int).SetUint64(lastBlock)) - testhelpers.RequireImpl(t, err) - cancelNode() - _, bc, _, l2client, _, cancelNode, _ = prepareNode(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, stackDataDir, 0, 0) - defer cancelNode() - for i := genesis + 1; i <= genesis+100; i++ { + expectedBalance, err := client.BalanceAt(ctx, GetTestAddressForAccountName(t, "User2"), new(big.Int).SetUint64(lastBlock)) + Require(t, err) + + node.StopAndWait() + cancel1() + t.Log("stopped first node") + + AddDefaultValNode(t, ctx, nodeConfig, true) + l2info, stack, chainDb, arbDb, blockchain = createL2BlockChain(t, l2info, dataDir, params.ArbitrumDevTestChainConfig(), cacheConfig) + node, err = arbnode.CreateNode(ctx, stack, chainDb, arbDb, nodeConfig, blockchain, nil, node.DeployInfo, nil, nil, feedErrChan) + Require(t, err) + Require(t, node.Start(ctx)) + client = ClientForStack(t, stack) + defer node.StopAndWait() + bc = node.Backend.ArbInterface().BlockChain() + gas := skipGas + blocks := skipBlocks + for i := genesis + 1; i <= genesis+uint64(txCount); i++ { block := bc.GetBlockByNumber(i) if block == nil { Fail(t, "header not found for block number:", i) + continue } + gas += block.GasUsed() + blocks++ _, err := bc.StateAt(block.Root()) - if (i-genesis-1)%5 == 0 { + if (skipBlocks == 0 && skipGas == 0) || (skipBlocks != 0 && blocks > skipBlocks) || (skipGas != 0 && gas > skipGas) { + if err != nil { + t.Log("blocks:", blocks, "skipBlocks:", skipBlocks, "gas:", gas, "skipGas:", skipGas) + } Require(t, err, "state not found, root:", block.Root(), "blockNumber:", i, "blockHash", block.Hash(), "err:", err) - t.Log("have state for block:", i) + gas = 0 + blocks = 0 } else { if err == nil { + t.Log("blocks:", blocks, "skipBlocks:", skipBlocks, "gas:", gas, "skipGas:", skipGas) Fail(t, "state shouldn't be available, root:", block.Root(), "blockNumber:", i, "blockHash", block.Hash()) } expectedErr := &trie.MissingNodeError{} if !errors.As(err, &expectedErr) { Fail(t, "getting state failed with unexpected error, root:", block.Root(), "blockNumber:", i, "blockHash", block.Hash()) } - t.Log("no state for block:", i) } } + for i := genesis + 1; i <= genesis+uint64(txCount); i += i % 10 { + _, err = client.BalanceAt(ctx, GetTestAddressForAccountName(t, "User2"), new(big.Int).SetUint64(i)) + testhelpers.RequireImpl(t, err) + } - balance, err := l2client.BalanceAt(ctx, GetTestAddressForAccountName(t, "User2"), new(big.Int).SetUint64(lastBlock)) + balance, err := client.BalanceAt(ctx, GetTestAddressForAccountName(t, "User2"), new(big.Int).SetUint64(lastBlock)) testhelpers.RequireImpl(t, err) if balance.Cmp(expectedBalance) != 0 { testhelpers.FailImpl(t, "unexpected balance result for last block, want: ", expectedBalance, " have: ", balance) } } + +func TestSkippingSavingStateAndRecreatingAfterRestart(t *testing.T) { + // test defaults + testSkippingSavingStateAndRecreatingAfterRestart(t, 0, 0, 512) + testSkippingSavingStateAndRecreatingAfterRestart(t, 127, 0, 512) + testSkippingSavingStateAndRecreatingAfterRestart(t, 0, 15*1000*1000, 512) + testSkippingSavingStateAndRecreatingAfterRestart(t, 127, 15*1000*1000, 512) + + // one test block ~ 925000 gas + testBlockGas := uint64(925000) + skipGasValues := []uint64{testBlockGas, 2 * testBlockGas, 3 * testBlockGas, 5 * testBlockGas, 21 * testBlockGas} + skipBlockValues := []uint32{1, 2, 3, 5, 21} + for _, skipGas := range skipGasValues { + for _, skipBlocks := range skipBlockValues[:len(skipBlockValues)-2] { + testSkippingSavingStateAndRecreatingAfterRestart(t, skipBlocks, skipGas, 21) + } + } + skipBlockValues = []uint32{1, 2, 3, 7, 19, 20, 21, 22} + for _, skipBlocks := range skipBlockValues[:len(skipBlockValues)-2] { + testSkippingSavingStateAndRecreatingAfterRestart(t, skipBlocks, 0, 21) + testSkippingSavingStateAndRecreatingAfterRestart(t, skipBlocks, testBlockGas*100, 21) + } + skipGasValues = []uint64{1, + testBlockGas - 2, testBlockGas - 1, testBlockGas, testBlockGas + 1, testBlockGas + 2, + 2*testBlockGas - 2, 2*testBlockGas - 1, 2 * testBlockGas, 2*testBlockGas + 1, + 7 * testBlockGas, 21 * testBlockGas} + for _, skipGas := range skipGasValues { + testSkippingSavingStateAndRecreatingAfterRestart(t, 0, skipGas, 21) + testSkippingSavingStateAndRecreatingAfterRestart(t, 100, skipGas, 21) + } +} From 4cbf2eb7d820c3a719a5d35bd0d5946f505ae5c7 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 11 Apr 2023 13:28:14 +0000 Subject: [PATCH 016/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index b884ded52..c90d53074 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit b884ded52258c18eb4bcaf89b0d41fc3c91b30fe +Subproject commit c90d53074f5e57fd39a70994c4143bf3b2496946 From 9d7f0887240a507682017491a63b44b7a8be6b71 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 11 Apr 2023 13:40:54 +0000 Subject: [PATCH 017/775] fix test failure message --- system_tests/recreatestate_rpc_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index e0b98f652..8bc0a083e 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -337,8 +337,8 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks u genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum lastBlock, err := client.BlockNumber(ctx) Require(t, err) - if lastBlock < genesis+uint64(txCount) { - Fail(t, "internal test error - not enough blocks produced during preparation, want:", genesis+100, "have:", lastBlock) + if want := genesis + uint64(txCount); lastBlock < want { + Fail(t, "internal test error - not enough blocks produced during preparation, want:", want, "have:", lastBlock) } expectedBalance, err := client.BalanceAt(ctx, GetTestAddressForAccountName(t, "User2"), new(big.Int).SetUint64(lastBlock)) Require(t, err) From 6c332b274bc9e23c2fe1d9e337b7cf52286f91c5 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 18 Apr 2023 23:07:09 -0600 Subject: [PATCH 018/775] sync_monitor: remove blockNum It will be back from execNode's sync_monitor --- arbnode/sync_monitor.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/arbnode/sync_monitor.go b/arbnode/sync_monitor.go index 22d2a47e3..bd9b24529 100644 --- a/arbnode/sync_monitor.go +++ b/arbnode/sync_monitor.go @@ -73,8 +73,6 @@ func (s *SyncMonitor) SyncProgressMap() map[string]interface{} { syncing = true builtMessageCount = 0 } else { - blockNum := s.txStreamer.exec.MessageIndexToBlockNumber(builtMessageCount) - res["blockNum"] = blockNum builtMessageCount++ res["messageOfLastBlock"] = builtMessageCount } From 7678cd7456ef6325d6d2c20bf04133185754b3cb Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 19 Apr 2023 15:06:25 -0600 Subject: [PATCH 019/775] execnode L1 reader --- execution/gethexec/node.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 0625c21ed..af0541cfc 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -116,6 +116,7 @@ type ExecutionNode struct { Sequencer *Sequencer // either nil or same as TxPublisher TxPublisher TransactionPublisher ConfigFetcher ConfigFetcher + L1Reader *headerreader.HeaderReader } func CreateExecutionNode( @@ -219,6 +220,7 @@ func CreateExecutionNode( sequencer, txPublisher, configFetcher, + l1Reader, }, nil } @@ -251,10 +253,9 @@ func (n *ExecutionNode) Start(ctx context.Context) error { if err != nil { return fmt.Errorf("error starting transaction puiblisher: %w", err) } - // TODO after separation - // if n.L1Reader != nil { - // n.L1Reader.Start(ctx) - // } + if n.L1Reader != nil { + n.L1Reader.Start(ctx) + } return nil } @@ -265,10 +266,9 @@ func (n *ExecutionNode) StopAndWait() { n.TxPublisher.StopAndWait() } n.Recorder.OrderlyShutdown() - // TODO after separation - // if n.L1Reader != nil && n.L1Reader.Started() { - // n.L1Reader.StopAndWait() - // } + if n.L1Reader != nil && n.L1Reader.Started() { + n.L1Reader.StopAndWait() + } if n.ExecEngine.Started() { n.ExecEngine.StopAndWait() } From a6aeffa7501bd69d8fe0c95a90a6cb467cb07303 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 19 Apr 2023 15:07:40 -0600 Subject: [PATCH 020/775] fix merge errors --- cmd/nitro/init.go | 5 ++-- cmd/nitro/nitro.go | 2 +- system_tests/conditionaltx_test.go | 48 ++++++++++++++++-------------- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 5bcfe66f6..891e4d5cb 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -28,7 +28,6 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/arbos/arbosState" "github.com/offchainlabs/nitro/arbutil" @@ -242,7 +241,7 @@ var hashListRegex = regexp.MustCompile("^(0x)?[0-9a-fA-F]{64}(,(0x)?[0-9a-fA-F]{ // Finds important roots to retain while proving func findImportantRoots(ctx context.Context, chainDb ethdb.Database, stack *node.Node, nodeConfig *NodeConfig, cacheConfig *core.CacheConfig, l1Client arbutil.L1Interface, rollupAddrs arbnode.RollupAddresses) ([]common.Hash, error) { initConfig := &nodeConfig.Init - chainConfig := execution.TryReadStoredChainConfig(chainDb) + chainConfig := gethexec.TryReadStoredChainConfig(chainDb) if chainConfig == nil { return nil, errors.New("database doesn't have a chain config (was this node initialized?)") } @@ -423,7 +422,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if err != nil { return chainDb, nil, fmt.Errorf("error pruning: %w", err) } - l2BlockChain, err := execution.GetBlockChain(chainDb, cacheConfig, chainConfig, config.Execution.TxLookupLimit) + l2BlockChain, err := gethexec.GetBlockChain(chainDb, cacheConfig, chainConfig, config.Execution.TxLookupLimit) if err != nil { return chainDb, nil, err } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 31c1f7326..99da4606b 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -386,7 +386,7 @@ func mainImpl() int { } } - chainDb, l2BlockChain, err := openInitializeChainDb(ctx, stack, nodeConfig, new(big.Int).SetUint64(nodeConfig.L2.ChainID), gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Node.Caching), l1Client, rollupAddrs) + chainDb, l2BlockChain, err := openInitializeChainDb(ctx, stack, nodeConfig, new(big.Int).SetUint64(nodeConfig.L2.ChainID), gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching), l1Client, rollupAddrs) defer closeDb(chainDb, "chainDb") if l2BlockChain != nil { // Calling Stop on the blockchain multiple times does nothing diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index 9204c8324..7364581bd 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -20,22 +20,21 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rpc" - "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/arbnode/execution" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/solgen/go/mocksgen" ) -func getStorageRootHash(t *testing.T, node *arbnode.Node, address common.Address) common.Hash { +func getStorageRootHash(t *testing.T, execNode *gethexec.ExecutionNode, address common.Address) common.Hash { t.Helper() - statedb, err := node.Execution.Backend.ArbInterface().BlockChain().State() + statedb, err := execNode.Backend.ArbInterface().BlockChain().State() Require(t, err) trie := statedb.StorageTrie(address) return trie.Hash() } -func getStorageSlotValue(t *testing.T, node *arbnode.Node, address common.Address) map[common.Hash]common.Hash { +func getStorageSlotValue(t *testing.T, execNode *gethexec.ExecutionNode, address common.Address) map[common.Hash]common.Hash { t.Helper() - statedb, err := node.Execution.Backend.ArbInterface().BlockChain().State() + statedb, err := execNode.Backend.ArbInterface().BlockChain().State() Require(t, err) slotValue := make(map[common.Hash]common.Hash) Require(t, err) @@ -206,6 +205,7 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { defer requireClose(t, l1stack) defer node.StopAndWait() + execNode := getExecNode(t, node) auth := l2info.GetDefaultTransactOpts("Owner", ctx) contractAddress1, simple1 := deploySimple(t, ctx, auth, l2client) tx, err := simple1.Increment(&auth) @@ -222,10 +222,10 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) - currentRootHash1 := getStorageRootHash(t, node, contractAddress1) - currentSlotValueMap1 := getStorageSlotValue(t, node, contractAddress1) - currentRootHash2 := getStorageRootHash(t, node, contractAddress2) - currentSlotValueMap2 := getStorageSlotValue(t, node, contractAddress2) + currentRootHash1 := getStorageRootHash(t, execNode, contractAddress1) + currentSlotValueMap1 := getStorageSlotValue(t, execNode, contractAddress1) + currentRootHash2 := getStorageRootHash(t, execNode, contractAddress2) + currentSlotValueMap2 := getStorageSlotValue(t, execNode, contractAddress2) rpcClient, err := node.Stack.Attach() Require(t, err) @@ -261,18 +261,18 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { Require(t, err) previousStorageRootHash1 := currentRootHash1 - currentRootHash1 = getStorageRootHash(t, node, contractAddress1) + currentRootHash1 = getStorageRootHash(t, execNode, contractAddress1) if bytes.Equal(previousStorageRootHash1.Bytes(), currentRootHash1.Bytes()) { Fail(t, "storage root hash didn't change as expected") } - currentSlotValueMap1 = getStorageSlotValue(t, node, contractAddress1) + currentSlotValueMap1 = getStorageSlotValue(t, execNode, contractAddress1) previousStorageRootHash2 := currentRootHash2 - currentRootHash2 = getStorageRootHash(t, node, contractAddress2) + currentRootHash2 = getStorageRootHash(t, execNode, contractAddress2) if bytes.Equal(previousStorageRootHash2.Bytes(), currentRootHash2.Bytes()) { Fail(t, "storage root hash didn't change as expected") } - currentSlotValueMap2 = getStorageSlotValue(t, node, contractAddress2) + currentSlotValueMap2 = getStorageSlotValue(t, execNode, contractAddress2) block, err = l1client.BlockByNumber(ctx, nil) Require(t, err) @@ -366,7 +366,8 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { } cancelCtxWithTimeout() wg.Wait() - bc := node.Execution.Backend.ArbInterface().BlockChain() + execNode := getExecNode(t, node) + bc := execNode.Backend.ArbInterface().BlockChain() genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum var receipts types.Receipts @@ -402,17 +403,18 @@ func TestSendRawTransactionConditionalPreCheck(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - nodeConfig := arbnode.ConfigDefaultL1Test() - nodeConfig.Sequencer.MaxBlockSpeed = 0 - nodeConfig.TxPreChecker.Strictness = execution.TxPreCheckerStrictnessLikelyCompatible - nodeConfig.TxPreChecker.RequiredStateAge = 1 - nodeConfig.TxPreChecker.RequiredStateMaxBlocks = 2 + execConfig := gethexec.ConfigDefaultTest() + execConfig.Sequencer.MaxBlockSpeed = 0 + execConfig.TxPreChecker.Strictness = gethexec.TxPreCheckerStrictnessLikelyCompatible + execConfig.TxPreChecker.RequiredStateAge = 1 + execConfig.TxPreChecker.RequiredStateMaxBlocks = 2 - l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, nil) + l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, execConfig, nil, nil) defer requireClose(t, l1stack) defer node.StopAndWait() rpcClient, err := node.Stack.Attach() Require(t, err) + execNode := getExecNode(t, node) l2info.GenerateAccount("User2") @@ -427,7 +429,7 @@ func TestSendRawTransactionConditionalPreCheck(t *testing.T) { Require(t, err, "failed to call Increment()") _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) - currentRootHash := getStorageRootHash(t, node, contractAddress) + currentRootHash := getStorageRootHash(t, execNode, contractAddress) options := &arbitrum_types.ConditionalOptions{ KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{ contractAddress: {RootHash: ¤tRootHash}, @@ -446,7 +448,7 @@ func TestSendRawTransactionConditionalPreCheck(t *testing.T) { Require(t, err, "failed to call Increment()") _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) - currentRootHash = getStorageRootHash(t, node, contractAddress) + currentRootHash = getStorageRootHash(t, execNode, contractAddress) options = &arbitrum_types.ConditionalOptions{ KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{ contractAddress: {RootHash: ¤tRootHash}, From f28de1a2419aa7878cca725cdf638be944ab4750 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Sun, 30 Apr 2023 13:37:23 -0600 Subject: [PATCH 021/775] fix merge problems --- arbnode/node.go | 2 ++ system_tests/batch_poster_test.go | 5 +++-- system_tests/debugapi_test.go | 2 +- system_tests/staker_test.go | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 9cb8c33ef..f68eff96c 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -470,6 +470,8 @@ func ConfigDefaultL1Test() *Config { config.DelayedSequencer = TestDelayedSequencerConfig config.BatchPoster = TestBatchPosterConfig config.SeqCoordinator = TestSeqCoordinatorConfig + config.Sequencer = true + config.Dangerous.NoCoordinator = true return config } diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 863f7ab04..fa33a0deb 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -175,8 +175,9 @@ func TestBatchPosterKeepsUp(t *testing.T) { conf := arbnode.ConfigDefaultL1Test() conf.BatchPoster.CompressionLevel = brotli.BestCompression conf.BatchPoster.MaxBatchPostDelay = time.Hour - conf.RPC.RPCTxFeeCap = 1000. - l2info, nodeA, l2clientA, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil) + execConf := gethexec.ConfigDefaultTest() + execConf.RPC.RPCTxFeeCap = 1000. + l2info, nodeA, l2clientA, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, execConf, nil, nil) defer requireClose(t, l1stack) defer nodeA.StopAndWait() l2info.GasPrice = big.NewInt(100e9) diff --git a/system_tests/debugapi_test.go b/system_tests/debugapi_test.go index 03e3dfd40..ff28e2350 100644 --- a/system_tests/debugapi_test.go +++ b/system_tests/debugapi_test.go @@ -14,7 +14,7 @@ import ( func TestDebugAPI(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, nil, nil) + _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, nil, nil, nil) defer requireClose(t, l1stack) defer requireClose(t, l2stack) diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 47cc19f69..bf89f5feb 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -76,7 +76,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) types.NewArbitrumSigner(types.NewLondonSigner(l2chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), transferGas, ) - _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, l2chainConfig, nil, l2info) + _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, l2chainConfig, nil, l2info) defer requireClose(t, l1stack) defer l2nodeA.StopAndWait() execNodeA := getExecNode(t, l2nodeA) From 85d6480bb3866c85ef79e825c2313f12ec42193d Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 10 May 2023 20:01:24 -0600 Subject: [PATCH 022/775] update headerreader API --- cmd/nitro/nitro.go | 1 + execution/gethexec/node.go | 6 +++++- system_tests/common_test.go | 6 +++--- system_tests/das_test.go | 6 +++--- system_tests/full_challenge_impl_test.go | 4 ++-- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 2b46bb183..5e55d153a 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -465,6 +465,7 @@ func mainImpl() int { } execNode, err := gethexec.CreateExecutionNode( + ctx, stack, chainDb, l2BlockChain, diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index af0541cfc..e6ec68ed3 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -120,6 +120,7 @@ type ExecutionNode struct { } func CreateExecutionNode( + ctx context.Context, stack *node.Node, chainDB ethdb.Database, l2BlockChain *core.BlockChain, @@ -137,7 +138,10 @@ func CreateExecutionNode( var l1Reader *headerreader.HeaderReader if l1client != nil { - l1Reader = headerreader.New(l1client, func() *headerreader.Config { return &configFetcher().L1Reader }) + l1Reader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher().L1Reader }) + if err != nil { + return nil, err + } } fwTarget := config.ForwardingTarget() diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 8c030c5e7..8fb396e3d 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -568,7 +568,7 @@ func createTestNodeOnL1WithConfigImpl( Require(t, execConfig.Validate()) execConfigFetcher := func() *gethexec.Config { return execConfig } - execNode, err := gethexec.CreateExecutionNode(l2stack, l2chainDb, l2blockchain, l1client, execConfigFetcher) + execNode, err := gethexec.CreateExecutionNode(ctx, l2stack, l2chainDb, l2blockchain, l1client, execConfigFetcher) Require(t, err) currentNode, err = arbnode.CreateNode( @@ -610,7 +610,7 @@ func CreateTestL2WithConfig( Require(t, execConfig.Validate()) execConfigFetcher := func() *gethexec.Config { return execConfig } - execNode, err := gethexec.CreateExecutionNode(stack, chainDb, blockchain, nil, execConfigFetcher) + execNode, err := gethexec.CreateExecutionNode(ctx, stack, chainDb, blockchain, nil, execConfigFetcher) Require(t, err) currentNode, err := arbnode.CreateNode(ctx, stack, execNode, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), nil, nil, nil, nil, feedErrChan) @@ -731,7 +731,7 @@ func Create2ndNodeWithConfig( AddDefaultValNode(t, ctx, nodeConfig, true) configFetcher := func() *gethexec.Config { return execConfig } - currentExec, err := gethexec.CreateExecutionNode(l2stack, l2chainDb, l2blockchain, l1client, configFetcher) + currentExec, err := gethexec.CreateExecutionNode(ctx, l2stack, l2chainDb, l2blockchain, l1client, configFetcher) Require(t, err) currentNode, err := arbnode.CreateNode(ctx, l2stack, currentExec, l2arbDb, NewFetcherFromConfig(nodeConfig), l2blockchain.Config(), l1client, first.DeployInfo, &txOpts, dataSigner, feedErrChan) diff --git a/system_tests/das_test.go b/system_tests/das_test.go index 125937239..aaa3bfffb 100644 --- a/system_tests/das_test.go +++ b/system_tests/das_test.go @@ -137,7 +137,7 @@ func TestDASRekey(t *testing.T) { l1NodeConfigA.DataAvailability.RestfulClientAggregatorConfig.Enable = true l1NodeConfigA.DataAvailability.RestfulClientAggregatorConfig.Urls = []string{restServerUrlA} l1NodeConfigA.DataAvailability.L1NodeURL = "none" - execA, err := gethexec.CreateExecutionNode(l2stackA, l2chainDb, l2blockchain, l1client, gethexec.ConfigDefaultTest) + execA, err := gethexec.CreateExecutionNode(ctx, l2stackA, l2chainDb, l2blockchain, l1client, gethexec.ConfigDefaultTest) Require(t, err) nodeA, err := arbnode.CreateNode(ctx, l2stackA, execA, l2arbDb, NewFetcherFromConfig(l1NodeConfigA), l2blockchain.Config(), l1client, addresses, sequencerTxOptsPtr, nil, feedErrChan) @@ -182,7 +182,7 @@ func TestDASRekey(t *testing.T) { l2blockchain, err := gethexec.GetBlockChain(l2chainDb, nil, chainConfig, gethexec.ConfigDefaultTest().TxLookupLimit) Require(t, err) - execA, err := gethexec.CreateExecutionNode(l2stackA, l2chainDb, l2blockchain, l1client, gethexec.ConfigDefaultTest) + execA, err := gethexec.CreateExecutionNode(ctx, l2stackA, l2chainDb, l2blockchain, l1client, gethexec.ConfigDefaultTest) Require(t, err) l1NodeConfigA.DataAvailability.AggregatorConfig = aggConfigForBackend(t, backendConfigB) @@ -313,7 +313,7 @@ func TestDASComplexConfigAndRestMirror(t *testing.T) { l2info, l2stackA, l2chainDb, l2arbDb, l2blockchain := createL2BlockChain(t, nil, "", chainConfig) l2info.GenerateAccount("User2") - execA, err := gethexec.CreateExecutionNode(l2stackA, l2chainDb, l2blockchain, l1client, gethexec.ConfigDefaultTest) + execA, err := gethexec.CreateExecutionNode(ctx, l2stackA, l2chainDb, l2blockchain, l1client, gethexec.ConfigDefaultTest) Require(t, err) sequencerTxOpts := l1info.GetDefaultTransactOpts("Sequencer", ctx) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index f946a8a9c..bcd8c3ffc 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -271,7 +271,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall asserterL2Info, asserterL2Stack, asserterL2ChainDb, asserterL2ArbDb, asserterL2Blockchain := createL2BlockChain(t, nil, "", chainConfig) asserterRollupAddresses.Bridge = asserterBridgeAddr asserterRollupAddresses.SequencerInbox = asserterSeqInboxAddr - asserterExec, err := gethexec.CreateExecutionNode(asserterL2Stack, asserterL2ChainDb, asserterL2Blockchain, l1Backend, gethexec.ConfigDefaultTest) + asserterExec, err := gethexec.CreateExecutionNode(ctx, asserterL2Stack, asserterL2ChainDb, asserterL2Blockchain, l1Backend, gethexec.ConfigDefaultTest) Require(t, err) asserterL2, err := arbnode.CreateNode(ctx, asserterL2Stack, asserterExec, asserterL2ArbDb, NewFetcherFromConfig(conf), chainConfig, l1Backend, asserterRollupAddresses, nil, nil, fatalErrChan) Require(t, err) @@ -282,7 +282,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall challengerRollupAddresses := *asserterRollupAddresses challengerRollupAddresses.Bridge = challengerBridgeAddr challengerRollupAddresses.SequencerInbox = challengerSeqInboxAddr - challengerExec, err := gethexec.CreateExecutionNode(challengerL2Stack, challengerL2ChainDb, challengerL2Blockchain, l1Backend, gethexec.ConfigDefaultTest) + challengerExec, err := gethexec.CreateExecutionNode(ctx, challengerL2Stack, challengerL2ChainDb, challengerL2Blockchain, l1Backend, gethexec.ConfigDefaultTest) Require(t, err) challengerL2, err := arbnode.CreateNode(ctx, challengerL2Stack, challengerExec, challengerL2ArbDb, NewFetcherFromConfig(conf), chainConfig, l1Backend, &challengerRollupAddresses, nil, nil, fatalErrChan) Require(t, err) From 20c3e8d5be7de479f19df3c9b040aa58f7de3f82 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 11 May 2023 10:45:33 -0600 Subject: [PATCH 023/775] Use sequencer inbox isSequencer to verify feed signatures --- arbnode/node.go | 4 +- arbnode/seq_coordinator.go | 2 +- broadcastclient/broadcastclient.go | 4 +- broadcastclient/broadcastclient_test.go | 6 +-- broadcastclients/broadcastclients.go | 4 +- contracts | 2 +- das/aggregator.go | 14 +++--- das/sign_after_store_das_writer.go | 14 +++--- ...poster_verifier.go => address_verifier.go} | 44 +++++++++++-------- util/signature/sign_verify.go | 2 +- util/signature/verifier.go | 16 +++---- util/signature/verifier_test.go | 2 +- 12 files changed, 61 insertions(+), 53 deletions(-) rename util/contracts/{batch_poster_verifier.go => address_verifier.go} (54%) diff --git a/arbnode/node.go b/arbnode/node.go index 32b227058..1a0277d58 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -710,7 +710,7 @@ func createNodeImpl( return nil, err } var coordinator *SeqCoordinator - var bpVerifier *contracts.BatchPosterVerifier + var bpVerifier *contracts.AddressVerifier if deployInfo != nil && l1client != nil { sequencerInboxAddr := deployInfo.SequencerInbox @@ -718,7 +718,7 @@ func createNodeImpl( if err != nil { return nil, err } - bpVerifier = contracts.NewBatchPosterVerifier(seqInboxCaller) + bpVerifier = contracts.NewAddressVerifier(seqInboxCaller) } if config.SeqCoordinator.Enable { diff --git a/arbnode/seq_coordinator.go b/arbnode/seq_coordinator.go index dc5cb03a4..1320226b4 100644 --- a/arbnode/seq_coordinator.go +++ b/arbnode/seq_coordinator.go @@ -132,7 +132,7 @@ var TestSeqCoordinatorConfig = SeqCoordinatorConfig{ Signing: signature.DefaultSignVerifyConfig, } -func NewSeqCoordinator(dataSigner signature.DataSignerFunc, bpvalidator *contracts.BatchPosterVerifier, streamer *TransactionStreamer, sequencer *execution.Sequencer, sync *SyncMonitor, config SeqCoordinatorConfig) (*SeqCoordinator, error) { +func NewSeqCoordinator(dataSigner signature.DataSignerFunc, bpvalidator *contracts.AddressVerifier, streamer *TransactionStreamer, sequencer *execution.Sequencer, sync *SyncMonitor, config SeqCoordinatorConfig) (*SeqCoordinator, error) { redisCoordinator, err := redisutil.NewRedisCoordinator(config.RedisUrl) if err != nil { return nil, err diff --git a/broadcastclient/broadcastclient.go b/broadcastclient/broadcastclient.go index fc9b268d1..2cb03250f 100644 --- a/broadcastclient/broadcastclient.go +++ b/broadcastclient/broadcastclient.go @@ -152,10 +152,10 @@ func NewBroadcastClient( txStreamer TransactionStreamerInterface, confirmedSequencerNumberListener chan arbutil.MessageIndex, fatalErrChan chan error, - bpVerifier contracts.BatchPosterVerifierInterface, + addrVerifier contracts.AddressVerifierInterface, adjustCount func(int32), ) (*BroadcastClient, error) { - sigVerifier, err := signature.NewVerifier(&config().Verifier, bpVerifier) + sigVerifier, err := signature.NewVerifier(&config().Verifier, addrVerifier) if err != nil { return nil, err } diff --git a/broadcastclient/broadcastclient_test.go b/broadcastclient/broadcastclient_test.go index 871d9d8d8..65fa86782 100644 --- a/broadcastclient/broadcastclient_test.go +++ b/broadcastclient/broadcastclient_test.go @@ -200,14 +200,14 @@ func (ts *dummyTransactionStreamer) AddBroadcastMessages(feedMessages []*broadca func newTestBroadcastClient(config Config, listenerAddress net.Addr, chainId uint64, currentMessageCount arbutil.MessageIndex, txStreamer TransactionStreamerInterface, confirmedSequenceNumberListener chan arbutil.MessageIndex, feedErrChan chan error, validAddr *common.Address) (*BroadcastClient, error) { port := listenerAddress.(*net.TCPAddr).Port - var bpv contracts.BatchPosterVerifierInterface + var av contracts.AddressVerifierInterface if validAddr != nil { config.Verifier.AcceptSequencer = true - bpv = contracts.NewMockBatchPosterVerifier(*validAddr) + av = contracts.NewMockAddressVerifier(*validAddr) } else { config.Verifier.AcceptSequencer = false } - return NewBroadcastClient(func() *Config { return &config }, fmt.Sprintf("ws://127.0.0.1:%d/", port), chainId, currentMessageCount, txStreamer, confirmedSequenceNumberListener, feedErrChan, bpv, func(_ int32) {}) + return NewBroadcastClient(func() *Config { return &config }, fmt.Sprintf("ws://127.0.0.1:%d/", port), chainId, currentMessageCount, txStreamer, confirmedSequenceNumberListener, feedErrChan, av, func(_ int32) {}) } func startMakeBroadcastClient(ctx context.Context, t *testing.T, clientConfig Config, addr net.Addr, index int, expectedCount int, chainId uint64, wg *sync.WaitGroup, sequencerAddr *common.Address) { diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index baf7cf639..72e8e0a40 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -28,7 +28,7 @@ func NewBroadcastClients( txStreamer broadcastclient.TransactionStreamerInterface, confirmedSequenceNumberListener chan arbutil.MessageIndex, fatalErrChan chan error, - bpVerifier contracts.BatchPosterVerifierInterface, + addrVerifier contracts.AddressVerifierInterface, ) (*BroadcastClients, error) { config := configFetcher() urlCount := len(config.URLs) @@ -48,7 +48,7 @@ func NewBroadcastClients( txStreamer, confirmedSequenceNumberListener, fatalErrChan, - bpVerifier, + addrVerifier, func(delta int32) { clients.adjustCount(delta) }, ) if err != nil { diff --git a/contracts b/contracts index a68783436..8ec95252c 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit a68783436b5105a64f54efe5fbd55174704a7618 +Subproject commit 8ec95252ca044ff8cfbf3d90929d756c113b9661 diff --git a/das/aggregator.go b/das/aggregator.go index 7c1504d6f..0d002217a 100644 --- a/das/aggregator.go +++ b/das/aggregator.go @@ -60,7 +60,7 @@ type Aggregator struct { maxAllowedServiceStoreFailures int keysetHash [32]byte keysetBytes []byte - bpVerifier *contracts.BatchPosterVerifier + addrVerifier *contracts.AddressVerifier } type ServiceDetails struct { @@ -153,9 +153,9 @@ func NewAggregatorWithSeqInboxCaller( os.Exit(0) } - var bpVerifier *contracts.BatchPosterVerifier + var addrVerifier *contracts.AddressVerifier if seqInboxCaller != nil { - bpVerifier = contracts.NewBatchPosterVerifier(seqInboxCaller) + addrVerifier = contracts.NewAddressVerifier(seqInboxCaller) } return &Aggregator{ @@ -166,7 +166,7 @@ func NewAggregatorWithSeqInboxCaller( maxAllowedServiceStoreFailures: config.AggregatorConfig.AssumedHonest - 1, keysetHash: keysetHash, keysetBytes: ksBuf.Bytes(), - bpVerifier: bpVerifier, + addrVerifier: addrVerifier, }, nil } @@ -196,16 +196,16 @@ type storeResponse struct { // signature is not checked, which is useful for testing. func (a *Aggregator) Store(ctx context.Context, message []byte, timeout uint64, sig []byte) (*arbstate.DataAvailabilityCertificate, error) { log.Trace("das.Aggregator.Store", "message", pretty.FirstFewBytes(message), "timeout", time.Unix(int64(timeout), 0), "sig", pretty.FirstFewBytes(sig)) - if a.bpVerifier != nil { + if a.addrVerifier != nil { actualSigner, err := DasRecoverSigner(message, timeout, sig) if err != nil { return nil, err } - isBatchPoster, err := a.bpVerifier.IsBatchPoster(ctx, actualSigner) + isBatchPosterOrSequencer, err := a.addrVerifier.IsBatchPosterOrSequencer(ctx, actualSigner) if err != nil { return nil, err } - if !isBatchPoster { + if !isBatchPosterOrSequencer { return nil, errors.New("store request not properly signed") } } diff --git a/das/sign_after_store_das_writer.go b/das/sign_after_store_das_writer.go index 6d62ea42b..5bf78955a 100644 --- a/das/sign_after_store_das_writer.go +++ b/das/sign_after_store_das_writer.go @@ -78,7 +78,7 @@ type SignAfterStoreDASWriter struct { keysetHash [32]byte keysetBytes []byte storageService StorageService - bpVerifier *contracts.BatchPosterVerifier + addrVerifier *contracts.AddressVerifier // Extra batch poster verifier, for local installations to have their // own way of testing Stores. @@ -136,9 +136,9 @@ func NewSignAfterStoreDASWriterWithSeqInboxCaller( return nil, err } - var bpVerifier *contracts.BatchPosterVerifier + var addrVerifier *contracts.AddressVerifier if seqInboxCaller != nil { - bpVerifier = contracts.NewBatchPosterVerifier(seqInboxCaller) + addrVerifier = contracts.NewAddressVerifier(seqInboxCaller) } var extraBpVerifier func(message []byte, timeout uint64, sig []byte) bool @@ -174,7 +174,7 @@ func NewSignAfterStoreDASWriterWithSeqInboxCaller( keysetHash: ksHash, keysetBytes: ksBuf.Bytes(), storageService: storageService, - bpVerifier: bpVerifier, + addrVerifier: addrVerifier, extraBpVerifier: extraBpVerifier, }, nil } @@ -188,16 +188,16 @@ func (d *SignAfterStoreDASWriter) Store( verified = d.extraBpVerifier(message, timeout, sig) } - if !verified && d.bpVerifier != nil { + if !verified && d.addrVerifier != nil { actualSigner, err := DasRecoverSigner(message, timeout, sig) if err != nil { return nil, err } - isBatchPoster, err := d.bpVerifier.IsBatchPoster(ctx, actualSigner) + isBatchPosterOrSequencer, err := d.addrVerifier.IsBatchPosterOrSequencer(ctx, actualSigner) if err != nil { return nil, err } - if !isBatchPoster { + if !isBatchPosterOrSequencer { return nil, errors.New("store request not properly signed") } } diff --git a/util/contracts/batch_poster_verifier.go b/util/contracts/address_verifier.go similarity index 54% rename from util/contracts/batch_poster_verifier.go rename to util/contracts/address_verifier.go index da9354ed3..f2ccb5d69 100644 --- a/util/contracts/batch_poster_verifier.go +++ b/util/contracts/address_verifier.go @@ -13,7 +13,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/bridgegen" ) -type BatchPosterVerifier struct { +type AddressVerifier struct { seqInboxCaller *bridgegen.SequencerInboxCaller cache map[common.Address]bool cacheExpiry time.Time @@ -24,17 +24,17 @@ type BatchPosterVerifier struct { // consequences of a false positive (accepting a Store from a recently retired batch poster), but we don't want // to accept the consequences of a false negative (rejecting a Store from a recently added batch poster). -var batchPosterVerifierLifetime = time.Hour +var addressVerifierLifetime = time.Hour -func NewBatchPosterVerifier(seqInboxCaller *bridgegen.SequencerInboxCaller) *BatchPosterVerifier { - return &BatchPosterVerifier{ +func NewAddressVerifier(seqInboxCaller *bridgegen.SequencerInboxCaller) *AddressVerifier { + return &AddressVerifier{ seqInboxCaller: seqInboxCaller, cache: make(map[common.Address]bool), - cacheExpiry: time.Now().Add(batchPosterVerifierLifetime), + cacheExpiry: time.Now().Add(addressVerifierLifetime), } } -func (bpv *BatchPosterVerifier) IsBatchPoster(ctx context.Context, addr common.Address) (bool, error) { +func (bpv *AddressVerifier) IsBatchPosterOrSequencer(ctx context.Context, addr common.Address) (bool, error) { bpv.mutex.Lock() if time.Now().After(bpv.cacheExpiry) { if err := bpv.flushCache_locked(ctx); err != nil { @@ -48,44 +48,52 @@ func (bpv *BatchPosterVerifier) IsBatchPoster(ctx context.Context, addr common.A } bpv.mutex.Unlock() - isBatchPoster, err := bpv.seqInboxCaller.IsBatchPoster(&bind.CallOpts{Context: ctx}, addr) + result, err := bpv.seqInboxCaller.IsBatchPoster(&bind.CallOpts{Context: ctx}, addr) if err != nil { return false, err } - if isBatchPoster { + if !result { + var err error + result, err = bpv.seqInboxCaller.IsSequencer(&bind.CallOpts{Context: ctx}, addr) + if err != nil { + return false, err + } + } + if result { bpv.mutex.Lock() bpv.cache[addr] = true bpv.mutex.Unlock() + return true, nil } - return isBatchPoster, nil + return result, nil } -func (bpv *BatchPosterVerifier) FlushCache(ctx context.Context) error { +func (bpv *AddressVerifier) FlushCache(ctx context.Context) error { bpv.mutex.Lock() defer bpv.mutex.Unlock() return bpv.flushCache_locked(ctx) } -func (bpv *BatchPosterVerifier) flushCache_locked(ctx context.Context) error { +func (bpv *AddressVerifier) flushCache_locked(ctx context.Context) error { bpv.cache = make(map[common.Address]bool) - bpv.cacheExpiry = time.Now().Add(batchPosterVerifierLifetime) + bpv.cacheExpiry = time.Now().Add(addressVerifierLifetime) return nil } -func NewMockBatchPosterVerifier(validAddr common.Address) *MockBatchPosterVerifier { - return &MockBatchPosterVerifier{ +func NewMockAddressVerifier(validAddr common.Address) *MockAddressVerifier { + return &MockAddressVerifier{ validAddr: validAddr, } } -type MockBatchPosterVerifier struct { +type MockAddressVerifier struct { validAddr common.Address } -func (bpv *MockBatchPosterVerifier) IsBatchPoster(_ context.Context, addr common.Address) (bool, error) { +func (bpv *MockAddressVerifier) IsBatchPosterOrSequencer(_ context.Context, addr common.Address) (bool, error) { return addr == bpv.validAddr, nil } -type BatchPosterVerifierInterface interface { - IsBatchPoster(ctx context.Context, addr common.Address) (bool, error) +type AddressVerifierInterface interface { + IsBatchPosterOrSequencer(ctx context.Context, addr common.Address) (bool, error) } diff --git a/util/signature/sign_verify.go b/util/signature/sign_verify.go index 9a594ccbe..291191297 100644 --- a/util/signature/sign_verify.go +++ b/util/signature/sign_verify.go @@ -39,7 +39,7 @@ var DefaultSignVerifyConfig = SignVerifyConfig{ Symmetric: TestSimpleHmacConfig, } -func NewSignVerify(config *SignVerifyConfig, signerFunc DataSignerFunc, bpValidator contracts.BatchPosterVerifierInterface) (*SignVerify, error) { +func NewSignVerify(config *SignVerifyConfig, signerFunc DataSignerFunc, bpValidator contracts.AddressVerifierInterface) (*SignVerify, error) { var fallback *SimpleHmac if config.SymmetricFallback { var err error diff --git a/util/signature/verifier.go b/util/signature/verifier.go index fb0aae9e1..2bf5b854e 100644 --- a/util/signature/verifier.go +++ b/util/signature/verifier.go @@ -19,7 +19,7 @@ import ( type Verifier struct { config *VerifierConfig authorizedMap map[common.Address]struct{} - bpValidator contracts.BatchPosterVerifierInterface + addrVerifier contracts.AddressVerifierInterface } type VerifierConfig struct { @@ -62,19 +62,19 @@ var TestingFeedVerifierConfig = VerifierConfig{ }, } -func NewVerifier(config *VerifierConfig, bpValidator contracts.BatchPosterVerifierInterface) (*Verifier, error) { +func NewVerifier(config *VerifierConfig, addrVerifier contracts.AddressVerifierInterface) (*Verifier, error) { authorizedMap := make(map[common.Address]struct{}, len(config.AllowedAddresses)) for _, addrString := range config.AllowedAddresses { addr := common.HexToAddress(addrString) authorizedMap[addr] = struct{}{} } - if bpValidator == nil && !config.Dangerous.AcceptMissing && config.AcceptSequencer { + if addrVerifier == nil && !config.Dangerous.AcceptMissing && config.AcceptSequencer { return nil, errors.New("cannot read batch poster addresses") } return &Verifier{ config: config, authorizedMap: authorizedMap, - bpValidator: bpValidator, + addrVerifier: addrVerifier, }, nil } @@ -107,20 +107,20 @@ func (v *Verifier) verifyClosure(ctx context.Context, sig []byte, hash common.Ha return nil } - if v.config.Dangerous.AcceptMissing && v.bpValidator == nil { + if v.config.Dangerous.AcceptMissing && v.addrVerifier == nil { return nil } - if !v.config.AcceptSequencer || v.bpValidator == nil { + if !v.config.AcceptSequencer || v.addrVerifier == nil { return ErrSignerNotApproved } - batchPoster, err := v.bpValidator.IsBatchPoster(ctx, addr) + batchPosterOrSequencer, err := v.addrVerifier.IsBatchPosterOrSequencer(ctx, addr) if err != nil { return err } - if !batchPoster { + if !batchPosterOrSequencer { return ErrSignerNotApproved } diff --git a/util/signature/verifier_test.go b/util/signature/verifier_test.go index f6644f123..38c4bbe89 100644 --- a/util/signature/verifier_test.go +++ b/util/signature/verifier_test.go @@ -82,7 +82,7 @@ func TestVerifierBatchPoster(t *testing.T) { signingAddr := crypto.PubkeyToAddress(privateKey.PublicKey) dataSigner := DataSignerFromPrivateKey(privateKey) - bpVerifier := contracts.NewMockBatchPosterVerifier(signingAddr) + bpVerifier := contracts.NewMockAddressVerifier(signingAddr) config := TestingFeedVerifierConfig config.AcceptSequencer = true verifier, err := NewVerifier(&config, bpVerifier) From 365cd0570e52fd03ce85f36dfb2b4a99129c8514 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 23 May 2023 22:50:41 +0530 Subject: [PATCH 024/775] Test that parsing an empty CLI option set results in a default config --- arbnode/batch_poster.go | 1 + arbnode/node.go | 1 + arbnode/simple_redis_lock.go | 2 +- broadcastclient/broadcastclient.go | 2 +- cmd/genericconf/config.go | 2 +- cmd/genericconf/server.go | 6 +++--- cmd/nitro/config_test.go | 19 +++++++++++++++++++ cmd/nitro/nitro.go | 6 ++++++ das/das.go | 1 + go.mod | 3 +++ go.sum | 6 ++++++ util/headerreader/header_reader.go | 1 + util/signature/sign_verify.go | 6 ++---- util/signature/verifier.go | 2 +- 14 files changed, 47 insertions(+), 11 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 9a531df47..e992874f9 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -133,6 +133,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ ExtraBatchGas: 50_000, DataPoster: dataposter.DefaultDataPosterConfig, L1Wallet: DefaultBatchPosterL1WalletConfig, + RedisLock: DefaultRedisLockConfig, } var DefaultBatchPosterL1WalletConfig = genericconf.WalletConfig{ diff --git a/arbnode/node.go b/arbnode/node.go index e05737b71..56d70b1f5 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -419,6 +419,7 @@ var ConfigDefault = Config{ DelayedSequencer: DefaultDelayedSequencerConfig, BatchPoster: DefaultBatchPosterConfig, ForwardingTargetImpl: "", + Forwarder: execution.DefaultNodeForwarderConfig, TxPreChecker: execution.DefaultTxPreCheckerConfig, BlockValidator: staker.DefaultBlockValidatorConfig, Feed: broadcastclient.FeedConfigDefault, diff --git a/arbnode/simple_redis_lock.go b/arbnode/simple_redis_lock.go index 753bb7067..53c531a53 100644 --- a/arbnode/simple_redis_lock.go +++ b/arbnode/simple_redis_lock.go @@ -41,7 +41,7 @@ func RedisLockConfigAddOptions(prefix string, f *flag.FlagSet) { f.String(prefix+".my-id", "", "this node's id prefix when acquiring the lock (optional)") f.Duration(prefix+".lockout-duration", DefaultRedisLockConfig.LockoutDuration, "how long lock is held") f.Duration(prefix+".refresh-duration", DefaultRedisLockConfig.RefreshDuration, "how long between consecutive calls to redis") - f.String(prefix+".key", prefix+".simple-lock-key", "key for lock") + f.String(prefix+".key", DefaultRedisLockConfig.Key, "key for lock") f.Bool(prefix+".background-lock", DefaultRedisLockConfig.BackgroundLock, "should node always try grabing lock in background") } diff --git a/broadcastclient/broadcastclient.go b/broadcastclient/broadcastclient.go index fc9b268d1..e4c9f9397 100644 --- a/broadcastclient/broadcastclient.go +++ b/broadcastclient/broadcastclient.go @@ -95,7 +95,7 @@ var DefaultConfig = Config{ RequireChainId: false, RequireFeedVersion: false, Verifier: signature.DefultFeedVerifierConfig, - URLs: []string{""}, + URLs: []string{}, Timeout: 20 * time.Second, EnableCompression: true, } diff --git a/cmd/genericconf/config.go b/cmd/genericconf/config.go index 88825e9ea..bdf86ba6c 100644 --- a/cmd/genericconf/config.go +++ b/cmd/genericconf/config.go @@ -33,7 +33,7 @@ func ConfConfigAddOptions(prefix string, f *flag.FlagSet) { var ConfConfigDefault = ConfConfig{ Dump: false, EnvPrefix: "", - File: nil, + File: []string{}, S3: DefaultS3Config, String: "", ReloadInterval: 0, diff --git a/cmd/genericconf/server.go b/cmd/genericconf/server.go index 17c4a7a87..40252514b 100644 --- a/cmd/genericconf/server.go +++ b/cmd/genericconf/server.go @@ -26,7 +26,7 @@ var HTTPConfigDefault = HTTPConfig{ Port: 8547, API: append(node.DefaultConfig.HTTPModules, "eth", "arb"), RPCPrefix: node.DefaultConfig.HTTPPathPrefix, - CORSDomain: node.DefaultConfig.HTTPCors, + CORSDomain: []string{}, VHosts: node.DefaultConfig.HTTPVirtualHosts, ServerTimeouts: HTTPServerTimeoutConfigDefault, } @@ -91,7 +91,7 @@ var WSConfigDefault = WSConfig{ Port: 8548, API: append(node.DefaultConfig.WSModules, "eth", "arb"), RPCPrefix: node.DefaultConfig.WSPathPrefix, - Origins: node.DefaultConfig.WSOrigins, + Origins: []string{}, ExposeAll: node.DefaultConfig.WSExposeAll, } @@ -137,7 +137,7 @@ type GraphQLConfig struct { var GraphQLConfigDefault = GraphQLConfig{ Enable: false, - CORSDomain: node.DefaultConfig.GraphQLCors, + CORSDomain: []string{}, VHosts: node.DefaultConfig.GraphQLVirtualHosts, } diff --git a/cmd/nitro/config_test.go b/cmd/nitro/config_test.go index cd3e4bd6a..3f76d1750 100644 --- a/cmd/nitro/config_test.go +++ b/cmd/nitro/config_test.go @@ -14,10 +14,29 @@ import ( "testing" "time" + "github.com/offchainlabs/nitro/cmd/util/confighelpers" "github.com/offchainlabs/nitro/util/colors" "github.com/offchainlabs/nitro/util/testhelpers" + + "github.com/r3labs/diff/v3" + flag "github.com/spf13/pflag" ) +func TestEmptyCliConfig(t *testing.T) { + f := flag.NewFlagSet("", flag.ContinueOnError) + NodeConfigAddOptions(f) + k, err := confighelpers.BeginCommonParse(f, []string{}) + Require(t, err) + var emptyCliNodeConfig NodeConfig + err = confighelpers.EndCommonParse(k, &emptyCliNodeConfig) + Require(t, err) + if !reflect.DeepEqual(emptyCliNodeConfig, NodeConfigDefault) { + changelog, err := diff.Diff(emptyCliNodeConfig, NodeConfigDefault) + Require(t, err) + Fail(t, "empty cli config differs from expected default", changelog) + } +} + func TestSeqConfig(t *testing.T) { args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.parent-chain-reader.enable=false --parent-chain.id 5 --chain.id 421613 --parent-chain.wallet.pathname /l1keystore --parent-chain.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.sequencer.enable --node.feed.output.enable --node.feed.output.port 9642", " ") _, _, _, err := ParseNode(context.Background(), args) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 334ce969e..5f8827781 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -610,16 +610,22 @@ type NodeConfig struct { var NodeConfigDefault = NodeConfig{ Conf: genericconf.ConfConfigDefault, Node: arbnode.ConfigDefault, + Validation: valnode.DefaultValidationConfig, L1: conf.L1ConfigDefault, L2: conf.L2ConfigDefault, LogLevel: int(log.LvlInfo), LogType: "plaintext", + FileLogging: genericconf.DefaultFileLoggingConfig, Persistent: conf.PersistentConfigDefault, HTTP: genericconf.HTTPConfigDefault, WS: genericconf.WSConfigDefault, IPC: genericconf.IPCConfigDefault, + AuthRPC: genericconf.AuthRPCConfigDefault, + GraphQL: genericconf.GraphQLConfigDefault, Metrics: false, MetricsServer: genericconf.MetricsServerConfigDefault, + Init: InitConfigDefault, + Rpc: genericconf.DefaultRpcConfig, } func NodeConfigAddOptions(f *flag.FlagSet) { diff --git a/das/das.go b/das/das.go index a5d5c8d56..9783c12c6 100644 --- a/das/das.go +++ b/das/das.go @@ -69,6 +69,7 @@ var DefaultDataAvailabilityConfig = DataAvailabilityConfig{ RestfulClientAggregatorConfig: DefaultRestfulClientAggregatorConfig, L1ConnectionAttempts: 15, PanicOnError: false, + IpfsStorageServiceConfig: DefaultIpfsStorageServiceConfig, } func OptionalAddressFromString(s string) (*common.Address, error) { diff --git a/go.mod b/go.mod index 42217858f..7b42380b8 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/multiformats/go-multiaddr v0.8.0 github.com/multiformats/go-multihash v0.2.1 github.com/pkg/errors v0.9.1 + github.com/r3labs/diff/v3 v3.0.1 github.com/spf13/pflag v1.0.5 github.com/wealdtech/go-merkletree v1.0.0 golang.org/x/term v0.5.0 @@ -228,6 +229,8 @@ require ( github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/stretchr/testify v1.8.2 // indirect github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect + github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa // indirect github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect diff --git a/go.sum b/go.sum index 2432bec38..8c0b3c637 100644 --- a/go.sum +++ b/go.sum @@ -1440,6 +1440,8 @@ github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= github.com/quic-go/webtransport-go v0.5.2 h1:GA6Bl6oZY+g/flt00Pnu0XtivSD8vukOu3lYhJjnGEk= github.com/quic-go/webtransport-go v0.5.2/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= +github.com/r3labs/diff/v3 v3.0.1 h1:CBKqf3XmNRHXKmdU7mZP1w7TV0pDyVCis1AUHtA4Xtg= +github.com/r3labs/diff/v3 v3.0.1/go.mod h1:f1S9bourRbiM66NskseyUdo0fTmEE0qKrikYJX63dgo= github.com/rabbitmq/amqp091-go v1.1.0/go.mod h1:ogQDLSOACsLPsIq0NpbtiifNZi2YOz0VTJ0kHRghqbM= github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= @@ -1586,6 +1588,10 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= +github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE= github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= github.com/warpfork/go-testmark v0.9.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index 1f501ed1c..2fcbd0d5d 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -78,6 +78,7 @@ func AddOptions(prefix string, f *flag.FlagSet) { f.Bool(prefix+".poll-only", DefaultConfig.PollOnly, "do not attempt to subscribe to header events") f.Bool(prefix+".use-finality-data", DefaultConfig.UseFinalityData, "use l1 data about finalized/safe blocks") f.Duration(prefix+".poll-interval", DefaultConfig.PollInterval, "interval when polling endpoint") + f.Duration(prefix+".subscribe-err-interval", DefaultConfig.SubscribeErrInterval, "interval for subscribe error") f.Duration(prefix+".tx-timeout", DefaultConfig.TxTimeout, "timeout when waiting for a transaction") f.Duration(prefix+".old-header-timeout", DefaultConfig.OldHeaderTimeout, "warns if the latest l1 block is at least this old") } diff --git a/util/signature/sign_verify.go b/util/signature/sign_verify.go index 9a594ccbe..874c781dc 100644 --- a/util/signature/sign_verify.go +++ b/util/signature/sign_verify.go @@ -31,12 +31,10 @@ func SignVerifyConfigAddOptions(prefix string, f *flag.FlagSet) { } var DefaultSignVerifyConfig = SignVerifyConfig{ - ECDSA: VerifierConfig{ - AcceptSequencer: true, - }, + ECDSA: DefultFeedVerifierConfig, SymmetricFallback: false, SymmetricSign: false, - Symmetric: TestSimpleHmacConfig, + Symmetric: EmptySimpleHmacConfig, } func NewSignVerify(config *SignVerifyConfig, signerFunc DataSignerFunc, bpValidator contracts.BatchPosterVerifierInterface) (*SignVerify, error) { diff --git a/util/signature/verifier.go b/util/signature/verifier.go index fb0aae9e1..d1fc71e1d 100644 --- a/util/signature/verifier.go +++ b/util/signature/verifier.go @@ -37,7 +37,7 @@ var ErrMissingSignature = fmt.Errorf("%w: signature not found", ErrSignatureNotV var ErrSignerNotApproved = fmt.Errorf("%w: signer not approved", ErrSignatureNotVerified) func FeedVerifierConfigAddOptions(prefix string, f *flag.FlagSet) { - f.StringArray(prefix+".allowed-addresses", DefultFeedVerifierConfig.AllowedAddresses, "a list of allowed addresses") + f.StringSlice(prefix+".allowed-addresses", DefultFeedVerifierConfig.AllowedAddresses, "a list of allowed addresses") f.Bool(prefix+".accept-sequencer", DefultFeedVerifierConfig.AcceptSequencer, "accept verified message from sequencer") DangerousFeedVerifierConfigAddOptions(prefix+".dangerous", f) } From 690998e632c413d87fa17fc8488889bdab74c80e Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 23 May 2023 23:08:58 +0530 Subject: [PATCH 025/775] Use update geth for missing config --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index a23dc84cf..d79f1644a 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit a23dc84cfd8a00f1a971edf917563a72fdf4304f +Subproject commit d79f1644a1ac5b4adf068771ee080ce5ed6202cb From 30e208b8a80632c12fdec2bd4c1fc68c8d6c0c4f Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 23 May 2023 23:19:52 +0530 Subject: [PATCH 026/775] update gitmodules --- .gitmodules | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitmodules b/.gitmodules index e1c15431c..e5b31b642 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,3 +20,5 @@ [submodule "arbitrator/wasm-testsuite/testsuite"] path = arbitrator/wasm-testsuite/testsuite url = https://github.com/WebAssembly/testsuite.git +[submodule "go-ethereum/"] + branch = missing_bloom_confirm \ No newline at end of file From cec5da143eb408e19b9434680a90d296b11a17df Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 23 May 2023 23:29:37 +0530 Subject: [PATCH 027/775] update gitmodules --- .gitmodules | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index e5b31b642..15f0570e4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,7 @@ [submodule "go-ethereum"] path = go-ethereum url = https://github.com/OffchainLabs/go-ethereum.git + branch = missing_bloom_confirm [submodule "fastcache"] path = fastcache url = https://github.com/OffchainLabs/fastcache.git @@ -19,6 +20,4 @@ url = https://github.com/OffchainLabs/blockscout.git [submodule "arbitrator/wasm-testsuite/testsuite"] path = arbitrator/wasm-testsuite/testsuite - url = https://github.com/WebAssembly/testsuite.git -[submodule "go-ethereum/"] - branch = missing_bloom_confirm \ No newline at end of file + url = https://github.com/WebAssembly/testsuite.git \ No newline at end of file From 3a9291b891f641098d4e18351347425b7c5aa3ae Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 23 May 2023 23:46:15 +0530 Subject: [PATCH 028/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index d79f1644a..a23dc84cf 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit d79f1644a1ac5b4adf068771ee080ce5ed6202cb +Subproject commit a23dc84cfd8a00f1a971edf917563a72fdf4304f From 4e99ba0282c294b66c5cff2b1ef1398ef0710421 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 23 May 2023 23:47:49 +0530 Subject: [PATCH 029/775] update gitmodules --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 15f0570e4..4a3ca5ccf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,4 +20,4 @@ url = https://github.com/OffchainLabs/blockscout.git [submodule "arbitrator/wasm-testsuite/testsuite"] path = arbitrator/wasm-testsuite/testsuite - url = https://github.com/WebAssembly/testsuite.git \ No newline at end of file + url = https://github.com/WebAssembly/testsuite.git From 7934e571c98117b199057b8d8675472e24aac013 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 24 May 2023 00:23:08 +0530 Subject: [PATCH 030/775] update gitmodules --- .gitmodules | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 4a3ca5ccf..e1c15431c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,6 @@ [submodule "go-ethereum"] path = go-ethereum url = https://github.com/OffchainLabs/go-ethereum.git - branch = missing_bloom_confirm [submodule "fastcache"] path = fastcache url = https://github.com/OffchainLabs/fastcache.git From 191e99e7bf7c45166607e250f5963afa8b88a610 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 24 May 2023 00:34:47 +0530 Subject: [PATCH 031/775] Fix test --- util/signature/sign_verify.go | 8 ++++++++ util/signature/sign_verify_test.go | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/util/signature/sign_verify.go b/util/signature/sign_verify.go index 874c781dc..c91f8db86 100644 --- a/util/signature/sign_verify.go +++ b/util/signature/sign_verify.go @@ -36,6 +36,14 @@ var DefaultSignVerifyConfig = SignVerifyConfig{ SymmetricSign: false, Symmetric: EmptySimpleHmacConfig, } +var TestSignVerifyConfig = SignVerifyConfig{ + ECDSA: VerifierConfig{ + AcceptSequencer: true, + }, + SymmetricFallback: false, + SymmetricSign: false, + Symmetric: TestSimpleHmacConfig, +} func NewSignVerify(config *SignVerifyConfig, signerFunc DataSignerFunc, bpValidator contracts.BatchPosterVerifierInterface) (*SignVerify, error) { var fallback *SimpleHmac diff --git a/util/signature/sign_verify_test.go b/util/signature/sign_verify_test.go index 8ecb6e5cc..916fc03a2 100644 --- a/util/signature/sign_verify_test.go +++ b/util/signature/sign_verify_test.go @@ -17,7 +17,7 @@ func TestSignVerifyModes(t *testing.T) { signingAddr := crypto.PubkeyToAddress(privateKey.PublicKey) dataSigner := DataSignerFromPrivateKey(privateKey) - config := DefaultSignVerifyConfig + config := TestSignVerifyConfig config.SymmetricFallback = false config.SymmetricSign = false config.ECDSA.AcceptSequencer = false @@ -25,14 +25,14 @@ func TestSignVerifyModes(t *testing.T) { signVerifyECDSA, err := NewSignVerify(&config, dataSigner, nil) Require(t, err) - configSymmetric := DefaultSignVerifyConfig + configSymmetric := TestSignVerifyConfig configSymmetric.SymmetricFallback = true configSymmetric.SymmetricSign = true configSymmetric.ECDSA.AcceptSequencer = false signVerifySymmetric, err := NewSignVerify(&configSymmetric, nil, nil) Require(t, err) - configFallback := DefaultSignVerifyConfig + configFallback := TestSignVerifyConfig configFallback.SymmetricFallback = true configFallback.SymmetricSign = false configFallback.ECDSA.AllowedAddresses = []string{signingAddr.Hex()} From ea21852ed74c2949de5884395bede9d5ed708793 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 24 May 2023 00:36:07 +0530 Subject: [PATCH 032/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index a23dc84cf..d79f1644a 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit a23dc84cfd8a00f1a971edf917563a72fdf4304f +Subproject commit d79f1644a1ac5b4adf068771ee080ce5ed6202cb From 4919158b56c44c15b3d55d763df582dd601516c5 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 24 May 2023 00:42:47 +0530 Subject: [PATCH 033/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index d79f1644a..a23dc84cf 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit d79f1644a1ac5b4adf068771ee080ce5ed6202cb +Subproject commit a23dc84cfd8a00f1a971edf917563a72fdf4304f From 7985fc43059ff37bfeabd40f5b0d24ff0639d7c5 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 24 May 2023 19:54:27 +0530 Subject: [PATCH 034/775] Empty-Commit From da0df13293f7538bef3a5b596ea3319bbb03f852 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 24 May 2023 21:17:23 +0530 Subject: [PATCH 035/775] Changes based on offline discussion --- arbnode/batch_poster.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index e992874f9..36edcb3b4 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -41,6 +41,7 @@ import ( var ( batchPosterWalletBalance = metrics.NewRegisteredGaugeFloat64("arb/batchposter/wallet/balanceether", nil) batchPosterGasRefunderBalance = metrics.NewRegisteredGaugeFloat64("arb/batchposter/gasrefunder/balanceether", nil) + batchPosterSimpleRedisLockKey = "node.batch-poster.redis-lock.simple-lock-key" ) type batchPosterPosition struct { @@ -180,7 +181,9 @@ func NewBatchPoster(l1Reader *headerreader.HeaderReader, inbox *InboxTracker, st return nil, err } redisLockConfigFetcher := func() *SimpleRedisLockConfig { - return &config().RedisLock + simpleRedisLockConfig := config().RedisLock + simpleRedisLockConfig.Key = batchPosterSimpleRedisLockKey + return &simpleRedisLockConfig } redisLock, err := NewSimpleRedisLock(redisClient, redisLockConfigFetcher, func() bool { return syncMonitor.Synced() }) if err != nil { From d02469cea510d678340b7f1e1e241d9d667933ef Mon Sep 17 00:00:00 2001 From: amsanghi Date: Thu, 25 May 2023 22:43:25 +0530 Subject: [PATCH 036/775] test to ensure DIFFICULTY/PREVRANDAO opcode returns the expected value of 1 --- contracts | 2 +- go-ethereum | 2 +- system_tests/common_test.go | 17 +++++++++++--- system_tests/estimation_test.go | 40 +++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/contracts b/contracts index f48ce451e..fa5f51215 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit f48ce451e4bc2dbea9024cdc08fd0eb410fa61b5 +Subproject commit fa5f51215083e35382cc7ad8cdccf3e72b76fc30 diff --git a/go-ethereum b/go-ethereum index a23dc84cf..ffad045d0 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit a23dc84cfd8a00f1a971edf917563a72fdf4304f +Subproject commit ffad045d01f9c98135797f84ca80a16088d21ec2 diff --git a/system_tests/common_test.go b/system_tests/common_test.go index e471899ff..6b6b2e915 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -597,17 +597,28 @@ func createTestNodeOnL1WithConfigImpl( // L2 -Only. Enough for tests that needs no interface to L1 // Requires precompiles.AllowDebugPrecompiles = true func CreateTestL2(t *testing.T, ctx context.Context) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { - return CreateTestL2WithConfig(t, ctx, nil, arbnode.ConfigDefaultL2Test(), true) + return CreateTestL2WithArbOS(t, ctx, 11) +} + +func CreateTestL2WithArbOS(t *testing.T, ctx context.Context, arbOS uint64) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { + return CreateTestL2WithConfigArbOS(t, ctx, nil, arbnode.ConfigDefaultL2Test(), true, arbOS) } func CreateTestL2WithConfig( t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, takeOwnership bool, +) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { + return CreateTestL2WithConfigArbOS(t, ctx, l2Info, nodeConfig, takeOwnership, 11) +} + +func CreateTestL2WithConfigArbOS( + t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, takeOwnership bool, arbOS uint64, ) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { feedErrChan := make(chan error, 10) AddDefaultValNode(t, ctx, nodeConfig, true) - - l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, l2Info, "", params.ArbitrumDevTestChainConfig()) + chainConfig := params.ArbitrumDevTestChainConfig() + chainConfig.ArbitrumChainParams.InitialArbOSVersion = arbOS + l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, l2Info, "", chainConfig) currentNode, err := arbnode.CreateNode(ctx, stack, chainDb, arbDb, NewFetcherFromConfig(nodeConfig), blockchain, nil, nil, nil, nil, nil, feedErrChan) Require(t, err) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index c80492326..3b967ae81 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -127,6 +127,46 @@ func TestEstimate(t *testing.T) { } } +func TestDifficultyForLatestArbOS(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + l2info, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() + + auth := l2info.GetDefaultTransactOpts("Owner", ctx) + + // deploy a test contract + _, _, simple, err := mocksgen.DeploySimple(&auth, client) + Require(t, err, "could not deploy contract") + + difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) + Require(t, err) + if difficulty.Uint64() != 1 { + Fail(t, "Expected difficulty to be 1 by got:", difficulty) + } +} + +func TestDifficultyForArbOSTen(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + l2info, node, client := CreateTestL2WithArbOS(t, ctx, 10) + defer node.StopAndWait() + + auth := l2info.GetDefaultTransactOpts("Owner", ctx) + + // deploy a test contract + _, _, simple, err := mocksgen.DeploySimple(&auth, client) + Require(t, err, "could not deploy contract") + + difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) + Require(t, err) + if difficulty.Uint64() != 1 { + Fail(t, "Expected difficulty to be 1 by got:", difficulty) + } +} + func TestComponentEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() From 31a0a67d0285e385e3afb165d96067ef73b3a392 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Thu, 25 May 2023 22:49:20 +0530 Subject: [PATCH 037/775] Fix contracts branch --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index fa5f51215..3138c4b62 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit fa5f51215083e35382cc7ad8cdccf3e72b76fc30 +Subproject commit 3138c4b62e4e180d62f324101c0448eb4ab78484 From ccf472d95e5559d959a54560cbace548be8cc068 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Thu, 25 May 2023 22:53:23 +0530 Subject: [PATCH 038/775] Fix contracts branch --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 3138c4b62..7436762ab 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 3138c4b62e4e180d62f324101c0448eb4ab78484 +Subproject commit 7436762ab4236d31578e1f599a328eedeb2a632f From 9b632f9ec1e09375d0501641b151d3300c4ebcdd Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 26 May 2023 00:00:49 +0530 Subject: [PATCH 039/775] update submodules --- contracts | 2 +- go-ethereum | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts b/contracts index 7436762ab..08ac127e9 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 7436762ab4236d31578e1f599a328eedeb2a632f +Subproject commit 08ac127e966fa87a4d5ba3d23cd3132b57701132 diff --git a/go-ethereum b/go-ethereum index ffad045d0..87c313c37 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit ffad045d01f9c98135797f84ca80a16088d21ec2 +Subproject commit 87c313c37b8b59f0e5a6abed53ed169c2788e5b9 From e7220b6523cb037cfc4b900bc513263a15a24247 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 26 May 2023 00:06:34 +0530 Subject: [PATCH 040/775] update submodules --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 08ac127e9..f79f13697 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 08ac127e966fa87a4d5ba3d23cd3132b57701132 +Subproject commit f79f136972fa30588cef6e6082a54217fbdb4a84 From 1d3a93cd98d9824cef35170aee3bfb444c4c2670 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 30 May 2023 23:44:56 +0530 Subject: [PATCH 041/775] Changes based on PR comments --- system_tests/estimation_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index 3b967ae81..cbf757988 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -142,7 +142,7 @@ func TestDifficultyForLatestArbOS(t *testing.T) { difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) Require(t, err) - if difficulty.Uint64() != 1 { + if arbmath.BigEquals(difficulty, common.Big1) { Fail(t, "Expected difficulty to be 1 by got:", difficulty) } } @@ -162,7 +162,7 @@ func TestDifficultyForArbOSTen(t *testing.T) { difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) Require(t, err) - if difficulty.Uint64() != 1 { + if arbmath.BigEquals(difficulty, common.Big1) { Fail(t, "Expected difficulty to be 1 by got:", difficulty) } } From 22c9df320acc6c3ec099b98de06b16f659bf6da3 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 13 Jun 2023 16:11:11 +0000 Subject: [PATCH 042/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index c90d53074..c98e2c342 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit c90d53074f5e57fd39a70994c4143bf3b2496946 +Subproject commit c98e2c342dbbcf7479b1aff987ed251ad8b4e969 From 1bf55862536135186887a0a8b478648dc8ffd764 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 13 Jun 2023 16:26:52 +0000 Subject: [PATCH 043/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index c98e2c342..a47849f67 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit c98e2c342dbbcf7479b1aff987ed251ad8b4e969 +Subproject commit a47849f671f2f247bf5b3c02ab7b3bc2785b42fc From cb65f7ef7a9732e4ed929ab6b8640c80b288fc42 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 13 Jun 2023 17:26:17 +0000 Subject: [PATCH 044/775] fix recreate state test build --- system_tests/recreatestate_rpc_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index 3494179be..041553351 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -47,7 +47,7 @@ func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateD SnapshotLimit: 256, SnapshotWait: true, } - l2info, node, l2client, _, l1info, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, cacheConfig, nil) + l2info, node, l2client, _, l1info, _, _, l1stack = createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, cacheConfig, nil) cancel = func() { defer requireClose(t, l1stack) defer node.StopAndWait() @@ -303,7 +303,7 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks u AddDefaultValNode(t, ctx1, nodeConfig, true) l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, nil, t.TempDir(), params.ArbitrumDevTestChainConfig(), cacheConfig) - node, err := arbnode.CreateNode(ctx1, stack, chainDb, arbDb, nodeConfig, blockchain, nil, nil, nil, nil, feedErrChan) + node, err := arbnode.CreateNode(ctx1, stack, chainDb, arbDb, NewFetcherFromConfig(nodeConfig), blockchain, nil, nil, nil, nil, nil, feedErrChan) Require(t, err) err = node.TxStreamer.AddFakeInitMessage() Require(t, err) @@ -333,7 +333,7 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks u _, err := EnsureTxSucceeded(ctx, client, tx) testhelpers.RequireImpl(t, err) } - bc := node.Backend.ArbInterface().BlockChain() + bc := node.Execution.Backend.ArbInterface().BlockChain() genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum lastBlock, err := client.BlockNumber(ctx) Require(t, err) @@ -349,12 +349,12 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks u AddDefaultValNode(t, ctx, nodeConfig, true) l2info, stack, chainDb, arbDb, blockchain = createL2BlockChain(t, l2info, dataDir, params.ArbitrumDevTestChainConfig(), cacheConfig) - node, err = arbnode.CreateNode(ctx, stack, chainDb, arbDb, nodeConfig, blockchain, nil, node.DeployInfo, nil, nil, feedErrChan) + node, err = arbnode.CreateNode(ctx, stack, chainDb, arbDb, NewFetcherFromConfig(nodeConfig), blockchain, nil, node.DeployInfo, nil, nil, nil, feedErrChan) Require(t, err) Require(t, node.Start(ctx)) client = ClientForStack(t, stack) defer node.StopAndWait() - bc = node.Backend.ArbInterface().BlockChain() + bc = node.Execution.Backend.ArbInterface().BlockChain() gas := skipGas blocks := skipBlocks for i := genesis + 1; i <= genesis+uint64(txCount); i++ { From ed4cd44420fd118c65265fabd1267fdfdeac1564 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 14 Jun 2023 18:44:49 -0600 Subject: [PATCH 045/775] fix merge --- arbnode/node.go | 2 +- cmd/nitro/nitro.go | 3 +++ go-ethereum | 2 +- system_tests/forwarder_test.go | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 11ce2f549..760ba4ebf 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -808,7 +808,7 @@ func createNodeImpl( } } var messagePruner *MessagePruner - if config.MessagePruner.Enable && !config.Caching.Archive && stakerObj != nil { + if config.MessagePruner.Enable && stakerObj != nil { messagePruner = NewMessagePruner(txStreamer, inboxTracker, stakerObj, func() *MessagePrunerConfig { return &configFetcher.Get().MessagePruner }) } // always create DelayedSequencer, it won't do anything if it is disabled diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 40662e37f..b8589cbe1 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -683,6 +683,9 @@ func ParseNode(ctx context.Context, args []string) (*NodeConfig, *genericconf.Wa nodeConfig.L1.Wallet = genericconf.WalletConfigDefault nodeConfig.L2.DevWallet = genericconf.WalletConfigDefault + if nodeConfig.Execution.Archive { + nodeConfig.Node.MessagePruner.Enable = false + } err = nodeConfig.Validate() if err != nil { return nil, nil, nil, err diff --git a/go-ethereum b/go-ethereum index aa93654f7..7ea707239 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit aa93654f732abdbb7cf79574b8ca6e2f8a3337e7 +Subproject commit 7ea707239f34fc2fa56be4b1b97a470f00cab600 diff --git a/system_tests/forwarder_test.go b/system_tests/forwarder_test.go index 0ae266fd2..22421407d 100644 --- a/system_tests/forwarder_test.go +++ b/system_tests/forwarder_test.go @@ -323,7 +323,7 @@ func TestRedisForwarderFallbackNoRedis(t *testing.T) { l2info.GenerateAccount(user) tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, transferAmount, nil) sendFunc := func() error { return forwardingClient.SendTransaction(ctx, tx) } - err := tryWithTimeout(ctx, sendFunc, execution.DefaultTestForwarderConfig.UpdateInterval*10) + err := tryWithTimeout(ctx, sendFunc, gethexec.DefaultTestForwarderConfig.UpdateInterval*10) Require(t, err) _, err = EnsureTxSucceeded(ctx, fallbackClient, tx) From e165f3ded1d943222fc332936157a3bfb259540f Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 15 Jun 2023 01:38:13 +0000 Subject: [PATCH 046/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index a47849f67..eb96086a9 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit a47849f671f2f247bf5b3c02ab7b3bc2785b42fc +Subproject commit eb96086a95859470cfedd3539a9c8bb3132f015f From e8767b733ac9af585f24fcc2ce6a804c5fc4c85a Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 15 Jun 2023 01:55:27 +0000 Subject: [PATCH 047/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index eb96086a9..c86303cf0 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit eb96086a95859470cfedd3539a9c8bb3132f015f +Subproject commit c86303cf0b7c10f55a19b767a326a8bd06ce8108 From cba9ceacc25fbe826097ccf1ce07993d7a24b753 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 16 Jun 2023 14:36:00 +0000 Subject: [PATCH 048/775] add MaxNumberOfBlocksToSkipStateSaving and MaxAmountOfGasToSkipStateSaving to CachingConfig --- arbnode/execution/blockchain.go | 68 ++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/arbnode/execution/blockchain.go b/arbnode/execution/blockchain.go index 2ed0221b0..c05fafa2b 100644 --- a/arbnode/execution/blockchain.go +++ b/arbnode/execution/blockchain.go @@ -25,15 +25,17 @@ import ( ) type CachingConfig struct { - Archive bool `koanf:"archive"` - BlockCount uint64 `koanf:"block-count"` - BlockAge time.Duration `koanf:"block-age"` - TrieTimeLimit time.Duration `koanf:"trie-time-limit"` - TrieDirtyCache int `koanf:"trie-dirty-cache"` - TrieCleanCache int `koanf:"trie-clean-cache"` - SnapshotCache int `koanf:"snapshot-cache"` - DatabaseCache int `koanf:"database-cache"` - SnapshotRestoreMaxGas uint64 `koanf:"snapshot-restore-gas-limit"` + Archive bool `koanf:"archive"` + BlockCount uint64 `koanf:"block-count"` + BlockAge time.Duration `koanf:"block-age"` + TrieTimeLimit time.Duration `koanf:"trie-time-limit"` + TrieDirtyCache int `koanf:"trie-dirty-cache"` + TrieCleanCache int `koanf:"trie-clean-cache"` + SnapshotCache int `koanf:"snapshot-cache"` + DatabaseCache int `koanf:"database-cache"` + SnapshotRestoreMaxGas uint64 `koanf:"snapshot-restore-gas-limit"` + MaxNumberOfBlocksToSkipStateSaving uint32 `koanf:"max-number-of-blocks-to-skip-state-saving"` + MaxAmountOfGasToSkipStateSaving uint64 `koanf:"max-amount-of-gas-to-skip-state-saving"` } func CachingConfigAddOptions(prefix string, f *flag.FlagSet) { @@ -46,18 +48,22 @@ func CachingConfigAddOptions(prefix string, f *flag.FlagSet) { f.Int(prefix+".snapshot-cache", DefaultCachingConfig.SnapshotCache, "amount of memory in megabytes to cache state snapshots with") f.Int(prefix+".database-cache", DefaultCachingConfig.DatabaseCache, "amount of memory in megabytes to cache database contents with") f.Uint64(prefix+".snapshot-restore-gas-limit", DefaultCachingConfig.SnapshotRestoreMaxGas, "maximum gas rolled back to recover snapshot") + f.Uint32(prefix+".max-number-of-blocks-to-skip-state-saving", DefaultCachingConfig.MaxNumberOfBlocksToSkipStateSaving, "maximum number of blocks to skip state saving to persistent storage (archive node only)") + f.Uint64(prefix+".max-amount-of-gas-to-skip-state-saving", DefaultCachingConfig.MaxAmountOfGasToSkipStateSaving, "maximum amount of gas in blocks to skip saving state to Persistent storage (archive node only)") } var DefaultCachingConfig = CachingConfig{ - Archive: false, - BlockCount: 128, - BlockAge: 30 * time.Minute, - TrieTimeLimit: time.Hour, - TrieDirtyCache: 1024, - TrieCleanCache: 600, - SnapshotCache: 400, - DatabaseCache: 2048, - SnapshotRestoreMaxGas: 300_000_000_000, + Archive: false, + BlockCount: 128, + BlockAge: 30 * time.Minute, + TrieTimeLimit: time.Hour, + TrieDirtyCache: 1024, + TrieCleanCache: 600, + SnapshotCache: 400, + DatabaseCache: 2048, + SnapshotRestoreMaxGas: 300_000_000_000, + MaxNumberOfBlocksToSkipStateSaving: 127, + MaxAmountOfGasToSkipStateSaving: 15 * 1000 * 1000, } func DefaultCacheConfigFor(stack *node.Node, cachingConfig *CachingConfig) *core.CacheConfig { @@ -67,18 +73,20 @@ func DefaultCacheConfigFor(stack *node.Node, cachingConfig *CachingConfig) *core } return &core.CacheConfig{ - TrieCleanLimit: cachingConfig.TrieCleanCache, - TrieCleanJournal: stack.ResolvePath(baseConf.TrieCleanCacheJournal), - TrieCleanRejournal: baseConf.TrieCleanCacheRejournal, - TrieCleanNoPrefetch: baseConf.NoPrefetch, - TrieDirtyLimit: cachingConfig.TrieDirtyCache, - TrieDirtyDisabled: cachingConfig.Archive, - TrieTimeLimit: cachingConfig.TrieTimeLimit, - TriesInMemory: cachingConfig.BlockCount, - TrieRetention: cachingConfig.BlockAge, - SnapshotLimit: cachingConfig.SnapshotCache, - Preimages: baseConf.Preimages, - SnapshotRestoreMaxGas: cachingConfig.SnapshotRestoreMaxGas, + TrieCleanLimit: cachingConfig.TrieCleanCache, + TrieCleanJournal: stack.ResolvePath(baseConf.TrieCleanCacheJournal), + TrieCleanRejournal: baseConf.TrieCleanCacheRejournal, + TrieCleanNoPrefetch: baseConf.NoPrefetch, + TrieDirtyLimit: cachingConfig.TrieDirtyCache, + TrieDirtyDisabled: cachingConfig.Archive, + TrieTimeLimit: cachingConfig.TrieTimeLimit, + TriesInMemory: cachingConfig.BlockCount, + TrieRetention: cachingConfig.BlockAge, + SnapshotLimit: cachingConfig.SnapshotCache, + Preimages: baseConf.Preimages, + SnapshotRestoreMaxGas: cachingConfig.SnapshotRestoreMaxGas, + MaxNumberOfBlocksToSkipStateSaving: cachingConfig.MaxNumberOfBlocksToSkipStateSaving, + MaxAmountOfGasToSkipStateSaving: cachingConfig.MaxAmountOfGasToSkipStateSaving, } } From b517b8ef4c24707deaebc067aa103b1da794216b Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 21 Jun 2023 20:58:52 +0530 Subject: [PATCH 049/775] Changes based on PR comments --- system_tests/bloom_test.go | 2 +- system_tests/common_test.go | 23 +++++++---------------- system_tests/conditionaltx_test.go | 2 +- system_tests/contract_tx_test.go | 2 +- system_tests/estimation_test.go | 16 +++++++++------- system_tests/infra_fee_test.go | 2 +- system_tests/initialization_test.go | 2 +- system_tests/log_subscription_test.go | 2 +- system_tests/outbox_test.go | 2 +- system_tests/precompile_test.go | 8 ++++---- system_tests/reorg_resequencing_test.go | 2 +- system_tests/retryable_test.go | 2 +- system_tests/seq_coordinator_test.go | 2 +- system_tests/seq_nonce_test.go | 6 +++--- system_tests/seq_pause_test.go | 2 +- system_tests/seq_reject_test.go | 4 ++-- system_tests/seq_whitelist_test.go | 2 +- system_tests/seqfeed_test.go | 8 ++++---- system_tests/transfer_test.go | 2 +- 19 files changed, 42 insertions(+), 49 deletions(-) diff --git a/system_tests/bloom_test.go b/system_tests/bloom_test.go index 9ad3253d4..f2a9bd408 100644 --- a/system_tests/bloom_test.go +++ b/system_tests/bloom_test.go @@ -28,7 +28,7 @@ func TestBloom(t *testing.T) { nodeconfig := arbnode.ConfigDefaultL2Test() nodeconfig.RPC.BloomBitsBlocks = 256 nodeconfig.RPC.BloomConfirms = 1 - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, false) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, false, nil) defer node.StopAndWait() l2info.GenerateAccount("User2") diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 844ca63f1..b9908a7f0 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -622,32 +622,23 @@ func createTestNodeOnL1WithConfigImpl( // L2 -Only. Enough for tests that needs no interface to L1 // Requires precompiles.AllowDebugPrecompiles = true -func CreateTestL2(t *testing.T, ctx context.Context) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { - return CreateTestL2WithArbOS(t, ctx, 11) -} - -func CreateTestL2WithArbOS(t *testing.T, ctx context.Context, arbOS uint64) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { - return CreateTestL2WithConfigArbOS(t, ctx, nil, arbnode.ConfigDefaultL2Test(), true, arbOS) +func CreateTestL2(t *testing.T, ctx context.Context, chainConfig *params.ChainConfig) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { + return CreateTestL2WithConfig(t, ctx, nil, arbnode.ConfigDefaultL2Test(), true, chainConfig) } func CreateTestL2WithConfig( - t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, takeOwnership bool, -) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { - return CreateTestL2WithConfigArbOS(t, ctx, l2Info, nodeConfig, takeOwnership, 11) -} - -func CreateTestL2WithConfigArbOS( - t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, takeOwnership bool, arbOS uint64, + t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, takeOwnership bool, chainConfig *params.ChainConfig, ) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { feedErrChan := make(chan error, 10) AddDefaultValNode(t, ctx, nodeConfig, true) - chainConfig := params.ArbitrumDevTestChainConfig() - chainConfig.ArbitrumChainParams.InitialArbOSVersion = arbOS + + if chainConfig == nil { + chainConfig = params.ArbitrumDevTestChainConfig() + } l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, l2Info, "", chainConfig) currentNode, err := arbnode.CreateNode(ctx, stack, chainDb, arbDb, NewFetcherFromConfig(nodeConfig), blockchain, nil, nil, nil, nil, nil, feedErrChan) Require(t, err) - // Give the node an init message err = currentNode.TxStreamer.AddFakeInitMessage() Require(t, err) diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index c65103694..09260d7a7 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -308,7 +308,7 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) + l2info, node, client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() rpcClient, err := node.Stack.Attach() Require(t, err) diff --git a/system_tests/contract_tx_test.go b/system_tests/contract_tx_test.go index e671dcc6a..fb6e72080 100644 --- a/system_tests/contract_tx_test.go +++ b/system_tests/contract_tx_test.go @@ -27,7 +27,7 @@ func TestContractTxDeploy(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() nodeconfig := arbnode.ConfigDefaultL2Test() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, false) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, false, nil) defer node.StopAndWait() from := common.HexToAddress("0x123412341234") diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index 58b14fe7e..8dd116362 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -26,7 +26,7 @@ func TestDeploy(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) + l2info, node, client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) @@ -51,7 +51,7 @@ func TestEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) + l2info, node, client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) @@ -131,7 +131,7 @@ func TestDifficultyForLatestArbOS(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) + l2info, node, client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) @@ -143,7 +143,7 @@ func TestDifficultyForLatestArbOS(t *testing.T) { difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) Require(t, err) if arbmath.BigEquals(difficulty, common.Big1) { - Fail(t, "Expected difficulty to be 1 by got:", difficulty) + Fatal(t, "Expected difficulty to be 1 by got:", difficulty) } } @@ -151,7 +151,9 @@ func TestDifficultyForArbOSTen(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2WithArbOS(t, ctx, 10) + chainConfig := params.ArbitrumDevTestChainConfig() + chainConfig.ArbitrumChainParams.InitialArbOSVersion = 10 + l2info, node, client := CreateTestL2(t, ctx, chainConfig) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) @@ -163,7 +165,7 @@ func TestDifficultyForArbOSTen(t *testing.T) { difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) Require(t, err) if arbmath.BigEquals(difficulty, common.Big1) { - Fail(t, "Expected difficulty to be 1 by got:", difficulty) + Fatal(t, "Expected difficulty to be 1 by got:", difficulty) } } @@ -171,7 +173,7 @@ func TestComponentEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) + l2info, node, client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() l1BaseFee := new(big.Int).Set(arbostypes.DefaultInitialL1BaseFee) diff --git a/system_tests/infra_fee_test.go b/system_tests/infra_fee_test.go index 89f869576..237854bea 100644 --- a/system_tests/infra_fee_test.go +++ b/system_tests/infra_fee_test.go @@ -25,7 +25,7 @@ func TestInfraFee(t *testing.T) { defer cancel() nodeconfig := arbnode.ConfigDefaultL2Test() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, true) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, true, nil) defer node.StopAndWait() l2info.GenerateAccount("User2") diff --git a/system_tests/initialization_test.go b/system_tests/initialization_test.go index c7797d35e..90f9f2f6f 100644 --- a/system_tests/initialization_test.go +++ b/system_tests/initialization_test.go @@ -63,7 +63,7 @@ func TestInitContract(t *testing.T) { l2info.ArbInitData.Accounts = append(l2info.ArbInitData.Accounts, accountInfo) expectedSums[accountAddress] = sum } - _, node, client := CreateTestL2WithConfig(t, ctx, l2info, arbnode.ConfigDefaultL2Test(), true) + _, node, client := CreateTestL2WithConfig(t, ctx, l2info, arbnode.ConfigDefaultL2Test(), true, nil) defer node.StopAndWait() for accountAddress, sum := range expectedSums { diff --git a/system_tests/log_subscription_test.go b/system_tests/log_subscription_test.go index 5ee1732fb..54ad0fe5e 100644 --- a/system_tests/log_subscription_test.go +++ b/system_tests/log_subscription_test.go @@ -19,7 +19,7 @@ func TestLogSubscription(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) + l2info, node, client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) diff --git a/system_tests/outbox_test.go b/system_tests/outbox_test.go index 6b43cc83b..d79f74c5b 100644 --- a/system_tests/outbox_test.go +++ b/system_tests/outbox_test.go @@ -35,7 +35,7 @@ func TestOutboxProofs(t *testing.T) { withdrawTopic := arbSysAbi.Events["L2ToL1Tx"].ID merkleTopic := arbSysAbi.Events["SendMerkleUpdate"].ID - l2info, node, client := CreateTestL2(t, ctx) + l2info, node, client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) diff --git a/system_tests/precompile_test.go b/system_tests/precompile_test.go index ad08ff747..66feccf46 100644 --- a/system_tests/precompile_test.go +++ b/system_tests/precompile_test.go @@ -21,7 +21,7 @@ func TestPurePrecompileMethodCalls(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) + _, node, client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() arbSys, err := precompilesgen.NewArbSys(common.HexToAddress("0x64"), client) @@ -37,7 +37,7 @@ func TestViewLogReverts(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) + _, node, client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) @@ -53,7 +53,7 @@ func TestCustomSolidityErrors(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) + _, node, client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() callOpts := &bind.CallOpts{Context: ctx} @@ -86,7 +86,7 @@ func TestPrecompileErrorGasLeft(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - info, node, client := CreateTestL2(t, ctx) + info, node, client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() auth := info.GetDefaultTransactOpts("Faucet", ctx) diff --git a/system_tests/reorg_resequencing_test.go b/system_tests/reorg_resequencing_test.go index f132d4648..c3a46b139 100644 --- a/system_tests/reorg_resequencing_test.go +++ b/system_tests/reorg_resequencing_test.go @@ -19,7 +19,7 @@ func TestReorgResequencing(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) + l2info, node, client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() startMsgCount, err := node.TxStreamer.GetMessageCount() diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 7b0c3a756..41190831a 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -104,7 +104,7 @@ func retryableSetup(t *testing.T) ( func TestRetryableNoExist(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, l2client := CreateTestL2(t, ctx) + _, node, l2client := CreateTestL2(t, ctx, nil) defer node.StopAndWait() arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) diff --git a/system_tests/seq_coordinator_test.go b/system_tests/seq_coordinator_test.go index 2209e82d9..77b2c12ad 100644 --- a/system_tests/seq_coordinator_test.go +++ b/system_tests/seq_coordinator_test.go @@ -62,7 +62,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { createStartNode := func(nodeNum int) { nodeConfig.SeqCoordinator.MyUrlImpl = nodeNames[nodeNum] - _, node, _ := CreateTestL2WithConfig(t, ctx, l2Info, nodeConfig, false) + _, node, _ := CreateTestL2WithConfig(t, ctx, l2Info, nodeConfig, false, nil) nodes[nodeNum] = node } diff --git a/system_tests/seq_nonce_test.go b/system_tests/seq_nonce_test.go index 968f14136..3d15199ae 100644 --- a/system_tests/seq_nonce_test.go +++ b/system_tests/seq_nonce_test.go @@ -26,7 +26,7 @@ func TestSequencerParallelNonces(t *testing.T) { config := arbnode.ConfigDefaultL2Test() config.Sequencer.NonceFailureCacheExpiry = time.Minute - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false, nil) defer node.StopAndWait() l2info.GenerateAccount("Destination") @@ -63,7 +63,7 @@ func TestSequencerNonceTooHigh(t *testing.T) { defer cancel() config := arbnode.ConfigDefaultL2Test() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false, nil) defer node.StopAndWait() l2info.GetInfoWithPrivKey("Owner").Nonce++ @@ -91,7 +91,7 @@ func TestSequencerNonceTooHighQueueFull(t *testing.T) { config := arbnode.ConfigDefaultL2Test() config.Sequencer.NonceFailureCacheSize = 5 config.Sequencer.NonceFailureCacheExpiry = time.Minute - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false, nil) defer node.StopAndWait() count := 15 diff --git a/system_tests/seq_pause_test.go b/system_tests/seq_pause_test.go index fd057c018..2bd0139fc 100644 --- a/system_tests/seq_pause_test.go +++ b/system_tests/seq_pause_test.go @@ -16,7 +16,7 @@ func TestSequencerPause(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info1, nodeA, client := CreateTestL2(t, ctx) + l2info1, nodeA, client := CreateTestL2(t, ctx, nil) defer nodeA.StopAndWait() const numUsers = 100 diff --git a/system_tests/seq_reject_test.go b/system_tests/seq_reject_test.go index 19c06c4bc..35018d975 100644 --- a/system_tests/seq_reject_test.go +++ b/system_tests/seq_reject_test.go @@ -31,14 +31,14 @@ func TestSequencerRejection(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() feedErrChan := make(chan error, 10) - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true) + l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true, nil) defer nodeA.StopAndWait() clientNodeConfig := arbnode.ConfigDefaultL2Test() port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false) + _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false, nil) defer nodeB.StopAndWait() auth := l2info1.GetDefaultTransactOpts("Owner", ctx) diff --git a/system_tests/seq_whitelist_test.go b/system_tests/seq_whitelist_test.go index 2d671dcdd..e8a2e2742 100644 --- a/system_tests/seq_whitelist_test.go +++ b/system_tests/seq_whitelist_test.go @@ -18,7 +18,7 @@ func TestSequencerWhitelist(t *testing.T) { config := arbnode.ConfigDefaultL2Test() config.Sequencer.SenderWhitelist = GetTestAddressForAccountName(t, "Owner").String() + "," + GetTestAddressForAccountName(t, "User").String() - l2info, l2node, client := CreateTestL2WithConfig(t, ctx, nil, config, true) + l2info, l2node, client := CreateTestL2WithConfig(t, ctx, nil, config, true, nil) defer l2node.StopAndWait() l2info.GenerateAccount("User") diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index 0ae72e384..bcdf41d9b 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -44,13 +44,13 @@ func TestSequencerFeed(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true) + l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true, nil) defer nodeA.StopAndWait() clientNodeConfig := arbnode.ConfigDefaultL2Test() port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false) + _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false, nil) defer nodeB.StopAndWait() l2info1.GenerateAccount("User2") @@ -79,7 +79,7 @@ func TestRelayedSequencerFeed(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true) + l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true, nil) defer nodeA.StopAndWait() bigChainId, err := client1.ChainID(ctx) @@ -101,7 +101,7 @@ func TestRelayedSequencerFeed(t *testing.T) { clientNodeConfig := arbnode.ConfigDefaultL2Test() port = currentRelay.GetListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeC, client3 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false) + _, nodeC, client3 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false, nil) defer nodeC.StopAndWait() StartWatchChanErr(t, ctx, feedErrChan, nodeC) diff --git a/system_tests/transfer_test.go b/system_tests/transfer_test.go index 2e3317907..b7328f2b7 100644 --- a/system_tests/transfer_test.go +++ b/system_tests/transfer_test.go @@ -13,7 +13,7 @@ import ( func TestTransfer(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, client := CreateTestL2(t, ctx) + l2info, l2node, client := CreateTestL2(t, ctx, nil) defer l2node.StopAndWait() l2info.GenerateAccount("User2") From 92ccdb0510c35bd859dc842bd42f4d1ededffbad Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 21 Jun 2023 21:21:09 +0530 Subject: [PATCH 050/775] minor fix --- contracts | 2 +- go-ethereum | 2 +- go.mod | 2 -- go.sum | 2 -- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/contracts b/contracts index f48ce451e..c667c8972 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit f48ce451e4bc2dbea9024cdc08fd0eb410fa61b5 +Subproject commit c667c8972fbc25a596d82feaf6b426868f9f0437 diff --git a/go-ethereum b/go-ethereum index a23dc84cf..afeb7841e 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit a23dc84cfd8a00f1a971edf917563a72fdf4304f +Subproject commit afeb7841e15ca8517c58412578627708e719415b diff --git a/go.mod b/go.mod index c439943c7..32b33216d 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,6 @@ require ( github.com/libp2p/go-libp2p v0.26.4 github.com/multiformats/go-multiaddr v0.8.0 github.com/multiformats/go-multihash v0.2.1 - github.com/pkg/errors v0.9.1 github.com/r3labs/diff/v3 v3.0.1 github.com/spf13/pflag v1.0.5 github.com/wealdtech/go-merkletree v1.0.0 @@ -114,7 +113,6 @@ require ( github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect github.com/ipfs/go-block-format v0.1.1 // indirect diff --git a/go.sum b/go.sum index f083e5a98..bdb82b1e4 100644 --- a/go.sum +++ b/go.sum @@ -599,8 +599,6 @@ github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoI github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= From 37ff4e7a4e487fde17e40bc9b8eeb8ee2b3b2d3c Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 21 Jun 2023 21:24:32 +0530 Subject: [PATCH 051/775] minor fix --- system_tests/estimation_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index 8dd116362..eceaebddb 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -142,8 +142,8 @@ func TestDifficultyForLatestArbOS(t *testing.T) { difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) Require(t, err) - if arbmath.BigEquals(difficulty, common.Big1) { - Fatal(t, "Expected difficulty to be 1 by got:", difficulty) + if !arbmath.BigEquals(difficulty, common.Big1) { + Fatal(t, "Expected difficulty to be 1 but got:", difficulty) } } @@ -164,8 +164,8 @@ func TestDifficultyForArbOSTen(t *testing.T) { difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) Require(t, err) - if arbmath.BigEquals(difficulty, common.Big1) { - Fatal(t, "Expected difficulty to be 1 by got:", difficulty) + if !arbmath.BigEquals(difficulty, common.Big1) { + Fatal(t, "Expected difficulty to be 1 but got:", difficulty) } } From bc8e7bb970d62634831b9a69d15b186161af7f02 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 21 Jun 2023 22:20:06 +0530 Subject: [PATCH 052/775] Changes based on PR comments --- system_tests/block_validator_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index b3fd8ddb6..13658c898 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -14,13 +14,16 @@ import ( "time" "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/l2pricing" + "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" + "github.com/offchainlabs/nitro/util/arbmath" ) type workloadType uint @@ -60,6 +63,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops perTransfer := big.NewInt(1e12) + var simple *mocksgen.Simple if workload != upgradeArbOs { for i := 0; i < workloadLoops; i++ { var tx *types.Transaction @@ -108,6 +112,16 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops } } else { auth := l2info.GetDefaultTransactOpts("Owner", ctx) + // deploy a test contract + var err error + _, _, simple, err = mocksgen.DeploySimple(&auth, l2client) + Require(t, err, "could not deploy contract") + + difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) + Require(t, err) + if !arbmath.BigEquals(difficulty, common.Big1) { + Fatal(t, "Expected difficulty to be 1 but got:", difficulty) + } // make auth a chain owner arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) Require(t, err) @@ -122,6 +136,12 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) + difficulty, err = simple.GetBlockDifficulty(&bind.CallOpts{}) + Require(t, err) + if !arbmath.BigEquals(difficulty, common.Big1) { + Fatal(t, "Expected difficulty to be 1 but got:", difficulty) + } + tx = l2info.PrepareTxTo("Owner", nil, l2info.TransferGas, perTransfer, []byte{byte(vm.PUSH0)}) err = l2client.SendTransaction(ctx, tx) Require(t, err) @@ -157,6 +177,13 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops Fatal(t, "Unexpected balance:", l2balance) } } + if workload == upgradeArbOs { + difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) + Require(t, err) + if !arbmath.BigEquals(difficulty, common.Big1) { + Fatal(t, "Expected difficulty to be 1 but got:", difficulty) + } + } lastBlock, err := l2clientB.BlockByNumber(ctx, nil) Require(t, err) From a5434adc36c57c019768a6b525e364a234511e95 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 27 Jun 2023 11:36:14 -0600 Subject: [PATCH 053/775] remove unused sequencer.dangerous config --- execution/gethexec/sequencer.go | 44 +++++++++------------------------ 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index ffb919caa..8712003fa 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -54,35 +54,18 @@ var ( ) type SequencerConfig struct { - Enable bool `koanf:"enable"` - MaxBlockSpeed time.Duration `koanf:"max-block-speed" reload:"hot"` - MaxRevertGasReject uint64 `koanf:"max-revert-gas-reject" reload:"hot"` - MaxAcceptableTimestampDelta time.Duration `koanf:"max-acceptable-timestamp-delta" reload:"hot"` - SenderWhitelist string `koanf:"sender-whitelist"` - Forwarder ForwarderConfig `koanf:"forwarder"` - QueueSize int `koanf:"queue-size"` - QueueTimeout time.Duration `koanf:"queue-timeout" reload:"hot"` - NonceCacheSize int `koanf:"nonce-cache-size" reload:"hot"` - MaxTxDataSize int `koanf:"max-tx-data-size" reload:"hot"` - NonceFailureCacheSize int `koanf:"nonce-failure-cache-size" reload:"hot"` - NonceFailureCacheExpiry time.Duration `koanf:"nonce-failure-cache-expiry" reload:"hot"` - Dangerous DangerousSequencerConfig `koanf:"dangerous"` -} - -type DangerousSequencerConfig struct { - NoCoordinator bool `koanf:"no-coordinator"` -} - -var DefaultDangerousSequencerConfig = DangerousSequencerConfig{ - NoCoordinator: false, -} - -var TestDangerousSequencerConfig = DangerousSequencerConfig{ - NoCoordinator: true, -} - -func DangerousSequencerConfigAddOptions(prefix string, f *flag.FlagSet) { - f.Bool(prefix+".no-coordinator", DefaultDangerousSequencerConfig.NoCoordinator, "DANGEROUS! allows sequencer without coordinator.") + Enable bool `koanf:"enable"` + MaxBlockSpeed time.Duration `koanf:"max-block-speed" reload:"hot"` + MaxRevertGasReject uint64 `koanf:"max-revert-gas-reject" reload:"hot"` + MaxAcceptableTimestampDelta time.Duration `koanf:"max-acceptable-timestamp-delta" reload:"hot"` + SenderWhitelist string `koanf:"sender-whitelist"` + Forwarder ForwarderConfig `koanf:"forwarder"` + QueueSize int `koanf:"queue-size"` + QueueTimeout time.Duration `koanf:"queue-timeout" reload:"hot"` + NonceCacheSize int `koanf:"nonce-cache-size" reload:"hot"` + MaxTxDataSize int `koanf:"max-tx-data-size" reload:"hot"` + NonceFailureCacheSize int `koanf:"nonce-failure-cache-size" reload:"hot"` + NonceFailureCacheExpiry time.Duration `koanf:"nonce-failure-cache-expiry" reload:"hot"` } func (c *SequencerConfig) Validate() error { @@ -109,7 +92,6 @@ var DefaultSequencerConfig = SequencerConfig{ QueueSize: 1024, QueueTimeout: time.Second * 12, NonceCacheSize: 1024, - Dangerous: DefaultDangerousSequencerConfig, // 95% of the default batch poster limit, leaving 5KB for headers and such MaxTxDataSize: 95000, NonceFailureCacheSize: 1024, @@ -126,7 +108,6 @@ var TestSequencerConfig = SequencerConfig{ QueueSize: 128, QueueTimeout: time.Second * 5, NonceCacheSize: 4, - Dangerous: TestDangerousSequencerConfig, MaxTxDataSize: 95000, NonceFailureCacheSize: 1024, NonceFailureCacheExpiry: time.Second, @@ -145,7 +126,6 @@ func SequencerConfigAddOptions(prefix string, f *flag.FlagSet) { f.Int(prefix+".max-tx-data-size", DefaultSequencerConfig.MaxTxDataSize, "maximum transaction size the sequencer will accept") f.Int(prefix+".nonce-failure-cache-size", DefaultSequencerConfig.NonceFailureCacheSize, "number of transactions with too high of a nonce to keep in memory while waiting for their predecessor") f.Duration(prefix+".nonce-failure-cache-expiry", DefaultSequencerConfig.NonceFailureCacheExpiry, "maximum amount of time to wait for a predecessor before rejecting a tx with nonce too high") - DangerousSequencerConfigAddOptions(prefix+".dangerous", f) } type txQueueItem struct { From 5c1d6c718d83d6038aeb35df52bdf8013d735ea1 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 7 Jul 2023 16:54:06 -0700 Subject: [PATCH 054/775] Add cgroups v2 support to resourcemanager --- .../resourcemanager/resource_management.go | 84 +++++++++++-------- .../resource_management_test.go | 36 ++++---- 2 files changed, 69 insertions(+), 51 deletions(-) diff --git a/arbnode/resourcemanager/resource_management.go b/arbnode/resourcemanager/resource_management.go index acb535598..b1bdc45d7 100644 --- a/arbnode/resourcemanager/resource_management.go +++ b/arbnode/resourcemanager/resource_management.go @@ -90,18 +90,28 @@ type limitChecker interface { String() string } +func isSupported(c limitChecker) bool { + _, err := c.isLimitExceeded() + return err == nil +} + // newLimitChecker attempts to auto-discover the mechanism by which it -// can check system limits. Currently Cgroups V1 is supported, -// with Cgroups V2 likely to be implmemented next. If no supported -// mechanism is discovered, it logs an error and fails open, ie -// it creates a trivialLimitChecker that does no checks. +// can check system limits. Currently Cgroups V1 and V2 are supported. +// If no supported mechanism is discovered, it logs an error and +// fails open, ie it creates a trivialLimitChecker that does no checks. func newLimitChecker(conf *Config) limitChecker { - c := newCgroupsV1MemoryLimitChecker(DefaultCgroupsV1MemoryDirectory, conf.MemoryLimitPercent) + c := newCgroupsMemoryLimitChecker(cgroupsV1MemoryFiles, conf.MemoryLimitPercent) if isSupported(c) { log.Info("Cgroups v1 detected, enabling memory limit RPC throttling") return c } + c = newCgroupsMemoryLimitChecker(cgroupsV2MemoryFiles, conf.MemoryLimitPercent) + if isSupported(c) { + log.Info("Cgroups v2 detected, enabling memory limit RPC throttling") + return c + } + log.Error("No method for determining memory usage and limits was discovered, disabled memory limit RPC throttling") return &trivialLimitChecker{} } @@ -115,28 +125,37 @@ func (_ trivialLimitChecker) isLimitExceeded() (bool, error) { func (_ trivialLimitChecker) String() string { return "trivial" } -const DefaultCgroupsV1MemoryDirectory = "/sys/fs/cgroup/memory/" +type cgroupsMemoryFiles struct { + limitFile, usageFile, statsFile string + inactiveRe *regexp.Regexp +} -type cgroupsV1MemoryLimitChecker struct { - cgroupDir string - memoryLimitPercent int +const defaultCgroupsV1MemoryDirectory = "/sys/fs/cgroup/memory/" +const defaultCgroupsV2MemoryDirectory = "/sys/fs/cgroup/" - limitFile, usageFile, statsFile string +var cgroupsV1MemoryFiles = cgroupsMemoryFiles{ + limitFile: defaultCgroupsV1MemoryDirectory + "/memory.limit_in_bytes", + usageFile: defaultCgroupsV1MemoryDirectory + "/memory.usage_in_bytes", + statsFile: defaultCgroupsV1MemoryDirectory + "/memory.stat", + inactiveRe: regexp.MustCompile(`total_inactive_file (\d+)`), +} +var cgroupsV2MemoryFiles = cgroupsMemoryFiles{ + limitFile: defaultCgroupsV2MemoryDirectory + "/memory.max", + usageFile: defaultCgroupsV2MemoryDirectory + "/memory.current", + statsFile: defaultCgroupsV2MemoryDirectory + "/memory.stat", + inactiveRe: regexp.MustCompile(`inactive_file (\d+)`), } -func newCgroupsV1MemoryLimitChecker(cgroupDir string, memoryLimitPercent int) *cgroupsV1MemoryLimitChecker { - return &cgroupsV1MemoryLimitChecker{ - cgroupDir: cgroupDir, - memoryLimitPercent: memoryLimitPercent, - limitFile: cgroupDir + "/memory.limit_in_bytes", - usageFile: cgroupDir + "/memory.usage_in_bytes", - statsFile: cgroupDir + "/memory.stat", - } +type cgroupsMemoryLimitChecker struct { + files cgroupsMemoryFiles + memoryLimitPercent int } -func isSupported(c limitChecker) bool { - _, err := c.isLimitExceeded() - return err == nil +func newCgroupsMemoryLimitChecker(files cgroupsMemoryFiles, memoryLimitPercent int) *cgroupsMemoryLimitChecker { + return &cgroupsMemoryLimitChecker{ + files: files, + memoryLimitPercent: memoryLimitPercent, + } } // isLimitExceeded checks if the system memory used exceeds the limit @@ -145,24 +164,25 @@ func isSupported(c limitChecker) bool { // See the following page for details of calculating the memory used, // which is reported as container_memory_working_set_bytes in prometheus: // https://mihai-albert.com/2022/02/13/out-of-memory-oom-in-kubernetes-part-3-memory-metrics-sources-and-tools-to-collect-them/ -func (c *cgroupsV1MemoryLimitChecker) isLimitExceeded() (bool, error) { +func (c *cgroupsMemoryLimitChecker) isLimitExceeded() (bool, error) { var limit, usage, inactive int var err error - limit, err = readIntFromFile(c.limitFile) - if err != nil { + if limit, err = readIntFromFile(c.files.limitFile); err != nil { return false, err } - usage, err = readIntFromFile(c.usageFile) - if err != nil { + if usage, err = readIntFromFile(c.files.usageFile); err != nil { return false, err } - inactive, err = readInactive(c.statsFile) - if err != nil { + if inactive, err = readInactive(c.files.statsFile, c.files.inactiveRe); err != nil { return false, err } return usage-inactive >= ((limit * c.memoryLimitPercent) / 100), nil } +func (c cgroupsMemoryLimitChecker) String() string { + return "CgroupsMemoryLimitChecker" +} + func readIntFromFile(fileName string) (int, error) { file, err := os.Open(fileName) if err != nil { @@ -176,9 +196,7 @@ func readIntFromFile(fileName string) (int, error) { return limit, nil } -var re = regexp.MustCompile(`total_inactive_file (\d+)`) - -func readInactive(fileName string) (int, error) { +func readInactive(fileName string, re *regexp.Regexp) (int, error) { file, err := os.Open(fileName) if err != nil { return 0, err @@ -201,7 +219,3 @@ func readInactive(fileName string) (int, error) { return 0, errors.New("total_inactive_file not found in " + fileName) } - -func (c cgroupsV1MemoryLimitChecker) String() string { - return "CgroupsV1MemoryLimitChecker" -} diff --git a/arbnode/resourcemanager/resource_management_test.go b/arbnode/resourcemanager/resource_management_test.go index fe470e706..3d1248d91 100644 --- a/arbnode/resourcemanager/resource_management_test.go +++ b/arbnode/resourcemanager/resource_management_test.go @@ -6,52 +6,57 @@ package resourcemanager import ( "fmt" "os" + "regexp" "testing" ) -func updateFakeCgroupv1Files(c *cgroupsV1MemoryLimitChecker, limit, usage, inactive int) error { - limitFile, err := os.Create(c.limitFile) +func updateFakeCgroupFiles(c *cgroupsMemoryLimitChecker, limit, usage, inactive int) error { + limitFile, err := os.Create(c.files.limitFile) if err != nil { return err } - _, err = fmt.Fprintf(limitFile, "%d\n", limit) - if err != nil { + if _, err = fmt.Fprintf(limitFile, "%d\n", limit); err != nil { return err } - usageFile, err := os.Create(c.usageFile) + usageFile, err := os.Create(c.files.usageFile) if err != nil { return err } - _, err = fmt.Fprintf(usageFile, "%d\n", usage) - if err != nil { + if _, err = fmt.Fprintf(usageFile, "%d\n", usage); err != nil { return err } - statsFile, err := os.Create(c.statsFile) + statsFile, err := os.Create(c.files.statsFile) if err != nil { return err } - _, err = fmt.Fprintf(statsFile, `total_cache 1029980160 + if _, err = fmt.Fprintf(statsFile, `total_cache 1029980160 total_rss 1016209408 total_inactive_file %d total_active_file 321544192 -`, inactive) - if err != nil { +`, inactive); err != nil { return err } return nil } -func TestCgroupsv1MemoryLimit(t *testing.T) { +func TestCgroupsMemoryLimit(t *testing.T) { cgroupDir := t.TempDir() - c := newCgroupsV1MemoryLimitChecker(cgroupDir, 95) + testFiles := cgroupsMemoryFiles{ + limitFile: cgroupDir + "/memory.limit_in_bytes", + usageFile: cgroupDir + "/memory.usage_in_bytes", + statsFile: cgroupDir + "/memory.stat", + inactiveRe: regexp.MustCompile(`total_inactive_file (\d+)`), + } + + c := newCgroupsMemoryLimitChecker(testFiles, 95) _, err := c.isLimitExceeded() if err == nil { t.Error("Should fail open if can't read files") } - err = updateFakeCgroupv1Files(c, 1000, 1000, 51) + err = updateFakeCgroupFiles(c, 1000, 1000, 51) if err != nil { t.Error(err) } @@ -63,7 +68,7 @@ func TestCgroupsv1MemoryLimit(t *testing.T) { t.Error("Expected under limit") } - err = updateFakeCgroupv1Files(c, 1000, 1000, 50) + err = updateFakeCgroupFiles(c, 1000, 1000, 50) if err != nil { t.Error(err) } @@ -74,5 +79,4 @@ func TestCgroupsv1MemoryLimit(t *testing.T) { if !exceeded { t.Error("Expected over limit") } - } From 698165465e14311d43dbdb912977f5ddbcff498c Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 10 Jul 2023 16:42:24 -0600 Subject: [PATCH 055/775] fix merge errors --- arbnode/node.go | 58 ++++++++++---------------------------- execution/gethexec/node.go | 27 ++++++++++-------- 2 files changed, 30 insertions(+), 55 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index e695da483..65e16f721 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -14,7 +14,6 @@ import ( flag "github.com/spf13/pflag" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" @@ -371,7 +370,6 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet, feedInputEnable bool, feed BatchPosterConfigAddOptions(prefix+".batch-poster", f) MessagePrunerConfigAddOptions(prefix+".message-pruner", f) staker.BlockValidatorConfigAddOptions(prefix+".block-validator", f) - arbitrum.RecordingDatabaseConfigAddOptions(prefix+".recording-database", f) broadcastclient.FeedConfigAddOptions(prefix+".feed", f, feedInputEnable, feedOutputEnable) staker.L1ValidatorConfigAddOptions(prefix+".staker", f) SeqCoordinatorConfigAddOptions(prefix+".seq-coordinator", f) @@ -380,32 +378,22 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet, feedInputEnable bool, feed DangerousConfigAddOptions(prefix+".dangerous", f) TransactionStreamerConfigAddOptions(prefix+".transaction-streamer", f) MaintenanceConfigAddOptions(prefix+".maintenance", f) - - archiveMsg := fmt.Sprintf("retain past block state (deprecated, please use %v.caching.archive)", prefix) - f.Bool(prefix+".archive", ConfigDefault.Archive, archiveMsg) } var ConfigDefault = Config{ - RPC: arbitrum.DefaultConfig, - Sequencer: execution.DefaultSequencerConfig, - L1Reader: headerreader.DefaultConfig, - InboxReader: DefaultInboxReaderConfig, - DelayedSequencer: DefaultDelayedSequencerConfig, - BatchPoster: DefaultBatchPosterConfig, - MessagePruner: DefaultMessagePrunerConfig, - ForwardingTargetImpl: "", - TxPreChecker: execution.DefaultTxPreCheckerConfig, - BlockValidator: staker.DefaultBlockValidatorConfig, - Feed: broadcastclient.FeedConfigDefault, - Staker: staker.DefaultL1ValidatorConfig, - SeqCoordinator: DefaultSeqCoordinatorConfig, - DataAvailability: das.DefaultDataAvailabilityConfig, - SyncMonitor: DefaultSyncMonitorConfig, - Dangerous: DefaultDangerousConfig, - Archive: false, - TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second - Caching: execution.DefaultCachingConfig, - TransactionStreamer: DefaultTransactionStreamerConfig, + L1Reader: headerreader.DefaultConfig, + InboxReader: DefaultInboxReaderConfig, + DelayedSequencer: DefaultDelayedSequencerConfig, + BatchPoster: DefaultBatchPosterConfig, + MessagePruner: DefaultMessagePrunerConfig, + BlockValidator: staker.DefaultBlockValidatorConfig, + Feed: broadcastclient.FeedConfigDefault, + Staker: staker.DefaultL1ValidatorConfig, + SeqCoordinator: DefaultSeqCoordinatorConfig, + DataAvailability: das.DefaultDataAvailabilityConfig, + SyncMonitor: DefaultSyncMonitorConfig, + Dangerous: DefaultDangerousConfig, + TransactionStreamer: DefaultTransactionStreamerConfig, } func ConfigDefaultL1Test() *Config { @@ -579,15 +567,6 @@ func createNodeImpl( } } - sequencerConfigFetcher := func() *execution.SequencerConfig { return &configFetcher.Get().Sequencer } - txprecheckConfigFetcher := func() *execution.TxPreCheckerConfig { return &configFetcher.Get().TxPreChecker } - exec, err := execution.CreateExecutionNode(stack, chainDb, l2BlockChain, l1Reader, syncMonitor, - config.ForwardingTarget(), &config.Forwarder, config.RPC, - sequencerConfigFetcher, txprecheckConfigFetcher) - if err != nil { - return nil, err - } - var broadcastServer *broadcaster.Broadcaster if config.Feed.Output.Enable { var maybeDataSigner signature.DataSignerFunc @@ -797,7 +776,7 @@ func createNodeImpl( } notifiers := make([]staker.LatestStakedNotifier, 0) - if config.MessagePruner.Enable && !config.Caching.Archive { + if config.MessagePruner.Enable { messagePruner = NewMessagePruner(txStreamer, inboxTracker, func() *MessagePrunerConfig { return &configFetcher.Get().MessagePruner }) notifiers = append(notifiers, messagePruner) } @@ -834,10 +813,7 @@ func createNodeImpl( return nil, err } } - var messagePruner *MessagePruner - if config.MessagePruner.Enable && !config.Caching.Archive && stakerObj != nil { - messagePruner = NewMessagePruner(txStreamer, inboxTracker, stakerObj, func() *MessagePrunerConfig { return &configFetcher.Get().MessagePruner }) - } + // always create DelayedSequencer, it won't do anything if it is disabled delayedSequencer, err = NewDelayedSequencer(l1Reader, inboxReader, exec, coordinator, func() *DelayedSequencerConfig { return &configFetcher.Get().DelayedSequencer }) if err != nil { @@ -973,10 +949,6 @@ func (n *Node) Start(ctx context.Context) error { return fmt.Errorf("error starting inbox reader: %w", err) } } - err = n.Execution.TxPublisher.Start(ctx) - if err != nil { - return fmt.Errorf("error starting transaction puiblisher: %w", err) - } if n.SeqCoordinator != nil { n.SeqCoordinator.Start(ctx) } diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index e6ec68ed3..9dc546b52 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -35,16 +35,17 @@ func DangerousConfigAddOptions(prefix string, f *flag.FlagSet) { } type Config struct { - L1Reader headerreader.Config `koanf:"l1-reader" reload:"hot"` - Sequencer SequencerConfig `koanf:"sequencer" reload:"hot"` - TxPreChecker TxPreCheckerConfig `koanf:"tx-pre-checker" reload:"hot"` - Forwarder ForwarderConfig `koanf:"forwarder"` - ForwardingTargetImpl string `koanf:"forwarding-target"` - Caching CachingConfig `koanf:"caching"` - RPC arbitrum.Config `koanf:"rpc"` - Archive bool `koanf:"archive"` - TxLookupLimit uint64 `koanf:"tx-lookup-limit"` - Dangerous DangerousConfig `koanf:"dangerous"` + L1Reader headerreader.Config `koanf:"l1-reader" reload:"hot"` + Sequencer SequencerConfig `koanf:"sequencer" reload:"hot"` + RecordingDB arbitrum.RecordingDatabaseConfig `koanf:"recording-database"` + TxPreChecker TxPreCheckerConfig `koanf:"tx-pre-checker" reload:"hot"` + Forwarder ForwarderConfig `koanf:"forwarder"` + ForwardingTargetImpl string `koanf:"forwarding-target"` + Caching CachingConfig `koanf:"caching"` + RPC arbitrum.Config `koanf:"rpc"` + Archive bool `koanf:"archive"` + TxLookupLimit uint64 `koanf:"tx-lookup-limit"` + Dangerous DangerousConfig `koanf:"dangerous"` } func (c *Config) ForwardingTarget() string { @@ -68,12 +69,12 @@ func (c *Config) Validate() error { func ConfigAddOptions(prefix string, f *flag.FlagSet) { arbitrum.ConfigAddOptions(prefix+".rpc", f) SequencerConfigAddOptions(prefix+".sequencer", f) + arbitrum.RecordingDatabaseConfigAddOptions(prefix+".recording-database", f) f.String(prefix+".forwarding-target", ConfigDefault.ForwardingTargetImpl, "transaction forwarding target URL, or \"null\" to disable forwarding (iff not sequencer)") AddOptionsForNodeForwarderConfig(prefix+".forwarder", f) TxPreCheckerConfigAddOptions(prefix+".tx-pre-checker", f) CachingConfigAddOptions(prefix+".caching", 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)") - archiveMsg := fmt.Sprintf("retain past block state (deprecated, please use %v.caching.archive)", prefix) f.Bool(prefix+".archive", ConfigDefault.Archive, archiveMsg) DangerousConfigAddOptions(prefix+".dangerous", f) @@ -82,11 +83,13 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { var ConfigDefault = Config{ RPC: arbitrum.DefaultConfig, Sequencer: DefaultSequencerConfig, + RecordingDB: arbitrum.DefaultRecordingDatabaseConfig, ForwardingTargetImpl: "", TxPreChecker: DefaultTxPreCheckerConfig, Archive: false, TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second Caching: DefaultCachingConfig, + Dangerous: DefaultDangerousConfig, } func ConfigDefaultNonSequencerTest() *Config { @@ -132,7 +135,7 @@ func CreateExecutionNode( if err != nil { return nil, err } - recorder := NewBlockRecorder(execEngine, chainDB) + recorder := NewBlockRecorder(&config.RecordingDB, execEngine, chainDB) var txPublisher TransactionPublisher var sequencer *Sequencer From 232ded2a24121796b4c77cf0d6a3c1fc69de864e Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Mon, 17 Jul 2023 13:49:03 -0700 Subject: [PATCH 056/775] Split cgroups test into 3 tests --- .../resource_management_test.go | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/arbnode/resourcemanager/resource_management_test.go b/arbnode/resourcemanager/resource_management_test.go index 3d1248d91..699bcd24e 100644 --- a/arbnode/resourcemanager/resource_management_test.go +++ b/arbnode/resourcemanager/resource_management_test.go @@ -31,52 +31,62 @@ func updateFakeCgroupFiles(c *cgroupsMemoryLimitChecker, limit, usage, inactive if err != nil { return err } - if _, err = fmt.Fprintf(statsFile, `total_cache 1029980160 + _, err = fmt.Fprintf(statsFile, `total_cache 1029980160 total_rss 1016209408 total_inactive_file %d total_active_file 321544192 -`, inactive); err != nil { - return err - } - return nil +`, inactive) + return err } -func TestCgroupsMemoryLimit(t *testing.T) { - cgroupDir := t.TempDir() - testFiles := cgroupsMemoryFiles{ +func makeCgroupsTestDir(cgroupDir string) cgroupsMemoryFiles { + return cgroupsMemoryFiles{ limitFile: cgroupDir + "/memory.limit_in_bytes", usageFile: cgroupDir + "/memory.usage_in_bytes", statsFile: cgroupDir + "/memory.stat", inactiveRe: regexp.MustCompile(`total_inactive_file (\d+)`), } +} +func TestCgroupsFailIfCantOpen(t *testing.T) { + testFiles := makeCgroupsTestDir(t.TempDir()) c := newCgroupsMemoryLimitChecker(testFiles, 95) - _, err := c.isLimitExceeded() - if err == nil { - t.Error("Should fail open if can't read files") + var err error + if _, err = c.isLimitExceeded(); err == nil { + t.Fatal("Should fail open if can't read files") } +} - err = updateFakeCgroupFiles(c, 1000, 1000, 51) - if err != nil { - t.Error(err) +func TestCgroupsLimitNotExceeded(t *testing.T) { + testFiles := makeCgroupsTestDir(t.TempDir()) + c := newCgroupsMemoryLimitChecker(testFiles, 95) + + var err error + if err = updateFakeCgroupFiles(c, 1000, 1000, 51); err != nil { + t.Fatal(err) } exceeded, err := c.isLimitExceeded() if err != nil { - t.Error(err) + t.Fatal(err) } if exceeded { - t.Error("Expected under limit") + t.Fatal("Expected under limit") } +} - err = updateFakeCgroupFiles(c, 1000, 1000, 50) - if err != nil { - t.Error(err) +func TestCgroupsLimitExceeded(t *testing.T) { + testFiles := makeCgroupsTestDir(t.TempDir()) + c := newCgroupsMemoryLimitChecker(testFiles, 95) + + var err error + if err = updateFakeCgroupFiles(c, 1000, 1000, 50); err != nil { + t.Fatal(err) } - exceeded, err = c.isLimitExceeded() + exceeded, err := c.isLimitExceeded() if err != nil { - t.Error(err) + t.Fatal(err) } if !exceeded { - t.Error("Expected over limit") + t.Fatal("Expected over limit") } } From cebea6fb233da8ba7b348c68525df7d7e3068757 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 18 Jul 2023 02:24:52 +0000 Subject: [PATCH 057/775] add storage keys caching --- arbos/addressSet/addressSet.go | 4 +- arbos/addressTable/addressTable.go | 2 +- arbos/arbosState/arbosstate.go | 32 +++++------ arbos/arbosState/arbosstate_test.go | 2 +- arbos/blockhash/blockhash.go | 2 +- arbos/l1pricing/batchPoster.go | 8 +-- arbos/l1pricing/l1pricing.go | 4 +- arbos/queue_test.go | 2 +- arbos/retryables/retryable.go | 14 ++--- arbos/storage/queue.go | 2 +- arbos/storage/storage.go | 63 ++++++++++++++++++---- util/containers/safe_lru.go | 82 +++++++++++++++++++++++++++++ 12 files changed, 171 insertions(+), 46 deletions(-) create mode 100644 util/containers/safe_lru.go diff --git a/arbos/addressSet/addressSet.go b/arbos/addressSet/addressSet.go index ae2e6a34c..72200c037 100644 --- a/arbos/addressSet/addressSet.go +++ b/arbos/addressSet/addressSet.go @@ -24,9 +24,9 @@ func Initialize(sto *storage.Storage) error { func OpenAddressSet(sto *storage.Storage) *AddressSet { return &AddressSet{ - sto, + sto.NoCacheCopy(), sto.OpenStorageBackedUint64(0), - sto.OpenSubStorage([]byte{0}), + sto.OpenSubStorage([]byte{0}, false), } } diff --git a/arbos/addressTable/addressTable.go b/arbos/addressTable/addressTable.go index 220c2700f..56f04badf 100644 --- a/arbos/addressTable/addressTable.go +++ b/arbos/addressTable/addressTable.go @@ -25,7 +25,7 @@ func Initialize(sto *storage.Storage) { func Open(sto *storage.Storage) *AddressTable { numItems := sto.OpenStorageBackedUint64(0) - return &AddressTable{sto, sto.OpenSubStorage([]byte{}), numItems} + return &AddressTable{sto.NoCacheCopy(), sto.OpenSubStorage([]byte{}, false), numItems} } func (atab *AddressTable) Register(addr common.Address) (uint64, error) { diff --git a/arbos/arbosState/arbosstate.go b/arbos/arbosState/arbosstate.go index 2bea8f7c5..93ec1ec46 100644 --- a/arbos/arbosState/arbosstate.go +++ b/arbos/arbosState/arbosstate.go @@ -71,13 +71,13 @@ func OpenArbosState(stateDB vm.StateDB, burner burn.Burner) (*ArbosState, error) backingStorage.OpenStorageBackedUint64(uint64(upgradeVersionOffset)), backingStorage.OpenStorageBackedUint64(uint64(upgradeTimestampOffset)), backingStorage.OpenStorageBackedAddress(uint64(networkFeeAccountOffset)), - l1pricing.OpenL1PricingState(backingStorage.OpenSubStorage(l1PricingSubspace)), - l2pricing.OpenL2PricingState(backingStorage.OpenSubStorage(l2PricingSubspace)), - retryables.OpenRetryableState(backingStorage.OpenSubStorage(retryablesSubspace), stateDB), - addressTable.Open(backingStorage.OpenSubStorage(addressTableSubspace)), - addressSet.OpenAddressSet(backingStorage.OpenSubStorage(chainOwnerSubspace)), - merkleAccumulator.OpenMerkleAccumulator(backingStorage.OpenSubStorage(sendMerkleSubspace)), - blockhash.OpenBlockhashes(backingStorage.OpenSubStorage(blockhashesSubspace)), + l1pricing.OpenL1PricingState(backingStorage.OpenSubStorage(l1PricingSubspace, true)), + l2pricing.OpenL2PricingState(backingStorage.OpenSubStorage(l2PricingSubspace, true)), + retryables.OpenRetryableState(backingStorage.OpenSubStorage(retryablesSubspace, true), stateDB), + addressTable.Open(backingStorage.OpenSubStorage(addressTableSubspace, true)), + addressSet.OpenAddressSet(backingStorage.OpenSubStorage(chainOwnerSubspace, true)), + merkleAccumulator.OpenMerkleAccumulator(backingStorage.OpenSubStorage(sendMerkleSubspace, true)), + blockhash.OpenBlockhashes(backingStorage.OpenSubStorage(blockhashesSubspace, true)), backingStorage.OpenStorageBackedBigInt(uint64(chainIdOffset)), backingStorage.OpenStorageBackedBytes(chainConfigSubspace), backingStorage.OpenStorageBackedUint64(uint64(genesisBlockNumOffset)), @@ -220,14 +220,14 @@ func InitializeArbosState(stateDB vm.StateDB, burner burn.Burner, chainConfig *p if desiredArbosVersion >= 2 { initialRewardsRecipient = initialChainOwner } - _ = l1pricing.InitializeL1PricingState(sto.OpenSubStorage(l1PricingSubspace), initialRewardsRecipient, initMessage.InitialL1BaseFee) - _ = l2pricing.InitializeL2PricingState(sto.OpenSubStorage(l2PricingSubspace)) - _ = retryables.InitializeRetryableState(sto.OpenSubStorage(retryablesSubspace)) - addressTable.Initialize(sto.OpenSubStorage(addressTableSubspace)) - merkleAccumulator.InitializeMerkleAccumulator(sto.OpenSubStorage(sendMerkleSubspace)) - blockhash.InitializeBlockhashes(sto.OpenSubStorage(blockhashesSubspace)) - - ownersStorage := sto.OpenSubStorage(chainOwnerSubspace) + _ = l1pricing.InitializeL1PricingState(sto.OpenSubStorage(l1PricingSubspace, true), initialRewardsRecipient, initMessage.InitialL1BaseFee) + _ = l2pricing.InitializeL2PricingState(sto.OpenSubStorage(l2PricingSubspace, true)) + _ = retryables.InitializeRetryableState(sto.OpenSubStorage(retryablesSubspace, true)) + addressTable.Initialize(sto.OpenSubStorage(addressTableSubspace, true)) + merkleAccumulator.InitializeMerkleAccumulator(sto.OpenSubStorage(sendMerkleSubspace, true)) + blockhash.InitializeBlockhashes(sto.OpenSubStorage(blockhashesSubspace, true)) + + ownersStorage := sto.OpenSubStorage(chainOwnerSubspace, true) _ = addressSet.Initialize(ownersStorage) _ = addressSet.OpenAddressSet(ownersStorage).Add(initialChainOwner) @@ -385,7 +385,7 @@ func (state *ArbosState) ChainOwners() *addressSet.AddressSet { func (state *ArbosState) SendMerkleAccumulator() *merkleAccumulator.MerkleAccumulator { if state.sendMerkle == nil { - state.sendMerkle = merkleAccumulator.OpenMerkleAccumulator(state.backingStorage.OpenSubStorage(sendMerkleSubspace)) + state.sendMerkle = merkleAccumulator.OpenMerkleAccumulator(state.backingStorage.OpenSubStorage(sendMerkleSubspace, true)) } return state.sendMerkle } diff --git a/arbos/arbosState/arbosstate_test.go b/arbos/arbosState/arbosstate_test.go index c4643c918..384fc9c72 100644 --- a/arbos/arbosState/arbosstate_test.go +++ b/arbos/arbosState/arbosstate_test.go @@ -64,7 +64,7 @@ func TestStorageBackedInt64(t *testing.T) { func TestStorageSlots(t *testing.T) { state, _ := NewArbosMemoryBackedArbOSState() - sto := state.BackingStorage().OpenSubStorage([]byte{}) + sto := state.BackingStorage().OpenSubStorage([]byte{}, true) println("nil address", colors.Blue, storage.NilAddressRepresentation.String(), colors.Clear) diff --git a/arbos/blockhash/blockhash.go b/arbos/blockhash/blockhash.go index 2eedf7f5b..99fb3ef47 100644 --- a/arbos/blockhash/blockhash.go +++ b/arbos/blockhash/blockhash.go @@ -21,7 +21,7 @@ func InitializeBlockhashes(backingStorage *storage.Storage) { } func OpenBlockhashes(backingStorage *storage.Storage) *Blockhashes { - return &Blockhashes{backingStorage, backingStorage.OpenStorageBackedUint64(0)} + return &Blockhashes{backingStorage.NoCacheCopy(), backingStorage.OpenStorageBackedUint64(0)} } func (bh *Blockhashes) L1BlockNumber() (uint64, error) { diff --git a/arbos/l1pricing/batchPoster.go b/arbos/l1pricing/batchPoster.go index 97b7b1623..4ac86307e 100644 --- a/arbos/l1pricing/batchPoster.go +++ b/arbos/l1pricing/batchPoster.go @@ -42,13 +42,13 @@ func InitializeBatchPostersTable(storage *storage.Storage) error { if err := totalFundsDue.SetChecked(common.Big0); err != nil { return err } - return addressSet.Initialize(storage.OpenSubStorage(PosterAddrsKey)) + return addressSet.Initialize(storage.OpenSubStorage(PosterAddrsKey, true)) } func OpenBatchPostersTable(storage *storage.Storage) *BatchPostersTable { return &BatchPostersTable{ - posterAddrs: addressSet.OpenAddressSet(storage.OpenSubStorage(PosterAddrsKey)), - posterInfo: storage.OpenSubStorage(PosterInfoKey), + posterAddrs: addressSet.OpenAddressSet(storage.OpenSubStorage(PosterAddrsKey, true)), + posterInfo: storage.OpenSubStorage(PosterInfoKey, false), totalFundsDue: storage.OpenStorageBackedBigInt(totalFundsDueOffset), } } @@ -68,7 +68,7 @@ func (bpt *BatchPostersTable) OpenPoster(poster common.Address, createIfNotExist } func (bpt *BatchPostersTable) internalOpen(poster common.Address) *BatchPosterState { - bpStorage := bpt.posterInfo.OpenSubStorage(poster.Bytes()) + bpStorage := bpt.posterInfo.OpenSubStorage(poster.Bytes(), false) return &BatchPosterState{ fundsDue: bpStorage.OpenStorageBackedBigInt(0), payTo: bpStorage.OpenStorageBackedAddress(1), diff --git a/arbos/l1pricing/l1pricing.go b/arbos/l1pricing/l1pricing.go index 9772ac028..0d6bca7bf 100644 --- a/arbos/l1pricing/l1pricing.go +++ b/arbos/l1pricing/l1pricing.go @@ -82,7 +82,7 @@ var InitialEquilibrationUnitsV0 = arbmath.UintToBig(60 * params.TxDataNonZeroGas var InitialEquilibrationUnitsV6 = arbmath.UintToBig(params.TxDataNonZeroGasEIP2028 * 10000000) func InitializeL1PricingState(sto *storage.Storage, initialRewardsRecipient common.Address, initialL1BaseFee *big.Int) error { - bptStorage := sto.OpenSubStorage(BatchPosterTableKey) + bptStorage := sto.OpenSubStorage(BatchPosterTableKey, true) if err := InitializeBatchPostersTable(bptStorage); err != nil { return err } @@ -117,7 +117,7 @@ func InitializeL1PricingState(sto *storage.Storage, initialRewardsRecipient comm func OpenL1PricingState(sto *storage.Storage) *L1PricingState { return &L1PricingState{ sto, - OpenBatchPostersTable(sto.OpenSubStorage(BatchPosterTableKey)), + OpenBatchPostersTable(sto.OpenSubStorage(BatchPosterTableKey, true)), sto.OpenStorageBackedAddress(payRewardsToOffset), sto.OpenStorageBackedBigUint(equilibrationUnitsOffset), sto.OpenStorageBackedUint64(inertiaOffset), diff --git a/arbos/queue_test.go b/arbos/queue_test.go index d8d491bdb..abeec49a9 100644 --- a/arbos/queue_test.go +++ b/arbos/queue_test.go @@ -14,7 +14,7 @@ import ( func TestQueue(t *testing.T) { state, statedb := arbosState.NewArbosMemoryBackedArbOSState() - sto := state.BackingStorage().OpenSubStorage([]byte{}) + sto := state.BackingStorage().OpenSubStorage([]byte{}, true) Require(t, storage.InitializeQueue(sto)) q := storage.OpenQueue(sto) diff --git a/arbos/retryables/retryable.go b/arbos/retryables/retryable.go index abea2ab7b..032293854 100644 --- a/arbos/retryables/retryable.go +++ b/arbos/retryables/retryable.go @@ -31,13 +31,13 @@ var ( ) func InitializeRetryableState(sto *storage.Storage) error { - return storage.InitializeQueue(sto.OpenSubStorage(timeoutQueueKey)) + return storage.InitializeQueue(sto.OpenSubStorage(timeoutQueueKey, true)) } func OpenRetryableState(sto *storage.Storage, statedb vm.StateDB) *RetryableState { return &RetryableState{ sto, - storage.OpenQueue(sto.OpenSubStorage(timeoutQueueKey)), + storage.OpenQueue(sto.OpenSubStorage(timeoutQueueKey, true)), } } @@ -73,7 +73,7 @@ func (rs *RetryableState) CreateRetryable( beneficiary common.Address, calldata []byte, ) (*Retryable, error) { - sto := rs.retryables.OpenSubStorage(id.Bytes()) + sto := rs.retryables.OpenSubStorage(id.Bytes(), false) ret := &Retryable{ id, sto, @@ -100,7 +100,7 @@ func (rs *RetryableState) CreateRetryable( } func (rs *RetryableState) OpenRetryable(id common.Hash, currentTimestamp uint64) (*Retryable, error) { - sto := rs.retryables.OpenSubStorage(id.Bytes()) + sto := rs.retryables.OpenSubStorage(id.Bytes(), false) timeoutStorage := sto.OpenStorageBackedUint64(timeoutOffset) timeout, err := timeoutStorage.Get() if timeout == 0 || timeout < currentTimestamp || err != nil { @@ -134,7 +134,7 @@ func (rs *RetryableState) RetryableSizeBytes(id common.Hash, currentTime uint64) } func (rs *RetryableState) DeleteRetryable(id common.Hash, evm *vm.EVM, scenario util.TracingScenario) (bool, error) { - retStorage := rs.retryables.OpenSubStorage(id.Bytes()) + retStorage := rs.retryables.OpenSubStorage(id.Bytes(), false) timeout, err := retStorage.GetByUint64(timeoutOffset) if timeout == (common.Hash{}) || err != nil { return false, err @@ -157,7 +157,7 @@ func (rs *RetryableState) DeleteRetryable(id common.Hash, evm *vm.EVM, scenario _ = retStorage.ClearByUint64(beneficiaryOffset) _ = retStorage.ClearByUint64(timeoutOffset) _ = retStorage.ClearByUint64(timeoutWindowsLeftOffset) - err = retStorage.OpenSubStorage(calldataKey).ClearBytes() + err = retStorage.OpenSubStorage(calldataKey, false).ClearBytes() return true, err } @@ -291,7 +291,7 @@ func (rs *RetryableState) TryToReapOneRetryable(currentTimestamp uint64, evm *vm if err != nil || id == nil { return err } - retryableStorage := rs.retryables.OpenSubStorage(id.Bytes()) + retryableStorage := rs.retryables.OpenSubStorage(id.Bytes(), false) timeoutStorage := retryableStorage.OpenStorageBackedUint64(timeoutOffset) timeout, err := timeoutStorage.Get() if err != nil { diff --git a/arbos/storage/queue.go b/arbos/storage/queue.go index 55231d3a9..032ac11aa 100644 --- a/arbos/storage/queue.go +++ b/arbos/storage/queue.go @@ -25,7 +25,7 @@ func InitializeQueue(sto *Storage) error { func OpenQueue(sto *Storage) *Queue { return &Queue{ - sto, + sto.NoCacheCopy(), sto.OpenStorageBackedUint64(0), sto.OpenStorageBackedUint64(1), } diff --git a/arbos/storage/storage.go b/arbos/storage/storage.go index 478ad68f8..b93c835ff 100644 --- a/arbos/storage/storage.go +++ b/arbos/storage/storage.go @@ -4,6 +4,7 @@ package storage import ( + "bytes" "fmt" "math/big" @@ -17,6 +18,7 @@ import ( "github.com/offchainlabs/nitro/arbos/burn" "github.com/offchainlabs/nitro/arbos/util" "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/containers" ) // Storage allows ArbOS to store data persistently in the Ethereum-compatible stateDB. This is represented in @@ -43,12 +45,18 @@ type Storage struct { db vm.StateDB storageKey []byte burner burn.Burner + hashCache *containers.SafeLruCache[string, []byte] } const StorageReadCost = params.SloadGasEIP2200 const StorageWriteCost = params.SstoreSetGasEIP2200 const StorageWriteZeroCost = params.SstoreResetGasEIP2200 +const storageKeyCacheSize = 1024 + +// TODO(magic) rename? +var storageHashCache = containers.NewSafeLruCache[string, []byte](storageKeyCacheSize) + // NewGeth uses a Geth database to create an evm key-value store func NewGeth(statedb vm.StateDB, burner burn.Burner) *Storage { account := common.HexToAddress("0xA4B05FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") @@ -58,6 +66,7 @@ func NewGeth(statedb vm.StateDB, burner burn.Burner) *Storage { db: statedb, storageKey: []byte{}, burner: burner, + hashCache: storageHashCache, } } @@ -81,15 +90,16 @@ func NewMemoryBackedStateDB() vm.StateDB { // a page, to preserve contiguity within a page. This will reduce cost if/when Ethereum switches to storage // representations that reward contiguity. // Because page numbers are 248 bits, this gives us 124-bit security against collision attacks, which is good enough. -func mapAddress(storageKey []byte, key common.Hash) common.Hash { +func (store *Storage) mapAddress(storageKey []byte, key common.Hash) common.Hash { keyBytes := key.Bytes() boundary := common.HashLength - 1 - return common.BytesToHash( + mapped := common.BytesToHash( append( - crypto.Keccak256(storageKey, keyBytes[:boundary])[:boundary], + store.cachedKeccak(storageKey, keyBytes[:boundary])[:boundary], keyBytes[boundary], ), ) + return mapped } func writeCost(value common.Hash) uint64 { @@ -111,11 +121,11 @@ func (store *Storage) Get(key common.Hash) (common.Hash, error) { if info := store.burner.TracingInfo(); info != nil { info.RecordStorageGet(key) } - return store.db.GetState(store.account, mapAddress(store.storageKey, key)), nil + return store.db.GetState(store.account, store.mapAddress(store.storageKey, key)), nil } func (store *Storage) GetStorageSlot(key common.Hash) common.Hash { - return mapAddress(store.storageKey, key) + return store.mapAddress(store.storageKey, key) } func (store *Storage) GetUint64(key common.Hash) (uint64, error) { @@ -143,7 +153,7 @@ func (store *Storage) Set(key common.Hash, value common.Hash) error { if info := store.burner.TracingInfo(); info != nil { info.RecordStorageSet(key, value) } - store.db.SetState(store.account, mapAddress(store.storageKey, key), value) + store.db.SetState(store.account, store.mapAddress(store.storageKey, key), value) return nil } @@ -171,12 +181,27 @@ func (store *Storage) Swap(key common.Hash, newValue common.Hash) (common.Hash, return oldValue, store.Set(key, newValue) } -func (store *Storage) OpenSubStorage(id []byte) *Storage { +func (store *Storage) OpenSubStorage(id []byte, cacheKeys bool) *Storage { + var hashCache *containers.SafeLruCache[string, []byte] + if cacheKeys { + hashCache = storageHashCache + } return &Storage{ store.account, store.db, - crypto.Keccak256(store.storageKey, id), + store.cachedKeccak(store.storageKey, id), store.burner, + hashCache, + } +} + +func (store *Storage) NoCacheCopy() *Storage { + return &Storage{ + store.account, + store.db, + store.storageKey, + store.burner, + nil, } } @@ -266,6 +291,24 @@ func (store *Storage) Keccak(data ...[]byte) ([]byte, error) { return crypto.Keccak256(data...), nil } +func (store *Storage) cachedKeccak(data ...[]byte) []byte { + if store.hashCache == nil { + return crypto.Keccak256(data...) + } + keyString := string(bytes.Join(data, []byte{})) + hash, isCached := store.hashCache.Get(keyString) + if isCached { + return hash + } + // TODO(magic) we might miss the warning if concurrent Add will be before + if store.hashCache.Size()-store.hashCache.Len() == 1 { + log.Warn("Hash cache almost full, but we didn't expect that. We may be caching some non-static keys.") + } + hash = crypto.Keccak256(data...) + store.hashCache.Add(keyString, hash) + return hash +} + func (store *Storage) KeccakHash(data ...[]byte) (common.Hash, error) { bytes, err := store.Keccak(data...) return common.BytesToHash(bytes), err @@ -279,7 +322,7 @@ type StorageSlot struct { } func (store *Storage) NewSlot(offset uint64) StorageSlot { - return StorageSlot{store.account, store.db, mapAddress(store.storageKey, util.UintToHash(offset)), store.burner} + return StorageSlot{store.account, store.db, store.mapAddress(store.storageKey, util.UintToHash(offset)), store.burner} } func (ss *StorageSlot) Get() (common.Hash, error) { @@ -590,7 +633,7 @@ type StorageBackedBytes struct { func (store *Storage) OpenStorageBackedBytes(id []byte) StorageBackedBytes { return StorageBackedBytes{ - *store.OpenSubStorage(id), + *store.OpenSubStorage(id, false), } } diff --git a/util/containers/safe_lru.go b/util/containers/safe_lru.go new file mode 100644 index 000000000..40e7d993e --- /dev/null +++ b/util/containers/safe_lru.go @@ -0,0 +1,82 @@ +package containers + +import ( + "sync" +) + +// thread safe version of containers.LruCache +type SafeLruCache[K comparable, V any] struct { + inner *LruCache[K, V] + mutex sync.RWMutex +} + +func NewSafeLruCache[K comparable, V any](size int) *SafeLruCache[K, V] { + return NewSafeLruCacheWithOnEvict[K, V](size, nil) +} + +func NewSafeLruCacheWithOnEvict[K comparable, V any](size int, onEvict func(K, V)) *SafeLruCache[K, V] { + return &SafeLruCache[K, V]{ + inner: NewLruCacheWithOnEvict(size, onEvict), + } +} + +// Returns true if an item was evicted +func (c *SafeLruCache[K, V]) Add(key K, value V) bool { + c.mutex.Lock() + defer c.mutex.Unlock() + return c.inner.Add(key, value) +} + +func (c *SafeLruCache[K, V]) Get(key K) (V, bool) { + c.mutex.Lock() + defer c.mutex.Unlock() + return c.inner.Get(key) +} + +func (c *SafeLruCache[K, V]) Contains(key K) bool { + c.mutex.RLock() + defer c.mutex.RUnlock() + return c.inner.Contains(key) +} + +func (c *SafeLruCache[K, V]) Remove(key K) { + c.mutex.Lock() + defer c.mutex.Unlock() + c.inner.Remove(key) +} + +func (c *SafeLruCache[K, V]) GetOldest() (K, V, bool) { + c.mutex.RLock() + defer c.mutex.RUnlock() + return c.inner.GetOldest() +} + +func (c *SafeLruCache[K, V]) RemoveOldest() { + c.mutex.Lock() + defer c.mutex.Unlock() + c.inner.RemoveOldest() +} + +func (c *SafeLruCache[K, V]) Len() int { + c.mutex.RLock() + defer c.mutex.RUnlock() + return c.inner.Len() +} + +func (c *SafeLruCache[K, V]) Size() int { + c.mutex.RLock() + defer c.mutex.RUnlock() + return c.inner.Size() +} + +func (c *SafeLruCache[K, V]) Clear() { + c.mutex.Lock() + defer c.mutex.Unlock() + c.inner.Clear() +} + +func (c *SafeLruCache[K, V]) Resize(newSize int) { + c.mutex.Lock() + defer c.mutex.Unlock() + c.inner.Resize(newSize) +} From 691a213eb0127a20d32114dfcd73a652a84c2ea4 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 18 Jul 2023 16:42:33 +0000 Subject: [PATCH 058/775] add onetime warning when hash cache unexpectedly fills up --- arbos/storage/storage.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arbos/storage/storage.go b/arbos/storage/storage.go index b93c835ff..39af072f0 100644 --- a/arbos/storage/storage.go +++ b/arbos/storage/storage.go @@ -7,6 +7,7 @@ import ( "bytes" "fmt" "math/big" + "sync/atomic" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" @@ -54,8 +55,8 @@ const StorageWriteZeroCost = params.SstoreResetGasEIP2200 const storageKeyCacheSize = 1024 -// TODO(magic) rename? var storageHashCache = containers.NewSafeLruCache[string, []byte](storageKeyCacheSize) +var cacheFullLogged atomic.Bool // NewGeth uses a Geth database to create an evm key-value store func NewGeth(statedb vm.StateDB, burner burn.Burner) *Storage { @@ -300,12 +301,11 @@ func (store *Storage) cachedKeccak(data ...[]byte) []byte { if isCached { return hash } - // TODO(magic) we might miss the warning if concurrent Add will be before - if store.hashCache.Size()-store.hashCache.Len() == 1 { - log.Warn("Hash cache almost full, but we didn't expect that. We may be caching some non-static keys.") - } hash = crypto.Keccak256(data...) - store.hashCache.Add(keyString, hash) + evicted := store.hashCache.Add(keyString, hash) + if evicted && cacheFullLogged.CompareAndSwap(false, true) { + log.Warn("Hash cache full, we didn't expect that. Some non-static storage keys may fill up the cache.") + } return hash } From f802560c966b27eeba1b68a51585e1238ecb5787 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 18 Jul 2023 18:44:13 +0000 Subject: [PATCH 059/775] fix race in mapAddress --- arbos/storage/storage.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/arbos/storage/storage.go b/arbos/storage/storage.go index 39af072f0..f234e69d5 100644 --- a/arbos/storage/storage.go +++ b/arbos/storage/storage.go @@ -94,13 +94,10 @@ func NewMemoryBackedStateDB() vm.StateDB { func (store *Storage) mapAddress(storageKey []byte, key common.Hash) common.Hash { keyBytes := key.Bytes() boundary := common.HashLength - 1 - mapped := common.BytesToHash( - append( - store.cachedKeccak(storageKey, keyBytes[:boundary])[:boundary], - keyBytes[boundary], - ), - ) - return mapped + mapped := make([]byte, 0, common.HashLength) + mapped = append(mapped, store.cachedKeccak(storageKey, keyBytes[:boundary])[:boundary]...) + mapped = append(mapped, keyBytes[boundary]) + return common.BytesToHash(mapped) } func writeCost(value common.Hash) uint64 { @@ -292,13 +289,14 @@ func (store *Storage) Keccak(data ...[]byte) ([]byte, error) { return crypto.Keccak256(data...), nil } +// note: returned slice is not thread-safe func (store *Storage) cachedKeccak(data ...[]byte) []byte { if store.hashCache == nil { return crypto.Keccak256(data...) } keyString := string(bytes.Join(data, []byte{})) - hash, isCached := store.hashCache.Get(keyString) - if isCached { + hash, wasCached := store.hashCache.Get(keyString) + if wasCached { return hash } hash = crypto.Keccak256(data...) From 0fd07c6dbbee64e8c80f45125aec670c52ce7114 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 18 Jul 2023 19:04:26 +0000 Subject: [PATCH 060/775] remove redundant mapAddress parameter --- arbos/storage/storage.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arbos/storage/storage.go b/arbos/storage/storage.go index f234e69d5..66f3d4947 100644 --- a/arbos/storage/storage.go +++ b/arbos/storage/storage.go @@ -91,11 +91,11 @@ func NewMemoryBackedStateDB() vm.StateDB { // a page, to preserve contiguity within a page. This will reduce cost if/when Ethereum switches to storage // representations that reward contiguity. // Because page numbers are 248 bits, this gives us 124-bit security against collision attacks, which is good enough. -func (store *Storage) mapAddress(storageKey []byte, key common.Hash) common.Hash { +func (store *Storage) mapAddress(key common.Hash) common.Hash { keyBytes := key.Bytes() boundary := common.HashLength - 1 mapped := make([]byte, 0, common.HashLength) - mapped = append(mapped, store.cachedKeccak(storageKey, keyBytes[:boundary])[:boundary]...) + mapped = append(mapped, store.cachedKeccak(store.storageKey, keyBytes[:boundary])[:boundary]...) mapped = append(mapped, keyBytes[boundary]) return common.BytesToHash(mapped) } @@ -119,11 +119,11 @@ func (store *Storage) Get(key common.Hash) (common.Hash, error) { if info := store.burner.TracingInfo(); info != nil { info.RecordStorageGet(key) } - return store.db.GetState(store.account, store.mapAddress(store.storageKey, key)), nil + return store.db.GetState(store.account, store.mapAddress(key)), nil } func (store *Storage) GetStorageSlot(key common.Hash) common.Hash { - return store.mapAddress(store.storageKey, key) + return store.mapAddress(key) } func (store *Storage) GetUint64(key common.Hash) (uint64, error) { @@ -151,7 +151,7 @@ func (store *Storage) Set(key common.Hash, value common.Hash) error { if info := store.burner.TracingInfo(); info != nil { info.RecordStorageSet(key, value) } - store.db.SetState(store.account, store.mapAddress(store.storageKey, key), value) + store.db.SetState(store.account, store.mapAddress(key), value) return nil } @@ -320,7 +320,7 @@ type StorageSlot struct { } func (store *Storage) NewSlot(offset uint64) StorageSlot { - return StorageSlot{store.account, store.db, store.mapAddress(store.storageKey, util.UintToHash(offset)), store.burner} + return StorageSlot{store.account, store.db, store.mapAddress(util.UintToHash(offset)), store.burner} } func (ss *StorageSlot) Get() (common.Hash, error) { From 574270621f624c27c2eabda16cc005c3022c8408 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 24 Jul 2023 15:10:04 -0500 Subject: [PATCH 061/775] upgrade log level --- util/headerreader/header_reader.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index 1d52e8f78..85a510283 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -312,10 +312,18 @@ func (s *HeaderReader) logIfHeaderIsOld() { headerTime := time.Since(l1Timetamp) if headerTime >= s.config().OldHeaderTimeout { s.setError(fmt.Errorf("latest header is at least %v old", headerTime)) - log.Warn( - "latest L1 block is old", "l1Block", storedHeader.Number, - "l1Timestamp", l1Timetamp, "age", headerTime, - ) + // Upgrade the log level from warn to error when lossing connection to L1 for too long + if headerTime >= DefaultConfig.OldHeaderTimeout { + log.Error( + "latest L1 block is old", "l1Block", storedHeader.Number, + "l1Timestamp", l1Timetamp, "age", headerTime, + ) + } else { + log.Warn( + "latest L1 block is old", "l1Block", storedHeader.Number, + "l1Timestamp", l1Timetamp, "age", headerTime, + ) + } } } From 3e8bc374d0f9a5d2f55003c7a6567a66b732b8b7 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 24 Jul 2023 15:12:25 -0500 Subject: [PATCH 062/775] typo fix --- util/headerreader/header_reader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index 85a510283..2bd8f198a 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -312,7 +312,7 @@ func (s *HeaderReader) logIfHeaderIsOld() { headerTime := time.Since(l1Timetamp) if headerTime >= s.config().OldHeaderTimeout { s.setError(fmt.Errorf("latest header is at least %v old", headerTime)) - // Upgrade the log level from warn to error when lossing connection to L1 for too long + // Upgrade the log level from warn to error when losing connection to L1 for too long if headerTime >= DefaultConfig.OldHeaderTimeout { log.Error( "latest L1 block is old", "l1Block", storedHeader.Number, From bace811afa437b8770b6751765565817fe73a6ad Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Wed, 9 Aug 2023 16:23:25 -0700 Subject: [PATCH 063/775] Refactor resourcemanager as suggested in PR#1744 --- .../resourcemanager/resource_management.go | 26 +++++--- .../resource_management_test.go | 63 ++++++++++--------- 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/arbnode/resourcemanager/resource_management.go b/arbnode/resourcemanager/resource_management.go index b1bdc45d7..7d0ab47a0 100644 --- a/arbnode/resourcemanager/resource_management.go +++ b/arbnode/resourcemanager/resource_management.go @@ -23,6 +23,7 @@ var ( limitCheckDurationHistogram = metrics.NewRegisteredHistogram("arb/rpc/limitcheck/duration", nil, metrics.NewBoundedHistogramSample()) limitCheckSuccessCounter = metrics.NewRegisteredCounter("arb/rpc/limitcheck/success", nil) limitCheckFailureCounter = metrics.NewRegisteredCounter("arb/rpc/limitcheck/failure", nil) + errNotSupported = errors.New("not supported") ) // Init adds the resource manager's httpServer to a custom hook in geth. @@ -33,7 +34,15 @@ var ( func Init(conf *Config) { if conf.MemoryLimitPercent > 0 { node.WrapHTTPHandler = func(srv http.Handler) (http.Handler, error) { - return newHttpServer(srv, newLimitChecker(conf)), nil + var c limitChecker + var err error + c, err = newCgroupsMemoryLimitCheckerIfSupported(conf) + if errors.Is(err, errNotSupported) { + log.Error("No method for determining memory usage and limits was discovered, disabled memory limit RPC throttling") + c = &trivialLimitChecker{} + } + + return newHttpServer(srv, c), nil } } } @@ -95,25 +104,22 @@ func isSupported(c limitChecker) bool { return err == nil } -// newLimitChecker attempts to auto-discover the mechanism by which it -// can check system limits. Currently Cgroups V1 and V2 are supported. -// If no supported mechanism is discovered, it logs an error and -// fails open, ie it creates a trivialLimitChecker that does no checks. -func newLimitChecker(conf *Config) limitChecker { +// newCgroupsMemoryLimitCheckerIfSupported attempts to auto-discover whether +// Cgroups V1 or V2 is supported for checking system memory limits. +func newCgroupsMemoryLimitCheckerIfSupported(conf *Config) (*cgroupsMemoryLimitChecker, error) { c := newCgroupsMemoryLimitChecker(cgroupsV1MemoryFiles, conf.MemoryLimitPercent) if isSupported(c) { log.Info("Cgroups v1 detected, enabling memory limit RPC throttling") - return c + return c, nil } c = newCgroupsMemoryLimitChecker(cgroupsV2MemoryFiles, conf.MemoryLimitPercent) if isSupported(c) { log.Info("Cgroups v2 detected, enabling memory limit RPC throttling") - return c + return c, nil } - log.Error("No method for determining memory usage and limits was discovered, disabled memory limit RPC throttling") - return &trivialLimitChecker{} + return nil, errNotSupported } // trivialLimitChecker checks no limits, so its limits are never exceeded. diff --git a/arbnode/resourcemanager/resource_management_test.go b/arbnode/resourcemanager/resource_management_test.go index 699bcd24e..21f1dca23 100644 --- a/arbnode/resourcemanager/resource_management_test.go +++ b/arbnode/resourcemanager/resource_management_test.go @@ -57,36 +57,37 @@ func TestCgroupsFailIfCantOpen(t *testing.T) { } } -func TestCgroupsLimitNotExceeded(t *testing.T) { - testFiles := makeCgroupsTestDir(t.TempDir()) - c := newCgroupsMemoryLimitChecker(testFiles, 95) - - var err error - if err = updateFakeCgroupFiles(c, 1000, 1000, 51); err != nil { - t.Fatal(err) - } - exceeded, err := c.isLimitExceeded() - if err != nil { - t.Fatal(err) - } - if exceeded { - t.Fatal("Expected under limit") - } -} - -func TestCgroupsLimitExceeded(t *testing.T) { - testFiles := makeCgroupsTestDir(t.TempDir()) - c := newCgroupsMemoryLimitChecker(testFiles, 95) - - var err error - if err = updateFakeCgroupFiles(c, 1000, 1000, 50); err != nil { - t.Fatal(err) - } - exceeded, err := c.isLimitExceeded() - if err != nil { - t.Fatal(err) - } - if !exceeded { - t.Fatal("Expected over limit") +func TestCgroupsMemoryLimit(t *testing.T) { + for _, tc := range []struct { + desc string + inactive int + want bool + }{ + { + desc: "limit should be exceeded", + inactive: 50, + want: true, + }, + { + desc: "limit should not be exceeded", + inactive: 51, + want: false, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + testFiles := makeCgroupsTestDir(t.TempDir()) + c := newCgroupsMemoryLimitChecker(testFiles, 95) + if err := updateFakeCgroupFiles(c, 1000, 1000, tc.inactive); err != nil { + t.Fatalf("Updating cgroup files: %v", err) + } + exceeded, err := c.isLimitExceeded() + if err != nil { + t.Fatalf("Checking if limit exceeded: %v", err) + } + if exceeded != tc.want { + t.Errorf("isLimitExceeded() = %t, want %t", exceeded, tc.want) + } + }, + ) } } From 33f63430f6d229ee9a91364378082e5dfd08ad8e Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 10 Aug 2023 10:29:10 -0700 Subject: [PATCH 064/775] Fix comments on PR #1744 --- arbnode/resourcemanager/resource_management.go | 3 +-- arbnode/resourcemanager/resource_management_test.go | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arbnode/resourcemanager/resource_management.go b/arbnode/resourcemanager/resource_management.go index 7d0ab47a0..c4d7ee379 100644 --- a/arbnode/resourcemanager/resource_management.go +++ b/arbnode/resourcemanager/resource_management.go @@ -35,8 +35,7 @@ func Init(conf *Config) { if conf.MemoryLimitPercent > 0 { node.WrapHTTPHandler = func(srv http.Handler) (http.Handler, error) { var c limitChecker - var err error - c, err = newCgroupsMemoryLimitCheckerIfSupported(conf) + c, err := newCgroupsMemoryLimitCheckerIfSupported(conf) if errors.Is(err, errNotSupported) { log.Error("No method for determining memory usage and limits was discovered, disabled memory limit RPC throttling") c = &trivialLimitChecker{} diff --git a/arbnode/resourcemanager/resource_management_test.go b/arbnode/resourcemanager/resource_management_test.go index 21f1dca23..ba791fd72 100644 --- a/arbnode/resourcemanager/resource_management_test.go +++ b/arbnode/resourcemanager/resource_management_test.go @@ -51,8 +51,7 @@ func makeCgroupsTestDir(cgroupDir string) cgroupsMemoryFiles { func TestCgroupsFailIfCantOpen(t *testing.T) { testFiles := makeCgroupsTestDir(t.TempDir()) c := newCgroupsMemoryLimitChecker(testFiles, 95) - var err error - if _, err = c.isLimitExceeded(); err == nil { + if _, err := c.isLimitExceeded(); err == nil { t.Fatal("Should fail open if can't read files") } } From 468a2062624dba3ea2c5f4d3bb9a2638d1e9c9fc Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 10 Aug 2023 13:16:45 -0600 Subject: [PATCH 065/775] Default to using "safe" instead of "finalized" for delayed sequencing --- arbnode/delayed_sequencer.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/delayed_sequencer.go b/arbnode/delayed_sequencer.go index f45a85ac4..aa6d43785 100644 --- a/arbnode/delayed_sequencer.go +++ b/arbnode/delayed_sequencer.go @@ -52,14 +52,14 @@ func DelayedSequencerConfigAddOptions(prefix string, f *flag.FlagSet) { var DefaultDelayedSequencerConfig = DelayedSequencerConfig{ Enable: false, FinalizeDistance: 20, - RequireFullFinality: true, + RequireFullFinality: false, UseMergeFinality: true, } var TestDelayedSequencerConfig = DelayedSequencerConfig{ Enable: true, FinalizeDistance: 20, - RequireFullFinality: true, + RequireFullFinality: false, UseMergeFinality: true, } From 093d159a41399362669649d0aea1eec666daa7f7 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 16 Aug 2023 17:22:38 -0600 Subject: [PATCH 066/775] Support new preimage types in proving --- Makefile | 6 +- arbitrator/Cargo.lock | 173 ++++++++++++- arbitrator/arbutil/Cargo.toml | 4 + arbitrator/arbutil/src/lib.rs | 2 + arbitrator/arbutil/src/types.rs | 25 ++ arbitrator/jit/src/gostack.rs | 4 + arbitrator/jit/src/machine.rs | 20 +- arbitrator/jit/src/socket.rs | 1 - arbitrator/jit/src/wavmio.rs | 80 +++--- arbitrator/prover/src/host.rs | 20 +- arbitrator/prover/src/lib.rs | 13 +- arbitrator/prover/src/machine.rs | 36 ++- arbitrator/prover/src/main.rs | 58 ++--- .../prover/test-cases/rust/data/preimages.bin | Bin 19 -> 40 bytes .../prover/test-cases/rust/src/bin/host-io.rs | 17 +- arbitrator/wasm-libraries/Cargo.lock | 239 ++++++++++++++++++ arbitrator/wasm-libraries/host-io/Cargo.toml | 1 + arbitrator/wasm-libraries/host-io/src/lib.rs | 38 ++- arbstate/inbox.go | 20 +- arbutil/preimage_type.go | 13 + cmd/replay/db.go | 3 +- cmd/replay/main.go | 8 +- contracts | 2 +- das/syncing_fallback_storage.go | 22 +- staker/stateless_block_validator.go | 8 +- system_tests/validation_mock_test.go | 19 +- util/jsonapi/preimages.go | 4 +- validator/server_api/json.go | 15 +- validator/server_arb/machine.go | 19 +- validator/server_arb/preimage_resolver.go | 6 +- validator/server_arb/validator_spawner.go | 31 ++- validator/server_jit/jit_machine.go | 45 +--- validator/server_jit/spawner.go | 10 +- validator/validation_entry.go | 3 +- wavmio/higher.go | 9 +- wavmio/raw.go | 2 +- wavmio/raw.s | 2 +- wavmio/stub.go | 3 +- 38 files changed, 732 insertions(+), 249 deletions(-) create mode 100644 arbitrator/arbutil/src/types.rs create mode 100644 arbutil/preimage_type.go diff --git a/Makefile b/Makefile index 205025dfe..fdbde677f 100644 --- a/Makefile +++ b/Makefile @@ -261,17 +261,17 @@ $(output_root)/machines/latest/soft-float.wasm: $(DEP_PREDICATE) \ --export wavm__f32_demote_f64 \ --export wavm__f64_promote_f32 -$(output_root)/machines/latest/go_stub.wasm: $(DEP_PREDICATE) $(wildcard arbitrator/wasm-libraries/go-stub/src/*/*) +$(output_root)/machines/latest/go_stub.wasm: $(DEP_PREDICATE) $(wildcard arbitrator/wasm-libraries/go-stub/src/*) mkdir -p $(output_root)/machines/latest cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --package go-stub install arbitrator/wasm-libraries/target/wasm32-wasi/release/go_stub.wasm $@ -$(output_root)/machines/latest/host_io.wasm: $(DEP_PREDICATE) $(wildcard arbitrator/wasm-libraries/host-io/src/*/*) +$(output_root)/machines/latest/host_io.wasm: $(DEP_PREDICATE) $(wildcard arbitrator/wasm-libraries/host-io/src/*) mkdir -p $(output_root)/machines/latest cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --package host-io install arbitrator/wasm-libraries/target/wasm32-wasi/release/host_io.wasm $@ -$(output_root)/machines/latest/brotli.wasm: $(DEP_PREDICATE) $(wildcard arbitrator/wasm-libraries/brotli/src/*/*) .make/cbrotli-wasm +$(output_root)/machines/latest/brotli.wasm: $(DEP_PREDICATE) $(wildcard arbitrator/wasm-libraries/brotli/src/*) .make/cbrotli-wasm mkdir -p $(output_root)/machines/latest cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --package brotli install arbitrator/wasm-libraries/target/wasm32-wasi/release/brotli.wasm $@ diff --git a/arbitrator/Cargo.lock b/arbitrator/Cargo.lock index 41522a82b..472c9e4b5 100644 --- a/arbitrator/Cargo.lock +++ b/arbitrator/Cargo.lock @@ -55,6 +55,12 @@ dependencies = [ [[package]] name = "arbutil" version = "0.1.0" +dependencies = [ + "digest 0.10.7", + "num_enum", + "sha2", + "sha3 0.10.8", +] [[package]] name = "arrayvec" @@ -119,6 +125,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "block-padding" version = "0.2.1" @@ -224,6 +239,15 @@ dependencies = [ "windows-sys 0.33.0", ] +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + [[package]] name = "cranelift-bforest" version = "0.86.1" @@ -334,6 +358,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "darling" version = "0.13.4" @@ -378,6 +412,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", +] + [[package]] name = "either" version = "1.6.1" @@ -425,6 +469,12 @@ dependencies = [ "syn 1.0.76", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "eyre" version = "0.6.5" @@ -484,7 +534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "fallible-iterator", - "indexmap", + "indexmap 1.8.1", "stable_deref_trait", ] @@ -503,6 +553,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "heck" version = "0.3.3" @@ -555,6 +611,16 @@ dependencies = [ "hashbrown 0.11.2", ] +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + [[package]] name = "inkwell" version = "0.1.0-beta.4" @@ -617,7 +683,7 @@ dependencies = [ "parking_lot 0.12.1", "rand", "rand_pcg", - "sha3", + "sha3 0.9.1", "structopt", "thiserror", "wasmer", @@ -636,9 +702,12 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.0" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] [[package]] name = "lazy_static" @@ -852,6 +921,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "object" version = "0.28.4" @@ -970,6 +1060,16 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1010,7 +1110,7 @@ dependencies = [ "arbutil", "bincode", "brotli2", - "digest", + "digest 0.9.0", "eyre", "fnv", "hex", @@ -1024,7 +1124,7 @@ dependencies = [ "serde", "serde_json", "serde_with", - "sha3", + "sha3 0.9.1", "smallvec", "static_assertions", "structopt", @@ -1177,7 +1277,7 @@ checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" dependencies = [ "bytecheck", "hashbrown 0.12.3", - "indexmap", + "indexmap 1.8.1", "ptr_meta", "rend", "rkyv_derive", @@ -1323,18 +1423,39 @@ dependencies = [ "syn 1.0.76", ] +[[package]] +name = "sha2" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha3" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" dependencies = [ - "block-buffer", - "digest", + "block-buffer 0.9.0", + "digest 0.9.0", "keccak", "opaque-debug", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + [[package]] name = "slice-group-by" version = "0.3.0" @@ -1455,6 +1576,23 @@ dependencies = [ "syn 1.0.76", ] +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" +dependencies = [ + "indexmap 2.0.0", + "toml_datetime", + "winnow", +] + [[package]] name = "tracing" version = "0.1.34" @@ -1635,7 +1773,7 @@ checksum = "740f96c9e5d49f0056d716977657f3f7f8eea9923b41f46d1046946707aa038f" dependencies = [ "bytes", "cfg-if", - "indexmap", + "indexmap 1.8.1", "js-sys", "more-asserts", "serde", @@ -1740,7 +1878,7 @@ checksum = "3bc6cd7a2d2d3bd901ff491f131188c1030694350685279e16e1233b9922846b" dependencies = [ "enum-iterator", "enumset", - "indexmap", + "indexmap 1.8.1", "more-asserts", "rkyv", "target-lexicon", @@ -1758,7 +1896,7 @@ dependencies = [ "cfg-if", "corosensei", "enum-iterator", - "indexmap", + "indexmap 1.8.1", "lazy_static", "libc", "mach", @@ -1783,7 +1921,7 @@ version = "0.84.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77dc97c22bb5ce49a47b745bed8812d30206eff5ef3af31424f2c1820c0974b2" dependencies = [ - "indexmap", + "indexmap 1.8.1", ] [[package]] @@ -1914,3 +2052,12 @@ name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "winnow" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +dependencies = [ + "memchr", +] diff --git a/arbitrator/arbutil/Cargo.toml b/arbitrator/arbutil/Cargo.toml index e8b0e86d3..cab0b2298 100644 --- a/arbitrator/arbutil/Cargo.toml +++ b/arbitrator/arbutil/Cargo.toml @@ -4,3 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +digest = "0.10.7" +num_enum = "0.7.0" +sha2 = "0.10.7" +sha3 = "0.10.8" diff --git a/arbitrator/arbutil/src/lib.rs b/arbitrator/arbutil/src/lib.rs index 44d608682..aa748b84e 100644 --- a/arbitrator/arbutil/src/lib.rs +++ b/arbitrator/arbutil/src/lib.rs @@ -3,5 +3,7 @@ pub mod color; pub mod format; +mod types; pub use color::{Color, DebugColor}; +pub use types::PreimageType; diff --git a/arbitrator/arbutil/src/types.rs b/arbitrator/arbutil/src/types.rs new file mode 100644 index 000000000..165a90d8c --- /dev/null +++ b/arbitrator/arbutil/src/types.rs @@ -0,0 +1,25 @@ +// Copyright 2022-2023, Offchain Labs, Inc. +// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE + +use digest::Digest; +use num_enum::{IntoPrimitive, TryFromPrimitive}; + +// These values must be kept in sync with `arbutil/preimage_type.go`, +// and the if statement in `contracts/src/osp/OneStepProverHostIo.sol` (search for "UNKNOWN_PREIMAGE_TYPE"). +#[derive( + Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TryFromPrimitive, IntoPrimitive, +)] +#[repr(u8)] +pub enum PreimageType { + Keccak256, + Sha2_256, +} + +impl PreimageType { + pub fn hash(&self, preimage: &[u8]) -> [u8; 32] { + match self { + Self::Keccak256 => sha3::Keccak256::digest(preimage).into(), + Self::Sha2_256 => sha2::Sha256::digest(preimage).into(), + } + } +} diff --git a/arbitrator/jit/src/gostack.rs b/arbitrator/jit/src/gostack.rs index 80fccf179..bf7ac4767 100644 --- a/arbitrator/jit/src/gostack.rs +++ b/arbitrator/jit/src/gostack.rs @@ -64,6 +64,10 @@ impl GoStack { Self { start, memory } } + pub fn shift_start(&mut self, offset: u32) { + self.start += offset; + } + fn view(&self) -> &MemoryView { self.memory.view() } diff --git a/arbitrator/jit/src/machine.rs b/arbitrator/jit/src/machine.rs index 2cc97dd9c..ed22e12ef 100644 --- a/arbitrator/jit/src/machine.rs +++ b/arbitrator/jit/src/machine.rs @@ -6,7 +6,7 @@ use crate::{ wavmio, wavmio::Bytes32, Opts, }; -use arbutil::Color; +use arbutil::{Color, PreimageType}; use eyre::{bail, Result, WrapErr}; use sha3::{Digest, Keccak256}; use thiserror::Error; @@ -108,7 +108,13 @@ pub fn create(opts: &Opts, env: WasmEnv) -> (Instance, FunctionEnv, Sto "github.com/offchainlabs/nitro/wavmio.setGlobalStateU64" => func!(wavmio::set_global_state_u64), "github.com/offchainlabs/nitro/wavmio.readInboxMessage" => func!(wavmio::read_inbox_message), "github.com/offchainlabs/nitro/wavmio.readDelayedInboxMessage" => func!(wavmio::read_delayed_inbox_message), - "github.com/offchainlabs/nitro/wavmio.resolvePreImage" => func!(wavmio::resolve_preimage), + "github.com/offchainlabs/nitro/wavmio.resolvePreImage" => { + #[allow(deprecated)] // we're just keeping this around until we no longer need to validate old replay binaries + { + func!(wavmio::resolve_keccak_preimage) + } + }, + "github.com/offchainlabs/nitro/wavmio.resolveTypedPreimage" => func!(wavmio::resolve_typed_preimage), "github.com/offchainlabs/nitro/arbcompress.brotliCompress" => func!(arbcompress::brotli_compress), "github.com/offchainlabs/nitro/arbcompress.brotliDecompress" => func!(arbcompress::brotli_decompress), @@ -178,7 +184,7 @@ impl From for Escape { pub type WasmEnvMut<'a> = FunctionEnvMut<'a, WasmEnv>; pub type Inbox = BTreeMap>; -pub type Oracle = BTreeMap<[u8; 32], Vec>; +pub type Preimages = BTreeMap>>; #[derive(Default)] pub struct WasmEnv { @@ -193,7 +199,7 @@ pub struct WasmEnv { /// An ordered list of the 32-byte globals pub large_globals: [Bytes32; 2], /// An oracle allowing the prover to reverse keccak256 - pub preimages: Oracle, + pub preimages: Preimages, /// The sequencer inbox's messages pub sequencer_messages: Inbox, /// The delayed inbox's messages @@ -242,11 +248,12 @@ impl WasmEnv { file.read_exact(&mut buf)?; preimages.push(buf); } + let keccak_preimages = env.preimages.entry(PreimageType::Keccak256).or_default(); for preimage in preimages { let mut hasher = Keccak256::new(); hasher.update(&preimage); let hash = hasher.finalize().into(); - env.preimages.insert(hash, preimage); + keccak_preimages.insert(hash, preimage); } } @@ -311,8 +318,6 @@ pub struct ProcessEnv { pub debug: bool, /// Mechanism for asking for preimages and returning results pub socket: Option<(BufWriter, BufReader)>, - /// The last preimage received over the socket - pub last_preimage: Option<([u8; 32], Vec)>, /// A timestamp that helps with printing at various moments pub timestamp: Instant, /// Whether the machine has reached the first wavmio instruction @@ -325,7 +330,6 @@ impl Default for ProcessEnv { forks: false, debug: false, socket: None, - last_preimage: None, timestamp: Instant::now(), reached_wavmio: false, } diff --git a/arbitrator/jit/src/socket.rs b/arbitrator/jit/src/socket.rs index c34691641..3941763a0 100644 --- a/arbitrator/jit/src/socket.rs +++ b/arbitrator/jit/src/socket.rs @@ -11,7 +11,6 @@ use crate::wavmio::Bytes32; pub const SUCCESS: u8 = 0x0; pub const FAILURE: u8 = 0x1; -pub const PREIMAGE: u8 = 0x2; pub const ANOTHER: u8 = 0x3; pub const READY: u8 = 0x4; diff --git a/arbitrator/jit/src/wavmio.rs b/arbitrator/jit/src/wavmio.rs index 44edbc450..a398cb22f 100644 --- a/arbitrator/jit/src/wavmio.rs +++ b/arbitrator/jit/src/wavmio.rs @@ -7,10 +7,10 @@ use crate::{ socket, }; -use arbutil::Color; +use arbutil::{Color, PreimageType}; use std::{ io, - io::{BufReader, BufWriter, ErrorKind, Write}, + io::{BufReader, BufWriter, ErrorKind}, net::TcpStream, time::Instant, }; @@ -141,11 +141,25 @@ fn inbox_message_impl(sp: &GoStack, inbox: &Inbox, name: &str) -> MaybeEscape { Ok(()) } -pub fn resolve_preimage(mut env: WasmEnvMut, sp: u32) -> MaybeEscape { +#[deprecated] // we're just keeping this around until we no longer need to validate old replay binaries +pub fn resolve_keccak_preimage(mut env: WasmEnvMut, sp: u32) -> MaybeEscape { let (sp, env) = GoStack::new(sp, &mut env); + resolve_preimage_impl(env, sp, 0, "wavmio.ResolvePreImage") +} - let name = "wavmio.resolvePreImage"; +pub fn resolve_typed_preimage(mut env: WasmEnvMut, sp: u32) -> MaybeEscape { + let (mut sp, env) = GoStack::new(sp, &mut env); + let preimage_type = sp.read_u8(0); + sp.shift_start(8); // to account for the preimage type being the first slot + resolve_preimage_impl(env, sp, preimage_type, "wavmio.ResolveTypedPreimage") +} +pub fn resolve_preimage_impl( + env: &mut WasmEnv, + sp: GoStack, + preimage_type: u8, + name: &str, +) -> MaybeEscape { let hash_ptr = sp.read_u64(0); let hash_len = sp.read_u64(1); let offset = sp.read_u64(3); @@ -157,6 +171,12 @@ pub fn resolve_preimage(mut env: WasmEnvMut, sp: u32) -> MaybeEscape { return Ok(()); } + let Ok(preimage_type) = preimage_type.try_into() else { + eprintln!("Go trying to resolve pre image with unknown type {preimage_type}"); + sp.write_u64(7, 0); + return Ok(()); + }; + macro_rules! error { ($text:expr $(,$args:expr)*) => {{ let text = format!($text $(,$args)*); @@ -168,40 +188,10 @@ pub fn resolve_preimage(mut env: WasmEnvMut, sp: u32) -> MaybeEscape { let hash: &[u8; 32] = &hash.try_into().unwrap(); let hash_hex = hex::encode(hash); - let mut preimage = None; - let temporary; // makes the borrow checker happy - - // see if we've cached the preimage - if let Some((key, cached)) = &env.process.last_preimage { - if key == hash { - preimage = Some(cached); - } - } - - // see if this is a known preimage - if preimage.is_none() { - preimage = env.preimages.get(hash); - } - - // see if Go has the preimage - if preimage.is_none() { - if let Some((writer, reader)) = &mut env.process.socket { - socket::write_u8(writer, socket::PREIMAGE)?; - socket::write_bytes32(writer, hash)?; - writer.flush()?; - - if socket::read_u8(reader)? == socket::SUCCESS { - temporary = socket::read_bytes(reader)?; - env.process.last_preimage = Some((*hash, temporary.clone())); - preimage = Some(&temporary); - } - } - } - - let preimage = match preimage { - Some(preimage) => preimage, - None => error!("Missing requested preimage for hash {hash_hex} in {name}"), + let Some(preimage) = env.preimages.get(&preimage_type).and_then(|m| m.get(hash)) else { + error!("Missing requested preimage for preimage type {preimage_type:?} hash {hash_hex} in {name}"); }; + let offset = match u32::try_from(offset) { Ok(offset) => offset as usize, Err(_) => error!("bad offset {offset} in {name}"), @@ -291,11 +281,17 @@ fn ready_hostio(env: &mut WasmEnv) -> MaybeEscape { env.delayed_messages.insert(position, message); } - let preimage_count = socket::read_u64(stream)?; - for _ in 0..preimage_count { - let hash = socket::read_bytes32(stream)?; - let preimage = socket::read_bytes(stream)?; - env.preimages.insert(hash, preimage); + let preimage_types = socket::read_u64(stream)?; + for _ in 0..preimage_types { + let preimage_ty = PreimageType::try_from(socket::read_u8(stream)?) + .map_err(|e| Escape::Failure(e.to_string()))?; + let map = env.preimages.entry(preimage_ty).or_default(); + let preimage_count = socket::read_u64(stream)?; + for _ in 0..preimage_count { + let hash = socket::read_bytes32(stream)?; + let preimage = socket::read_bytes(stream)?; + map.insert(hash, preimage); + } } if socket::read_u8(stream)? != socket::READY { diff --git a/arbitrator/prover/src/host.rs b/arbitrator/prover/src/host.rs index f3826c067..c66052ad5 100644 --- a/arbitrator/prover/src/host.rs +++ b/arbitrator/prover/src/host.rs @@ -10,7 +10,7 @@ use crate::{ value::{ArbValueType, FunctionType}, wavm::{wasm_to_wavm, Instruction, Opcode}, }; -use arbutil::Color; +use arbutil::{Color, PreimageType}; use eyre::{bail, ErrReport, Result}; use lazy_static::lazy_static; use std::{collections::HashMap, str::FromStr}; @@ -49,7 +49,8 @@ pub enum Hostio { WavmSetGlobalStateBytes32, WavmGetGlobalStateU64, WavmSetGlobalStateU64, - WavmReadPreImage, + WavmReadKeccakPreimage, + WavmReadSha256Preimage, WavmReadInboxMessage, WavmReadDelayedInboxMessage, WavmHaltAndSetFinished, @@ -71,7 +72,8 @@ impl FromStr for Hostio { ("env", "wavm_set_globalstate_bytes32") => WavmSetGlobalStateBytes32, ("env", "wavm_get_globalstate_u64") => WavmGetGlobalStateU64, ("env", "wavm_set_globalstate_u64") => WavmSetGlobalStateU64, - ("env", "wavm_read_pre_image") => WavmReadPreImage, + ("env", "wavm_read_keccak_256_preimage") => WavmReadKeccakPreimage, + ("env", "wavm_read_sha2_256_preimage") => WavmReadSha256Preimage, ("env", "wavm_read_inbox_message") => WavmReadInboxMessage, ("env", "wavm_read_delayed_inbox_message") => WavmReadDelayedInboxMessage, ("env", "wavm_halt_and_set_finished") => WavmHaltAndSetFinished, @@ -107,7 +109,8 @@ impl Hostio { WavmSetGlobalStateBytes32 => func!([I32, I32]), WavmGetGlobalStateU64 => func!([I32], [I64]), WavmSetGlobalStateU64 => func!([I32, I64]), - WavmReadPreImage => func!([I32, I32], [I32]), + WavmReadKeccakPreimage => func!([I32, I32], [I32]), + WavmReadSha256Preimage => func!([I32, I32], [I32]), WavmReadInboxMessage => func!([I64, I32, I32], [I32]), WavmReadDelayedInboxMessage => func!([I64, I32, I32], [I32]), WavmHaltAndSetFinished => func!(), @@ -167,10 +170,15 @@ impl Hostio { opcode!(LocalGet, 1); opcode!(SetGlobalStateU64); } - WavmReadPreImage => { + WavmReadKeccakPreimage => { opcode!(LocalGet, 0); opcode!(LocalGet, 1); - opcode!(ReadPreImage); + opcode!(ReadPreImage, PreimageType::Keccak256); + } + WavmReadSha256Preimage => { + opcode!(LocalGet, 0); + opcode!(LocalGet, 1); + opcode!(ReadPreImage, PreimageType::Sha2_256); } WavmReadInboxMessage => { opcode!(LocalGet, 0); diff --git a/arbitrator/prover/src/lib.rs b/arbitrator/prover/src/lib.rs index 97845c0aa..e4ea7a06c 100644 --- a/arbitrator/prover/src/lib.rs +++ b/arbitrator/prover/src/lib.rs @@ -15,6 +15,7 @@ pub mod value; pub mod wavm; use crate::machine::{argument_data_to_inbox, Machine}; +use arbutil::PreimageType; use eyre::Result; use machine::{get_empty_preimage_resolver, GlobalState, MachineStatus, PreimageResolver}; use sha3::{Digest, Keccak256}; @@ -292,11 +293,11 @@ pub struct ResolvedPreimage { #[no_mangle] pub unsafe extern "C" fn arbitrator_set_preimage_resolver( mach: *mut Machine, - resolver: unsafe extern "C" fn(u64, *const u8) -> ResolvedPreimage, + resolver: unsafe extern "C" fn(u64, u8, *const u8) -> ResolvedPreimage, ) { - (*mach).set_preimage_resolver( - Arc::new(move |context: u64, hash: Bytes32| -> Option { - let res = resolver(context, hash.as_ptr()); + (*mach).set_preimage_resolver(Arc::new( + move |context: u64, ty: PreimageType, hash: Bytes32| -> Option { + let res = resolver(context, ty.into(), hash.as_ptr()); if res.len < 0 { return None; } @@ -310,8 +311,8 @@ pub unsafe extern "C" fn arbitrator_set_preimage_resolver( ); } Some(data) - }) as PreimageResolver, - ); + }, + ) as PreimageResolver); } #[no_mangle] diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index fff9c0f3d..d6e002daa 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -14,7 +14,7 @@ use crate::{ IBinOpType, IRelOpType, IUnOpType, Instruction, Opcode, }, }; -use arbutil::Color; +use arbutil::{Color, PreimageType}; use digest::Digest; use eyre::{bail, ensure, eyre, Result, WrapErr}; use fnv::FnvHashMap as HashMap; @@ -651,7 +651,7 @@ pub struct MachineState<'a> { initial_hash: Bytes32, } -pub type PreimageResolver = Arc Option>; +pub type PreimageResolver = Arc Option>; /// Wraps a preimage resolver to provide an easier API /// and cache the last preimage retrieved. @@ -675,7 +675,7 @@ impl PreimageResolverWrapper { } } - pub fn get(&mut self, context: u64, hash: Bytes32) -> Option<&[u8]> { + pub fn get(&mut self, context: u64, ty: PreimageType, hash: Bytes32) -> Option<&[u8]> { // TODO: this is unnecessarily complicated by the rust borrow checker. // This will probably be simplifiable when Polonius is shipped. if matches!(&self.last_resolved, Some(r) if r.0 != hash) { @@ -684,19 +684,19 @@ impl PreimageResolverWrapper { match &mut self.last_resolved { Some(resolved) => Some(&resolved.1), x => { - let data = (self.resolver)(context, hash)?; + let data = (self.resolver)(context, ty, hash)?; Some(&x.insert((hash, data)).1) } } } - pub fn get_const(&self, context: u64, hash: Bytes32) -> Option { + pub fn get_const(&self, context: u64, ty: PreimageType, hash: Bytes32) -> Option { if let Some(resolved) = &self.last_resolved { if resolved.0 == hash { return Some(resolved.1.clone()); } } - (self.resolver)(context, hash) + (self.resolver)(context, ty, hash) } } @@ -848,7 +848,7 @@ where } pub fn get_empty_preimage_resolver() -> PreimageResolver { - Arc::new(|_, _| None) as _ + Arc::new(|_, _, _| None) as _ } impl Machine { @@ -1864,8 +1864,11 @@ impl Machine { Opcode::ReadPreImage => { let offset = self.value_stack.pop().unwrap().assume_u32(); let ptr = self.value_stack.pop().unwrap().assume_u32(); + let preimage_ty = PreimageType::try_from(u8::try_from(inst.argument_data)?)?; if let Some(hash) = module.memory.load_32_byte_aligned(ptr.into()) { - if let Some(preimage) = self.preimage_resolver.get(self.context, hash) { + if let Some(preimage) = + self.preimage_resolver.get(self.context, preimage_ty, hash) + { let offset = usize::try_from(offset).unwrap(); let len = std::cmp::min(32, preimage.len().saturating_sub(offset)); let read = preimage.get(offset..(offset + len)).unwrap_or_default(); @@ -2279,10 +2282,19 @@ impl Machine { data.extend(mem_merkle.prove(idx).unwrap_or_default()); if next_inst.opcode == Opcode::ReadPreImage { let hash = Bytes32(prev_data); - let preimage = match self.preimage_resolver.get_const(self.context, hash) { - Some(b) => b, - None => panic!("Missing requested preimage for hash {}", hash), - }; + let preimage_ty = PreimageType::try_from( + u8::try_from(next_inst.argument_data) + .expect("ReadPreImage argument data is out of range for a u8"), + ) + .expect("Invalid preimage type in ReadPreImage argument data"); + let preimage = + match self + .preimage_resolver + .get_const(self.context, preimage_ty, hash) + { + Some(b) => b, + None => panic!("Missing requested preimage for hash {}", hash), + }; data.push(0); // preimage proof type data.extend(preimage); } else if next_inst.opcode == Opcode::ReadInboxMessage { diff --git a/arbitrator/prover/src/main.rs b/arbitrator/prover/src/main.rs index 9afa6a7f5..f820b03f4 100644 --- a/arbitrator/prover/src/main.rs +++ b/arbitrator/prover/src/main.rs @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -use arbutil::{format, Color, DebugColor}; +use arbutil::{format, Color, DebugColor, PreimageType}; use eyre::{Context, Result}; use fnv::{FnvHashMap as HashMap, FnvHashSet as HashSet}; use prover::{ @@ -9,9 +9,8 @@ use prover::{ utils::{Bytes32, CBytes}, wavm::Opcode, }; -use sha3::{Digest, Keccak256}; -use std::io::BufWriter; use std::sync::Arc; +use std::{convert::TryInto, io::BufWriter}; use std::{ fs::File, io::{BufReader, ErrorKind, Read, Write}, @@ -79,24 +78,6 @@ struct Opts { max_steps: Option, } -fn parse_size_delim(path: &Path) -> Result>> { - let mut file = BufReader::new(File::open(path)?); - let mut contents = Vec::new(); - loop { - let mut size_buf = [0u8; 8]; - match file.read_exact(&mut size_buf) { - Ok(()) => {} - Err(e) if e.kind() == ErrorKind::UnexpectedEof => break, - Err(e) => return Err(e.into()), - } - let size = u64::from_le_bytes(size_buf) as usize; - let mut buf = vec![0u8; size]; - file.read_exact(&mut buf)?; - contents.push(buf); - } - Ok(contents) -} - fn file_with_stub_header(path: &Path, headerlength: usize) -> Result> { let mut msg = vec![0u8; headerlength]; File::open(path).unwrap().read_to_end(&mut msg)?; @@ -160,19 +141,34 @@ fn main() -> Result<()> { delayed_position += 1; } - let mut preimages: HashMap = HashMap::default(); + let mut preimages: HashMap> = HashMap::default(); if let Some(path) = opts.preimages { - preimages = parse_size_delim(&path)? - .into_iter() - .map(|b| { - let mut hasher = Keccak256::new(); - hasher.update(&b); - (hasher.finalize().into(), CBytes::from(b.as_slice())) - }) - .collect(); + let mut file = BufReader::new(File::open(path)?); + loop { + let mut ty_buf = [0u8; 1]; + match file.read_exact(&mut ty_buf) { + Ok(()) => {} + Err(e) if e.kind() == ErrorKind::UnexpectedEof => break, + Err(e) => return Err(e.into()), + } + let preimage_ty: PreimageType = ty_buf[0].try_into()?; + + let mut size_buf = [0u8; 8]; + file.read_exact(&mut size_buf)?; + let size = u64::from_le_bytes(size_buf) as usize; + let mut buf = vec![0u8; size]; + file.read_exact(&mut buf)?; + + let hash = preimage_ty.hash(&buf); + preimages + .entry(preimage_ty) + .or_default() + .insert(hash.into(), buf.as_slice().into()); + } } let preimage_resolver = - Arc::new(move |_, hash| preimages.get(&hash).cloned()) as PreimageResolver; + Arc::new(move |_, ty, hash| preimages.get(&ty).and_then(|m| m.get(&hash)).cloned()) + as PreimageResolver; let last_block_hash = decode_hex_arg(&opts.last_block_hash, "--last-block-hash")?; let last_send_root = decode_hex_arg(&opts.last_send_root, "--last-send-root")?; diff --git a/arbitrator/prover/test-cases/rust/data/preimages.bin b/arbitrator/prover/test-cases/rust/data/preimages.bin index c832466d613236b54f28e9bfc02cd58880f8b18d..34ef5a4292ec9998940525f0bf323d2219048896 100644 GIT binary patch literal 40 ZcmZSJW`KZ<)SR4rh4TEOoD@bZVgQZm2+#lk literal 19 Vcmd;PfPjqDoSb}x^8BKl6aX6J1ZV&N diff --git a/arbitrator/prover/test-cases/rust/src/bin/host-io.rs b/arbitrator/prover/test-cases/rust/src/bin/host-io.rs index 3112ba562..19ddabddc 100644 --- a/arbitrator/prover/test-cases/rust/src/bin/host-io.rs +++ b/arbitrator/prover/test-cases/rust/src/bin/host-io.rs @@ -1,7 +1,8 @@ use hex_literal::hex; extern "C" { - pub fn wavm_read_pre_image(ptr: *mut u8, offset: usize) -> usize; + pub fn wavm_read_keccak_256_preimage(ptr: *mut u8, offset: usize) -> usize; + pub fn wavm_read_sha2_256_preimage(ptr: *mut u8, offset: usize) -> usize; pub fn wavm_read_inbox_message(msg_num: u64, ptr: *mut u8, offset: usize) -> usize; pub fn wavm_read_delayed_inbox_message(seq_num: u64, ptr: *mut u8, offset: usize) -> usize; pub fn wavm_halt_and_set_finished(); @@ -38,11 +39,17 @@ fn main() { for j in 0..32 { assert_eq!(bytebuffer.0[j], (j as u8) + 1); } - let hash = hex!("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"); - bytebuffer = Bytes32(hash); - println!("preimage"); + let keccak_hash = hex!("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"); + bytebuffer = Bytes32(keccak_hash); + println!("keccak preimage"); let expected_preimage = b"hello world"; - let len = wavm_read_pre_image(bytebuffer.0.as_mut_ptr(), 0); + let len = wavm_read_keccak_256_preimage(bytebuffer.0.as_mut_ptr(), 0); + assert_eq!(len, expected_preimage.len()); + assert_eq!(&bytebuffer.0[..len], expected_preimage); + println!("sha2 preimage"); + let sha2_hash = hex!("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"); + bytebuffer = Bytes32(sha2_hash); + let len = wavm_read_sha2_256_preimage(bytebuffer.0.as_mut_ptr(), 0); assert_eq!(len, expected_preimage.len()); assert_eq!(&bytebuffer.0[..len], expected_preimage); } diff --git a/arbitrator/wasm-libraries/Cargo.lock b/arbitrator/wasm-libraries/Cargo.lock index 04ac828ec..3b545fcc4 100644 --- a/arbitrator/wasm-libraries/Cargo.lock +++ b/arbitrator/wasm-libraries/Cargo.lock @@ -2,6 +2,25 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "arbutil" +version = "0.1.0" +dependencies = [ + "digest", + "num_enum", + "sha2", + "sha3", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "brotli" version = "0.1.0" @@ -9,12 +28,63 @@ dependencies = [ "go-abi", ] +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "go-abi" version = "0.1.0" @@ -29,13 +99,106 @@ dependencies = [ "rand_pcg", ] +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "host-io" version = "0.1.0" dependencies = [ + "arbutil", "go-abi", ] +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "num_enum" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +dependencies = [ + "proc-macro2", +] + [[package]] name = "rand" version = "0.8.4" @@ -60,6 +223,82 @@ dependencies = [ "rand_core", ] +[[package]] +name = "sha2" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "syn" +version = "2.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "wasi-stub" version = "0.1.0" + +[[package]] +name = "winnow" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83817bbecf72c73bad717ee86820ebf286203d2e04c3951f3cd538869c897364" +dependencies = [ + "memchr", +] diff --git a/arbitrator/wasm-libraries/host-io/Cargo.toml b/arbitrator/wasm-libraries/host-io/Cargo.toml index 8d31f4148..48f498f91 100644 --- a/arbitrator/wasm-libraries/host-io/Cargo.toml +++ b/arbitrator/wasm-libraries/host-io/Cargo.toml @@ -9,3 +9,4 @@ crate-type = ["cdylib"] [dependencies] go-abi = { path = "../go-abi" } +arbutil = { path = "../../arbutil" } diff --git a/arbitrator/wasm-libraries/host-io/src/lib.rs b/arbitrator/wasm-libraries/host-io/src/lib.rs index 65a4f9013..e8f59994a 100644 --- a/arbitrator/wasm-libraries/host-io/src/lib.rs +++ b/arbitrator/wasm-libraries/host-io/src/lib.rs @@ -1,11 +1,14 @@ +use arbutil::PreimageType; use go_abi::*; +use std::convert::TryInto; extern "C" { pub fn wavm_get_globalstate_bytes32(idx: u32, ptr: *mut u8); pub fn wavm_set_globalstate_bytes32(idx: u32, ptr: *const u8); pub fn wavm_get_globalstate_u64(idx: u32) -> u64; pub fn wavm_set_globalstate_u64(idx: u32, val: u64); - pub fn wavm_read_pre_image(ptr: *mut u8, offset: usize) -> usize; + pub fn wavm_read_keccak_256_preimage(ptr: *mut u8, offset: usize) -> usize; + pub fn wavm_read_sha2_256_preimage(ptr: *mut u8, offset: usize) -> usize; pub fn wavm_read_inbox_message(msg_num: u64, ptr: *mut u8, offset: usize) -> usize; pub fn wavm_read_delayed_inbox_message(seq_num: u64, ptr: *mut u8, offset: usize) -> usize; } @@ -117,26 +120,39 @@ pub unsafe extern "C" fn go__github_com_offchainlabs_nitro_wavmio_readDelayedInb } #[no_mangle] -pub unsafe extern "C" fn go__github_com_offchainlabs_nitro_wavmio_resolvePreImage(sp: GoStack) { - let hash_ptr = sp.read_u64(0); - let hash_len = sp.read_u64(1); - let offset = sp.read_u64(3); - let out_ptr = sp.read_u64(4); - let out_len = sp.read_u64(5); +pub unsafe extern "C" fn go__github_com_offchainlabs_nitro_wavmio_resolveTypedPreimage(sp: GoStack) { + let preimage_type = sp.read_u8(0); + let hash_ptr = sp.read_u64(1); + let hash_len = sp.read_u64(2); + let offset = sp.read_u64(4); + let out_ptr = sp.read_u64(5); + let out_len = sp.read_u64(6); if hash_len != 32 || out_len != 32 { eprintln!( - "Go attempting to resolve pre image with hash len {} and out len {}", + "Go attempting to resolve preimage with hash len {} and out len {}", hash_len, out_len, ); - sp.write_u64(7, 0); + sp.write_u64(8, 0); return; } + let Ok(preimage_type) = preimage_type.try_into() else { + eprintln!( + "Go trying to resolve preimage with unknown type {}", + preimage_type + ); + sp.write_u64(8, 0); + return; + }; let mut our_buf = MemoryLeaf([0u8; 32]); our_buf.0.copy_from_slice(&read_slice(hash_ptr, hash_len)); let our_ptr = our_buf.0.as_mut_ptr(); assert_eq!(our_ptr as usize % 32, 0); - let read = wavm_read_pre_image(our_ptr, offset as usize); + let preimage_reader = match preimage_type { + PreimageType::Keccak256 => wavm_read_keccak_256_preimage, + PreimageType::Sha2_256 => wavm_read_sha2_256_preimage, + }; + let read = preimage_reader(our_ptr, offset as usize); assert!(read <= 32); write_slice(&our_buf.0[..read], out_ptr); - sp.write_u64(7, read as u64); + sp.write_u64(8, read as u64); } diff --git a/arbstate/inbox.go b/arbstate/inbox.go index 80d40322c..3995bcf30 100644 --- a/arbstate/inbox.go +++ b/arbstate/inbox.go @@ -19,6 +19,7 @@ import ( "github.com/offchainlabs/nitro/arbcompress" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbos/l1pricing" + "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/das/dastree" "github.com/offchainlabs/nitro/zeroheavy" ) @@ -128,9 +129,16 @@ func RecoverPayloadFromDasBatch( batchNum uint64, sequencerMsg []byte, dasReader DataAvailabilityReader, - preimages map[common.Hash][]byte, + preimages map[arbutil.PreimageType]map[common.Hash][]byte, keysetValidationMode KeysetValidationMode, ) ([]byte, error) { + var keccakPreimages map[common.Hash][]byte + if preimages != nil { + if preimages[arbutil.Keccak256PreimageType] == nil { + preimages[arbutil.Keccak256PreimageType] = make(map[common.Hash][]byte) + } + keccakPreimages = preimages[arbutil.Keccak256PreimageType] + } cert, err := DeserializeDASCertFrom(bytes.NewReader(sequencerMsg[40:])) if err != nil { log.Error("Failed to deserialize DAS message", "err", err) @@ -138,7 +146,7 @@ func RecoverPayloadFromDasBatch( } version := cert.Version recordPreimage := func(key common.Hash, value []byte) { - preimages[key] = value + keccakPreimages[key] = value } if version >= 2 { @@ -179,7 +187,7 @@ func RecoverPayloadFromDasBatch( log.Error("Couldn't get keyset", "err", err) return nil, err } - if preimages != nil { + if keccakPreimages != nil { dastree.RecordHash(recordPreimage, keysetPreimage) } @@ -211,11 +219,11 @@ func RecoverPayloadFromDasBatch( return nil, err } - if preimages != nil { + if keccakPreimages != nil { if version == 0 { treeLeaf := dastree.FlatHashToTreeLeaf(dataHash) - preimages[dataHash] = payload - preimages[crypto.Keccak256Hash(treeLeaf)] = treeLeaf + keccakPreimages[dataHash] = payload + keccakPreimages[crypto.Keccak256Hash(treeLeaf)] = treeLeaf } else { dastree.RecordHash(recordPreimage, payload) } diff --git a/arbutil/preimage_type.go b/arbutil/preimage_type.go new file mode 100644 index 000000000..7eaf60c01 --- /dev/null +++ b/arbutil/preimage_type.go @@ -0,0 +1,13 @@ +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package arbutil + +type PreimageType uint8 + +// These values must be kept in sync with `arbitrator/arbutil/src/types.rs`, +// and the if statement in `contracts/src/osp/OneStepProverHostIo.sol` (search for "UNKNOWN_PREIMAGE_TYPE"). +const ( + Keccak256PreimageType PreimageType = iota + Sha2_256PreimageType +) diff --git a/cmd/replay/db.go b/cmd/replay/db.go index 9a065789c..7147c48f7 100644 --- a/cmd/replay/db.go +++ b/cmd/replay/db.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/ethdb" + "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/wavmio" ) @@ -34,7 +35,7 @@ func (db PreimageDb) Get(key []byte) ([]byte, error) { } else { return nil, fmt.Errorf("preimage DB attempted to access non-hash key %v", hex.EncodeToString(key)) } - return wavmio.ResolvePreImage(hash) + return wavmio.ResolveTypedPreimage(arbutil.Keccak256PreimageType, hash) } func (db PreimageDb) Put(key []byte, value []byte) error { diff --git a/cmd/replay/main.go b/cmd/replay/main.go index 501562d26..2fb13ceed 100644 --- a/cmd/replay/main.go +++ b/cmd/replay/main.go @@ -26,6 +26,7 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbos/burn" "github.com/offchainlabs/nitro/arbstate" + "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/cmd/chaininfo" "github.com/offchainlabs/nitro/das/dastree" "github.com/offchainlabs/nitro/gethhook" @@ -33,7 +34,7 @@ import ( ) func getBlockHeaderByHash(hash common.Hash) *types.Header { - enc, err := wavmio.ResolvePreImage(hash) + enc, err := wavmio.ResolveTypedPreimage(arbutil.Keccak256PreimageType, hash) if err != nil { panic(fmt.Errorf("Error resolving preimage: %w", err)) } @@ -102,7 +103,10 @@ type PreimageDASReader struct { } func (dasReader *PreimageDASReader) GetByHash(ctx context.Context, hash common.Hash) ([]byte, error) { - return dastree.Content(hash, wavmio.ResolvePreImage) + oracle := func(hash common.Hash) ([]byte, error) { + return wavmio.ResolveTypedPreimage(arbutil.Keccak256PreimageType, hash) + } + return dastree.Content(hash, oracle) } func (dasReader *PreimageDASReader) HealthCheck(ctx context.Context) error { diff --git a/contracts b/contracts index 97cfbe00f..33dd360ab 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 97cfbe00ff0eea4d7f5f5f3afb01598c19ddabc4 +Subproject commit 33dd360abf85b0ef8491d595cf9a28ee7ca37b8d diff --git a/das/syncing_fallback_storage.go b/das/syncing_fallback_storage.go index 7c67dbec6..8a4115514 100644 --- a/das/syncing_fallback_storage.go +++ b/das/syncing_fallback_storage.go @@ -212,22 +212,24 @@ func (s *l1SyncService) processBatchDelivered(ctx context.Context, batchDelivere binary.BigEndian.PutUint64(header[32:40], deliveredEvent.AfterDelayedMessagesRead.Uint64()) data = append(header, data...) - preimages := make(map[common.Hash][]byte) + preimages := make(map[arbutil.PreimageType]map[common.Hash][]byte) if _, err = arbstate.RecoverPayloadFromDasBatch(ctx, deliveredEvent.BatchSequenceNumber.Uint64(), data, s.dataSource, preimages, arbstate.KeysetValidate); err != nil { log.Error("recover payload failed", "txhash", batchDeliveredLog.TxHash, "data", data) return err } - for hash, contents := range preimages { - var err error - if s.config.CheckAlreadyExists { - _, err = s.syncTo.GetByHash(ctx, hash) - } - if err == nil || errors.Is(err, ErrNotFound) { - if err := s.syncTo.Put(ctx, contents, storeUntil); err != nil { + for _, preimages := range preimages { + for hash, contents := range preimages { + var err error + if s.config.CheckAlreadyExists { + _, err = s.syncTo.GetByHash(ctx, hash) + } + if err == nil || errors.Is(err, ErrNotFound) { + if err := s.syncTo.Put(ctx, contents, storeUntil); err != nil { + return err + } + } else { return err } - } else { - return err } } seqNumber := deliveredEvent.BatchSequenceNumber diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index 7add3e258..7fe913d92 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -178,7 +178,7 @@ type validationEntry struct { // Has batch when created - others could be added on record BatchInfo []validator.BatchInfo // Valid since Ready - Preimages map[common.Hash][]byte + Preimages map[arbutil.PreimageType]map[common.Hash][]byte DelayedMsg []byte } @@ -271,6 +271,7 @@ func (v *StatelessBlockValidator) ValidationEntryRecord(ctx context.Context, e * if e.Stage != ReadyForRecord { return fmt.Errorf("validation entry should be ReadyForRecord, is: %v", e.Stage) } + e.Preimages = make(map[arbutil.PreimageType]map[common.Hash][]byte) if e.Pos != 0 { recording, err := v.recorder.RecordBlockCreation(ctx, e.Pos, e.msg) if err != nil { @@ -282,7 +283,7 @@ func (v *StatelessBlockValidator) ValidationEntryRecord(ctx context.Context, e * e.BatchInfo = append(e.BatchInfo, recording.BatchInfo...) if recording.Preimages != nil { - e.Preimages = recording.Preimages + e.Preimages[arbutil.Keccak256PreimageType] = recording.Preimages } } if e.HasDelayedMsg { @@ -296,9 +297,6 @@ func (v *StatelessBlockValidator) ValidationEntryRecord(ctx context.Context, e * } e.DelayedMsg = delayedMsg } - if e.Preimages == nil { - e.Preimages = make(map[common.Hash][]byte) - } for _, batch := range e.BatchInfo { if len(batch.Data) <= 40 { continue diff --git a/system_tests/validation_mock_test.go b/system_tests/validation_mock_test.go index bfa2d6783..da6958b02 100644 --- a/system_tests/validation_mock_test.go +++ b/system_tests/validation_mock_test.go @@ -33,12 +33,13 @@ var sendRootKey = common.HexToHash("0x55667788") var batchNumKey = common.HexToHash("0x99aabbcc") var posInBatchKey = common.HexToHash("0xddeeff") -func globalstateFromTestPreimages(preimages map[common.Hash][]byte) validator.GoGlobalState { +func globalstateFromTestPreimages(preimages map[arbutil.PreimageType]map[common.Hash][]byte) validator.GoGlobalState { + keccakPreimages := preimages[arbutil.Keccak256PreimageType] return validator.GoGlobalState{ - Batch: new(big.Int).SetBytes(preimages[batchNumKey]).Uint64(), - PosInBatch: new(big.Int).SetBytes(preimages[posInBatchKey]).Uint64(), - BlockHash: common.BytesToHash(preimages[blockHashKey]), - SendRoot: common.BytesToHash(preimages[sendRootKey]), + Batch: new(big.Int).SetBytes(keccakPreimages[batchNumKey]).Uint64(), + PosInBatch: new(big.Int).SetBytes(keccakPreimages[posInBatchKey]).Uint64(), + BlockHash: common.BytesToHash(keccakPreimages[blockHashKey]), + SendRoot: common.BytesToHash(keccakPreimages[sendRootKey]), } } @@ -209,7 +210,9 @@ func TestValidationServerAPI(t *testing.T) { valInput := validator.ValidationInput{ StartState: startState, - Preimages: globalstateToTestPreimages(endState), + Preimages: map[arbutil.PreimageType]map[common.Hash][]byte{ + arbutil.Keccak256PreimageType: globalstateToTestPreimages(endState), + }, } valRun := client.Launch(&valInput, wasmRoot) res, err := valRun.Await(ctx) @@ -273,7 +276,9 @@ func TestValidationClientRoom(t *testing.T) { valInput := validator.ValidationInput{ StartState: startState, - Preimages: globalstateToTestPreimages(endState), + Preimages: map[arbutil.PreimageType]map[common.Hash][]byte{ + arbutil.Keccak256PreimageType: globalstateToTestPreimages(endState), + }, } valRuns := make([]validator.ValidationRun, 0, 4) diff --git a/util/jsonapi/preimages.go b/util/jsonapi/preimages.go index d669b7046..a0dfe8579 100644 --- a/util/jsonapi/preimages.go +++ b/util/jsonapi/preimages.go @@ -16,8 +16,8 @@ type PreimagesMapJson struct { Map map[common.Hash][]byte } -func NewPreimagesMapJson(inner map[common.Hash][]byte) PreimagesMapJson { - return PreimagesMapJson{inner} +func NewPreimagesMapJson(inner map[common.Hash][]byte) *PreimagesMapJson { + return &PreimagesMapJson{inner} } func (m *PreimagesMapJson) MarshalJSON() ([]byte, error) { diff --git a/validator/server_api/json.go b/validator/server_api/json.go index 95108757d..202974198 100644 --- a/validator/server_api/json.go +++ b/validator/server_api/json.go @@ -7,6 +7,7 @@ import ( "encoding/base64" "github.com/ethereum/go-ethereum/common" + "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/util/jsonapi" "github.com/offchainlabs/nitro/validator" ) @@ -20,20 +21,24 @@ type ValidationInputJson struct { Id uint64 HasDelayedMsg bool DelayedMsgNr uint64 - PreimagesB64 jsonapi.PreimagesMapJson + PreimagesB64 map[arbutil.PreimageType]*jsonapi.PreimagesMapJson BatchInfo []BatchInfoJson DelayedMsgB64 string StartState validator.GoGlobalState } func ValidationInputToJson(entry *validator.ValidationInput) *ValidationInputJson { + jsonPreimagesMap := make(map[arbutil.PreimageType]*jsonapi.PreimagesMapJson) + for ty, preimages := range entry.Preimages { + jsonPreimagesMap[ty] = jsonapi.NewPreimagesMapJson(preimages) + } res := &ValidationInputJson{ Id: entry.Id, HasDelayedMsg: entry.HasDelayedMsg, DelayedMsgNr: entry.DelayedMsgNr, DelayedMsgB64: base64.StdEncoding.EncodeToString(entry.DelayedMsg), StartState: entry.StartState, - PreimagesB64: jsonapi.NewPreimagesMapJson(entry.Preimages), + PreimagesB64: jsonPreimagesMap, } for _, binfo := range entry.BatchInfo { encData := base64.StdEncoding.EncodeToString(binfo.Data) @@ -43,12 +48,16 @@ func ValidationInputToJson(entry *validator.ValidationInput) *ValidationInputJso } func ValidationInputFromJson(entry *ValidationInputJson) (*validator.ValidationInput, error) { + preimages := make(map[arbutil.PreimageType]map[common.Hash][]byte) + for ty, jsonPreimages := range entry.PreimagesB64 { + preimages[ty] = jsonPreimages.Map + } valInput := &validator.ValidationInput{ Id: entry.Id, HasDelayedMsg: entry.HasDelayedMsg, DelayedMsgNr: entry.DelayedMsgNr, StartState: entry.StartState, - Preimages: entry.PreimagesB64.Map, + Preimages: preimages, } delayed, err := base64.StdEncoding.DecodeString(entry.DelayedMsgB64) if err != nil { diff --git a/validator/server_arb/machine.go b/validator/server_arb/machine.go index 310136278..e59659c7a 100644 --- a/validator/server_arb/machine.go +++ b/validator/server_arb/machine.go @@ -7,7 +7,7 @@ package server_arb #cgo CFLAGS: -g -Wall -I../../target/include/ #include "arbitrator.h" -ResolvedPreimage preimageResolverC(size_t context, const uint8_t* hash); +ResolvedPreimage preimageResolverC(size_t context, uint8_t preimageType, const uint8_t* hash); */ import "C" import ( @@ -21,6 +21,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" + "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/util/containers" "github.com/offchainlabs/nitro/validator" ) @@ -49,7 +51,7 @@ type ArbitratorMachine struct { // Assert that ArbitratorMachine implements MachineInterface var _ MachineInterface = (*ArbitratorMachine)(nil) -var preimageResolvers sync.Map +var preimageResolvers containers.SyncMap[int64, GoPreimageResolver] var lastPreimageResolverId int64 // atomic // Any future calls to this machine will result in a panic @@ -335,10 +337,10 @@ func (m *ArbitratorMachine) AddDelayedInboxMessage(index uint64, data []byte) er } } -type GoPreimageResolver = func(common.Hash) ([]byte, error) +type GoPreimageResolver = func(arbutil.PreimageType, common.Hash) ([]byte, error) //export preimageResolver -func preimageResolver(context C.size_t, ptr unsafe.Pointer) C.ResolvedPreimage { +func preimageResolver(context C.size_t, ty C.uint8_t, ptr unsafe.Pointer) C.ResolvedPreimage { var hash common.Hash input := (*[1 << 30]byte)(ptr)[:32] copy(hash[:], input) @@ -348,14 +350,7 @@ func preimageResolver(context C.size_t, ptr unsafe.Pointer) C.ResolvedPreimage { len: -1, } } - resolverFunc, ok := resolver.(GoPreimageResolver) - if !ok { - log.Warn("preimage resolver has wrong type") - return C.ResolvedPreimage{ - len: -1, - } - } - preimage, err := resolverFunc(hash) + preimage, err := resolver(arbutil.PreimageType(ty), hash) if err != nil { log.Error("preimage resolution failed", "err", err) return C.ResolvedPreimage{ diff --git a/validator/server_arb/preimage_resolver.go b/validator/server_arb/preimage_resolver.go index 24c040c71..cd4ea40e2 100644 --- a/validator/server_arb/preimage_resolver.go +++ b/validator/server_arb/preimage_resolver.go @@ -7,10 +7,10 @@ package server_arb #cgo CFLAGS: -g -Wall -I../../target/include/ #include "arbitrator.h" -extern ResolvedPreimage preimageResolver(size_t context, const uint8_t* hash); +extern ResolvedPreimage preimageResolver(size_t context, uint8_t preimageType, const uint8_t* hash); -ResolvedPreimage preimageResolverC(size_t context, const uint8_t* hash) { - return preimageResolver(context, hash); +ResolvedPreimage preimageResolverC(size_t context, uint8_t preimageType, const uint8_t* hash) { + return preimageResolver(context, preimageType, hash); } */ import "C" diff --git a/validator/server_arb/validator_spawner.go b/validator/server_arb/validator_spawner.go index f9d0705f5..163ddb073 100644 --- a/validator/server_arb/validator_spawner.go +++ b/validator/server_arb/validator_spawner.go @@ -13,6 +13,7 @@ import ( flag "github.com/spf13/pflag" + "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/util/containers" "github.com/offchainlabs/nitro/util/stopwaiter" "github.com/offchainlabs/nitro/validator" @@ -81,9 +82,9 @@ func (s *ArbitratorSpawner) Name() string { } func (v *ArbitratorSpawner) loadEntryToMachine(ctx context.Context, entry *validator.ValidationInput, mach *ArbitratorMachine) error { - resolver := func(hash common.Hash) ([]byte, error) { + resolver := func(ty arbutil.PreimageType, hash common.Hash) ([]byte, error) { // Check if it's a known preimage - if preimage, ok := entry.Preimages[hash]; ok { + if preimage, ok := entry.Preimages[ty][hash]; ok { return preimage, nil } return nil, errors.New("preimage not found") @@ -242,19 +243,25 @@ func (v *ArbitratorSpawner) writeToFile(ctx context.Context, input *validator.Va return err } defer preimageFile.Close() - for _, data := range input.Preimages { - if ctx.Err() != nil { - return ctx.Err() - } - lenbytes := make([]byte, 8) - binary.LittleEndian.PutUint64(lenbytes, uint64(len(data))) - _, err := preimageFile.Write(lenbytes) + for ty, preimages := range input.Preimages { + _, err = preimageFile.Write([]byte{byte(ty)}) if err != nil { return err } - _, err = preimageFile.Write(data) - if err != nil { - return err + for _, data := range preimages { + if ctx.Err() != nil { + return ctx.Err() + } + lenbytes := make([]byte, 8) + binary.LittleEndian.PutUint64(lenbytes, uint64(len(data))) + _, err := preimageFile.Write(lenbytes) + if err != nil { + return err + } + _, err = preimageFile.Write(data) + if err != nil { + return err + } } } diff --git a/validator/server_jit/jit_machine.go b/validator/server_jit/jit_machine.go index 394dae9c9..f763ce3ea 100644 --- a/validator/server_jit/jit_machine.go +++ b/validator/server_jit/jit_machine.go @@ -59,10 +59,8 @@ func (machine *JitMachine) close() { } } -type GoPreimageResolver = func(common.Hash) ([]byte, error) - func (machine *JitMachine) prove( - ctxIn context.Context, entry *validator.ValidationInput, resolver GoPreimageResolver, + ctxIn context.Context, entry *validator.ValidationInput, ) (validator.GoGlobalState, error) { ctx, cancel := context.WithCancel(ctxIn) defer cancel() // ensure our cleanup functions run when we're done @@ -144,7 +142,6 @@ func (machine *JitMachine) prove( const successByte = 0x0 const failureByte = 0x1 - const preimageByte = 0x2 const anotherByte = 0x3 const readyByte = 0x4 @@ -185,17 +182,25 @@ func (machine *JitMachine) prove( } // send known preimages - knownPreimages := entry.Preimages - if err := writeUint64(uint64(len(knownPreimages))); err != nil { + preimageTypes := entry.Preimages + if err := writeUint64(uint64(len(preimageTypes))); err != nil { return state, err } - for hash, preimage := range knownPreimages { - if err := writeExact(hash[:]); err != nil { + for ty, preimages := range preimageTypes { + if err := writeUint8(uint8(ty)); err != nil { return state, err } - if err := writeBytes(preimage); err != nil { + if err := writeUint64(uint64(len(preimages))); err != nil { return state, err } + for hash, preimage := range preimages { + if err := writeExact(hash[:]); err != nil { + return state, err + } + if err := writeBytes(preimage); err != nil { + return state, err + } + } } // signal that we are done sending global state @@ -232,28 +237,6 @@ func (machine *JitMachine) prove( return state, err } switch kind[0] { - case preimageByte: - hash, err := readHash() - if err != nil { - return state, err - } - preimage, err := resolver(hash) - if err != nil { - log.Error("Failed to resolve preimage for jit", "hash", hash) - if err := writeUint8(failureByte); err != nil { - return state, err - } - continue - } - - // send the preimage - if err := writeUint8(successByte); err != nil { - return state, err - } - if err := writeBytes(preimage); err != nil { - return state, err - } - case failureByte: length, err := readUint64() if err != nil { diff --git a/validator/server_jit/spawner.go b/validator/server_jit/spawner.go index 6de006b18..ff1749506 100644 --- a/validator/server_jit/spawner.go +++ b/validator/server_jit/spawner.go @@ -2,7 +2,6 @@ package server_jit import ( "context" - "errors" "fmt" "runtime" "sync/atomic" @@ -70,14 +69,7 @@ func (v *JitSpawner) execute( return validator.GoGlobalState{}, fmt.Errorf("unabled to get WASM machine: %w", err) } - resolver := func(hash common.Hash) ([]byte, error) { - // Check if it's a known preimage - if preimage, ok := entry.Preimages[hash]; ok { - return preimage, nil - } - return nil, errors.New("preimage not found") - } - state, err := machine.prove(ctx, entry, resolver) + state, err := machine.prove(ctx, entry) return state, err } diff --git a/validator/validation_entry.go b/validator/validation_entry.go index 7f3fb2d57..fed1940f1 100644 --- a/validator/validation_entry.go +++ b/validator/validation_entry.go @@ -2,6 +2,7 @@ package validator import ( "github.com/ethereum/go-ethereum/common" + "github.com/offchainlabs/nitro/arbutil" ) type BatchInfo struct { @@ -13,7 +14,7 @@ type ValidationInput struct { Id uint64 HasDelayedMsg bool DelayedMsgNr uint64 - Preimages map[common.Hash][]byte + Preimages map[arbutil.PreimageType]map[common.Hash][]byte BatchInfo []BatchInfo DelayedMsg []byte StartState GoGlobalState diff --git a/wavmio/higher.go b/wavmio/higher.go index 35aca061d..81fa4a5e3 100644 --- a/wavmio/higher.go +++ b/wavmio/higher.go @@ -6,7 +6,10 @@ package wavmio -import "github.com/ethereum/go-ethereum/common" +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/offchainlabs/nitro/arbutil" +) const INITIAL_CAPACITY = 128 const QUERY_SIZE = 32 @@ -61,9 +64,9 @@ func AdvanceInboxMessage() { setGlobalStateU64(IDX_INBOX_POSITION, pos+1) } -func ResolvePreImage(hash common.Hash) ([]byte, error) { +func ResolveTypedPreimage(ty arbutil.PreimageType, hash common.Hash) ([]byte, error) { return readBuffer(func(offset uint32, buf []byte) uint32 { - return resolvePreImage(hash[:], offset, buf) + return resolveTypedPreimage(uint8(ty), hash[:], offset, buf) }), nil } diff --git a/wavmio/raw.go b/wavmio/raw.go index 37b9961a7..f0462cbbe 100644 --- a/wavmio/raw.go +++ b/wavmio/raw.go @@ -12,4 +12,4 @@ func getGlobalStateU64(idx uint64) uint64 func setGlobalStateU64(idx uint64, val uint64) func readInboxMessage(msgNum uint64, offset uint32, output []byte) uint32 func readDelayedInboxMessage(seqNum uint64, offset uint32, output []byte) uint32 -func resolvePreImage(hash []byte, offset uint32, output []byte) uint32 +func resolveTypedPreimage(ty uint8, hash []byte, offset uint32, output []byte) uint32 diff --git a/wavmio/raw.s b/wavmio/raw.s index ded91c7ec..7347d1339 100644 --- a/wavmio/raw.s +++ b/wavmio/raw.s @@ -30,6 +30,6 @@ TEXT ·readDelayedInboxMessage(SB), NOSPLIT, $0 CallImport RET -TEXT ·resolvePreImage(SB), NOSPLIT, $0 +TEXT ·resolveTypedPreimage(SB), NOSPLIT, $0 CallImport RET diff --git a/wavmio/stub.go b/wavmio/stub.go index 05698429f..0893f3525 100644 --- a/wavmio/stub.go +++ b/wavmio/stub.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" + "github.com/offchainlabs/nitro/arbutil" ) // source for arrayFlags: https://stackoverflow.com/questions/28322997/how-to-get-a-list-of-values-into-a-flag-in-golang @@ -134,7 +135,7 @@ func AdvanceInboxMessage() { seqAdvanced++ } -func ResolvePreImage(hash common.Hash) ([]byte, error) { +func ResolveTypedPreimage(ty arbutil.PreimageType, hash common.Hash) ([]byte, error) { val, ok := preimages[hash] if !ok { return []byte{}, errors.New("preimage not found") From 15043f6dfaa8442e100dd67ea77c477fd6f9d410 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 16 Aug 2023 19:08:58 -0600 Subject: [PATCH 067/775] Supply arbutil to build wasm-libraries in Dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 367d76d4b..62455119f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,6 +44,7 @@ RUN apt-get install -y clang=1:11.0-51+nmu5 lld=1:11.0-51+nmu5 # pinned rust 1.65.0 RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.68.2 --target x86_64-unknown-linux-gnu wasm32-unknown-unknown wasm32-wasi COPY ./Makefile ./ +COPY arbitrator/arbutil arbitrator/arbutil COPY arbitrator/wasm-libraries arbitrator/wasm-libraries COPY --from=brotli-wasm-export / target/ RUN . ~/.cargo/env && NITRO_BUILD_IGNORE_TIMESTAMPS=1 RUSTFLAGS='-C symbol-mangling-version=v0' make build-wasm-libs From a45dac53a0e6f48cec0c971b81bf3e580c765c05 Mon Sep 17 00:00:00 2001 From: Nodar Date: Thu, 17 Aug 2023 17:54:00 +0200 Subject: [PATCH 068/775] Introduce koanf linter that checks that field names match koanf tags --- .gitignore | 1 + .gitmodules | 3 + .golangci.yml | 7 +++ Makefile | 4 +- go.mod | 17 +++--- go.sum | 34 ++++++----- linter/golangci-lint | 1 + linter/koanf/koanf.go | 116 +++++++++++++++++++++++++++++++++++++ linter/koanf/koanf_test.go | 31 ++++++++++ 9 files changed, 189 insertions(+), 25 deletions(-) create mode 160000 linter/golangci-lint create mode 100644 linter/koanf/koanf.go create mode 100644 linter/koanf/koanf_test.go diff --git a/.gitignore b/.gitignore index f0eb5c2ec..8937c1b5d 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ yarn-error.log local/ testdata system_tests/test-data/* +linter/koanf/koanf.so \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 7c78791c7..11d9caa2a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,3 +20,6 @@ [submodule "nitro-testnode"] path = nitro-testnode url = https://github.com/OffchainLabs/nitro-testnode.git +[submodule "linter/golangci-lint"] + path = linter/golangci-lint + url = https://github.com/golangci/golangci-lint diff --git a/.golangci.yml b/.golangci.yml index e794cdb84..952a52a0c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,6 +23,7 @@ linters: - nilerr # ensure errors aren't mishandled - staticcheck # check for suspicious constructs - unused # check for unused constructs + - koanf linters-settings: errcheck: @@ -51,3 +52,9 @@ linters-settings: disable: - shadow - fieldalignment + + + custom: + koanf: + path: linter/koanf/koanf.so + description: Koanf configuration linter diff --git a/Makefile b/Makefile index 205025dfe..71c051087 100644 --- a/Makefile +++ b/Makefile @@ -304,7 +304,9 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro # strategic rules to minimize dependency building .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make - golangci-lint run --fix + make build -C linter/golangci-lint + go build -buildmode=plugin -o linter/koanf/koanf.so linter/koanf/koanf.go + ./linter/golangci-lint/golangci-lint run --fix yarn --cwd contracts solhint @touch $@ diff --git a/go.mod b/go.mod index 5adfd1938..526f0a819 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/codeclysm/extract/v3 v3.0.2 github.com/dgraph-io/badger/v3 v3.2103.2 github.com/ethereum/go-ethereum v1.10.26 + github.com/fatih/structtag v1.2.0 github.com/google/go-cmp v0.5.9 github.com/hashicorp/golang-lru/v2 v2.0.1 github.com/ipfs/go-cid v0.3.2 @@ -31,7 +32,8 @@ require ( github.com/multiformats/go-multihash v0.2.1 github.com/spf13/pflag v1.0.5 github.com/wealdtech/go-merkletree v1.0.0 - golang.org/x/term v0.6.0 + golang.org/x/term v0.11.0 + golang.org/x/tools v0.12.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) @@ -256,8 +258,7 @@ require ( go.uber.org/zap v1.24.0 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect - golang.org/x/mod v0.9.0 // indirect - golang.org/x/tools v0.7.0 // indirect + golang.org/x/mod v0.12.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/grpc v1.46.0 // indirect @@ -309,11 +310,11 @@ require ( github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect - golang.org/x/crypto v0.6.0 - golang.org/x/net v0.8.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.6.0 - golang.org/x/text v0.8.0 // indirect + golang.org/x/crypto v0.12.0 + golang.org/x/net v0.14.0 // indirect + golang.org/x/sync v0.3.0 // indirect + golang.org/x/sys v0.11.0 + golang.org/x/text v0.12.0 // indirect golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect ) diff --git a/go.sum b/go.sum index 58155db12..43240135c 100644 --- a/go.sum +++ b/go.sum @@ -326,6 +326,8 @@ github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:Jp github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= +github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -1737,8 +1739,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1774,8 +1776,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1835,8 +1837,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1857,8 +1859,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1951,12 +1953,12 @@ golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1966,8 +1968,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2035,8 +2037,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= +golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/linter/golangci-lint b/linter/golangci-lint new file mode 160000 index 000000000..8000abaf0 --- /dev/null +++ b/linter/golangci-lint @@ -0,0 +1 @@ +Subproject commit 8000abaf0e6e28e8179864f0317349cecab47c05 diff --git a/linter/koanf/koanf.go b/linter/koanf/koanf.go new file mode 100644 index 000000000..4aaddaa49 --- /dev/null +++ b/linter/koanf/koanf.go @@ -0,0 +1,116 @@ +package main + +import ( + "fmt" + "go/ast" + "go/token" + "reflect" + "strings" + "unicode" + + "github.com/fatih/structtag" + + "golang.org/x/tools/go/analysis" +) + +func New(conf any) ([]*analysis.Analyzer, error) { + return []*analysis.Analyzer{Analyzer}, nil +} + +var Analyzer = &analysis.Analyzer{ + Name: "koanfcheck", + Doc: "check for koanf misconfigurations", + Run: func(p *analysis.Pass) (interface{}, error) { return run(false, p) }, + ResultType: reflect.TypeOf(Result{}), +} + +var analyzerForTests = &analysis.Analyzer{ + Name: "testkoanfcheck", + Doc: "check for koanf misconfigurations (for tests)", + Run: func(p *analysis.Pass) (interface{}, error) { return run(true, p) }, + ResultType: reflect.TypeOf(Result{}), +} + +// koanfError indicates the position of an error in configuration. +type koanfError struct { + Pos token.Position + Message string +} + +// Result is returned from the checkStruct function, and holds all the +// configuration errors. +type Result struct { + Errors []koanfError +} + +func run(dryRun bool, pass *analysis.Pass) (interface{}, error) { + var ret Result + for _, f := range pass.Files { + ast.Inspect(f, func(node ast.Node) bool { + var res Result + switch v := node.(type) { + case *ast.StructType: + res = checkStruct(pass, v) + default: + } + for _, err := range res.Errors { + ret.Errors = append(ret.Errors, err) + if !dryRun { + pass.Report(analysis.Diagnostic{ + Pos: pass.Fset.File(f.Pos()).Pos(err.Pos.Offset), + Message: err.Message, + Category: "koanf", + }) + } + } + return true + }, + ) + } + return ret, nil +} + +func checkStruct(pass *analysis.Pass, s *ast.StructType) Result { + var res Result + for _, f := range s.Fields.List { + if f.Tag == nil { + continue + } + tags, err := structtag.Parse(strings.Trim((f.Tag.Value), "`")) + if err != nil { + continue + } + tag, err := tags.Get("koanf") + if err != nil { + continue + } + tagName := normalize(tag.Name) + fieldName := f.Names[0].Name + if !strings.EqualFold(tagName, fieldName) { + res.Errors = append(res.Errors, koanfError{ + Pos: pass.Fset.Position(f.Pos()), + Message: fmt.Sprintf("field name: %q doesn't match tag name: %q\n", fieldName, tagName), + }) + } + } + return res +} + +func normalize(s string) string { + ans := s[:1] + for i := 1; i < len(s); i++ { + c := rune(s[i]) + if !isAlphanumeric(c) { + continue + } + if !isAlphanumeric(rune(s[i-1])) && unicode.IsLower(c) { + c = unicode.ToUpper(c) + } + ans += string(c) + } + return ans +} + +func isAlphanumeric(c rune) bool { + return unicode.IsLetter(c) || unicode.IsDigit(c) +} diff --git a/linter/koanf/koanf_test.go b/linter/koanf/koanf_test.go new file mode 100644 index 000000000..2e3e68b0f --- /dev/null +++ b/linter/koanf/koanf_test.go @@ -0,0 +1,31 @@ +package main + +import ( + "os" + "path/filepath" + "testing" + + "golang.org/x/tools/go/analysis/analysistest" +) + +func TestAll(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get wd: %s", err) + } + testdata := filepath.Join(filepath.Dir(wd), "testdata") + res := analysistest.Run(t, testdata, analyzerForTests, "a") + if cnt := countErrors(res); cnt != 1 { + t.Errorf("analysistest.Run() got %v errors, expected 1", cnt) + } +} + +func countErrors(errs []*analysistest.Result) int { + cnt := 0 + for _, e := range errs { + if r, ok := e.Result.(Result); ok { + cnt += len(r.Errors) + } + } + return cnt +} From 7547edb550f6bca2761d2b06d761e6cf201cb7bf Mon Sep 17 00:00:00 2001 From: Nodar Date: Thu, 17 Aug 2023 17:56:28 +0200 Subject: [PATCH 069/775] Add empty line at the end of gitignore --- .gitignore | 2 +- .golangci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 8937c1b5d..02cc86192 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,4 @@ yarn-error.log local/ testdata system_tests/test-data/* -linter/koanf/koanf.so \ No newline at end of file +linter/koanf/koanf.so diff --git a/.golangci.yml b/.golangci.yml index 952a52a0c..8f2fdda03 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,7 +23,7 @@ linters: - nilerr # ensure errors aren't mishandled - staticcheck # check for suspicious constructs - unused # check for unused constructs - - koanf + - koanf # check for koanf configurations linters-settings: errcheck: From eba8989a80857d89573223c385ea5f4dabbe66a8 Mon Sep 17 00:00:00 2001 From: Nodar Date: Thu, 17 Aug 2023 17:57:31 +0200 Subject: [PATCH 070/775] drop extra empty line in golangci.yml --- .golangci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index 8f2fdda03..47f471b5a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -53,7 +53,6 @@ linters-settings: - shadow - fieldalignment - custom: koanf: path: linter/koanf/koanf.so From a5c667343a62d839baa5384141001bd3b182778f Mon Sep 17 00:00:00 2001 From: Nodar Date: Fri, 18 Aug 2023 15:11:13 +0200 Subject: [PATCH 071/775] Run custom linter as go binary instead of plugin for golangci-lint, drop golangci-lint submodule --- .gitignore | 1 - .gitmodules | 3 --- .golangci.yml | 6 ------ Makefile | 4 +--- linter/golangci-lint | 1 - linter/koanf/koanf.go | 6 +++++- 6 files changed, 6 insertions(+), 15 deletions(-) delete mode 160000 linter/golangci-lint diff --git a/.gitignore b/.gitignore index 02cc86192..f0eb5c2ec 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,3 @@ yarn-error.log local/ testdata system_tests/test-data/* -linter/koanf/koanf.so diff --git a/.gitmodules b/.gitmodules index 11d9caa2a..7c78791c7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,6 +20,3 @@ [submodule "nitro-testnode"] path = nitro-testnode url = https://github.com/OffchainLabs/nitro-testnode.git -[submodule "linter/golangci-lint"] - path = linter/golangci-lint - url = https://github.com/golangci/golangci-lint diff --git a/.golangci.yml b/.golangci.yml index 47f471b5a..e794cdb84 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,7 +23,6 @@ linters: - nilerr # ensure errors aren't mishandled - staticcheck # check for suspicious constructs - unused # check for unused constructs - - koanf # check for koanf configurations linters-settings: errcheck: @@ -52,8 +51,3 @@ linters-settings: disable: - shadow - fieldalignment - - custom: - koanf: - path: linter/koanf/koanf.so - description: Koanf configuration linter diff --git a/Makefile b/Makefile index 71c051087..896bdd6a6 100644 --- a/Makefile +++ b/Makefile @@ -304,9 +304,7 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro # strategic rules to minimize dependency building .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make - make build -C linter/golangci-lint - go build -buildmode=plugin -o linter/koanf/koanf.so linter/koanf/koanf.go - ./linter/golangci-lint/golangci-lint run --fix + go run linter/koanf/koanf.go ./... yarn --cwd contracts solhint @touch $@ diff --git a/linter/golangci-lint b/linter/golangci-lint deleted file mode 160000 index 8000abaf0..000000000 --- a/linter/golangci-lint +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8000abaf0e6e28e8179864f0317349cecab47c05 diff --git a/linter/koanf/koanf.go b/linter/koanf/koanf.go index 4aaddaa49..bc94a9c20 100644 --- a/linter/koanf/koanf.go +++ b/linter/koanf/koanf.go @@ -9,8 +9,8 @@ import ( "unicode" "github.com/fatih/structtag" - "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/singlechecker" ) func New(conf any) ([]*analysis.Analyzer, error) { @@ -114,3 +114,7 @@ func normalize(s string) string { func isAlphanumeric(c rune) bool { return unicode.IsLetter(c) || unicode.IsDigit(c) } + +func main() { + singlechecker.Main(Analyzer) +} From ed4942d38adc5afe1918740d35c3e67d1204f372 Mon Sep 17 00:00:00 2001 From: Nodar Date: Fri, 18 Aug 2023 16:02:53 +0200 Subject: [PATCH 072/775] Rename testdata to testsdata because testdata is already in .gitignore --- linter/koanf/koanf_test.go | 2 +- linter/testsdata/src/a/a.go | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 linter/testsdata/src/a/a.go diff --git a/linter/koanf/koanf_test.go b/linter/koanf/koanf_test.go index 2e3e68b0f..5582e6160 100644 --- a/linter/koanf/koanf_test.go +++ b/linter/koanf/koanf_test.go @@ -13,7 +13,7 @@ func TestAll(t *testing.T) { if err != nil { t.Fatalf("Failed to get wd: %s", err) } - testdata := filepath.Join(filepath.Dir(wd), "testdata") + testdata := filepath.Join(filepath.Dir(wd), "testsdata") res := analysistest.Run(t, testdata, analyzerForTests, "a") if cnt := countErrors(res); cnt != 1 { t.Errorf("analysistest.Run() got %v errors, expected 1", cnt) diff --git a/linter/testsdata/src/a/a.go b/linter/testsdata/src/a/a.go new file mode 100644 index 000000000..ddf77b6ed --- /dev/null +++ b/linter/testsdata/src/a/a.go @@ -0,0 +1,11 @@ +package a + +type Config struct { + L2 int `koanf:"chain"` + LogLevel int `koanf:"log-level"` + LogType int `koanf:"log-type"` + Metrics int `koanf:"metrics"` + PProf int `koanf:"pprof"` + Node int `koanf:"node"` + Queue int `koanf:"queue"` +} From c93e79a45f37bc729e2d83a70991f4078964b0f4 Mon Sep 17 00:00:00 2001 From: Nodar Date: Fri, 18 Aug 2023 17:18:21 +0200 Subject: [PATCH 073/775] rename 'testsdata' to 'testdata' drop it from .gitignore --- .gitignore | 1 - linter/koanf/koanf_test.go | 2 +- linter/{testsdata => testdata}/src/a/a.go | 0 3 files changed, 1 insertion(+), 2 deletions(-) rename linter/{testsdata => testdata}/src/a/a.go (100%) diff --git a/.gitignore b/.gitignore index f0eb5c2ec..60df842f0 100644 --- a/.gitignore +++ b/.gitignore @@ -19,5 +19,4 @@ solgen/go/ target/ yarn-error.log local/ -testdata system_tests/test-data/* diff --git a/linter/koanf/koanf_test.go b/linter/koanf/koanf_test.go index 5582e6160..2e3e68b0f 100644 --- a/linter/koanf/koanf_test.go +++ b/linter/koanf/koanf_test.go @@ -13,7 +13,7 @@ func TestAll(t *testing.T) { if err != nil { t.Fatalf("Failed to get wd: %s", err) } - testdata := filepath.Join(filepath.Dir(wd), "testsdata") + testdata := filepath.Join(filepath.Dir(wd), "testdata") res := analysistest.Run(t, testdata, analyzerForTests, "a") if cnt := countErrors(res); cnt != 1 { t.Errorf("analysistest.Run() got %v errors, expected 1", cnt) diff --git a/linter/testsdata/src/a/a.go b/linter/testdata/src/a/a.go similarity index 100% rename from linter/testsdata/src/a/a.go rename to linter/testdata/src/a/a.go From 810887cd35aa10a590def3db03945a3ea308debe Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 18 Aug 2023 11:56:03 -0500 Subject: [PATCH 074/775] add sequencer coordinator management UI tool --- Dockerfile | 1 + Makefile | 5 +- .../rediscoordinator/redis_coordinator.go | 77 ++++++ .../seq-coordinator-manager.go | 249 ++++++++++++++++++ go.mod | 8 +- go.sum | 26 ++ 6 files changed, 364 insertions(+), 2 deletions(-) create mode 100644 cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go create mode 100644 cmd/seq-coordinator-manager/seq-coordinator-manager.go diff --git a/Dockerfile b/Dockerfile index 367d76d4b..c1a28760c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -202,6 +202,7 @@ WORKDIR /home/user COPY --from=node-builder /workspace/target/bin/nitro /usr/local/bin/ COPY --from=node-builder /workspace/target/bin/relay /usr/local/bin/ COPY --from=node-builder /workspace/target/bin/nitro-val /usr/local/bin/ +COPY --from=node-builder /workspace/target/bin/seq-coordinator-manager /usr/local/bin/ COPY --from=machine-versions /workspace/machines /home/user/target/machines USER root RUN export DEBIAN_FRONTEND=noninteractive && \ diff --git a/Makefile b/Makefile index 205025dfe..1358f961e 100644 --- a/Makefile +++ b/Makefile @@ -88,7 +88,7 @@ push: lint test-go .make/fmt all: build build-replay-env test-gen-proofs @touch .make/all -build: $(patsubst %,$(output_root)/bin/%, nitro deploy relay daserver datool seq-coordinator-invalidate nitro-val) +build: $(patsubst %,$(output_root)/bin/%, nitro deploy relay daserver datool seq-coordinator-invalidate nitro-val seq-coordinator-manager) @printf $(done) build-node-deps: $(go_source) build-prover-header build-prover-lib build-jit .make/solgen .make/cbrotli-lib @@ -185,6 +185,9 @@ $(output_root)/bin/seq-coordinator-invalidate: $(DEP_PREDICATE) build-node-deps $(output_root)/bin/nitro-val: $(DEP_PREDICATE) build-node-deps go build $(GOLANG_PARAMS) -o $@ "$(CURDIR)/cmd/nitro-val" +$(output_root)/bin/seq-coordinator-manager: $(DEP_PREDICATE) build-node-deps + go build $(GOLANG_PARAMS) -o $@ "$(CURDIR)/cmd/seq-coordinator-manager" + # recompile wasm, but don't change timestamp unless files differ $(replay_wasm): $(DEP_PREDICATE) $(go_source) .make/solgen mkdir -p `dirname $(replay_wasm)` diff --git a/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go b/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go new file mode 100644 index 000000000..db3724240 --- /dev/null +++ b/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go @@ -0,0 +1,77 @@ +package rediscoordinator + +import ( + "context" + "errors" + "strings" + + "github.com/go-redis/redis/v8" + "github.com/offchainlabs/nitro/util/redisutil" +) + +type RedisCoordinator struct { + Client redis.UniversalClient +} + +func NewRedisCoordinator(redisURL string) (*RedisCoordinator, error) { + redisClient, err := redisutil.RedisClientFromURL(redisURL) + if err != nil { + return nil, err + } + + return &RedisCoordinator{ + Client: redisClient, + }, nil +} + +func (rc *RedisCoordinator) GetPriorities(ctx context.Context) ([]string, map[string]int, error) { + prioritiesMap := make(map[string]int) + prioritiesString, err := rc.Client.Get(ctx, redisutil.PRIORITIES_KEY).Result() + if err != nil { + if errors.Is(err, redis.Nil) { + err = errors.New("sequencer priorities unset") + } + return []string{}, prioritiesMap, err + } + priorities := strings.Split(prioritiesString, ",") + for _, url := range priorities { + prioritiesMap[url]++ + } + return priorities, prioritiesMap, nil +} + +func (rc *RedisCoordinator) GetLivelinessMap(ctx context.Context) (map[string]int, error) { + livelinessMap := make(map[string]int) + livelinessList, _, err := rc.Client.Scan(ctx, 0, redisutil.WANTS_LOCKOUT_KEY_PREFIX+"*", 0).Result() + if err != nil { + return livelinessMap, err + } + for _, elem := range livelinessList { + url := strings.TrimPrefix(elem, redisutil.WANTS_LOCKOUT_KEY_PREFIX) + livelinessMap[url]++ + } + return livelinessMap, nil +} + +func (rc *RedisCoordinator) UpdatePriorities(ctx context.Context, priorities []string) error { + prioritiesString := strings.Join(priorities, ",") + err := rc.Client.Set(ctx, redisutil.PRIORITIES_KEY, prioritiesString, 0).Err() + if err != nil { + if errors.Is(err, redis.Nil) { + err = errors.New("sequencer priorities unset") + } + } + return err +} + +// CurrentChosenSequencer retrieves the current chosen sequencer holding the lock +func (c *RedisCoordinator) CurrentChosenSequencer(ctx context.Context) (string, error) { + current, err := c.Client.Get(ctx, redisutil.CHOSENSEQ_KEY).Result() + if errors.Is(err, redis.Nil) { + return "", nil + } + if err != nil { + return "", err + } + return current, nil +} diff --git a/cmd/seq-coordinator-manager/seq-coordinator-manager.go b/cmd/seq-coordinator-manager/seq-coordinator-manager.go new file mode 100644 index 000000000..5844e2e7e --- /dev/null +++ b/cmd/seq-coordinator-manager/seq-coordinator-manager.go @@ -0,0 +1,249 @@ +package main + +import ( + "context" + "fmt" + "os" + "strconv" + + "github.com/enescakir/emoji" + "github.com/ethereum/go-ethereum/log" + "github.com/gdamore/tcell/v2" + "github.com/offchainlabs/nitro/cmd/seq-coordinator-manager/rediscoordinator" + "github.com/rivo/tview" +) + +// Tview +var pages = tview.NewPages() +var app = tview.NewApplication() + +// Lists +var prioritySeqList = tview.NewList().ShowSecondaryText(false) +var nonPrioritySeqList = tview.NewList().ShowSecondaryText(false) + +// Forms +var addSeqForm = tview.NewForm() +var priorityForm = tview.NewForm() +var nonPriorityForm = tview.NewForm() + +// Sequencer coordinator managment UI data store +type manager struct { + redisCoordinator *rediscoordinator.RedisCoordinator + prioritiesMap map[string]int + livelinessMap map[string]int + priorityList []string + nonPriorityList []string +} + +func main() { + ctx, cancelFunc := context.WithCancel(context.Background()) + defer cancelFunc() + + args := os.Args[1:] + if len(args) != 1 { + fmt.Fprintf(os.Stderr, "Usage: redis-seq-manager [redis-url]\n") + os.Exit(1) + } + redisURL := args[0] + redisCoordinator, err := rediscoordinator.NewRedisCoordinator(redisURL) + if err != nil { + panic(err) + } + + seqManager := &manager{ + redisCoordinator: redisCoordinator, + prioritiesMap: make(map[string]int), + livelinessMap: make(map[string]int), + } + + seqManager.refreshAllLists(ctx) + seqManager.populateLists(ctx) + + prioritySeqList.SetSelectedFunc(func(index int, name string, second_name string, shortcut rune) { + nonPriorityForm.Clear(true) + + n := len(seqManager.priorityList) + priorities := make([]string, n) + for i := 0; i < n; i++ { + priorities[i] = strconv.Itoa(i) + } + + target := index + priorityForm.Clear(true) + priorityForm.AddTextView("Additional details:", "Status:\nBlockNumber:", 0, 2, false, true) + priorityForm.AddDropDown("Change priority to ->", priorities, index, func(priority string, selection int) { + target = selection + }) + priorityForm.AddButton("Save", func() { + if target != index { + seqManager.updatePriorityList(ctx, index, target) + } + seqManager.populateLists(ctx) + pages.SwitchToPage("Menu") + }) + }) + + nonPrioritySeqList.SetSelectedFunc(func(index int, name string, second_name string, shortcut rune) { + priorityForm.Clear(true) + + n := len(seqManager.priorityList) + priorities := make([]string, n+1) + for i := 0; i < n+1; i++ { + priorities[i] = strconv.Itoa(i) + } + + target := index + nonPriorityForm.Clear(true) + nonPriorityForm.AddTextView("Additional details:", "Status:\nBlockNumber:", 0, 2, false, true) + nonPriorityForm.AddDropDown("Set priority to ->", priorities, index, func(priority string, selection int) { + target = selection + }) + nonPriorityForm.AddButton("Save", func() { + seqManager.priorityList = append(seqManager.priorityList, seqManager.nonPriorityList[index]) + index = len(seqManager.priorityList) - 1 + seqManager.updatePriorityList(ctx, index, target) + nonPriorityForm.Clear(true) + seqManager.populateLists(ctx) + pages.SwitchToPage("Menu") + }) + }) + + // UI design + flex := tview.NewFlex() + priorityHeading := tview.NewTextView(). + SetTextColor(tcell.ColorYellow). + SetText("-----Priority List-----") + nonPriorityHeading := tview.NewTextView(). + SetTextColor(tcell.ColorYellow). + SetText("-----Not in priority list but online-----") + instructions := tview.NewTextView(). + SetTextColor(tcell.ColorYellow). + SetText("(r) to refresh \n(a) to add sequencer\n(q) to quit") + + flex.SetDirection(tview.FlexRow). + AddItem(priorityHeading, 0, 1, false). + AddItem(tview.NewFlex(). + AddItem(prioritySeqList, 0, 2, true). + AddItem(priorityForm, 0, 3, false), 0, 12, false). + AddItem(nonPriorityHeading, 0, 1, false). + AddItem(tview.NewFlex(). + AddItem(nonPrioritySeqList, 0, 2, true). + AddItem(nonPriorityForm, 0, 3, false), 0, 12, false). + AddItem(instructions, 0, 2, false).SetBorder(true) + + flex.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + if event.Rune() == 114 { + seqManager.refreshAllLists(ctx) + priorityForm.Clear(true) + nonPriorityForm.Clear(true) + seqManager.populateLists(ctx) + pages.SwitchToPage("Menu") + } else if event.Rune() == 97 { + addSeqForm.Clear(true) + seqManager.addSeqPriorityForm(ctx) + pages.SwitchToPage("Add Sequencer") + } else if event.Rune() == 113 { + app.Stop() + } + return event + }) + + pages.AddPage("Menu", flex, true, true) + pages.AddPage("Add Sequencer", addSeqForm, true, false) + + if err := app.SetRoot(pages, true).EnableMouse(true).Run(); err != nil { + panic(err) + } +} + +// updatePriorityList updates the list by changing the position of seq present at `index` to target +func (sm *manager) updatePriorityList(ctx context.Context, index int, target int) { + for i := index - 1; i >= target; i-- { + sm.priorityList[i], sm.priorityList[i+1] = sm.priorityList[i+1], sm.priorityList[i] + } + for i := index + 1; i <= target; i++ { + sm.priorityList[i], sm.priorityList[i-1] = sm.priorityList[i-1], sm.priorityList[i] + } + err := sm.redisCoordinator.UpdatePriorities(ctx, sm.priorityList) + if err != nil { + log.Warn("Failed to update priority, reverting change", "sequencer", sm.priorityList[target], "err", err) + } + sm.refreshAllLists(ctx) +} + +// populateLists populates seq's in priority list and seq's that are online but not in priority +func (sm *manager) populateLists(ctx context.Context) { + prioritySeqList.Clear() + chosen, err := sm.redisCoordinator.CurrentChosenSequencer(ctx) + if err != nil { + panic(err) + } + for index, seqURL := range sm.priorityList { + sec := "" + if seqURL == chosen { + sec = fmt.Sprintf(" %vchosen", emoji.LeftArrow) + } + status := fmt.Sprintf("%v ", emoji.RedCircle) + if _, ok := sm.livelinessMap[seqURL]; ok { + status = fmt.Sprintf("%v ", emoji.GreenCircle) + } + prioritySeqList.AddItem(status+seqURL+sec, "", rune(48+index), nil).SetSecondaryTextColor(tcell.ColorPurple) + } + + nonPrioritySeqList.Clear() + status := fmt.Sprintf("%v ", emoji.GreenCircle) + for _, seqURL := range sm.nonPriorityList { + nonPrioritySeqList.AddItem(status+seqURL, "", rune(45), nil) + } +} + +// addSeqPriorityForm returns a form with fields to add a new sequencer to priority list +func (sm *manager) addSeqPriorityForm(ctx context.Context) *tview.Form { + URL := "" + addSeqForm.AddInputField("Sequencer URL", "", 0, nil, func(url string) { + URL = url + }) + addSeqForm.AddButton("Cancel", func() { + priorityForm.Clear(true) + sm.populateLists(ctx) + pages.SwitchToPage("Menu") + }) + addSeqForm.AddButton("Add", func() { + // check if url is valid, i.e it doesnt already exist in the priority list + if _, ok := sm.prioritiesMap[URL]; !ok && URL != "" { + sm.priorityList = append(sm.priorityList, URL) + err := sm.redisCoordinator.UpdatePriorities(ctx, sm.priorityList) + if err != nil { + log.Warn("Failed to add sequencer to the priority list", URL) + } + sm.refreshAllLists(ctx) + } + sm.populateLists(ctx) + pages.SwitchToPage("Menu") + }) + return addSeqForm +} + +// refreshAllLists gets the current status of all the lists displayed in the UI +func (sm *manager) refreshAllLists(ctx context.Context) { + sequencerURLList, mapping, err := sm.redisCoordinator.GetPriorities(ctx) + if err != nil { + panic(err) + } + sm.priorityList = sequencerURLList + sm.prioritiesMap = mapping + + mapping, err = sm.redisCoordinator.GetLivelinessMap(ctx) + if err != nil { + panic(err) + } + sm.livelinessMap = mapping + + urlList := []string{} + for url := range sm.livelinessMap { + if _, ok := sm.prioritiesMap[url]; !ok { + urlList = append(urlList, url) + } + } + sm.nonPriorityList = urlList +} diff --git a/go.mod b/go.mod index 5adfd1938..e8fa50319 100644 --- a/go.mod +++ b/go.mod @@ -86,11 +86,14 @@ require ( github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect + github.com/enescakir/emoji v1.0.0 // indirect github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gammazero/deque v0.2.1 // indirect + github.com/gdamore/encoding v1.0.0 // indirect + github.com/gdamore/tcell/v2 v2.6.0 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -188,6 +191,7 @@ require ( github.com/libp2p/go-reuseport v0.2.0 // indirect github.com/libp2p/go-yamux/v4 v4.0.0 // indirect github.com/libp2p/zeroconf/v2 v2.2.0 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/miekg/dns v1.1.50 // indirect @@ -224,6 +228,8 @@ require ( github.com/quic-go/webtransport-go v0.5.2 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/rhnvrm/simples3 v0.6.1 // indirect + github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 // indirect + github.com/rivo/uniseg v0.4.3 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/samber/lo v1.36.0 // indirect @@ -298,7 +304,7 @@ require ( github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mitchellh/mapstructure v1.4.2 github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect diff --git a/go.sum b/go.sum index 58155db12..5f03dee5b 100644 --- a/go.sum +++ b/go.sum @@ -310,6 +310,8 @@ github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/ github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/enescakir/emoji v1.0.0 h1:W+HsNql8swfCQFtioDGDHCHri8nudlK1n5p2rHCJoog= +github.com/enescakir/emoji v1.0.0/go.mod h1:Bt1EKuLnKDTYpLALApstIkAjdDrS/8IAgTkKp+WKFD0= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -348,6 +350,10 @@ github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZ github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= +github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= +github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= +github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -1140,6 +1146,8 @@ github.com/libp2p/zeroconf/v2 v2.2.0/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0 github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lucas-clemente/quic-go v0.19.3/go.mod h1:ADXpNbTQjq1hIzCpB+y/k5iz4n4z4IwqoLb94Kh5Hu8= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -1174,6 +1182,8 @@ github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -1443,6 +1453,11 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rhnvrm/simples3 v0.6.1 h1:H0DJwybR6ryQE+Odi9eqkHuzjYAeJgtGcGtuBwOhsH8= github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= +github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 h1:ZyM/+FYnpbZsFWuCohniM56kRoHRB4r5EuIzXEYkpxo= +github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703/go.mod h1:nVwGv4MP47T0jvlk7KuTTjjuSmrGO4JF0iaiNt4bufE= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= +github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1631,6 +1646,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLCur2yWnJzwQEKRcAHXo6seXGuSwWw= github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -1774,6 +1790,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1835,6 +1852,7 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1857,6 +1875,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1948,13 +1967,18 @@ golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1966,6 +1990,7 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2035,6 +2060,7 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From ef30f3187e85ba9d80b63a7a06c9e68ef4c30539 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 21 Aug 2023 10:25:56 -0500 Subject: [PATCH 075/775] add keyboard-only support with additional functionalities --- .../seq-coordinator-manager.go | 93 +++++++++++++++---- 1 file changed, 75 insertions(+), 18 deletions(-) diff --git a/cmd/seq-coordinator-manager/seq-coordinator-manager.go b/cmd/seq-coordinator-manager/seq-coordinator-manager.go index 5844e2e7e..f39a810e9 100644 --- a/cmd/seq-coordinator-manager/seq-coordinator-manager.go +++ b/cmd/seq-coordinator-manager/seq-coordinator-manager.go @@ -70,17 +70,37 @@ func main() { target := index priorityForm.Clear(true) - priorityForm.AddTextView("Additional details:", "Status:\nBlockNumber:", 0, 2, false, true) + priorityForm.AddTextView("Additional details:", "Status:\nBlockNumber:\nStatus:\nBlockNumber:", 0, 2, false, true) priorityForm.AddDropDown("Change priority to ->", priorities, index, func(priority string, selection int) { target = selection }) - priorityForm.AddButton("Save", func() { + priorityForm.AddButton("Update", func() { if target != index { seqManager.updatePriorityList(ctx, index, target) } + priorityForm.Clear(true) + seqManager.populateLists(ctx) + pages.SwitchToPage("Menu") + app.SetFocus(prioritySeqList) + }) + priorityForm.AddButton("Cancel", func() { + priorityForm.Clear(true) + pages.SwitchToPage("Menu") + app.SetFocus(prioritySeqList) + }) + priorityForm.AddButton("Remove", func() { + url := seqManager.priorityList[0] + delete(seqManager.prioritiesMap, url) + seqManager.updatePriorityList(ctx, index, 0) + seqManager.priorityList = seqManager.priorityList[1:] + + priorityForm.Clear(true) seqManager.populateLists(ctx) pages.SwitchToPage("Menu") + app.SetFocus(prioritySeqList) }) + priorityForm.SetFocus(1) + app.SetFocus(priorityForm) }) nonPrioritySeqList.SetSelectedFunc(func(index int, name string, second_name string, shortcut rune) { @@ -98,14 +118,30 @@ func main() { nonPriorityForm.AddDropDown("Set priority to ->", priorities, index, func(priority string, selection int) { target = selection }) - nonPriorityForm.AddButton("Save", func() { - seqManager.priorityList = append(seqManager.priorityList, seqManager.nonPriorityList[index]) + nonPriorityForm.AddButton("Update", func() { + key := seqManager.nonPriorityList[index] + seqManager.priorityList = append(seqManager.priorityList, key) + seqManager.prioritiesMap[key]++ + index = len(seqManager.priorityList) - 1 seqManager.updatePriorityList(ctx, index, target) + nonPriorityForm.Clear(true) seqManager.populateLists(ctx) pages.SwitchToPage("Menu") + if len(seqManager.nonPriorityList) > 0 { + app.SetFocus(nonPrioritySeqList) + } else { + app.SetFocus(prioritySeqList) + } + }) + nonPriorityForm.AddButton("Cancel", func() { + nonPriorityForm.Clear(true) + pages.SwitchToPage("Menu") + app.SetFocus(nonPrioritySeqList) }) + nonPriorityForm.SetFocus(1) + app.SetFocus(nonPriorityForm) }) // UI design @@ -118,18 +154,18 @@ func main() { SetText("-----Not in priority list but online-----") instructions := tview.NewTextView(). SetTextColor(tcell.ColorYellow). - SetText("(r) to refresh \n(a) to add sequencer\n(q) to quit") + SetText("(r) to refresh\n(s) to save all changes\n(c) to switch between lists\n(a) to add sequencer\n(q) to quit\n(tab) to navigate") flex.SetDirection(tview.FlexRow). AddItem(priorityHeading, 0, 1, false). AddItem(tview.NewFlex(). AddItem(prioritySeqList, 0, 2, true). - AddItem(priorityForm, 0, 3, false), 0, 12, false). + AddItem(priorityForm, 0, 3, true), 0, 12, true). AddItem(nonPriorityHeading, 0, 1, false). AddItem(tview.NewFlex(). AddItem(nonPrioritySeqList, 0, 2, true). - AddItem(nonPriorityForm, 0, 3, false), 0, 12, false). - AddItem(instructions, 0, 2, false).SetBorder(true) + AddItem(nonPriorityForm, 0, 3, true), 0, 12, true). + AddItem(instructions, 0, 3, false).SetBorder(true) flex.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Rune() == 114 { @@ -138,10 +174,24 @@ func main() { nonPriorityForm.Clear(true) seqManager.populateLists(ctx) pages.SwitchToPage("Menu") + app.SetFocus(prioritySeqList) + } else if event.Rune() == 115 { + seqManager.pushUpdates(ctx) + priorityForm.Clear(true) + nonPriorityForm.Clear(true) + seqManager.populateLists(ctx) + pages.SwitchToPage("Menu") + app.SetFocus(prioritySeqList) } else if event.Rune() == 97 { addSeqForm.Clear(true) seqManager.addSeqPriorityForm(ctx) pages.SwitchToPage("Add Sequencer") + } else if event.Rune() == 99 { + if prioritySeqList.HasFocus() { + app.SetFocus(nonPrioritySeqList) + } else { + app.SetFocus(prioritySeqList) + } } else if event.Rune() == 113 { app.Stop() } @@ -164,11 +214,14 @@ func (sm *manager) updatePriorityList(ctx context.Context, index int, target int for i := index + 1; i <= target; i++ { sm.priorityList[i], sm.priorityList[i-1] = sm.priorityList[i-1], sm.priorityList[i] } - err := sm.redisCoordinator.UpdatePriorities(ctx, sm.priorityList) - if err != nil { - log.Warn("Failed to update priority, reverting change", "sequencer", sm.priorityList[target], "err", err) + + urlList := []string{} + for url := range sm.livelinessMap { + if _, ok := sm.prioritiesMap[url]; !ok { + urlList = append(urlList, url) + } } - sm.refreshAllLists(ctx) + sm.nonPriorityList = urlList } // populateLists populates seq's in priority list and seq's that are online but not in priority @@ -187,7 +240,7 @@ func (sm *manager) populateLists(ctx context.Context) { if _, ok := sm.livelinessMap[seqURL]; ok { status = fmt.Sprintf("%v ", emoji.GreenCircle) } - prioritySeqList.AddItem(status+seqURL+sec, "", rune(48+index), nil).SetSecondaryTextColor(tcell.ColorPurple) + prioritySeqList.AddItem(status+seqURL+sec, "", int32(48+index), nil).SetSecondaryTextColor(tcell.ColorPurple) } nonPrioritySeqList.Clear() @@ -212,11 +265,6 @@ func (sm *manager) addSeqPriorityForm(ctx context.Context) *tview.Form { // check if url is valid, i.e it doesnt already exist in the priority list if _, ok := sm.prioritiesMap[URL]; !ok && URL != "" { sm.priorityList = append(sm.priorityList, URL) - err := sm.redisCoordinator.UpdatePriorities(ctx, sm.priorityList) - if err != nil { - log.Warn("Failed to add sequencer to the priority list", URL) - } - sm.refreshAllLists(ctx) } sm.populateLists(ctx) pages.SwitchToPage("Menu") @@ -224,6 +272,15 @@ func (sm *manager) addSeqPriorityForm(ctx context.Context) *tview.Form { return addSeqForm } +// pushUpdates pushes the local changes to the redis server +func (sm *manager) pushUpdates(ctx context.Context) { + err := sm.redisCoordinator.UpdatePriorities(ctx, sm.priorityList) + if err != nil { + log.Warn("Failed to push local changes to the priority list") + } + sm.refreshAllLists(ctx) +} + // refreshAllLists gets the current status of all the lists displayed in the UI func (sm *manager) refreshAllLists(ctx context.Context) { sequencerURLList, mapping, err := sm.redisCoordinator.GetPriorities(ctx) From f95dd315b720dc149f46821691e482fabb97f938 Mon Sep 17 00:00:00 2001 From: Nodar Date: Mon, 21 Aug 2023 18:00:21 +0200 Subject: [PATCH 076/775] Implement linter detection of non-matching flag and filed name --- linter/koanf/koanf.go | 100 +++++++++++++++++++++++++++++++++++++ linter/koanf/koanf_test.go | 4 +- linter/testdata/src/a/a.go | 27 ++++++++++ 3 files changed, 129 insertions(+), 2 deletions(-) diff --git a/linter/koanf/koanf.go b/linter/koanf/koanf.go index bc94a9c20..8dbb392cb 100644 --- a/linter/koanf/koanf.go +++ b/linter/koanf/koanf.go @@ -51,6 +51,8 @@ func run(dryRun bool, pass *analysis.Pass) (interface{}, error) { switch v := node.(type) { case *ast.StructType: res = checkStruct(pass, v) + case *ast.FuncDecl: + res = checkFlagDefs(pass, v) default: } for _, err := range res.Errors { @@ -70,6 +72,104 @@ func run(dryRun bool, pass *analysis.Pass) (interface{}, error) { return ret, nil } +func containsFlagSet(params []*ast.Field) bool { + for _, p := range params { + se, ok := p.Type.(*ast.StarExpr) + if !ok { + continue + } + sle, ok := se.X.(*ast.SelectorExpr) + if !ok { + continue + } + if sle.Sel.Name == "FlagSet" { + return true + } + } + return false +} + +// checkFlagDefs checks flag definitions in the function. +// Result contains list of errors where flag name doesn't match field name. +func checkFlagDefs(pass *analysis.Pass, f *ast.FuncDecl) Result { + // Ignore functions that does not get flagset as parameter. + if !containsFlagSet(f.Type.Params.List) { + return Result{} + } + var res Result + for _, s := range f.Body.List { + es, ok := s.(*ast.ExprStmt) + if !ok { + continue + } + callE, ok := es.X.(*ast.CallExpr) + if !ok { + continue + } + if len(callE.Args) != 3 { + continue + } + sl, ok := extractStrLit(callE.Args[0]) + if !ok { + continue + } + s, ok := selector(callE.Args[1]) + if !ok { + continue + } + if normSL := normalize(sl); !strings.EqualFold(normSL, s) { + res.Errors = append(res.Errors, koanfError{ + Pos: pass.Fset.Position(f.Pos()), + Message: fmt.Sprintf("koanf tag name: %q doesn't match the field: %q", sl, s), + }) + } + + } + return res +} + +func selector(e ast.Expr) (string, bool) { + n, ok := e.(ast.Node) + if !ok { + return "", false + } + se, ok := n.(*ast.SelectorExpr) + if !ok { + return "", false + } + return se.Sel.Name, true +} + +// Extracts literal from expression that is either: +// - string literal or +// - sum of variable and string literal. +// E.g. +// strLitFromSum(`"max-size"`) = "max-size" +// - strLitFromSum(`prefix + ".enable"“) = ".enable". +func extractStrLit(e ast.Expr) (string, bool) { + if s, ok := strLit(e); ok { + return s, true + } + if be, ok := e.(*ast.BinaryExpr); ok { + if be.Op == token.ADD { + if s, ok := strLit(be.Y); ok { + // Drop the prefix dot. + return s[1:], true + } + } + } + return "", false +} + +func strLit(e ast.Expr) (string, bool) { + if s, ok := e.(*ast.BasicLit); ok { + if s.Kind == token.STRING { + return strings.Trim(s.Value, "\""), true + } + } + return "", false +} + func checkStruct(pass *analysis.Pass, s *ast.StructType) Result { var res Result for _, f := range s.Fields.List { diff --git a/linter/koanf/koanf_test.go b/linter/koanf/koanf_test.go index 2e3e68b0f..e3ad5e604 100644 --- a/linter/koanf/koanf_test.go +++ b/linter/koanf/koanf_test.go @@ -15,8 +15,8 @@ func TestAll(t *testing.T) { } testdata := filepath.Join(filepath.Dir(wd), "testdata") res := analysistest.Run(t, testdata, analyzerForTests, "a") - if cnt := countErrors(res); cnt != 1 { - t.Errorf("analysistest.Run() got %v errors, expected 1", cnt) + if cnt := countErrors(res); cnt != 3 { + t.Errorf("analysistest.Run() got %v errors, expected 3", cnt) } } diff --git a/linter/testdata/src/a/a.go b/linter/testdata/src/a/a.go index ddf77b6ed..86b773910 100644 --- a/linter/testdata/src/a/a.go +++ b/linter/testdata/src/a/a.go @@ -1,6 +1,11 @@ package a +import ( + "flag" +) + type Config struct { + // Field name doesn't match koanf tag. L2 int `koanf:"chain"` LogLevel int `koanf:"log-level"` LogType int `koanf:"log-type"` @@ -9,3 +14,25 @@ type Config struct { Node int `koanf:"node"` Queue int `koanf:"queue"` } + +type BatchPosterConfig struct { + Enable bool `koanf:"enable"` + MaxSize int `koanf:"max-size" reload:"hot"` +} + +// Flag names don't match field names from default config. +// Contains 2 errors. +func BatchPosterConfigAddOptions(prefix string, f *flag.FlagSet) { + f.Bool(prefix+".enabled", DefaultBatchPosterConfig.Enable, "enable posting batches to l1") + f.Int("max-sz", DefaultBatchPosterConfig.MaxSize, "maximum batch size") +} + +func ConfigAddOptions(prefix string, f *flag.FlagSet) { + f.Bool(prefix+".enable", DefaultBatchPosterConfig.Enable, "enable posting batches to l1") + f.Int("max-size", DefaultBatchPosterConfig.MaxSize, "maximum batch size") +} + +var DefaultBatchPosterConfig = BatchPosterConfig{ + Enable: false, + MaxSize: 100000, +} From f8d72581bd06fd1221c75a70f92c4be8bb70dc03 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 21 Aug 2023 12:15:57 -0500 Subject: [PATCH 077/775] typo fix --- cmd/seq-coordinator-manager/seq-coordinator-manager.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/seq-coordinator-manager/seq-coordinator-manager.go b/cmd/seq-coordinator-manager/seq-coordinator-manager.go index f39a810e9..b8a4a47ac 100644 --- a/cmd/seq-coordinator-manager/seq-coordinator-manager.go +++ b/cmd/seq-coordinator-manager/seq-coordinator-manager.go @@ -41,7 +41,7 @@ func main() { args := os.Args[1:] if len(args) != 1 { - fmt.Fprintf(os.Stderr, "Usage: redis-seq-manager [redis-url]\n") + fmt.Fprintf(os.Stderr, "Usage: seq-coordinator-manager [redis-url]\n") os.Exit(1) } redisURL := args[0] @@ -70,7 +70,7 @@ func main() { target := index priorityForm.Clear(true) - priorityForm.AddTextView("Additional details:", "Status:\nBlockNumber:\nStatus:\nBlockNumber:", 0, 2, false, true) + priorityForm.AddTextView("Additional details:", "Status:\nBlockNumber:", 0, 2, false, true) priorityForm.AddDropDown("Change priority to ->", priorities, index, func(priority string, selection int) { target = selection }) From 309bbb42d3d5733637eb993c67187b090787d6e2 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 21 Aug 2023 13:16:35 -0500 Subject: [PATCH 078/775] remove additional details and update list numbering to accomodate longer lists --- .../seq-coordinator-manager.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/cmd/seq-coordinator-manager/seq-coordinator-manager.go b/cmd/seq-coordinator-manager/seq-coordinator-manager.go index b8a4a47ac..eb28f6023 100644 --- a/cmd/seq-coordinator-manager/seq-coordinator-manager.go +++ b/cmd/seq-coordinator-manager/seq-coordinator-manager.go @@ -70,7 +70,6 @@ func main() { target := index priorityForm.Clear(true) - priorityForm.AddTextView("Additional details:", "Status:\nBlockNumber:", 0, 2, false, true) priorityForm.AddDropDown("Change priority to ->", priorities, index, func(priority string, selection int) { target = selection }) @@ -99,7 +98,7 @@ func main() { pages.SwitchToPage("Menu") app.SetFocus(prioritySeqList) }) - priorityForm.SetFocus(1) + priorityForm.SetFocus(0) app.SetFocus(priorityForm) }) @@ -114,7 +113,6 @@ func main() { target := index nonPriorityForm.Clear(true) - nonPriorityForm.AddTextView("Additional details:", "Status:\nBlockNumber:", 0, 2, false, true) nonPriorityForm.AddDropDown("Set priority to ->", priorities, index, func(priority string, selection int) { target = selection }) @@ -140,7 +138,7 @@ func main() { pages.SwitchToPage("Menu") app.SetFocus(nonPrioritySeqList) }) - nonPriorityForm.SetFocus(1) + nonPriorityForm.SetFocus(0) app.SetFocus(nonPriorityForm) }) @@ -236,17 +234,17 @@ func (sm *manager) populateLists(ctx context.Context) { if seqURL == chosen { sec = fmt.Sprintf(" %vchosen", emoji.LeftArrow) } - status := fmt.Sprintf("%v ", emoji.RedCircle) + status := fmt.Sprintf("(%d) %v ", index, emoji.RedCircle) if _, ok := sm.livelinessMap[seqURL]; ok { - status = fmt.Sprintf("%v ", emoji.GreenCircle) + status = fmt.Sprintf("(%d) %v ", index, emoji.GreenCircle) } - prioritySeqList.AddItem(status+seqURL+sec, "", int32(48+index), nil).SetSecondaryTextColor(tcell.ColorPurple) + prioritySeqList.AddItem(status+seqURL+sec, "", rune(0), nil).SetSecondaryTextColor(tcell.ColorPurple) } nonPrioritySeqList.Clear() - status := fmt.Sprintf("%v ", emoji.GreenCircle) + status := fmt.Sprintf("(-) %v ", emoji.GreenCircle) for _, seqURL := range sm.nonPriorityList { - nonPrioritySeqList.AddItem(status+seqURL, "", rune(45), nil) + nonPrioritySeqList.AddItem(status+seqURL, "", rune(0), nil) } } From 121cc8bfee933c856230b9f11d4d9fdb40a4cb0f Mon Sep 17 00:00:00 2001 From: Nodar Date: Wed, 23 Aug 2023 15:04:26 +0200 Subject: [PATCH 079/775] Merge with mater --- go.mod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 2cae3a9cf..10991bc3a 100644 --- a/go.mod +++ b/go.mod @@ -33,6 +33,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/wealdtech/go-merkletree v1.0.0 golang.org/x/term v0.6.0 + golang.org/x/tools v0.7.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) @@ -258,7 +259,6 @@ require ( go4.org v0.0.0-20200411211856-f5505b9728dd // indirect golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect golang.org/x/mod v0.9.0 // indirect - golang.org/x/tools v0.7.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/grpc v1.46.0 // indirect @@ -312,7 +312,7 @@ require ( golang.org/x/crypto v0.6.0 golang.org/x/net v0.8.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.6.0 + golang.org/x/sys v0.7.0 golang.org/x/text v0.8.0 // indirect golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect From ccfb0065a03ee026743f7cfa81cc72e4f26725ab Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 23 Aug 2023 17:13:28 -0500 Subject: [PATCH 080/775] Initialize dev wallet as a chain owner in nitro-testnode --- nitro-testnode | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nitro-testnode b/nitro-testnode index 14f24a1ba..7ad12c0f1 160000 --- a/nitro-testnode +++ b/nitro-testnode @@ -1 +1 @@ -Subproject commit 14f24a1bad2625412602d06156156c380bd589d2 +Subproject commit 7ad12c0f1be75a72c7360d5258e0090f8225594e From 47e5e9f24821d1badcddf68cc60cfefedbb572d9 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 24 Aug 2023 10:33:30 -0500 Subject: [PATCH 081/775] fix minor bug --- cmd/seq-coordinator-manager/seq-coordinator-manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/seq-coordinator-manager/seq-coordinator-manager.go b/cmd/seq-coordinator-manager/seq-coordinator-manager.go index eb28f6023..96da53cc9 100644 --- a/cmd/seq-coordinator-manager/seq-coordinator-manager.go +++ b/cmd/seq-coordinator-manager/seq-coordinator-manager.go @@ -88,7 +88,7 @@ func main() { app.SetFocus(prioritySeqList) }) priorityForm.AddButton("Remove", func() { - url := seqManager.priorityList[0] + url := seqManager.priorityList[index] delete(seqManager.prioritiesMap, url) seqManager.updatePriorityList(ctx, index, 0) seqManager.priorityList = seqManager.priorityList[1:] From 90dd010b9427a9fb7f1f8b1919a14c1ae0ab1f94 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 24 Aug 2023 10:52:45 -0500 Subject: [PATCH 082/775] update recent merge conflict resolution --- go.sum | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go.sum b/go.sum index f7fdad471..4362d4b01 100644 --- a/go.sum +++ b/go.sum @@ -1973,6 +1973,9 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= From c5f6ba3ecb01ada623c5fe90e306ead00cb73d93 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 24 Aug 2023 13:48:16 -0500 Subject: [PATCH 083/775] update RedisCoordinator to inherit redisutil's implementation --- .../rediscoordinator/redis_coordinator.go | 25 +------------------ .../seq-coordinator-manager.go | 11 +++++--- 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go b/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go index db3724240..3dcb6f720 100644 --- a/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go +++ b/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go @@ -10,18 +10,7 @@ import ( ) type RedisCoordinator struct { - Client redis.UniversalClient -} - -func NewRedisCoordinator(redisURL string) (*RedisCoordinator, error) { - redisClient, err := redisutil.RedisClientFromURL(redisURL) - if err != nil { - return nil, err - } - - return &RedisCoordinator{ - Client: redisClient, - }, nil + *redisutil.RedisCoordinator } func (rc *RedisCoordinator) GetPriorities(ctx context.Context) ([]string, map[string]int, error) { @@ -63,15 +52,3 @@ func (rc *RedisCoordinator) UpdatePriorities(ctx context.Context, priorities []s } return err } - -// CurrentChosenSequencer retrieves the current chosen sequencer holding the lock -func (c *RedisCoordinator) CurrentChosenSequencer(ctx context.Context) (string, error) { - current, err := c.Client.Get(ctx, redisutil.CHOSENSEQ_KEY).Result() - if errors.Is(err, redis.Nil) { - return "", nil - } - if err != nil { - return "", err - } - return current, nil -} diff --git a/cmd/seq-coordinator-manager/seq-coordinator-manager.go b/cmd/seq-coordinator-manager/seq-coordinator-manager.go index 96da53cc9..9bbafe18d 100644 --- a/cmd/seq-coordinator-manager/seq-coordinator-manager.go +++ b/cmd/seq-coordinator-manager/seq-coordinator-manager.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/gdamore/tcell/v2" "github.com/offchainlabs/nitro/cmd/seq-coordinator-manager/rediscoordinator" + "github.com/offchainlabs/nitro/util/redisutil" "github.com/rivo/tview" ) @@ -45,15 +46,17 @@ func main() { os.Exit(1) } redisURL := args[0] - redisCoordinator, err := rediscoordinator.NewRedisCoordinator(redisURL) + redisutilCoordinator, err := redisutil.NewRedisCoordinator(redisURL) if err != nil { panic(err) } seqManager := &manager{ - redisCoordinator: redisCoordinator, - prioritiesMap: make(map[string]int), - livelinessMap: make(map[string]int), + redisCoordinator: &rediscoordinator.RedisCoordinator{ + RedisCoordinator: redisutilCoordinator, + }, + prioritiesMap: make(map[string]int), + livelinessMap: make(map[string]int), } seqManager.refreshAllLists(ctx) From 6d7667715a5bf5311bf9b6289a11148724c075e8 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 25 Aug 2023 11:45:53 -0500 Subject: [PATCH 084/775] add comments --- .../rediscoordinator/redis_coordinator.go | 4 ++++ cmd/seq-coordinator-manager/seq-coordinator-manager.go | 1 + 2 files changed, 5 insertions(+) diff --git a/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go b/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go index 3dcb6f720..a393719a1 100644 --- a/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go +++ b/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go @@ -9,10 +9,12 @@ import ( "github.com/offchainlabs/nitro/util/redisutil" ) +// RedisCoordinator builds upon RedisCoordinator of redisutil with additional functionality type RedisCoordinator struct { *redisutil.RedisCoordinator } +// GetPriorities returns the priority list of sequencers func (rc *RedisCoordinator) GetPriorities(ctx context.Context) ([]string, map[string]int, error) { prioritiesMap := make(map[string]int) prioritiesString, err := rc.Client.Get(ctx, redisutil.PRIORITIES_KEY).Result() @@ -29,6 +31,7 @@ func (rc *RedisCoordinator) GetPriorities(ctx context.Context) ([]string, map[st return priorities, prioritiesMap, nil } +// GetLivelinessMap returns a map whose keys are sequencers that have their liveliness set to OK func (rc *RedisCoordinator) GetLivelinessMap(ctx context.Context) (map[string]int, error) { livelinessMap := make(map[string]int) livelinessList, _, err := rc.Client.Scan(ctx, 0, redisutil.WANTS_LOCKOUT_KEY_PREFIX+"*", 0).Result() @@ -42,6 +45,7 @@ func (rc *RedisCoordinator) GetLivelinessMap(ctx context.Context) (map[string]in return livelinessMap, nil } +// UpdatePriorities updates the priority list of sequencers func (rc *RedisCoordinator) UpdatePriorities(ctx context.Context, priorities []string) error { prioritiesString := strings.Join(priorities, ",") err := rc.Client.Set(ctx, redisutil.PRIORITIES_KEY, prioritiesString, 0).Err() diff --git a/cmd/seq-coordinator-manager/seq-coordinator-manager.go b/cmd/seq-coordinator-manager/seq-coordinator-manager.go index 9bbafe18d..0a279cff6 100644 --- a/cmd/seq-coordinator-manager/seq-coordinator-manager.go +++ b/cmd/seq-coordinator-manager/seq-coordinator-manager.go @@ -265,6 +265,7 @@ func (sm *manager) addSeqPriorityForm(ctx context.Context) *tview.Form { addSeqForm.AddButton("Add", func() { // check if url is valid, i.e it doesnt already exist in the priority list if _, ok := sm.prioritiesMap[URL]; !ok && URL != "" { + sm.prioritiesMap[URL]++ sm.priorityList = append(sm.priorityList, URL) } sm.populateLists(ctx) From d53b1bc2dc48c4a07c6298547c4ac3f33b88c226 Mon Sep 17 00:00:00 2001 From: Nodar Date: Mon, 28 Aug 2023 16:31:49 +0200 Subject: [PATCH 085/775] Drop unused fields with koanf tags --- cmd/datool/datool.go | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/cmd/datool/datool.go b/cmd/datool/datool.go index 1de85037e..d20a5b52c 100644 --- a/cmd/datool/datool.go +++ b/cmd/datool/datool.go @@ -84,14 +84,13 @@ func startClient(args []string) error { // datool client rpc store type ClientStoreConfig struct { - URL string `koanf:"url"` - Message string `koanf:"message"` - RandomMessageSize int `koanf:"random-message-size"` - DASRetentionPeriod time.Duration `koanf:"das-retention-period"` - SigningKey string `koanf:"signing-key"` - SigningWallet string `koanf:"signing-wallet"` - SigningWalletPassword string `koanf:"signing-wallet-password"` - Conf genericconf.ConfConfig `koanf:"conf"` + URL string `koanf:"url"` + Message string `koanf:"message"` + RandomMessageSize int `koanf:"random-message-size"` + DASRetentionPeriod time.Duration `koanf:"das-retention-period"` + SigningKey string `koanf:"signing-key"` + SigningWallet string `koanf:"signing-wallet"` + SigningWalletPassword string `koanf:"signing-wallet-password"` } func parseClientStoreConfig(args []string) (*ClientStoreConfig, error) { @@ -196,9 +195,8 @@ func startClientStore(args []string) error { // datool client rest getbyhash type RESTClientGetByHashConfig struct { - URL string `koanf:"url"` - DataHash string `koanf:"data-hash"` - Conf genericconf.ConfConfig `koanf:"conf"` + URL string `koanf:"url"` + DataHash string `koanf:"data-hash"` } func parseRESTClientGetByHashConfig(args []string) (*RESTClientGetByHashConfig, error) { @@ -257,8 +255,7 @@ func startRESTClientGetByHash(args []string) error { // das keygen type KeyGenConfig struct { - Dir string - Conf genericconf.ConfConfig `koanf:"conf"` + Dir string // ECDSA mode. ECDSA bool `koanf:"ecdsa"` // Wallet mode. From 2b01cf8fe37f115f548ae481e2deb34d6cbecef1 Mon Sep 17 00:00:00 2001 From: Nodar Date: Mon, 28 Aug 2023 17:34:31 +0200 Subject: [PATCH 086/775] Implement linter detection of koanf fields that aren't used outside flag definitions --- Makefile | 2 +- linter/koanf/handlers.go | 241 +++++++++++++++++++++++++++++++ linter/koanf/koanf.go | 201 ++++++-------------------- linter/koanf/koanf_test.go | 62 ++++++-- linter/testdata/src/a/a.go | 38 ----- linter/testdata/src/koanf/a/a.go | 58 ++++++++ linter/testdata/src/koanf/b/b.go | 52 +++++++ 7 files changed, 447 insertions(+), 207 deletions(-) create mode 100644 linter/koanf/handlers.go delete mode 100644 linter/testdata/src/a/a.go create mode 100644 linter/testdata/src/koanf/a/a.go create mode 100644 linter/testdata/src/koanf/b/b.go diff --git a/Makefile b/Makefile index 0d93958c2..33487d060 100644 --- a/Makefile +++ b/Makefile @@ -304,7 +304,7 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro # strategic rules to minimize dependency building .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make - go run linter/koanf/koanf.go ./... + go run linter/koanf/koanf.go linter/koanf/handlers.go ./... go run linter/pointercheck/pointer.go ./... golangci-lint run --fix yarn --cwd contracts solhint diff --git a/linter/koanf/handlers.go b/linter/koanf/handlers.go new file mode 100644 index 000000000..452291e60 --- /dev/null +++ b/linter/koanf/handlers.go @@ -0,0 +1,241 @@ +package main + +import ( + "fmt" + "go/ast" + "go/token" + "strings" + "unicode" + + "github.com/fatih/structtag" + "golang.org/x/tools/go/analysis" +) + +// handleComposite tracks use of fields in composite literals. +// E.g. `Config{A: 1, B: 2, C: 3}` will increase counters of fields A,B and C. +func handleComposite(pass *analysis.Pass, cl *ast.CompositeLit, cnt map[string]int) { + id, ok := cl.Type.(*ast.Ident) + if !ok { + return + } + for _, e := range cl.Elts { + if kv, ok := e.(*ast.KeyValueExpr); ok { + if ki, ok := kv.Key.(*ast.Ident); ok { + fi := pass.TypesInfo.Types[id].Type.String() + "." + ki.Name + cnt[normalizeID(pass, fi)]++ + } + } + } +} + +// handleSelector handles selector expression recursively, that is an expression: +// a.B.C.D will update counter for fields: a.B.C.D, a.B.C and a.B. +func handleSelector(pass *analysis.Pass, se *ast.SelectorExpr, inc int, cnt map[string]int) string { + if e, ok := se.X.(*ast.SelectorExpr); ok { + // Full field identifier, including package name. + fi := pass.TypesInfo.Types[e].Type.String() + "." + se.Sel.Name + cnt[normalizeID(pass, fi)] += inc + prefix := handleSelector(pass, e, inc, cnt) + fi = prefix + "." + se.Sel.Name + cnt[normalizeID(pass, fi)] += inc + return fi + } + // Handle selectors on function calls, e.g. `config().Enabled`. + if _, ok := se.X.(*ast.CallExpr); ok { + fi := pass.TypesInfo.Types[se.X].Type.String() + "." + se.Sel.Name + cnt[normalizeID(pass, fi)] += inc + return fi + } + if ident, ok := se.X.(*ast.Ident); ok { + if pass.TypesInfo.Types[ident].Type != nil { + fi := pass.TypesInfo.Types[ident].Type.String() + "." + se.Sel.Name + cnt[normalizeID(pass, fi)] += inc + return fi + } + } + return "" +} + +// koanfFields returns a map of fields that have koanf tag. +func koanfFields(pass *analysis.Pass) map[string]token.Pos { + res := make(map[string]token.Pos) + for _, f := range pass.Files { + pkgName := f.Name.Name + ast.Inspect(f, func(node ast.Node) bool { + if ts, ok := node.(*ast.TypeSpec); ok { + st, ok := ts.Type.(*ast.StructType) + if !ok { + return true + } + for _, f := range st.Fields.List { + if tag := tagFromField(f); tag != "" { + t := strings.Join([]string{pkgName, ts.Name.Name, f.Names[0].Name}, ".") + res[t] = f.Pos() + } + } + } + return true + }) + } + return res +} + +func containsFlagSet(params []*ast.Field) bool { + for _, p := range params { + se, ok := p.Type.(*ast.StarExpr) + if !ok { + continue + } + sle, ok := se.X.(*ast.SelectorExpr) + if !ok { + continue + } + if sle.Sel.Name == "FlagSet" { + return true + } + } + return false +} + +// checkFlagDefs checks flag definitions in the function. +// Result contains list of errors where flag name doesn't match field name. +func checkFlagDefs(pass *analysis.Pass, f *ast.FuncDecl, cnt map[string]int) Result { + // Ignore functions that does not get flagset as parameter. + if !containsFlagSet(f.Type.Params.List) { + return Result{} + } + var res Result + for _, s := range f.Body.List { + es, ok := s.(*ast.ExprStmt) + if !ok { + continue + } + callE, ok := es.X.(*ast.CallExpr) + if !ok { + continue + } + if len(callE.Args) != 3 { + continue + } + sl, ok := extractStrLit(callE.Args[0]) + if !ok { + continue + } + s, ok := selectorName(callE.Args[1]) + if !ok { + continue + } + handleSelector(pass, callE.Args[1].(*ast.SelectorExpr), -1, cnt) + if normSL := normalizeTag(sl); !strings.EqualFold(normSL, s) { + res.Errors = append(res.Errors, koanfError{ + Pos: f.Pos(), + Message: fmt.Sprintf("koanf tag name: %q doesn't match the field: %q", sl, s), + err: errIncorrectFlag, + }) + } + + } + return res +} + +func selectorName(e ast.Expr) (string, bool) { + n, ok := e.(ast.Node) + if !ok { + return "", false + } + se, ok := n.(*ast.SelectorExpr) + if !ok { + return "", false + } + return se.Sel.Name, true +} + +// Extracts literal from expression that is either: +// - string literal or +// - sum of variable and string literal. +// E.g. +// strLitFromSum(`"max-size"`) = "max-size" +// - strLitFromSum(`prefix + ".enable"“) = ".enable". +func extractStrLit(e ast.Expr) (string, bool) { + if s, ok := strLit(e); ok { + return s, true + } + if be, ok := e.(*ast.BinaryExpr); ok { + if be.Op == token.ADD { + if s, ok := strLit(be.Y); ok { + // Drop the prefix dot. + return s[1:], true + } + } + } + return "", false +} + +func strLit(e ast.Expr) (string, bool) { + if s, ok := e.(*ast.BasicLit); ok { + if s.Kind == token.STRING { + return strings.Trim(s.Value, "\""), true + } + } + return "", false +} + +// tagFromField extracts koanf tag from struct field. +func tagFromField(f *ast.Field) string { + if f.Tag == nil { + return "" + } + tags, err := structtag.Parse(strings.Trim((f.Tag.Value), "`")) + if err != nil { + return "" + } + tag, err := tags.Get("koanf") + if err != nil { + return "" + } + return normalizeTag(tag.Name) +} + +// checkStruct returns violations where koanf tag name doesn't match field names. +func checkStruct(pass *analysis.Pass, s *ast.StructType) Result { + var res Result + for _, f := range s.Fields.List { + tag := tagFromField(f) + if tag == "" { + continue + } + fieldName := f.Names[0].Name + if !strings.EqualFold(tag, fieldName) { + res.Errors = append(res.Errors, koanfError{ + Pos: f.Pos(), + Message: fmt.Sprintf("field name: %q doesn't match tag name: %q\n", fieldName, tag), + err: errMismatch, + }) + } + } + return res +} + +func normalizeTag(s string) string { + ans := s[:1] + for i := 1; i < len(s); i++ { + c := rune(s[i]) + if !isAlphanumeric(c) { + continue + } + if !isAlphanumeric(rune(s[i-1])) && unicode.IsLower(c) { + c = unicode.ToUpper(c) + } + ans += string(c) + } + return ans +} + +func isAlphanumeric(c rune) bool { + return unicode.IsLetter(c) || unicode.IsDigit(c) +} + +func normalizeID(pass *analysis.Pass, id string) string { + id = strings.TrimPrefix(id, "*") + return pass.Pkg.Name() + strings.TrimPrefix(id, pass.Pkg.Path()) +} diff --git a/linter/koanf/koanf.go b/linter/koanf/koanf.go index 8dbb392cb..d6780760e 100644 --- a/linter/koanf/koanf.go +++ b/linter/koanf/koanf.go @@ -1,18 +1,23 @@ package main import ( + "errors" "fmt" "go/ast" "go/token" "reflect" - "strings" - "unicode" - "github.com/fatih/structtag" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/singlechecker" ) +var ( + errUnused = errors.New("unused") + errMismatch = errors.New("mismmatched field name and tag in a struct") + // e.g. f.Int("max-sz", DefaultBatchPosterConfig.MaxSize, "maximum batch size") + errIncorrectFlag = errors.New("mismatching flag initialization") +) + func New(conf any) ([]*analysis.Analyzer, error) { return []*analysis.Analyzer{Analyzer}, nil } @@ -33,8 +38,9 @@ var analyzerForTests = &analysis.Analyzer{ // koanfError indicates the position of an error in configuration. type koanfError struct { - Pos token.Position + Pos token.Pos Message string + err error } // Result is returned from the checkStruct function, and holds all the @@ -44,7 +50,14 @@ type Result struct { } func run(dryRun bool, pass *analysis.Pass) (interface{}, error) { - var ret Result + var ( + ret Result + cnt = make(map[string]int) + // koanfFields map contains all the struct koanfFields that have koanf tag. + // It identifies field as "{pkgName}.{structName}.{field_Name}". + // e.g. "a.BatchPosterConfig.Enable", "a.BatchPosterConfig.MaxSize" + koanfFields = koanfFields(pass) + ) for _, f := range pass.Files { ast.Inspect(f, func(node ast.Node) bool { var res Result @@ -52,167 +65,41 @@ func run(dryRun bool, pass *analysis.Pass) (interface{}, error) { case *ast.StructType: res = checkStruct(pass, v) case *ast.FuncDecl: - res = checkFlagDefs(pass, v) - default: - } - for _, err := range res.Errors { - ret.Errors = append(ret.Errors, err) - if !dryRun { - pass.Report(analysis.Diagnostic{ - Pos: pass.Fset.File(f.Pos()).Pos(err.Pos.Offset), - Message: err.Message, - Category: "koanf", - }) + res = checkFlagDefs(pass, v, cnt) + case *ast.SelectorExpr: + handleSelector(pass, v, 1, cnt) + case *ast.IfStmt: + if se, ok := v.Cond.(*ast.SelectorExpr); ok { + handleSelector(pass, se, 1, cnt) } + case *ast.CompositeLit: + handleComposite(pass, v, cnt) + default: } + ret.Errors = append(ret.Errors, res.Errors...) return true - }, - ) - } - return ret, nil -} - -func containsFlagSet(params []*ast.Field) bool { - for _, p := range params { - se, ok := p.Type.(*ast.StarExpr) - if !ok { - continue - } - sle, ok := se.X.(*ast.SelectorExpr) - if !ok { - continue - } - if sle.Sel.Name == "FlagSet" { - return true - } - } - return false -} - -// checkFlagDefs checks flag definitions in the function. -// Result contains list of errors where flag name doesn't match field name. -func checkFlagDefs(pass *analysis.Pass, f *ast.FuncDecl) Result { - // Ignore functions that does not get flagset as parameter. - if !containsFlagSet(f.Type.Params.List) { - return Result{} - } - var res Result - for _, s := range f.Body.List { - es, ok := s.(*ast.ExprStmt) - if !ok { - continue - } - callE, ok := es.X.(*ast.CallExpr) - if !ok { - continue - } - if len(callE.Args) != 3 { - continue - } - sl, ok := extractStrLit(callE.Args[0]) - if !ok { - continue - } - s, ok := selector(callE.Args[1]) - if !ok { - continue - } - if normSL := normalize(sl); !strings.EqualFold(normSL, s) { - res.Errors = append(res.Errors, koanfError{ - Pos: pass.Fset.Position(f.Pos()), - Message: fmt.Sprintf("koanf tag name: %q doesn't match the field: %q", sl, s), - }) - } - + }) } - return res -} - -func selector(e ast.Expr) (string, bool) { - n, ok := e.(ast.Node) - if !ok { - return "", false - } - se, ok := n.(*ast.SelectorExpr) - if !ok { - return "", false - } - return se.Sel.Name, true -} - -// Extracts literal from expression that is either: -// - string literal or -// - sum of variable and string literal. -// E.g. -// strLitFromSum(`"max-size"`) = "max-size" -// - strLitFromSum(`prefix + ".enable"“) = ".enable". -func extractStrLit(e ast.Expr) (string, bool) { - if s, ok := strLit(e); ok { - return s, true - } - if be, ok := e.(*ast.BinaryExpr); ok { - if be.Op == token.ADD { - if s, ok := strLit(be.Y); ok { - // Drop the prefix dot. - return s[1:], true - } - } - } - return "", false -} - -func strLit(e ast.Expr) (string, bool) { - if s, ok := e.(*ast.BasicLit); ok { - if s.Kind == token.STRING { - return strings.Trim(s.Value, "\""), true + for k := range koanfFields { + if cnt[k] == 0 { + ret.Errors = append(ret.Errors, + koanfError{ + Pos: koanfFields[k], + Message: fmt.Sprintf("field %v not used", k), + err: errUnused, + }) } } - return "", false -} - -func checkStruct(pass *analysis.Pass, s *ast.StructType) Result { - var res Result - for _, f := range s.Fields.List { - if f.Tag == nil { - continue - } - tags, err := structtag.Parse(strings.Trim((f.Tag.Value), "`")) - if err != nil { - continue - } - tag, err := tags.Get("koanf") - if err != nil { - continue - } - tagName := normalize(tag.Name) - fieldName := f.Names[0].Name - if !strings.EqualFold(tagName, fieldName) { - res.Errors = append(res.Errors, koanfError{ - Pos: pass.Fset.Position(f.Pos()), - Message: fmt.Sprintf("field name: %q doesn't match tag name: %q\n", fieldName, tagName), + for _, err := range ret.Errors { + if !dryRun { + pass.Report(analysis.Diagnostic{ + Pos: err.Pos, + Message: err.Message, + Category: "koanf", }) } } - return res -} - -func normalize(s string) string { - ans := s[:1] - for i := 1; i < len(s); i++ { - c := rune(s[i]) - if !isAlphanumeric(c) { - continue - } - if !isAlphanumeric(rune(s[i-1])) && unicode.IsLower(c) { - c = unicode.ToUpper(c) - } - ans += string(c) - } - return ans -} - -func isAlphanumeric(c rune) bool { - return unicode.IsLetter(c) || unicode.IsDigit(c) + return ret, nil } func main() { diff --git a/linter/koanf/koanf_test.go b/linter/koanf/koanf_test.go index e3ad5e604..064ae533c 100644 --- a/linter/koanf/koanf_test.go +++ b/linter/koanf/koanf_test.go @@ -1,31 +1,71 @@ package main import ( + "errors" "os" "path/filepath" "testing" + "github.com/google/go-cmp/cmp" "golang.org/x/tools/go/analysis/analysistest" ) -func TestAll(t *testing.T) { +var ( + incorrectFlag = "incorrect_flag" + mismatch = "mismatch" + unused = "unused" +) + +func testData(t *testing.T) string { + t.Helper() wd, err := os.Getwd() if err != nil { t.Fatalf("Failed to get wd: %s", err) } - testdata := filepath.Join(filepath.Dir(wd), "testdata") - res := analysistest.Run(t, testdata, analyzerForTests, "a") - if cnt := countErrors(res); cnt != 3 { - t.Errorf("analysistest.Run() got %v errors, expected 3", cnt) + return filepath.Join(filepath.Dir(wd), "testdata") +} + +// Tests koanf/a package that contains two types of errors where: +// - koanf tag doesn't match field name. +// - flag definition doesn't match field name. +// Errors are marked as comments in the package source file. +func TestMismatch(t *testing.T) { + testdata := testData(t) + got := errCounts(analysistest.Run(t, testdata, analyzerForTests, "koanf/a")) + want := map[string]int{ + incorrectFlag: 2, + mismatch: 1, + } + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("analysistest.Run() unexpected diff:\n%s\n", diff) + } +} + +func TestUnused(t *testing.T) { + testdata := testData(t) + got := errCounts(analysistest.Run(t, testdata, analyzerForTests, "koanf/b")) + if diff := cmp.Diff(got, map[string]int{"unused": 2}); diff != "" { + t.Errorf("analysistest.Run() unexpected diff:\n%s\n", diff) } } -func countErrors(errs []*analysistest.Result) int { - cnt := 0 - for _, e := range errs { - if r, ok := e.Result.(Result); ok { - cnt += len(r.Errors) +func errCounts(res []*analysistest.Result) map[string]int { + m := make(map[string]int) + for _, r := range res { + if rs, ok := r.Result.(Result); ok { + for _, e := range rs.Errors { + var s string + switch { + case errors.Is(e.err, errIncorrectFlag): + s = incorrectFlag + case errors.Is(e.err, errMismatch): + s = mismatch + case errors.Is(e.err, errUnused): + s = unused + } + m[s] = m[s] + 1 + } } } - return cnt + return m } diff --git a/linter/testdata/src/a/a.go b/linter/testdata/src/a/a.go deleted file mode 100644 index 86b773910..000000000 --- a/linter/testdata/src/a/a.go +++ /dev/null @@ -1,38 +0,0 @@ -package a - -import ( - "flag" -) - -type Config struct { - // Field name doesn't match koanf tag. - L2 int `koanf:"chain"` - LogLevel int `koanf:"log-level"` - LogType int `koanf:"log-type"` - Metrics int `koanf:"metrics"` - PProf int `koanf:"pprof"` - Node int `koanf:"node"` - Queue int `koanf:"queue"` -} - -type BatchPosterConfig struct { - Enable bool `koanf:"enable"` - MaxSize int `koanf:"max-size" reload:"hot"` -} - -// Flag names don't match field names from default config. -// Contains 2 errors. -func BatchPosterConfigAddOptions(prefix string, f *flag.FlagSet) { - f.Bool(prefix+".enabled", DefaultBatchPosterConfig.Enable, "enable posting batches to l1") - f.Int("max-sz", DefaultBatchPosterConfig.MaxSize, "maximum batch size") -} - -func ConfigAddOptions(prefix string, f *flag.FlagSet) { - f.Bool(prefix+".enable", DefaultBatchPosterConfig.Enable, "enable posting batches to l1") - f.Int("max-size", DefaultBatchPosterConfig.MaxSize, "maximum batch size") -} - -var DefaultBatchPosterConfig = BatchPosterConfig{ - Enable: false, - MaxSize: 100000, -} diff --git a/linter/testdata/src/koanf/a/a.go b/linter/testdata/src/koanf/a/a.go new file mode 100644 index 000000000..a0513fb09 --- /dev/null +++ b/linter/testdata/src/koanf/a/a.go @@ -0,0 +1,58 @@ +package a + +import ( + "flag" +) + +type Config struct { + L2 int `koanf:"chain"` // Err: mismatch. + LogLevel int `koanf:"log-level"` + LogType int `koanf:"log-type"` + Metrics int `koanf:"metrics"` + PProf int `koanf:"pprof"` + Node int `koanf:"node"` + Queue int `koanf:"queue"` +} + +// Cover using of all fields in a various way: + +// Instantiating a type. +var defaultConfig = Config{ + L2: 1, + LogLevel: 2, +} + +// Instantiating a type an taking reference. +var defaultConfigPtr = &Config{ + LogType: 3, + Metrics: 4, +} + +func init() { + defaultConfig.PProf = 5 + defaultConfig.Node, _ = 6, 0 + defaultConfigPtr.Queue = 7 +} + +type BatchPosterConfig struct { + Enable bool `koanf:"enable"` + MaxSize int `koanf:"max-size" reload:"hot"` +} + +var DefaultBatchPosterConfig BatchPosterConfig + +func BatchPosterConfigAddOptions(prefix string, f *flag.FlagSet) { + f.Bool(prefix+".enabled", DefaultBatchPosterConfig.Enable, "") // Err: incorrect flag. + f.Int("max-sz", DefaultBatchPosterConfig.MaxSize, "") // Err: incorrect flag. +} + +func ConfigAddOptions(prefix string, f *flag.FlagSet) { + f.Bool(prefix+".enable", DefaultBatchPosterConfig.Enable, "enable posting batches to l1") + f.Int("max-size", DefaultBatchPosterConfig.MaxSize, "maximum batch size") +} + +func init() { + // Fields must be used outside flag definitions at least once. + DefaultBatchPosterConfig.Enable = true + DefaultBatchPosterConfig.MaxSize = 3 +} diff --git a/linter/testdata/src/koanf/b/b.go b/linter/testdata/src/koanf/b/b.go new file mode 100644 index 000000000..fe958f17b --- /dev/null +++ b/linter/testdata/src/koanf/b/b.go @@ -0,0 +1,52 @@ +package b + +import ( + "flag" + "fmt" +) + +type ParCfg struct { + child ChildCfg `koanf:"child"` + grandChild GrandChildCfg `koanf:grandchild` +} + +var defaultCfg = ParCfg{} + +type ChildCfg struct { + A bool `koanf:"A"` + B bool `koanf:"B"` + C bool `koanf:"C"` + D bool `koanf:"D"` // Error: not used outside flag definition. +} + +var defaultChildCfg = ChildCfg{} + +func childConfigAddOptions(prefix string, f *flag.FlagSet) { + f.Bool(prefix+".a", defaultChildCfg.A, "") + f.Bool("b", defaultChildCfg.B, "") + f.Bool("c", defaultChildCfg.C, "") + f.Bool("d", defaultChildCfg.D, "") +} + +type GrandChildCfg struct { + A int `koanf:"A"` // Error: unused. +} + +func (c *GrandChildCfg) Do() { +} + +func configPtr() *ChildCfg { + return nil +} +func config() ChildCfg { + return ChildCfg{} +} + +func init() { + fmt.Printf("%v %v", config().A, configPtr().B) + // This covers usage of both `ParCfg.Child` and `ChildCfg.C`. + _ = defaultCfg.child.C + // Covers usage of grandChild. + defaultCfg.grandChild.Do() + +} From 80dc09da065f87fb5bc740dd820d687cc0942a38 Mon Sep 17 00:00:00 2001 From: Nodar Date: Mon, 28 Aug 2023 17:54:25 +0200 Subject: [PATCH 087/775] Enable custom linters (koanf/pointercheck) in CI --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2f5765d7..5b0b33848 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -129,6 +129,10 @@ jobs: version: latest skip-go-installation: true skip-pkg-cache: true + - name: Custom Lint + run: | + go run linter/koanf/koanf.go linter/koanf/handlers.go ./... + go run linter/pointercheck/pointer.go ./... - name: Set environment variables run: | From 10af61eb84e7d4e9eaa263794c53c0f14da09fc2 Mon Sep 17 00:00:00 2001 From: Nodar Date: Mon, 28 Aug 2023 17:55:35 +0200 Subject: [PATCH 088/775] Fix whitespace in ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5b0b33848..916969f32 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -132,7 +132,7 @@ jobs: - name: Custom Lint run: | go run linter/koanf/koanf.go linter/koanf/handlers.go ./... - go run linter/pointercheck/pointer.go ./... + go run linter/pointercheck/pointer.go ./... - name: Set environment variables run: | From 2754cf3322f7a359ff9c20186be706e7c8033040 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 29 Aug 2023 11:50:24 -0600 Subject: [PATCH 089/775] Fix batch bounds calculation on L3s --- arbnode/batch_poster.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index e9a166374..429701be7 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -787,7 +787,8 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) if err != nil { return false, err } - blockNumberWithPadding := arbmath.SaturatingUAdd(arbmath.BigToUintSaturating(latestHeader.Number), uint64(config.L1BlockBoundBypass/ethPosBlockTime)) + latestBlockNumber := arbutil.ParentHeaderToL1BlockNumber(latestHeader) + blockNumberWithPadding := arbmath.SaturatingUAdd(latestBlockNumber, uint64(config.L1BlockBoundBypass/ethPosBlockTime)) timestampWithPadding := arbmath.SaturatingUAdd(latestHeader.Time, uint64(config.L1BlockBoundBypass/time.Second)) l1BoundMinBlockNumber = arbmath.SaturatingUSub(blockNumberWithPadding, arbmath.BigToUintSaturating(maxTimeVariation.DelayBlocks)) From 64b6adb383227dfc47b4d10f5cfb34d76c1dc6a1 Mon Sep 17 00:00:00 2001 From: Nodar Date: Tue, 29 Aug 2023 20:03:52 +0200 Subject: [PATCH 090/775] Implement structinit linter that checks for marked structs that all instantiations initialize all the fields --- Makefile | 1 + linter/structinit/structinit.go | 122 ++++++++++++++++++++++++++ linter/structinit/structinit_test.go | 36 ++++++++ linter/testdata/src/structinit/a/a.go | 28 ++++++ 4 files changed, 187 insertions(+) create mode 100644 linter/structinit/structinit.go create mode 100644 linter/structinit/structinit_test.go create mode 100644 linter/testdata/src/structinit/a/a.go diff --git a/Makefile b/Makefile index 33487d060..9f1c2b37e 100644 --- a/Makefile +++ b/Makefile @@ -306,6 +306,7 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make go run linter/koanf/koanf.go linter/koanf/handlers.go ./... go run linter/pointercheck/pointer.go ./... + go run linter/structinit/structinit.go ./... golangci-lint run --fix yarn --cwd contracts solhint @touch $@ diff --git a/linter/structinit/structinit.go b/linter/structinit/structinit.go new file mode 100644 index 000000000..e4e65bc3f --- /dev/null +++ b/linter/structinit/structinit.go @@ -0,0 +1,122 @@ +package main + +import ( + "fmt" + "go/ast" + "go/token" + "reflect" + "strings" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/singlechecker" +) + +// Tip for linter that struct that has this comment should be included in the +// analysis. +// Note: comment should be directly line above the struct definition. +const linterTip = "// lint:require-exhaustive-initialization" + +func New(conf any) ([]*analysis.Analyzer, error) { + return []*analysis.Analyzer{Analyzer}, nil +} + +// Analyzer implements struct analyzer for structs that are annotated with +// `linterTip`, it checks that every instantiation initializes all the fields. +var Analyzer = &analysis.Analyzer{ + Name: "structinit", + Doc: "check for struct field initializations", + Run: func(p *analysis.Pass) (interface{}, error) { return run(false, p) }, + ResultType: reflect.TypeOf(Result{}), +} + +var analyzerForTests = &analysis.Analyzer{ + Name: "teststructinit", + Doc: "check for struct field initializations", + Run: func(p *analysis.Pass) (interface{}, error) { return run(true, p) }, + ResultType: reflect.TypeOf(Result{}), +} + +type structError struct { + Pos token.Pos + Message string +} + +type Result struct { + Errors []structError +} + +func run(dryRun bool, pass *analysis.Pass) (interface{}, error) { + var ( + ret Result + structs = markedStructs(pass) + ) + for _, f := range pass.Files { + ast.Inspect(f, func(node ast.Node) bool { + // For every composite literal check that number of elements in + // the literal match the number of struct fields. + if cl, ok := node.(*ast.CompositeLit); ok { + stName := pass.TypesInfo.Types[cl].Type.String() + if cnt, found := structs[stName]; found && cnt != len(cl.Elts) { + ret.Errors = append(ret.Errors, structError{ + Pos: cl.Pos(), + Message: fmt.Sprintf("struct: %q initialized with: %v of total: %v fields", stName, len(cl.Elts), cnt), + }) + + } + + } + return true + }) + } + for _, err := range ret.Errors { + if !dryRun { + pass.Report(analysis.Diagnostic{ + Pos: err.Pos, + Message: err.Message, + Category: "structinit", + }) + } + } + return ret, nil +} + +// markedStructs returns a map of structs that are annotated for linter to check +// that all fields are initialized when the struct is instantiated. +// It maps struct full name (including package path) to number of fields it contains. +func markedStructs(pass *analysis.Pass) map[string]int { + res := make(map[string]int) + for _, f := range pass.Files { + tips := make(map[position]bool) + ast.Inspect(f, func(node ast.Node) bool { + switch n := node.(type) { + case *ast.Comment: + p := pass.Fset.Position(node.Pos()) + if strings.Contains(n.Text, linterTip) { + tips[position{p.Filename, p.Line + 1}] = true + } + case *ast.TypeSpec: + if st, ok := n.Type.(*ast.StructType); ok { + p := pass.Fset.Position(st.Struct) + if tips[position{p.Filename, p.Line}] { + fieldsCnt := 0 + for _, field := range st.Fields.List { + fieldsCnt += len(field.Names) + } + res[pass.Pkg.Path()+"."+n.Name.Name] = fieldsCnt + } + } + } + return true + }) + } + return res +} + +type position struct { + fileName string + line int +} + +func main() { + singlechecker.Main(Analyzer) +} diff --git a/linter/structinit/structinit_test.go b/linter/structinit/structinit_test.go new file mode 100644 index 000000000..db3676e18 --- /dev/null +++ b/linter/structinit/structinit_test.go @@ -0,0 +1,36 @@ +package main + +import ( + "os" + "path/filepath" + "testing" + + "golang.org/x/tools/go/analysis/analysistest" +) + +func testData(t *testing.T) string { + t.Helper() + wd, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get wd: %s", err) + } + return filepath.Join(filepath.Dir(wd), "testdata") +} + +func TestLinter(t *testing.T) { + testdata := testData(t) + got := errCount(analysistest.Run(t, testdata, analyzerForTests, "structinit/a")) + if got != 2 { + t.Errorf("analysistest.Run() got %d errors, expected 2", got) + } +} + +func errCount(res []*analysistest.Result) int { + cnt := 0 + for _, r := range res { + if rs, ok := r.Result.(Result); ok { + cnt += len(rs.Errors) + } + } + return cnt +} diff --git a/linter/testdata/src/structinit/a/a.go b/linter/testdata/src/structinit/a/a.go new file mode 100644 index 000000000..40be4dea2 --- /dev/null +++ b/linter/testdata/src/structinit/a/a.go @@ -0,0 +1,28 @@ +package a + +import "fmt" + +// lint:require-exhaustive-initialization +type interestingStruct struct { + x int + b *boringStruct +} + +type boringStruct struct { + x, y int +} + +func init() { + a := &interestingStruct{ + x: 1, // Error: only single field is initialized. + } + fmt.Println(a) + b := interestingStruct{ + b: nil, // Error: only single field is initialized. + } + fmt.Println(b) + c := &boringStruct{ + x: 1, // Not an error since it's not annotated for the linter. + } + fmt.Println(c) +} From 89d96b6ffaf1b2a2b97c27a08885b86a83e2e993 Mon Sep 17 00:00:00 2001 From: Nodar Date: Tue, 29 Aug 2023 20:06:18 +0200 Subject: [PATCH 091/775] Add testcase to structinit linter --- linter/testdata/src/structinit/a/a.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/linter/testdata/src/structinit/a/a.go b/linter/testdata/src/structinit/a/a.go index 40be4dea2..45f605972 100644 --- a/linter/testdata/src/structinit/a/a.go +++ b/linter/testdata/src/structinit/a/a.go @@ -13,16 +13,21 @@ type boringStruct struct { } func init() { - a := &interestingStruct{ - x: 1, // Error: only single field is initialized. + a := &interestingStruct{ // Error: only single field is initialized. + x: 1, } fmt.Println(a) - b := interestingStruct{ - b: nil, // Error: only single field is initialized. + b := interestingStruct{ // Error: only single field is initialized. + b: nil, } fmt.Println(b) - c := &boringStruct{ - x: 1, // Not an error since it's not annotated for the linter. + c := interestingStruct{ // Not an error, all fields are initialized. + x: 1, + b: nil, } fmt.Println(c) + d := &boringStruct{ // Not an error since it's not annotated for the linter. + x: 1, + } + fmt.Println(d) } From de3b6a9305b4cacca9a915e48ea0b8c4b874ef93 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 29 Aug 2023 15:06:24 -0600 Subject: [PATCH 092/775] Fix clippy warning about an Arc not being Send+Sync --- arbitrator/prover/src/utils.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arbitrator/prover/src/utils.rs b/arbitrator/prover/src/utils.rs index 6c11e9af0..efd94dcd7 100644 --- a/arbitrator/prover/src/utils.rs +++ b/arbitrator/prover/src/utils.rs @@ -158,6 +158,10 @@ impl From<&[u8]> for CBytes { } } +// There's no thread safety concerns for CBytes +unsafe impl Send for CBytes {} +unsafe impl Sync for CBytes {} + #[derive(Serialize, Deserialize)] #[serde(remote = "Type")] enum RemoteType { From 9227df788929352184e0bd792898f15beabac0b9 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 29 Aug 2023 15:32:04 -0600 Subject: [PATCH 093/775] Fix formatting --- arbitrator/jit/src/syscall.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbitrator/jit/src/syscall.rs b/arbitrator/jit/src/syscall.rs index 4cd0363b4..c81641a7f 100644 --- a/arbitrator/jit/src/syscall.rs +++ b/arbitrator/jit/src/syscall.rs @@ -306,10 +306,10 @@ pub fn js_value_index(mut env: WasmEnvMut, sp: u32) { pub fn js_value_call(mut env: WasmEnvMut, sp: u32) -> MaybeEscape { let Some(resume) = env.data().exports.resume.clone() else { - return Escape::failure(format!("wasmer failed to bind {}", "resume".red())) + return Escape::failure(format!("wasmer failed to bind {}", "resume".red())); }; let Some(get_stack_pointer) = env.data().exports.get_stack_pointer.clone() else { - return Escape::failure(format!("wasmer failed to bind {}", "getsp".red())) + return Escape::failure(format!("wasmer failed to bind {}", "getsp".red())); }; let sp = GoStack::simple(sp, &env); let data = env.data_mut(); From daac2b8f21e2c7837a65c12d8f8294403dc54b25 Mon Sep 17 00:00:00 2001 From: Nodar Date: Wed, 30 Aug 2023 15:37:33 +0200 Subject: [PATCH 094/775] Add comment about increaseBy parameter --- linter/koanf/handlers.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/linter/koanf/handlers.go b/linter/koanf/handlers.go index 452291e60..00cd10c07 100644 --- a/linter/koanf/handlers.go +++ b/linter/koanf/handlers.go @@ -30,26 +30,28 @@ func handleComposite(pass *analysis.Pass, cl *ast.CompositeLit, cnt map[string]i // handleSelector handles selector expression recursively, that is an expression: // a.B.C.D will update counter for fields: a.B.C.D, a.B.C and a.B. -func handleSelector(pass *analysis.Pass, se *ast.SelectorExpr, inc int, cnt map[string]int) string { +// It updates counters map in place, increasing corresponding identifiers by +// increaseBy amount. +func handleSelector(pass *analysis.Pass, se *ast.SelectorExpr, increaseBy int, cnt map[string]int) string { if e, ok := se.X.(*ast.SelectorExpr); ok { // Full field identifier, including package name. fi := pass.TypesInfo.Types[e].Type.String() + "." + se.Sel.Name - cnt[normalizeID(pass, fi)] += inc - prefix := handleSelector(pass, e, inc, cnt) + cnt[normalizeID(pass, fi)] += increaseBy + prefix := handleSelector(pass, e, increaseBy, cnt) fi = prefix + "." + se.Sel.Name - cnt[normalizeID(pass, fi)] += inc + cnt[normalizeID(pass, fi)] += increaseBy return fi } // Handle selectors on function calls, e.g. `config().Enabled`. if _, ok := se.X.(*ast.CallExpr); ok { fi := pass.TypesInfo.Types[se.X].Type.String() + "." + se.Sel.Name - cnt[normalizeID(pass, fi)] += inc + cnt[normalizeID(pass, fi)] += increaseBy return fi } if ident, ok := se.X.(*ast.Ident); ok { if pass.TypesInfo.Types[ident].Type != nil { fi := pass.TypesInfo.Types[ident].Type.String() + "." + se.Sel.Name - cnt[normalizeID(pass, fi)] += inc + cnt[normalizeID(pass, fi)] += increaseBy return fi } } From ad64d967f68b84b1e8ed29a3d6907bd639b8cb16 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 30 Aug 2023 09:37:29 -0600 Subject: [PATCH 095/775] Make PreimageResolver Send+Sync --- arbitrator/prover/src/machine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index fff9c0f3d..d5a9c52d9 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -651,7 +651,7 @@ pub struct MachineState<'a> { initial_hash: Bytes32, } -pub type PreimageResolver = Arc Option>; +pub type PreimageResolver = Arc Option + Send + Sync>; /// Wraps a preimage resolver to provide an easier API /// and cache the last preimage retrieved. From 283b5d71a1d8eff096e878d8f028cf33356585e9 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 30 Aug 2023 09:53:11 -0600 Subject: [PATCH 096/775] Extend comment explaining why CBytes is Send+Sync --- arbitrator/prover/src/utils.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arbitrator/prover/src/utils.rs b/arbitrator/prover/src/utils.rs index efd94dcd7..e86ea9676 100644 --- a/arbitrator/prover/src/utils.rs +++ b/arbitrator/prover/src/utils.rs @@ -158,7 +158,10 @@ impl From<&[u8]> for CBytes { } } -// There's no thread safety concerns for CBytes +// There's no thread safety concerns for CBytes. +// This type is basically a Box<[u8]> (which is Send + Sync) with libc as an allocator. +// Any data races between threads are prevented by Rust borrowing rules, +// and the data isn't thread-local so there's no concern moving it between threads. unsafe impl Send for CBytes {} unsafe impl Sync for CBytes {} From f6f659e7b2513ab48f0a276340676636350d98f0 Mon Sep 17 00:00:00 2001 From: Nodar Date: Wed, 30 Aug 2023 18:04:20 +0200 Subject: [PATCH 097/775] Implement legacy storage encoding with hot-reload flag to change encoding strategy on the fly --- arbnode/dataposter/data_poster.go | 24 +++-- arbnode/dataposter/leveldb/leveldb.go | 26 ++--- arbnode/dataposter/redis/redisstorage.go | 28 +++--- arbnode/dataposter/slice/slicestorage.go | 22 ++--- arbnode/dataposter/storage/storage.go | 117 +++++++++++++++++++++++ arbnode/dataposter/storage_test.go | 64 ++++++++----- 6 files changed, 202 insertions(+), 79 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index b1db655d7..adfde88f7 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -101,17 +101,23 @@ func NewDataPoster(db ethdb.Database, headerReader *headerreader.HeaderReader, a initConfig.UseNoOpStorage = true log.Info("Disabling data poster storage, as parent chain appears to be an Arbitrum chain without a mempool") } + encF := func() storage.EncoderDecoderInterface { + if config().LegacyStorageEncoding { + return &storage.LegacyEncoderDecoder{} + } + return &storage.EncoderDecoder{} + } var queue QueueStorage switch { case initConfig.UseNoOpStorage: queue = &noop.Storage{} case initConfig.UseLevelDB: - queue = leveldb.New(db) + queue = leveldb.New(db, encF) case redisClient == nil: - queue = slice.NewStorage() + queue = slice.NewStorage(encF) default: var err error - queue, err = redisstorage.NewStorage(redisClient, "data-poster.queue", &initConfig.RedisSigner) + queue, err = redisstorage.NewStorage(redisClient, "data-poster.queue", &initConfig.RedisSigner, encF) if err != nil { return nil, err } @@ -174,7 +180,7 @@ func (p *DataPoster) getNextNonceAndMaybeMeta(ctx context.Context) (uint64, []by } lastQueueItem, err := p.queue.FetchLast(ctx) if err != nil { - return 0, nil, false, err + return 0, nil, false, fmt.Errorf("fetching last element from queue: %w", err) } if lastQueueItem != nil { nextNonce := lastQueueItem.Data.Nonce + 1 @@ -364,7 +370,10 @@ func (p *DataPoster) saveTx(ctx context.Context, prevTx, newTx *storage.QueuedTr if prevTx != nil && prevTx.Data.Nonce != newTx.Data.Nonce { return fmt.Errorf("prevTx nonce %v doesn't match newTx nonce %v", prevTx.Data.Nonce, newTx.Data.Nonce) } - return p.queue.Put(ctx, newTx.Data.Nonce, prevTx, newTx) + if err := p.queue.Put(ctx, newTx.Data.Nonce, prevTx, newTx); err != nil { + return fmt.Errorf("putting new tx in the queue: %w", err) + } + return nil } func (p *DataPoster) sendTx(ctx context.Context, prevTx *storage.QueuedTransaction, newTx *storage.QueuedTransaction) error { @@ -546,7 +555,7 @@ func (p *DataPoster) Start(ctxIn context.Context) { // replacing them by fee. queueContents, err := p.queue.FetchContents(ctx, unconfirmedNonce, maxTxsToRbf) if err != nil { - log.Error("Failed to get tx queue contents", "err", err) + log.Error("Failed to fetch tx queue contents", "err", err) return minWait } for index, tx := range queueContents { @@ -616,6 +625,7 @@ type DataPosterConfig struct { AllocateMempoolBalance bool `koanf:"allocate-mempool-balance" reload:"hot"` UseLevelDB bool `koanf:"use-leveldb"` UseNoOpStorage bool `koanf:"use-noop-storage"` + LegacyStorageEncoding bool `koanf:"legacy-storage-encoding" reload:"hot"` } // ConfigFetcher function type is used instead of directly passing config so @@ -636,6 +646,7 @@ func DataPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Bool(prefix+".allocate-mempool-balance", DefaultDataPosterConfig.AllocateMempoolBalance, "if true, don't put transactions in the mempool that spend a total greater than the batch poster's balance") f.Bool(prefix+".use-leveldb", DefaultDataPosterConfig.UseLevelDB, "uses leveldb when enabled") f.Bool(prefix+".use-noop-storage", DefaultDataPosterConfig.UseNoOpStorage, "uses noop storage, it doesn't store anything") + f.Bool(prefix+".legacy-storage-encoding", DefaultDataPosterConfig.LegacyStorageEncoding, "encodes items in a legacy way (as it was before dropping generics)") signature.SimpleHmacConfigAddOptions(prefix+".redis-signer", f) } @@ -651,6 +662,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ AllocateMempoolBalance: true, UseLevelDB: false, UseNoOpStorage: false, + LegacyStorageEncoding: true, } var DefaultDataPosterConfigForValidator = func() DataPosterConfig { diff --git a/arbnode/dataposter/leveldb/leveldb.go b/arbnode/dataposter/leveldb/leveldb.go index e41a8665a..cfb34b04f 100644 --- a/arbnode/dataposter/leveldb/leveldb.go +++ b/arbnode/dataposter/leveldb/leveldb.go @@ -12,14 +12,14 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb/memorydb" - "github.com/ethereum/go-ethereum/rlp" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/syndtr/goleveldb/leveldb" ) // Storage implements leveldb based storage for batch poster. type Storage struct { - db ethdb.Database + db ethdb.Database + encDec storage.EncoderDecoderF } var ( @@ -31,16 +31,8 @@ var ( countKey = []byte(".count_key") ) -func New(db ethdb.Database) *Storage { - return &Storage{db: db} -} - -func (s *Storage) decodeItem(data []byte) (*storage.QueuedTransaction, error) { - var item storage.QueuedTransaction - if err := rlp.DecodeBytes(data, &item); err != nil { - return nil, fmt.Errorf("decoding item: %w", err) - } - return &item, nil +func New(db ethdb.Database, enc storage.EncoderDecoderF) *Storage { + return &Storage{db: db, encDec: enc} } func idxToKey(idx uint64) []byte { @@ -55,7 +47,7 @@ func (s *Storage) FetchContents(_ context.Context, startingIndex uint64, maxResu if !it.Next() { break } - item, err := s.decodeItem(it.Value()) + item, err := s.encDec().Decode(it.Value()) if err != nil { return nil, err } @@ -84,7 +76,7 @@ func (s *Storage) FetchLast(ctx context.Context) (*storage.QueuedTransaction, er if err != nil { return nil, err } - return s.decodeItem(val) + return s.encDec().Decode(val) } func (s *Storage) Prune(ctx context.Context, until uint64) error { @@ -117,7 +109,7 @@ func (s *Storage) valueAt(_ context.Context, key []byte) ([]byte, error) { val, err := s.db.Get(key) if err != nil { if isErrNotFound(err) { - return rlp.EncodeToBytes((*storage.QueuedTransaction)(nil)) + return s.encDec().Encode((*storage.QueuedTransaction)(nil)) } return nil, err } @@ -130,14 +122,14 @@ func (s *Storage) Put(ctx context.Context, index uint64, prev, new *storage.Queu if err != nil { return err } - prevEnc, err := rlp.EncodeToBytes(prev) + prevEnc, err := s.encDec().Encode(prev) if err != nil { return fmt.Errorf("encoding previous item: %w", err) } if !bytes.Equal(stored, prevEnc) { return fmt.Errorf("replacing different item than expected at index: %v, stored: %v, prevEnc: %v", index, stored, prevEnc) } - newEnc, err := rlp.EncodeToBytes(new) + newEnc, err := s.encDec().Encode(new) if err != nil { return fmt.Errorf("encoding new item: %w", err) } diff --git a/arbnode/dataposter/redis/redisstorage.go b/arbnode/dataposter/redis/redisstorage.go index e6fe666c6..5123cea15 100644 --- a/arbnode/dataposter/redis/redisstorage.go +++ b/arbnode/dataposter/redis/redisstorage.go @@ -9,7 +9,6 @@ import ( "errors" "fmt" - "github.com/ethereum/go-ethereum/rlp" "github.com/go-redis/redis/v8" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/util/signature" @@ -23,14 +22,15 @@ type Storage struct { client redis.UniversalClient signer *signature.SimpleHmac key string + encDec storage.EncoderDecoderF } -func NewStorage(client redis.UniversalClient, key string, signerConf *signature.SimpleHmacConfig) (*Storage, error) { +func NewStorage(client redis.UniversalClient, key string, signerConf *signature.SimpleHmacConfig, enc storage.EncoderDecoderF) (*Storage, error) { signer, err := signature.NewSimpleHmac(signerConf) if err != nil { return nil, err } - return &Storage{client, signer, key}, nil + return &Storage{client, signer, key, enc}, nil } func joinHmacMsg(msg []byte, sig []byte) ([]byte, error) { @@ -65,16 +65,15 @@ func (s *Storage) FetchContents(ctx context.Context, startingIndex uint64, maxRe } var items []*storage.QueuedTransaction for _, itemString := range itemStrings { - var item storage.QueuedTransaction data, err := s.peelVerifySignature([]byte(itemString)) if err != nil { return nil, err } - err = rlp.DecodeBytes(data, &item) + item, err := s.encDec().Decode(data) if err != nil { return nil, err } - items = append(items, &item) + items = append(items, item) } return items, nil } @@ -95,16 +94,15 @@ func (s *Storage) FetchLast(ctx context.Context) (*storage.QueuedTransaction, er } var ret *storage.QueuedTransaction if len(itemStrings) > 0 { - var item storage.QueuedTransaction data, err := s.peelVerifySignature([]byte(itemStrings[0])) if err != nil { return nil, err } - err = rlp.DecodeBytes(data, &item) + item, err := s.encDec().Decode(data) if err != nil { return nil, err } - ret = &item + ret = item } return ret, nil } @@ -144,21 +142,20 @@ func (s *Storage) Put(ctx context.Context, index uint64, prev, new *storage.Queu if err != nil { return fmt.Errorf("failed to validate item already in redis at index%v: %w", index, err) } - prevItemEncoded, err := rlp.EncodeToBytes(prev) + prevItemEncoded, err := s.encDec().Encode(prev) if err != nil { return err } if !bytes.Equal(verifiedItem, prevItemEncoded) { return fmt.Errorf("%w: replacing different item than expected at index %v", storage.ErrStorageRace, index) } - err = pipe.ZRem(ctx, s.key, haveItems[0]).Err() - if err != nil { + if err := pipe.ZRem(ctx, s.key, haveItems[0]).Err(); err != nil { return err } } else { return fmt.Errorf("expected only one return value for Put but got %v", len(haveItems)) } - newItemEncoded, err := rlp.EncodeToBytes(*new) + newItemEncoded, err := s.encDec().Encode(new) if err != nil { return err } @@ -170,11 +167,10 @@ func (s *Storage) Put(ctx context.Context, index uint64, prev, new *storage.Queu if err != nil { return err } - err = pipe.ZAdd(ctx, s.key, &redis.Z{ + if err := pipe.ZAdd(ctx, s.key, &redis.Z{ Score: float64(index), Member: string(signedItem), - }).Err() - if err != nil { + }).Err(); err != nil { return err } _, err = pipe.Exec(ctx) diff --git a/arbnode/dataposter/slice/slicestorage.go b/arbnode/dataposter/slice/slicestorage.go index 6eda5ca9a..04286df41 100644 --- a/arbnode/dataposter/slice/slicestorage.go +++ b/arbnode/dataposter/slice/slicestorage.go @@ -9,25 +9,17 @@ import ( "errors" "fmt" - "github.com/ethereum/go-ethereum/rlp" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" ) type Storage struct { firstNonce uint64 queue [][]byte + encDec func() storage.EncoderDecoderInterface } -func NewStorage() *Storage { - return &Storage{} -} - -func (s *Storage) decodeItem(data []byte) (*storage.QueuedTransaction, error) { - var item storage.QueuedTransaction - if err := rlp.DecodeBytes(data, &item); err != nil { - return nil, fmt.Errorf("decoding item: %w", err) - } - return &item, nil +func NewStorage(encDec func() storage.EncoderDecoderInterface) *Storage { + return &Storage{encDec: encDec} } func (s *Storage) FetchContents(_ context.Context, startingIndex uint64, maxResults uint64) ([]*storage.QueuedTransaction, error) { @@ -43,7 +35,7 @@ func (s *Storage) FetchContents(_ context.Context, startingIndex uint64, maxResu } var res []*storage.QueuedTransaction for _, r := range txs { - item, err := s.decodeItem(r) + item, err := s.encDec().Decode(r) if err != nil { return nil, err } @@ -56,7 +48,7 @@ func (s *Storage) FetchLast(context.Context) (*storage.QueuedTransaction, error) if len(s.queue) == 0 { return nil, nil } - return s.decodeItem(s.queue[len(s.queue)-1]) + return s.encDec().Decode(s.queue[len(s.queue)-1]) } func (s *Storage) Prune(_ context.Context, until uint64) error { @@ -73,7 +65,7 @@ func (s *Storage) Put(_ context.Context, index uint64, prev, new *storage.Queued if new == nil { return fmt.Errorf("tried to insert nil item at index %v", index) } - newEnc, err := rlp.EncodeToBytes(new) + newEnc, err := s.encDec().Encode(new) if err != nil { return fmt.Errorf("encoding new item: %w", err) } @@ -93,7 +85,7 @@ func (s *Storage) Put(_ context.Context, index uint64, prev, new *storage.Queued if queueIdx > len(s.queue) { return fmt.Errorf("attempted to set out-of-bounds index %v in queue starting at %v of length %v", index, s.firstNonce, len(s.queue)) } - prevEnc, err := rlp.EncodeToBytes(prev) + prevEnc, err := s.encDec().Encode(prev) if err != nil { return fmt.Errorf("encoding previous item: %w", err) } diff --git a/arbnode/dataposter/storage/storage.go b/arbnode/dataposter/storage/storage.go index 174ab131a..57085c4fb 100644 --- a/arbnode/dataposter/storage/storage.go +++ b/arbnode/dataposter/storage/storage.go @@ -2,9 +2,12 @@ package storage import ( "errors" + "fmt" "time" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" + "github.com/offchainlabs/nitro/arbutil" ) var ( @@ -24,3 +27,117 @@ type QueuedTransaction struct { Created time.Time // may be earlier than the tx was given to the tx poster NextReplacement time.Time } + +// LegacyQueuedTransaction is used for backwards compatibility. +// Before https://github.com/OffchainLabs/nitro/pull/1773: the queuedTransaction +// looked like this and was rlp encoded directly. After the pr, we are store +// rlp encoding of Meta into queuedTransaction and rlp encoding it once more +// to store it. +type LegacyQueuedTransaction struct { + FullTx *types.Transaction `rlp:"nil"` + Data types.DynamicFeeTx + Meta BatchPosterPosition + Sent bool + Created time.Time // may be earlier than the tx was given to the tx poster + NextReplacement time.Time +} + +// This is also for legacy reason. Since Batchposter is in arbnode package, +// we can't refer to BatchPosterPosition type there even if we export it (that +// would create cyclic dependency). +// Ideally we'll factor out Batch Poster from arbnode into separate package +// and BatchPosterPosition into another separate package as well. +// For the sake of minimal refactoring, that struct is duplicated here. +type BatchPosterPosition struct { + MessageCount arbutil.MessageIndex + DelayedMessageCount uint64 + NextSeqNum uint64 +} + +func DecodeLegacyQueuedTransaction(data []byte) (*LegacyQueuedTransaction, error) { + var val LegacyQueuedTransaction + if err := rlp.DecodeBytes(data, &val); err != nil { + return nil, fmt.Errorf("decoding legacy queued transaction: %w", err) + } + return &val, nil +} + +func LegacyToQueuedTransaction(legacyQT *LegacyQueuedTransaction) (*QueuedTransaction, error) { + meta, err := rlp.EncodeToBytes(legacyQT.Meta) + if err != nil { + return nil, fmt.Errorf("converting legacy to queued transaction: %w", err) + } + return &QueuedTransaction{ + FullTx: legacyQT.FullTx, + Data: legacyQT.Data, + Meta: meta, + Sent: legacyQT.Sent, + Created: legacyQT.Created, + NextReplacement: legacyQT.NextReplacement, + }, nil +} + +func QueuedTransactionToLegacy(qt *QueuedTransaction) (*LegacyQueuedTransaction, error) { + if qt == nil { + return nil, nil + } + var meta BatchPosterPosition + if qt.Meta != nil { + if err := rlp.DecodeBytes(qt.Meta, &meta); err != nil { + return nil, fmt.Errorf("converting queued transaction to legacy: %w", err) + } + } + return &LegacyQueuedTransaction{ + FullTx: qt.FullTx, + Data: qt.Data, + Meta: meta, + Sent: qt.Sent, + Created: qt.Created, + NextReplacement: qt.NextReplacement, + }, nil +} + +type EncoderDecoder struct{} + +func (e *EncoderDecoder) Encode(qt *QueuedTransaction) ([]byte, error) { + return rlp.EncodeToBytes(qt) +} + +func (e *EncoderDecoder) Decode(data []byte) (*QueuedTransaction, error) { + var item QueuedTransaction + if err := rlp.DecodeBytes(data, &item); err != nil { + return nil, fmt.Errorf("decoding item: %w", err) + } + return &item, nil +} + +type LegacyEncoderDecoder struct{} + +func (e *LegacyEncoderDecoder) Encode(qt *QueuedTransaction) ([]byte, error) { + legacyQt, err := QueuedTransactionToLegacy(qt) + if err != nil { + return nil, fmt.Errorf("encoding legacy item: %w", err) + } + return rlp.EncodeToBytes(legacyQt) +} + +func (le *LegacyEncoderDecoder) Decode(data []byte) (*QueuedTransaction, error) { + val, err := DecodeLegacyQueuedTransaction(data) + if err != nil { + return nil, fmt.Errorf("decoding legacy item: %w", err) + } + return LegacyToQueuedTransaction(val) +} + +// Typically interfaces belong to where they are being used, not at implementing +// site, but this is used in all storages (besides no-op) and all of them +// require all the functions for this interface. +type EncoderDecoderInterface interface { + Encode(*QueuedTransaction) ([]byte, error) + Decode([]byte) (*QueuedTransaction, error) +} + +// EncoderDecoderF is a function type that returns encoder/decoder interface. +// This is needed to implement hot-reloading flag to switch encoding/decoding +// strategy on the fly. +type EncoderDecoderF func() EncoderDecoderInterface diff --git a/arbnode/dataposter/storage_test.go b/arbnode/dataposter/storage_test.go index 2424ac084..eac05502b 100644 --- a/arbnode/dataposter/storage_test.go +++ b/arbnode/dataposter/storage_test.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/offchainlabs/nitro/arbnode/dataposter/leveldb" @@ -27,36 +28,41 @@ var ignoreData = cmp.Options{ cmpopts.IgnoreFields(types.Transaction{}, "hash", "size", "from"), } -func newLevelDBStorage(t *testing.T) *leveldb.Storage { +func newLevelDBStorage(t *testing.T, encF storage.EncoderDecoderF) *leveldb.Storage { t.Helper() db, err := rawdb.NewLevelDBDatabase(path.Join(t.TempDir(), "level.db"), 0, 0, "default", false) if err != nil { t.Fatalf("NewLevelDBDatabase() unexpected error: %v", err) } - return leveldb.New(db) + return leveldb.New(db, encF) } -func newSliceStorage() *slice.Storage { - return slice.NewStorage() +func newSliceStorage(encF storage.EncoderDecoderF) *slice.Storage { + return slice.NewStorage(encF) } -func newRedisStorage(ctx context.Context, t *testing.T) *redis.Storage { +func newRedisStorage(ctx context.Context, t *testing.T, encF storage.EncoderDecoderF) *redis.Storage { t.Helper() redisUrl := redisutil.CreateTestRedis(ctx, t) client, err := redisutil.RedisClientFromURL(redisUrl) if err != nil { t.Fatalf("RedisClientFromURL(%q) unexpected error: %v", redisUrl, err) } - s, err := redis.NewStorage(client, "", &signature.TestSimpleHmacConfig) + s, err := redis.NewStorage(client, "", &signature.TestSimpleHmacConfig, encF) if err != nil { t.Fatalf("redis.NewStorage() unexpected error: %v", err) } return s } -func valueOf(i int) *storage.QueuedTransaction { +func valueOf(t *testing.T, i int) *storage.QueuedTransaction { + t.Helper() + meta, err := rlp.EncodeToBytes(storage.BatchPosterPosition{DelayedMessageCount: uint64(i)}) + if err != nil { + t.Fatalf("Encoding batch poster position, error: %v", err) + } return &storage.QueuedTransaction{ - Meta: []byte{byte(i)}, + Meta: meta, Data: types.DynamicFeeTx{ ChainID: big.NewInt(int64(i)), Nonce: uint64(i), @@ -73,10 +79,10 @@ func valueOf(i int) *storage.QueuedTransaction { } } -func values(from, to int) []*storage.QueuedTransaction { +func values(t *testing.T, from, to int) []*storage.QueuedTransaction { var res []*storage.QueuedTransaction for i := from; i <= to; i++ { - res = append(res, valueOf(i)) + res = append(res, valueOf(t, i)) } return res } @@ -85,7 +91,7 @@ func values(from, to int) []*storage.QueuedTransaction { func initStorage(ctx context.Context, t *testing.T, s QueueStorage) QueueStorage { t.Helper() for i := 0; i < 20; i++ { - if err := s.Put(ctx, uint64(i), nil, valueOf(i)); err != nil { + if err := s.Put(ctx, uint64(i), nil, valueOf(t, i)); err != nil { t.Fatalf("Error putting a key/value: %v", err) } } @@ -95,10 +101,18 @@ func initStorage(ctx context.Context, t *testing.T, s QueueStorage) QueueStorage // Returns a map of all empty storages. func storages(t *testing.T) map[string]QueueStorage { t.Helper() + f := func(enc storage.EncoderDecoderInterface) storage.EncoderDecoderF { + return func() storage.EncoderDecoderInterface { + return enc + } + } return map[string]QueueStorage{ - "levelDB": newLevelDBStorage(t), - "slice": newSliceStorage(), - "redis": newRedisStorage(context.Background(), t), + "levelDBLegacy": newLevelDBStorage(t, f(&storage.LegacyEncoderDecoder{})), + "sliceLegacy": newSliceStorage(f(&storage.LegacyEncoderDecoder{})), + "redisLegacy": newRedisStorage(context.Background(), t, f(&storage.LegacyEncoderDecoder{})), + "levelDB": newLevelDBStorage(t, f(&storage.EncoderDecoder{})), + "slice": newSliceStorage(f(&storage.EncoderDecoder{})), + "redis": newRedisStorage(context.Background(), t, f(&storage.EncoderDecoder{})), } } @@ -125,13 +139,13 @@ func TestFetchContents(t *testing.T) { desc: "sequence with single digits", startIdx: 5, maxResults: 3, - want: values(5, 7), + want: values(t, 5, 7), }, { desc: "corner case of single element", startIdx: 0, maxResults: 1, - want: values(0, 0), + want: values(t, 0, 0), }, { desc: "no elements", @@ -143,13 +157,13 @@ func TestFetchContents(t *testing.T) { desc: "sequence with variable number of digits", startIdx: 9, maxResults: 3, - want: values(9, 11), + want: values(t, 9, 11), }, { desc: "max results goes over the last element", startIdx: 13, maxResults: 10, - want: values(13, 19), + want: values(t, 13, 19), }, } { t.Run(name+"_"+tc.desc, func(t *testing.T) { @@ -171,7 +185,7 @@ func TestLast(t *testing.T) { t.Run(name, func(t *testing.T) { ctx := context.Background() for i := 0; i < cnt; i++ { - val := valueOf(i) + val := valueOf(t, i) if err := s.Put(ctx, uint64(i), nil, val); err != nil { t.Fatalf("Error putting a key/value: %v", err) } @@ -185,12 +199,12 @@ func TestLast(t *testing.T) { } }) - last := valueOf(cnt - 1) + last := valueOf(t, cnt-1) t.Run(name+"_update_entries", func(t *testing.T) { ctx := context.Background() for i := 0; i < cnt-1; i++ { - prev := valueOf(i) - newVal := valueOf(cnt + i) + prev := valueOf(t, i) + newVal := valueOf(t, cnt+i) if err := s.Put(ctx, uint64(i), prev, newVal); err != nil { t.Fatalf("Error putting a key/value: %v, prev: %v, new: %v", err, prev, newVal) } @@ -227,17 +241,17 @@ func TestPrune(t *testing.T) { { desc: "prune all but one", pruneFrom: 19, - want: values(19, 19), + want: values(t, 19, 19), }, { desc: "pruning first element", pruneFrom: 1, - want: values(1, 19), + want: values(t, 1, 19), }, { desc: "pruning first 11 elements", pruneFrom: 11, - want: values(11, 19), + want: values(t, 11, 19), }, { desc: "pruning from higher than biggest index", From bb08e9d3fb5a5424f7e5885e411733978a2df736 Mon Sep 17 00:00:00 2001 From: Nodar Date: Wed, 30 Aug 2023 18:51:23 +0200 Subject: [PATCH 098/775] Use new encoding for slicestorage, attempt both decodings no matter what encoding is enabled --- arbnode/dataposter/data_poster.go | 2 +- arbnode/dataposter/storage/storage.go | 29 ++++++++++++++++++--------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index adfde88f7..a289a1762 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -114,7 +114,7 @@ func NewDataPoster(db ethdb.Database, headerReader *headerreader.HeaderReader, a case initConfig.UseLevelDB: queue = leveldb.New(db, encF) case redisClient == nil: - queue = slice.NewStorage(encF) + queue = slice.NewStorage(func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) default: var err error queue, err = redisstorage.NewStorage(redisClient, "data-poster.queue", &initConfig.RedisSigner, encF) diff --git a/arbnode/dataposter/storage/storage.go b/arbnode/dataposter/storage/storage.go index 57085c4fb..a132f375e 100644 --- a/arbnode/dataposter/storage/storage.go +++ b/arbnode/dataposter/storage/storage.go @@ -6,6 +6,7 @@ import ( "time" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/offchainlabs/nitro/arbutil" ) @@ -97,6 +98,22 @@ func QueuedTransactionToLegacy(qt *QueuedTransaction) (*LegacyQueuedTransaction, }, nil } +// Decode tries to decode QueuedTransaction, if that fails it tries to decode +// into legacy queued transaction and converts to queued +func decode(data []byte) (*QueuedTransaction, error) { + var item QueuedTransaction + if err := rlp.DecodeBytes(data, &item); err != nil { + log.Warn("Failed to decode QueuedTransaction, attempting to decide legacy queued transaction", "error", err) + val, err := DecodeLegacyQueuedTransaction(data) + if err != nil { + return nil, fmt.Errorf("decoding legacy item: %w", err) + } + return LegacyToQueuedTransaction(val) + } + return &item, nil + +} + type EncoderDecoder struct{} func (e *EncoderDecoder) Encode(qt *QueuedTransaction) ([]byte, error) { @@ -104,11 +121,7 @@ func (e *EncoderDecoder) Encode(qt *QueuedTransaction) ([]byte, error) { } func (e *EncoderDecoder) Decode(data []byte) (*QueuedTransaction, error) { - var item QueuedTransaction - if err := rlp.DecodeBytes(data, &item); err != nil { - return nil, fmt.Errorf("decoding item: %w", err) - } - return &item, nil + return decode(data) } type LegacyEncoderDecoder struct{} @@ -122,11 +135,7 @@ func (e *LegacyEncoderDecoder) Encode(qt *QueuedTransaction) ([]byte, error) { } func (le *LegacyEncoderDecoder) Decode(data []byte) (*QueuedTransaction, error) { - val, err := DecodeLegacyQueuedTransaction(data) - if err != nil { - return nil, fmt.Errorf("decoding legacy item: %w", err) - } - return LegacyToQueuedTransaction(val) + return decode(data) } // Typically interfaces belong to where they are being used, not at implementing From 2e6d59ac0c3bfa6679011c974d37fdd16fad2992 Mon Sep 17 00:00:00 2001 From: Nodar Date: Wed, 30 Aug 2023 18:52:20 +0200 Subject: [PATCH 099/775] drop empty line --- arbnode/dataposter/storage/storage.go | 1 - 1 file changed, 1 deletion(-) diff --git a/arbnode/dataposter/storage/storage.go b/arbnode/dataposter/storage/storage.go index a132f375e..ed848b9b7 100644 --- a/arbnode/dataposter/storage/storage.go +++ b/arbnode/dataposter/storage/storage.go @@ -111,7 +111,6 @@ func decode(data []byte) (*QueuedTransaction, error) { return LegacyToQueuedTransaction(val) } return &item, nil - } type EncoderDecoder struct{} From 06930b67bf24630f002abbe523c2ae9e3fd71362 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 30 Aug 2023 12:56:15 -0600 Subject: [PATCH 100/775] Fix pollForReverts channel reading --- arbnode/batch_poster.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 429701be7..7efa2b3f7 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -309,8 +309,8 @@ func (b *BatchPoster) pollForReverts(ctx context.Context) { // - polling is through context, or // - we see a transaction in the block from dataposter that was reverted. select { - case h, closed := <-headerCh: - if closed { + case h, ok := <-headerCh: + if !ok { log.Info("L1 headers channel has been closed") return } From 5ce0f8164c3b05c2056cc22083cc1e2ebdc6d33d Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 30 Aug 2023 14:26:51 -0600 Subject: [PATCH 101/775] Disable wait-for-l1-finality on L3 data posters --- arbnode/dataposter/data_poster.go | 39 +++++++++++++++++-------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index b1db655d7..f20d7dd59 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -162,11 +162,14 @@ func (p *DataPoster) canPostWithNonce(ctx context.Context, nextNonce uint64) err return nil } +func (p *DataPoster) waitForL1Finality() bool { + return p.config().WaitForL1Finality && !p.headerReader.IsParentChainArbitrum() +} + // Requires the caller hold the mutex. // Returns the next nonce, its metadata if stored, a bool indicating if the metadata is present, and an error. // Unlike GetNextNonceAndMeta, this does not call the metadataRetriever if the metadata is not stored in the queue. func (p *DataPoster) getNextNonceAndMaybeMeta(ctx context.Context) (uint64, []byte, bool, error) { - config := p.config() // Ensure latest finalized block state is available. blockNum, err := p.client.BlockNumber(ctx) if err != nil { @@ -185,7 +188,7 @@ func (p *DataPoster) getNextNonceAndMaybeMeta(ctx context.Context) (uint64, []by } if err := p.updateNonce(ctx); err != nil { - if !p.queue.IsPersistent() && config.WaitForL1Finality { + if !p.queue.IsPersistent() && p.waitForL1Finality() { return 0, nil, false, fmt.Errorf("error getting latest finalized nonce (and queue is not persistent): %w", err) } // Fall back to using a recent block to get the nonce. This is safe because there's nothing in the queue. @@ -433,7 +436,7 @@ func (p *DataPoster) replaceTx(ctx context.Context, prevTx *storage.QueuedTransa // The mutex must be held by the caller. func (p *DataPoster) updateNonce(ctx context.Context) error { var blockNumQuery *big.Int - if p.config().WaitForL1Finality { + if p.waitForL1Finality() { blockNumQuery = big.NewInt(int64(rpc.FinalizedBlockNumber)) } header, err := p.client.HeaderByNumber(ctx, blockNumQuery) @@ -602,20 +605,22 @@ type QueueStorage interface { } type DataPosterConfig struct { - RedisSigner signature.SimpleHmacConfig `koanf:"redis-signer"` - ReplacementTimes string `koanf:"replacement-times"` - WaitForL1Finality bool `koanf:"wait-for-l1-finality" reload:"hot"` - MaxMempoolTransactions uint64 `koanf:"max-mempool-transactions" reload:"hot"` - MaxQueuedTransactions int `koanf:"max-queued-transactions" reload:"hot"` - TargetPriceGwei float64 `koanf:"target-price-gwei" reload:"hot"` - UrgencyGwei float64 `koanf:"urgency-gwei" reload:"hot"` - MinFeeCapGwei float64 `koanf:"min-fee-cap-gwei" reload:"hot"` - MinTipCapGwei float64 `koanf:"min-tip-cap-gwei" reload:"hot"` - MaxTipCapGwei float64 `koanf:"max-tip-cap-gwei" reload:"hot"` - NonceRbfSoftConfs uint64 `koanf:"nonce-rbf-soft-confs" reload:"hot"` - AllocateMempoolBalance bool `koanf:"allocate-mempool-balance" reload:"hot"` - UseLevelDB bool `koanf:"use-leveldb"` - UseNoOpStorage bool `koanf:"use-noop-storage"` + RedisSigner signature.SimpleHmacConfig `koanf:"redis-signer"` + ReplacementTimes string `koanf:"replacement-times"` + // This is forcibly disabled if the parent chain is an Arbitrum chain, + // so you should probably use DataPoster's waitForL1Finality method instead of reading this field directly. + WaitForL1Finality bool `koanf:"wait-for-l1-finality" reload:"hot"` + MaxMempoolTransactions uint64 `koanf:"max-mempool-transactions" reload:"hot"` + MaxQueuedTransactions int `koanf:"max-queued-transactions" reload:"hot"` + TargetPriceGwei float64 `koanf:"target-price-gwei" reload:"hot"` + UrgencyGwei float64 `koanf:"urgency-gwei" reload:"hot"` + MinFeeCapGwei float64 `koanf:"min-fee-cap-gwei" reload:"hot"` + MinTipCapGwei float64 `koanf:"min-tip-cap-gwei" reload:"hot"` + MaxTipCapGwei float64 `koanf:"max-tip-cap-gwei" reload:"hot"` + NonceRbfSoftConfs uint64 `koanf:"nonce-rbf-soft-confs" reload:"hot"` + AllocateMempoolBalance bool `koanf:"allocate-mempool-balance" reload:"hot"` + UseLevelDB bool `koanf:"use-leveldb"` + UseNoOpStorage bool `koanf:"use-noop-storage"` } // ConfigFetcher function type is used instead of directly passing config so From 370ac231089a56649372e7bbe21ce3c26cefda80 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 30 Aug 2023 20:43:12 -0600 Subject: [PATCH 102/775] Fix off by 1 in validator logging --- staker/block_validator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staker/block_validator.go b/staker/block_validator.go index f04b85204..94bc2a080 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -597,7 +597,7 @@ func (v *BlockValidator) iterativeValidationPrint(ctx context.Context) time.Dura var batchMsgs arbutil.MessageIndex var printedCount int64 if validated.GlobalState.Batch > 0 { - batchMsgs, err = v.inboxTracker.GetBatchMessageCount(validated.GlobalState.Batch) + batchMsgs, err = v.inboxTracker.GetBatchMessageCount(validated.GlobalState.Batch - 1) } if err != nil { printedCount = -1 From a7e26b2c038471bcd11831fbcc517238114efbb9 Mon Sep 17 00:00:00 2001 From: Nodar Date: Thu, 31 Aug 2023 15:30:04 +0200 Subject: [PATCH 103/775] Drop normalize method in koanf.go, ignore case when comparing tag and a field --- linter/koanf/koanf.go | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/linter/koanf/koanf.go b/linter/koanf/koanf.go index bc94a9c20..2127fb23b 100644 --- a/linter/koanf/koanf.go +++ b/linter/koanf/koanf.go @@ -6,7 +6,6 @@ import ( "go/token" "reflect" "strings" - "unicode" "github.com/fatih/structtag" "golang.org/x/tools/go/analysis" @@ -84,7 +83,7 @@ func checkStruct(pass *analysis.Pass, s *ast.StructType) Result { if err != nil { continue } - tagName := normalize(tag.Name) + tagName := strings.ReplaceAll(tag.Name, "-", "") fieldName := f.Names[0].Name if !strings.EqualFold(tagName, fieldName) { res.Errors = append(res.Errors, koanfError{ @@ -96,25 +95,6 @@ func checkStruct(pass *analysis.Pass, s *ast.StructType) Result { return res } -func normalize(s string) string { - ans := s[:1] - for i := 1; i < len(s); i++ { - c := rune(s[i]) - if !isAlphanumeric(c) { - continue - } - if !isAlphanumeric(rune(s[i-1])) && unicode.IsLower(c) { - c = unicode.ToUpper(c) - } - ans += string(c) - } - return ans -} - -func isAlphanumeric(c rune) bool { - return unicode.IsLetter(c) || unicode.IsDigit(c) -} - func main() { singlechecker.Main(Analyzer) } From 4d2118660a75fb1dcf04491e07049a2041d3fd83 Mon Sep 17 00:00:00 2001 From: Nodar Date: Thu, 31 Aug 2023 15:38:54 +0200 Subject: [PATCH 104/775] drop tag normalization in koanf.go --- linter/koanf/handlers.go | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/linter/koanf/handlers.go b/linter/koanf/handlers.go index 2381a230e..582600401 100644 --- a/linter/koanf/handlers.go +++ b/linter/koanf/handlers.go @@ -5,7 +5,6 @@ import ( "go/ast" "go/token" "strings" - "unicode" "github.com/fatih/structtag" "golang.org/x/tools/go/analysis" @@ -195,7 +194,7 @@ func tagFromField(f *ast.Field) string { if err != nil { return "" } - return strings.ReplaceAll(tag.Name, "-", "") + return normalizeTag(tag.Name) } // checkStruct returns violations where koanf tag name doesn't match field names. @@ -219,22 +218,7 @@ func checkStruct(pass *analysis.Pass, s *ast.StructType) Result { } func normalizeTag(s string) string { - ans := s[:1] - for i := 1; i < len(s); i++ { - c := rune(s[i]) - if !isAlphanumeric(c) { - continue - } - if !isAlphanumeric(rune(s[i-1])) && unicode.IsLower(c) { - c = unicode.ToUpper(c) - } - ans += string(c) - } - return ans -} - -func isAlphanumeric(c rune) bool { - return unicode.IsLetter(c) || unicode.IsDigit(c) + return strings.ReplaceAll(s, "-", "") } func normalizeID(pass *analysis.Pass, id string) string { From 8cb2606040a993d7fd1f6cf08e5af842ff1b2d1d Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 31 Aug 2023 10:49:42 -0500 Subject: [PATCH 105/775] add new type Uint64OrHex --- go-ethereum | 2 +- system_tests/conditionaltx_test.go | 29 ++++++++++++++--------------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/go-ethereum b/go-ethereum index c905292f8..f8363dc42 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit c905292f8af601f7fca261e65a7d4bc144261e29 +Subproject commit f8363dc42d6cf8dbd76aed2550207a90919e88ee diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index c65103694..b758ba180 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -16,7 +16,6 @@ import ( "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/arbitrum_types" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rpc" @@ -103,23 +102,23 @@ func getOptions(address common.Address, rootHash common.Hash, slotValueMap map[c } func getFulfillableBlockTimeLimits(t *testing.T, blockNumber uint64, timestamp uint64) []*arbitrum_types.ConditionalOptions { - future := hexutil.Uint64(timestamp + 30) - past := hexutil.Uint64(timestamp - 1) - futureBlockNumber := hexutil.Uint64(blockNumber + 1000) - currentBlockNumber := hexutil.Uint64(blockNumber) + future := common.Uint64OrHex(timestamp + 30) + past := common.Uint64OrHex(timestamp - 1) + futureBlockNumber := common.Uint64OrHex(blockNumber + 1000) + currentBlockNumber := common.Uint64OrHex(blockNumber) return getBlockTimeLimits(t, currentBlockNumber, futureBlockNumber, past, future) } func getUnfulfillableBlockTimeLimits(t *testing.T, blockNumber uint64, timestamp uint64) []*arbitrum_types.ConditionalOptions { - future := hexutil.Uint64(timestamp + 30) - past := hexutil.Uint64(timestamp - 1) - futureBlockNumber := hexutil.Uint64(blockNumber + 1000) - previousBlockNumber := hexutil.Uint64(blockNumber - 1) + future := common.Uint64OrHex(timestamp + 30) + past := common.Uint64OrHex(timestamp - 1) + futureBlockNumber := common.Uint64OrHex(blockNumber + 1000) + previousBlockNumber := common.Uint64OrHex(blockNumber - 1) // skip first empty options return getBlockTimeLimits(t, futureBlockNumber, previousBlockNumber, future, past)[1:] } -func getBlockTimeLimits(t *testing.T, blockMin, blockMax hexutil.Uint64, timeMin, timeMax hexutil.Uint64) []*arbitrum_types.ConditionalOptions { +func getBlockTimeLimits(t *testing.T, blockMin, blockMax common.Uint64OrHex, timeMin, timeMax common.Uint64OrHex) []*arbitrum_types.ConditionalOptions { basic := []*arbitrum_types.ConditionalOptions{ {}, {TimestampMin: &timeMin}, @@ -157,9 +156,9 @@ func optionsProduct(optionsA, optionsB []*arbitrum_types.ConditionalOptions) []* c.KnownAccounts[k] = v } limitTriples := []struct { - a *hexutil.Uint64 - b *hexutil.Uint64 - c **hexutil.Uint64 + a *common.Uint64OrHex + b *common.Uint64OrHex + c **common.Uint64OrHex }{ {a.BlockNumberMin, b.BlockNumberMin, &c.BlockNumberMin}, {a.BlockNumberMax, b.BlockNumberMax, &c.BlockNumberMax}, @@ -168,10 +167,10 @@ func optionsProduct(optionsA, optionsB []*arbitrum_types.ConditionalOptions) []* } for _, tripple := range limitTriples { if tripple.b != nil { - value := hexutil.Uint64(*tripple.b) + value := common.Uint64OrHex(*tripple.b) *tripple.c = &value } else if tripple.a != nil { - value := hexutil.Uint64(*tripple.a) + value := common.Uint64OrHex(*tripple.a) *tripple.c = &value } else { *tripple.c = nil From 1f6ddc4f16497f80a203fdfb8f7c4cca04bfba93 Mon Sep 17 00:00:00 2001 From: Nodar Date: Thu, 31 Aug 2023 17:55:40 +0200 Subject: [PATCH 106/775] Change warning to debug when decoding queued transaction fails, add another debug line when it succeeds --- arbnode/dataposter/storage/storage.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arbnode/dataposter/storage/storage.go b/arbnode/dataposter/storage/storage.go index ed848b9b7..734e2770e 100644 --- a/arbnode/dataposter/storage/storage.go +++ b/arbnode/dataposter/storage/storage.go @@ -103,11 +103,12 @@ func QueuedTransactionToLegacy(qt *QueuedTransaction) (*LegacyQueuedTransaction, func decode(data []byte) (*QueuedTransaction, error) { var item QueuedTransaction if err := rlp.DecodeBytes(data, &item); err != nil { - log.Warn("Failed to decode QueuedTransaction, attempting to decide legacy queued transaction", "error", err) + log.Debug("Failed to decode QueuedTransaction, attempting to decide legacy queued transaction", "error", err) val, err := DecodeLegacyQueuedTransaction(data) if err != nil { return nil, fmt.Errorf("decoding legacy item: %w", err) } + log.Debug("Succeeded decoding QueuedTransaction with legacy encoder") return LegacyToQueuedTransaction(val) } return &item, nil From 8f3f8162b88f22e3ef56e3ebbc6ba627b10b8ecb Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 31 Aug 2023 12:59:35 -0500 Subject: [PATCH 107/775] reuse type math.HexOrDecimal64 --- go-ethereum | 2 +- system_tests/conditionaltx_test.go | 29 +++++++++++++++-------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/go-ethereum b/go-ethereum index f8363dc42..b4bd0da11 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit f8363dc42d6cf8dbd76aed2550207a90919e88ee +Subproject commit b4bd0da1142fe6bb81cac7e0794ebb4746b9885a diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index b758ba180..14aa00031 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/arbitrum_types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rpc" @@ -102,23 +103,23 @@ func getOptions(address common.Address, rootHash common.Hash, slotValueMap map[c } func getFulfillableBlockTimeLimits(t *testing.T, blockNumber uint64, timestamp uint64) []*arbitrum_types.ConditionalOptions { - future := common.Uint64OrHex(timestamp + 30) - past := common.Uint64OrHex(timestamp - 1) - futureBlockNumber := common.Uint64OrHex(blockNumber + 1000) - currentBlockNumber := common.Uint64OrHex(blockNumber) + future := math.HexOrDecimal64(timestamp + 30) + past := math.HexOrDecimal64(timestamp - 1) + futureBlockNumber := math.HexOrDecimal64(blockNumber + 1000) + currentBlockNumber := math.HexOrDecimal64(blockNumber) return getBlockTimeLimits(t, currentBlockNumber, futureBlockNumber, past, future) } func getUnfulfillableBlockTimeLimits(t *testing.T, blockNumber uint64, timestamp uint64) []*arbitrum_types.ConditionalOptions { - future := common.Uint64OrHex(timestamp + 30) - past := common.Uint64OrHex(timestamp - 1) - futureBlockNumber := common.Uint64OrHex(blockNumber + 1000) - previousBlockNumber := common.Uint64OrHex(blockNumber - 1) + future := math.HexOrDecimal64(timestamp + 30) + past := math.HexOrDecimal64(timestamp - 1) + futureBlockNumber := math.HexOrDecimal64(blockNumber + 1000) + previousBlockNumber := math.HexOrDecimal64(blockNumber - 1) // skip first empty options return getBlockTimeLimits(t, futureBlockNumber, previousBlockNumber, future, past)[1:] } -func getBlockTimeLimits(t *testing.T, blockMin, blockMax common.Uint64OrHex, timeMin, timeMax common.Uint64OrHex) []*arbitrum_types.ConditionalOptions { +func getBlockTimeLimits(t *testing.T, blockMin, blockMax math.HexOrDecimal64, timeMin, timeMax math.HexOrDecimal64) []*arbitrum_types.ConditionalOptions { basic := []*arbitrum_types.ConditionalOptions{ {}, {TimestampMin: &timeMin}, @@ -156,9 +157,9 @@ func optionsProduct(optionsA, optionsB []*arbitrum_types.ConditionalOptions) []* c.KnownAccounts[k] = v } limitTriples := []struct { - a *common.Uint64OrHex - b *common.Uint64OrHex - c **common.Uint64OrHex + a *math.HexOrDecimal64 + b *math.HexOrDecimal64 + c **math.HexOrDecimal64 }{ {a.BlockNumberMin, b.BlockNumberMin, &c.BlockNumberMin}, {a.BlockNumberMax, b.BlockNumberMax, &c.BlockNumberMax}, @@ -167,10 +168,10 @@ func optionsProduct(optionsA, optionsB []*arbitrum_types.ConditionalOptions) []* } for _, tripple := range limitTriples { if tripple.b != nil { - value := common.Uint64OrHex(*tripple.b) + value := math.HexOrDecimal64(*tripple.b) *tripple.c = &value } else if tripple.a != nil { - value := common.Uint64OrHex(*tripple.a) + value := math.HexOrDecimal64(*tripple.a) *tripple.c = &value } else { *tripple.c = nil From d23602ffc8215367d7705c0e4867cb357949ba84 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 31 Aug 2023 19:42:15 -0600 Subject: [PATCH 108/775] Fix batch poster fixAccErr not resetting when the error stops --- arbnode/batch_poster.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 429701be7..53cd5d559 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -970,10 +970,14 @@ func (b *BatchPoster) Start(ctxIn context.Context) { return b.config().PollInterval } posted, err := b.maybePostSequencerBatch(ctx) + ephemeralError := errors.Is(err, AccumulatorNotFoundErr) || errors.Is(err, storage.ErrStorageRace) + if !ephemeralError { + b.firstAccErr = time.Time{} + } if err != nil { b.building = nil logLevel := log.Error - if errors.Is(err, AccumulatorNotFoundErr) || errors.Is(err, storage.ErrStorageRace) { + if ephemeralError { // Likely the inbox tracker just isn't caught up. // Let's see if this error disappears naturally. if b.firstAccErr == (time.Time{}) { @@ -982,8 +986,6 @@ func (b *BatchPoster) Start(ctxIn context.Context) { } else if time.Since(b.firstAccErr) < time.Minute { logLevel = log.Debug } - } else { - b.firstAccErr = time.Time{} } logLevel("error posting batch", "err", err) return b.config().ErrorDelay From 053e13a4d81da7e417be72c70f023bf86aa11189 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 31 Aug 2023 19:47:50 -0600 Subject: [PATCH 109/775] Rename firstAccErr to firstEphemeralError --- arbnode/batch_poster.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 53cd5d559..43cf97f2a 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -56,20 +56,20 @@ type batchPosterPosition struct { type BatchPoster struct { stopwaiter.StopWaiter - l1Reader *headerreader.HeaderReader - inbox *InboxTracker - streamer *TransactionStreamer - config BatchPosterConfigFetcher - seqInbox *bridgegen.SequencerInbox - bridge *bridgegen.Bridge - syncMonitor *SyncMonitor - seqInboxABI *abi.ABI - seqInboxAddr common.Address - building *buildingBatch - daWriter das.DataAvailabilityServiceWriter - dataPoster *dataposter.DataPoster - redisLock *redislock.Simple - firstAccErr time.Time // first time a continuous missing accumulator occurred + l1Reader *headerreader.HeaderReader + inbox *InboxTracker + streamer *TransactionStreamer + config BatchPosterConfigFetcher + seqInbox *bridgegen.SequencerInbox + bridge *bridgegen.Bridge + syncMonitor *SyncMonitor + seqInboxABI *abi.ABI + seqInboxAddr common.Address + building *buildingBatch + daWriter das.DataAvailabilityServiceWriter + dataPoster *dataposter.DataPoster + redisLock *redislock.Simple + firstEphemeralError time.Time // first time a continuous error suspected to be ephemeral occurred // An estimate of the number of batches we want to post but haven't yet. // This doesn't include batches which we don't want to post yet due to the L1 bounds. backlog uint64 @@ -972,7 +972,7 @@ func (b *BatchPoster) Start(ctxIn context.Context) { posted, err := b.maybePostSequencerBatch(ctx) ephemeralError := errors.Is(err, AccumulatorNotFoundErr) || errors.Is(err, storage.ErrStorageRace) if !ephemeralError { - b.firstAccErr = time.Time{} + b.firstEphemeralError = time.Time{} } if err != nil { b.building = nil @@ -980,10 +980,10 @@ func (b *BatchPoster) Start(ctxIn context.Context) { if ephemeralError { // Likely the inbox tracker just isn't caught up. // Let's see if this error disappears naturally. - if b.firstAccErr == (time.Time{}) { - b.firstAccErr = time.Now() + if b.firstEphemeralError == (time.Time{}) { + b.firstEphemeralError = time.Now() logLevel = log.Debug - } else if time.Since(b.firstAccErr) < time.Minute { + } else if time.Since(b.firstEphemeralError) < time.Minute { logLevel = log.Debug } } From 2f9db18cb552cec9647c9c6dfd9cbe4d7ef079b9 Mon Sep 17 00:00:00 2001 From: Nodar Date: Fri, 1 Sep 2023 16:34:51 +0200 Subject: [PATCH 110/775] Compare correct encodings in redis storage, drop nil rlp tag from queuedTransaction struct --- arbnode/dataposter/data_poster.go | 2 +- arbnode/dataposter/redis/redisstorage.go | 15 +++++++++++++++ arbnode/dataposter/storage/storage.go | 8 +++----- arbnode/dataposter/storage_test.go | 9 +++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 5231a1c33..dff2602ca 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -112,7 +112,7 @@ func NewDataPoster(db ethdb.Database, headerReader *headerreader.HeaderReader, a case initConfig.UseNoOpStorage: queue = &noop.Storage{} case initConfig.UseLevelDB: - queue = leveldb.New(db, encF) + queue = leveldb.New(db, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) case redisClient == nil: queue = slice.NewStorage(func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) default: diff --git a/arbnode/dataposter/redis/redisstorage.go b/arbnode/dataposter/redis/redisstorage.go index 5123cea15..f2393611b 100644 --- a/arbnode/dataposter/redis/redisstorage.go +++ b/arbnode/dataposter/redis/redisstorage.go @@ -114,6 +114,17 @@ func (s *Storage) Prune(ctx context.Context, until uint64) error { return nil } +// normalizeDecoding decodes data (regardless of what encoding it used), and +// encodes it according to current encoding for storage. +// As a result, encoded data is transformed to currently used encoding. +func (s *Storage) normalizeDecoding(data []byte) ([]byte, error) { + item, err := s.encDec().Decode(data) + if err != nil { + return nil, err + } + return s.encDec().Encode(item) +} + func (s *Storage) Put(ctx context.Context, index uint64, prev, new *storage.QueuedTransaction) error { if new == nil { return fmt.Errorf("tried to insert nil item at index %v", index) @@ -142,6 +153,10 @@ func (s *Storage) Put(ctx context.Context, index uint64, prev, new *storage.Queu if err != nil { return fmt.Errorf("failed to validate item already in redis at index%v: %w", index, err) } + verifiedItem, err = s.normalizeDecoding(verifiedItem) + if err != nil { + return fmt.Errorf("error normalizing encoding for verified item: %w", err) + } prevItemEncoded, err := s.encDec().Encode(prev) if err != nil { return err diff --git a/arbnode/dataposter/storage/storage.go b/arbnode/dataposter/storage/storage.go index 734e2770e..b59bf7bf6 100644 --- a/arbnode/dataposter/storage/storage.go +++ b/arbnode/dataposter/storage/storage.go @@ -21,7 +21,7 @@ var ( ) type QueuedTransaction struct { - FullTx *types.Transaction `rlp:"nil"` + FullTx *types.Transaction Data types.DynamicFeeTx Meta []byte Sent bool @@ -35,7 +35,7 @@ type QueuedTransaction struct { // rlp encoding of Meta into queuedTransaction and rlp encoding it once more // to store it. type LegacyQueuedTransaction struct { - FullTx *types.Transaction `rlp:"nil"` + FullTx *types.Transaction Data types.DynamicFeeTx Meta BatchPosterPosition Sent bool @@ -46,9 +46,7 @@ type LegacyQueuedTransaction struct { // This is also for legacy reason. Since Batchposter is in arbnode package, // we can't refer to BatchPosterPosition type there even if we export it (that // would create cyclic dependency). -// Ideally we'll factor out Batch Poster from arbnode into separate package -// and BatchPosterPosition into another separate package as well. -// For the sake of minimal refactoring, that struct is duplicated here. +// We'll drop this struct in a few releases when we drop legacy encoding. type BatchPosterPosition struct { MessageCount arbutil.MessageIndex DelayedMessageCount uint64 diff --git a/arbnode/dataposter/storage_test.go b/arbnode/dataposter/storage_test.go index eac05502b..d536e5da0 100644 --- a/arbnode/dataposter/storage_test.go +++ b/arbnode/dataposter/storage_test.go @@ -6,6 +6,7 @@ import ( "path" "testing" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" @@ -22,6 +23,7 @@ import ( var ignoreData = cmp.Options{ cmpopts.IgnoreUnexported( + types.Transaction{}, types.DynamicFeeTx{}, big.Int{}, ), @@ -62,6 +64,13 @@ func valueOf(t *testing.T, i int) *storage.QueuedTransaction { t.Fatalf("Encoding batch poster position, error: %v", err) } return &storage.QueuedTransaction{ + FullTx: types.NewTransaction( + uint64(i), + common.Address{}, + big.NewInt(int64(i)), + uint64(i), + big.NewInt(int64(i)), + []byte{byte(i)}), Meta: meta, Data: types.DynamicFeeTx{ ChainID: big.NewInt(int64(i)), From 0bf724b80497f821ff31fc36519ffe53b37d9676 Mon Sep 17 00:00:00 2001 From: Nodar Date: Fri, 1 Sep 2023 17:09:28 +0200 Subject: [PATCH 111/775] Fix incorrect merge with base pr --- linter/koanf/koanf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linter/koanf/koanf.go b/linter/koanf/koanf.go index d483cf775..c7c38e257 100644 --- a/linter/koanf/koanf.go +++ b/linter/koanf/koanf.go @@ -116,7 +116,7 @@ func checkFlagDefs(pass *analysis.Pass, f *ast.FuncDecl) Result { if !ok { continue } - if normSL := normalize(sl); !strings.EqualFold(normSL, s) { + if normSL := strings.ReplaceAll(sl, "-", ""); !strings.EqualFold(normSL, s) { res.Errors = append(res.Errors, koanfError{ Pos: pass.Fset.Position(f.Pos()), Message: fmt.Sprintf("koanf tag name: %q doesn't match the field: %q", sl, s), From 293ed4c504e3370acb0984cac36db02dd1e82275 Mon Sep 17 00:00:00 2001 From: Nodar Date: Fri, 1 Sep 2023 17:14:06 +0200 Subject: [PATCH 112/775] Specify folders of linters instead of separate go files in CI yml --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 916969f32..a0f5251f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,8 +131,8 @@ jobs: skip-pkg-cache: true - name: Custom Lint run: | - go run linter/koanf/koanf.go linter/koanf/handlers.go ./... - go run linter/pointercheck/pointer.go ./... + go run ./linter/koanf ./... + go run ./linter/pointercheck ./... - name: Set environment variables run: | From 1182da1bc3fef5f9117edb64323f0480b6e1f63b Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 1 Sep 2023 09:54:04 -0600 Subject: [PATCH 113/775] Fix changing the basefee in non-mutating calls --- arbos/tx_processor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbos/tx_processor.go b/arbos/tx_processor.go index 09a4692ea..0d44ac548 100644 --- a/arbos/tx_processor.go +++ b/arbos/tx_processor.go @@ -677,7 +677,7 @@ func (p *TxProcessor) GetPaidGasPrice() *big.Int { if version != 9 { gasPrice = p.evm.Context.BaseFee if p.msg.TxRunMode != core.MessageCommitMode && p.msg.GasFeeCap.Sign() == 0 { - gasPrice.SetInt64(0) // gasprice zero behavior + gasPrice = common.Big0 } } return gasPrice From 4be9bbb019fde7e6103304f266a85e0622f3b7b8 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 1 Sep 2023 13:24:48 -0500 Subject: [PATCH 114/775] remove precompilesgen dependency from headerreader --- arbnode/node.go | 7 +++++-- cmd/daserver/daserver.go | 5 ++++- cmd/nitro/nitro.go | 5 ++++- system_tests/das_test.go | 4 +++- util/headerreader/header_reader.go | 17 +++++++++-------- 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index e6960a3f2..e3e9223b1 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -40,6 +40,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/challengegen" "github.com/offchainlabs/nitro/solgen/go/ospgen" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/contracts" @@ -235,7 +236,8 @@ func GenerateRollupConfig(prod bool, wasmModuleRoot common.Hash, rollupOwner com } func DeployOnL1(ctx context.Context, l1client arbutil.L1Interface, deployAuth *bind.TransactOpts, batchPoster common.Address, authorizeValidators uint64, readerConfig headerreader.ConfigFetcher, config rollupgen.Config) (*chaininfo.RollupAddresses, error) { - l1Reader, err := headerreader.New(ctx, l1client, readerConfig) + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) + l1Reader, err := headerreader.New(ctx, l1client, readerConfig, arbSys) if err != nil { return nil, err } @@ -611,7 +613,8 @@ func createNodeImpl( var l1Reader *headerreader.HeaderReader if config.ParentChainReader.Enable { - l1Reader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher.Get().ParentChainReader }) + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) + l1Reader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher.Get().ParentChainReader }, arbSys) if err != nil { return nil, err } diff --git a/cmd/daserver/daserver.go b/cmd/daserver/daserver.go index 7cdfc3991..335aba6a1 100644 --- a/cmd/daserver/daserver.go +++ b/cmd/daserver/daserver.go @@ -17,6 +17,7 @@ import ( flag "github.com/spf13/pflag" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics/exp" @@ -24,6 +25,7 @@ import ( "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/cmd/util/confighelpers" "github.com/offchainlabs/nitro/das" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/headerreader" ) @@ -196,7 +198,8 @@ func startup() error { if err != nil { return err } - l1Reader, err = headerreader.New(ctx, l1Client, func() *headerreader.Config { return &headerreader.DefaultConfig }) // TODO: config + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1Client) + l1Reader, err = headerreader.New(ctx, l1Client, func() *headerreader.Config { return &headerreader.DefaultConfig }, arbSys) // TODO: config if err != nil { return err } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 407ed0afe..dd26fea46 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" _ "github.com/ethereum/go-ethereum/eth/tracers/js" _ "github.com/ethereum/go-ethereum/eth/tracers/native" @@ -48,6 +49,7 @@ import ( "github.com/offchainlabs/nitro/cmd/util" "github.com/offchainlabs/nitro/cmd/util/confighelpers" _ "github.com/offchainlabs/nitro/nodeInterface" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/colors" "github.com/offchainlabs/nitro/util/headerreader" @@ -354,7 +356,8 @@ func mainImpl() int { flag.Usage() log.Crit("--node.validator.only-create-wallet-contract requires --node.validator.use-smart-contract-wallet") } - l1Reader, err := headerreader.New(ctx, l1Client, func() *headerreader.Config { return &liveNodeConfig.Get().Node.ParentChainReader }) + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1Client) + l1Reader, err := headerreader.New(ctx, l1Client, func() *headerreader.Config { return &liveNodeConfig.Get().Node.ParentChainReader }, arbSys) if err != nil { log.Crit("failed to get L1 headerreader", "error", err) diff --git a/system_tests/das_test.go b/system_tests/das_test.go index 795212093..8889d2d53 100644 --- a/system_tests/das_test.go +++ b/system_tests/das_test.go @@ -28,6 +28,7 @@ import ( "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/das" "github.com/offchainlabs/nitro/solgen/go/bridgegen" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/signature" ) @@ -233,7 +234,8 @@ func TestDASComplexConfigAndRestMirror(t *testing.T) { chainConfig := params.ArbitrumDevTestDASChainConfig() l1info, l1client, _, l1stack := createTestL1BlockChain(t, nil) defer requireClose(t, l1stack) - l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }) + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) + l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }, arbSys) Require(t, err) l1Reader.Start(ctx) defer l1Reader.StopAndWait() diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index e5807224c..8487ccd54 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -18,17 +18,20 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbutil" - "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/stopwaiter" flag "github.com/spf13/pflag" ) +type ArbSysInterface interface { + ArbBlockNumber(*bind.CallOpts) (*big.Int, error) +} + type HeaderReader struct { stopwaiter.StopWaiter config ConfigFetcher client arbutil.L1Interface isParentChainArbitrum bool - arbSys *precompilesgen.ArbSys + arbSys ArbSysInterface chanMutex sync.RWMutex // All fields below require the chanMutex @@ -91,25 +94,23 @@ var TestConfig = Config{ UseFinalityData: false, } -func New(ctx context.Context, client arbutil.L1Interface, config ConfigFetcher) (*HeaderReader, error) { +func New(ctx context.Context, client arbutil.L1Interface, config ConfigFetcher, arbSysPrecompile ArbSysInterface) (*HeaderReader, error) { isParentChainArbitrum := false - var arbSys *precompilesgen.ArbSys codeAt, err := client.CodeAt(ctx, types.ArbSysAddress, nil) if err != nil { return nil, err } if len(codeAt) != 0 { isParentChainArbitrum = true - arbSys, err = precompilesgen.NewArbSys(types.ArbSysAddress, client) - if err != nil { - return nil, err + if arbSysPrecompile == nil { + return nil, errors.New("unable to create ArbSys from precompilesgen") } } return &HeaderReader{ client: client, config: config, isParentChainArbitrum: isParentChainArbitrum, - arbSys: arbSys, + arbSys: arbSysPrecompile, outChannels: make(map[chan<- *types.Header]struct{}), outChannelsBehind: make(map[chan<- *types.Header]struct{}), safe: cachedHeader{rpcBlockNum: big.NewInt(rpc.SafeBlockNumber.Int64())}, From 57f25acccc14d0633502136bacc4e637dc89ea02 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 1 Sep 2023 14:23:19 -0500 Subject: [PATCH 115/775] modify implementation to handle CodeAt errors in lb --- arbnode/node.go | 4 ++-- cmd/daserver/daserver.go | 2 +- cmd/nitro/nitro.go | 2 +- system_tests/das_test.go | 2 +- util/headerreader/header_reader.go | 20 +++++++++++--------- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index e3e9223b1..7fde92977 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -237,7 +237,7 @@ func GenerateRollupConfig(prod bool, wasmModuleRoot common.Hash, rollupOwner com func DeployOnL1(ctx context.Context, l1client arbutil.L1Interface, deployAuth *bind.TransactOpts, batchPoster common.Address, authorizeValidators uint64, readerConfig headerreader.ConfigFetcher, config rollupgen.Config) (*chaininfo.RollupAddresses, error) { arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) - l1Reader, err := headerreader.New(ctx, l1client, readerConfig, arbSys) + l1Reader, err := headerreader.New(ctx, l1client, readerConfig, arbSys, true) if err != nil { return nil, err } @@ -614,7 +614,7 @@ func createNodeImpl( var l1Reader *headerreader.HeaderReader if config.ParentChainReader.Enable { arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) - l1Reader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher.Get().ParentChainReader }, arbSys) + l1Reader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher.Get().ParentChainReader }, arbSys, true) if err != nil { return nil, err } diff --git a/cmd/daserver/daserver.go b/cmd/daserver/daserver.go index 335aba6a1..6b874f463 100644 --- a/cmd/daserver/daserver.go +++ b/cmd/daserver/daserver.go @@ -199,7 +199,7 @@ func startup() error { return err } arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1Client) - l1Reader, err = headerreader.New(ctx, l1Client, func() *headerreader.Config { return &headerreader.DefaultConfig }, arbSys) // TODO: config + l1Reader, err = headerreader.New(ctx, l1Client, func() *headerreader.Config { return &headerreader.DefaultConfig }, arbSys, true) // TODO: config if err != nil { return err } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index dd26fea46..e404733b1 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -357,7 +357,7 @@ func mainImpl() int { log.Crit("--node.validator.only-create-wallet-contract requires --node.validator.use-smart-contract-wallet") } arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1Client) - l1Reader, err := headerreader.New(ctx, l1Client, func() *headerreader.Config { return &liveNodeConfig.Get().Node.ParentChainReader }, arbSys) + l1Reader, err := headerreader.New(ctx, l1Client, func() *headerreader.Config { return &liveNodeConfig.Get().Node.ParentChainReader }, arbSys, true) if err != nil { log.Crit("failed to get L1 headerreader", "error", err) diff --git a/system_tests/das_test.go b/system_tests/das_test.go index 8889d2d53..e79b993d0 100644 --- a/system_tests/das_test.go +++ b/system_tests/das_test.go @@ -235,7 +235,7 @@ func TestDASComplexConfigAndRestMirror(t *testing.T) { l1info, l1client, _, l1stack := createTestL1BlockChain(t, nil) defer requireClose(t, l1stack) arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) - l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }, arbSys) + l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }, arbSys, true) Require(t, err) l1Reader.Start(ctx) defer l1Reader.StopAndWait() diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index 8487ccd54..c7fa93738 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -94,16 +94,18 @@ var TestConfig = Config{ UseFinalityData: false, } -func New(ctx context.Context, client arbutil.L1Interface, config ConfigFetcher, arbSysPrecompile ArbSysInterface) (*HeaderReader, error) { +func New(ctx context.Context, client arbutil.L1Interface, config ConfigFetcher, arbSysPrecompile ArbSysInterface, usePrecompilesgen bool) (*HeaderReader, error) { isParentChainArbitrum := false - codeAt, err := client.CodeAt(ctx, types.ArbSysAddress, nil) - if err != nil { - return nil, err - } - if len(codeAt) != 0 { - isParentChainArbitrum = true - if arbSysPrecompile == nil { - return nil, errors.New("unable to create ArbSys from precompilesgen") + if usePrecompilesgen { + codeAt, err := client.CodeAt(ctx, types.ArbSysAddress, nil) + if err != nil { + return nil, err + } + if len(codeAt) != 0 { + isParentChainArbitrum = true + if arbSysPrecompile == nil { + return nil, errors.New("unable to create ArbSys from precompilesgen") + } } } return &HeaderReader{ From 800c0a4d34fb49c139ef4d78d5cc2c8eec856bb0 Mon Sep 17 00:00:00 2001 From: Nodar Date: Mon, 4 Sep 2023 15:51:32 +0200 Subject: [PATCH 116/775] Run linters by specifying linter folder rather than go files --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 33487d060..d6082261c 100644 --- a/Makefile +++ b/Makefile @@ -304,8 +304,8 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro # strategic rules to minimize dependency building .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make - go run linter/koanf/koanf.go linter/koanf/handlers.go ./... - go run linter/pointercheck/pointer.go ./... + go run ./linter/koanf ./... + go run ./linter/pointercheck ./... golangci-lint run --fix yarn --cwd contracts solhint @touch $@ From c2a6a54c923e22e4d6f027e9acd80b93507b0bbb Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 5 Sep 2023 11:07:52 -0500 Subject: [PATCH 117/775] address PR comments --- .../rediscoordinator/redis_coordinator.go | 34 +------------ .../seq-coordinator-manager.go | 48 +++++++++++-------- util/redisutil/redis_coordinator.go | 26 ++++++++++ 3 files changed, 57 insertions(+), 51 deletions(-) diff --git a/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go b/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go index a393719a1..782ab3801 100644 --- a/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go +++ b/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go @@ -14,37 +14,6 @@ type RedisCoordinator struct { *redisutil.RedisCoordinator } -// GetPriorities returns the priority list of sequencers -func (rc *RedisCoordinator) GetPriorities(ctx context.Context) ([]string, map[string]int, error) { - prioritiesMap := make(map[string]int) - prioritiesString, err := rc.Client.Get(ctx, redisutil.PRIORITIES_KEY).Result() - if err != nil { - if errors.Is(err, redis.Nil) { - err = errors.New("sequencer priorities unset") - } - return []string{}, prioritiesMap, err - } - priorities := strings.Split(prioritiesString, ",") - for _, url := range priorities { - prioritiesMap[url]++ - } - return priorities, prioritiesMap, nil -} - -// GetLivelinessMap returns a map whose keys are sequencers that have their liveliness set to OK -func (rc *RedisCoordinator) GetLivelinessMap(ctx context.Context) (map[string]int, error) { - livelinessMap := make(map[string]int) - livelinessList, _, err := rc.Client.Scan(ctx, 0, redisutil.WANTS_LOCKOUT_KEY_PREFIX+"*", 0).Result() - if err != nil { - return livelinessMap, err - } - for _, elem := range livelinessList { - url := strings.TrimPrefix(elem, redisutil.WANTS_LOCKOUT_KEY_PREFIX) - livelinessMap[url]++ - } - return livelinessMap, nil -} - // UpdatePriorities updates the priority list of sequencers func (rc *RedisCoordinator) UpdatePriorities(ctx context.Context, priorities []string) error { prioritiesString := strings.Join(priorities, ",") @@ -53,6 +22,7 @@ func (rc *RedisCoordinator) UpdatePriorities(ctx context.Context, priorities []s if errors.Is(err, redis.Nil) { err = errors.New("sequencer priorities unset") } + return err } - return err + return nil } diff --git a/cmd/seq-coordinator-manager/seq-coordinator-manager.go b/cmd/seq-coordinator-manager/seq-coordinator-manager.go index 0a279cff6..a0123a912 100644 --- a/cmd/seq-coordinator-manager/seq-coordinator-manager.go +++ b/cmd/seq-coordinator-manager/seq-coordinator-manager.go @@ -30,8 +30,8 @@ var nonPriorityForm = tview.NewForm() // Sequencer coordinator managment UI data store type manager struct { redisCoordinator *rediscoordinator.RedisCoordinator - prioritiesMap map[string]int - livelinessMap map[string]int + prioritiesSet map[string]bool + livelinessSet map[string]bool priorityList []string nonPriorityList []string } @@ -55,8 +55,8 @@ func main() { redisCoordinator: &rediscoordinator.RedisCoordinator{ RedisCoordinator: redisutilCoordinator, }, - prioritiesMap: make(map[string]int), - livelinessMap: make(map[string]int), + prioritiesSet: make(map[string]bool), + livelinessSet: make(map[string]bool), } seqManager.refreshAllLists(ctx) @@ -92,7 +92,7 @@ func main() { }) priorityForm.AddButton("Remove", func() { url := seqManager.priorityList[index] - delete(seqManager.prioritiesMap, url) + delete(seqManager.prioritiesSet, url) seqManager.updatePriorityList(ctx, index, 0) seqManager.priorityList = seqManager.priorityList[1:] @@ -122,7 +122,7 @@ func main() { nonPriorityForm.AddButton("Update", func() { key := seqManager.nonPriorityList[index] seqManager.priorityList = append(seqManager.priorityList, key) - seqManager.prioritiesMap[key]++ + seqManager.prioritiesSet[key] = true index = len(seqManager.priorityList) - 1 seqManager.updatePriorityList(ctx, index, target) @@ -188,9 +188,11 @@ func main() { seqManager.addSeqPriorityForm(ctx) pages.SwitchToPage("Add Sequencer") } else if event.Rune() == 99 { - if prioritySeqList.HasFocus() { + if prioritySeqList.HasFocus() || priorityForm.HasFocus() { + priorityForm.Clear(true) app.SetFocus(nonPrioritySeqList) } else { + nonPriorityForm.Clear(true) app.SetFocus(prioritySeqList) } } else if event.Rune() == 113 { @@ -217,8 +219,8 @@ func (sm *manager) updatePriorityList(ctx context.Context, index int, target int } urlList := []string{} - for url := range sm.livelinessMap { - if _, ok := sm.prioritiesMap[url]; !ok { + for url := range sm.livelinessSet { + if _, ok := sm.prioritiesSet[url]; !ok { urlList = append(urlList, url) } } @@ -238,7 +240,7 @@ func (sm *manager) populateLists(ctx context.Context) { sec = fmt.Sprintf(" %vchosen", emoji.LeftArrow) } status := fmt.Sprintf("(%d) %v ", index, emoji.RedCircle) - if _, ok := sm.livelinessMap[seqURL]; ok { + if _, ok := sm.livelinessSet[seqURL]; ok { status = fmt.Sprintf("(%d) %v ", index, emoji.GreenCircle) } prioritySeqList.AddItem(status+seqURL+sec, "", rune(0), nil).SetSecondaryTextColor(tcell.ColorPurple) @@ -264,8 +266,8 @@ func (sm *manager) addSeqPriorityForm(ctx context.Context) *tview.Form { }) addSeqForm.AddButton("Add", func() { // check if url is valid, i.e it doesnt already exist in the priority list - if _, ok := sm.prioritiesMap[URL]; !ok && URL != "" { - sm.prioritiesMap[URL]++ + if _, ok := sm.prioritiesSet[URL]; !ok && URL != "" { + sm.prioritiesSet[URL] = true sm.priorityList = append(sm.priorityList, URL) } sm.populateLists(ctx) @@ -285,24 +287,32 @@ func (sm *manager) pushUpdates(ctx context.Context) { // refreshAllLists gets the current status of all the lists displayed in the UI func (sm *manager) refreshAllLists(ctx context.Context) { - sequencerURLList, mapping, err := sm.redisCoordinator.GetPriorities(ctx) + priorityList, err := sm.redisCoordinator.GetPriorities(ctx) if err != nil { panic(err) } - sm.priorityList = sequencerURLList - sm.prioritiesMap = mapping + sm.priorityList = priorityList + sm.prioritiesSet = getMapfromlist(priorityList) - mapping, err = sm.redisCoordinator.GetLivelinessMap(ctx) + livelinessList, err := sm.redisCoordinator.GetLiveliness(ctx) if err != nil { panic(err) } - sm.livelinessMap = mapping + sm.livelinessSet = getMapfromlist(livelinessList) urlList := []string{} - for url := range sm.livelinessMap { - if _, ok := sm.prioritiesMap[url]; !ok { + for url := range sm.livelinessSet { + if _, ok := sm.prioritiesSet[url]; !ok { urlList = append(urlList, url) } } sm.nonPriorityList = urlList } + +func getMapfromlist(list []string) map[string]bool { + mapping := make(map[string]bool) + for _, url := range list { + mapping[url] = true + } + return mapping +} diff --git a/util/redisutil/redis_coordinator.go b/util/redisutil/redis_coordinator.go index 0ee92fef1..357dfb2e9 100644 --- a/util/redisutil/redis_coordinator.go +++ b/util/redisutil/redis_coordinator.go @@ -76,6 +76,32 @@ func (c *RedisCoordinator) CurrentChosenSequencer(ctx context.Context) (string, return current, nil } +// GetPriorities returns the priority list of sequencers +func (rc *RedisCoordinator) GetPriorities(ctx context.Context) ([]string, error) { + prioritiesString, err := rc.Client.Get(ctx, PRIORITIES_KEY).Result() + if err != nil { + if errors.Is(err, redis.Nil) { + err = errors.New("sequencer priorities unset") + } + return []string{}, err + } + prioritiesList := strings.Split(prioritiesString, ",") + return prioritiesList, nil +} + +// GetLiveliness returns a map whose keys are sequencers that have their liveliness set to OK +func (rc *RedisCoordinator) GetLiveliness(ctx context.Context) ([]string, error) { + livelinessList, _, err := rc.Client.Scan(ctx, 0, WANTS_LOCKOUT_KEY_PREFIX+"*", 0).Result() + if err != nil { + return []string{}, err + } + for i, elem := range livelinessList { + url := strings.TrimPrefix(elem, WANTS_LOCKOUT_KEY_PREFIX) + livelinessList[i] = url + } + return livelinessList, nil +} + func MessageKeyFor(pos arbutil.MessageIndex) string { return fmt.Sprintf("%s%d", MESSAGE_KEY_PREFIX, pos) } From 5af5d4f7d80c8324083e1bd46cfb4dfc664d6ff4 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 6 Sep 2023 14:13:56 -0500 Subject: [PATCH 118/775] check for valid inputs for setting pendingWasmModuleRoot --- staker/stateless_block_validator.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index 7add3e258..7131fe607 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + "regexp" "sync" "testing" @@ -455,8 +456,9 @@ func (v *StatelessBlockValidator) Start(ctx_in context.Context) error { } v.pendingWasmModuleRoot = latest } else { + valid, _ := regexp.MatchString("(0x)?[0-9a-fA-F]{64}", v.config.PendingUpgradeModuleRoot) v.pendingWasmModuleRoot = common.HexToHash(v.config.PendingUpgradeModuleRoot) - if (v.pendingWasmModuleRoot == common.Hash{}) { + if (!valid || v.pendingWasmModuleRoot == common.Hash{}) { return errors.New("pending-upgrade-module-root config value illegal") } } From 3c4ba0ad08565f686afcc3113277207a588065a2 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 7 Sep 2023 12:18:55 +0000 Subject: [PATCH 119/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index c86303cf0..1a58f1b34 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit c86303cf0b7c10f55a19b767a326a8bd06ce8108 +Subproject commit 1a58f1b34e24ecf1679a21edff0a199305aa82f8 From 8e9d7870c0ee65cc99dcd16d1dcd587f8dfaddda Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 7 Sep 2023 12:46:14 +0000 Subject: [PATCH 120/775] remove not used parameter of stackConfigForTest --- system_tests/common_test.go | 12 ++++-------- system_tests/forwarder_test.go | 8 ++++---- system_tests/ipc_test.go | 2 +- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 11cda2121..81cb18ab3 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -290,7 +290,7 @@ func createTestL1BlockChain(t *testing.T, l1info info) (info, *ethclient.Client, return createTestL1BlockChainWithConfig(t, l1info, nil) } -func stackConfigForTest(t *testing.T, dataDir string) *node.Config { +func stackConfigForTest(t *testing.T) *node.Config { stackConfig := node.DefaultConfig stackConfig.HTTPPort = 0 stackConfig.WSPort = 0 @@ -299,11 +299,7 @@ func stackConfigForTest(t *testing.T, dataDir string) *node.Config { stackConfig.P2P.NoDial = true stackConfig.P2P.NoDiscovery = true stackConfig.P2P.NAT = nil - if dataDir != "" { - stackConfig.DataDir = dataDir - } else { - stackConfig.DataDir = t.TempDir() - } + stackConfig.DataDir = t.TempDir() return &stackConfig } @@ -396,7 +392,7 @@ func createTestL1BlockChainWithConfig(t *testing.T, l1info info, stackConfig *no l1info = NewL1TestInfo(t) } if stackConfig == nil { - stackConfig = stackConfigForTest(t, "") + stackConfig = stackConfigForTest(t) } l1info.GenerateAccount("Faucet") @@ -738,7 +734,7 @@ func Create2ndNodeWithConfig( l1client := ethclient.NewClient(l1rpcClient) if stackConfig == nil { - stackConfig = stackConfigForTest(t, "") + stackConfig = stackConfigForTest(t) } l2stack, err := node.New(stackConfig) Require(t, err) diff --git a/system_tests/forwarder_test.go b/system_tests/forwarder_test.go index 7f54b4811..0a954719d 100644 --- a/system_tests/forwarder_test.go +++ b/system_tests/forwarder_test.go @@ -35,7 +35,7 @@ func TestStaticForwarder(t *testing.T) { ipcPath := tmpPath(t, "test.ipc") ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath - stackConfig := stackConfigForTest(t, "") + stackConfig := stackConfigForTest(t) ipcConfig.Apply(stackConfig) nodeConfigA := arbnode.ConfigDefaultL1Test() nodeConfigA.BatchPoster.Enable = false @@ -97,7 +97,7 @@ func fallbackSequencer( ctx context.Context, t *testing.T, opts *fallbackSequencerOpts, ) (l2info info, currentNode *arbnode.Node, l2client *ethclient.Client, l1info info, l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node) { - stackConfig := stackConfigForTest(t, "") + stackConfig := stackConfigForTest(t) ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = opts.ipcPath ipcConfig.Apply(stackConfig) @@ -118,7 +118,7 @@ func createForwardingNode( redisUrl string, fallbackPath string, ) (*ethclient.Client, *arbnode.Node) { - stackConfig := stackConfigForTest(t, "") + stackConfig := stackConfigForTest(t) if ipcPath != "" { ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath @@ -144,7 +144,7 @@ func createSequencer( ipcPath string, redisUrl string, ) (*ethclient.Client, *arbnode.Node) { - stackConfig := stackConfigForTest(t, "") + stackConfig := stackConfigForTest(t) ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath ipcConfig.Apply(stackConfig) diff --git a/system_tests/ipc_test.go b/system_tests/ipc_test.go index 40f2aad62..01ecf859d 100644 --- a/system_tests/ipc_test.go +++ b/system_tests/ipc_test.go @@ -18,7 +18,7 @@ func TestIpcRpc(t *testing.T) { ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath - stackConf := stackConfigForTest(t, "") + stackConf := stackConfigForTest(t) ipcConfig.Apply(stackConf) ctx, cancel := context.WithCancel(context.Background()) From 0b42d1faa41e995b1a81b1c7ed363faed04ac708 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 7 Sep 2023 13:11:13 +0000 Subject: [PATCH 121/775] make sure that each test tx is included in next block --- system_tests/recreatestate_rpc_test.go | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index 4a92879ed..45b7d1bd1 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -273,7 +273,6 @@ func TestRecreateStateForRPCBlockNotFoundWhileRecreating(t *testing.T) { } func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks uint32, skipGas uint64, txCount int) { - t.Helper() maxRecreateStateDepth := int64(30 * 1000 * 1000) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -311,14 +310,6 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks u Require(t, err) Require(t, node.Start(ctx1)) client := ClientForStack(t, stack) - debugAuth := l2info.GetDefaultTransactOpts("Owner", ctx1) - // make auth a chain owner - arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) - Require(t, err, "failed to deploy ArbDebug") - tx, err := arbdebug.BecomeChainOwner(&debugAuth) - Require(t, err, "failed to deploy ArbDebug") - _, err = EnsureTxSucceeded(ctx1, client, tx) - Require(t, err) StartWatchChanErr(t, ctx, feedErrChan, node) dataDir := node.Stack.DataDir() @@ -330,13 +321,13 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks u txs = append(txs, tx) err := client.SendTransaction(ctx, tx) Require(t, err) - } - for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, client, tx) + receipt, err := EnsureTxSucceeded(ctx, client, tx) Require(t, err) + if have, want := receipt.BlockNumber.Uint64(), uint64(i)+1; have != want { + Fatal(t, "internal test error - tx got included in unexpected block number, have:", have, "want:", want) + } } - bc := node.Execution.Backend.ArbInterface().BlockChain() - genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum + genesis := uint64(0) lastBlock, err := client.BlockNumber(ctx) Require(t, err) if want := genesis + uint64(txCount); lastBlock < want { @@ -356,7 +347,7 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks u Require(t, node.Start(ctx)) client = ClientForStack(t, stack) defer node.StopAndWait() - bc = node.Execution.Backend.ArbInterface().BlockChain() + bc := node.Execution.Backend.ArbInterface().BlockChain() gas := skipGas blocks := skipBlocks for i := genesis + 1; i <= genesis+uint64(txCount); i++ { From 68c0039aab67cd1b4ed7ade05b23dd89271ef775 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 7 Sep 2023 16:06:16 +0000 Subject: [PATCH 122/775] simplify test params --- system_tests/recreatestate_rpc_test.go | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index 45b7d1bd1..d0ee9b36b 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -19,7 +19,6 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util" ) @@ -391,31 +390,20 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks u func TestSkippingSavingStateAndRecreatingAfterRestart(t *testing.T) { // test defaults - testSkippingSavingStateAndRecreatingAfterRestart(t, 0, 0, 512) testSkippingSavingStateAndRecreatingAfterRestart(t, 127, 0, 512) testSkippingSavingStateAndRecreatingAfterRestart(t, 0, 15*1000*1000, 512) testSkippingSavingStateAndRecreatingAfterRestart(t, 127, 15*1000*1000, 512) // one test block ~ 925000 gas testBlockGas := uint64(925000) - skipGasValues := []uint64{testBlockGas, 2 * testBlockGas, 3 * testBlockGas, 5 * testBlockGas, 21 * testBlockGas} - skipBlockValues := []uint32{1, 2, 3, 5, 21} + skipBlockValues := []uint64{0, 1, 2, 3, 5, 7, 19, 20, 21, 99, 100, 101} + skipGasValues := []uint64{0} + for _, i := range skipBlockValues[1:] { + skipGasValues = append(skipGasValues, []uint64{i*testBlockGas - 2, i*testBlockGas - 1, i * testBlockGas, i*testBlockGas + 1, i*testBlockGas + 2}...) + } for _, skipGas := range skipGasValues { for _, skipBlocks := range skipBlockValues[:len(skipBlockValues)-2] { - testSkippingSavingStateAndRecreatingAfterRestart(t, skipBlocks, skipGas, 21) + testSkippingSavingStateAndRecreatingAfterRestart(t, uint32(skipBlocks), skipGas, 100) } } - skipBlockValues = []uint32{1, 2, 3, 7, 19, 20, 21, 22} - for _, skipBlocks := range skipBlockValues[:len(skipBlockValues)-2] { - testSkippingSavingStateAndRecreatingAfterRestart(t, skipBlocks, 0, 21) - testSkippingSavingStateAndRecreatingAfterRestart(t, skipBlocks, testBlockGas*100, 21) - } - skipGasValues = []uint64{1, - testBlockGas - 2, testBlockGas - 1, testBlockGas, testBlockGas + 1, testBlockGas + 2, - 2*testBlockGas - 2, 2*testBlockGas - 1, 2 * testBlockGas, 2*testBlockGas + 1, - 7 * testBlockGas, 21 * testBlockGas} - for _, skipGas := range skipGasValues { - testSkippingSavingStateAndRecreatingAfterRestart(t, 0, skipGas, 21) - testSkippingSavingStateAndRecreatingAfterRestart(t, 100, skipGas, 21) - } } From eba6785faf31ba3c9bc0e041d65da119d491acbc Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 7 Sep 2023 10:50:31 -0600 Subject: [PATCH 123/775] Fix Start/Stop of the staker wallet's data poster --- staker/eoa_validator_wallet.go | 4 ---- staker/staker.go | 8 ++++++-- staker/validator_wallet.go | 6 ++---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/staker/eoa_validator_wallet.go b/staker/eoa_validator_wallet.go index 09175332b..5285e96ea 100644 --- a/staker/eoa_validator_wallet.go +++ b/staker/eoa_validator_wallet.go @@ -15,11 +15,9 @@ import ( "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/solgen/go/challengegen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" - "github.com/offchainlabs/nitro/util/stopwaiter" ) type EoaValidatorWallet struct { - stopwaiter.StopWaiter auth *bind.TransactOpts client arbutil.L1Interface rollupAddress common.Address @@ -129,11 +127,9 @@ func (w *EoaValidatorWallet) AuthIfEoa() *bind.TransactOpts { func (w *EoaValidatorWallet) Start(ctx context.Context) { w.dataPoster.Start(ctx) - w.StopWaiter.Start(ctx, w) } func (b *EoaValidatorWallet) StopAndWait() { - b.StopWaiter.StopAndWait() b.dataPoster.StopAndWait() } diff --git a/staker/staker.go b/staker/staker.go index 9b7e6c238..8fdbbd648 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -372,11 +372,15 @@ func (s *Staker) getLatestStakedState(ctx context.Context, staker common.Address func (s *Staker) StopAndWait() { s.StopWaiter.StopAndWait() - s.wallet.StopAndWait() + if s.Strategy() != WatchtowerStrategy { + s.wallet.StopAndWait() + } } func (s *Staker) Start(ctxIn context.Context) { - s.wallet.Start(ctxIn) + if s.Strategy() != WatchtowerStrategy { + s.wallet.Start(ctxIn) + } s.StopWaiter.Start(ctxIn, s) backoff := time.Second s.CallIteratively(func(ctx context.Context) (returningWait time.Duration) { diff --git a/staker/validator_wallet.go b/staker/validator_wallet.go index 133a808ea..fb0f5ed95 100644 --- a/staker/validator_wallet.go +++ b/staker/validator_wallet.go @@ -24,7 +24,6 @@ import ( "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/headerreader" - "github.com/offchainlabs/nitro/util/stopwaiter" ) var validatorABI abi.ABI @@ -66,7 +65,6 @@ type ValidatorWalletInterface interface { } type ContractValidatorWallet struct { - stopwaiter.StopWaiter con *rollupgen.ValidatorWallet address atomic.Pointer[common.Address] onWalletCreated func(common.Address) @@ -413,11 +411,11 @@ func (v *ContractValidatorWallet) AuthIfEoa() *bind.TransactOpts { } func (w *ContractValidatorWallet) Start(ctx context.Context) { - w.StopWaiter.Start(ctx, w) + w.dataPoster.Start(ctx) } func (b *ContractValidatorWallet) StopAndWait() { - b.StopWaiter.StopAndWait() + b.dataPoster.StopAndWait() } func (b *ContractValidatorWallet) DataPoster() *dataposter.DataPoster { From c67b318f3773e25d42c536f8c00d54a9fa9bb052 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 7 Sep 2023 16:53:59 +0000 Subject: [PATCH 124/775] shorten state saving skipping test --- system_tests/recreatestate_rpc_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index d0ee9b36b..fd078e194 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -396,10 +396,10 @@ func TestSkippingSavingStateAndRecreatingAfterRestart(t *testing.T) { // one test block ~ 925000 gas testBlockGas := uint64(925000) - skipBlockValues := []uint64{0, 1, 2, 3, 5, 7, 19, 20, 21, 99, 100, 101} + skipBlockValues := []uint64{0, 1, 2, 3, 5, 100, 101} skipGasValues := []uint64{0} for _, i := range skipBlockValues[1:] { - skipGasValues = append(skipGasValues, []uint64{i*testBlockGas - 2, i*testBlockGas - 1, i * testBlockGas, i*testBlockGas + 1, i*testBlockGas + 2}...) + skipGasValues = append(skipGasValues, []uint64{i*testBlockGas - 1, i * testBlockGas, i*testBlockGas + 1}...) } for _, skipGas := range skipGasValues { for _, skipBlocks := range skipBlockValues[:len(skipBlockValues)-2] { From 20b213a7cc222862f45eb887f4e23bafeba23fe2 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 7 Sep 2023 23:05:52 +0000 Subject: [PATCH 125/775] clean extra return values form prepareNodeWithHistory --- system_tests/recreatestate_rpc_test.go | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index fd078e194..fbc008c9f 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -15,20 +15,19 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/util" ) -func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, txCount uint64, skipBlocks uint32, skipGas uint64) (node *arbnode.Node, bc *core.BlockChain, db ethdb.Database, l2client *ethclient.Client, l2info info, l1info info, l1stack *node.Node, nodeConfig *arbnode.Config, cacheConfig *core.CacheConfig, cancel func()) { +func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, txCount uint64, skipBlocks uint32, skipGas uint64) (node *arbnode.Node, bc *core.BlockChain, db ethdb.Database, l2client *ethclient.Client, cancel func()) { t.Helper() - nodeConfig = arbnode.ConfigDefaultL1Test() + nodeConfig := arbnode.ConfigDefaultL1Test() nodeConfig.RPC.MaxRecreateStateDepth = maxRecreateStateDepth nodeConfig.Sequencer.MaxBlockSpeed = 0 nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 - cacheConfig = &core.CacheConfig{ + cacheConfig := &core.CacheConfig{ // Arbitrum Config Options TriesInMemory: 128, TrieRetention: 30 * time.Minute, @@ -45,7 +44,7 @@ func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateD SnapshotLimit: 256, SnapshotWait: true, } - l2info, node, l2client, _, l1info, _, _, l1stack = createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, cacheConfig, nil) + l2info, node, l2client, _, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, cacheConfig, nil) cancel = func() { defer requireClose(t, l1stack) defer node.StopAndWait() @@ -64,8 +63,7 @@ func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateD } bc = node.Execution.Backend.ArbInterface().BlockChain() db = node.Execution.Backend.ChainDb() - - return + return node, bc, db, l2client, cancel } func fillHeaderCache(t *testing.T, bc *core.BlockChain, from, to uint64) { @@ -115,7 +113,7 @@ func removeStatesFromDb(t *testing.T, bc *core.BlockChain, db ethdb.Database, fr func TestRecreateStateForRPCNoDepthLimit(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, _, _, _, _, _, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32, 0, 0) + _, bc, db, l2client, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -139,7 +137,7 @@ func TestRecreateStateForRPCBigEnoughDepthLimit(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() depthGasLimit := int64(256 * util.NormalizeL2GasForL1GasInitial(800_000, params.GWei)) - _, bc, db, l2client, _, _, _, _, _, cancelNode := prepareNodeWithHistory(t, ctx, depthGasLimit, 32, 0, 0) + _, bc, db, l2client, cancelNode := prepareNodeWithHistory(t, ctx, depthGasLimit, 32, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -163,7 +161,7 @@ func TestRecreateStateForRPCDepthLimitExceeded(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() depthGasLimit := int64(200) - _, bc, db, l2client, _, _, _, _, _, cancelNode := prepareNodeWithHistory(t, ctx, depthGasLimit, 32, 0, 0) + _, bc, db, l2client, cancelNode := prepareNodeWithHistory(t, ctx, depthGasLimit, 32, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -186,7 +184,7 @@ func TestRecreateStateForRPCMissingBlockParent(t *testing.T) { var headerCacheLimit uint64 = 512 ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, _, _, _, _, _, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, headerCacheLimit+5, 0, 0) + _, bc, db, l2client, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, headerCacheLimit+5, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -219,7 +217,7 @@ func TestRecreateStateForRPCMissingBlockParent(t *testing.T) { func TestRecreateStateForRPCBeyondGenesis(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, _, _, _, _, _, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32, 0, 0) + _, bc, db, l2client, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) @@ -243,7 +241,7 @@ func TestRecreateStateForRPCBlockNotFoundWhileRecreating(t *testing.T) { var blockCacheLimit uint64 = 256 ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, _, _, _, _, _, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, blockCacheLimit+4, 0, 0) + _, bc, db, l2client, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, blockCacheLimit+4, 0, 0) defer cancelNode() lastBlock, err := l2client.BlockNumber(ctx) From f238cda3d48f17d4a4403a64bb4ce9b06c3865e4 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 8 Sep 2023 10:27:18 -0600 Subject: [PATCH 126/775] Improve batch size and tx size limit defaults for L3s --- arbnode/batch_poster.go | 27 +++++++++++++------------- arbnode/execution/sequencer.go | 1 + arbnode/node.go | 13 +++---------- cmd/chaininfo/arbitrum_chain_info.json | 6 +++++- cmd/chaininfo/chain_info.go | 5 +++-- cmd/deploy/deploy.go | 20 +++++++++++++------ cmd/nitro/nitro.go | 16 ++++++++++++++- system_tests/common_test.go | 9 +++++++-- 8 files changed, 62 insertions(+), 35 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 8a69bf13e..42b983f0f 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -167,19 +167,20 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { var DefaultBatchPosterConfig = BatchPosterConfig{ Enable: false, DisableDasFallbackStoreDataOnChain: false, - MaxSize: 100000, - PollInterval: time.Second * 10, - ErrorDelay: time.Second * 10, - MaxDelay: time.Hour, - WaitForMaxDelay: false, - CompressionLevel: brotli.BestCompression, - DASRetentionPeriod: time.Hour * 24 * 15, - GasRefunderAddress: "", - ExtraBatchGas: 50_000, - DataPoster: dataposter.DefaultDataPosterConfig, - ParentChainWallet: DefaultBatchPosterL1WalletConfig, - L1BlockBound: "", - L1BlockBoundBypass: time.Hour, + // This default is overridden for L3 chains in applyChainParameters in cmd/nitro/nitro.go + MaxSize: 100000, + PollInterval: time.Second * 10, + ErrorDelay: time.Second * 10, + MaxDelay: time.Hour, + WaitForMaxDelay: false, + CompressionLevel: brotli.BestCompression, + DASRetentionPeriod: time.Hour * 24 * 15, + GasRefunderAddress: "", + ExtraBatchGas: 50_000, + DataPoster: dataposter.DefaultDataPosterConfig, + ParentChainWallet: DefaultBatchPosterL1WalletConfig, + L1BlockBound: "", + L1BlockBoundBypass: time.Hour, } var DefaultBatchPosterL1WalletConfig = genericconf.WalletConfig{ diff --git a/arbnode/execution/sequencer.go b/arbnode/execution/sequencer.go index 402958399..927ce7ac0 100644 --- a/arbnode/execution/sequencer.go +++ b/arbnode/execution/sequencer.go @@ -110,6 +110,7 @@ var DefaultSequencerConfig = SequencerConfig{ NonceCacheSize: 1024, Dangerous: DefaultDangerousSequencerConfig, // 95% of the default batch poster limit, leaving 5KB for headers and such + // This default is overridden for L3 chains in applyChainParameters in cmd/nitro/nitro.go MaxTxDataSize: 95000, NonceFailureCacheSize: 1024, NonceFailureCacheExpiry: time.Second, diff --git a/arbnode/node.go b/arbnode/node.go index e6960a3f2..2882881dd 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -234,19 +234,12 @@ func GenerateRollupConfig(prod bool, wasmModuleRoot common.Hash, rollupOwner com } } -func DeployOnL1(ctx context.Context, l1client arbutil.L1Interface, deployAuth *bind.TransactOpts, batchPoster common.Address, authorizeValidators uint64, readerConfig headerreader.ConfigFetcher, config rollupgen.Config) (*chaininfo.RollupAddresses, error) { - l1Reader, err := headerreader.New(ctx, l1client, readerConfig) - if err != nil { - return nil, err - } - l1Reader.Start(ctx) - defer l1Reader.StopAndWait() - +func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReader, deployAuth *bind.TransactOpts, batchPoster common.Address, authorizeValidators uint64, config rollupgen.Config) (*chaininfo.RollupAddresses, error) { if config.WasmModuleRoot == (common.Hash{}) { return nil, errors.New("no machine specified") } - rollupCreator, _, validatorUtils, validatorWalletCreator, err := deployRollupCreator(ctx, l1Reader, deployAuth) + rollupCreator, _, validatorUtils, validatorWalletCreator, err := deployRollupCreator(ctx, parentChainReader, deployAuth) if err != nil { return nil, fmt.Errorf("error deploying rollup creator: %w", err) } @@ -265,7 +258,7 @@ func DeployOnL1(ctx context.Context, l1client arbutil.L1Interface, deployAuth *b if err != nil { return nil, fmt.Errorf("error submitting create rollup tx: %w", err) } - receipt, err := l1Reader.WaitForTxApproval(ctx, tx) + receipt, err := parentChainReader.WaitForTxApproval(ctx, tx) if err != nil { return nil, fmt.Errorf("error executing create rollup tx: %w", err) } diff --git a/cmd/chaininfo/arbitrum_chain_info.json b/cmd/chaininfo/arbitrum_chain_info.json index f5fa56102..e66774d42 100644 --- a/cmd/chaininfo/arbitrum_chain_info.json +++ b/cmd/chaininfo/arbitrum_chain_info.json @@ -2,6 +2,7 @@ { "chain-name": "arb1", "parent-chain-id": 1, + "parent-chain-is-arbitrum": false, "sequencer-url": "https://arb1-sequencer.arbitrum.io/rpc", "feed-url": "wss://arb1.arbitrum.io/feed", "has-genesis-state": true, @@ -51,6 +52,7 @@ { "chain-name": "nova", "parent-chain-id": 1, + "parent-chain-is-arbitrum": false, "sequencer-url": "https://nova.arbitrum.io/rpc", "feed-url": "wss://nova.arbitrum.io/feed", "das-index-url": "https://nova.arbitrum.io/das-servers", @@ -100,6 +102,7 @@ { "chain-name": "goerli-rollup", "parent-chain-id": 5, + "parent-chain-is-arbitrum": false, "sequencer-url": "https://goerli-rollup.arbitrum.io/rpc", "feed-url": "wss://goerli-rollup.arbitrum.io/feed", "chain-config": @@ -215,9 +218,10 @@ } } }, - { + { "chain-id": 421614, "parent-chain-id": 11155111, + "parent-chain-is-arbitrum": false, "chain-name": "sepolia-rollup", "sequencer-url": "https://sepolia-rollup-sequencer.arbitrum.io/rpc", "feed-url": "wss://sepolia-rollup.arbitrum.io/feed", diff --git a/cmd/chaininfo/chain_info.go b/cmd/chaininfo/chain_info.go index c9ffca983..f75779b4a 100644 --- a/cmd/chaininfo/chain_info.go +++ b/cmd/chaininfo/chain_info.go @@ -18,8 +18,9 @@ import ( var DefaultChainInfo []byte type ChainInfo struct { - ChainName string `json:"chain-name"` - ParentChainId uint64 `json:"parent-chain-id"` + ChainName string `json:"chain-name"` + ParentChainId uint64 `json:"parent-chain-id"` + ParentChainIsArbitrum *bool `json:"parent-chain-is-arbitrum"` // This is the forwarding target to submit transactions to, called the sequencer URL for clarity SequencerUrl string `json:"sequencer-url"` FeedUrl string `json:"feed-url"` diff --git a/cmd/deploy/deploy.go b/cmd/deploy/deploy.go index 357fda14e..17725a7a4 100644 --- a/cmd/deploy/deploy.go +++ b/cmd/deploy/deploy.go @@ -127,13 +127,19 @@ func main() { panic(fmt.Errorf("failed to deserialize chain config: %w", err)) } + l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerReaderConfig }) + if err != nil { + panic(fmt.Errorf("failed to create header reader: %w", err)) + } + l1Reader.Start(ctx) + defer l1Reader.StopAndWait() + deployedAddresses, err := arbnode.DeployOnL1( ctx, - l1client, + l1Reader, l1TransactionOpts, sequencerAddress, *authorizevalidators, - func() *headerreader.Config { return &headerReaderConfig }, arbnode.GenerateRollupConfig(*prod, moduleRoot, ownerAddress, &chainConfig, chainConfigJson, loserEscrowAddress), ) if err != nil { @@ -148,12 +154,14 @@ func main() { if err := os.WriteFile(*outfile, deployData, 0600); err != nil { panic(err) } + parentChainIsArbitrum := l1Reader.IsParentChainArbitrum() chainsInfo := []chaininfo.ChainInfo{ { - ChainName: *l2ChainName, - ParentChainId: l1ChainId.Uint64(), - ChainConfig: &chainConfig, - RollupAddresses: deployedAddresses, + ChainName: *l2ChainName, + ParentChainId: l1ChainId.Uint64(), + ParentChainIsArbitrum: &parentChainIsArbitrum, + ChainConfig: &chainConfig, + RollupAddresses: deployedAddresses, }, } chainsInfoJson, err := json.Marshal(chainsInfo) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 407ed0afe..350a8f7ca 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -357,7 +357,6 @@ func mainImpl() int { l1Reader, err := headerreader.New(ctx, l1Client, func() *headerreader.Config { return &liveNodeConfig.Get().Node.ParentChainReader }) if err != nil { log.Crit("failed to get L1 headerreader", "error", err) - } // Just create validator smart wallet if needed then exit @@ -768,6 +767,16 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c if err != nil { return false, err } + var parentChainIsArbitrum bool + if chainInfo.ParentChainIsArbitrum != nil { + parentChainIsArbitrum = *chainInfo.ParentChainIsArbitrum + } else { + log.Warn("Chain information parentChainIsArbitrum field missing, in the future this will be required", "chainId", chainId, "parentChainId", chainInfo.ParentChainId) + _, err := chaininfo.ProcessChainInfo(chainInfo.ParentChainId, "", combinedL2ChainInfoFiles, "") + if err == nil { + parentChainIsArbitrum = true + } + } chainDefaults := map[string]interface{}{ "persistent.chain": chainInfo.ChainName, "chain.id": chainInfo.ChainConfig.ChainID.Uint64(), @@ -787,6 +796,11 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c if !chainInfo.HasGenesisState { chainDefaults["init.empty"] = true } + if parentChainIsArbitrum { + safeBatchSize := execution.DefaultSequencerConfig.MaxTxDataSize - 5000 + chainDefaults["node.batch-poster.max-size"] = safeBatchSize + chainDefaults["node.sequencer.max-tx-data-size"] = safeBatchSize - 5000 + } err = k.Load(confmap.Provider(chainDefaults, "."), nil) if err != nil { return false, err diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 81cb18ab3..b92fbf757 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -475,13 +475,18 @@ func DeployOnTestL1( Require(t, err) serializedChainConfig, err := json.Marshal(chainConfig) Require(t, err) + + l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }) + Require(t, err) + l1Reader.Start(ctx) + defer l1Reader.StopAndWait() + addresses, err := arbnode.DeployOnL1( ctx, - l1client, + l1Reader, &l1TransactionOpts, l1info.GetAddress("Sequencer"), 0, - func() *headerreader.Config { return &headerreader.TestConfig }, arbnode.GenerateRollupConfig(false, locator.LatestWasmModuleRoot(), l1info.GetAddress("RollupOwner"), chainConfig, serializedChainConfig, common.Address{}), ) Require(t, err) From 0e0fe26ed7d74bcb5c39040a23c57eecc9abee87 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 8 Sep 2023 16:06:34 +0000 Subject: [PATCH 127/775] refactor setting cache config in tests --- system_tests/arbtrace_test.go | 2 +- system_tests/common_test.go | 21 +-- system_tests/debugapi_test.go | 2 +- system_tests/recreatestate_rpc_test.go | 177 ++++++++++++++++--------- system_tests/staker_test.go | 2 +- 5 files changed, 131 insertions(+), 73 deletions(-) diff --git a/system_tests/arbtrace_test.go b/system_tests/arbtrace_test.go index 4aab5c71b..78907aa62 100644 --- a/system_tests/arbtrace_test.go +++ b/system_tests/arbtrace_test.go @@ -147,7 +147,7 @@ func TestArbTraceForwarding(t *testing.T) { nodeConfig := arbnode.ConfigDefaultL1Test() nodeConfig.RPC.ClassicRedirect = ipcPath nodeConfig.RPC.ClassicRedirectTimeout = time.Second - _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, nil, nil) + _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, nil) defer requireClose(t, l1stack) defer requireClose(t, l2stack) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 81cb18ab3..ce1624a27 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -493,13 +493,13 @@ func DeployOnTestL1( } func createL2BlockChain( - t *testing.T, l2info *BlockchainTestInfo, dataDir string, chainConfig *params.ChainConfig, cacheConfig *core.CacheConfig, + t *testing.T, l2info *BlockchainTestInfo, dataDir string, chainConfig *params.ChainConfig, cacheConfig *execution.CachingConfig, ) (*BlockchainTestInfo, *node.Node, ethdb.Database, ethdb.Database, *core.BlockChain) { return createL2BlockChainWithStackConfig(t, l2info, dataDir, chainConfig, nil, nil, cacheConfig) } func createL2BlockChainWithStackConfig( - t *testing.T, l2info *BlockchainTestInfo, dataDir string, chainConfig *params.ChainConfig, initMessage *arbostypes.ParsedInitMessage, stackConfig *node.Config, cacheConfig *core.CacheConfig, + t *testing.T, l2info *BlockchainTestInfo, dataDir string, chainConfig *params.ChainConfig, initMessage *arbostypes.ParsedInitMessage, stackConfig *node.Config, cacheConfig *execution.CachingConfig, ) (*BlockchainTestInfo, *node.Node, ethdb.Database, ethdb.Database, *core.BlockChain) { if l2info == nil { l2info = NewArbTestInfo(t, chainConfig.ChainID) @@ -530,7 +530,11 @@ func createL2BlockChainWithStackConfig( SerializedChainConfig: serializedChainConfig, } } - blockchain, err := execution.WriteOrTestBlockChain(chainDb, cacheConfig, initReader, chainConfig, initMessage, arbnode.ConfigDefaultL2Test().TxLookupLimit, 0) + var coreCacheConfig *core.CacheConfig + if cacheConfig != nil { + coreCacheConfig = execution.DefaultCacheConfigFor(stack, cacheConfig) + } + blockchain, err := execution.WriteOrTestBlockChain(chainDb, coreCacheConfig, initReader, chainConfig, initMessage, arbnode.ConfigDefaultL2Test().TxLookupLimit, 0) Require(t, err) return l2info, stack, chainDb, arbDb, blockchain @@ -565,7 +569,7 @@ func createTestNodeOnL1WithConfig( l2info info, currentNode *arbnode.Node, l2client *ethclient.Client, l1info info, l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node, ) { - l2info, currentNode, l2client, _, l1info, l1backend, l1client, l1stack = createTestNodeOnL1WithConfigImpl(t, ctx, isSequencer, nodeConfig, chainConfig, stackConfig, nil, nil) + l2info, currentNode, l2client, _, l1info, l1backend, l1client, l1stack = createTestNodeOnL1WithConfigImpl(t, ctx, isSequencer, nodeConfig, chainConfig, stackConfig, nil) return } @@ -576,7 +580,6 @@ func createTestNodeOnL1WithConfigImpl( nodeConfig *arbnode.Config, chainConfig *params.ChainConfig, stackConfig *node.Config, - cacheConfig *core.CacheConfig, l2info_in info, ) ( l2info info, currentNode *arbnode.Node, l2client *ethclient.Client, l2stack *node.Node, @@ -598,7 +601,7 @@ func createTestNodeOnL1WithConfigImpl( l2info = NewArbTestInfo(t, chainConfig.ChainID) } addresses, initMessage := DeployOnTestL1(t, ctx, l1info, l1client, chainConfig) - _, l2stack, l2chainDb, l2arbDb, l2blockchain = createL2BlockChainWithStackConfig(t, l2info, "", chainConfig, initMessage, stackConfig, cacheConfig) + _, l2stack, l2chainDb, l2arbDb, l2blockchain = createL2BlockChainWithStackConfig(t, l2info, "", chainConfig, initMessage, stackConfig, &nodeConfig.Caching) var sequencerTxOptsPtr *bind.TransactOpts var dataSigner signature.DataSignerFunc if isSequencer { @@ -644,7 +647,7 @@ func CreateTestL2WithConfig( AddDefaultValNode(t, ctx, nodeConfig, true) - l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, l2Info, "", params.ArbitrumDevTestChainConfig(), nil) + l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, l2Info, "", params.ArbitrumDevTestChainConfig(), &nodeConfig.Caching) currentNode, err := arbnode.CreateNode(ctx, stack, chainDb, arbDb, NewFetcherFromConfig(nodeConfig), blockchain, nil, nil, nil, nil, nil, feedErrChan) Require(t, err) @@ -749,7 +752,9 @@ func Create2ndNodeWithConfig( txOpts := l1info.GetDefaultTransactOpts("Sequencer", ctx) chainConfig := first.Execution.ArbInterface.BlockChain().Config() initMessage := getInitMessage(ctx, t, l1client, first.DeployInfo) - l2blockchain, err := execution.WriteOrTestBlockChain(l2chainDb, nil, initReader, chainConfig, initMessage, arbnode.ConfigDefaultL2Test().TxLookupLimit, 0) + + coreCacheConfig := execution.DefaultCacheConfigFor(l2stack, &nodeConfig.Caching) + l2blockchain, err := execution.WriteOrTestBlockChain(l2chainDb, coreCacheConfig, initReader, chainConfig, initMessage, arbnode.ConfigDefaultL2Test().TxLookupLimit, 0) Require(t, err) AddDefaultValNode(t, ctx, nodeConfig, true) diff --git a/system_tests/debugapi_test.go b/system_tests/debugapi_test.go index ff28e2350..03e3dfd40 100644 --- a/system_tests/debugapi_test.go +++ b/system_tests/debugapi_test.go @@ -14,7 +14,7 @@ import ( func TestDebugAPI(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, nil, nil, nil) + _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, nil, nil) defer requireClose(t, l1stack) defer requireClose(t, l2stack) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index fbc008c9f..dbf68c847 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -6,7 +6,6 @@ import ( "math/big" "strings" "testing" - "time" "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" @@ -18,33 +17,13 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/arbnode/execution" "github.com/offchainlabs/nitro/util" ) -func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, txCount uint64, skipBlocks uint32, skipGas uint64) (node *arbnode.Node, bc *core.BlockChain, db ethdb.Database, l2client *ethclient.Client, cancel func()) { +func prepareNodeWithHistory(t *testing.T, ctx context.Context, nodeConfig *arbnode.Config, txCount uint64) (node *arbnode.Node, executionNode *execution.ExecutionNode, l2client *ethclient.Client, cancel func()) { t.Helper() - nodeConfig := arbnode.ConfigDefaultL1Test() - nodeConfig.RPC.MaxRecreateStateDepth = maxRecreateStateDepth - nodeConfig.Sequencer.MaxBlockSpeed = 0 - nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 - cacheConfig := &core.CacheConfig{ - // Arbitrum Config Options - TriesInMemory: 128, - TrieRetention: 30 * time.Minute, - MaxNumberOfBlocksToSkipStateSaving: skipBlocks, - MaxAmountOfGasToSkipStateSaving: skipGas, - - // disable caching of states in BlockChain.stateCache - TrieCleanLimit: 0, - TrieDirtyLimit: 0, - - TrieDirtyDisabled: true, - - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 256, - SnapshotWait: true, - } - l2info, node, l2client, _, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, cacheConfig, nil) + l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, nil) cancel = func() { defer requireClose(t, l1stack) defer node.StopAndWait() @@ -61,9 +40,7 @@ func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateD _, err := EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) } - bc = node.Execution.Backend.ArbInterface().BlockChain() - db = node.Execution.Backend.ChainDb() - return node, bc, db, l2client, cancel + return node, node.Execution, l2client, cancel } func fillHeaderCache(t *testing.T, bc *core.BlockChain, from, to uint64) { @@ -113,8 +90,20 @@ func removeStatesFromDb(t *testing.T, bc *core.BlockChain, db ethdb.Database, fr func TestRecreateStateForRPCNoDepthLimit(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32, 0, 0) + nodeConfig := arbnode.ConfigDefaultL1Test() + nodeConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth + nodeConfig.Sequencer.MaxBlockSpeed = 0 + nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 + nodeConfig.Caching.Archive = true + // disable caching of states in BlockChain.stateCache + nodeConfig.Caching.TrieCleanCache = 0 + nodeConfig.Caching.TrieDirtyCache = 0 + nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 + nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 + _, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, 32) defer cancelNode() + bc := execNode.Backend.ArbInterface().BlockChain() + db := execNode.Backend.ChainDb() lastBlock, err := l2client.BlockNumber(ctx) Require(t, err) @@ -137,8 +126,20 @@ func TestRecreateStateForRPCBigEnoughDepthLimit(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() depthGasLimit := int64(256 * util.NormalizeL2GasForL1GasInitial(800_000, params.GWei)) - _, bc, db, l2client, cancelNode := prepareNodeWithHistory(t, ctx, depthGasLimit, 32, 0, 0) + nodeConfig := arbnode.ConfigDefaultL1Test() + nodeConfig.RPC.MaxRecreateStateDepth = depthGasLimit + nodeConfig.Sequencer.MaxBlockSpeed = 0 + nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 + nodeConfig.Caching.Archive = true + // disable caching of states in BlockChain.stateCache + nodeConfig.Caching.TrieCleanCache = 0 + nodeConfig.Caching.TrieDirtyCache = 0 + nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 + nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 + _, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, 32) defer cancelNode() + bc := execNode.Backend.ArbInterface().BlockChain() + db := execNode.Backend.ChainDb() lastBlock, err := l2client.BlockNumber(ctx) Require(t, err) @@ -160,9 +161,20 @@ func TestRecreateStateForRPCBigEnoughDepthLimit(t *testing.T) { func TestRecreateStateForRPCDepthLimitExceeded(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - depthGasLimit := int64(200) - _, bc, db, l2client, cancelNode := prepareNodeWithHistory(t, ctx, depthGasLimit, 32, 0, 0) + nodeConfig := arbnode.ConfigDefaultL1Test() + nodeConfig.RPC.MaxRecreateStateDepth = int64(200) + nodeConfig.Sequencer.MaxBlockSpeed = 0 + nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 + nodeConfig.Caching.Archive = true + // disable caching of states in BlockChain.stateCache + nodeConfig.Caching.TrieCleanCache = 0 + nodeConfig.Caching.TrieDirtyCache = 0 + nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 + nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 + _, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, 32) defer cancelNode() + bc := execNode.Backend.ArbInterface().BlockChain() + db := execNode.Backend.ChainDb() lastBlock, err := l2client.BlockNumber(ctx) Require(t, err) @@ -184,8 +196,20 @@ func TestRecreateStateForRPCMissingBlockParent(t *testing.T) { var headerCacheLimit uint64 = 512 ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, headerCacheLimit+5, 0, 0) + nodeConfig := arbnode.ConfigDefaultL1Test() + nodeConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth + nodeConfig.Sequencer.MaxBlockSpeed = 0 + nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 + nodeConfig.Caching.Archive = true + // disable caching of states in BlockChain.stateCache + nodeConfig.Caching.TrieCleanCache = 0 + nodeConfig.Caching.TrieDirtyCache = 0 + nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 + nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 + _, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, headerCacheLimit+5) defer cancelNode() + bc := execNode.Backend.ArbInterface().BlockChain() + db := execNode.Backend.ChainDb() lastBlock, err := l2client.BlockNumber(ctx) Require(t, err) @@ -217,8 +241,21 @@ func TestRecreateStateForRPCMissingBlockParent(t *testing.T) { func TestRecreateStateForRPCBeyondGenesis(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, 32, 0, 0) + + nodeConfig := arbnode.ConfigDefaultL1Test() + nodeConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth + nodeConfig.Sequencer.MaxBlockSpeed = 0 + nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 + nodeConfig.Caching.Archive = true + // disable caching of states in BlockChain.stateCache + nodeConfig.Caching.TrieCleanCache = 0 + nodeConfig.Caching.TrieDirtyCache = 0 + nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 + nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 + _, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, 32) defer cancelNode() + bc := execNode.Backend.ArbInterface().BlockChain() + db := execNode.Backend.ChainDb() lastBlock, err := l2client.BlockNumber(ctx) Require(t, err) @@ -241,8 +278,20 @@ func TestRecreateStateForRPCBlockNotFoundWhileRecreating(t *testing.T) { var blockCacheLimit uint64 = 256 ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, bc, db, l2client, cancelNode := prepareNodeWithHistory(t, ctx, arbitrum.InfiniteMaxRecreateStateDepth, blockCacheLimit+4, 0, 0) + nodeConfig := arbnode.ConfigDefaultL1Test() + nodeConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth + nodeConfig.Sequencer.MaxBlockSpeed = 0 + nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 + nodeConfig.Caching.Archive = true + // disable caching of states in BlockChain.stateCache + nodeConfig.Caching.TrieCleanCache = 0 + nodeConfig.Caching.TrieDirtyCache = 0 + nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 + nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 + _, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, blockCacheLimit+4) defer cancelNode() + bc := execNode.Backend.ArbInterface().BlockChain() + db := execNode.Backend.ChainDb() lastBlock, err := l2client.BlockNumber(ctx) Require(t, err) @@ -269,7 +318,7 @@ func TestRecreateStateForRPCBlockNotFoundWhileRecreating(t *testing.T) { } } -func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks uint32, skipGas uint64, txCount int) { +func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig *execution.CachingConfig, txCount int) { maxRecreateStateDepth := int64(30 * 1000 * 1000) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -279,27 +328,14 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks u nodeConfig.RPC.MaxRecreateStateDepth = maxRecreateStateDepth nodeConfig.Sequencer.MaxBlockSpeed = 0 nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 - cacheConfig := &core.CacheConfig{ - // Arbitrum Config Options - TriesInMemory: 128, - TrieRetention: 30 * time.Minute, - MaxNumberOfBlocksToSkipStateSaving: skipBlocks, - MaxAmountOfGasToSkipStateSaving: skipGas, - - // disable caching of states in BlockChain.stateCache - TrieCleanLimit: 0, - TrieDirtyLimit: 0, - - TrieDirtyDisabled: true, - - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 256, - SnapshotWait: true, - } + nodeConfig.Caching = *cacheConfig + + skipBlocks := nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving + skipGas := nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving feedErrChan := make(chan error, 10) AddDefaultValNode(t, ctx1, nodeConfig, true) - l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, nil, t.TempDir(), params.ArbitrumDevTestChainConfig(), cacheConfig) + l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, nil, t.TempDir(), params.ArbitrumDevTestChainConfig(), &nodeConfig.Caching) node, err := arbnode.CreateNode(ctx1, stack, chainDb, arbDb, NewFetcherFromConfig(nodeConfig), blockchain, nil, nil, nil, nil, nil, feedErrChan) Require(t, err) @@ -338,7 +374,7 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks u t.Log("stopped first node") AddDefaultValNode(t, ctx, nodeConfig, true) - l2info, stack, chainDb, arbDb, blockchain = createL2BlockChain(t, l2info, dataDir, params.ArbitrumDevTestChainConfig(), cacheConfig) + l2info, stack, chainDb, arbDb, blockchain = createL2BlockChain(t, l2info, dataDir, params.ArbitrumDevTestChainConfig(), &nodeConfig.Caching) node, err = arbnode.CreateNode(ctx, stack, chainDb, arbDb, NewFetcherFromConfig(nodeConfig), blockchain, nil, node.DeployInfo, nil, nil, nil, feedErrChan) Require(t, err) Require(t, node.Start(ctx)) @@ -387,21 +423,38 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, skipBlocks u } func TestSkippingSavingStateAndRecreatingAfterRestart(t *testing.T) { + cacheConfig := execution.DefaultCachingConfig + cacheConfig.Archive = true + // disable caching of states in BlockChain.stateCache + cacheConfig.TrieCleanCache = 0 + cacheConfig.TrieDirtyCache = 0 // test defaults - testSkippingSavingStateAndRecreatingAfterRestart(t, 127, 0, 512) - testSkippingSavingStateAndRecreatingAfterRestart(t, 0, 15*1000*1000, 512) - testSkippingSavingStateAndRecreatingAfterRestart(t, 127, 15*1000*1000, 512) + testSkippingSavingStateAndRecreatingAfterRestart(t, &cacheConfig, 512) + + cacheConfig.MaxNumberOfBlocksToSkipStateSaving = 127 + cacheConfig.MaxAmountOfGasToSkipStateSaving = 0 + testSkippingSavingStateAndRecreatingAfterRestart(t, &cacheConfig, 512) + + cacheConfig.MaxNumberOfBlocksToSkipStateSaving = 0 + cacheConfig.MaxAmountOfGasToSkipStateSaving = 15 * 1000 * 1000 + testSkippingSavingStateAndRecreatingAfterRestart(t, &cacheConfig, 512) + + cacheConfig.MaxNumberOfBlocksToSkipStateSaving = 127 + cacheConfig.MaxAmountOfGasToSkipStateSaving = 15 * 1000 * 1000 + testSkippingSavingStateAndRecreatingAfterRestart(t, &cacheConfig, 512) // one test block ~ 925000 gas testBlockGas := uint64(925000) - skipBlockValues := []uint64{0, 1, 2, 3, 5, 100, 101} - skipGasValues := []uint64{0} - for _, i := range skipBlockValues[1:] { - skipGasValues = append(skipGasValues, []uint64{i*testBlockGas - 1, i * testBlockGas, i*testBlockGas + 1}...) + skipBlockValues := []uint64{0, 1, 2, 3, 5, 21, 51, 100, 101} + var skipGasValues []uint64 + for _, i := range skipBlockValues { + skipGasValues = append(skipGasValues, i*testBlockGas) } for _, skipGas := range skipGasValues { for _, skipBlocks := range skipBlockValues[:len(skipBlockValues)-2] { - testSkippingSavingStateAndRecreatingAfterRestart(t, uint32(skipBlocks), skipGas, 100) + cacheConfig.MaxAmountOfGasToSkipStateSaving = skipGas + cacheConfig.MaxNumberOfBlocksToSkipStateSaving = uint32(skipBlocks) + testSkippingSavingStateAndRecreatingAfterRestart(t, &cacheConfig, 100) } } } diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 82eede9f6..b1c7091e5 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -64,7 +64,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) types.NewArbitrumSigner(types.NewLondonSigner(l2chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), transferGas, ) - _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, l2chainConfig, nil, nil, l2info) + _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, l2chainConfig, nil, nil) defer requireClose(t, l1stack) defer l2nodeA.StopAndWait() From cc58fbb8e263839d2425d1c34fbed846eec71656 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 8 Sep 2023 16:36:23 +0000 Subject: [PATCH 128/775] fix staker test --- system_tests/staker_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index b1c7091e5..dc6445092 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -64,7 +64,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) types.NewArbitrumSigner(types.NewLondonSigner(l2chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), transferGas, ) - _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, l2chainConfig, nil, nil) + _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, l2chainConfig, nil, l2info) defer requireClose(t, l1stack) defer l2nodeA.StopAndWait() From 2f24e29d7e7127c43e2a16d0d195552fd6443819 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 8 Sep 2023 11:22:57 -0600 Subject: [PATCH 129/775] Ensure the parent chain has enough space for our batches --- cmd/nitro/nitro.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 350a8f7ca..4ebe598ee 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -797,9 +797,14 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c chainDefaults["init.empty"] = true } if parentChainIsArbitrum { - safeBatchSize := execution.DefaultSequencerConfig.MaxTxDataSize - 5000 + l2MaxTxSize := execution.DefaultSequencerConfig.MaxTxDataSize + bufferSpace := 5000 + if l2MaxTxSize < bufferSpace*2 { + return false, fmt.Errorf("not enough room in parent chain max tx size %v for bufferSpace %v * 2", l2MaxTxSize, bufferSpace) + } + safeBatchSize := l2MaxTxSize - bufferSpace chainDefaults["node.batch-poster.max-size"] = safeBatchSize - chainDefaults["node.sequencer.max-tx-data-size"] = safeBatchSize - 5000 + chainDefaults["node.sequencer.max-tx-data-size"] = safeBatchSize - bufferSpace } err = k.Load(confmap.Provider(chainDefaults, "."), nil) if err != nil { From db2eff36890ae967f84ec6047849644fb4a5e163 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 8 Sep 2023 16:26:06 -0600 Subject: [PATCH 130/775] Make the default data poster storage backend LevelDB --- arbnode/dataposter/data_poster.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index dff2602ca..b1e6555b2 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -111,16 +111,16 @@ func NewDataPoster(db ethdb.Database, headerReader *headerreader.HeaderReader, a switch { case initConfig.UseNoOpStorage: queue = &noop.Storage{} - case initConfig.UseLevelDB: - queue = leveldb.New(db, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) - case redisClient == nil: - queue = slice.NewStorage(func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) - default: + case redisClient != nil: var err error queue, err = redisstorage.NewStorage(redisClient, "data-poster.queue", &initConfig.RedisSigner, encF) if err != nil { return nil, err } + case initConfig.UseLevelDB: + queue = leveldb.New(db, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) + default: + queue = slice.NewStorage(func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) } return &DataPoster{ headerReader: headerReader, @@ -665,7 +665,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ MaxTipCapGwei: 5, NonceRbfSoftConfs: 1, AllocateMempoolBalance: true, - UseLevelDB: false, + UseLevelDB: true, UseNoOpStorage: false, LegacyStorageEncoding: true, } From 6d473afc52784e7573821d216d872ddc0277a03d Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 8 Sep 2023 16:39:07 -0600 Subject: [PATCH 131/775] Use a separate prefix for the staker data poster --- arbnode/dataposter/storage/storage.go | 1 + arbnode/node.go | 6 +++--- system_tests/staker_test.go | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/arbnode/dataposter/storage/storage.go b/arbnode/dataposter/storage/storage.go index b59bf7bf6..70637c48e 100644 --- a/arbnode/dataposter/storage/storage.go +++ b/arbnode/dataposter/storage/storage.go @@ -15,6 +15,7 @@ var ( ErrStorageRace = errors.New("storage race error") BlockValidatorPrefix string = "v" // the prefix for all block validator keys + StakerPrefix string = "S" // the prefix for all staker keys BatchPosterPrefix string = "b" // the prefix for all batch poster keys // TODO(anodar): move everything else from schema.go file to here once // execution split is complete. diff --git a/arbnode/node.go b/arbnode/node.go index 2882881dd..356c46681 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -538,7 +538,7 @@ func checkArbDbSchemaVersion(arbDb ethdb.Database) error { return nil } -func ValidatorDataposter( +func StakerDataposter( db ethdb.Database, l1Reader *headerreader.HeaderReader, transactOpts *bind.TransactOpts, cfgFetcher ConfigFetcher, syncMonitor *SyncMonitor, ) (*dataposter.DataPoster, error) { @@ -802,8 +802,8 @@ func createNodeImpl( var messagePruner *MessagePruner if config.Staker.Enable { - dp, err := ValidatorDataposter( - rawdb.NewTable(arbDb, storage.BlockValidatorPrefix), + dp, err := StakerDataposter( + rawdb.NewTable(arbDb, storage.StakerPrefix), l1Reader, txOptsValidator, configFetcher, diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 82eede9f6..96ea1ee2e 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -130,7 +130,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) valConfig := staker.TestL1ValidatorConfig - dpA, err := arbnode.ValidatorDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.BlockValidatorPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) + dpA, err := arbnode.StakerDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } @@ -178,7 +178,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } Require(t, err) - dpB, err := arbnode.ValidatorDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.BlockValidatorPrefix), l2nodeB.L1Reader, &l1authB, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) + dpB, err := arbnode.StakerDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeB.L1Reader, &l1authB, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } @@ -217,7 +217,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) err = valWalletB.Initialize(ctx) Require(t, err) } - dpC, err := arbnode.ValidatorDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.BlockValidatorPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) + dpC, err := arbnode.StakerDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } From 8e4c931eeb1b5793cc44a221aa54bb3029db0bf0 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sat, 9 Sep 2023 22:14:20 -0600 Subject: [PATCH 132/775] Handle block "not found" case in batch revert polling --- arbnode/batch_poster.go | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 42b983f0f..8144c9b7b 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -11,6 +11,7 @@ import ( "fmt" "math" "math/big" + "strings" "sync/atomic" "time" @@ -262,12 +263,13 @@ func NewBatchPoster(dataPosterDB ethdb.Database, l1Reader *headerreader.HeaderRe // contain reverted batch_poster transaction. // It returns true if it finds batch posting needs to halt, which is true if a batch reverts // unless the data poster is configured with noop storage which can tolerate reverts. -func (b *BatchPoster) checkReverts(ctx context.Context, from, to int64) (bool, error) { - if from > to { - return false, fmt.Errorf("wrong range, from: %d is more to: %d", from, to) +// From must be a pointer to the starting block, which is updated after each block is checked for reverts +func (b *BatchPoster) checkReverts(ctx context.Context, from *int64, to int64) (bool, error) { + if *from > to { + return false, fmt.Errorf("wrong range, from: %d > to: %d", from, to) } - for idx := from; idx <= to; idx++ { - number := big.NewInt(idx) + for ; *from <= to; *from++ { + number := big.NewInt(*from) block, err := b.l1Reader.Client().BlockByNumber(ctx, number) if err != nil { return false, fmt.Errorf("getting block: %v by number: %w", number, err) @@ -277,7 +279,7 @@ func (b *BatchPoster) checkReverts(ctx context.Context, from, to int64) (bool, e if err != nil { return false, fmt.Errorf("getting sender of transaction tx: %v, %w", tx.Hash(), err) } - if bytes.Equal(from.Bytes(), b.dataPoster.Sender().Bytes()) { + if from == b.dataPoster.Sender() { r, err := b.l1Reader.Client().TransactionReceipt(ctx, tx.Hash()) if err != nil { return false, fmt.Errorf("getting a receipt for transaction: %v, %w", tx.Hash(), err) @@ -303,7 +305,7 @@ func (b *BatchPoster) pollForReverts(ctx context.Context) { headerCh, unsubscribe := b.l1Reader.Subscribe(false) defer unsubscribe() - last := int64(0) // number of last seen block + nextToCheck := int64(0) // the first unchecked block for { // Poll until: // - L1 headers reader channel is closed, or @@ -312,31 +314,37 @@ func (b *BatchPoster) pollForReverts(ctx context.Context) { select { case h, ok := <-headerCh: if !ok { - log.Info("L1 headers channel has been closed") + log.Info("L1 headers channel checking for batch poster reverts has been closed") return } // If this is the first block header, set last seen as number-1. // We may see same block number again if there is L1 reorg, in that // case we check the block again. - if last == 0 || last == h.Number.Int64() { - last = h.Number.Int64() - 1 + if nextToCheck == 0 || nextToCheck == h.Number.Int64() { + nextToCheck = h.Number.Int64() } - if h.Number.Int64()-last > 100 { - log.Warn("Large gap between last seen and current block number, skipping check for reverts", "last", last, "current", h.Number) - last = h.Number.Int64() + if h.Number.Int64()-nextToCheck > 100 { + log.Warn("Large gap between last seen and current block number, skipping check for reverts", "last", nextToCheck, "current", h.Number) + nextToCheck = h.Number.Int64() continue } - reverted, err := b.checkReverts(ctx, last+1, h.Number.Int64()) + reverted, err := b.checkReverts(ctx, &nextToCheck, h.Number.Int64()) if err != nil { - log.Error("Checking batch reverts", "error", err) + logLevel := log.Error + if strings.Contains(err.Error(), "not found") { + // Just parent chain node inconsistency + // One node sent us a block, but another didn't have it + // We'll try to check this block again next loop + logLevel = log.Debug + } + logLevel("Error checking batch reverts", "err", err) continue } if reverted { b.batchReverted.Store(true) return } - last = h.Number.Int64() case <-ctx.Done(): return } From e9dd36a900545be953f38449bf57aa8317808e58 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 12 Sep 2023 12:18:13 -0600 Subject: [PATCH 133/775] Don't confirmDataPosterIsReady if watchtower --- staker/staker.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/staker/staker.go b/staker/staker.go index 8fdbbd648..1b6538b16 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -552,11 +552,11 @@ func (s *Staker) confirmDataPosterIsReady(ctx context.Context) error { } func (s *Staker) Act(ctx context.Context) (*types.Transaction, error) { - err := s.confirmDataPosterIsReady(ctx) - if err != nil { - return nil, err - } if s.config.strategy != WatchtowerStrategy { + err := s.confirmDataPosterIsReady(ctx) + if err != nil { + return nil, err + } whitelisted, err := s.IsWhitelisted(ctx) if err != nil { return nil, fmt.Errorf("error checking if whitelisted: %w", err) From dd00ab30d31609ca2ecb12041e8f0f8dad242b74 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 13 Sep 2023 00:57:41 +0000 Subject: [PATCH 134/775] fix db error checking taking pebble into account --- arbnode/dataposter/data_poster.go | 3 ++- arbnode/dataposter/leveldb/leveldb.go | 3 ++- arbnode/dataposter/storage_test.go | 12 +++++++++++- arbnode/transaction_streamer.go | 3 ++- cmd/nitro/nitro.go | 7 +++++-- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index b1e6555b2..cfcf69bb2 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -118,7 +118,7 @@ func NewDataPoster(db ethdb.Database, headerReader *headerreader.HeaderReader, a return nil, err } case initConfig.UseLevelDB: - queue = leveldb.New(db, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) + queue = leveldb.New(db, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) // TODO rename leveldb package default: queue = slice.NewStorage(func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) } @@ -649,6 +649,7 @@ func DataPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Float64(prefix+".max-tip-cap-gwei", DefaultDataPosterConfig.MaxTipCapGwei, "the maximum tip cap to post transactions at") f.Uint64(prefix+".nonce-rbf-soft-confs", DefaultDataPosterConfig.NonceRbfSoftConfs, "the maximum probable reorg depth, used to determine when a transaction will no longer likely need replaced-by-fee") f.Bool(prefix+".allocate-mempool-balance", DefaultDataPosterConfig.AllocateMempoolBalance, "if true, don't put transactions in the mempool that spend a total greater than the batch poster's balance") + // TODO rename use-leveldb to take pebble into account f.Bool(prefix+".use-leveldb", DefaultDataPosterConfig.UseLevelDB, "uses leveldb when enabled") f.Bool(prefix+".use-noop-storage", DefaultDataPosterConfig.UseNoOpStorage, "uses noop storage, it doesn't store anything") f.Bool(prefix+".legacy-storage-encoding", DefaultDataPosterConfig.LegacyStorageEncoding, "encodes items in a legacy way (as it was before dropping generics)") diff --git a/arbnode/dataposter/leveldb/leveldb.go b/arbnode/dataposter/leveldb/leveldb.go index cfb34b04f..ef694e940 100644 --- a/arbnode/dataposter/leveldb/leveldb.go +++ b/arbnode/dataposter/leveldb/leveldb.go @@ -10,6 +10,7 @@ import ( "fmt" "strconv" + "github.com/cockroachdb/pebble" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" @@ -175,5 +176,5 @@ func (s *Storage) IsPersistent() bool { } func isErrNotFound(err error) bool { - return errors.Is(err, leveldb.ErrNotFound) || errors.Is(err, memorydb.ErrMemorydbNotFound) + return errors.Is(err, leveldb.ErrNotFound) || errors.Is(err, pebble.ErrNotFound) || errors.Is(err, memorydb.ErrMemorydbNotFound) } diff --git a/arbnode/dataposter/storage_test.go b/arbnode/dataposter/storage_test.go index d536e5da0..cd96a5dde 100644 --- a/arbnode/dataposter/storage_test.go +++ b/arbnode/dataposter/storage_test.go @@ -36,7 +36,16 @@ func newLevelDBStorage(t *testing.T, encF storage.EncoderDecoderF) *leveldb.Stor if err != nil { t.Fatalf("NewLevelDBDatabase() unexpected error: %v", err) } - return leveldb.New(db, encF) + return leveldb.New(db, encF) // TODO rename leveldb package +} + +func newPebbleDBStorage(t *testing.T, encF storage.EncoderDecoderF) *leveldb.Storage { + t.Helper() + db, err := rawdb.NewPebbleDBDatabase(path.Join(t.TempDir(), "pebble.db"), 0, 0, "default", false) + if err != nil { + t.Fatalf("NewPebbleDBDatabase() unexpected error: %v", err) + } + return leveldb.New(db, encF) // TODO rename leveldb package } func newSliceStorage(encF storage.EncoderDecoderF) *slice.Storage { @@ -120,6 +129,7 @@ func storages(t *testing.T) map[string]QueueStorage { "sliceLegacy": newSliceStorage(f(&storage.LegacyEncoderDecoder{})), "redisLegacy": newRedisStorage(context.Background(), t, f(&storage.LegacyEncoderDecoder{})), "levelDB": newLevelDBStorage(t, f(&storage.EncoderDecoder{})), + "pebbleDB": newPebbleDBStorage(t, f(&storage.EncoderDecoder{})), "slice": newSliceStorage(f(&storage.EncoderDecoder{})), "redis": newRedisStorage(context.Background(), t, f(&storage.EncoderDecoder{})), } diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 0f514ba9c..4d1e542db 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -19,6 +19,7 @@ import ( "errors" + "github.com/cockroachdb/pebble" flag "github.com/spf13/pflag" "github.com/syndtr/goleveldb/leveldb" @@ -508,7 +509,7 @@ func (s *TransactionStreamer) AddBroadcastMessages(feedMessages []*broadcaster.B if broadcastStartPos > 0 { _, err := s.GetMessage(broadcastStartPos - 1) if err != nil { - if !errors.Is(err, leveldb.ErrNotFound) { + if !errors.Is(err, leveldb.ErrNotFound) && !errors.Is(err, pebble.ErrNotFound) { return err } // Message before current message doesn't exist in database, so don't add current messages yet diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 4ebe598ee..951b0e4cc 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -18,6 +18,7 @@ import ( "syscall" "time" + "github.com/cockroachdb/pebble" "github.com/knadh/koanf" "github.com/knadh/koanf/providers/confmap" flag "github.com/spf13/pflag" @@ -114,7 +115,7 @@ func closeDb(db io.Closer, name string) { if db != nil { err := db.Close() // unfortunately the freezer db means we can't just use errors.Is - if err != nil && !strings.Contains(err.Error(), leveldb.ErrClosed.Error()) { + if err != nil && !strings.Contains(err.Error(), leveldb.ErrClosed.Error()) && !strings.Contains(err.Error(), pebble.ErrClosed.Error()) { log.Warn("failed to close database on shutdown", "db", name, "err", err) } } @@ -158,7 +159,9 @@ func mainImpl() int { } stackConf := node.DefaultConfig stackConf.DataDir = nodeConfig.Persistent.Chain - stackConf.DBEngine = "leveldb" + // TODO add config option to choose DBEngine + // stackConf.DBEngine = "leveldb" + stackConf.DBEngine = "pebble" nodeConfig.HTTP.Apply(&stackConf) nodeConfig.WS.Apply(&stackConf) nodeConfig.Auth.Apply(&stackConf) From efc4fc134d97b55f9b5f2fd91a7fb1e8c1021f5a Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 13 Sep 2023 11:08:10 -0500 Subject: [PATCH 135/775] add new RPC GetL2BlockRangeForL1 to fetch L2 block range for L1 block number --- contracts | 2 +- go-ethereum | 2 +- nodeInterface/NodeInterface.go | 80 ++++++++++++++++++++++++++++++ system_tests/nodeinterface_test.go | 72 +++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 system_tests/nodeinterface_test.go diff --git a/contracts b/contracts index 97cfbe00f..accdcee45 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 97cfbe00ff0eea4d7f5f5f3afb01598c19ddabc4 +Subproject commit accdcee45798af5025836a04ee5bdcb0669cb476 diff --git a/go-ethereum b/go-ethereum index b4bd0da11..3f2e789b3 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit b4bd0da1142fe6bb81cac7e0794ebb4746b9885a +Subproject commit 3f2e789b3857ccdd647c319e16f1a00805d1d6bd diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index a36345866..3b743dbb2 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -590,3 +590,83 @@ func (n NodeInterface) LegacyLookupMessageBatchProof(c ctx, evm mech, batchNum h calldataForL1 = data return } + +func (n NodeInterface) getL1BlockNum(l2BlockNum uint64) (uint64, error) { + blockHeader, err := n.backend.HeaderByNumber(n.context, rpc.BlockNumber(l2BlockNum)) + if err != nil { + return 0, err + } + l1BlockNum := types.DeserializeHeaderExtraInformation(blockHeader).L1BlockNumber + return l1BlockNum, nil +} + +func (n NodeInterface) GetL2BlockRangeForL1(c ctx, evm mech, l1BlockNum uint64) ([]uint64, error) { + currentBlockNum := n.backend.CurrentBlock().Number.Uint64() + genesis := n.backend.ChainConfig().ArbitrumChainParams.GenesisBlockNum + + checkCorrectness := func(blockNum uint64, target uint64) error { + blockL1Num, err := n.getL1BlockNum(blockNum) + if err != nil { + return err + } + if blockL1Num != target { + return errors.New("no L2 block was found with the given L1 block number") + } + return nil + } + + lowFirstBlock := genesis + highFirstBlock := currentBlockNum + lowLastBlock := genesis + highLastBlock := currentBlockNum + var storedMid uint64 + var storedMidBlockL1Num uint64 + for lowFirstBlock < highFirstBlock || lowLastBlock < highLastBlock { + if lowFirstBlock < highFirstBlock { + mid := (lowFirstBlock + highFirstBlock) / 2 + midBlockL1Num, err := n.getL1BlockNum(mid) + if err != nil { + return nil, err + } + storedMid = mid + storedMidBlockL1Num = midBlockL1Num + if midBlockL1Num < l1BlockNum { + lowFirstBlock = mid + 1 + } else { + highFirstBlock = mid + } + } + if lowLastBlock < highLastBlock { + // dont fetch midBlockL1Num if its already fetched above + mid := (lowLastBlock + highLastBlock) / 2 + var midBlockL1Num uint64 + var err error + if mid == storedMid { + midBlockL1Num = storedMidBlockL1Num + } else { + midBlockL1Num, err = n.getL1BlockNum(mid) + if err != nil { + return nil, err + } + } + if midBlockL1Num < l1BlockNum+1 { + lowLastBlock = mid + 1 + } else { + highLastBlock = mid + } + } + } + err := checkCorrectness(highFirstBlock, l1BlockNum) + if err != nil { + return nil, err + } + err = checkCorrectness(highLastBlock, l1BlockNum) + if err != nil { + highLastBlock -= 1 + err = checkCorrectness(highLastBlock, l1BlockNum) + if err != nil { + return nil, err + } + } + return []uint64{highFirstBlock, highLastBlock}, nil +} diff --git a/system_tests/nodeinterface_test.go b/system_tests/nodeinterface_test.go new file mode 100644 index 000000000..266b50d6c --- /dev/null +++ b/system_tests/nodeinterface_test.go @@ -0,0 +1,72 @@ +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package arbtest + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/offchainlabs/nitro/arbos/util" + "github.com/offchainlabs/nitro/solgen/go/node_interfacegen" +) + +func getL1BlockNum(t *testing.T, ctx context.Context, client *ethclient.Client, l2BlockNum uint64) uint64 { + header, err := client.HeaderByNumber(ctx, big.NewInt(int64(l2BlockNum))) + Require(t, err) + l1BlockNum := types.DeserializeHeaderExtraInformation(header).L1BlockNumber + return l1BlockNum +} + +func TestGetL2BlockRangeForL1(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + l2info, node, l2client, l1info, _, _, l1stack := createTestNodeOnL1(t, ctx, true) + defer requireClose(t, l1stack) + defer node.StopAndWait() + user := l1info.GetDefaultTransactOpts("User", ctx) + + numTransactions := 30 + for i := 0; i < numTransactions; i++ { + TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), l2info, l2client, ctx) + } + + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) + Require(t, err) + + l1BlockNums := map[uint64][]uint64{} + latestL2, err := l2client.BlockNumber(ctx) + Require(t, err) + for l2BlockNum := uint64(0); l2BlockNum <= latestL2; l2BlockNum++ { + l1BlockNum := getL1BlockNum(t, ctx, l2client, l2BlockNum) + l1BlockNums[l1BlockNum] = append(l1BlockNums[l1BlockNum], l2BlockNum) + } + + // Test success + for l1BlockNum := range l1BlockNums { + rng, err := nodeInterface.GetL2BlockRangeForL1(&bind.CallOpts{}, l1BlockNum) + Require(t, err) + n := len(l1BlockNums[l1BlockNum]) + expected := []uint64{l1BlockNums[l1BlockNum][0], l1BlockNums[l1BlockNum][n-1]} + if expected[0] != rng[0] || expected[1] != rng[1] { + unexpectedL1BlockNum := getL1BlockNum(t, ctx, l2client, rng[1]) + // handle the edge case when new l2 blocks are produced between latestL2 was last calculated and now + if unexpectedL1BlockNum != l1BlockNum { + t.Fatalf("GetL2BlockRangeForL1 failed to get a valid range for L1 block number: %v. Given range: %v. Expected range: %v", l1BlockNum, rng, expected) + } + } + } + // Test invalid case + finalValidL1BlockNumber := getL1BlockNum(t, ctx, l2client, latestL2) + _, err = nodeInterface.GetL2BlockRangeForL1(&bind.CallOpts{}, finalValidL1BlockNumber+1) + if err == nil { + t.Fatalf("GetL2BlockRangeForL1 didn't fail for an invalid input") + } + +} From ff047501632ae86ae876451389de16e1c8419f1b Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 13 Sep 2023 16:28:32 +0000 Subject: [PATCH 136/775] add persistent.db-engine config option --- cmd/conf/database.go | 11 +++++++++++ cmd/nitro/nitro.go | 9 +++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/cmd/conf/database.go b/cmd/conf/database.go index 2ce3d74bc..dcd54784f 100644 --- a/cmd/conf/database.go +++ b/cmd/conf/database.go @@ -18,6 +18,7 @@ type PersistentConfig struct { LogDir string `koanf:"log-dir"` Handles int `koanf:"handles"` Ancient string `koanf:"ancient"` + DBEngine string `koanf:"db-engine"` } var PersistentConfigDefault = PersistentConfig{ @@ -26,6 +27,7 @@ var PersistentConfigDefault = PersistentConfig{ LogDir: "", Handles: 512, Ancient: "", + DBEngine: "leveldb", } func PersistentConfigAddOptions(prefix string, f *flag.FlagSet) { @@ -34,6 +36,7 @@ func PersistentConfigAddOptions(prefix string, f *flag.FlagSet) { f.String(prefix+".log-dir", PersistentConfigDefault.LogDir, "directory to store log file") f.Int(prefix+".handles", PersistentConfigDefault.Handles, "number of file descriptor handles to use for the database") f.String(prefix+".ancient", PersistentConfigDefault.Ancient, "directory of ancient where the chain freezer can be opened") + f.String(prefix+".db-engine", PersistentConfigDefault.DBEngine, "backing database implementation to use ('leveldb' or 'pebble')") } func (c *PersistentConfig) ResolveDirectoryNames() error { @@ -85,3 +88,11 @@ func DatabaseInDirectory(path string) bool { return err == nil } + +func (c *PersistentConfig) Validate() error { + // we are validating .db-engine here to avoid unintended behaviour as empty string value also has meaning in geth's node.Config.DBEngine + if c.DBEngine != "leveldb" && c.DBEngine != "pebble" { + return fmt.Errorf("Invalid .db-engine choice: \"%v\", allowed \"leveldb\" or \"pebble\"", c.DBEngine) + } + return nil +} diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 951b0e4cc..f2baa9ace 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -159,9 +159,7 @@ func mainImpl() int { } stackConf := node.DefaultConfig stackConf.DataDir = nodeConfig.Persistent.Chain - // TODO add config option to choose DBEngine - // stackConf.DBEngine = "leveldb" - stackConf.DBEngine = "pebble" + stackConf.DBEngine = nodeConfig.Persistent.DBEngine nodeConfig.HTTP.Apply(&stackConf) nodeConfig.WS.Apply(&stackConf) nodeConfig.Auth.Apply(&stackConf) @@ -673,7 +671,10 @@ func (c *NodeConfig) Validate() error { if err := c.ParentChain.Validate(); err != nil { return err } - return c.Node.Validate() + if err := c.Node.Validate(); err != nil { + return err + } + return c.Persistent.Validate() } func (c *NodeConfig) GetReloadInterval() time.Duration { From 176d7be4df2e227799355451b56c969aaff67b60 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 13 Sep 2023 11:01:32 -0600 Subject: [PATCH 137/775] Make batch revert nextToCheck a field --- arbnode/batch_poster.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 8144c9b7b..89a36eba9 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -76,7 +76,8 @@ type BatchPoster struct { backlog uint64 lastHitL1Bounds time.Time // The last time we wanted to post a message but hit the L1 bounds - batchReverted atomic.Bool // indicates whether data poster batch was reverted + batchReverted atomic.Bool // indicates whether data poster batch was reverted + nextRevertCheckBlock int64 // the last parent block scanned for reverting batches } type l1BlockBound int @@ -263,13 +264,12 @@ func NewBatchPoster(dataPosterDB ethdb.Database, l1Reader *headerreader.HeaderRe // contain reverted batch_poster transaction. // It returns true if it finds batch posting needs to halt, which is true if a batch reverts // unless the data poster is configured with noop storage which can tolerate reverts. -// From must be a pointer to the starting block, which is updated after each block is checked for reverts -func (b *BatchPoster) checkReverts(ctx context.Context, from *int64, to int64) (bool, error) { - if *from > to { - return false, fmt.Errorf("wrong range, from: %d > to: %d", from, to) +func (b *BatchPoster) checkReverts(ctx context.Context, to int64) (bool, error) { + if b.nextRevertCheckBlock > to { + return false, fmt.Errorf("wrong range, from: %d > to: %d", b.nextRevertCheckBlock, to) } - for ; *from <= to; *from++ { - number := big.NewInt(*from) + for ; b.nextRevertCheckBlock <= to; b.nextRevertCheckBlock++ { + number := big.NewInt(b.nextRevertCheckBlock) block, err := b.l1Reader.Client().BlockByNumber(ctx, number) if err != nil { return false, fmt.Errorf("getting block: %v by number: %w", number, err) @@ -305,7 +305,6 @@ func (b *BatchPoster) pollForReverts(ctx context.Context) { headerCh, unsubscribe := b.l1Reader.Subscribe(false) defer unsubscribe() - nextToCheck := int64(0) // the first unchecked block for { // Poll until: // - L1 headers reader channel is closed, or @@ -317,19 +316,20 @@ func (b *BatchPoster) pollForReverts(ctx context.Context) { log.Info("L1 headers channel checking for batch poster reverts has been closed") return } + blockNum := h.Number.Int64() // If this is the first block header, set last seen as number-1. // We may see same block number again if there is L1 reorg, in that // case we check the block again. - if nextToCheck == 0 || nextToCheck == h.Number.Int64() { - nextToCheck = h.Number.Int64() + if b.nextRevertCheckBlock == 0 || b.nextRevertCheckBlock > blockNum { + b.nextRevertCheckBlock = blockNum } - if h.Number.Int64()-nextToCheck > 100 { - log.Warn("Large gap between last seen and current block number, skipping check for reverts", "last", nextToCheck, "current", h.Number) - nextToCheck = h.Number.Int64() + if blockNum-b.nextRevertCheckBlock > 100 { + log.Warn("Large gap between last seen and current block number, skipping check for reverts", "last", b.nextRevertCheckBlock, "current", blockNum) + b.nextRevertCheckBlock = blockNum continue } - reverted, err := b.checkReverts(ctx, &nextToCheck, h.Number.Int64()) + reverted, err := b.checkReverts(ctx, blockNum) if err != nil { logLevel := log.Error if strings.Contains(err.Error(), "not found") { From 39480a0425ff76b4b743273004eb029f5d86aa51 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 13 Sep 2023 11:14:11 -0600 Subject: [PATCH 138/775] Reorder prechecker balance and conditional options checks --- arbnode/execution/tx_pre_checker.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arbnode/execution/tx_pre_checker.go b/arbnode/execution/tx_pre_checker.go index dc069a6d1..968a1f266 100644 --- a/arbnode/execution/tx_pre_checker.go +++ b/arbnode/execution/tx_pre_checker.go @@ -145,11 +145,6 @@ func PreCheckTx(bc *core.BlockChain, chainConfig *params.ChainConfig, header *ty if config.Strictness < TxPreCheckerStrictnessLikelyCompatible { return nil } - balance := statedb.GetBalance(sender) - cost := tx.Cost() - if arbmath.BigLessThan(balance, cost) { - return fmt.Errorf("%w: address %v have %v want %v", core.ErrInsufficientFunds, sender, balance, cost) - } if options != nil { if err := options.Check(extraInfo.L1BlockNumber, header.Time, statedb); err != nil { conditionalTxRejectedByTxPreCheckerCurrentStateCounter.Inc(1) @@ -185,6 +180,11 @@ func PreCheckTx(bc *core.BlockChain, chainConfig *params.ChainConfig, header *ty conditionalTxAcceptedByTxPreCheckerOldStateCounter.Inc(1) } } + balance := statedb.GetBalance(sender) + cost := tx.Cost() + if arbmath.BigLessThan(balance, cost) { + return fmt.Errorf("%w: address %v have %v want %v", core.ErrInsufficientFunds, sender, balance, cost) + } if config.Strictness >= TxPreCheckerStrictnessFullValidation && tx.Nonce() > stateNonce { return MakeNonceError(sender, tx.Nonce(), stateNonce) } From 2dc3009c6c55500b30a28e80edb049423ada69ef Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 13 Sep 2023 19:54:21 +0000 Subject: [PATCH 139/775] rename .data-poster.use-leveldb to .use-db-storage, rename dataposter/leveldb package --- arbnode/dataposter/data_poster.go | 15 +++++++-------- .../{leveldb/leveldb.go => dbstorage/storage.go} | 4 ++-- arbnode/dataposter/storage_test.go | 10 +++++----- 3 files changed, 14 insertions(+), 15 deletions(-) rename arbnode/dataposter/{leveldb/leveldb.go => dbstorage/storage.go} (98%) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index cfcf69bb2..41952bbd8 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -21,7 +21,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "github.com/go-redis/redis/v8" - "github.com/offchainlabs/nitro/arbnode/dataposter/leveldb" + "github.com/offchainlabs/nitro/arbnode/dataposter/dbstorage" "github.com/offchainlabs/nitro/arbnode/dataposter/noop" "github.com/offchainlabs/nitro/arbnode/dataposter/slice" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" @@ -117,8 +117,8 @@ func NewDataPoster(db ethdb.Database, headerReader *headerreader.HeaderReader, a if err != nil { return nil, err } - case initConfig.UseLevelDB: - queue = leveldb.New(db, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) // TODO rename leveldb package + case initConfig.UseDBStorage: + queue = dbstorage.New(db, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) default: queue = slice.NewStorage(func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) } @@ -628,7 +628,7 @@ type DataPosterConfig struct { MaxTipCapGwei float64 `koanf:"max-tip-cap-gwei" reload:"hot"` NonceRbfSoftConfs uint64 `koanf:"nonce-rbf-soft-confs" reload:"hot"` AllocateMempoolBalance bool `koanf:"allocate-mempool-balance" reload:"hot"` - UseLevelDB bool `koanf:"use-leveldb"` + UseDBStorage bool `koanf:"use-db-storage"` UseNoOpStorage bool `koanf:"use-noop-storage"` LegacyStorageEncoding bool `koanf:"legacy-storage-encoding" reload:"hot"` } @@ -649,8 +649,7 @@ func DataPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Float64(prefix+".max-tip-cap-gwei", DefaultDataPosterConfig.MaxTipCapGwei, "the maximum tip cap to post transactions at") f.Uint64(prefix+".nonce-rbf-soft-confs", DefaultDataPosterConfig.NonceRbfSoftConfs, "the maximum probable reorg depth, used to determine when a transaction will no longer likely need replaced-by-fee") f.Bool(prefix+".allocate-mempool-balance", DefaultDataPosterConfig.AllocateMempoolBalance, "if true, don't put transactions in the mempool that spend a total greater than the batch poster's balance") - // TODO rename use-leveldb to take pebble into account - f.Bool(prefix+".use-leveldb", DefaultDataPosterConfig.UseLevelDB, "uses leveldb when enabled") + f.Bool(prefix+".use-db-storage", DefaultDataPosterConfig.UseDBStorage, "uses database storage when enabled") f.Bool(prefix+".use-noop-storage", DefaultDataPosterConfig.UseNoOpStorage, "uses noop storage, it doesn't store anything") f.Bool(prefix+".legacy-storage-encoding", DefaultDataPosterConfig.LegacyStorageEncoding, "encodes items in a legacy way (as it was before dropping generics)") signature.SimpleHmacConfigAddOptions(prefix+".redis-signer", f) @@ -666,7 +665,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ MaxTipCapGwei: 5, NonceRbfSoftConfs: 1, AllocateMempoolBalance: true, - UseLevelDB: true, + UseDBStorage: true, UseNoOpStorage: false, LegacyStorageEncoding: true, } @@ -688,7 +687,7 @@ var TestDataPosterConfig = DataPosterConfig{ MaxTipCapGwei: 5, NonceRbfSoftConfs: 1, AllocateMempoolBalance: true, - UseLevelDB: false, + UseDBStorage: false, UseNoOpStorage: false, } diff --git a/arbnode/dataposter/leveldb/leveldb.go b/arbnode/dataposter/dbstorage/storage.go similarity index 98% rename from arbnode/dataposter/leveldb/leveldb.go rename to arbnode/dataposter/dbstorage/storage.go index ef694e940..be4c24b5a 100644 --- a/arbnode/dataposter/leveldb/leveldb.go +++ b/arbnode/dataposter/dbstorage/storage.go @@ -1,7 +1,7 @@ // Copyright 2021-2023, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package leveldb +package dbstorage import ( "bytes" @@ -17,7 +17,7 @@ import ( "github.com/syndtr/goleveldb/leveldb" ) -// Storage implements leveldb based storage for batch poster. +// Storage implements db based storage for batch poster. type Storage struct { db ethdb.Database encDec storage.EncoderDecoderF diff --git a/arbnode/dataposter/storage_test.go b/arbnode/dataposter/storage_test.go index cd96a5dde..4d8c87b85 100644 --- a/arbnode/dataposter/storage_test.go +++ b/arbnode/dataposter/storage_test.go @@ -12,7 +12,7 @@ import ( "github.com/ethereum/go-ethereum/rlp" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/offchainlabs/nitro/arbnode/dataposter/leveldb" + "github.com/offchainlabs/nitro/arbnode/dataposter/dbstorage" "github.com/offchainlabs/nitro/arbnode/dataposter/redis" "github.com/offchainlabs/nitro/arbnode/dataposter/slice" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" @@ -30,22 +30,22 @@ var ignoreData = cmp.Options{ cmpopts.IgnoreFields(types.Transaction{}, "hash", "size", "from"), } -func newLevelDBStorage(t *testing.T, encF storage.EncoderDecoderF) *leveldb.Storage { +func newLevelDBStorage(t *testing.T, encF storage.EncoderDecoderF) *dbstorage.Storage { t.Helper() db, err := rawdb.NewLevelDBDatabase(path.Join(t.TempDir(), "level.db"), 0, 0, "default", false) if err != nil { t.Fatalf("NewLevelDBDatabase() unexpected error: %v", err) } - return leveldb.New(db, encF) // TODO rename leveldb package + return dbstorage.New(db, encF) } -func newPebbleDBStorage(t *testing.T, encF storage.EncoderDecoderF) *leveldb.Storage { +func newPebbleDBStorage(t *testing.T, encF storage.EncoderDecoderF) *dbstorage.Storage { t.Helper() db, err := rawdb.NewPebbleDBDatabase(path.Join(t.TempDir(), "pebble.db"), 0, 0, "default", false) if err != nil { t.Fatalf("NewPebbleDBDatabase() unexpected error: %v", err) } - return leveldb.New(db, encF) // TODO rename leveldb package + return dbstorage.New(db, encF) } func newSliceStorage(encF storage.EncoderDecoderF) *slice.Storage { From bf0c01a1e98a846801288d1893f3a171ff96cb35 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 13 Sep 2023 15:27:04 -0500 Subject: [PATCH 140/775] fix failing test --- cmd/deploy/deploy.go | 5 ++++- system_tests/common_test.go | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cmd/deploy/deploy.go b/cmd/deploy/deploy.go index 17725a7a4..3e698749d 100644 --- a/cmd/deploy/deploy.go +++ b/cmd/deploy/deploy.go @@ -14,10 +14,12 @@ import ( "github.com/offchainlabs/nitro/cmd/chaininfo" "github.com/offchainlabs/nitro/cmd/genericconf" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/validator/server_common" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -127,7 +129,8 @@ func main() { panic(fmt.Errorf("failed to deserialize chain config: %w", err)) } - l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerReaderConfig }) + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) + l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerReaderConfig }, arbSys, true) if err != nil { panic(fmt.Errorf("failed to create header reader: %w", err)) } diff --git a/system_tests/common_test.go b/system_tests/common_test.go index b92fbf757..a643b1b71 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -476,7 +476,8 @@ func DeployOnTestL1( serializedChainConfig, err := json.Marshal(chainConfig) Require(t, err) - l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }) + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) + l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }, arbSys, true) Require(t, err) l1Reader.Start(ctx) defer l1Reader.StopAndWait() From 6a9fd710cd6611ec6adcdadc56f8307afe13ecce Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 13 Sep 2023 19:42:33 -0500 Subject: [PATCH 141/775] revert impl --- arbnode/node.go | 2 +- cmd/daserver/daserver.go | 2 +- cmd/deploy/deploy.go | 2 +- cmd/nitro/nitro.go | 2 +- system_tests/common_test.go | 2 +- system_tests/das_test.go | 2 +- util/headerreader/header_reader.go | 11 +++++------ 7 files changed, 11 insertions(+), 12 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index a40c84fa9..5bdc71626 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -606,7 +606,7 @@ func createNodeImpl( var l1Reader *headerreader.HeaderReader if config.ParentChainReader.Enable { arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) - l1Reader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher.Get().ParentChainReader }, arbSys, true) + l1Reader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher.Get().ParentChainReader }, arbSys) if err != nil { return nil, err } diff --git a/cmd/daserver/daserver.go b/cmd/daserver/daserver.go index 6b874f463..335aba6a1 100644 --- a/cmd/daserver/daserver.go +++ b/cmd/daserver/daserver.go @@ -199,7 +199,7 @@ func startup() error { return err } arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1Client) - l1Reader, err = headerreader.New(ctx, l1Client, func() *headerreader.Config { return &headerreader.DefaultConfig }, arbSys, true) // TODO: config + l1Reader, err = headerreader.New(ctx, l1Client, func() *headerreader.Config { return &headerreader.DefaultConfig }, arbSys) // TODO: config if err != nil { return err } diff --git a/cmd/deploy/deploy.go b/cmd/deploy/deploy.go index 3e698749d..d687821e8 100644 --- a/cmd/deploy/deploy.go +++ b/cmd/deploy/deploy.go @@ -130,7 +130,7 @@ func main() { } arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) - l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerReaderConfig }, arbSys, true) + l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerReaderConfig }, arbSys) if err != nil { panic(fmt.Errorf("failed to create header reader: %w", err)) } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index f2cb3a37d..a7dc7f26f 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -357,7 +357,7 @@ func mainImpl() int { log.Crit("--node.validator.only-create-wallet-contract requires --node.validator.use-smart-contract-wallet") } arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1Client) - l1Reader, err := headerreader.New(ctx, l1Client, func() *headerreader.Config { return &liveNodeConfig.Get().Node.ParentChainReader }, arbSys, true) + l1Reader, err := headerreader.New(ctx, l1Client, func() *headerreader.Config { return &liveNodeConfig.Get().Node.ParentChainReader }, arbSys) if err != nil { log.Crit("failed to get L1 headerreader", "error", err) } diff --git a/system_tests/common_test.go b/system_tests/common_test.go index a643b1b71..9fd002bd9 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -477,7 +477,7 @@ func DeployOnTestL1( Require(t, err) arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) - l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }, arbSys, true) + l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }, arbSys) Require(t, err) l1Reader.Start(ctx) defer l1Reader.StopAndWait() diff --git a/system_tests/das_test.go b/system_tests/das_test.go index e79b993d0..8889d2d53 100644 --- a/system_tests/das_test.go +++ b/system_tests/das_test.go @@ -235,7 +235,7 @@ func TestDASComplexConfigAndRestMirror(t *testing.T) { l1info, l1client, _, l1stack := createTestL1BlockChain(t, nil) defer requireClose(t, l1stack) arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) - l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }, arbSys, true) + l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }, arbSys) Require(t, err) l1Reader.Start(ctx) defer l1Reader.StopAndWait() diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index c7fa93738..befd54ace 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -94,25 +94,24 @@ var TestConfig = Config{ UseFinalityData: false, } -func New(ctx context.Context, client arbutil.L1Interface, config ConfigFetcher, arbSysPrecompile ArbSysInterface, usePrecompilesgen bool) (*HeaderReader, error) { +func New(ctx context.Context, client arbutil.L1Interface, config ConfigFetcher, arbSysPrecompile ArbSysInterface) (*HeaderReader, error) { isParentChainArbitrum := false - if usePrecompilesgen { + var arbSys ArbSysInterface + if arbSysPrecompile != nil { codeAt, err := client.CodeAt(ctx, types.ArbSysAddress, nil) if err != nil { return nil, err } if len(codeAt) != 0 { isParentChainArbitrum = true - if arbSysPrecompile == nil { - return nil, errors.New("unable to create ArbSys from precompilesgen") - } + arbSys = arbSysPrecompile } } return &HeaderReader{ client: client, config: config, isParentChainArbitrum: isParentChainArbitrum, - arbSys: arbSysPrecompile, + arbSys: arbSys, outChannels: make(map[chan<- *types.Header]struct{}), outChannelsBehind: make(map[chan<- *types.Header]struct{}), safe: cachedHeader{rpcBlockNum: big.NewInt(rpc.SafeBlockNumber.Int64())}, From aa3023e859594cdb3b9e867544cf1abda86af405 Mon Sep 17 00:00:00 2001 From: Nodar Date: Fri, 15 Sep 2023 16:18:51 +0200 Subject: [PATCH 142/775] Allow using different redis keys for dataposter --- arbnode/batch_poster.go | 13 ++++++++++- arbnode/dataposter/data_poster.go | 39 ++++++++++++++++++++----------- arbnode/node.go | 12 +++++++++- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 89a36eba9..a96f569be 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -253,7 +253,18 @@ func NewBatchPoster(dataPosterDB ethdb.Database, l1Reader *headerreader.HeaderRe dataPosterConfigFetcher := func() *dataposter.DataPosterConfig { return &config().DataPoster } - b.dataPoster, err = dataposter.NewDataPoster(dataPosterDB, l1Reader, transactOpts, redisClient, redisLock, dataPosterConfigFetcher, b.getBatchPosterPosition) + b.dataPoster, err = dataposter.NewDataPoster( + &dataposter.DataPosterOpts{ + Database: dataPosterDB, + HeaderReader: l1Reader, + Auth: transactOpts, + RedisClient: redisClient, + RedisLock: redisLock, + Config: dataPosterConfigFetcher, + MetadataRetriever: b.getBatchPosterPosition, + RedisKey: "data-poster.queue", + }, + ) if err != nil { return nil, err } diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index b1e6555b2..d9e10b243 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -91,18 +91,29 @@ func parseReplacementTimes(val string) ([]time.Duration, error) { return append(res, time.Hour*24*365*10), nil } -func NewDataPoster(db ethdb.Database, headerReader *headerreader.HeaderReader, auth *bind.TransactOpts, redisClient redis.UniversalClient, redisLock AttemptLocker, config ConfigFetcher, metadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error)) (*DataPoster, error) { - initConfig := config() +type DataPosterOpts struct { + Database ethdb.Database + HeaderReader *headerreader.HeaderReader + Auth *bind.TransactOpts + RedisClient redis.UniversalClient + RedisLock AttemptLocker + Config ConfigFetcher + MetadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error) + RedisKey string // Redis storage key +} + +func NewDataPoster(opts *DataPosterOpts) (*DataPoster, error) { + initConfig := opts.Config() replacementTimes, err := parseReplacementTimes(initConfig.ReplacementTimes) if err != nil { return nil, err } - if headerReader.IsParentChainArbitrum() && !initConfig.UseNoOpStorage { + if opts.HeaderReader.IsParentChainArbitrum() && !initConfig.UseNoOpStorage { initConfig.UseNoOpStorage = true log.Info("Disabling data poster storage, as parent chain appears to be an Arbitrum chain without a mempool") } encF := func() storage.EncoderDecoderInterface { - if config().LegacyStorageEncoding { + if opts.Config().LegacyStorageEncoding { return &storage.LegacyEncoderDecoder{} } return &storage.EncoderDecoder{} @@ -111,27 +122,27 @@ func NewDataPoster(db ethdb.Database, headerReader *headerreader.HeaderReader, a switch { case initConfig.UseNoOpStorage: queue = &noop.Storage{} - case redisClient != nil: + case opts.RedisClient != nil: var err error - queue, err = redisstorage.NewStorage(redisClient, "data-poster.queue", &initConfig.RedisSigner, encF) + queue, err = redisstorage.NewStorage(opts.RedisClient, opts.RedisKey, &initConfig.RedisSigner, encF) if err != nil { return nil, err } case initConfig.UseLevelDB: - queue = leveldb.New(db, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) + queue = leveldb.New(opts.Database, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) default: queue = slice.NewStorage(func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) } return &DataPoster{ - headerReader: headerReader, - client: headerReader.Client(), - sender: auth.From, - signer: auth.Signer, - config: config, + headerReader: opts.HeaderReader, + client: opts.HeaderReader.Client(), + sender: opts.Auth.From, + signer: opts.Auth.Signer, + config: opts.Config, replacementTimes: replacementTimes, - metadataRetriever: metadataRetriever, + metadataRetriever: opts.MetadataRetriever, queue: queue, - redisLock: redisLock, + redisLock: opts.RedisLock, errorCount: make(map[uint64]int), }, nil } diff --git a/arbnode/node.go b/arbnode/node.go index 5bdc71626..3fc1f556f 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -564,7 +564,17 @@ func StakerDataposter( dpCfg := func() *dataposter.DataPosterConfig { return &cfg.Staker.DataPoster } - return dataposter.NewDataPoster(db, l1Reader, transactOpts, redisC, redisLock, dpCfg, mdRetriever) + return dataposter.NewDataPoster( + &dataposter.DataPosterOpts{ + Database: db, + HeaderReader: l1Reader, + Auth: transactOpts, + RedisClient: redisC, + RedisLock: redisLock, + Config: dpCfg, + MetadataRetriever: mdRetriever, + RedisKey: "staker-data-poster.queue", + }) } func createNodeImpl( From e2ed2e89a928936451378f88157e11ab76c68e63 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 15 Sep 2023 10:03:03 -0600 Subject: [PATCH 143/775] Fix chain id logged in missing field warning --- cmd/nitro/nitro.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index a7dc7f26f..47fafba2e 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -774,7 +774,7 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c if chainInfo.ParentChainIsArbitrum != nil { parentChainIsArbitrum = *chainInfo.ParentChainIsArbitrum } else { - log.Warn("Chain information parentChainIsArbitrum field missing, in the future this will be required", "chainId", chainId, "parentChainId", chainInfo.ParentChainId) + log.Warn("Chain information parentChainIsArbitrum field missing, in the future this will be required", "chainId", chainInfo.ChainConfig.ChainID, "parentChainId", chainInfo.ParentChainId) _, err := chaininfo.ProcessChainInfo(chainInfo.ParentChainId, "", combinedL2ChainInfoFiles, "") if err == nil { parentChainIsArbitrum = true From 6228940f9cb3473d084071ab9505a6275e0525bb Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 15 Sep 2023 13:18:38 -0500 Subject: [PATCH 144/775] add methods to configure brotli compression level in ArbOS 12 --- arbcompress/compress_common.go | 5 ++- arbcompress/compress_test.go | 2 +- arbitrator/prover/test-cases/go/main.go | 3 +- arbos/arbosState/arbosstate.go | 3 ++ arbos/l1pricing/l1pricing.go | 41 +++++++++++++++++++------ contracts | 2 +- precompiles/ArbOwner.go | 4 +++ precompiles/ArbOwnerPublic.go | 5 +++ precompiles/precompile.go | 2 ++ system_tests/fees_test.go | 2 +- system_tests/state_fuzz_test.go | 3 +- 11 files changed, 55 insertions(+), 17 deletions(-) diff --git a/arbcompress/compress_common.go b/arbcompress/compress_common.go index 6b66fe302..7d3976d56 100644 --- a/arbcompress/compress_common.go +++ b/arbcompress/compress_common.go @@ -3,7 +3,6 @@ package arbcompress -const LEVEL_FAST = 0 const LEVEL_WELL = 11 const WINDOW_SIZE = 22 // BROTLI_DEFAULT_WINDOW @@ -11,6 +10,6 @@ func compressedBufferSizeFor(length int) int { return length + (length>>10)*8 + 64 // actual limit is: length + (length >> 14) * 4 + 6 } -func CompressFast(input []byte) ([]byte, error) { - return compressLevel(input, LEVEL_FAST) +func CompressFast(input []byte, level int) ([]byte, error) { + return compressLevel(input, level) } diff --git a/arbcompress/compress_test.go b/arbcompress/compress_test.go index fffcda892..88e7eb4eb 100644 --- a/arbcompress/compress_test.go +++ b/arbcompress/compress_test.go @@ -27,7 +27,7 @@ func testCompressDecompress(t *testing.T, data []byte) { } testDecompress(t, compressedWell, data) - compressedFast, err := CompressFast(data) + compressedFast, err := CompressFast(data, 0) if err != nil { t.Fatal(err) } diff --git a/arbitrator/prover/test-cases/go/main.go b/arbitrator/prover/test-cases/go/main.go index a5a1028fb..8df8b2255 100644 --- a/arbitrator/prover/test-cases/go/main.go +++ b/arbitrator/prover/test-cases/go/main.go @@ -13,6 +13,7 @@ import ( merkletree "github.com/wealdtech/go-merkletree" "github.com/offchainlabs/nitro/arbcompress" + "github.com/offchainlabs/nitro/arbos/l1pricing" ) // MerkleSample is an example using the Merkle tree to generate and verify proofs. @@ -42,7 +43,7 @@ func MerkleSample(data [][]byte, toproove int) (bool, error) { } func testCompression(data []byte) { - compressed, err := arbcompress.CompressFast(data) + compressed, err := arbcompress.CompressFast(data, l1pricing.InitialBrotliCompressionLevel) if err != nil { panic(err) } diff --git a/arbos/arbosState/arbosstate.go b/arbos/arbosState/arbosstate.go index 48e29e121..0be5e51f8 100644 --- a/arbos/arbosState/arbosstate.go +++ b/arbos/arbosState/arbosstate.go @@ -318,6 +318,9 @@ func (state *ArbosState) UpgradeArbosVersion( if !firstTime { ensure(state.chainOwners.ClearList()) } + case 11: + // Update Brotli compression level for fast compression from 0 to 1 + ensure(state.l1PricingState.SetBrotliCompressionLevel(1)) default: return fmt.Errorf( "the chain is upgrading to unsupported ArbOS version %v, %w", diff --git a/arbos/l1pricing/l1pricing.go b/arbos/l1pricing/l1pricing.go index 34d6021f0..6f90a9e3b 100644 --- a/arbos/l1pricing/l1pricing.go +++ b/arbos/l1pricing/l1pricing.go @@ -36,8 +36,9 @@ type L1PricingState struct { inertia storage.StorageBackedUint64 perUnitReward storage.StorageBackedUint64 // variables - lastUpdateTime storage.StorageBackedUint64 // timestamp of the last update from L1 that we processed - fundsDueForRewards storage.StorageBackedBigInt + lastUpdateTime storage.StorageBackedUint64 // timestamp of the last update from L1 that we processed + fundsDueForRewards storage.StorageBackedBigInt + brotliCompressionLevel storage.StorageBackedUint64 // brotli compression level used for pricing // funds collected since update are recorded as the balance in account L1PricerFundsPoolAddress unitsSinceUpdate storage.StorageBackedUint64 // calldata units collected for since last update pricePerUnit storage.StorageBackedBigUint // current price per calldata unit @@ -63,6 +64,7 @@ const ( perUnitRewardOffset lastUpdateTimeOffset fundsDueForRewardsOffset + brotliCompressionLevelOffset unitsSinceOffset pricePerUnitOffset lastSurplusOffset @@ -72,10 +74,11 @@ const ( ) const ( - InitialInertia = 10 - InitialPerUnitReward = 10 - InitialPerBatchGasCostV6 = 100_000 - InitialPerBatchGasCostV12 = 210_000 // overriden as part of the upgrade + InitialInertia = 10 + InitialPerUnitReward = 10 + InitialPerBatchGasCostV6 = 100_000 + InitialPerBatchGasCostV12 = 210_000 // overriden as part of the upgrade + InitialBrotliCompressionLevel = 0 ) // one minute at 100000 bytes / sec @@ -112,6 +115,10 @@ func InitializeL1PricingState(sto *storage.Storage, initialRewardsRecipient comm if err := pricePerUnit.SetSaturatingWithWarning(initialL1BaseFee, "initial L1 base fee (storing in price per unit)"); err != nil { return err } + brotliCompressionLevel := sto.OpenStorageBackedInt64(brotliCompressionLevelOffset) + if err := brotliCompressionLevel.Set(InitialBrotliCompressionLevel); err != nil { + return err + } return nil } @@ -125,6 +132,7 @@ func OpenL1PricingState(sto *storage.Storage) *L1PricingState { sto.OpenStorageBackedUint64(perUnitRewardOffset), sto.OpenStorageBackedUint64(lastUpdateTimeOffset), sto.OpenStorageBackedBigInt(fundsDueForRewardsOffset), + sto.OpenStorageBackedUint64(brotliCompressionLevelOffset), sto.OpenStorageBackedUint64(unitsSinceOffset), sto.OpenStorageBackedBigUint(pricePerUnitOffset), sto.OpenStorageBackedBigInt(lastSurplusOffset), @@ -254,6 +262,17 @@ func (ps *L1PricingState) SetL1FeesAvailable(val *big.Int) error { return ps.l1FeesAvailable.SetChecked(val) } +func (ps *L1PricingState) BrotliCompressionLevel() (uint64, error) { + return ps.brotliCompressionLevel.Get() +} + +func (ps *L1PricingState) SetBrotliCompressionLevel(val uint64) error { + if val <= arbcompress.LEVEL_WELL { + return ps.brotliCompressionLevel.Set(val) + } + return errors.New("invalid brotli compression level") +} + func (ps *L1PricingState) AddToL1FeesAvailable(delta *big.Int) (*big.Int, error) { old, err := ps.L1FeesAvailable() if err != nil { @@ -500,7 +519,11 @@ func (ps *L1PricingState) getPosterUnitsWithoutCache(tx *types.Transaction, post return 0 } - l1Bytes, err := byteCountAfterBrotli0(txBytes) + level, err := ps.BrotliCompressionLevel() + if err != nil { + panic(fmt.Sprintf("failed to get brotli compression level: %v", err)) + } + l1Bytes, err := byteCountAfterBrotliLevel(txBytes, int(level)) if err != nil { panic(fmt.Sprintf("failed to compress tx: %v", err)) } @@ -585,8 +608,8 @@ func (ps *L1PricingState) PosterDataCost(message *core.Message, poster common.Ad return am.BigMulByUint(pricePerUnit, units), units } -func byteCountAfterBrotli0(input []byte) (uint64, error) { - compressed, err := arbcompress.CompressFast(input) +func byteCountAfterBrotliLevel(input []byte, level int) (uint64, error) { + compressed, err := arbcompress.CompressFast(input, level) if err != nil { return 0, err } diff --git a/contracts b/contracts index 97cfbe00f..55d096e21 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 97cfbe00ff0eea4d7f5f5f3afb01598c19ddabc4 +Subproject commit 55d096e219f352344bb7ba87ad66228f708d0a7a diff --git a/precompiles/ArbOwner.go b/precompiles/ArbOwner.go index 1abf1d0d0..2384bfbd8 100644 --- a/precompiles/ArbOwner.go +++ b/precompiles/ArbOwner.go @@ -142,6 +142,10 @@ func (con ArbOwner) SetAmortizedCostCapBips(c ctx, evm mech, cap uint64) error { return c.State.L1PricingState().SetAmortizedCostCapBips(cap) } +func (con ArbOwner) SetBrotliCompressionLevel(c ctx, evm mech, level uint64) error { + return c.State.L1PricingState().SetBrotliCompressionLevel(level) +} + func (con ArbOwner) ReleaseL1PricerSurplusFunds(c ctx, evm mech, maxWeiToRelease huge) (huge, error) { balance := evm.StateDB.GetBalance(l1pricing.L1PricerFundsPoolAddress) l1p := c.State.L1PricingState() diff --git a/precompiles/ArbOwnerPublic.go b/precompiles/ArbOwnerPublic.go index fb4326b1c..3952f221d 100644 --- a/precompiles/ArbOwnerPublic.go +++ b/precompiles/ArbOwnerPublic.go @@ -47,3 +47,8 @@ func (con ArbOwnerPublic) GetInfraFeeAccount(c ctx, evm mech) (addr, error) { } return c.State.InfraFeeAccount() } + +// GetBrotliCompressionLevel gets the current brotli compression level used for fast compression +func (con ArbOwnerPublic) GetBrotliCompressionLevel(c ctx, evm mech) (uint64, error) { + return c.State.L1PricingState().BrotliCompressionLevel() +} diff --git a/precompiles/precompile.go b/precompiles/precompile.go index a91756e63..77102a95b 100644 --- a/precompiles/precompile.go +++ b/precompiles/precompile.go @@ -554,6 +554,7 @@ func Precompiles() map[addr]ArbosPrecompile { ArbOwnerPublic := insert(MakePrecompile(templates.ArbOwnerPublicMetaData, &ArbOwnerPublic{Address: hex("6b")})) ArbOwnerPublic.methodsByName["GetInfraFeeAccount"].arbosVersion = 5 ArbOwnerPublic.methodsByName["RectifyChainOwner"].arbosVersion = 11 + ArbOwnerPublic.methodsByName["GetBrotliCompressionLevel"].arbosVersion = 12 ArbRetryableImpl := &ArbRetryableTx{Address: types.ArbRetryableTxAddress} ArbRetryable := insert(MakePrecompile(templates.ArbRetryableTxMetaData, ArbRetryableImpl)) @@ -589,6 +590,7 @@ func Precompiles() map[addr]ArbosPrecompile { ArbOwner.methodsByName["SetInfraFeeAccount"].arbosVersion = 5 ArbOwner.methodsByName["ReleaseL1PricerSurplusFunds"].arbosVersion = 10 ArbOwner.methodsByName["SetChainConfig"].arbosVersion = 11 + ArbOwner.methodsByName["SetBrotliCompressionLevel"].arbosVersion = 12 insert(ownerOnly(ArbOwnerImpl.Address, ArbOwner, emitOwnerActs)) insert(debugOnly(MakePrecompile(templates.ArbDebugMetaData, &ArbDebug{Address: hex("ff")}))) diff --git a/system_tests/fees_test.go b/system_tests/fees_test.go index bdd998357..21e326e65 100644 --- a/system_tests/fees_test.go +++ b/system_tests/fees_test.go @@ -303,7 +303,7 @@ func TestSequencerPriceAdjustsFrom25Gwei(t *testing.T) { func compressedTxSize(t *testing.T, tx *types.Transaction) uint64 { txBin, err := tx.MarshalBinary() Require(t, err) - compressed, err := arbcompress.CompressFast(txBin) + compressed, err := arbcompress.CompressFast(txBin, l1pricing.InitialBrotliCompressionLevel) Require(t, err) return uint64(len(compressed)) } diff --git a/system_tests/state_fuzz_test.go b/system_tests/state_fuzz_test.go index a8209499d..17aad870d 100644 --- a/system_tests/state_fuzz_test.go +++ b/system_tests/state_fuzz_test.go @@ -24,6 +24,7 @@ import ( "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/arbos/arbosState" "github.com/offchainlabs/nitro/arbos/arbostypes" + "github.com/offchainlabs/nitro/arbos/l1pricing" "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbstate" "github.com/offchainlabs/nitro/statetransfer" @@ -174,7 +175,7 @@ func FuzzStateTransition(f *testing.F) { binary.BigEndian.PutUint64(seqBatch[32:40], uint64(len(delayedMessages))) if compressSeqMsg { seqBatch = append(seqBatch, arbstate.BrotliMessageHeaderByte) - seqMsgCompressed, err := arbcompress.CompressFast(seqMsg) + seqMsgCompressed, err := arbcompress.CompressFast(seqMsg, l1pricing.InitialBrotliCompressionLevel) if err != nil { panic(fmt.Sprintf("failed to compress sequencer message: %v", err)) } From 3941ebc9e07bca3f5be9a9c3abe2816b8665312b Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 15 Sep 2023 14:02:42 -0500 Subject: [PATCH 145/775] fix overflow possibility --- nodeInterface/NodeInterface.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index 3b743dbb2..92ed2064c 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -623,7 +623,7 @@ func (n NodeInterface) GetL2BlockRangeForL1(c ctx, evm mech, l1BlockNum uint64) var storedMidBlockL1Num uint64 for lowFirstBlock < highFirstBlock || lowLastBlock < highLastBlock { if lowFirstBlock < highFirstBlock { - mid := (lowFirstBlock + highFirstBlock) / 2 + mid := arbmath.SaturatingUAdd(lowFirstBlock, highFirstBlock) / 2 midBlockL1Num, err := n.getL1BlockNum(mid) if err != nil { return nil, err @@ -638,7 +638,7 @@ func (n NodeInterface) GetL2BlockRangeForL1(c ctx, evm mech, l1BlockNum uint64) } if lowLastBlock < highLastBlock { // dont fetch midBlockL1Num if its already fetched above - mid := (lowLastBlock + highLastBlock) / 2 + mid := arbmath.SaturatingUAdd(lowLastBlock, highLastBlock) / 2 var midBlockL1Num uint64 var err error if mid == storedMid { From bc52aad3a4486ead6c5db4e90d37789763764aef Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 15 Sep 2023 14:37:34 -0500 Subject: [PATCH 146/775] fix error --- arbos/l1pricing/l1pricing.go | 2 +- contracts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arbos/l1pricing/l1pricing.go b/arbos/l1pricing/l1pricing.go index 6f90a9e3b..b9b9761b0 100644 --- a/arbos/l1pricing/l1pricing.go +++ b/arbos/l1pricing/l1pricing.go @@ -115,7 +115,7 @@ func InitializeL1PricingState(sto *storage.Storage, initialRewardsRecipient comm if err := pricePerUnit.SetSaturatingWithWarning(initialL1BaseFee, "initial L1 base fee (storing in price per unit)"); err != nil { return err } - brotliCompressionLevel := sto.OpenStorageBackedInt64(brotliCompressionLevelOffset) + brotliCompressionLevel := sto.OpenStorageBackedUint64(brotliCompressionLevelOffset) if err := brotliCompressionLevel.Set(InitialBrotliCompressionLevel); err != nil { return err } diff --git a/contracts b/contracts index 55d096e21..bb2ca5313 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 55d096e219f352344bb7ba87ad66228f708d0a7a +Subproject commit bb2ca53132116a59386b5f5010e711f485162c13 From fa69b19e3b69258d516df4b5d0b8ebdb7299a8ac Mon Sep 17 00:00:00 2001 From: Nodar Date: Mon, 18 Sep 2023 13:28:54 +0200 Subject: [PATCH 147/775] Factor out validator wallets and transaction builder into separate packages --- arbnode/node.go | 5 ++- cmd/nitro/nitro.go | 3 +- staker/l1_validator.go | 5 ++- staker/staker.go | 26 +++++++++++- .../builder.go} | 25 ++++++++++- .../contract.go} | 41 ++++++------------- .../eoa.go} | 11 +++-- system_tests/staker_test.go | 11 ++--- 8 files changed, 80 insertions(+), 47 deletions(-) rename staker/{builder_backend.go => txbuilder/builder.go} (80%) rename staker/{validator_wallet.go => validatorwallet/contract.go} (92%) rename staker/{eoa_validator_wallet.go => validatorwallet/eoa.go} (92%) diff --git a/arbnode/node.go b/arbnode/node.go index 5bdc71626..c7c191d1d 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -43,6 +43,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/staker" + "github.com/offchainlabs/nitro/staker/validatorwallet" "github.com/offchainlabs/nitro/util/contracts" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/redisutil" @@ -826,7 +827,7 @@ func createNodeImpl( tmpAddress := common.HexToAddress(config.Staker.ContractWalletAddress) existingWalletAddress = &tmpAddress } - wallet, err = staker.NewContractValidatorWallet(dp, existingWalletAddress, deployInfo.ValidatorWalletCreator, deployInfo.Rollup, l1Reader, txOptsValidator, int64(deployInfo.DeployedAt), func(common.Address) {}, getExtraGas) + wallet, err = validatorwallet.NewContractValidatorWallet(dp, existingWalletAddress, deployInfo.ValidatorWalletCreator, deployInfo.Rollup, l1Reader, txOptsValidator, int64(deployInfo.DeployedAt), func(common.Address) {}, getExtraGas) if err != nil { return nil, err } @@ -834,7 +835,7 @@ func createNodeImpl( if len(config.Staker.ContractWalletAddress) > 0 { return nil, errors.New("validator contract wallet specified but flag to use a smart contract wallet was not specified") } - wallet, err = staker.NewEoaValidatorWallet(dp, deployInfo.Rollup, l1client, txOptsValidator, getExtraGas) + wallet, err = validatorwallet.NewEoaValidatorWallet(dp, deployInfo.Rollup, l1client, txOptsValidator, getExtraGas) if err != nil { return nil, err } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index a7dc7f26f..50bb09238 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -51,6 +51,7 @@ import ( _ "github.com/offchainlabs/nitro/nodeInterface" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/staker" + "github.com/offchainlabs/nitro/staker/validatorwallet" "github.com/offchainlabs/nitro/util/colors" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/rpcclient" @@ -367,7 +368,7 @@ func mainImpl() int { if err != nil { log.Crit("error getting rollup addresses config", "err", err) } - addr, err := staker.GetValidatorWalletContract(ctx, deployInfo.ValidatorWalletCreator, int64(deployInfo.DeployedAt), l1TransactionOptsValidator, l1Reader, true) + addr, err := validatorwallet.GetValidatorWalletContract(ctx, deployInfo.ValidatorWalletCreator, int64(deployInfo.DeployedAt), l1TransactionOptsValidator, l1Reader, true) if err != nil { log.Crit("error creating validator wallet contract", "error", err, "address", l1TransactionOptsValidator.From.Hex()) } diff --git a/staker/l1_validator.go b/staker/l1_validator.go index aa9107fd9..dd3afec65 100644 --- a/staker/l1_validator.go +++ b/staker/l1_validator.go @@ -11,6 +11,7 @@ import ( "time" "github.com/offchainlabs/nitro/arbstate" + "github.com/offchainlabs/nitro/staker/txbuilder" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/validator" @@ -45,7 +46,7 @@ type L1Validator struct { rollupAddress common.Address validatorUtils *rollupgen.ValidatorUtils client arbutil.L1Interface - builder *ValidatorTxBuilder + builder *txbuilder.ValidatorTxBuilder wallet ValidatorWalletInterface callOpts bind.CallOpts @@ -66,7 +67,7 @@ func NewL1Validator( txStreamer TransactionStreamerInterface, blockValidator *BlockValidator, ) (*L1Validator, error) { - builder, err := NewValidatorTxBuilder(wallet) + builder, err := txbuilder.NewValidatorTxBuilder(wallet) if err != nil { return nil, err } diff --git a/staker/staker.go b/staker/staker.go index 1b6538b16..3c989cb4f 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -24,6 +24,7 @@ import ( "github.com/offchainlabs/nitro/arbnode/redislock" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/cmd/genericconf" + "github.com/offchainlabs/nitro/staker/txbuilder" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/stopwaiter" "github.com/offchainlabs/nitro/validator" @@ -254,6 +255,27 @@ type Staker struct { fatalErr chan<- error } +type ValidatorWalletInterface interface { + Initialize(context.Context) error + // Address must be able to be called concurrently with other functions + Address() *common.Address + // Address must be able to be called concurrently with other functions + AddressOrZero() common.Address + TxSenderAddress() *common.Address + RollupAddress() common.Address + ChallengeManagerAddress() common.Address + L1Client() arbutil.L1Interface + TestTransactions(context.Context, []*types.Transaction) error + ExecuteTransactions(context.Context, *txbuilder.ValidatorTxBuilder, common.Address) (*types.Transaction, error) + TimeoutChallenges(context.Context, []uint64) (*types.Transaction, error) + CanBatchTxs() bool + AuthIfEoa() *bind.TransactOpts + Start(context.Context) + StopAndWait() + // May be nil + DataPoster() *dataposter.DataPoster +} + func NewStaker( l1Reader L1ReaderInterface, wallet ValidatorWalletInterface, @@ -777,8 +799,8 @@ func (s *Staker) handleConflict(ctx context.Context, info *StakerInfo) error { newChallengeManager, err := NewChallengeManager( ctx, s.builder, - s.builder.builderAuth, - *s.builder.wallet.Address(), + s.builder.BuilderAuth(), + *s.builder.WalletAddress(), s.wallet.ChallengeManagerAddress(), *info.CurrentChallenge, s.statelessBlockValidator, diff --git a/staker/builder_backend.go b/staker/txbuilder/builder.go similarity index 80% rename from staker/builder_backend.go rename to staker/txbuilder/builder.go index 1bf15ff02..e0c3c5735 100644 --- a/staker/builder_backend.go +++ b/staker/txbuilder/builder.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package staker +package txbuilder import ( "context" @@ -15,6 +15,15 @@ import ( "github.com/offchainlabs/nitro/arbutil" ) +type ValidatorWalletInterface interface { + // Address must be able to be called concurrently with other functions + Address() *common.Address + L1Client() arbutil.L1Interface + TestTransactions(context.Context, []*types.Transaction) error + ExecuteTransactions(context.Context, *ValidatorTxBuilder, common.Address) (*types.Transaction, error) + AuthIfEoa() *bind.TransactOpts +} + // ValidatorTxBuilder combines any transactions sent to it via SendTransaction into one batch, // which is then sent to the validator wallet. // This lets the validator make multiple atomic transactions. @@ -101,3 +110,17 @@ func (b *ValidatorTxBuilder) AuthWithAmount(ctx context.Context, amount *big.Int func (b *ValidatorTxBuilder) Auth(ctx context.Context) (*bind.TransactOpts, error) { return b.AuthWithAmount(ctx, common.Big0) } + +func (b *ValidatorTxBuilder) Transactions() []*types.Transaction { + return b.transactions +} + +// Auth is the same as AuthWithAmount with a 0 amount specified. +// See AuthWithAmount docs for important details. +func (b *ValidatorTxBuilder) BuilderAuth() *bind.TransactOpts { + return b.builderAuth +} + +func (b *ValidatorTxBuilder) WalletAddress() *common.Address { + return b.wallet.Address() +} diff --git a/staker/validator_wallet.go b/staker/validatorwallet/contract.go similarity index 92% rename from staker/validator_wallet.go rename to staker/validatorwallet/contract.go index fb0f5ed95..0ad850436 100644 --- a/staker/validator_wallet.go +++ b/staker/validatorwallet/contract.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package staker +package validatorwallet import ( "context" @@ -22,6 +22,7 @@ import ( "github.com/offchainlabs/nitro/arbnode/dataposter" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/solgen/go/rollupgen" + "github.com/offchainlabs/nitro/staker/txbuilder" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/headerreader" ) @@ -43,27 +44,6 @@ func init() { walletCreatedID = parsedValidatorWalletCreator.Events["WalletCreated"].ID } -type ValidatorWalletInterface interface { - Initialize(context.Context) error - // Address must be able to be called concurrently with other functions - Address() *common.Address - // Address must be able to be called concurrently with other functions - AddressOrZero() common.Address - TxSenderAddress() *common.Address - RollupAddress() common.Address - ChallengeManagerAddress() common.Address - L1Client() arbutil.L1Interface - TestTransactions(context.Context, []*types.Transaction) error - ExecuteTransactions(context.Context, *ValidatorTxBuilder, common.Address) (*types.Transaction, error) - TimeoutChallenges(context.Context, []uint64) (*types.Transaction, error) - CanBatchTxs() bool - AuthIfEoa() *bind.TransactOpts - Start(context.Context) - StopAndWait() - // May be nil - DataPoster() *dataposter.DataPoster -} - type ContractValidatorWallet struct { con *rollupgen.ValidatorWallet address atomic.Pointer[common.Address] @@ -79,8 +59,6 @@ type ContractValidatorWallet struct { getExtraGas func() uint64 } -var _ ValidatorWalletInterface = (*ContractValidatorWallet)(nil) - func NewContractValidatorWallet(dp *dataposter.DataPoster, address *common.Address, walletFactoryAddr, rollupAddress common.Address, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts, rollupFromBlock int64, onWalletCreated func(common.Address), getExtraGas func() uint64) (*ContractValidatorWallet, error) { var con *rollupgen.ValidatorWallet @@ -257,8 +235,8 @@ func combineTxes(txes []*types.Transaction) ([][]byte, []common.Address, []*big. } // Not thread safe! Don't call this from multiple threads at the same time. -func (v *ContractValidatorWallet) ExecuteTransactions(ctx context.Context, builder *ValidatorTxBuilder, gasRefunder common.Address) (*types.Transaction, error) { - txes := builder.transactions +func (v *ContractValidatorWallet) ExecuteTransactions(ctx context.Context, builder *txbuilder.ValidatorTxBuilder, gasRefunder common.Address) (*types.Transaction, error) { + txes := builder.Transactions() if len(txes) == 0 { return nil, nil } @@ -273,7 +251,7 @@ func (v *ContractValidatorWallet) ExecuteTransactions(ctx context.Context, build if err != nil { return nil, err } - builder.transactions = nil + builder.ClearTransactions() return arbTx, nil } @@ -314,7 +292,7 @@ func (v *ContractValidatorWallet) ExecuteTransactions(ctx context.Context, build if err != nil { return nil, err } - builder.transactions = nil + builder.ClearTransactions() return arbTx, nil } @@ -422,6 +400,13 @@ func (b *ContractValidatorWallet) DataPoster() *dataposter.DataPoster { return b.dataPoster } +type L1ReaderInterface interface { + Client() arbutil.L1Interface + Subscribe(bool) (<-chan *types.Header, func()) + WaitForTxApproval(ctx context.Context, tx *types.Transaction) (*types.Receipt, error) + UseFinalityData() bool +} + func GetValidatorWalletContract( ctx context.Context, validatorWalletFactoryAddr common.Address, diff --git a/staker/eoa_validator_wallet.go b/staker/validatorwallet/eoa.go similarity index 92% rename from staker/eoa_validator_wallet.go rename to staker/validatorwallet/eoa.go index 5285e96ea..5f848aa4e 100644 --- a/staker/eoa_validator_wallet.go +++ b/staker/validatorwallet/eoa.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package staker +package validatorwallet import ( "context" @@ -15,6 +15,7 @@ import ( "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/solgen/go/challengegen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" + "github.com/offchainlabs/nitro/staker/txbuilder" ) type EoaValidatorWallet struct { @@ -27,8 +28,6 @@ type EoaValidatorWallet struct { getExtraGas func() uint64 } -var _ ValidatorWalletInterface = (*EoaValidatorWallet)(nil) - func NewEoaValidatorWallet(dataPoster *dataposter.DataPoster, rollupAddress common.Address, l1Client arbutil.L1Interface, auth *bind.TransactOpts, getExtraGas func() uint64) (*EoaValidatorWallet, error) { return &EoaValidatorWallet{ auth: auth, @@ -82,11 +81,11 @@ func (w *EoaValidatorWallet) TestTransactions(context.Context, []*types.Transact return nil } -func (w *EoaValidatorWallet) ExecuteTransactions(ctx context.Context, builder *ValidatorTxBuilder, _ common.Address) (*types.Transaction, error) { - if len(builder.transactions) == 0 { +func (w *EoaValidatorWallet) ExecuteTransactions(ctx context.Context, builder *txbuilder.ValidatorTxBuilder, _ common.Address) (*types.Transaction, error) { + if len(builder.Transactions()) == 0 { return nil, nil } - tx := builder.transactions[0] // we ignore future txs and only execute the first + tx := builder.Transactions()[0] // we ignore future txs and only execute the first return w.postTransaction(ctx, tx) } diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 96ea1ee2e..2f2287a2f 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -31,6 +31,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/staker" + "github.com/offchainlabs/nitro/staker/validatorwallet" "github.com/offchainlabs/nitro/util" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/colors" @@ -104,10 +105,10 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) TransferBalance(t, "Faucet", "ValidatorB", balance, l1info, l1client, ctx) l1authB := l1info.GetDefaultTransactOpts("ValidatorB", ctx) - valWalletAddrAPtr, err := staker.GetValidatorWalletContract(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader, true) + valWalletAddrAPtr, err := validatorwallet.GetValidatorWalletContract(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader, true) Require(t, err) valWalletAddrA := *valWalletAddrAPtr - valWalletAddrCheck, err := staker.GetValidatorWalletContract(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader, true) + valWalletAddrCheck, err := validatorwallet.GetValidatorWalletContract(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader, true) Require(t, err) if valWalletAddrA == *valWalletAddrCheck { Require(t, err, "didn't cache validator wallet address", valWalletAddrA.String(), "vs", valWalletAddrCheck.String()) @@ -134,7 +135,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } - valWalletA, err := staker.NewContractValidatorWallet(dpA, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, &l1authA, 0, func(common.Address) {}, func() uint64 { return valConfig.ExtraGas }) + valWalletA, err := validatorwallet.NewContractValidatorWallet(dpA, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, &l1authA, 0, func(common.Address) {}, func() uint64 { return valConfig.ExtraGas }) Require(t, err) if honestStakerInactive { valConfig.Strategy = "Defensive" @@ -182,7 +183,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } - valWalletB, err := staker.NewEoaValidatorWallet(dpB, l2nodeB.DeployInfo.Rollup, l2nodeB.L1Reader.Client(), &l1authB, func() uint64 { return 0 }) + valWalletB, err := validatorwallet.NewEoaValidatorWallet(dpB, l2nodeB.DeployInfo.Rollup, l2nodeB.L1Reader.Client(), &l1authB, func() uint64 { return 0 }) Require(t, err) valConfig.Strategy = "MakeNodes" statelessB, err := staker.NewStatelessBlockValidator( @@ -221,7 +222,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } - valWalletC, err := staker.NewContractValidatorWallet(dpC, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, nil, 0, func(common.Address) {}, func() uint64 { return 10000 }) + valWalletC, err := validatorwallet.NewContractValidatorWallet(dpC, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, nil, 0, func(common.Address) {}, func() uint64 { return 10000 }) Require(t, err) valConfig.Strategy = "Watchtower" stakerC, err := staker.NewStaker( From 921ca50709144997edd0dbe28f38c665e096e6a6 Mon Sep 17 00:00:00 2001 From: Nodar Date: Mon, 18 Sep 2023 13:35:30 +0200 Subject: [PATCH 148/775] Rename wallet structs to reduce verbosity at call sites --- arbnode/node.go | 4 +-- staker/l1_validator.go | 4 +-- staker/staker.go | 2 +- staker/txbuilder/builder.go | 28 ++++++++-------- staker/validatorwallet/contract.go | 52 +++++++++++++++--------------- staker/validatorwallet/eoa.go | 38 +++++++++++----------- system_tests/staker_test.go | 6 ++-- 7 files changed, 67 insertions(+), 67 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index c7c191d1d..c5b79058b 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -827,7 +827,7 @@ func createNodeImpl( tmpAddress := common.HexToAddress(config.Staker.ContractWalletAddress) existingWalletAddress = &tmpAddress } - wallet, err = validatorwallet.NewContractValidatorWallet(dp, existingWalletAddress, deployInfo.ValidatorWalletCreator, deployInfo.Rollup, l1Reader, txOptsValidator, int64(deployInfo.DeployedAt), func(common.Address) {}, getExtraGas) + wallet, err = validatorwallet.NewContract(dp, existingWalletAddress, deployInfo.ValidatorWalletCreator, deployInfo.Rollup, l1Reader, txOptsValidator, int64(deployInfo.DeployedAt), func(common.Address) {}, getExtraGas) if err != nil { return nil, err } @@ -835,7 +835,7 @@ func createNodeImpl( if len(config.Staker.ContractWalletAddress) > 0 { return nil, errors.New("validator contract wallet specified but flag to use a smart contract wallet was not specified") } - wallet, err = validatorwallet.NewEoaValidatorWallet(dp, deployInfo.Rollup, l1client, txOptsValidator, getExtraGas) + wallet, err = validatorwallet.NewEOA(dp, deployInfo.Rollup, l1client, txOptsValidator, getExtraGas) if err != nil { return nil, err } diff --git a/staker/l1_validator.go b/staker/l1_validator.go index dd3afec65..09bcc6446 100644 --- a/staker/l1_validator.go +++ b/staker/l1_validator.go @@ -46,7 +46,7 @@ type L1Validator struct { rollupAddress common.Address validatorUtils *rollupgen.ValidatorUtils client arbutil.L1Interface - builder *txbuilder.ValidatorTxBuilder + builder *txbuilder.Builder wallet ValidatorWalletInterface callOpts bind.CallOpts @@ -67,7 +67,7 @@ func NewL1Validator( txStreamer TransactionStreamerInterface, blockValidator *BlockValidator, ) (*L1Validator, error) { - builder, err := txbuilder.NewValidatorTxBuilder(wallet) + builder, err := txbuilder.NewBuilder(wallet) if err != nil { return nil, err } diff --git a/staker/staker.go b/staker/staker.go index 3c989cb4f..d52d1adc7 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -266,7 +266,7 @@ type ValidatorWalletInterface interface { ChallengeManagerAddress() common.Address L1Client() arbutil.L1Interface TestTransactions(context.Context, []*types.Transaction) error - ExecuteTransactions(context.Context, *txbuilder.ValidatorTxBuilder, common.Address) (*types.Transaction, error) + ExecuteTransactions(context.Context, *txbuilder.Builder, common.Address) (*types.Transaction, error) TimeoutChallenges(context.Context, []uint64) (*types.Transaction, error) CanBatchTxs() bool AuthIfEoa() *bind.TransactOpts diff --git a/staker/txbuilder/builder.go b/staker/txbuilder/builder.go index e0c3c5735..9a5e9df2b 100644 --- a/staker/txbuilder/builder.go +++ b/staker/txbuilder/builder.go @@ -20,16 +20,16 @@ type ValidatorWalletInterface interface { Address() *common.Address L1Client() arbutil.L1Interface TestTransactions(context.Context, []*types.Transaction) error - ExecuteTransactions(context.Context, *ValidatorTxBuilder, common.Address) (*types.Transaction, error) + ExecuteTransactions(context.Context, *Builder, common.Address) (*types.Transaction, error) AuthIfEoa() *bind.TransactOpts } -// ValidatorTxBuilder combines any transactions sent to it via SendTransaction into one batch, +// Builder combines any transactions sent to it via SendTransaction into one batch, // which is then sent to the validator wallet. // This lets the validator make multiple atomic transactions. // This inherits from an eth client so it can be used as an L1Interface, // where it transparently intercepts calls to SendTransaction and queues them for the next batch. -type ValidatorTxBuilder struct { +type Builder struct { arbutil.L1Interface transactions []*types.Transaction builderAuth *bind.TransactOpts @@ -37,7 +37,7 @@ type ValidatorTxBuilder struct { wallet ValidatorWalletInterface } -func NewValidatorTxBuilder(wallet ValidatorWalletInterface) (*ValidatorTxBuilder, error) { +func NewBuilder(wallet ValidatorWalletInterface) (*Builder, error) { randKey, err := crypto.GenerateKey() if err != nil { return nil, err @@ -52,7 +52,7 @@ func NewValidatorTxBuilder(wallet ValidatorWalletInterface) (*ValidatorTxBuilder } isAuthFake = true } - return &ValidatorTxBuilder{ + return &Builder{ builderAuth: builderAuth, wallet: wallet, L1Interface: wallet.L1Client(), @@ -60,22 +60,22 @@ func NewValidatorTxBuilder(wallet ValidatorWalletInterface) (*ValidatorTxBuilder }, nil } -func (b *ValidatorTxBuilder) BuildingTransactionCount() int { +func (b *Builder) BuildingTransactionCount() int { return len(b.transactions) } -func (b *ValidatorTxBuilder) ClearTransactions() { +func (b *Builder) ClearTransactions() { b.transactions = nil } -func (b *ValidatorTxBuilder) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) { +func (b *Builder) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) { if len(b.transactions) == 0 && !b.isAuthFake { return b.L1Interface.EstimateGas(ctx, call) } return 0, nil } -func (b *ValidatorTxBuilder) SendTransaction(ctx context.Context, tx *types.Transaction) error { +func (b *Builder) SendTransaction(ctx context.Context, tx *types.Transaction) error { b.transactions = append(b.transactions, tx) err := b.wallet.TestTransactions(ctx, b.transactions) if err != nil { @@ -89,7 +89,7 @@ func (b *ValidatorTxBuilder) SendTransaction(ctx context.Context, tx *types.Tran // While this is not currently required, it's recommended not to reuse the returned auth for multiple transactions, // as for an EOA this has the nonce in it. However, the EOA wwallet currently will only publish the first created tx, // which is why that doesn't really matter. -func (b *ValidatorTxBuilder) AuthWithAmount(ctx context.Context, amount *big.Int) (*bind.TransactOpts, error) { +func (b *Builder) AuthWithAmount(ctx context.Context, amount *big.Int) (*bind.TransactOpts, error) { nonce, err := b.NonceAt(ctx, b.builderAuth.From, nil) if err != nil { return nil, err @@ -107,20 +107,20 @@ func (b *ValidatorTxBuilder) AuthWithAmount(ctx context.Context, amount *big.Int // Auth is the same as AuthWithAmount with a 0 amount specified. // See AuthWithAmount docs for important details. -func (b *ValidatorTxBuilder) Auth(ctx context.Context) (*bind.TransactOpts, error) { +func (b *Builder) Auth(ctx context.Context) (*bind.TransactOpts, error) { return b.AuthWithAmount(ctx, common.Big0) } -func (b *ValidatorTxBuilder) Transactions() []*types.Transaction { +func (b *Builder) Transactions() []*types.Transaction { return b.transactions } // Auth is the same as AuthWithAmount with a 0 amount specified. // See AuthWithAmount docs for important details. -func (b *ValidatorTxBuilder) BuilderAuth() *bind.TransactOpts { +func (b *Builder) BuilderAuth() *bind.TransactOpts { return b.builderAuth } -func (b *ValidatorTxBuilder) WalletAddress() *common.Address { +func (b *Builder) WalletAddress() *common.Address { return b.wallet.Address() } diff --git a/staker/validatorwallet/contract.go b/staker/validatorwallet/contract.go index 0ad850436..3ade358ce 100644 --- a/staker/validatorwallet/contract.go +++ b/staker/validatorwallet/contract.go @@ -44,7 +44,7 @@ func init() { walletCreatedID = parsedValidatorWalletCreator.Events["WalletCreated"].ID } -type ContractValidatorWallet struct { +type Contract struct { con *rollupgen.ValidatorWallet address atomic.Pointer[common.Address] onWalletCreated func(common.Address) @@ -59,8 +59,8 @@ type ContractValidatorWallet struct { getExtraGas func() uint64 } -func NewContractValidatorWallet(dp *dataposter.DataPoster, address *common.Address, walletFactoryAddr, rollupAddress common.Address, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts, rollupFromBlock int64, onWalletCreated func(common.Address), - getExtraGas func() uint64) (*ContractValidatorWallet, error) { +func NewContract(dp *dataposter.DataPoster, address *common.Address, walletFactoryAddr, rollupAddress common.Address, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts, rollupFromBlock int64, onWalletCreated func(common.Address), + getExtraGas func() uint64) (*Contract, error) { var con *rollupgen.ValidatorWallet if address != nil { var err error @@ -73,7 +73,7 @@ func NewContractValidatorWallet(dp *dataposter.DataPoster, address *common.Addre if err != nil { return nil, err } - wallet := &ContractValidatorWallet{ + wallet := &Contract{ con: con, onWalletCreated: onWalletCreated, l1Reader: l1Reader, @@ -90,7 +90,7 @@ func NewContractValidatorWallet(dp *dataposter.DataPoster, address *common.Addre return wallet, nil } -func (v *ContractValidatorWallet) validateWallet(ctx context.Context) error { +func (v *Contract) validateWallet(ctx context.Context) error { if v.con == nil || v.auth == nil { return nil } @@ -109,7 +109,7 @@ func (v *ContractValidatorWallet) validateWallet(ctx context.Context) error { return nil } -func (v *ContractValidatorWallet) Initialize(ctx context.Context) error { +func (v *Contract) Initialize(ctx context.Context) error { err := v.populateWallet(ctx, false) if err != nil { return err @@ -124,12 +124,12 @@ func (v *ContractValidatorWallet) Initialize(ctx context.Context) error { } // May be the nil if the wallet hasn't been deployed yet -func (v *ContractValidatorWallet) Address() *common.Address { +func (v *Contract) Address() *common.Address { return v.address.Load() } // May be zero if the wallet hasn't been deployed yet -func (v *ContractValidatorWallet) AddressOrZero() common.Address { +func (v *Contract) AddressOrZero() common.Address { addr := v.address.Load() if addr == nil { return common.Address{} @@ -137,14 +137,14 @@ func (v *ContractValidatorWallet) AddressOrZero() common.Address { return *addr } -func (v *ContractValidatorWallet) TxSenderAddress() *common.Address { +func (v *Contract) TxSenderAddress() *common.Address { if v.auth == nil { return nil } return &v.auth.From } -func (v *ContractValidatorWallet) From() common.Address { +func (v *Contract) From() common.Address { if v.auth == nil { return common.Address{} } @@ -152,7 +152,7 @@ func (v *ContractValidatorWallet) From() common.Address { } // nil value == 0 value -func (v *ContractValidatorWallet) getAuth(ctx context.Context, value *big.Int) (*bind.TransactOpts, error) { +func (v *Contract) getAuth(ctx context.Context, value *big.Int) (*bind.TransactOpts, error) { newAuth := *v.auth newAuth.Context = ctx newAuth.Value = value @@ -164,7 +164,7 @@ func (v *ContractValidatorWallet) getAuth(ctx context.Context, value *big.Int) ( return &newAuth, nil } -func (v *ContractValidatorWallet) executeTransaction(ctx context.Context, tx *types.Transaction, gasRefunder common.Address) (*types.Transaction, error) { +func (v *Contract) executeTransaction(ctx context.Context, tx *types.Transaction, gasRefunder common.Address) (*types.Transaction, error) { auth, err := v.getAuth(ctx, tx.Value()) if err != nil { return nil, err @@ -180,7 +180,7 @@ func (v *ContractValidatorWallet) executeTransaction(ctx context.Context, tx *ty return v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), data, gas, auth.Value) } -func (v *ContractValidatorWallet) populateWallet(ctx context.Context, createIfMissing bool) error { +func (v *Contract) populateWallet(ctx context.Context, createIfMissing bool) error { if v.con != nil { return nil } @@ -235,7 +235,7 @@ func combineTxes(txes []*types.Transaction) ([][]byte, []common.Address, []*big. } // Not thread safe! Don't call this from multiple threads at the same time. -func (v *ContractValidatorWallet) ExecuteTransactions(ctx context.Context, builder *txbuilder.ValidatorTxBuilder, gasRefunder common.Address) (*types.Transaction, error) { +func (v *Contract) ExecuteTransactions(ctx context.Context, builder *txbuilder.Builder, gasRefunder common.Address) (*types.Transaction, error) { txes := builder.Transactions() if len(txes) == 0 { return nil, nil @@ -296,7 +296,7 @@ func (v *ContractValidatorWallet) ExecuteTransactions(ctx context.Context, build return arbTx, nil } -func (v *ContractValidatorWallet) estimateGas(ctx context.Context, value *big.Int, data []byte) (uint64, error) { +func (v *Contract) estimateGas(ctx context.Context, value *big.Int, data []byte) (uint64, error) { h, err := v.l1Reader.LastHeader(ctx) if err != nil { return 0, fmt.Errorf("getting the last header: %w", err) @@ -325,7 +325,7 @@ func (v *ContractValidatorWallet) estimateGas(ctx context.Context, value *big.In return g + v.getExtraGas(), nil } -func (v *ContractValidatorWallet) TimeoutChallenges(ctx context.Context, challenges []uint64) (*types.Transaction, error) { +func (v *Contract) TimeoutChallenges(ctx context.Context, challenges []uint64) (*types.Transaction, error) { auth, err := v.getAuth(ctx, nil) if err != nil { return nil, err @@ -342,26 +342,26 @@ func (v *ContractValidatorWallet) TimeoutChallenges(ctx context.Context, challen } // gasForTxData returns auth.GasLimit if it's nonzero, otherwise returns estimate. -func (v *ContractValidatorWallet) gasForTxData(ctx context.Context, auth *bind.TransactOpts, data []byte) (uint64, error) { +func (v *Contract) gasForTxData(ctx context.Context, auth *bind.TransactOpts, data []byte) (uint64, error) { if auth.GasLimit != 0 { return auth.GasLimit, nil } return v.estimateGas(ctx, auth.Value, data) } -func (v *ContractValidatorWallet) L1Client() arbutil.L1Interface { +func (v *Contract) L1Client() arbutil.L1Interface { return v.l1Reader.Client() } -func (v *ContractValidatorWallet) RollupAddress() common.Address { +func (v *Contract) RollupAddress() common.Address { return v.rollupAddress } -func (v *ContractValidatorWallet) ChallengeManagerAddress() common.Address { +func (v *Contract) ChallengeManagerAddress() common.Address { return v.challengeManagerAddress } -func (v *ContractValidatorWallet) TestTransactions(ctx context.Context, txs []*types.Transaction) error { +func (v *Contract) TestTransactions(ctx context.Context, txs []*types.Transaction) error { if v.Address() == nil { return nil } @@ -380,23 +380,23 @@ func (v *ContractValidatorWallet) TestTransactions(ctx context.Context, txs []*t return err } -func (v *ContractValidatorWallet) CanBatchTxs() bool { +func (v *Contract) CanBatchTxs() bool { return true } -func (v *ContractValidatorWallet) AuthIfEoa() *bind.TransactOpts { +func (v *Contract) AuthIfEoa() *bind.TransactOpts { return nil } -func (w *ContractValidatorWallet) Start(ctx context.Context) { +func (w *Contract) Start(ctx context.Context) { w.dataPoster.Start(ctx) } -func (b *ContractValidatorWallet) StopAndWait() { +func (b *Contract) StopAndWait() { b.dataPoster.StopAndWait() } -func (b *ContractValidatorWallet) DataPoster() *dataposter.DataPoster { +func (b *Contract) DataPoster() *dataposter.DataPoster { return b.dataPoster } diff --git a/staker/validatorwallet/eoa.go b/staker/validatorwallet/eoa.go index 5f848aa4e..b2c9f68b5 100644 --- a/staker/validatorwallet/eoa.go +++ b/staker/validatorwallet/eoa.go @@ -18,7 +18,7 @@ import ( "github.com/offchainlabs/nitro/staker/txbuilder" ) -type EoaValidatorWallet struct { +type EOA struct { auth *bind.TransactOpts client arbutil.L1Interface rollupAddress common.Address @@ -28,8 +28,8 @@ type EoaValidatorWallet struct { getExtraGas func() uint64 } -func NewEoaValidatorWallet(dataPoster *dataposter.DataPoster, rollupAddress common.Address, l1Client arbutil.L1Interface, auth *bind.TransactOpts, getExtraGas func() uint64) (*EoaValidatorWallet, error) { - return &EoaValidatorWallet{ +func NewEOA(dataPoster *dataposter.DataPoster, rollupAddress common.Address, l1Client arbutil.L1Interface, auth *bind.TransactOpts, getExtraGas func() uint64) (*EOA, error) { + return &EOA{ auth: auth, client: l1Client, rollupAddress: rollupAddress, @@ -38,7 +38,7 @@ func NewEoaValidatorWallet(dataPoster *dataposter.DataPoster, rollupAddress comm }, nil } -func (w *EoaValidatorWallet) Initialize(ctx context.Context) error { +func (w *EOA) Initialize(ctx context.Context) error { rollup, err := rollupgen.NewRollupUserLogic(w.rollupAddress, w.client) if err != nil { return err @@ -52,36 +52,36 @@ func (w *EoaValidatorWallet) Initialize(ctx context.Context) error { return err } -func (w *EoaValidatorWallet) Address() *common.Address { +func (w *EOA) Address() *common.Address { return &w.auth.From } -func (w *EoaValidatorWallet) AddressOrZero() common.Address { +func (w *EOA) AddressOrZero() common.Address { return w.auth.From } -func (w *EoaValidatorWallet) TxSenderAddress() *common.Address { +func (w *EOA) TxSenderAddress() *common.Address { return &w.auth.From } -func (w *EoaValidatorWallet) L1Client() arbutil.L1Interface { +func (w *EOA) L1Client() arbutil.L1Interface { return w.client } -func (w *EoaValidatorWallet) RollupAddress() common.Address { +func (w *EOA) RollupAddress() common.Address { return w.rollupAddress } -func (w *EoaValidatorWallet) ChallengeManagerAddress() common.Address { +func (w *EOA) ChallengeManagerAddress() common.Address { return w.challengeManagerAddress } -func (w *EoaValidatorWallet) TestTransactions(context.Context, []*types.Transaction) error { +func (w *EOA) TestTransactions(context.Context, []*types.Transaction) error { // We only use the first tx which is checked implicitly by gas estimation return nil } -func (w *EoaValidatorWallet) ExecuteTransactions(ctx context.Context, builder *txbuilder.ValidatorTxBuilder, _ common.Address) (*types.Transaction, error) { +func (w *EOA) ExecuteTransactions(ctx context.Context, builder *txbuilder.Builder, _ common.Address) (*types.Transaction, error) { if len(builder.Transactions()) == 0 { return nil, nil } @@ -89,7 +89,7 @@ func (w *EoaValidatorWallet) ExecuteTransactions(ctx context.Context, builder *t return w.postTransaction(ctx, tx) } -func (w *EoaValidatorWallet) postTransaction(ctx context.Context, baseTx *types.Transaction) (*types.Transaction, error) { +func (w *EOA) postTransaction(ctx context.Context, baseTx *types.Transaction) (*types.Transaction, error) { nonce, err := w.L1Client().NonceAt(ctx, w.auth.From, nil) if err != nil { return nil, err @@ -102,7 +102,7 @@ func (w *EoaValidatorWallet) postTransaction(ctx context.Context, baseTx *types. return newTx, nil } -func (w *EoaValidatorWallet) TimeoutChallenges(ctx context.Context, timeouts []uint64) (*types.Transaction, error) { +func (w *EOA) TimeoutChallenges(ctx context.Context, timeouts []uint64) (*types.Transaction, error) { if len(timeouts) == 0 { return nil, nil } @@ -116,22 +116,22 @@ func (w *EoaValidatorWallet) TimeoutChallenges(ctx context.Context, timeouts []u return w.postTransaction(ctx, tx) } -func (w *EoaValidatorWallet) CanBatchTxs() bool { +func (w *EOA) CanBatchTxs() bool { return false } -func (w *EoaValidatorWallet) AuthIfEoa() *bind.TransactOpts { +func (w *EOA) AuthIfEoa() *bind.TransactOpts { return w.auth } -func (w *EoaValidatorWallet) Start(ctx context.Context) { +func (w *EOA) Start(ctx context.Context) { w.dataPoster.Start(ctx) } -func (b *EoaValidatorWallet) StopAndWait() { +func (b *EOA) StopAndWait() { b.dataPoster.StopAndWait() } -func (b *EoaValidatorWallet) DataPoster() *dataposter.DataPoster { +func (b *EOA) DataPoster() *dataposter.DataPoster { return b.dataPoster } diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 2f2287a2f..d7207271e 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -135,7 +135,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } - valWalletA, err := validatorwallet.NewContractValidatorWallet(dpA, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, &l1authA, 0, func(common.Address) {}, func() uint64 { return valConfig.ExtraGas }) + valWalletA, err := validatorwallet.NewContract(dpA, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, &l1authA, 0, func(common.Address) {}, func() uint64 { return valConfig.ExtraGas }) Require(t, err) if honestStakerInactive { valConfig.Strategy = "Defensive" @@ -183,7 +183,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } - valWalletB, err := validatorwallet.NewEoaValidatorWallet(dpB, l2nodeB.DeployInfo.Rollup, l2nodeB.L1Reader.Client(), &l1authB, func() uint64 { return 0 }) + valWalletB, err := validatorwallet.NewEOA(dpB, l2nodeB.DeployInfo.Rollup, l2nodeB.L1Reader.Client(), &l1authB, func() uint64 { return 0 }) Require(t, err) valConfig.Strategy = "MakeNodes" statelessB, err := staker.NewStatelessBlockValidator( @@ -222,7 +222,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } - valWalletC, err := validatorwallet.NewContractValidatorWallet(dpC, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, nil, 0, func(common.Address) {}, func() uint64 { return 10000 }) + valWalletC, err := validatorwallet.NewContract(dpC, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, nil, 0, func(common.Address) {}, func() uint64 { return 10000 }) Require(t, err) valConfig.Strategy = "Watchtower" stakerC, err := staker.NewStaker( From f58c9eb7cd3f571757ccaff6e3a7899c118a9033 Mon Sep 17 00:00:00 2001 From: Nodar Date: Mon, 18 Sep 2023 15:32:07 +0200 Subject: [PATCH 149/775] Implement noop validator wallet and use it for watchtwer steker strategy --- arbnode/node.go | 52 +++++++++++++++-------------- staker/validatorwallet/noop.go | 60 ++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 24 deletions(-) create mode 100644 staker/validatorwallet/noop.go diff --git a/arbnode/node.go b/arbnode/node.go index c5b79058b..37cbb48c9 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "math/big" + "strings" "time" flag "github.com/spf13/pflag" @@ -816,28 +817,32 @@ func createNodeImpl( return nil, err } getExtraGas := func() uint64 { return configFetcher.Get().Staker.ExtraGas } - var wallet staker.ValidatorWalletInterface - if config.Staker.UseSmartContractWallet || txOptsValidator == nil { - var existingWalletAddress *common.Address - if len(config.Staker.ContractWalletAddress) > 0 { - if !common.IsHexAddress(config.Staker.ContractWalletAddress) { - log.Error("invalid validator smart contract wallet", "addr", config.Staker.ContractWalletAddress) - return nil, errors.New("invalid validator smart contract wallet address") + // TODO: factor this out into separate helper, and split rest of node + // creation into multiple helpers. + var wallet staker.ValidatorWalletInterface = validatorwallet.NewNoOp() + if !strings.EqualFold(config.Staker.Strategy, "watchtower") { + if config.Staker.UseSmartContractWallet || txOptsValidator == nil { + var existingWalletAddress *common.Address + if len(config.Staker.ContractWalletAddress) > 0 { + if !common.IsHexAddress(config.Staker.ContractWalletAddress) { + log.Error("invalid validator smart contract wallet", "addr", config.Staker.ContractWalletAddress) + return nil, errors.New("invalid validator smart contract wallet address") + } + tmpAddress := common.HexToAddress(config.Staker.ContractWalletAddress) + existingWalletAddress = &tmpAddress + } + wallet, err = validatorwallet.NewContract(dp, existingWalletAddress, deployInfo.ValidatorWalletCreator, deployInfo.Rollup, l1Reader, txOptsValidator, int64(deployInfo.DeployedAt), func(common.Address) {}, getExtraGas) + if err != nil { + return nil, err + } + } else { + if len(config.Staker.ContractWalletAddress) > 0 { + return nil, errors.New("validator contract wallet specified but flag to use a smart contract wallet was not specified") + } + wallet, err = validatorwallet.NewEOA(dp, deployInfo.Rollup, l1client, txOptsValidator, getExtraGas) + if err != nil { + return nil, err } - tmpAddress := common.HexToAddress(config.Staker.ContractWalletAddress) - existingWalletAddress = &tmpAddress - } - wallet, err = validatorwallet.NewContract(dp, existingWalletAddress, deployInfo.ValidatorWalletCreator, deployInfo.Rollup, l1Reader, txOptsValidator, int64(deployInfo.DeployedAt), func(common.Address) {}, getExtraGas) - if err != nil { - return nil, err - } - } else { - if len(config.Staker.ContractWalletAddress) > 0 { - return nil, errors.New("validator contract wallet specified but flag to use a smart contract wallet was not specified") - } - wallet, err = validatorwallet.NewEOA(dp, deployInfo.Rollup, l1client, txOptsValidator, getExtraGas) - if err != nil { - return nil, err } } @@ -851,9 +856,8 @@ func createNodeImpl( if err != nil { return nil, err } - if stakerObj.Strategy() != staker.WatchtowerStrategy { - err := wallet.Initialize(ctx) - if err != nil { + if stakerObj.Strategy() == staker.WatchtowerStrategy { + if err := wallet.Initialize(ctx); err != nil { return nil, err } } diff --git a/staker/validatorwallet/noop.go b/staker/validatorwallet/noop.go new file mode 100644 index 000000000..57ff270e7 --- /dev/null +++ b/staker/validatorwallet/noop.go @@ -0,0 +1,60 @@ +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package validatorwallet + +import ( + "context" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/offchainlabs/nitro/arbnode/dataposter" + "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/staker/txbuilder" +) + +// NoOp validator wallet is used for watchtower mode. +type NoOp struct{} + +func NewNoOp() *NoOp { + return &NoOp{} +} + +func (*NoOp) Initialize(context.Context) error { return nil } + +func (*NoOp) Address() *common.Address { return nil } + +func (*NoOp) AddressOrZero() common.Address { return common.Address{} } + +func (*NoOp) TxSenderAddress() *common.Address { return nil } + +func (*NoOp) From() common.Address { return common.Address{} } + +func (*NoOp) ExecuteTransactions(context.Context, *txbuilder.Builder, common.Address) (*types.Transaction, error) { + return nil, nil +} + +func (*NoOp) TimeoutChallenges(ctx context.Context, challenges []uint64) (*types.Transaction, error) { + return nil, nil +} + +func (*NoOp) L1Client() arbutil.L1Interface { return nil } + +func (*NoOp) RollupAddress() common.Address { return common.Address{} } + +func (*NoOp) ChallengeManagerAddress() common.Address { return common.Address{} } + +func (*NoOp) TestTransactions(ctx context.Context, txs []*types.Transaction) error { + return nil +} + +func (*NoOp) CanBatchTxs() bool { return false } + +func (*NoOp) AuthIfEoa() *bind.TransactOpts { return nil } + +func (w *NoOp) Start(ctx context.Context) {} + +func (b *NoOp) StopAndWait() {} + +func (b *NoOp) DataPoster() *dataposter.DataPoster { return nil } From 321502016fd1b28a5f8948b80df9024ed80ae56f Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 18 Sep 2023 10:34:19 -0500 Subject: [PATCH 150/775] fix failing test --- Makefile | 2 +- arbos/arbosState/arbosstate.go | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 56bf4df3c..ca299df2e 100644 --- a/Makefile +++ b/Makefile @@ -212,7 +212,7 @@ $(arbitrator_jit): $(DEP_PREDICATE) .make/cbrotli-lib $(jit_files) $(arbitrator_cases)/rust/target/wasm32-wasi/release/%.wasm: $(arbitrator_cases)/rust/src/bin/%.rs $(arbitrator_cases)/rust/src/lib.rs cargo build --manifest-path $(arbitrator_cases)/rust/Cargo.toml --release --target wasm32-wasi --bin $(patsubst $(arbitrator_cases)/rust/target/wasm32-wasi/release/%.wasm,%, $@) -$(arbitrator_cases)/go/main: $(arbitrator_cases)/go/main.go +$(arbitrator_cases)/go/main: $(arbitrator_cases)/go/main.go .make/solgen cd $(arbitrator_cases)/go && GOOS=js GOARCH=wasm go build main.go $(arbitrator_generated_header): $(DEP_PREDICATE) arbitrator/prover/src/lib.rs arbitrator/prover/src/utils.rs diff --git a/arbos/arbosState/arbosstate.go b/arbos/arbosState/arbosstate.go index 0be5e51f8..c87d0f224 100644 --- a/arbos/arbosState/arbosstate.go +++ b/arbos/arbosState/arbosstate.go @@ -319,6 +319,14 @@ func (state *ArbosState) UpgradeArbosVersion( ensure(state.chainOwners.ClearList()) } case 11: + if !chainConfig.DebugMode() { + // This upgrade isn't finalized so we only want to support it for testing + return fmt.Errorf( + "the chain is upgrading to unsupported ArbOS version %v, %w", + state.arbosVersion+1, + ErrFatalNodeOutOfDate, + ) + } // Update Brotli compression level for fast compression from 0 to 1 ensure(state.l1PricingState.SetBrotliCompressionLevel(1)) default: From 2894e69c5094f29532f69c9d2208d76db1015317 Mon Sep 17 00:00:00 2001 From: Nodar Date: Mon, 18 Sep 2023 19:30:08 +0200 Subject: [PATCH 151/775] Return errors from noop validator wallet when trying to execute transactions or timout challenges --- arbnode/node.go | 2 +- staker/validatorwallet/noop.go | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 37cbb48c9..3801e2047 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -819,7 +819,7 @@ func createNodeImpl( getExtraGas := func() uint64 { return configFetcher.Get().Staker.ExtraGas } // TODO: factor this out into separate helper, and split rest of node // creation into multiple helpers. - var wallet staker.ValidatorWalletInterface = validatorwallet.NewNoOp() + var wallet staker.ValidatorWalletInterface = validatorwallet.NewNoOp(l1client) if !strings.EqualFold(config.Staker.Strategy, "watchtower") { if config.Staker.UseSmartContractWallet || txOptsValidator == nil { var existingWalletAddress *common.Address diff --git a/staker/validatorwallet/noop.go b/staker/validatorwallet/noop.go index 57ff270e7..0a1e66d09 100644 --- a/staker/validatorwallet/noop.go +++ b/staker/validatorwallet/noop.go @@ -5,6 +5,7 @@ package validatorwallet import ( "context" + "errors" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -15,10 +16,12 @@ import ( ) // NoOp validator wallet is used for watchtower mode. -type NoOp struct{} +type NoOp struct { + l1Client arbutil.L1Interface +} -func NewNoOp() *NoOp { - return &NoOp{} +func NewNoOp(l1Client arbutil.L1Interface) *NoOp { + return &NoOp{l1Client: l1Client} } func (*NoOp) Initialize(context.Context) error { return nil } @@ -32,14 +35,14 @@ func (*NoOp) TxSenderAddress() *common.Address { return nil } func (*NoOp) From() common.Address { return common.Address{} } func (*NoOp) ExecuteTransactions(context.Context, *txbuilder.Builder, common.Address) (*types.Transaction, error) { - return nil, nil + return nil, errors.New("no op validator wallet cannot execute transactions") } func (*NoOp) TimeoutChallenges(ctx context.Context, challenges []uint64) (*types.Transaction, error) { - return nil, nil + return nil, errors.New("no op validator wallet cannot timeout challenges") } -func (*NoOp) L1Client() arbutil.L1Interface { return nil } +func (n *NoOp) L1Client() arbutil.L1Interface { return n.l1Client } func (*NoOp) RollupAddress() common.Address { return common.Address{} } From b5379b9eba7b847bdb64cdb6c0bb2640bbe86211 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 18 Sep 2023 16:06:02 -0500 Subject: [PATCH 152/775] address PR comments --- contracts | 2 +- nodeInterface/NodeInterface.go | 106 ++++++++++++++--------------- system_tests/nodeinterface_test.go | 43 ++++++------ 3 files changed, 77 insertions(+), 74 deletions(-) diff --git a/contracts b/contracts index accdcee45..436e1cf82 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit accdcee45798af5025836a04ee5bdcb0669cb476 +Subproject commit 436e1cf82c5696eb918d842256328ba86fbe5019 diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index 92ed2064c..98394f934 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -591,82 +591,82 @@ func (n NodeInterface) LegacyLookupMessageBatchProof(c ctx, evm mech, batchNum h return } -func (n NodeInterface) getL1BlockNum(l2BlockNum uint64) (uint64, error) { +func (n NodeInterface) blockL1Num(l2BlockNum uint64) (uint64, error) { blockHeader, err := n.backend.HeaderByNumber(n.context, rpc.BlockNumber(l2BlockNum)) if err != nil { return 0, err } - l1BlockNum := types.DeserializeHeaderExtraInformation(blockHeader).L1BlockNumber - return l1BlockNum, nil + blockL1Num := types.DeserializeHeaderExtraInformation(blockHeader).L1BlockNumber + return blockL1Num, nil } -func (n NodeInterface) GetL2BlockRangeForL1(c ctx, evm mech, l1BlockNum uint64) ([]uint64, error) { +func (n NodeInterface) matchL2BlockNumWithL1(l2BlockNum uint64, l1BlockNum uint64) error { + blockL1Num, err := n.blockL1Num(l2BlockNum) + if err != nil { + return fmt.Errorf("failed to get the L1 block number of the L2 block: %v. Error: %w", l2BlockNum, err) + } + if blockL1Num != l1BlockNum { + return fmt.Errorf("no L2 block was found with the given L1 block number. Found L2 block: %v with L1 block number: %v, given L1 block number: %v", l2BlockNum, blockL1Num, l1BlockNum) + } + return nil +} + +// L2BlockRangeForL1 finds the first and last L2 block numbers that have the given L1 block number +func (n NodeInterface) L2BlockRangeForL1(c ctx, evm mech, l1BlockNum uint64) (uint64, uint64, error) { currentBlockNum := n.backend.CurrentBlock().Number.Uint64() genesis := n.backend.ChainConfig().ArbitrumChainParams.GenesisBlockNum - checkCorrectness := func(blockNum uint64, target uint64) error { - blockL1Num, err := n.getL1BlockNum(blockNum) - if err != nil { - return err - } - if blockL1Num != target { - return errors.New("no L2 block was found with the given L1 block number") - } - return nil + type helperStruct struct { + low uint64 + high uint64 } - lowFirstBlock := genesis - highFirstBlock := currentBlockNum - lowLastBlock := genesis - highLastBlock := currentBlockNum - var storedMid uint64 - var storedMidBlockL1Num uint64 - for lowFirstBlock < highFirstBlock || lowLastBlock < highLastBlock { - if lowFirstBlock < highFirstBlock { - mid := arbmath.SaturatingUAdd(lowFirstBlock, highFirstBlock) / 2 - midBlockL1Num, err := n.getL1BlockNum(mid) - if err != nil { - return nil, err - } - storedMid = mid - storedMidBlockL1Num = midBlockL1Num - if midBlockL1Num < l1BlockNum { - lowFirstBlock = mid + 1 - } else { - highFirstBlock = mid - } - } - if lowLastBlock < highLastBlock { + searchHelper := func(currentBlock *helperStruct, fetchedMid *helperStruct, target uint64) error { + if currentBlock.low < currentBlock.high { // dont fetch midBlockL1Num if its already fetched above - mid := arbmath.SaturatingUAdd(lowLastBlock, highLastBlock) / 2 + mid := arbmath.SaturatingUAdd(currentBlock.low, currentBlock.high) / 2 var midBlockL1Num uint64 var err error - if mid == storedMid { - midBlockL1Num = storedMidBlockL1Num + if mid == fetchedMid.low { + midBlockL1Num = fetchedMid.high } else { - midBlockL1Num, err = n.getL1BlockNum(mid) + midBlockL1Num, err = n.blockL1Num(mid) if err != nil { - return nil, err + return err } + fetchedMid.low = mid + fetchedMid.high = midBlockL1Num } - if midBlockL1Num < l1BlockNum+1 { - lowLastBlock = mid + 1 + if midBlockL1Num < target { + currentBlock.low = mid + 1 } else { - highLastBlock = mid + currentBlock.high = mid } + return nil } + return nil } - err := checkCorrectness(highFirstBlock, l1BlockNum) - if err != nil { - return nil, err + firstBlock := &helperStruct{low: genesis, high: currentBlockNum} + lastBlock := &helperStruct{low: genesis, high: currentBlockNum} + // in storedMid low corresponds to value mid and high corresponds to midBlockL1Num inside searchHelper + storedMid := &helperStruct{low: currentBlockNum + 1} + var err error + for firstBlock.low < firstBlock.high || lastBlock.low < lastBlock.high { + if err = searchHelper(firstBlock, storedMid, l1BlockNum); err != nil { + return 0, 0, err + } + if err = searchHelper(lastBlock, storedMid, l1BlockNum+1); err != nil { + return 0, 0, err + } } - err = checkCorrectness(highLastBlock, l1BlockNum) - if err != nil { - highLastBlock -= 1 - err = checkCorrectness(highLastBlock, l1BlockNum) - if err != nil { - return nil, err + if err := n.matchL2BlockNumWithL1(firstBlock.high, l1BlockNum); err != nil { + return 0, 0, err + } + if err := n.matchL2BlockNumWithL1(lastBlock.high, l1BlockNum); err != nil { + lastBlock.high -= 1 + if err = n.matchL2BlockNumWithL1(lastBlock.high, l1BlockNum); err != nil { + return 0, 0, err } } - return []uint64{highFirstBlock, highLastBlock}, nil + return firstBlock.high, lastBlock.high, nil } diff --git a/system_tests/nodeinterface_test.go b/system_tests/nodeinterface_test.go index 266b50d6c..bfdff3d02 100644 --- a/system_tests/nodeinterface_test.go +++ b/system_tests/nodeinterface_test.go @@ -10,19 +10,11 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" "github.com/offchainlabs/nitro/arbos/util" "github.com/offchainlabs/nitro/solgen/go/node_interfacegen" ) -func getL1BlockNum(t *testing.T, ctx context.Context, client *ethclient.Client, l2BlockNum uint64) uint64 { - header, err := client.HeaderByNumber(ctx, big.NewInt(int64(l2BlockNum))) - Require(t, err) - l1BlockNum := types.DeserializeHeaderExtraInformation(header).L1BlockNumber - return l1BlockNum -} - -func TestGetL2BlockRangeForL1(t *testing.T) { +func TestL2BlockRangeForL1(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -32,7 +24,7 @@ func TestGetL2BlockRangeForL1(t *testing.T) { defer node.StopAndWait() user := l1info.GetDefaultTransactOpts("User", ctx) - numTransactions := 30 + numTransactions := 200 for i := 0; i < numTransactions; i++ { TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), l2info, l2client, ctx) } @@ -40,31 +32,42 @@ func TestGetL2BlockRangeForL1(t *testing.T) { nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) Require(t, err) + getBlockL1Num := func(l2BlockNum uint64) uint64 { + header, err := l2client.HeaderByNumber(ctx, big.NewInt(int64(l2BlockNum))) + Require(t, err) + l1BlockNum := types.DeserializeHeaderExtraInformation(header).L1BlockNumber + return l1BlockNum + } + l1BlockNums := map[uint64][]uint64{} latestL2, err := l2client.BlockNumber(ctx) Require(t, err) for l2BlockNum := uint64(0); l2BlockNum <= latestL2; l2BlockNum++ { - l1BlockNum := getL1BlockNum(t, ctx, l2client, l2BlockNum) - l1BlockNums[l1BlockNum] = append(l1BlockNums[l1BlockNum], l2BlockNum) + l1BlockNum := getBlockL1Num(l2BlockNum) + if len(l1BlockNums[l1BlockNum]) <= 1 { + l1BlockNums[l1BlockNum] = append(l1BlockNums[l1BlockNum], l2BlockNum) + } else { + l1BlockNums[l1BlockNum][1] = l2BlockNum + } } // Test success for l1BlockNum := range l1BlockNums { - rng, err := nodeInterface.GetL2BlockRangeForL1(&bind.CallOpts{}, l1BlockNum) + rng, err := nodeInterface.L2BlockRangeForL1(&bind.CallOpts{}, l1BlockNum) Require(t, err) n := len(l1BlockNums[l1BlockNum]) expected := []uint64{l1BlockNums[l1BlockNum][0], l1BlockNums[l1BlockNum][n-1]} - if expected[0] != rng[0] || expected[1] != rng[1] { - unexpectedL1BlockNum := getL1BlockNum(t, ctx, l2client, rng[1]) - // handle the edge case when new l2 blocks are produced between latestL2 was last calculated and now - if unexpectedL1BlockNum != l1BlockNum { - t.Fatalf("GetL2BlockRangeForL1 failed to get a valid range for L1 block number: %v. Given range: %v. Expected range: %v", l1BlockNum, rng, expected) + if expected[0] != rng.FirstBlock || expected[1] != rng.LastBlock { + unexpectedL1BlockNum := getBlockL1Num(rng.LastBlock) + // Handle the edge case when new l2 blocks are produced between latestL2 was last calculated and now. + if unexpectedL1BlockNum != l1BlockNum || rng.LastBlock < expected[1] { + t.Errorf("L2BlockRangeForL1(%d) = (%d %d) want (%d %d)", l1BlockNum, rng.FirstBlock, rng.LastBlock, expected[0], expected[1]) } } } // Test invalid case - finalValidL1BlockNumber := getL1BlockNum(t, ctx, l2client, latestL2) - _, err = nodeInterface.GetL2BlockRangeForL1(&bind.CallOpts{}, finalValidL1BlockNumber+1) + finalValidL1BlockNumber := getBlockL1Num(latestL2) + _, err = nodeInterface.L2BlockRangeForL1(&bind.CallOpts{}, finalValidL1BlockNumber+1) if err == nil { t.Fatalf("GetL2BlockRangeForL1 didn't fail for an invalid input") } From 0e444b077e50c2d0a4631dbbd18a9057458856e2 Mon Sep 17 00:00:00 2001 From: Nodar Date: Tue, 19 Sep 2023 14:56:10 +0200 Subject: [PATCH 153/775] Add flag to dataposter and clear leveldb when that flag is set --- arbnode/batch_poster.go | 4 +-- arbnode/dataposter/data_poster.go | 50 +++++++++++++++++++-------- arbnode/dataposter/leveldb/leveldb.go | 12 +++++++ arbnode/dataposter/storage_test.go | 27 +++++++++++++++ arbnode/node.go | 5 +-- system_tests/batch_poster_test.go | 2 +- system_tests/staker_test.go | 6 ++-- 7 files changed, 83 insertions(+), 23 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 89a36eba9..4f50831e6 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -210,7 +210,7 @@ var TestBatchPosterConfig = BatchPosterConfig{ L1BlockBoundBypass: time.Hour, } -func NewBatchPoster(dataPosterDB ethdb.Database, l1Reader *headerreader.HeaderReader, inbox *InboxTracker, streamer *TransactionStreamer, syncMonitor *SyncMonitor, config BatchPosterConfigFetcher, deployInfo *chaininfo.RollupAddresses, transactOpts *bind.TransactOpts, daWriter das.DataAvailabilityServiceWriter) (*BatchPoster, error) { +func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader *headerreader.HeaderReader, inbox *InboxTracker, streamer *TransactionStreamer, syncMonitor *SyncMonitor, config BatchPosterConfigFetcher, deployInfo *chaininfo.RollupAddresses, transactOpts *bind.TransactOpts, daWriter das.DataAvailabilityServiceWriter) (*BatchPoster, error) { seqInbox, err := bridgegen.NewSequencerInbox(deployInfo.SequencerInbox, l1Reader.Client()) if err != nil { return nil, err @@ -253,7 +253,7 @@ func NewBatchPoster(dataPosterDB ethdb.Database, l1Reader *headerreader.HeaderRe dataPosterConfigFetcher := func() *dataposter.DataPosterConfig { return &config().DataPoster } - b.dataPoster, err = dataposter.NewDataPoster(dataPosterDB, l1Reader, transactOpts, redisClient, redisLock, dataPosterConfigFetcher, b.getBatchPosterPosition) + b.dataPoster, err = dataposter.NewDataPoster(ctx, dataPosterDB, l1Reader, transactOpts, redisClient, redisLock, dataPosterConfigFetcher, b.getBatchPosterPosition) if err != nil { return nil, err } diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index b1e6555b2..546cedfa3 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -91,7 +91,7 @@ func parseReplacementTimes(val string) ([]time.Duration, error) { return append(res, time.Hour*24*365*10), nil } -func NewDataPoster(db ethdb.Database, headerReader *headerreader.HeaderReader, auth *bind.TransactOpts, redisClient redis.UniversalClient, redisLock AttemptLocker, config ConfigFetcher, metadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error)) (*DataPoster, error) { +func NewDataPoster(ctx context.Context, db ethdb.Database, headerReader *headerreader.HeaderReader, auth *bind.TransactOpts, redisClient redis.UniversalClient, redisLock AttemptLocker, config ConfigFetcher, metadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error)) (*DataPoster, error) { initConfig := config() replacementTimes, err := parseReplacementTimes(initConfig.ReplacementTimes) if err != nil { @@ -118,7 +118,13 @@ func NewDataPoster(db ethdb.Database, headerReader *headerreader.HeaderReader, a return nil, err } case initConfig.UseLevelDB: - queue = leveldb.New(db, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) + ldb := leveldb.New(db, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) + if config().Dangerous.ClearLevelDB { + if err := ldb.PruneAll(ctx); err != nil { + return nil, err + } + } + queue = ldb default: queue = slice.NewStorage(func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) } @@ -618,19 +624,26 @@ type DataPosterConfig struct { ReplacementTimes string `koanf:"replacement-times"` // This is forcibly disabled if the parent chain is an Arbitrum chain, // so you should probably use DataPoster's waitForL1Finality method instead of reading this field directly. - WaitForL1Finality bool `koanf:"wait-for-l1-finality" reload:"hot"` - MaxMempoolTransactions uint64 `koanf:"max-mempool-transactions" reload:"hot"` - MaxQueuedTransactions int `koanf:"max-queued-transactions" reload:"hot"` - TargetPriceGwei float64 `koanf:"target-price-gwei" reload:"hot"` - UrgencyGwei float64 `koanf:"urgency-gwei" reload:"hot"` - MinFeeCapGwei float64 `koanf:"min-fee-cap-gwei" reload:"hot"` - MinTipCapGwei float64 `koanf:"min-tip-cap-gwei" reload:"hot"` - MaxTipCapGwei float64 `koanf:"max-tip-cap-gwei" reload:"hot"` - NonceRbfSoftConfs uint64 `koanf:"nonce-rbf-soft-confs" reload:"hot"` - AllocateMempoolBalance bool `koanf:"allocate-mempool-balance" reload:"hot"` - UseLevelDB bool `koanf:"use-leveldb"` - UseNoOpStorage bool `koanf:"use-noop-storage"` - LegacyStorageEncoding bool `koanf:"legacy-storage-encoding" reload:"hot"` + WaitForL1Finality bool `koanf:"wait-for-l1-finality" reload:"hot"` + MaxMempoolTransactions uint64 `koanf:"max-mempool-transactions" reload:"hot"` + MaxQueuedTransactions int `koanf:"max-queued-transactions" reload:"hot"` + TargetPriceGwei float64 `koanf:"target-price-gwei" reload:"hot"` + UrgencyGwei float64 `koanf:"urgency-gwei" reload:"hot"` + MinFeeCapGwei float64 `koanf:"min-fee-cap-gwei" reload:"hot"` + MinTipCapGwei float64 `koanf:"min-tip-cap-gwei" reload:"hot"` + MaxTipCapGwei float64 `koanf:"max-tip-cap-gwei" reload:"hot"` + NonceRbfSoftConfs uint64 `koanf:"nonce-rbf-soft-confs" reload:"hot"` + AllocateMempoolBalance bool `koanf:"allocate-mempool-balance" reload:"hot"` + UseLevelDB bool `koanf:"use-leveldb"` + UseNoOpStorage bool `koanf:"use-noop-storage"` + LegacyStorageEncoding bool `koanf:"legacy-storage-encoding" reload:"hot"` + Dangerous DangerousConfig `koanf:"dangerous"` +} + +type DangerousConfig struct { + // This should be used with caution, only when dataposter somehow gets in a + // bad state and we require clearing it. + ClearLevelDB bool `koanf:"clear-leveldb"` } // ConfigFetcher function type is used instead of directly passing config so @@ -652,7 +665,13 @@ func DataPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Bool(prefix+".use-leveldb", DefaultDataPosterConfig.UseLevelDB, "uses leveldb when enabled") f.Bool(prefix+".use-noop-storage", DefaultDataPosterConfig.UseNoOpStorage, "uses noop storage, it doesn't store anything") f.Bool(prefix+".legacy-storage-encoding", DefaultDataPosterConfig.LegacyStorageEncoding, "encodes items in a legacy way (as it was before dropping generics)") + signature.SimpleHmacConfigAddOptions(prefix+".redis-signer", f) + addDangerousOptions(prefix+".dangerous", f) +} + +func addDangerousOptions(prefix string, f *pflag.FlagSet) { + f.Bool(prefix+".clear-leveldb", DefaultDataPosterConfig.Dangerous.ClearLevelDB, "clear leveldb") } var DefaultDataPosterConfig = DataPosterConfig{ @@ -668,6 +687,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ UseLevelDB: true, UseNoOpStorage: false, LegacyStorageEncoding: true, + Dangerous: DangerousConfig{ClearLevelDB: false}, } var DefaultDataPosterConfigForValidator = func() DataPosterConfig { diff --git a/arbnode/dataposter/leveldb/leveldb.go b/arbnode/dataposter/leveldb/leveldb.go index cfb34b04f..7c6560297 100644 --- a/arbnode/dataposter/leveldb/leveldb.go +++ b/arbnode/dataposter/leveldb/leveldb.go @@ -79,6 +79,18 @@ func (s *Storage) FetchLast(ctx context.Context) (*storage.QueuedTransaction, er return s.encDec().Decode(val) } +func (s *Storage) PruneAll(ctx context.Context) error { + idx, err := s.lastItemIdx(ctx) + if err != nil { + return fmt.Errorf("pruning all keys: %w", err) + } + until, err := strconv.Atoi(string(idx)) + if err != nil { + return fmt.Errorf("converting last item index bytes to integer: %w", err) + } + return s.Prune(ctx, uint64(until+1)) +} + func (s *Storage) Prune(ctx context.Context, until uint64) error { cnt, err := s.Length(ctx) if err != nil { diff --git a/arbnode/dataposter/storage_test.go b/arbnode/dataposter/storage_test.go index d536e5da0..0b3df5012 100644 --- a/arbnode/dataposter/storage_test.go +++ b/arbnode/dataposter/storage_test.go @@ -135,6 +135,33 @@ func initStorages(ctx context.Context, t *testing.T) map[string]QueueStorage { return m } +func TestPruneAll(t *testing.T) { + s := newLevelDBStorage(t, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) + ctx := context.Background() + for i := 0; i < 20; i++ { + if err := s.Put(ctx, uint64(i), nil, valueOf(t, i)); err != nil { + t.Fatalf("Error putting a key/value: %v", err) + } + } + size, err := s.Length(ctx) + if err != nil { + t.Fatalf("Length() unexpected error %v", err) + } + if size != 20 { + t.Errorf("Length()=%v want 20", size) + } + if err := s.PruneAll(ctx); err != nil { + t.Fatalf("PruneAll() unexpected error: %v", err) + } + size, err = s.Length(ctx) + if err != nil { + t.Fatalf("Length() unexpected error %v", err) + } + if size != 0 { + t.Errorf("Length()=%v want 0", size) + } +} + func TestFetchContents(t *testing.T) { ctx := context.Background() for name, s := range initStorages(ctx, t) { diff --git a/arbnode/node.go b/arbnode/node.go index 5bdc71626..a2e526b09 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -540,7 +540,7 @@ func checkArbDbSchemaVersion(arbDb ethdb.Database) error { } func StakerDataposter( - db ethdb.Database, l1Reader *headerreader.HeaderReader, + ctx context.Context, db ethdb.Database, l1Reader *headerreader.HeaderReader, transactOpts *bind.TransactOpts, cfgFetcher ConfigFetcher, syncMonitor *SyncMonitor, ) (*dataposter.DataPoster, error) { if transactOpts == nil { @@ -564,7 +564,7 @@ func StakerDataposter( dpCfg := func() *dataposter.DataPosterConfig { return &cfg.Staker.DataPoster } - return dataposter.NewDataPoster(db, l1Reader, transactOpts, redisC, redisLock, dpCfg, mdRetriever) + return dataposter.NewDataPoster(ctx, db, l1Reader, transactOpts, redisC, redisLock, dpCfg, mdRetriever) } func createNodeImpl( @@ -805,6 +805,7 @@ func createNodeImpl( if config.Staker.Enable { dp, err := StakerDataposter( + ctx, rawdb.NewTable(arbDb, storage.StakerPrefix), l1Reader, txOptsValidator, diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 11bf92608..8b0811c22 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -82,7 +82,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { for i := 0; i < parallelBatchPosters; i++ { // Make a copy of the batch poster config so NewBatchPoster calling Validate() on it doesn't race batchPosterConfig := conf.BatchPoster - batchPoster, err := arbnode.NewBatchPoster(nil, nodeA.L1Reader, nodeA.InboxTracker, nodeA.TxStreamer, nodeA.SyncMonitor, func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, nodeA.DeployInfo, &seqTxOpts, nil) + batchPoster, err := arbnode.NewBatchPoster(ctx, nil, nodeA.L1Reader, nodeA.InboxTracker, nodeA.TxStreamer, nodeA.SyncMonitor, func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, nodeA.DeployInfo, &seqTxOpts, nil) Require(t, err) batchPoster.Start(ctx) defer batchPoster.StopAndWait() diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 96ea1ee2e..b4ce67b17 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -130,7 +130,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) valConfig := staker.TestL1ValidatorConfig - dpA, err := arbnode.StakerDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) + dpA, err := arbnode.StakerDataposter(ctx, rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } @@ -178,7 +178,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } Require(t, err) - dpB, err := arbnode.StakerDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeB.L1Reader, &l1authB, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) + dpB, err := arbnode.StakerDataposter(ctx, rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeB.L1Reader, &l1authB, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } @@ -217,7 +217,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) err = valWalletB.Initialize(ctx) Require(t, err) } - dpC, err := arbnode.StakerDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) + dpC, err := arbnode.StakerDataposter(ctx, rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } From 9fd0ff5f9b59c2b73aa42f8426ec1bf8acfa9fa2 Mon Sep 17 00:00:00 2001 From: Nodar Date: Tue, 19 Sep 2023 15:21:31 +0200 Subject: [PATCH 154/775] Pass context to batch poster --- arbnode/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/node.go b/arbnode/node.go index a2e526b09..28f0ada33 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -874,7 +874,7 @@ func createNodeImpl( if txOptsBatchPoster == nil { return nil, errors.New("batchposter, but no TxOpts") } - batchPoster, err = NewBatchPoster(rawdb.NewTable(arbDb, storage.BatchPosterPrefix), l1Reader, inboxTracker, txStreamer, syncMonitor, func() *BatchPosterConfig { return &configFetcher.Get().BatchPoster }, deployInfo, txOptsBatchPoster, daWriter) + batchPoster, err = NewBatchPoster(ctx, rawdb.NewTable(arbDb, storage.BatchPosterPrefix), l1Reader, inboxTracker, txStreamer, syncMonitor, func() *BatchPosterConfig { return &configFetcher.Get().BatchPoster }, deployInfo, txOptsBatchPoster, daWriter) if err != nil { return nil, err } From 2aa15ad45eaf2f8390e12c75611cf3e29cd16bf0 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 19 Sep 2023 15:44:00 -0600 Subject: [PATCH 155/775] Add an optional limit to the maximum size of the relay catchup buffer --- broadcaster/broadcaster.go | 2 +- broadcaster/sequencenumbercatchupbuffer.go | 29 +++++++++--- .../sequencenumbercatchupbuffer_test.go | 47 +++++++++++++++++++ wsbroadcastserver/wsbroadcastserver.go | 4 ++ 4 files changed, 75 insertions(+), 7 deletions(-) diff --git a/broadcaster/broadcaster.go b/broadcaster/broadcaster.go index bde80c93d..c3f4c62ce 100644 --- a/broadcaster/broadcaster.go +++ b/broadcaster/broadcaster.go @@ -61,7 +61,7 @@ type ConfirmedSequenceNumberMessage struct { } func NewBroadcaster(config wsbroadcastserver.BroadcasterConfigFetcher, chainId uint64, feedErrChan chan error, dataSigner signature.DataSignerFunc) *Broadcaster { - catchupBuffer := NewSequenceNumberCatchupBuffer(func() bool { return config().LimitCatchup }) + catchupBuffer := NewSequenceNumberCatchupBuffer(func() bool { return config().LimitCatchup }, func() int { return config().MaxCatchup }) return &Broadcaster{ server: wsbroadcastserver.NewWSBroadcastServer(config, catchupBuffer, chainId, feedErrChan), catchupBuffer: catchupBuffer, diff --git a/broadcaster/sequencenumbercatchupbuffer.go b/broadcaster/sequencenumbercatchupbuffer.go index 7664f1b8d..bdd3e60c5 100644 --- a/broadcaster/sequencenumbercatchupbuffer.go +++ b/broadcaster/sequencenumbercatchupbuffer.go @@ -29,11 +29,13 @@ type SequenceNumberCatchupBuffer struct { messages []*BroadcastFeedMessage messageCount int32 limitCatchup func() bool + maxCatchup func() int } -func NewSequenceNumberCatchupBuffer(limitCatchup func() bool) *SequenceNumberCatchupBuffer { +func NewSequenceNumberCatchupBuffer(limitCatchup func() bool, maxCatchup func() int) *SequenceNumberCatchupBuffer { return &SequenceNumberCatchupBuffer{ limitCatchup: limitCatchup, + maxCatchup: maxCatchup, } } @@ -98,6 +100,15 @@ func (b *SequenceNumberCatchupBuffer) OnRegisterClient(clientConnection *wsbroad return nil, bmCount, time.Since(start) } +// Takes as input an index into the messages array, not a message index +func (b *SequenceNumberCatchupBuffer) pruneBufferToIndex(idx int) { + b.messages = b.messages[idx:] + if len(b.messages) > 10 && cap(b.messages) > len(b.messages)*10 { + // Too much spare capacity, copy to fresh slice to reset memory usage + b.messages = append([]*BroadcastFeedMessage(nil), b.messages[:len(b.messages)]...) + } +} + func (b *SequenceNumberCatchupBuffer) deleteConfirmed(confirmedSequenceNumber arbutil.MessageIndex) { if len(b.messages) == 0 { return @@ -126,11 +137,7 @@ func (b *SequenceNumberCatchupBuffer) deleteConfirmed(confirmedSequenceNumber ar return } - b.messages = b.messages[confirmedIndex+1:] - if len(b.messages) > 10 && cap(b.messages) > len(b.messages)*10 { - // Too much spare capacity, copy to fresh slice to reset memory usage - b.messages = append([]*BroadcastFeedMessage(nil), b.messages[:len(b.messages)]...) - } + b.pruneBufferToIndex(int(confirmedIndex) + 1) } func (b *SequenceNumberCatchupBuffer) OnDoBroadcast(bmi interface{}) error { @@ -147,6 +154,12 @@ func (b *SequenceNumberCatchupBuffer) OnDoBroadcast(bmi interface{}) error { confirmedSequenceNumberGauge.Update(int64(confirmMsg.SequenceNumber)) } + maxCatchup := b.maxCatchup() + if maxCatchup == 0 { + b.messages = nil + return nil + } + for _, newMsg := range broadcastMessage.Messages { if len(b.messages) == 0 { // Add to empty list @@ -167,6 +180,10 @@ func (b *SequenceNumberCatchupBuffer) OnDoBroadcast(bmi interface{}) error { } } + if maxCatchup >= 0 && len(b.messages) > maxCatchup { + b.pruneBufferToIndex(len(b.messages) - maxCatchup) + } + return nil } diff --git a/broadcaster/sequencenumbercatchupbuffer_test.go b/broadcaster/sequencenumbercatchupbuffer_test.go index 40fae9875..17d850d9e 100644 --- a/broadcaster/sequencenumbercatchupbuffer_test.go +++ b/broadcaster/sequencenumbercatchupbuffer_test.go @@ -22,6 +22,7 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/util/arbmath" ) func TestGetEmptyCacheMessages(t *testing.T) { @@ -29,6 +30,7 @@ func TestGetEmptyCacheMessages(t *testing.T) { messages: nil, messageCount: 0, limitCatchup: func() bool { return false }, + maxCatchup: func() int { return -1 }, } // Get everything @@ -60,6 +62,7 @@ func TestGetCacheMessages(t *testing.T) { messages: createDummyBroadcastMessages(indexes), messageCount: int32(len(indexes)), limitCatchup: func() bool { return false }, + maxCatchup: func() int { return -1 }, } // Get everything @@ -110,6 +113,7 @@ func TestDeleteConfirmedNil(t *testing.T) { messages: nil, messageCount: 0, limitCatchup: func() bool { return false }, + maxCatchup: func() int { return -1 }, } buffer.deleteConfirmed(0) @@ -124,6 +128,7 @@ func TestDeleteConfirmInvalidOrder(t *testing.T) { messages: createDummyBroadcastMessages(indexes), messageCount: int32(len(indexes)), limitCatchup: func() bool { return false }, + maxCatchup: func() int { return -1 }, } // Confirm before cache @@ -139,6 +144,7 @@ func TestDeleteConfirmed(t *testing.T) { messages: createDummyBroadcastMessages(indexes), messageCount: int32(len(indexes)), limitCatchup: func() bool { return false }, + maxCatchup: func() int { return -1 }, } // Confirm older than cache @@ -154,6 +160,7 @@ func TestDeleteFreeMem(t *testing.T) { messages: createDummyBroadcastMessagesImpl(indexes, len(indexes)*10+1), messageCount: int32(len(indexes)), limitCatchup: func() bool { return false }, + maxCatchup: func() int { return -1 }, } // Confirm older than cache @@ -169,6 +176,7 @@ func TestBroadcastBadMessage(t *testing.T) { messages: nil, messageCount: 0, limitCatchup: func() bool { return false }, + maxCatchup: func() int { return -1 }, } var foo int @@ -187,6 +195,7 @@ func TestBroadcastPastSeqNum(t *testing.T) { messages: createDummyBroadcastMessagesImpl(indexes, len(indexes)*10+1), messageCount: int32(len(indexes)), limitCatchup: func() bool { return false }, + maxCatchup: func() int { return -1 }, } bm := BroadcastMessage{ @@ -208,6 +217,8 @@ func TestBroadcastFutureSeqNum(t *testing.T) { buffer := SequenceNumberCatchupBuffer{ messages: createDummyBroadcastMessagesImpl(indexes, len(indexes)*10+1), messageCount: int32(len(indexes)), + limitCatchup: func() bool { return false }, + maxCatchup: func() int { return -1 }, } bm := BroadcastMessage{ @@ -223,3 +234,39 @@ func TestBroadcastFutureSeqNum(t *testing.T) { } } + +func TestMaxCatchupBufferSize(t *testing.T) { + limit := 5 + buffer := SequenceNumberCatchupBuffer{ + messages: nil, + messageCount: 0, + limitCatchup: func() bool { return false }, + maxCatchup: func() int { return limit }, + } + + for i := 10; i <= 20; i += 2 { + bm := BroadcastMessage{ + Messages: []*BroadcastFeedMessage{ + { + SequenceNumber: arbutil.MessageIndex(i), + }, + { + SequenceNumber: arbutil.MessageIndex(i + 1), + }, + }, + } + err := buffer.OnDoBroadcast(bm) + if err != nil { + t.Error("expected error") + } + haveMessages := buffer.getCacheMessages(0) + expectedCount := arbmath.MinInt(i+2-10, limit) + if len(haveMessages.Messages) != expectedCount { + t.Errorf("after broadcasting messages %v and %v, expected to have %v messages but got %v", i, i+1, expectedCount, len(haveMessages.Messages)) + } + expectedFirstMessage := arbutil.MessageIndex(arbmath.MaxInt(10, i+2-limit)) + if haveMessages.Messages[0].SequenceNumber != expectedFirstMessage { + t.Errorf("after broadcasting messages %v and %v, expected the first message to be %v but got %v", i, i+1, expectedFirstMessage, haveMessages.Messages[0].SequenceNumber) + } + } +} diff --git a/wsbroadcastserver/wsbroadcastserver.go b/wsbroadcastserver/wsbroadcastserver.go index 014995cee..cd277387a 100644 --- a/wsbroadcastserver/wsbroadcastserver.go +++ b/wsbroadcastserver/wsbroadcastserver.go @@ -60,6 +60,7 @@ type BroadcasterConfig struct { EnableCompression bool `koanf:"enable-compression" reload:"hot"` // if reloaded to false will cause disconnection of clients with enabled compression on next broadcast RequireCompression bool `koanf:"require-compression" reload:"hot"` // if reloaded to true will cause disconnection of clients with disabled compression on next broadcast LimitCatchup bool `koanf:"limit-catchup" reload:"hot"` + MaxCatchup int `koanf:"max-catchup" reload:"hot"` ConnectionLimits ConnectionLimiterConfig `koanf:"connection-limits" reload:"hot"` ClientDelay time.Duration `koanf:"client-delay" reload:"hot"` } @@ -93,6 +94,7 @@ func BroadcasterConfigAddOptions(prefix string, f *flag.FlagSet) { f.Bool(prefix+".enable-compression", DefaultBroadcasterConfig.EnableCompression, "enable per message deflate compression support") f.Bool(prefix+".require-compression", DefaultBroadcasterConfig.RequireCompression, "require clients to use compression") f.Bool(prefix+".limit-catchup", DefaultBroadcasterConfig.LimitCatchup, "only supply catchup buffer if requested sequence number is reasonable") + f.Int(prefix+".max-catchup", DefaultBroadcasterConfig.MaxCatchup, "the maximum size of the catchup buffer (-1 means unlimited)") ConnectionLimiterConfigAddOptions(prefix+".connection-limits", f) f.Duration(prefix+".client-delay", DefaultBroadcasterConfig.ClientDelay, "delay the first messages sent to each client by this amount") } @@ -117,6 +119,7 @@ var DefaultBroadcasterConfig = BroadcasterConfig{ EnableCompression: true, RequireCompression: false, LimitCatchup: false, + MaxCatchup: -1, ConnectionLimits: DefaultConnectionLimiterConfig, ClientDelay: 0, } @@ -141,6 +144,7 @@ var DefaultTestBroadcasterConfig = BroadcasterConfig{ EnableCompression: true, RequireCompression: false, LimitCatchup: false, + MaxCatchup: -1, ConnectionLimits: DefaultConnectionLimiterConfig, ClientDelay: 0, } From 724e82aa8d771f7f4f7f4de94175c029d3e95ca1 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 19 Sep 2023 15:45:05 -0600 Subject: [PATCH 156/775] Make constants in test clearer --- broadcaster/sequencenumbercatchupbuffer_test.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/broadcaster/sequencenumbercatchupbuffer_test.go b/broadcaster/sequencenumbercatchupbuffer_test.go index 17d850d9e..fc6655057 100644 --- a/broadcaster/sequencenumbercatchupbuffer_test.go +++ b/broadcaster/sequencenumbercatchupbuffer_test.go @@ -244,7 +244,8 @@ func TestMaxCatchupBufferSize(t *testing.T) { maxCatchup: func() int { return limit }, } - for i := 10; i <= 20; i += 2 { + firstMessage := 10 + for i := firstMessage; i <= 20; i += 2 { bm := BroadcastMessage{ Messages: []*BroadcastFeedMessage{ { @@ -256,15 +257,13 @@ func TestMaxCatchupBufferSize(t *testing.T) { }, } err := buffer.OnDoBroadcast(bm) - if err != nil { - t.Error("expected error") - } + Require(t, err) haveMessages := buffer.getCacheMessages(0) - expectedCount := arbmath.MinInt(i+2-10, limit) + expectedCount := arbmath.MinInt(i+len(bm.Messages)-firstMessage, limit) if len(haveMessages.Messages) != expectedCount { t.Errorf("after broadcasting messages %v and %v, expected to have %v messages but got %v", i, i+1, expectedCount, len(haveMessages.Messages)) } - expectedFirstMessage := arbutil.MessageIndex(arbmath.MaxInt(10, i+2-limit)) + expectedFirstMessage := arbutil.MessageIndex(arbmath.MaxInt(firstMessage, i+len(bm.Messages)-limit)) if haveMessages.Messages[0].SequenceNumber != expectedFirstMessage { t.Errorf("after broadcasting messages %v and %v, expected the first message to be %v but got %v", i, i+1, expectedFirstMessage, haveMessages.Messages[0].SequenceNumber) } From 9b2788f8dfd6f915f27b2f10323f809d8d34b477 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 20 Sep 2023 11:05:34 -0500 Subject: [PATCH 157/775] address PR comments --- contracts | 2 +- nodeInterface/NodeInterface.go | 75 ++++++++++++------------------ system_tests/nodeinterface_test.go | 34 ++++++-------- 3 files changed, 46 insertions(+), 65 deletions(-) diff --git a/contracts b/contracts index 436e1cf82..9edc1b943 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 436e1cf82c5696eb918d842256328ba86fbe5019 +Subproject commit 9edc1b943ed0255f050f91f265d96bc1ad9de1a2 diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index 98394f934..e990383a3 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -591,7 +591,7 @@ func (n NodeInterface) LegacyLookupMessageBatchProof(c ctx, evm mech, batchNum h return } -func (n NodeInterface) blockL1Num(l2BlockNum uint64) (uint64, error) { +func (n NodeInterface) BlockL1Num(c ctx, evm mech, l2BlockNum uint64) (uint64, error) { blockHeader, err := n.backend.HeaderByNumber(n.context, rpc.BlockNumber(l2BlockNum)) if err != nil { return 0, err @@ -600,8 +600,8 @@ func (n NodeInterface) blockL1Num(l2BlockNum uint64) (uint64, error) { return blockL1Num, nil } -func (n NodeInterface) matchL2BlockNumWithL1(l2BlockNum uint64, l1BlockNum uint64) error { - blockL1Num, err := n.blockL1Num(l2BlockNum) +func (n NodeInterface) matchL2BlockNumWithL1(c ctx, evm mech, l2BlockNum uint64, l1BlockNum uint64) error { + blockL1Num, err := n.BlockL1Num(c, evm, l2BlockNum) if err != nil { return fmt.Errorf("failed to get the L1 block number of the L2 block: %v. Error: %w", l2BlockNum, err) } @@ -616,57 +616,44 @@ func (n NodeInterface) L2BlockRangeForL1(c ctx, evm mech, l1BlockNum uint64) (ui currentBlockNum := n.backend.CurrentBlock().Number.Uint64() genesis := n.backend.ChainConfig().ArbitrumChainParams.GenesisBlockNum - type helperStruct struct { - low uint64 - high uint64 - } - - searchHelper := func(currentBlock *helperStruct, fetchedMid *helperStruct, target uint64) error { - if currentBlock.low < currentBlock.high { - // dont fetch midBlockL1Num if its already fetched above - mid := arbmath.SaturatingUAdd(currentBlock.low, currentBlock.high) / 2 - var midBlockL1Num uint64 - var err error - if mid == fetchedMid.low { - midBlockL1Num = fetchedMid.high - } else { - midBlockL1Num, err = n.blockL1Num(mid) + storedMids := map[uint64]uint64{} + firstL2BlockForL1 := func(target uint64) (uint64, error) { + low, high := genesis, currentBlockNum + for low < high { + mid := arbmath.SaturatingUAdd(low, high) / 2 + if _, ok := storedMids[mid]; !ok { + midBlockL1Num, err := n.BlockL1Num(c, evm, mid) if err != nil { - return err + return 0, err } - fetchedMid.low = mid - fetchedMid.high = midBlockL1Num + storedMids[mid] = midBlockL1Num } - if midBlockL1Num < target { - currentBlock.low = mid + 1 + if storedMids[mid] < target { + low = mid + 1 } else { - currentBlock.high = mid + high = mid } - return nil - } - return nil - } - firstBlock := &helperStruct{low: genesis, high: currentBlockNum} - lastBlock := &helperStruct{low: genesis, high: currentBlockNum} - // in storedMid low corresponds to value mid and high corresponds to midBlockL1Num inside searchHelper - storedMid := &helperStruct{low: currentBlockNum + 1} - var err error - for firstBlock.low < firstBlock.high || lastBlock.low < lastBlock.high { - if err = searchHelper(firstBlock, storedMid, l1BlockNum); err != nil { - return 0, 0, err - } - if err = searchHelper(lastBlock, storedMid, l1BlockNum+1); err != nil { - return 0, 0, err } + return high, nil } - if err := n.matchL2BlockNumWithL1(firstBlock.high, l1BlockNum); err != nil { + + firstBlock, err := firstL2BlockForL1(l1BlockNum) + if err != nil { + return 0, 0, err + } + lastBlock, err := firstL2BlockForL1(l1BlockNum + 1) + if err != nil { + return 0, 0, err + } + + if err := n.matchL2BlockNumWithL1(c, evm, firstBlock, l1BlockNum); err != nil { return 0, 0, err } - if err := n.matchL2BlockNumWithL1(lastBlock.high, l1BlockNum); err != nil { - lastBlock.high -= 1 - if err = n.matchL2BlockNumWithL1(lastBlock.high, l1BlockNum); err != nil { + if err := n.matchL2BlockNumWithL1(c, evm, lastBlock, l1BlockNum); err != nil { + lastBlock -= 1 + if err = n.matchL2BlockNumWithL1(c, evm, lastBlock, l1BlockNum); err != nil { return 0, 0, err } } - return firstBlock.high, lastBlock.high, nil + return firstBlock, lastBlock, nil } diff --git a/system_tests/nodeinterface_test.go b/system_tests/nodeinterface_test.go index bfdff3d02..3389dda7c 100644 --- a/system_tests/nodeinterface_test.go +++ b/system_tests/nodeinterface_test.go @@ -32,22 +32,16 @@ func TestL2BlockRangeForL1(t *testing.T) { nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) Require(t, err) - getBlockL1Num := func(l2BlockNum uint64) uint64 { - header, err := l2client.HeaderByNumber(ctx, big.NewInt(int64(l2BlockNum))) - Require(t, err) - l1BlockNum := types.DeserializeHeaderExtraInformation(header).L1BlockNumber - return l1BlockNum - } - - l1BlockNums := map[uint64][]uint64{} + l1BlockNums := map[uint64][2]uint64{} latestL2, err := l2client.BlockNumber(ctx) Require(t, err) for l2BlockNum := uint64(0); l2BlockNum <= latestL2; l2BlockNum++ { - l1BlockNum := getBlockL1Num(l2BlockNum) - if len(l1BlockNums[l1BlockNum]) <= 1 { - l1BlockNums[l1BlockNum] = append(l1BlockNums[l1BlockNum], l2BlockNum) + l1BlockNum, err := nodeInterface.BlockL1Num(&bind.CallOpts{}, l2BlockNum) + Require(t, err) + if _, ok := l1BlockNums[l1BlockNum]; !ok { + l1BlockNums[l1BlockNum] = [2]uint64{l2BlockNum, l2BlockNum} } else { - l1BlockNums[l1BlockNum][1] = l2BlockNum + l1BlockNums[l1BlockNum] = [2]uint64{l1BlockNums[l1BlockNum][0], l2BlockNum} } } @@ -55,20 +49,20 @@ func TestL2BlockRangeForL1(t *testing.T) { for l1BlockNum := range l1BlockNums { rng, err := nodeInterface.L2BlockRangeForL1(&bind.CallOpts{}, l1BlockNum) Require(t, err) - n := len(l1BlockNums[l1BlockNum]) - expected := []uint64{l1BlockNums[l1BlockNum][0], l1BlockNums[l1BlockNum][n-1]} - if expected[0] != rng.FirstBlock || expected[1] != rng.LastBlock { - unexpectedL1BlockNum := getBlockL1Num(rng.LastBlock) + expected := l1BlockNums[l1BlockNum] + if rng.FirstBlock != expected[0] || rng.LastBlock != expected[1] { + unexpectedL1BlockNum, err := nodeInterface.BlockL1Num(&bind.CallOpts{}, rng.LastBlock) + Require(t, err) // Handle the edge case when new l2 blocks are produced between latestL2 was last calculated and now. - if unexpectedL1BlockNum != l1BlockNum || rng.LastBlock < expected[1] { + if unexpectedL1BlockNum != l1BlockNum || rng.LastBlock < expected[1] || rng.FirstBlock != expected[0] { t.Errorf("L2BlockRangeForL1(%d) = (%d %d) want (%d %d)", l1BlockNum, rng.FirstBlock, rng.LastBlock, expected[0], expected[1]) } } } // Test invalid case - finalValidL1BlockNumber := getBlockL1Num(latestL2) - _, err = nodeInterface.L2BlockRangeForL1(&bind.CallOpts{}, finalValidL1BlockNumber+1) - if err == nil { + finalValidL1BlockNumber, err := nodeInterface.BlockL1Num(&bind.CallOpts{}, latestL2) + Require(t, err) + if _, err := nodeInterface.L2BlockRangeForL1(&bind.CallOpts{}, finalValidL1BlockNumber+1); err == nil { t.Fatalf("GetL2BlockRangeForL1 didn't fail for an invalid input") } From 0979ae8bcc6497537bec0bcd3f793ae41f2035f2 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Wed, 20 Sep 2023 17:07:14 -0700 Subject: [PATCH 158/775] Add DAS error when 1 error away from failure --- das/aggregator.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/das/aggregator.go b/das/aggregator.go index 3b34f1276..e8cc0a3c2 100644 --- a/das/aggregator.go +++ b/das/aggregator.go @@ -290,6 +290,10 @@ func (a *Aggregator) Store(ctx context.Context, message []byte, timeout uint64, cd.aggSignersMask = aggSignersMask certDetailsChan <- cd returned = true + if a.maxAllowedServiceStoreFailures > 0 && // Ignore the case where AssumedHonest = 1, probably a testnet + storeFailures+1 > a.maxAllowedServiceStoreFailures { + log.Error("das.Aggregator: storing the batch data succeeded to enough DAS commitee members to generate the Data Availability Cert, but if one more had failed then the cert would not have been able to be generated. Look for preceding logs with \"Error from backend\"") + } } else if storeFailures > a.maxAllowedServiceStoreFailures { cd := certDetails{} cd.err = fmt.Errorf("aggregator failed to store message to at least %d out of %d DASes (assuming %d are honest). %w", a.requiredServicesForStore, len(a.services), a.config.AssumedHonest, BatchToDasFailed) From 994d0b5b9a640e8cc745c39a24373a5127f867d7 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 21 Sep 2023 09:17:47 -0500 Subject: [PATCH 159/775] code refactor --- nodeInterface/NodeInterface.go | 4 ++-- system_tests/nodeinterface_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index e990383a3..2a45ac033 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -639,11 +639,11 @@ func (n NodeInterface) L2BlockRangeForL1(c ctx, evm mech, l1BlockNum uint64) (ui firstBlock, err := firstL2BlockForL1(l1BlockNum) if err != nil { - return 0, 0, err + return 0, 0, fmt.Errorf("failed to get the first L2 block with the L1 block: %v. Error: %w", l1BlockNum, err) } lastBlock, err := firstL2BlockForL1(l1BlockNum + 1) if err != nil { - return 0, 0, err + return 0, 0, fmt.Errorf("failed to get the last L2 block with the L1 block: %v. Error: %w", l1BlockNum, err) } if err := n.matchL2BlockNumWithL1(c, evm, firstBlock, l1BlockNum); err != nil { diff --git a/system_tests/nodeinterface_test.go b/system_tests/nodeinterface_test.go index 3389dda7c..63b3d7bb7 100644 --- a/system_tests/nodeinterface_test.go +++ b/system_tests/nodeinterface_test.go @@ -32,16 +32,16 @@ func TestL2BlockRangeForL1(t *testing.T) { nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) Require(t, err) - l1BlockNums := map[uint64][2]uint64{} + l1BlockNums := map[uint64]*[2]uint64{} latestL2, err := l2client.BlockNumber(ctx) Require(t, err) for l2BlockNum := uint64(0); l2BlockNum <= latestL2; l2BlockNum++ { l1BlockNum, err := nodeInterface.BlockL1Num(&bind.CallOpts{}, l2BlockNum) Require(t, err) if _, ok := l1BlockNums[l1BlockNum]; !ok { - l1BlockNums[l1BlockNum] = [2]uint64{l2BlockNum, l2BlockNum} + l1BlockNums[l1BlockNum] = &[2]uint64{l2BlockNum, l2BlockNum} } else { - l1BlockNums[l1BlockNum] = [2]uint64{l1BlockNums[l1BlockNum][0], l2BlockNum} + l1BlockNums[l1BlockNum][1] = l2BlockNum } } From cb10050cbbee58b228055c1454744670121613fb Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 22 Sep 2023 09:33:45 -0500 Subject: [PATCH 160/775] code refactor --- nodeInterface/NodeInterface.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index 2a45ac033..f114cd5ac 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -591,6 +591,7 @@ func (n NodeInterface) LegacyLookupMessageBatchProof(c ctx, evm mech, batchNum h return } +// L2BlockRangeForL1 fetches the L1 block number of a given l2 block number. func (n NodeInterface) BlockL1Num(c ctx, evm mech, l2BlockNum uint64) (uint64, error) { blockHeader, err := n.backend.HeaderByNumber(n.context, rpc.BlockNumber(l2BlockNum)) if err != nil { @@ -619,6 +620,13 @@ func (n NodeInterface) L2BlockRangeForL1(c ctx, evm mech, l1BlockNum uint64) (ui storedMids := map[uint64]uint64{} firstL2BlockForL1 := func(target uint64) (uint64, error) { low, high := genesis, currentBlockNum + highBlockL1Num, err := n.BlockL1Num(c, evm, high) + if err != nil { + return 0, err + } + if highBlockL1Num < target { + return high + 1, nil + } for low < high { mid := arbmath.SaturatingUAdd(low, high) / 2 if _, ok := storedMids[mid]; !ok { @@ -649,11 +657,9 @@ func (n NodeInterface) L2BlockRangeForL1(c ctx, evm mech, l1BlockNum uint64) (ui if err := n.matchL2BlockNumWithL1(c, evm, firstBlock, l1BlockNum); err != nil { return 0, 0, err } - if err := n.matchL2BlockNumWithL1(c, evm, lastBlock, l1BlockNum); err != nil { - lastBlock -= 1 - if err = n.matchL2BlockNumWithL1(c, evm, lastBlock, l1BlockNum); err != nil { - return 0, 0, err - } + lastBlock -= 1 + if err = n.matchL2BlockNumWithL1(c, evm, lastBlock, l1BlockNum); err != nil { + return 0, 0, err } return firstBlock, lastBlock, nil } From 9580c4dae7b8db62187856ebc0ea801f720ebaf2 Mon Sep 17 00:00:00 2001 From: Nodar Date: Fri, 22 Sep 2023 18:59:40 +0200 Subject: [PATCH 161/775] Add test for sequencer inbox refunder --- contracts | 2 +- system_tests/seqinbox_test.go | 62 +++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/contracts b/contracts index 97cfbe00f..23fe920ed 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 97cfbe00ff0eea4d7f5f5f3afb01598c19ddabc4 +Subproject commit 23fe920edb52ff1185f7706d59ada82616a0d32a diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index bf3e7c86c..de615278c 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" @@ -38,6 +39,49 @@ type blockTestState struct { const seqInboxTestIters = 40 +func deployGasRefunder(ctx context.Context, t *testing.T, info *BlockchainTestInfo, client *ethclient.Client) common.Address { + t.Helper() + abi, err := bridgegen.GasRefunderMetaData.GetAbi() + if err != nil { + t.Fatalf("Error getting gas refunder abi: %v", err) + } + fauOpts := info.GetDefaultTransactOpts("Faucet", ctx) + addr, tx, _, err := bind.DeployContract(&fauOpts, *abi, common.FromHex(bridgegen.GasRefunderBin), client) + if err != nil { + t.Fatalf("Error getting gas refunder contract deployment transaction: %v", err) + } + if _, err := EnsureTxSucceeded(ctx, client, tx); err != nil { + t.Fatalf("Error deploying gas refunder contract: %v", err) + } + tx = info.PrepareTxTo("Faucet", &addr, 30000, big.NewInt(9223372036854775807), nil) + if err := client.SendTransaction(ctx, tx); err != nil { + t.Fatalf("Error sending gas refunder funding transaction") + } + if _, err := EnsureTxSucceeded(ctx, client, tx); err != nil { + t.Fatalf("Error funding gas refunder") + } + contract, err := bridgegen.NewGasRefunder(addr, client) + if err != nil { + t.Fatalf("Error getting gas refunder contract binding: %v", err) + } + tx, err = contract.AllowContracts(&fauOpts, []common.Address{info.GetAddress("SequencerInbox")}) + if err != nil { + t.Fatalf("Error creating transaction for altering allowlist in refunder: %v", err) + } + if _, err := EnsureTxSucceeded(ctx, client, tx); err != nil { + t.Fatalf("Error addting sequencer inbox in gas refunder allowlist: %v", err) + } + + tx, err = contract.AllowRefundees(&fauOpts, []common.Address{info.GetAddress("Sequencer")}) + if err != nil { + t.Fatalf("Error creating transaction for altering allowlist in refunder: %v", err) + } + if _, err := EnsureTxSucceeded(ctx, client, tx); err != nil { + t.Fatalf("Error addting sequencer in gas refunder allowlist: %v", err) + } + return addr +} + func testSequencerInboxReaderImpl(t *testing.T, validator bool) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) @@ -58,6 +102,8 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { Require(t, err) seqOpts := l1Info.GetDefaultTransactOpts("Sequencer", ctx) + gasRefunderAddr := deployGasRefunder(ctx, t, l1Info, l1Client) + ownerAddress := l2Info.GetAddress("Owner") var startL2BlockNumber uint64 = 0 @@ -216,10 +262,14 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { } seqOpts.Nonce = big.NewInt(int64(seqNonce)) var tx *types.Transaction + before, err := l1Client.BalanceAt(ctx, seqOpts.From, nil) + if err != nil { + t.Fatalf("BalanceAt(%v) unexpected error: %v", seqOpts.From, err) + } if i%5 == 0 { - tx, err = seqInbox.AddSequencerL2Batch(&seqOpts, big.NewInt(int64(len(blockStates))), batchData, big.NewInt(1), common.Address{}, big.NewInt(0), big.NewInt(0)) + tx, err = seqInbox.AddSequencerL2Batch(&seqOpts, big.NewInt(int64(len(blockStates))), batchData, big.NewInt(1), gasRefunderAddr, big.NewInt(0), big.NewInt(0)) } else { - tx, err = seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(int64(len(blockStates))), batchData, big.NewInt(1), common.Address{}) + tx, err = seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(int64(len(blockStates))), batchData, big.NewInt(1), gasRefunderAddr) } Require(t, err) txRes, err := EnsureTxSucceeded(ctx, l1Client, tx) @@ -233,6 +283,14 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { txRes, err = EnsureTxSucceeded(ctx, l1Client, tx) Require(t, err) } + after, err := l1Client.BalanceAt(ctx, seqOpts.From, nil) + if err != nil { + t.Fatalf("BalanceAt(%v) unexpected error: %v", seqOpts.From, err) + } + txCost := txRes.EffectiveGasPrice.Uint64() * txRes.GasUsed + if diff := before.Int64() - after.Int64(); diff >= int64(txCost) { + t.Errorf("Transaction: %v was not refunded, balance diff: %v, cost: %v", tx.Hash(), diff, txCost) + } state.l2BlockNumber += uint64(numMessages) state.l1BlockNumber = txRes.BlockNumber.Uint64() From 48c6a705cd529763af17e91becb056aebe567e63 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 22 Sep 2023 19:19:39 +0200 Subject: [PATCH 162/775] Add nativeToken flag to deployer and update createRollup call --- .gitmodules | 2 +- Dockerfile | 2 + arbnode/node.go | 77 +++++++++++++------------------------ cmd/chaininfo/chain_info.go | 1 + cmd/deploy/deploy.go | 3 ++ system_tests/common_test.go | 1 + 6 files changed, 35 insertions(+), 51 deletions(-) diff --git a/.gitmodules b/.gitmodules index 7c78791c7..444199c4e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,7 +13,7 @@ [submodule "contracts"] path = contracts url = https://github.com/OffchainLabs/nitro-contracts.git - branch = develop + branch = feature-orbit-bridge [submodule "arbitrator/wasm-testsuite/testsuite"] path = arbitrator/wasm-testsuite/testsuite url = https://github.com/WebAssembly/testsuite.git diff --git a/Dockerfile b/Dockerfile index c1a28760c..88e239356 100644 --- a/Dockerfile +++ b/Dockerfile @@ -76,6 +76,7 @@ COPY ./fastcache ./fastcache COPY ./go-ethereum ./go-ethereum COPY --from=brotli-wasm-export / target/ COPY --from=contracts-builder workspace/contracts/build/contracts/src/precompiles/ contracts/build/contracts/src/precompiles/ +COPY --from=contracts-builder workspace/contracts/node_modules/@offchainlabs/upgrade-executor/build/contracts/src/UpgradeExecutor.sol/UpgradeExecutor.json contracts/ COPY --from=contracts-builder workspace/.make/ .make/ RUN PATH="$PATH:/usr/local/go/bin" NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-wasm-bin @@ -179,6 +180,7 @@ COPY fastcache/go.mod fastcache/go.sum fastcache/ RUN go mod download COPY . ./ COPY --from=contracts-builder workspace/contracts/build/ contracts/build/ +COPY --from=contracts-builder workspace/contracts/node_modules/@offchainlabs/upgrade-executor/build/contracts/src/UpgradeExecutor.sol/UpgradeExecutor.json contracts/node_modules/@offchainlabs/upgrade-executor/build/contracts/src/UpgradeExecutor.sol/ COPY --from=contracts-builder workspace/.make/ .make/ COPY --from=prover-header-export / target/ COPY --from=brotli-library-export / target/ diff --git a/arbnode/node.go b/arbnode/node.go index 5bdc71626..0509f17bb 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -42,6 +42,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/ospgen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" + "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/contracts" "github.com/offchainlabs/nitro/util/headerreader" @@ -61,53 +62,6 @@ func andTxSucceeded(ctx context.Context, l1Reader *headerreader.HeaderReader, tx return nil } -func deployBridgeCreator(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts) (common.Address, error) { - client := l1Reader.Client() - bridgeTemplate, tx, _, err := bridgegen.DeployBridge(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("bridge deploy error: %w", err) - } - - seqInboxTemplate, tx, _, err := bridgegen.DeploySequencerInbox(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("sequencer inbox deploy error: %w", err) - } - - inboxTemplate, tx, _, err := bridgegen.DeployInbox(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("inbox deploy error: %w", err) - } - - rollupEventBridgeTemplate, tx, _, err := rollupgen.DeployRollupEventInbox(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("rollup event bridge deploy error: %w", err) - } - - outboxTemplate, tx, _, err := bridgegen.DeployOutbox(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("outbox deploy error: %w", err) - } - - bridgeCreatorAddr, tx, bridgeCreator, err := rollupgen.DeployBridgeCreator(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("bridge creator deploy error: %w", err) - } - - tx, err = bridgeCreator.UpdateTemplates(auth, bridgeTemplate, seqInboxTemplate, inboxTemplate, rollupEventBridgeTemplate, outboxTemplate) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("bridge creator update templates error: %w", err) - } - - return bridgeCreatorAddr, nil -} - func deployChallengeFactory(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts) (common.Address, common.Address, error) { client := l1Reader.Client() osp0, tx, _, err := ospgen.DeployOneStepProver0(auth, client) @@ -150,9 +104,12 @@ func deployChallengeFactory(ctx context.Context, l1Reader *headerreader.HeaderRe } func deployRollupCreator(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts) (*rollupgen.RollupCreator, common.Address, common.Address, common.Address, error) { - bridgeCreator, err := deployBridgeCreator(ctx, l1Reader, auth) + fmt.Println("Deploying bridge creator...") + auth.GasLimit = uint64(14183487) + bridgeCreator, tx, _, err := rollupgen.DeployBridgeCreator(auth, l1Reader.Client()) + err = andTxSucceeded(ctx, l1Reader, tx, err) if err != nil { - return nil, common.Address{}, common.Address{}, common.Address{}, err + return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("bridge creator deploy error: %w", err) } ospEntryAddr, challengeManagerAddr, err := deployChallengeFactory(ctx, l1Reader, auth) @@ -178,6 +135,12 @@ func deployRollupCreator(ctx context.Context, l1Reader *headerreader.HeaderReade return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("rollup creator deploy error: %w", err) } + upgradeExecutor, tx, _, err := upgrade_executorgen.DeployUpgradeExecutor(auth, l1Reader.Client()) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("upgrade executor deploy error: %w", err) + } + validatorUtils, tx, _, err := rollupgen.DeployValidatorUtils(auth, l1Reader.Client()) err = andTxSucceeded(ctx, l1Reader, tx, err) if err != nil { @@ -190,6 +153,13 @@ func deployRollupCreator(ctx context.Context, l1Reader *headerreader.HeaderReade return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("validator wallet creator deploy error: %w", err) } + l2FactoriesDeployHelper, tx, _, err := rollupgen.DeployDeployHelper(auth, l1Reader.Client()) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("deploy helper creator deploy error: %w", err) + } + + tx, err = rollupCreator.SetTemplates( auth, bridgeCreator, @@ -197,8 +167,10 @@ func deployRollupCreator(ctx context.Context, l1Reader *headerreader.HeaderReade challengeManagerAddr, rollupAdminLogic, rollupUserLogic, + upgradeExecutor, validatorUtils, validatorWalletCreator, + l2FactoriesDeployHelper, ) err = andTxSucceeded(ctx, l1Reader, tx, err) if err != nil { @@ -235,7 +207,7 @@ func GenerateRollupConfig(prod bool, wasmModuleRoot common.Hash, rollupOwner com } } -func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReader, deployAuth *bind.TransactOpts, batchPoster common.Address, authorizeValidators uint64, config rollupgen.Config) (*chaininfo.RollupAddresses, error) { +func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReader, deployAuth *bind.TransactOpts, batchPoster common.Address, authorizeValidators uint64, config rollupgen.Config, nativeToken common.Address) (*chaininfo.RollupAddresses, error) { if config.WasmModuleRoot == (common.Hash{}) { return nil, errors.New("no machine specified") } @@ -250,11 +222,16 @@ func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReade validatorAddrs = append(validatorAddrs, crypto.CreateAddress(validatorWalletCreator, i)) } + // 0.1 gwei + maxFeePerGas := big.NewInt(100000000) tx, err := rollupCreator.CreateRollup( deployAuth, config, batchPoster, validatorAddrs, + nativeToken, + false, + maxFeePerGas, ) if err != nil { return nil, fmt.Errorf("error submitting create rollup tx: %w", err) diff --git a/cmd/chaininfo/chain_info.go b/cmd/chaininfo/chain_info.go index f75779b4a..2902e9611 100644 --- a/cmd/chaininfo/chain_info.go +++ b/cmd/chaininfo/chain_info.go @@ -106,6 +106,7 @@ type RollupAddresses struct { Inbox common.Address `json:"inbox"` SequencerInbox common.Address `json:"sequencer-inbox"` Rollup common.Address `json:"rollup"` + NativeToken common.Address `json:"native-token"` ValidatorUtils common.Address `json:"validator-utils"` ValidatorWalletCreator common.Address `json:"validator-wallet-creator"` DeployedAt uint64 `json:"deployed-at"` diff --git a/cmd/deploy/deploy.go b/cmd/deploy/deploy.go index d687821e8..4da3ae765 100644 --- a/cmd/deploy/deploy.go +++ b/cmd/deploy/deploy.go @@ -40,6 +40,7 @@ func main() { deployAccount := flag.String("l1DeployAccount", "", "l1 seq account to use (default is first account in keystore)") ownerAddressString := flag.String("ownerAddress", "", "the rollup owner's address") sequencerAddressString := flag.String("sequencerAddress", "", "the sequencer's address") + nativeTokenAddressString := flag.String("nativeTokenAddress", "", "address of the ERC20 token which is used as native L2 currency") loserEscrowAddressString := flag.String("loserEscrowAddress", "", "the address which half of challenge loser's funds accumulate at") wasmmoduleroot := flag.String("wasmmoduleroot", "", "WASM module root hash") wasmrootpath := flag.String("wasmrootpath", "", "path to machine folders") @@ -137,6 +138,7 @@ func main() { l1Reader.Start(ctx) defer l1Reader.StopAndWait() + nativeToken := common.HexToAddress(*nativeTokenAddressString) deployedAddresses, err := arbnode.DeployOnL1( ctx, l1Reader, @@ -144,6 +146,7 @@ func main() { sequencerAddress, *authorizevalidators, arbnode.GenerateRollupConfig(*prod, moduleRoot, ownerAddress, &chainConfig, chainConfigJson, loserEscrowAddress), + nativeToken, ) if err != nil { flag.Usage() diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 9fd002bd9..1bdb29118 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -489,6 +489,7 @@ func DeployOnTestL1( l1info.GetAddress("Sequencer"), 0, arbnode.GenerateRollupConfig(false, locator.LatestWasmModuleRoot(), l1info.GetAddress("RollupOwner"), chainConfig, serializedChainConfig, common.Address{}), + common.Address{}, ) Require(t, err) l1info.SetContract("Bridge", addresses.Bridge) From e9751ab13e7b517ee10ddff99853baff01b5f5a3 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 22 Sep 2023 19:20:11 +0200 Subject: [PATCH 163/775] Deploy UpgradeExecutor --- solgen/gen.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/solgen/gen.go b/solgen/gen.go index c29db9303..5d43946fa 100644 --- a/solgen/gen.go +++ b/solgen/gen.go @@ -96,6 +96,27 @@ func main() { modInfo.addArtifact(artifact) } + // add upgrade executor module which is not compiled locally, but imported from 'nitro-contracts' depedencies + upgExecutorPath := filepath.Join(parent, "contracts", "node_modules", "@offchainlabs", "upgrade-executor", "build", "contracts", "src", "UpgradeExecutor.sol", "UpgradeExecutor.json") + _, err = os.Stat(upgExecutorPath) + if !os.IsNotExist(err) { + data, err := os.ReadFile(upgExecutorPath) + if err != nil { + // log.Fatal(string(output)) + log.Fatal("could not read", upgExecutorPath, "for contract", "UpgradeExecutor", err) + } + artifact := HardHatArtifact{} + if err := json.Unmarshal(data, &artifact); err != nil { + log.Fatal("failed to parse contract", "UpgradeExecutor", err) + } + modInfo := modules["upgrade_executorgen"] + if modInfo == nil { + modInfo = &moduleInfo{} + modules["upgrade_executorgen"] = modInfo + } + modInfo.addArtifact(artifact) + } + for module, info := range modules { code, err := bind.Bind( From 27ee8870d6f1d9d9ea7926c073d01a1c50e3dd4d Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 22 Sep 2023 12:59:38 -0700 Subject: [PATCH 164/775] Fixed memory limits rather than percentage based --- .../resourcemanager/resource_management.go | 94 ++++++++++++++----- .../resource_management_test.go | 51 +++++++++- cmd/nitro/nitro.go | 6 +- 3 files changed, 123 insertions(+), 28 deletions(-) diff --git a/arbnode/resourcemanager/resource_management.go b/arbnode/resourcemanager/resource_management.go index 88b7d6509..acf67d35f 100644 --- a/arbnode/resourcemanager/resource_management.go +++ b/arbnode/resourcemanager/resource_management.go @@ -12,6 +12,7 @@ import ( "regexp" "strconv" "time" + "unicode" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" @@ -31,37 +32,83 @@ var ( // prior to RPC request handling. // // Must be run before the go-ethereum stack is set up (ethereum/go-ethereum/node.New). -func Init(conf *Config) { - if conf.MemLimitPercent > 0 { - node.WrapHTTPHandler = func(srv http.Handler) (http.Handler, error) { - var c limitChecker - c, err := newCgroupsMemoryLimitCheckerIfSupported(conf) - if errors.Is(err, errNotSupported) { - log.Error("No method for determining memory usage and limits was discovered, disabled memory limit RPC throttling") - c = &trivialLimitChecker{} - } +func Init(conf *Config) error { + if conf.MemFreeLimit == "" { + return nil + } + + limit, err := parseMemLimit(conf.MemFreeLimit) + if err != nil { + return err + } - return newHttpServer(srv, c), nil + node.WrapHTTPHandler = func(srv http.Handler) (http.Handler, error) { + var c limitChecker + c, err := newCgroupsMemoryLimitCheckerIfSupported(limit) + if errors.Is(err, errNotSupported) { + log.Error("No method for determining memory usage and limits was discovered, disabled memory limit RPC throttling") + c = &trivialLimitChecker{} } + + return newHttpServer(srv, c), nil } + return nil +} + +func parseMemLimit(limitStr_ string) (int, error) { + limitStr := limitStr_ + limitAccumulator := 1 + done := false + for !done { + switch unicode.ToUpper(rune(limitStr[len(limitStr)-1])) { + case 'B': + limitStr = limitStr[:len(limitStr)-1] + continue + case 'K': + limitStr = limitStr[:len(limitStr)-1] + limitAccumulator *= 1024 + done = true + case 'M': + limitStr = limitStr[:len(limitStr)-1] + limitAccumulator *= 1024 * 1024 + done = true + case 'G': + limitStr = limitStr[:len(limitStr)-1] + limitAccumulator *= 1024 * 1024 * 1024 + done = true + case 'T': + limitStr = limitStr[:len(limitStr)-1] + limitAccumulator *= 1024 * 1024 * 1024 * 1024 + done = true + default: + done = true + } + } + + limitInUnits, err := strconv.Atoi(limitStr) + if err != nil { + return 0, err + } + + return limitAccumulator * limitInUnits, nil } // Config contains the configuration for resourcemanager functionality. // Currently only a memory limit is supported, other limits may be added // in the future. type Config struct { - MemLimitPercent int `koanf:"mem-limit-percent" reload:"hot"` + MemFreeLimit string `koanf:"mem-free-limit" reload:"hot"` } // DefaultConfig has the defaul resourcemanager configuration, // all limits are disabled. var DefaultConfig = Config{ - MemLimitPercent: 0, + MemFreeLimit: "", } // ConfigAddOptions adds the configuration options for resourcemanager. func ConfigAddOptions(prefix string, f *pflag.FlagSet) { - f.Int(prefix+".mem-limit-percent", DefaultConfig.MemLimitPercent, "RPC calls are throttled if system memory utilization exceeds this percent value, zero (default) is disabled") + f.String(prefix+".mem-free-limit", DefaultConfig.MemFreeLimit, "RPC calls are throttled if free system memory is below this amount, expressed in bytes or multiples of bytes with suffix B, K, M, G") } // httpServer implements http.Handler and wraps calls to inner with a resource @@ -105,14 +152,14 @@ func isSupported(c limitChecker) bool { // newCgroupsMemoryLimitCheckerIfSupported attempts to auto-discover whether // Cgroups V1 or V2 is supported for checking system memory limits. -func newCgroupsMemoryLimitCheckerIfSupported(conf *Config) (*cgroupsMemoryLimitChecker, error) { - c := newCgroupsMemoryLimitChecker(cgroupsV1MemoryFiles, conf.MemLimitPercent) +func newCgroupsMemoryLimitCheckerIfSupported(memLimitBytes int) (*cgroupsMemoryLimitChecker, error) { + c := newCgroupsMemoryLimitChecker(cgroupsV1MemoryFiles, memLimitBytes) if isSupported(c) { log.Info("Cgroups v1 detected, enabling memory limit RPC throttling") return c, nil } - c = newCgroupsMemoryLimitChecker(cgroupsV2MemoryFiles, conf.MemLimitPercent) + c = newCgroupsMemoryLimitChecker(cgroupsV2MemoryFiles, memLimitBytes) if isSupported(c) { log.Info("Cgroups v2 detected, enabling memory limit RPC throttling") return c, nil @@ -152,19 +199,18 @@ var cgroupsV2MemoryFiles = cgroupsMemoryFiles{ } type cgroupsMemoryLimitChecker struct { - files cgroupsMemoryFiles - memoryLimitPercent int + files cgroupsMemoryFiles + memLimitBytes int } -func newCgroupsMemoryLimitChecker(files cgroupsMemoryFiles, memoryLimitPercent int) *cgroupsMemoryLimitChecker { +func newCgroupsMemoryLimitChecker(files cgroupsMemoryFiles, memLimitBytes int) *cgroupsMemoryLimitChecker { return &cgroupsMemoryLimitChecker{ - files: files, - memoryLimitPercent: memoryLimitPercent, + files: files, + memLimitBytes: memLimitBytes, } } -// isLimitExceeded checks if the system memory used exceeds the limit -// scaled by the configured memoryLimitPercent. +// isLimitExceeded checks if the system memory free is less than the limit. // // See the following page for details of calculating the memory used, // which is reported as container_memory_working_set_bytes in prometheus: @@ -181,7 +227,7 @@ func (c *cgroupsMemoryLimitChecker) isLimitExceeded() (bool, error) { if inactive, err = readInactive(c.files.statsFile, c.files.inactiveRe); err != nil { return false, err } - return usage-inactive >= ((limit * c.memoryLimitPercent) / 100), nil + return limit-(usage-inactive) <= c.memLimitBytes, nil } func (c cgroupsMemoryLimitChecker) String() string { diff --git a/arbnode/resourcemanager/resource_management_test.go b/arbnode/resourcemanager/resource_management_test.go index ba791fd72..e9aa2ab7e 100644 --- a/arbnode/resourcemanager/resource_management_test.go +++ b/arbnode/resourcemanager/resource_management_test.go @@ -50,7 +50,7 @@ func makeCgroupsTestDir(cgroupDir string) cgroupsMemoryFiles { func TestCgroupsFailIfCantOpen(t *testing.T) { testFiles := makeCgroupsTestDir(t.TempDir()) - c := newCgroupsMemoryLimitChecker(testFiles, 95) + c := newCgroupsMemoryLimitChecker(testFiles, 1024*1024*512) if _, err := c.isLimitExceeded(); err == nil { t.Fatal("Should fail open if can't read files") } @@ -59,24 +59,69 @@ func TestCgroupsFailIfCantOpen(t *testing.T) { func TestCgroupsMemoryLimit(t *testing.T) { for _, tc := range []struct { desc string + sysLimit int inactive int + usage int + memLimit string want bool }{ { desc: "limit should be exceeded", + sysLimit: 1000, inactive: 50, + usage: 1000, + memLimit: "50B", want: true, }, { desc: "limit should not be exceeded", + sysLimit: 1000, inactive: 51, + usage: 1000, + memLimit: "50b", + want: false, + }, + { + desc: "limit (MB) should be exceeded", + sysLimit: 1000 * 1024 * 1024, + inactive: 50 * 1024 * 1024, + usage: 1000 * 1024 * 1024, + memLimit: "50MB", + want: true, + }, + { + desc: "limit (MB) should not be exceeded", + sysLimit: 1000 * 1024 * 1024, + inactive: 1 + 50*1024*1024, + usage: 1000 * 1024 * 1024, + memLimit: "50m", + want: false, + }, + { + desc: "limit (GB) should be exceeded", + sysLimit: 1000 * 1024 * 1024 * 1024, + inactive: 50 * 1024 * 1024 * 1024, + usage: 1000 * 1024 * 1024 * 1024, + memLimit: "50G", + want: true, + }, + { + desc: "limit (GB) should not be exceeded", + sysLimit: 1000 * 1024 * 1024 * 1024, + inactive: 1 + 50*1024*1024*1024, + usage: 1000 * 1024 * 1024 * 1024, + memLimit: "50gb", want: false, }, } { t.Run(tc.desc, func(t *testing.T) { testFiles := makeCgroupsTestDir(t.TempDir()) - c := newCgroupsMemoryLimitChecker(testFiles, 95) - if err := updateFakeCgroupFiles(c, 1000, 1000, tc.inactive); err != nil { + memLimit, err := parseMemLimit(tc.memLimit) + if err != nil { + t.Fatalf("Parsing memory limit failed: %v", err) + } + c := newCgroupsMemoryLimitChecker(testFiles, memLimit) + if err := updateFakeCgroupFiles(c, tc.sysLimit, tc.usage, tc.inactive); err != nil { t.Fatalf("Updating cgroup files: %v", err) } exceeded, err := c.isLimitExceeded() diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index a7dc7f26f..535c5ab0b 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -380,7 +380,11 @@ func mainImpl() int { nodeConfig.Node.TxLookupLimit = 0 } - resourcemanager.Init(&nodeConfig.Node.ResourceMgmt) + err = resourcemanager.Init(&nodeConfig.Node.ResourceMgmt) + if err != nil { + flag.Usage() + log.Crit("failed to start resource management module") + } var sameProcessValidationNodeEnabled bool if nodeConfig.Node.BlockValidator.Enable && (nodeConfig.Node.BlockValidator.ValidationServer.URL == "self" || nodeConfig.Node.BlockValidator.ValidationServer.URL == "self-auth") { From 452499424b67447adae34cd1b89204fc18206e25 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Sat, 23 Sep 2023 08:40:42 +0200 Subject: [PATCH 165/775] Update testnode branch --- .gitmodules | 1 + arbnode/node.go | 4 ++-- nitro-testnode | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 444199c4e..75e66a648 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,3 +20,4 @@ [submodule "nitro-testnode"] path = nitro-testnode url = https://github.com/OffchainLabs/nitro-testnode.git + branch = fee-token-support diff --git a/arbnode/node.go b/arbnode/node.go index 0509f17bb..5e694898b 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -104,8 +104,8 @@ func deployChallengeFactory(ctx context.Context, l1Reader *headerreader.HeaderRe } func deployRollupCreator(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts) (*rollupgen.RollupCreator, common.Address, common.Address, common.Address, error) { - fmt.Println("Deploying bridge creator...") - auth.GasLimit = uint64(14183487) + // deploying bridge creator takes ~14.2 million gas + auth.GasLimit = uint64(15000000) bridgeCreator, tx, _, err := rollupgen.DeployBridgeCreator(auth, l1Reader.Client()) err = andTxSucceeded(ctx, l1Reader, tx, err) if err != nil { diff --git a/nitro-testnode b/nitro-testnode index 7ad12c0f1..441166624 160000 --- a/nitro-testnode +++ b/nitro-testnode @@ -1 +1 @@ -Subproject commit 7ad12c0f1be75a72c7360d5258e0090f8225594e +Subproject commit 441166624c54857a11c0a880f12e19d7dbeebc69 From 5bd76f333be3fdd54fd48db02723f8b84726daf1 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 25 Sep 2023 10:13:48 -0500 Subject: [PATCH 166/775] add documentation --- nodeInterface/NodeInterface.go | 1 + 1 file changed, 1 insertion(+) diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index f114cd5ac..698425539 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -592,6 +592,7 @@ func (n NodeInterface) LegacyLookupMessageBatchProof(c ctx, evm mech, batchNum h } // L2BlockRangeForL1 fetches the L1 block number of a given l2 block number. +// c ctx and evm mech arguments are not used but supplied to match the precompile function type in NodeInterface contract func (n NodeInterface) BlockL1Num(c ctx, evm mech, l2BlockNum uint64) (uint64, error) { blockHeader, err := n.backend.HeaderByNumber(n.context, rpc.BlockNumber(l2BlockNum)) if err != nil { From 1cb88fbf1f5a5ba200d9a55ae87426ff720262c4 Mon Sep 17 00:00:00 2001 From: Nodar Date: Mon, 25 Sep 2023 17:20:49 +0200 Subject: [PATCH 167/775] Use staker address as part of redis key for dataposter --- arbnode/node.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arbnode/node.go b/arbnode/node.go index 3fc1f556f..912b40458 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -564,6 +564,10 @@ func StakerDataposter( dpCfg := func() *dataposter.DataPosterConfig { return &cfg.Staker.DataPoster } + addr := common.Address{}.String() + if transactOpts != nil { + addr = transactOpts.From.String() + } return dataposter.NewDataPoster( &dataposter.DataPosterOpts{ Database: db, @@ -573,7 +577,7 @@ func StakerDataposter( RedisLock: redisLock, Config: dpCfg, MetadataRetriever: mdRetriever, - RedisKey: "staker-data-poster.queue", + RedisKey: addr + ".staker-data-poster.queue", }) } From 0d7a15f1f1d9de9547627cb6cb53dea3f13f21ad Mon Sep 17 00:00:00 2001 From: anodar Date: Mon, 25 Sep 2023 19:08:31 +0200 Subject: [PATCH 168/775] Drop nil comparison since it's already checked --- arbnode/node.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 912b40458..eb7ff5aca 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -564,10 +564,6 @@ func StakerDataposter( dpCfg := func() *dataposter.DataPosterConfig { return &cfg.Staker.DataPoster } - addr := common.Address{}.String() - if transactOpts != nil { - addr = transactOpts.From.String() - } return dataposter.NewDataPoster( &dataposter.DataPosterOpts{ Database: db, @@ -577,7 +573,8 @@ func StakerDataposter( RedisLock: redisLock, Config: dpCfg, MetadataRetriever: mdRetriever, - RedisKey: addr + ".staker-data-poster.queue", + // transactOpts is non-nil, it's checked at the beginning. + RedisKey: transactOpts.From.String() + ".staker-data-poster.queue", }) } From 4ad21f6b7fcf147cd1ce321b5a43d7845a0a4062 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Mon, 25 Sep 2023 10:48:00 -0700 Subject: [PATCH 169/775] Simplify resourcemanager.parseMemLimit --- .../resourcemanager/resource_management.go | 55 ++++++++----------- cmd/nitro/nitro.go | 5 +- 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/arbnode/resourcemanager/resource_management.go b/arbnode/resourcemanager/resource_management.go index acf67d35f..4a63d428f 100644 --- a/arbnode/resourcemanager/resource_management.go +++ b/arbnode/resourcemanager/resource_management.go @@ -11,8 +11,8 @@ import ( "os" "regexp" "strconv" + "strings" "time" - "unicode" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" @@ -55,42 +55,31 @@ func Init(conf *Config) error { return nil } -func parseMemLimit(limitStr_ string) (int, error) { - limitStr := limitStr_ - limitAccumulator := 1 - done := false - for !done { - switch unicode.ToUpper(rune(limitStr[len(limitStr)-1])) { - case 'B': - limitStr = limitStr[:len(limitStr)-1] - continue - case 'K': - limitStr = limitStr[:len(limitStr)-1] - limitAccumulator *= 1024 - done = true - case 'M': - limitStr = limitStr[:len(limitStr)-1] - limitAccumulator *= 1024 * 1024 - done = true - case 'G': - limitStr = limitStr[:len(limitStr)-1] - limitAccumulator *= 1024 * 1024 * 1024 - done = true - case 'T': - limitStr = limitStr[:len(limitStr)-1] - limitAccumulator *= 1024 * 1024 * 1024 * 1024 - done = true - default: - done = true - } - } - - limitInUnits, err := strconv.Atoi(limitStr) +func parseMemLimit(limitStr string) (int, error) { + var ( + limit int = 1 + s string + ) + _, err := fmt.Sscanf(limitStr, "%d%s", &limit, &s) if err != nil { return 0, err } - return limitAccumulator * limitInUnits, nil + switch strings.ToUpper(s) { + case "K", "KB": + limit <<= 10 + case "M", "MB": + limit <<= 20 + case "G", "GB": + limit <<= 30 + case "T", "TB": + limit <<= 40 + case "B": + default: + return 0, fmt.Errorf("Unsupported memory limit suffix string %s", s) + } + + return limit, nil } // Config contains the configuration for resourcemanager functionality. diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 535c5ab0b..d2162a9d0 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -380,10 +380,9 @@ func mainImpl() int { nodeConfig.Node.TxLookupLimit = 0 } - err = resourcemanager.Init(&nodeConfig.Node.ResourceMgmt) - if err != nil { + if err := resourcemanager.Init(&nodeConfig.Node.ResourceMgmt); err != nil { flag.Usage() - log.Crit("failed to start resource management module") + log.Crit("Failed to start resource management module", "err", err) } var sameProcessValidationNodeEnabled bool From 000a97b49f842356211d6958c304fbc657266fb2 Mon Sep 17 00:00:00 2001 From: anodar Date: Tue, 26 Sep 2023 16:24:22 +0200 Subject: [PATCH 170/775] Fix nil pointer dereference in BlockNum precompile --- nodeInterface/NodeInterface.go | 3 +++ system_tests/nodeinterface_test.go | 32 ++++++++++++++++++------------ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index 698425539..f13f8ce6c 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -598,6 +598,9 @@ func (n NodeInterface) BlockL1Num(c ctx, evm mech, l2BlockNum uint64) (uint64, e if err != nil { return 0, err } + if blockHeader == nil { + return 0, fmt.Errorf("nil header for l2 block: %d", l2BlockNum) + } blockL1Num := types.DeserializeHeaderExtraInformation(blockHeader).L1BlockNumber return blockL1Num, nil } diff --git a/system_tests/nodeinterface_test.go b/system_tests/nodeinterface_test.go index 63b3d7bb7..167f2204c 100644 --- a/system_tests/nodeinterface_test.go +++ b/system_tests/nodeinterface_test.go @@ -30,40 +30,46 @@ func TestL2BlockRangeForL1(t *testing.T) { } nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) - Require(t, err) + if err != nil { + t.Fatalf("Error creating node interface: %v", err) + } l1BlockNums := map[uint64]*[2]uint64{} latestL2, err := l2client.BlockNumber(ctx) - Require(t, err) + if err != nil { + t.Fatalf("Error querying most recent l2 block: %v", err) + } for l2BlockNum := uint64(0); l2BlockNum <= latestL2; l2BlockNum++ { l1BlockNum, err := nodeInterface.BlockL1Num(&bind.CallOpts{}, l2BlockNum) - Require(t, err) + if err != nil { + t.Fatalf("Error quering l1 block number for l2 block: %d, error: %v", l2BlockNum, err) + } if _, ok := l1BlockNums[l1BlockNum]; !ok { l1BlockNums[l1BlockNum] = &[2]uint64{l2BlockNum, l2BlockNum} - } else { - l1BlockNums[l1BlockNum][1] = l2BlockNum } + l1BlockNums[l1BlockNum][1] = l2BlockNum } - // Test success + // Test success. for l1BlockNum := range l1BlockNums { rng, err := nodeInterface.L2BlockRangeForL1(&bind.CallOpts{}, l1BlockNum) - Require(t, err) + if err != nil { + t.Fatalf("Error getting l2 block range for l1 block: %d, error: %v", l1BlockNum, err) + } expected := l1BlockNums[l1BlockNum] if rng.FirstBlock != expected[0] || rng.LastBlock != expected[1] { unexpectedL1BlockNum, err := nodeInterface.BlockL1Num(&bind.CallOpts{}, rng.LastBlock) - Require(t, err) + if err != nil { + t.Fatalf("Error quering l1 block number for l2 block: %d, error: %v", rng.LastBlock, err) + } // Handle the edge case when new l2 blocks are produced between latestL2 was last calculated and now. if unexpectedL1BlockNum != l1BlockNum || rng.LastBlock < expected[1] || rng.FirstBlock != expected[0] { t.Errorf("L2BlockRangeForL1(%d) = (%d %d) want (%d %d)", l1BlockNum, rng.FirstBlock, rng.LastBlock, expected[0], expected[1]) } } } - // Test invalid case - finalValidL1BlockNumber, err := nodeInterface.BlockL1Num(&bind.CallOpts{}, latestL2) - Require(t, err) - if _, err := nodeInterface.L2BlockRangeForL1(&bind.CallOpts{}, finalValidL1BlockNumber+1); err == nil { + // Test invalid case. + if _, err := nodeInterface.L2BlockRangeForL1(&bind.CallOpts{}, 1e5); err == nil { t.Fatalf("GetL2BlockRangeForL1 didn't fail for an invalid input") } - } From ee5e7ac53828ad689d057cae33112e5dce9f3f0b Mon Sep 17 00:00:00 2001 From: anodar Date: Tue, 26 Sep 2023 16:34:34 +0200 Subject: [PATCH 171/775] Update go-ethereum pin --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 3f2e789b3..45efc8230 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 3f2e789b3857ccdd647c319e16f1a00805d1d6bd +Subproject commit 45efc8230c2561cf56652dabccdd670101f75b0c From d9759471db186104be49b2a66dbf18c2255755d6 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 26 Sep 2023 11:34:16 -0500 Subject: [PATCH 172/775] initial test node builder pattern and few impl --- system_tests/aliasing_test.go | 26 +-- system_tests/bloom_test.go | 22 +-- system_tests/common_test.go | 95 ++++++++- system_tests/conditionaltx_test.go | 128 ++++++------ system_tests/contract_tx_test.go | 17 +- system_tests/estimation_test.go | 75 +++---- system_tests/infra_fee_test.go | 28 +-- system_tests/initialization_test.go | 6 +- system_tests/log_subscription_test.go | 15 +- system_tests/outbox_test.go | 17 +- system_tests/precompile_test.go | 29 +-- system_tests/reorg_resequencing_test.go | 43 ++-- system_tests/retryable_test.go | 250 ++++++++++++------------ system_tests/seq_coordinator_test.go | 4 +- system_tests/seq_nonce_test.go | 34 ++-- system_tests/seq_pause_test.go | 21 +- system_tests/seq_reject_test.go | 44 ++--- system_tests/seq_whitelist_test.go | 18 +- system_tests/seqfeed_test.go | 48 ++--- system_tests/transfer_test.go | 18 +- 20 files changed, 514 insertions(+), 424 deletions(-) diff --git a/system_tests/aliasing_test.go b/system_tests/aliasing_test.go index 5e4e65a2c..852a75720 100644 --- a/system_tests/aliasing_test.go +++ b/system_tests/aliasing_test.go @@ -22,20 +22,20 @@ func TestAliasing(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) - user := l1info.GetDefaultTransactOpts("User", ctx) - TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), l2info, l2client, ctx) + auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + user := testNode.L1Info.GetDefaultTransactOpts("User", ctx) + TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), testNode.L2Info, testNode.L2Client, ctx) - simpleAddr, simple := deploySimple(t, ctx, auth, l2client) + simpleAddr, simple := testNode.DeploySimple(t, auth) simpleContract, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) Require(t, err) // Test direct calls - arbsys, err := precompilesgen.NewArbSys(types.ArbSysAddress, l2client) + arbsys, err := precompilesgen.NewArbSys(types.ArbSysAddress, testNode.L2Client) Require(t, err) top, err := arbsys.IsTopLevelCall(nil) Require(t, err) @@ -56,14 +56,14 @@ func TestAliasing(t *testing.T) { // check via L2 tx, err := simple.CheckCalls(&auth, top, direct, static, delegate, callcode, call) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) // check signed txes via L1 data, err := simpleContract.Pack("checkCalls", top, direct, static, delegate, callcode, call) Require(t, err) - tx = l2info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) - SendSignedTxViaL1(t, ctx, l1info, l1client, l2client, tx) + tx = testNode.L2Info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) + SendSignedTxViaL1(t, ctx, testNode.L1Info, testNode.L1Client, testNode.L2Client, tx) } testUnsigned := func(top, direct, static, delegate, callcode, call bool) { @@ -72,8 +72,8 @@ func TestAliasing(t *testing.T) { // check unsigned txes via L1 data, err := simpleContract.Pack("checkCalls", top, direct, static, delegate, callcode, call) Require(t, err) - tx := l2info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) - SendUnsignedTxViaL1(t, ctx, l1info, l1client, l2client, tx) + tx := testNode.L2Info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) + SendUnsignedTxViaL1(t, ctx, testNode.L1Info, testNode.L1Client, testNode.L2Client, tx) } testL2Signed(true, true, false, false, false, false) diff --git a/system_tests/bloom_test.go b/system_tests/bloom_test.go index 9ad3253d4..c61583adf 100644 --- a/system_tests/bloom_test.go +++ b/system_tests/bloom_test.go @@ -28,14 +28,14 @@ func TestBloom(t *testing.T) { nodeconfig := arbnode.ConfigDefaultL2Test() nodeconfig.RPC.BloomBitsBlocks = 256 nodeconfig.RPC.BloomConfirms = 1 - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, false) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeconfig).CreateTestNodeOnL2Only(t, false) + defer testNode.L2Node.StopAndWait() - l2info.GenerateAccount("User2") + testNode.L2Info.GenerateAccount("User2") - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) + ownerTxOpts := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) ownerTxOpts.Context = ctx - _, simple := deploySimple(t, ctx, ownerTxOpts, client) + _, simple := testNode.DeploySimple(t, ownerTxOpts) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) @@ -63,7 +63,7 @@ func TestBloom(t *testing.T) { if sendNullEvent { tx, err = simple.EmitNullEvent(&ownerTxOpts) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) } @@ -74,7 +74,7 @@ func TestBloom(t *testing.T) { tx, err = simple.Increment(&ownerTxOpts) } Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) if i%100 == 0 { t.Log("counts: ", i, "/", countsNum) @@ -82,7 +82,7 @@ func TestBloom(t *testing.T) { } for { - sectionSize, sectionNum := node.Execution.Backend.APIBackend().BloomStatus() + sectionSize, sectionNum := testNode.L2Node.Execution.Backend.APIBackend().BloomStatus() if sectionSize != 256 { Fatal(t, "unexpected section size: ", sectionSize) } @@ -92,14 +92,14 @@ func TestBloom(t *testing.T) { } <-time.After(time.Second) } - lastHeader, err := client.HeaderByNumber(ctx, nil) + lastHeader, err := testNode.L2Client.HeaderByNumber(ctx, nil) Require(t, err) nullEventQuery := ethereum.FilterQuery{ FromBlock: big.NewInt(0), ToBlock: lastHeader.Number, Topics: [][]common.Hash{{simpleABI.Events["NullEvent"].ID}}, } - logs, err := client.FilterLogs(ctx, nullEventQuery) + logs, err := testNode.L2Client.FilterLogs(ctx, nullEventQuery) Require(t, err) if len(logs) != len(nullEventCounts) { Fatal(t, "expected ", len(nullEventCounts), " logs, got ", len(logs)) @@ -107,7 +107,7 @@ func TestBloom(t *testing.T) { incrementEventQuery := ethereum.FilterQuery{ Topics: [][]common.Hash{{simpleABI.Events["CounterEvent"].ID}}, } - logs, err = client.FilterLogs(ctx, incrementEventQuery) + logs, err = testNode.L2Client.FilterLogs(ctx, incrementEventQuery) Require(t, err) if len(logs) != len(eventCounts) { Fatal(t, "expected ", len(eventCounts), " logs, got ", len(logs)) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 9fd002bd9..8c76baba3 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -57,6 +57,91 @@ import ( "github.com/offchainlabs/nitro/util/testhelpers" ) +type NodeBuilder struct { + // Nodebuilder configuration + ctx context.Context + chainConfig *params.ChainConfig + cacheConfig *core.CacheConfig + nodeConfig *arbnode.Config + l1StackConfig *node.Config + l2StackConfig *node.Config + isSequencer bool + + // L1 Nodebuilder fields + L1Info info + L1Client *ethclient.Client + L1Backend *eth.Ethereum + L1Stack *node.Node + + // L2 Nodebuilder fields + L2Info info + L2Client *ethclient.Client + L2Backend *eth.Ethereum + L2Node *arbnode.Node + L2Stack *node.Node + L2ChainDB ethdb.Database + L2NodeDB ethdb.Database + L2Blockchain *core.BlockChain +} + +func NewNodeBuilder(ctx context.Context) *NodeBuilder { + return &NodeBuilder{ctx: ctx} +} + +func (b *NodeBuilder) SetChainConfig(c *params.ChainConfig) *NodeBuilder { + b.chainConfig = c + return b +} + +func (b *NodeBuilder) SetNodeConfig(c *arbnode.Config) *NodeBuilder { + b.nodeConfig = c + return b +} + +func (b *NodeBuilder) SetCacheConfig(c *core.CacheConfig) *NodeBuilder { + b.cacheConfig = c + return b +} + +func (b *NodeBuilder) SetL1StackConfig(c *node.Config) *NodeBuilder { + b.l1StackConfig = c + return b +} + +func (b *NodeBuilder) SetL2StackConfig(c *node.Config) *NodeBuilder { + b.l2StackConfig = c + return b +} + +func (b *NodeBuilder) SetL1Info(l1Info info) *NodeBuilder { + b.L1Info = l1Info + return b +} + +func (b *NodeBuilder) SetL2Info(l2Info info) *NodeBuilder { + b.L2Info = l2Info + return b +} + +func (b *NodeBuilder) SetIsSequencer(v bool) *NodeBuilder { + b.isSequencer = v + return b +} + +func (b *NodeBuilder) CreateTestNodeOnL1AndL2(t *testing.T) *NodeBuilder { + b.L2Info, b.L2Node, b.L2Client, b.L2Stack, b.L1Info, b.L1Backend, b.L1Client, b.L1Stack = + createTestNodeOnL1WithConfigImpl(t, b.ctx, b.isSequencer, b.nodeConfig, b.chainConfig, b.l2StackConfig, b.cacheConfig, b.L2Info) + return b +} + +func (b *NodeBuilder) CreateTestNodeOnL2Only(t *testing.T, takeOwnership bool) *NodeBuilder { + b.L2Info, b.L2Node, b.L2Client = CreateTestL2WithConfig(t, b.ctx, b.L2Info, b.nodeConfig, takeOwnership) + return b +} +func (b *NodeBuilder) DeploySimple(t *testing.T, auth bind.TransactOpts) (common.Address, *mocksgen.Simple) { + return deploySimple(t, b.ctx, auth, b.L2Client) +} + type info = *BlockchainTestInfo type client = arbutil.L1Interface @@ -639,12 +724,12 @@ func createTestNodeOnL1WithConfigImpl( // L2 -Only. Enough for tests that needs no interface to L1 // Requires precompiles.AllowDebugPrecompiles = true -func CreateTestL2(t *testing.T, ctx context.Context) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { - return CreateTestL2WithConfig(t, ctx, nil, arbnode.ConfigDefaultL2Test(), true) -} - func CreateTestL2WithConfig( - t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, takeOwnership bool, + t *testing.T, + ctx context.Context, + l2Info *BlockchainTestInfo, + nodeConfig *arbnode.Config, + takeOwnership bool, ) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { feedErrChan := make(chan error, 10) diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index 14aa00031..f4b6dd85c 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -203,42 +203,42 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, l2client, _, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) - contractAddress1, simple1 := deploySimple(t, ctx, auth, l2client) + auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + contractAddress1, simple1 := testNode.DeploySimple(t, auth) tx, err := simple1.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) - contractAddress2, simple2 := deploySimple(t, ctx, auth, l2client) + contractAddress2, simple2 := testNode.DeploySimple(t, auth) tx, err = simple2.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) tx, err = simple2.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) - currentRootHash1 := getStorageRootHash(t, node, contractAddress1) - currentSlotValueMap1 := getStorageSlotValue(t, node, contractAddress1) - currentRootHash2 := getStorageRootHash(t, node, contractAddress2) - currentSlotValueMap2 := getStorageSlotValue(t, node, contractAddress2) + currentRootHash1 := getStorageRootHash(t, testNode.L2Node, contractAddress1) + currentSlotValueMap1 := getStorageSlotValue(t, testNode.L2Node, contractAddress1) + currentRootHash2 := getStorageRootHash(t, testNode.L2Node, contractAddress2) + currentSlotValueMap2 := getStorageSlotValue(t, testNode.L2Node, contractAddress2) - rpcClient, err := node.Stack.Attach() + rpcClient, err := testNode.L2Node.Stack.Attach() Require(t, err) - l2info.GenerateAccount("User2") + testNode.L2Info.GenerateAccount("User2") - testConditionalTxThatShouldSucceed(t, ctx, -1, l2info, rpcClient, nil) + testConditionalTxThatShouldSucceed(t, ctx, -1, testNode.L2Info, rpcClient, nil) for i, options := range getEmptyOptions(contractAddress1) { - testConditionalTxThatShouldSucceed(t, ctx, i, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, i, testNode.L2Info, rpcClient, options) } - block, err := l1client.BlockByNumber(ctx, nil) + block, err := testNode.L1Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber := block.NumberU64() blockTime := block.Time() @@ -249,33 +249,33 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { options1 := dedupOptions(t, append(append(optionsAB, optionsA...), optionsB...)) options1 = optionsDedupProduct(t, options1, getFulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options1 { - testConditionalTxThatShouldSucceed(t, ctx, i, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, i, testNode.L2Info, rpcClient, options) } tx, err = simple1.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) tx, err = simple2.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) previousStorageRootHash1 := currentRootHash1 - currentRootHash1 = getStorageRootHash(t, node, contractAddress1) + currentRootHash1 = getStorageRootHash(t, testNode.L2Node, contractAddress1) if bytes.Equal(previousStorageRootHash1.Bytes(), currentRootHash1.Bytes()) { Fatal(t, "storage root hash didn't change as expected") } - currentSlotValueMap1 = getStorageSlotValue(t, node, contractAddress1) + currentSlotValueMap1 = getStorageSlotValue(t, testNode.L2Node, contractAddress1) previousStorageRootHash2 := currentRootHash2 - currentRootHash2 = getStorageRootHash(t, node, contractAddress2) + currentRootHash2 = getStorageRootHash(t, testNode.L2Node, contractAddress2) if bytes.Equal(previousStorageRootHash2.Bytes(), currentRootHash2.Bytes()) { Fatal(t, "storage root hash didn't change as expected") } - currentSlotValueMap2 = getStorageSlotValue(t, node, contractAddress2) + currentSlotValueMap2 = getStorageSlotValue(t, testNode.L2Node, contractAddress2) - block, err = l1client.BlockByNumber(ctx, nil) + block, err = testNode.L1Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() blockTime = block.Time() @@ -286,35 +286,35 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { options2 := dedupOptions(t, append(append(optionsCD, optionsC...), optionsD...)) options2 = optionsDedupProduct(t, options2, getFulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options2 { - testConditionalTxThatShouldSucceed(t, ctx, i, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, i, testNode.L2Info, rpcClient, options) } for i, options := range options1 { - testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, i, testNode.L2Info, rpcClient, options, -32003) } - block, err = l1client.BlockByNumber(ctx, nil) + block, err = testNode.L1Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() blockTime = block.Time() options3 := optionsDedupProduct(t, options2, getUnfulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options3 { - testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, i, testNode.L2Info, rpcClient, options, -32003) } options4 := optionsDedupProduct(t, options2, options1) for i, options := range options4 { - testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, i, testNode.L2Info, rpcClient, options, -32003) } } func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() - rpcClient, err := node.Stack.Attach() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() + rpcClient, err := testNode.L2Node.Stack.Attach() Require(t, err) - auth := l2info.GetDefaultTransactOpts("Owner", ctx) - contractAddress, simple := deploySimple(t, ctx, auth, client) + auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + contractAddress, simple := testNode.DeploySimple(t, auth) simpleContract, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) Require(t, err) @@ -325,11 +325,11 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { var options []*arbitrum_types.ConditionalOptions for i := 0; i < numTxes; i++ { account := fmt.Sprintf("User%v", i) - l2info.GenerateAccount(account) - tx := l2info.PrepareTx("Owner", account, l2info.TransferGas, big.NewInt(1e16), nil) - err := client.SendTransaction(ctx, tx) + testNode.L2Info.GenerateAccount(account) + tx := testNode.L2Info.PrepareTx("Owner", account, testNode.L2Info.TransferGas, big.NewInt(1e16), nil) + err := testNode.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) } for i := numTxes - 1; i >= 0; i-- { @@ -337,7 +337,7 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { data, err := simpleContract.Pack("logAndIncrement", big.NewInt(int64(expected))) Require(t, err) account := fmt.Sprintf("User%v", i) - txes = append(txes, l2info.PrepareTxTo(account, &contractAddress, l2info.TransferGas, big.NewInt(0), data)) + txes = append(txes, testNode.L2Info.PrepareTxTo(account, &contractAddress, testNode.L2Info.TransferGas, big.NewInt(0), data)) options = append(options, &arbitrum_types.ConditionalOptions{KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{contractAddress: {SlotValue: map[common.Hash]common.Hash{{0}: common.BigToHash(big.NewInt(int64(expected)))}}}}) } ctxWithTimeout, cancelCtxWithTimeout := context.WithTimeout(ctx, 5*time.Second) @@ -367,7 +367,7 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { } cancelCtxWithTimeout() wg.Wait() - bc := node.Execution.Backend.ArbInterface().BlockChain() + bc := testNode.L2Node.Execution.Backend.ArbInterface().BlockChain() genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum var receipts types.Receipts @@ -409,34 +409,34 @@ func TestSendRawTransactionConditionalPreCheck(t *testing.T) { nodeConfig.TxPreChecker.RequiredStateAge = 1 nodeConfig.TxPreChecker.RequiredStateMaxBlocks = 2 - l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, nil) - defer requireClose(t, l1stack) - defer node.StopAndWait() - rpcClient, err := node.Stack.Attach() + testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() + rpcClient, err := testNode.L2Node.Stack.Attach() Require(t, err) - l2info.GenerateAccount("User2") + testNode.L2Info.GenerateAccount("User2") - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) start := time.Now().Unix() - contractAddress, simple := deploySimple(t, ctx, auth, l2client) + contractAddress, simple := testNode.DeploySimple(t, auth) if time.Since(time.Unix(start, 0)) > 200*time.Millisecond { start++ time.Sleep(time.Until(time.Unix(start, 0))) } tx, err := simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) - currentRootHash := getStorageRootHash(t, node, contractAddress) + currentRootHash := getStorageRootHash(t, testNode.L2Node, contractAddress) options := &arbitrum_types.ConditionalOptions{ KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{ contractAddress: {RootHash: ¤tRootHash}, }, } - testConditionalTxThatShouldFail(t, ctx, 0, l2info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, 0, testNode.L2Info, rpcClient, options, -32003) time.Sleep(time.Until(time.Unix(start+1, 0))) - testConditionalTxThatShouldSucceed(t, ctx, 1, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, 1, testNode.L2Info, rpcClient, options) start = time.Now().Unix() if time.Since(time.Unix(start, 0)) > 200*time.Millisecond { @@ -445,23 +445,23 @@ func TestSendRawTransactionConditionalPreCheck(t *testing.T) { } tx, err = simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) - currentRootHash = getStorageRootHash(t, node, contractAddress) + currentRootHash = getStorageRootHash(t, testNode.L2Node, contractAddress) options = &arbitrum_types.ConditionalOptions{ KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{ contractAddress: {RootHash: ¤tRootHash}, }, } - testConditionalTxThatShouldFail(t, ctx, 2, l2info, rpcClient, options, -32003) - tx = l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) - Require(t, l2client.SendTransaction(ctx, tx)) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + testConditionalTxThatShouldFail(t, ctx, 2, testNode.L2Info, rpcClient, options, -32003) + tx = testNode.L2Info.PrepareTx("Owner", "User2", testNode.L2Info.TransferGas, big.NewInt(1e12), nil) + Require(t, testNode.L2Client.SendTransaction(ctx, tx)) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) - testConditionalTxThatShouldFail(t, ctx, 3, l2info, rpcClient, options, -32003) - tx = l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) - Require(t, l2client.SendTransaction(ctx, tx)) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + testConditionalTxThatShouldFail(t, ctx, 3, testNode.L2Info, rpcClient, options, -32003) + tx = testNode.L2Info.PrepareTx("Owner", "User2", testNode.L2Info.TransferGas, big.NewInt(1e12), nil) + Require(t, testNode.L2Client.SendTransaction(ctx, tx)) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) - testConditionalTxThatShouldSucceed(t, ctx, 4, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, 4, testNode.L2Info, rpcClient, options) } diff --git a/system_tests/contract_tx_test.go b/system_tests/contract_tx_test.go index e671dcc6a..ff2912f53 100644 --- a/system_tests/contract_tx_test.go +++ b/system_tests/contract_tx_test.go @@ -26,19 +26,18 @@ func TestContractTxDeploy(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - nodeconfig := arbnode.ConfigDefaultL2Test() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, false) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, false) + defer testNode.L2Node.StopAndWait() from := common.HexToAddress("0x123412341234") - TransferBalanceTo(t, "Faucet", from, big.NewInt(1e18), l2info, client, ctx) + TransferBalanceTo(t, "Faucet", from, big.NewInt(1e18), testNode.L2Info, testNode.L2Client, ctx) for stateNonce := uint64(0); stateNonce < 2; stateNonce++ { - pos, err := node.TxStreamer.GetMessageCount() + pos, err := testNode.L2Node.TxStreamer.GetMessageCount() Require(t, err) var delayedMessagesRead uint64 if pos > 0 { - lastMessage, err := node.TxStreamer.GetMessage(pos - 1) + lastMessage, err := testNode.L2Node.TxStreamer.GetMessage(pos - 1) Require(t, err) delayedMessagesRead = lastMessage.DelayedMessagesRead } @@ -70,7 +69,7 @@ func TestContractTxDeploy(t *testing.T) { l2Msg = append(l2Msg, math.U256Bytes(contractTx.Value)...) l2Msg = append(l2Msg, contractTx.Data...) - err = node.TxStreamer.AddMessages(pos, true, []arbostypes.MessageWithMetadata{ + err = testNode.L2Node.TxStreamer.AddMessages(pos, true, []arbostypes.MessageWithMetadata{ { Message: &arbostypes.L1IncomingMessage{ Header: &arbostypes.L1IncomingMessageHeader{ @@ -91,7 +90,7 @@ func TestContractTxDeploy(t *testing.T) { txHash := types.NewTx(contractTx).Hash() t.Log("made contract tx", contractTx, "with hash", txHash) - receipt, err := WaitForTx(ctx, client, txHash, time.Second*10) + receipt, err := WaitForTx(ctx, testNode.L2Client, txHash, time.Second*10) Require(t, err) if receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "Receipt has non-successful status", receipt.Status) @@ -104,7 +103,7 @@ func TestContractTxDeploy(t *testing.T) { t.Log("deployed contract", receipt.ContractAddress, "from address", from, "with nonce", stateNonce) stateNonce++ - code, err := client.CodeAt(ctx, receipt.ContractAddress, nil) + code, err := testNode.L2Client.CodeAt(ctx, receipt.ContractAddress, nil) Require(t, err) if !bytes.Equal(code, []byte{0xFE}) { Fatal(t, "expected contract", receipt.ContractAddress, "code of 0xFE but got", hex.EncodeToString(code)) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index 26b5a7814..449f816ba 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" + "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/node_interfacegen" @@ -26,17 +27,17 @@ func TestDeploy(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) auth.GasMargin = 0 // don't adjust, we want to see if the estimate alone is sufficient - _, simple := deploySimple(t, ctx, auth, client) + _, simple := testNode.DeploySimple(t, auth) tx, err := simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) counter, err := simple.Counter(&bind.CallOpts{}) @@ -51,24 +52,24 @@ func TestEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) auth.GasMargin = 0 // don't adjust, we want to see if the estimate alone is sufficient gasPrice := big.NewInt(params.GWei / 10) // set the gas price - arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), client) + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), testNode.L2Client) Require(t, err, "could not deploy ArbOwner contract") tx, err := arbOwner.SetMinimumL2BaseFee(&auth, gasPrice) Require(t, err, "could not set L2 gas price") - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) // connect to arbGasInfo precompile - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), testNode.L2Client) Require(t, err, "could not deploy contract") // wait for price to come to equilibrium @@ -76,8 +77,8 @@ func TestEstimate(t *testing.T) { numTriesLeft := 20 for !equilibrated && numTriesLeft > 0 { // make an empty block to let the gas price update - l2info.GasPrice = new(big.Int).Mul(l2info.GasPrice, big.NewInt(2)) - TransferBalance(t, "Owner", "Owner", common.Big0, l2info, client, ctx) + testNode.L2Info.GasPrice = new(big.Int).Mul(testNode.L2Info.GasPrice, big.NewInt(2)) + TransferBalance(t, "Owner", "Owner", common.Big0, testNode.L2Info, testNode.L2Client, ctx) // check if the price has equilibrated _, _, _, _, _, setPrice, err := arbGasInfo.GetPricesInWei(&bind.CallOpts{}) @@ -91,22 +92,22 @@ func TestEstimate(t *testing.T) { Fatal(t, "L2 gas price did not converge", gasPrice) } - initialBalance, err := client.BalanceAt(ctx, auth.From, nil) + initialBalance, err := testNode.L2Client.BalanceAt(ctx, auth.From, nil) Require(t, err, "could not get balance") // deploy a test contract - _, tx, simple, err := mocksgen.DeploySimple(&auth, client) + _, tx, simple, err := mocksgen.DeploySimple(&auth, testNode.L2Client) Require(t, err, "could not deploy contract") - receipt, err := EnsureTxSucceeded(ctx, client, tx) + receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) - header, err := client.HeaderByNumber(ctx, receipt.BlockNumber) + header, err := testNode.L2Client.HeaderByNumber(ctx, receipt.BlockNumber) Require(t, err, "could not get header") if header.BaseFee.Cmp(gasPrice) != 0 { Fatal(t, "Header has wrong basefee", header.BaseFee, gasPrice) } - balance, err := client.BalanceAt(ctx, auth.From, nil) + balance, err := testNode.L2Client.BalanceAt(ctx, auth.From, nil) Require(t, err, "could not get balance") expectedCost := receipt.GasUsed * gasPrice.Uint64() observedCost := initialBalance.Uint64() - balance.Uint64() @@ -116,7 +117,7 @@ func TestEstimate(t *testing.T) { tx, err = simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) counter, err := simple.Counter(&bind.CallOpts{}) @@ -131,11 +132,11 @@ func TestComponentEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() l1BaseFee := new(big.Int).Set(arbostypes.DefaultInitialL1BaseFee) - l2BaseFee := GetBaseFee(t, client, ctx) + l2BaseFee := GetBaseFee(t, testNode.L2Client, ctx) colors.PrintGrey("l1 basefee ", l1BaseFee) colors.PrintGrey("l2 basefee ", l2BaseFee) @@ -144,10 +145,10 @@ func TestComponentEstimate(t *testing.T) { maxPriorityFeePerGas := big.NewInt(0) maxFeePerGas := arbmath.BigMulByUfrac(l2BaseFee, 3, 2) - l2info.GenerateAccount("User") - TransferBalance(t, "Owner", "User", userBalance, l2info, client, ctx) + testNode.L2Info.GenerateAccount("User") + TransferBalance(t, "Owner", "User", userBalance, testNode.L2Info, testNode.L2Client, ctx) - from := l2info.GetAddress("User") + from := testNode.L2Info.GetAddress("User") to := testhelpers.RandomAddress() gas := uint64(100000000) calldata := []byte{0x00, 0x12} @@ -171,7 +172,7 @@ func TestComponentEstimate(t *testing.T) { Value: value, Data: estimateCalldata, } - returnData, err := client.CallContract(ctx, msg, nil) + returnData, err := testNode.L2Client.CallContract(ctx, msg, nil) Require(t, err) outputs, err := nodeMethod.Outputs.Unpack(returnData) @@ -185,8 +186,8 @@ func TestComponentEstimate(t *testing.T) { baseFee, _ := outputs[2].(*big.Int) l1BaseFeeEstimate, _ := outputs[3].(*big.Int) - tx := l2info.SignTxAs("User", &types.DynamicFeeTx{ - ChainID: node.Execution.ArbInterface.BlockChain().Config().ChainID, + tx := testNode.L2Info.SignTxAs("User", &types.DynamicFeeTx{ + ChainID: testNode.L2Node.Execution.ArbInterface.BlockChain().Config().ChainID, Nonce: 0, GasTipCap: maxPriorityFeePerGas, GasFeeCap: maxFeePerGas, @@ -207,8 +208,8 @@ func TestComponentEstimate(t *testing.T) { Fatal(t, baseFee, l2BaseFee.Uint64()) } - Require(t, client.SendTransaction(ctx, tx)) - receipt, err := EnsureTxSucceeded(ctx, client, tx) + Require(t, testNode.L2Client.SendTransaction(ctx, tx)) + receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) l2Used := receipt.GasUsed - receipt.GasUsedForL1 @@ -223,14 +224,14 @@ func TestDisableL1Charging(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() addr := common.HexToAddress("0x12345678") - gasWithL1Charging, err := client.EstimateGas(ctx, ethereum.CallMsg{To: &addr}) + gasWithL1Charging, err := testNode.L2Client.EstimateGas(ctx, ethereum.CallMsg{To: &addr}) Require(t, err) - gasWithoutL1Charging, err := client.EstimateGas(ctx, ethereum.CallMsg{To: &addr, SkipL1Charging: true}) + gasWithoutL1Charging, err := testNode.L2Client.EstimateGas(ctx, ethereum.CallMsg{To: &addr, SkipL1Charging: true}) Require(t, err) if gasWithL1Charging <= gasWithoutL1Charging { @@ -240,14 +241,14 @@ func TestDisableL1Charging(t *testing.T) { Fatal(t, "Incorrect gas estimate with disabled L1 charging") } - _, err = client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithL1Charging}, nil) + _, err = testNode.L2Client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithL1Charging}, nil) Require(t, err) - _, err = client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging}, nil) + _, err = testNode.L2Client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging}, nil) if err == nil { Fatal(t, "CallContract passed with insufficient gas") } - _, err = client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging, SkipL1Charging: true}, nil) + _, err = testNode.L2Client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging, SkipL1Charging: true}, nil) Require(t, err) } diff --git a/system_tests/infra_fee_test.go b/system_tests/infra_fee_test.go index 89f869576..10f43547f 100644 --- a/system_tests/infra_fee_test.go +++ b/system_tests/infra_fee_test.go @@ -25,45 +25,45 @@ func TestInfraFee(t *testing.T) { defer cancel() nodeconfig := arbnode.ConfigDefaultL2Test() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, true) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeconfig).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() - l2info.GenerateAccount("User2") + testNode.L2Info.GenerateAccount("User2") - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) + ownerTxOpts := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) ownerTxOpts.Context = ctx - ownerCallOpts := l2info.GetDefaultCallOpts("Owner", ctx) + ownerCallOpts := testNode.L2Info.GetDefaultCallOpts("Owner", ctx) - arbowner, err := precompilesgen.NewArbOwner(common.HexToAddress("70"), client) + arbowner, err := precompilesgen.NewArbOwner(common.HexToAddress("70"), testNode.L2Client) Require(t, err) - arbownerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("6b"), client) + arbownerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("6b"), testNode.L2Client) Require(t, err) networkFeeAddr, err := arbownerPublic.GetNetworkFeeAccount(ownerCallOpts) Require(t, err) infraFeeAddr := common.BytesToAddress(crypto.Keccak256([]byte{3, 2, 6})) tx, err := arbowner.SetInfraFeeAccount(&ownerTxOpts, infraFeeAddr) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) - _, simple := deploySimple(t, ctx, ownerTxOpts, client) + _, simple := testNode.DeploySimple(t, ownerTxOpts) - netFeeBalanceBefore, err := client.BalanceAt(ctx, networkFeeAddr, nil) + netFeeBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - infraFeeBalanceBefore, err := client.BalanceAt(ctx, infraFeeAddr, nil) + infraFeeBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) tx, err = simple.Increment(&ownerTxOpts) Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, client, tx) + receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) l2GasUsed := receipt.GasUsed - receipt.GasUsedForL1 expectedFunds := arbmath.BigMulByUint(arbmath.UintToBig(l2pricing.InitialBaseFeeWei), l2GasUsed) expectedBalanceAfter := arbmath.BigAdd(infraFeeBalanceBefore, expectedFunds) - netFeeBalanceAfter, err := client.BalanceAt(ctx, networkFeeAddr, nil) + netFeeBalanceAfter, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - infraFeeBalanceAfter, err := client.BalanceAt(ctx, infraFeeAddr, nil) + infraFeeBalanceAfter, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) if !arbmath.BigEquals(netFeeBalanceBefore, netFeeBalanceAfter) { diff --git a/system_tests/initialization_test.go b/system_tests/initialization_test.go index c7797d35e..cec68d693 100644 --- a/system_tests/initialization_test.go +++ b/system_tests/initialization_test.go @@ -63,14 +63,14 @@ func TestInitContract(t *testing.T) { l2info.ArbInitData.Accounts = append(l2info.ArbInitData.Accounts, accountInfo) expectedSums[accountAddress] = sum } - _, node, client := CreateTestL2WithConfig(t, ctx, l2info, arbnode.ConfigDefaultL2Test(), true) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).SetL2Info(l2info).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() for accountAddress, sum := range expectedSums { msg := ethereum.CallMsg{ To: &accountAddress, } - res, err := client.CallContract(ctx, msg, big.NewInt(0)) + res, err := testNode.L2Client.CallContract(ctx, msg, big.NewInt(0)) Require(t, err) resBig := new(big.Int).SetBytes(res) if resBig.Cmp(sum) != 0 { diff --git a/system_tests/log_subscription_test.go b/system_tests/log_subscription_test.go index 5ee1732fb..c64737bdc 100644 --- a/system_tests/log_subscription_test.go +++ b/system_tests/log_subscription_test.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" ) @@ -19,21 +20,21 @@ func TestLogSubscription(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) - arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, client) + auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, testNode.L2Client) Require(t, err) logChan := make(chan types.Log, 128) - subscription, err := client.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, logChan) + subscription, err := testNode.L2Client.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, logChan) Require(t, err) defer subscription.Unsubscribe() tx, err := arbSys.WithdrawEth(&auth, common.Address{}) Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, client, tx) + receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) if len(receipt.Logs) != 1 { @@ -52,6 +53,6 @@ func TestLogSubscription(t *testing.T) { if !reflect.DeepEqual(receiptLog, subscriptionLog) { Fatal(t, "Receipt log", receiptLog, "is different than subscription log", subscriptionLog) } - _, err = client.BlockByHash(ctx, subscriptionLog.BlockHash) + _, err = testNode.L2Client.BlockByHash(ctx, subscriptionLog.BlockHash) Require(t, err) } diff --git a/system_tests/outbox_test.go b/system_tests/outbox_test.go index 6b43cc83b..e0db03411 100644 --- a/system_tests/outbox_test.go +++ b/system_tests/outbox_test.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/gethhook" "github.com/offchainlabs/nitro/solgen/go/node_interfacegen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" @@ -35,14 +36,14 @@ func TestOutboxProofs(t *testing.T) { withdrawTopic := arbSysAbi.Events["L2ToL1Tx"].ID merkleTopic := arbSysAbi.Events["SendMerkleUpdate"].ID - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) - arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, client) + arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, testNode.L2Client) Require(t, err) - nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, client) + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, testNode.L2Client) Require(t, err) txnCount := int64(1 + rand.Intn(16)) @@ -71,7 +72,7 @@ func TestOutboxProofs(t *testing.T) { txns = append(txns, tx.Hash()) time.Sleep(4 * time.Millisecond) // Geth takes a few ms for the receipt to show up - _, err = client.TransactionReceipt(ctx, tx.Hash()) + _, err = testNode.L2Client.TransactionReceipt(ctx, tx.Hash()) if err == nil { merkleState, err := arbSys.SendMerkleTreeState(&bind.CallOpts{}) Require(t, err, "could not get merkle root") @@ -86,7 +87,7 @@ func TestOutboxProofs(t *testing.T) { for _, tx := range txns { var receipt *types.Receipt - receipt, err = client.TransactionReceipt(ctx, tx) + receipt, err = testNode.L2Client.TransactionReceipt(ctx, tx) Require(t, err, "No receipt for txn") if receipt.Status != types.ReceiptStatusSuccessful { @@ -187,7 +188,7 @@ func TestOutboxProofs(t *testing.T) { // in one lookup, query geth for all the data we need to construct a proof var logs []types.Log if len(query) > 0 { - logs, err = client.FilterLogs(ctx, ethereum.FilterQuery{ + logs, err = testNode.L2Client.FilterLogs(ctx, ethereum.FilterQuery{ Addresses: []common.Address{ types.ArbSysAddress, }, diff --git a/system_tests/precompile_test.go b/system_tests/precompile_test.go index ad08ff747..261c45035 100644 --- a/system_tests/precompile_test.go +++ b/system_tests/precompile_test.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/params" + "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" @@ -21,10 +22,10 @@ func TestPurePrecompileMethodCalls(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() - arbSys, err := precompilesgen.NewArbSys(common.HexToAddress("0x64"), client) + arbSys, err := precompilesgen.NewArbSys(common.HexToAddress("0x64"), testNode.L2Client) Require(t, err, "could not deploy ArbSys contract") chainId, err := arbSys.ArbChainID(&bind.CallOpts{}) Require(t, err, "failed to get the ChainID") @@ -37,10 +38,10 @@ func TestViewLogReverts(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), testNode.L2Client) Require(t, err, "could not deploy ArbSys contract") err = arbDebug.EventsView(nil) @@ -53,11 +54,11 @@ func TestCustomSolidityErrors(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() callOpts := &bind.CallOpts{Context: ctx} - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), testNode.L2Client) Require(t, err, "could not bind ArbDebug contract") customError := arbDebug.CustomRevert(callOpts, 1024) if customError == nil { @@ -69,7 +70,7 @@ func TestCustomSolidityErrors(t *testing.T) { Fatal(t, observedMessage) } - arbSys, err := precompilesgen.NewArbSys(arbos.ArbSysAddress, client) + arbSys, err := precompilesgen.NewArbSys(arbos.ArbSysAddress, testNode.L2Client) Require(t, err, "could not bind ArbSys contract") _, customError = arbSys.ArbBlockHash(callOpts, big.NewInt(1e9)) if customError == nil { @@ -86,11 +87,11 @@ func TestPrecompileErrorGasLeft(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() - auth := info.GetDefaultTransactOpts("Faucet", ctx) - _, _, simple, err := mocksgen.DeploySimple(&auth, client) + auth := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) + _, _, simple, err := mocksgen.DeploySimple(&auth, testNode.L2Client) Require(t, err) assertNotAllGasConsumed := func(to common.Address, input []byte) { diff --git a/system_tests/reorg_resequencing_test.go b/system_tests/reorg_resequencing_test.go index f132d4648..4f72f9823 100644 --- a/system_tests/reorg_resequencing_test.go +++ b/system_tests/reorg_resequencing_test.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/params" + "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/arbostypes" ) @@ -19,27 +20,27 @@ func TestReorgResequencing(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() - startMsgCount, err := node.TxStreamer.GetMessageCount() + startMsgCount, err := testNode.L2Node.TxStreamer.GetMessageCount() Require(t, err) - l2info.GenerateAccount("Intermediate") - l2info.GenerateAccount("User1") - l2info.GenerateAccount("User2") - l2info.GenerateAccount("User3") - l2info.GenerateAccount("User4") - TransferBalance(t, "Owner", "User1", big.NewInt(params.Ether), l2info, client, ctx) - TransferBalance(t, "Owner", "Intermediate", big.NewInt(params.Ether*3), l2info, client, ctx) - TransferBalance(t, "Intermediate", "User2", big.NewInt(params.Ether), l2info, client, ctx) - TransferBalance(t, "Intermediate", "User3", big.NewInt(params.Ether), l2info, client, ctx) + testNode.L2Info.GenerateAccount("Intermediate") + testNode.L2Info.GenerateAccount("User1") + testNode.L2Info.GenerateAccount("User2") + testNode.L2Info.GenerateAccount("User3") + testNode.L2Info.GenerateAccount("User4") + TransferBalance(t, "Owner", "User1", big.NewInt(params.Ether), testNode.L2Info, testNode.L2Client, ctx) + TransferBalance(t, "Owner", "Intermediate", big.NewInt(params.Ether*3), testNode.L2Info, testNode.L2Client, ctx) + TransferBalance(t, "Intermediate", "User2", big.NewInt(params.Ether), testNode.L2Info, testNode.L2Client, ctx) + TransferBalance(t, "Intermediate", "User3", big.NewInt(params.Ether), testNode.L2Info, testNode.L2Client, ctx) // Intermediate does not have exactly 1 ether because of fees accountsWithBalance := []string{"User1", "User2", "User3"} verifyBalances := func(scenario string) { for _, account := range accountsWithBalance { - balance, err := client.BalanceAt(ctx, l2info.GetAddress(account), nil) + balance, err := testNode.L2Client.BalanceAt(ctx, testNode.L2Info.GetAddress(account), nil) Require(t, err) if balance.Int64() != params.Ether { Fatal(t, "expected account", account, "to have a balance of 1 ether but instead it has", balance, "wei "+scenario) @@ -48,15 +49,15 @@ func TestReorgResequencing(t *testing.T) { } verifyBalances("before reorg") - err = node.TxStreamer.ReorgTo(startMsgCount) + err = testNode.L2Node.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = node.Execution.ExecEngine.HeadMessageNumberSync(t) + _, err = testNode.L2Node.Execution.ExecEngine.HeadMessageNumberSync(t) Require(t, err) verifyBalances("after empty reorg") - prevMessage, err := node.TxStreamer.GetMessage(startMsgCount - 1) + prevMessage, err := testNode.L2Node.TxStreamer.GetMessage(startMsgCount - 1) Require(t, err) delayedIndexHash := common.BigToHash(big.NewInt(int64(prevMessage.DelayedMessagesRead))) newMessage := &arbostypes.L1IncomingMessage{ @@ -68,24 +69,24 @@ func TestReorgResequencing(t *testing.T) { RequestId: &delayedIndexHash, L1BaseFee: common.Big0, }, - L2msg: append(l2info.GetAddress("User4").Bytes(), math.U256Bytes(big.NewInt(params.Ether))...), + L2msg: append(testNode.L2Info.GetAddress("User4").Bytes(), math.U256Bytes(big.NewInt(params.Ether))...), } - err = node.TxStreamer.AddMessages(startMsgCount, true, []arbostypes.MessageWithMetadata{{ + err = testNode.L2Node.TxStreamer.AddMessages(startMsgCount, true, []arbostypes.MessageWithMetadata{{ Message: newMessage, DelayedMessagesRead: prevMessage.DelayedMessagesRead + 1, }}) Require(t, err) - _, err = node.Execution.ExecEngine.HeadMessageNumberSync(t) + _, err = testNode.L2Node.Execution.ExecEngine.HeadMessageNumberSync(t) Require(t, err) accountsWithBalance = append(accountsWithBalance, "User4") verifyBalances("after reorg with new deposit") - err = node.TxStreamer.ReorgTo(startMsgCount) + err = testNode.L2Node.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = node.Execution.ExecEngine.HeadMessageNumberSync(t) + _, err = testNode.L2Node.Execution.ExecEngine.HeadMessageNumberSync(t) Require(t, err) verifyBalances("after second empty reorg") diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index b1dd32d1d..eb7d3528c 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -32,25 +32,22 @@ import ( ) func retryableSetup(t *testing.T) ( - *BlockchainTestInfo, - *BlockchainTestInfo, - *ethclient.Client, - *ethclient.Client, + *NodeBuilder, *bridgegen.Inbox, func(*types.Receipt) *types.Transaction, context.Context, func(), ) { ctx, cancel := context.WithCancel(context.Background()) - l2info, l2node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) + testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - l2info.GenerateAccount("User2") - l2info.GenerateAccount("Beneficiary") - l2info.GenerateAccount("Burn") + testNode.L2Info.GenerateAccount("User2") + testNode.L2Info.GenerateAccount("Beneficiary") + testNode.L2Info.GenerateAccount("Burn") - delayedInbox, err := bridgegen.NewInbox(l1info.GetAddress("Inbox"), l1client) + delayedInbox, err := bridgegen.NewInbox(testNode.L1Info.GetAddress("Inbox"), testNode.L1Client) Require(t, err) - delayedBridge, err := arbnode.NewDelayedBridge(l1client, l1info.GetAddress("Bridge"), 0) + delayedBridge, err := arbnode.NewDelayedBridge(testNode.L1Client, testNode.L1Info.GetAddress("Bridge"), 0) Require(t, err) lookupL2Tx := func(l1Receipt *types.Receipt) *types.Transaction { @@ -90,15 +87,15 @@ func retryableSetup(t *testing.T) ( // burn some gas so that the faucet's Callvalue + Balance never exceeds a uint256 discard := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - TransferBalance(t, "Faucet", "Burn", discard, l2info, l2client, ctx) + TransferBalance(t, "Faucet", "Burn", discard, testNode.L2Info, testNode.L2Client, ctx) teardown := func() { // check the integrity of the RPC - blockNum, err := l2client.BlockNumber(ctx) + blockNum, err := testNode.L2Client.BlockNumber(ctx) Require(t, err, "failed to get L2 block number") for number := uint64(0); number < blockNum; number++ { - block, err := l2client.BlockByNumber(ctx, arbmath.UintToBig(number)) + block, err := testNode.L2Client.BlockByNumber(ctx, arbmath.UintToBig(number)) Require(t, err, "failed to get L2 block", number, "of", blockNum) if block.Number().Uint64() != number { Fatal(t, "block number mismatch", number, block.Number().Uint64()) @@ -107,19 +104,20 @@ func retryableSetup(t *testing.T) ( cancel() - l2node.StopAndWait() - requireClose(t, l1stack) + testNode.L2Node.StopAndWait() + requireClose(t, testNode.L1Stack) } - return l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown + return testNode, delayedInbox, lookupL2Tx, ctx, teardown } func TestRetryableNoExist(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, l2client := CreateTestL2(t, ctx) - defer node.StopAndWait() - arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() + + arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), testNode.L2Client) Require(t, err) _, err = arbRetryableTx.GetTimeout(&bind.CallOpts{}, common.Hash{}) if err.Error() != "execution reverted: error NoTicketWithID()" { @@ -129,20 +127,20 @@ func TestRetryableNoExist(t *testing.T) { func TestSubmitRetryableImmediateSuccess(t *testing.T) { t.Parallel() - l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - user2Address := l2info.GetAddress("User2") - beneficiaryAddress := l2info.GetAddress("Beneficiary") + user2Address := testNode.L2Info.GetAddress("User2") + beneficiaryAddress := testNode.L2Info.GetAddress("Beneficiary") deposit := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) callValue := big.NewInt(1e6) - nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, testNode.L2Client) Require(t, err, "failed to deploy NodeInterface") // estimate the gas needed to auto redeem the retryable - usertxoptsL2 := l2info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL2 := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL2.NoSend = true usertxoptsL2.GasMargin = 0 tx, err := nodeInterface.EstimateRetryableTicket( @@ -160,7 +158,7 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { colors.PrintBlue("estimate: ", estimate) // submit & auto redeem the retryable using the gas estimate - usertxoptsL1 := l1info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL1 := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL1.Value = deposit l1tx, err := delayedInbox.CreateRetryableTicket( &usertxoptsL1, @@ -175,21 +173,21 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) - receipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) + receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, lookupL2Tx(l1Receipt)) Require(t, err) if receipt.Status != types.ReceiptStatusSuccessful { Fatal(t) } - l2balance, err := l2client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := testNode.L2Client.BalanceAt(ctx, testNode.L2Info.GetAddress("User2"), nil) Require(t, err) if !arbmath.BigEquals(l2balance, big.NewInt(1e6)) { @@ -199,18 +197,18 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { func TestSubmitRetryableFailThenRetry(t *testing.T) { t.Parallel() - l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) - usertxopts := l1info.GetDefaultTransactOpts("Faucet", ctx) + ownerTxOpts := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + usertxopts := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxopts.Value = arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - simpleAddr, simple := deploySimple(t, ctx, ownerTxOpts, l2client) + simpleAddr, simple := testNode.DeploySimple(t, ownerTxOpts) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) - beneficiaryAddress := l2info.GetAddress("Beneficiary") + beneficiaryAddress := testNode.L2Info.GetAddress("Beneficiary") l1tx, err := delayedInbox.CreateRetryableTicket( &usertxopts, simpleAddr, @@ -225,15 +223,15 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) - receipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) + receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, lookupL2Tx(l1Receipt)) Require(t, err) if len(receipt.Logs) != 2 { Fatal(t, len(receipt.Logs)) @@ -242,23 +240,23 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { firstRetryTxId := receipt.Logs[1].Topics[2] // get receipt for the auto redeem, make sure it failed - receipt, err = WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) + receipt, err = WaitForTx(ctx, testNode.L2Client, firstRetryTxId, time.Second*5) Require(t, err) if receipt.Status != types.ReceiptStatusFailed { Fatal(t, receipt.GasUsed) } - arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) + arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), testNode.L2Client) Require(t, err) tx, err := arbRetryableTx.Redeem(&ownerTxOpts, ticketId) Require(t, err) - receipt, err = EnsureTxSucceeded(ctx, l2client, tx) + receipt, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) retryTxId := receipt.Logs[0].Topics[2] // check the receipt for the retry - receipt, err = WaitForTx(ctx, l2client, retryTxId, time.Second*1) + receipt, err = WaitForTx(ctx, testNode.L2Client, retryTxId, time.Second*1) Require(t, err) if receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, receipt.Status) @@ -288,32 +286,32 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { func TestSubmissionGasCosts(t *testing.T) { t.Parallel() - l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, l2client, l2info) - elevateL2Basefee(t, ctx, l2client, l2info) + infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, testNode.L2Client, testNode.L2Info) + elevateL2Basefee(t, ctx, testNode.L2Client, testNode.L2Info) - usertxopts := l1info.GetDefaultTransactOpts("Faucet", ctx) + usertxopts := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxopts.Value = arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - l2info.GenerateAccount("Refund") - l2info.GenerateAccount("Receive") - faucetAddress := util.RemapL1Address(l1info.GetAddress("Faucet")) - beneficiaryAddress := l2info.GetAddress("Beneficiary") - feeRefundAddress := l2info.GetAddress("Refund") - receiveAddress := l2info.GetAddress("Receive") + testNode.L2Info.GenerateAccount("Refund") + testNode.L2Info.GenerateAccount("Receive") + faucetAddress := util.RemapL1Address(testNode.L1Info.GetAddress("Faucet")) + beneficiaryAddress := testNode.L2Info.GetAddress("Beneficiary") + feeRefundAddress := testNode.L2Info.GetAddress("Refund") + receiveAddress := testNode.L2Info.GetAddress("Receive") colors.PrintBlue("Faucet ", faucetAddress) colors.PrintBlue("Receive ", receiveAddress) colors.PrintBlue("Beneficiary ", beneficiaryAddress) colors.PrintBlue("Fee Refund ", feeRefundAddress) - fundsBeforeSubmit, err := l2client.BalanceAt(ctx, faucetAddress, nil) + fundsBeforeSubmit, err := testNode.L2Client.BalanceAt(ctx, faucetAddress, nil) Require(t, err) - infraBalanceBefore, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceBefore, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) usefulGas := params.TxGas @@ -337,28 +335,28 @@ func TestSubmissionGasCosts(t *testing.T) { ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) submissionTxOuter := lookupL2Tx(l1Receipt) - submissionReceipt, err := EnsureTxSucceeded(ctx, l2client, submissionTxOuter) + submissionReceipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, submissionTxOuter) Require(t, err) if len(submissionReceipt.Logs) != 2 { Fatal(t, "Unexpected number of logs:", len(submissionReceipt.Logs)) } firstRetryTxId := submissionReceipt.Logs[1].Topics[2] // get receipt for the auto redeem - redeemReceipt, err := WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) + redeemReceipt, err := WaitForTx(ctx, testNode.L2Client, firstRetryTxId, time.Second*5) Require(t, err) if redeemReceipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "first retry tx failed") } - redeemBlock, err := l2client.HeaderByNumber(ctx, redeemReceipt.BlockNumber) + redeemBlock, err := testNode.L2Client.HeaderByNumber(ctx, redeemReceipt.BlockNumber) Require(t, err) l2BaseFee := redeemBlock.BaseFee @@ -366,18 +364,18 @@ func TestSubmissionGasCosts(t *testing.T) { excessWei := arbmath.BigMulByUint(l2BaseFee, excessGasLimit) excessWei.Add(excessWei, arbmath.BigMul(excessGasPrice, retryableGas)) - fundsAfterSubmit, err := l2client.BalanceAt(ctx, faucetAddress, nil) + fundsAfterSubmit, err := testNode.L2Client.BalanceAt(ctx, faucetAddress, nil) Require(t, err) - beneficiaryFunds, err := l2client.BalanceAt(ctx, beneficiaryAddress, nil) + beneficiaryFunds, err := testNode.L2Client.BalanceAt(ctx, beneficiaryAddress, nil) Require(t, err) - refundFunds, err := l2client.BalanceAt(ctx, feeRefundAddress, nil) + refundFunds, err := testNode.L2Client.BalanceAt(ctx, feeRefundAddress, nil) Require(t, err) - receiveFunds, err := l2client.BalanceAt(ctx, receiveAddress, nil) + receiveFunds, err := testNode.L2Client.BalanceAt(ctx, receiveAddress, nil) Require(t, err) - infraBalanceAfter, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceAfter, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceAfter, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceAfter, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) colors.PrintBlue("CallGas ", retryableGas) @@ -424,7 +422,7 @@ func TestSubmissionGasCosts(t *testing.T) { Fatal(t, "Supplied gas was improperly deducted\n", fundsBeforeSubmit, "\n", fundsAfterSubmit) } - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), testNode.L2Client) Require(t, err) minimumBaseFee, err := arbGasInfo.GetMinimumGasPrice(&bind.CallOpts{Context: ctx}) Require(t, err) @@ -460,17 +458,17 @@ func waitForL1DelayBlocks(t *testing.T, ctx context.Context, l1client *ethclient func TestDepositETH(t *testing.T) { t.Parallel() - _, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - faucetAddr := l1info.GetAddress("Faucet") + faucetAddr := testNode.L1Info.GetAddress("Faucet") - oldBalance, err := l2client.BalanceAt(ctx, faucetAddr, nil) + oldBalance, err := testNode.L2Client.BalanceAt(ctx, faucetAddr, nil) if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", faucetAddr, err) } - txOpts := l1info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) txOpts.Value = big.NewInt(13) l1tx, err := delayedInbox.DepositEth0(&txOpts) @@ -478,20 +476,20 @@ func TestDepositETH(t *testing.T) { t.Fatalf("DepositEth0() unexected error: %v", err) } - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) if err != nil { t.Fatalf("EnsureTxSucceeded() unexpected error: %v", err) } if l1Receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("Got transaction status: %v, want: %v", l1Receipt.Status, types.ReceiptStatusSuccessful) } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) - l2Receipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) + l2Receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, lookupL2Tx(l1Receipt)) if err != nil { t.Fatalf("EnsureTxSucceeded unexpected error: %v", err) } - newBalance, err := l2client.BalanceAt(ctx, faucetAddr, l2Receipt.BlockNumber) + newBalance, err := testNode.L2Client.BalanceAt(ctx, faucetAddr, l2Receipt.BlockNumber) if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", faucetAddr, err) } @@ -501,13 +499,13 @@ func TestDepositETH(t *testing.T) { } func TestArbitrumContractTx(t *testing.T) { - l2Info, l1Info, l2Client, l1Client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - faucetL2Addr := util.RemapL1Address(l1Info.GetAddress("Faucet")) - TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), l2Info, l2Client, ctx) + faucetL2Addr := util.RemapL1Address(testNode.L1Info.GetAddress("Faucet")) + TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), testNode.L2Info, testNode.L2Client, ctx) - l2TxOpts := l2Info.GetDefaultTransactOpts("Faucet", ctx) - l2ContractAddr, _ := deploySimple(t, ctx, l2TxOpts, l2Client) + l2TxOpts := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) + l2ContractAddr, _ := testNode.DeploySimple(t, l2TxOpts) l2ContractABI, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) if err != nil { t.Fatalf("Error parsing contract ABI: %v", err) @@ -517,15 +515,15 @@ func TestArbitrumContractTx(t *testing.T) { t.Fatalf("Error packing method's call data: %v", err) } unsignedTx := types.NewTx(&types.ArbitrumContractTx{ - ChainId: l2Info.Signer.ChainID(), + ChainId: testNode.L2Info.Signer.ChainID(), From: faucetL2Addr, - GasFeeCap: l2Info.GasPrice.Mul(l2Info.GasPrice, big.NewInt(2)), + GasFeeCap: testNode.L2Info.GasPrice.Mul(testNode.L2Info.GasPrice, big.NewInt(2)), Gas: 1e6, To: &l2ContractAddr, Value: common.Big0, Data: data, }) - txOpts := l1Info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) l1tx, err := delayedInbox.SendContractTransaction( &txOpts, arbmath.UintToBig(unsignedTx.Gas()), @@ -537,15 +535,15 @@ func TestArbitrumContractTx(t *testing.T) { if err != nil { t.Fatalf("Error sending unsigned transaction: %v", err) } - receipt, err := EnsureTxSucceeded(ctx, l1Client, l1tx) + receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", l1tx.Hash(), err) } if receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("L1 transaction: %v has failed", l1tx.Hash()) } - waitForL1DelayBlocks(t, ctx, l1Client, l1Info) - receipt, err = EnsureTxSucceeded(ctx, l2Client, lookupL2Tx(receipt)) + waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) + receipt, err = EnsureTxSucceeded(ctx, testNode.L2Client, lookupL2Tx(receipt)) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", unsignedTx.Hash(), err) } @@ -554,17 +552,17 @@ func TestArbitrumContractTx(t *testing.T) { func TestL1FundedUnsignedTransaction(t *testing.T) { t.Parallel() ctx := context.Background() - l2Info, node, l2Client, l1Info, _, l1Client, l1Stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1Stack) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() - faucetL2Addr := util.RemapL1Address(l1Info.GetAddress("Faucet")) + faucetL2Addr := util.RemapL1Address(testNode.L1Info.GetAddress("Faucet")) // Transfer balance to Faucet's corresponding L2 address, so that there is // enough balance on its' account for executing L2 transaction. - TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), l2Info, l2Client, ctx) + TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), testNode.L2Info, testNode.L2Client, ctx) - l2TxOpts := l2Info.GetDefaultTransactOpts("Faucet", ctx) - contractAddr, _ := deploySimple(t, ctx, l2TxOpts, l2Client) + l2TxOpts := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) + contractAddr, _ := testNode.DeploySimple(t, l2TxOpts) contractABI, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) if err != nil { t.Fatalf("Error parsing contract ABI: %v", err) @@ -573,27 +571,27 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { if err != nil { t.Fatalf("Error packing method's call data: %v", err) } - nonce, err := l2Client.NonceAt(ctx, faucetL2Addr, nil) + nonce, err := testNode.L2Client.NonceAt(ctx, faucetL2Addr, nil) if err != nil { t.Fatalf("Error getting nonce at address: %v, error: %v", faucetL2Addr, err) } unsignedTx := types.NewTx(&types.ArbitrumUnsignedTx{ - ChainId: l2Info.Signer.ChainID(), + ChainId: testNode.L2Info.Signer.ChainID(), From: faucetL2Addr, Nonce: nonce, - GasFeeCap: l2Info.GasPrice, + GasFeeCap: testNode.L2Info.GasPrice, Gas: 1e6, To: &contractAddr, Value: common.Big0, Data: data, }) - delayedInbox, err := bridgegen.NewInbox(l1Info.GetAddress("Inbox"), l1Client) + delayedInbox, err := bridgegen.NewInbox(testNode.L1Info.GetAddress("Inbox"), testNode.L1Client) if err != nil { t.Fatalf("Error getting Go binding of L1 Inbox contract: %v", err) } - txOpts := l1Info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) l1tx, err := delayedInbox.SendUnsignedTransaction( &txOpts, arbmath.UintToBig(unsignedTx.Gas()), @@ -606,15 +604,15 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { if err != nil { t.Fatalf("Error sending unsigned transaction: %v", err) } - receipt, err := EnsureTxSucceeded(ctx, l1Client, l1tx) + receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", l1tx.Hash(), err) } if receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("L1 transaction: %v has failed", l1tx.Hash()) } - waitForL1DelayBlocks(t, ctx, l1Client, l1Info) - receipt, err = EnsureTxSucceeded(ctx, l2Client, unsignedTx) + waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) + receipt, err = EnsureTxSucceeded(ctx, testNode.L2Client, unsignedTx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", unsignedTx.Hash(), err) } @@ -624,28 +622,28 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { } func TestRetryableSubmissionAndRedeemFees(t *testing.T) { - l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, l2client, l2info) + infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, testNode.L2Client, testNode.L2Info) - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) - simpleAddr, simple := deploySimple(t, ctx, ownerTxOpts, l2client) + ownerTxOpts := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + simpleAddr, simple := testNode.DeploySimple(t, ownerTxOpts) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) - elevateL2Basefee(t, ctx, l2client, l2info) + elevateL2Basefee(t, ctx, testNode.L2Client, testNode.L2Info) - infraBalanceBefore, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceBefore, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - beneficiaryAddress := l2info.GetAddress("Beneficiary") + beneficiaryAddress := testNode.L2Info.GetAddress("Beneficiary") deposit := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) callValue := common.Big0 - usertxoptsL1 := l1info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL1 := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL1.Value = deposit - baseFee := GetBaseFee(t, l2client, ctx) + baseFee := GetBaseFee(t, testNode.L2Client, ctx) l1tx, err := delayedInbox.CreateRetryableTicket( &usertxoptsL1, simpleAddr, @@ -659,16 +657,16 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { simpleABI.Methods["incrementRedeem"].ID, ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) submissionTxOuter := lookupL2Tx(l1Receipt) - submissionReceipt, err := EnsureTxSucceeded(ctx, l2client, submissionTxOuter) + submissionReceipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, submissionTxOuter) Require(t, err) if len(submissionReceipt.Logs) != 2 { Fatal(t, len(submissionReceipt.Logs)) @@ -676,36 +674,36 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { ticketId := submissionReceipt.Logs[0].Topics[1] firstRetryTxId := submissionReceipt.Logs[1].Topics[2] // get receipt for the auto redeem, make sure it failed - autoRedeemReceipt, err := WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) + autoRedeemReceipt, err := WaitForTx(ctx, testNode.L2Client, firstRetryTxId, time.Second*5) Require(t, err) if autoRedeemReceipt.Status != types.ReceiptStatusFailed { Fatal(t, "first retry tx shouldn't have succeeded") } - infraBalanceAfterSubmission, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceAfterSubmission, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceAfterSubmission, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceAfterSubmission, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - usertxoptsL2 := l2info.GetDefaultTransactOpts("Faucet", ctx) - arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) + usertxoptsL2 := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) + arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), testNode.L2Client) Require(t, err) tx, err := arbRetryableTx.Redeem(&usertxoptsL2, ticketId) Require(t, err) - redeemReceipt, err := EnsureTxSucceeded(ctx, l2client, tx) + redeemReceipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) retryTxId := redeemReceipt.Logs[0].Topics[2] // check the receipt for the retry - retryReceipt, err := WaitForTx(ctx, l2client, retryTxId, time.Second*1) + retryReceipt, err := WaitForTx(ctx, testNode.L2Client, retryTxId, time.Second*1) Require(t, err) if retryReceipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "retry failed") } - infraBalanceAfterRedeem, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceAfterRedeem, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceAfterRedeem, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceAfterRedeem, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) // verify that the increment happened, so we know the retry succeeded @@ -734,11 +732,11 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { infraRedeemFee := arbmath.BigSub(infraBalanceAfterRedeem, infraBalanceAfterSubmission) networkRedeemFee := arbmath.BigSub(networkBalanceAfterRedeem, networkBalanceAfterSubmission) - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), testNode.L2Client) Require(t, err) minimumBaseFee, err := arbGasInfo.GetMinimumGasPrice(&bind.CallOpts{Context: ctx}) Require(t, err) - submissionBaseFee := GetBaseFeeAt(t, l2client, ctx, submissionReceipt.BlockNumber) + submissionBaseFee := GetBaseFeeAt(t, testNode.L2Client, ctx, submissionReceipt.BlockNumber) submissionTx, ok := submissionTxOuter.GetInner().(*types.ArbitrumSubmitRetryableTx) if !ok { Fatal(t, "inner tx isn't ArbitrumSubmitRetryableTx") @@ -752,13 +750,13 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { retryableSubmissionFee, ) - retryTxOuter, _, err := l2client.TransactionByHash(ctx, retryTxId) + retryTxOuter, _, err := testNode.L2Client.TransactionByHash(ctx, retryTxId) Require(t, err) retryTx, ok := retryTxOuter.GetInner().(*types.ArbitrumRetryTx) if !ok { Fatal(t, "inner tx isn't ArbitrumRetryTx") } - redeemBaseFee := GetBaseFeeAt(t, l2client, ctx, redeemReceipt.BlockNumber) + redeemBaseFee := GetBaseFeeAt(t, testNode.L2Client, ctx, redeemReceipt.BlockNumber) t.Log("redeem base fee:", redeemBaseFee) // redeem & retry expected fees diff --git a/system_tests/seq_coordinator_test.go b/system_tests/seq_coordinator_test.go index b1f50c943..27b7031dc 100644 --- a/system_tests/seq_coordinator_test.go +++ b/system_tests/seq_coordinator_test.go @@ -62,8 +62,8 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { createStartNode := func(nodeNum int) { nodeConfig.SeqCoordinator.MyUrl = nodeNames[nodeNum] - _, node, _ := CreateTestL2WithConfig(t, ctx, l2Info, nodeConfig, false) - nodes[nodeNum] = node + testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeConfig).SetL2Info(l2Info).CreateTestNodeOnL2Only(t, false) + nodes[nodeNum] = testNode.L2Node } trySequencing := func(nodeNum int) bool { diff --git a/system_tests/seq_nonce_test.go b/system_tests/seq_nonce_test.go index 968f14136..18363b998 100644 --- a/system_tests/seq_nonce_test.go +++ b/system_tests/seq_nonce_test.go @@ -26,10 +26,10 @@ func TestSequencerParallelNonces(t *testing.T) { config := arbnode.ConfigDefaultL2Test() config.Sequencer.NonceFailureCacheExpiry = time.Minute - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(config).CreateTestNodeOnL2Only(t, false) + defer testNode.L2Node.StopAndWait() - l2info.GenerateAccount("Destination") + testNode.L2Info.GenerateAccount("Destination") wg := sync.WaitGroup{} for thread := 0; thread < 10; thread++ { @@ -37,11 +37,11 @@ func TestSequencerParallelNonces(t *testing.T) { go func() { defer wg.Done() for i := 0; i < 10; i++ { - tx := l2info.PrepareTx("Owner", "Destination", l2info.TransferGas, common.Big1, nil) + tx := testNode.L2Info.PrepareTx("Owner", "Destination", testNode.L2Info.TransferGas, common.Big1, nil) // Sleep a random amount of time up to 20 milliseconds time.Sleep(time.Millisecond * time.Duration(rand.Intn(20))) t.Log("Submitting transaction with nonce", tx.Nonce()) - err := client.SendTransaction(ctx, tx) + err := testNode.L2Client.SendTransaction(ctx, tx) Require(t, err) t.Log("Got response for transaction with nonce", tx.Nonce()) } @@ -49,8 +49,8 @@ func TestSequencerParallelNonces(t *testing.T) { } wg.Wait() - addr := l2info.GetAddress("Destination") - balance, err := client.BalanceAt(ctx, addr, nil) + addr := testNode.L2Info.GetAddress("Destination") + balance, err := testNode.L2Client.BalanceAt(ctx, addr, nil) Require(t, err) if !arbmath.BigEquals(balance, big.NewInt(100)) { Fatal(t, "Unexpected user balance", balance) @@ -63,14 +63,14 @@ func TestSequencerNonceTooHigh(t *testing.T) { defer cancel() config := arbnode.ConfigDefaultL2Test() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(config).CreateTestNodeOnL2Only(t, false) + defer testNode.L2Node.StopAndWait() - l2info.GetInfoWithPrivKey("Owner").Nonce++ + testNode.L2Info.GetInfoWithPrivKey("Owner").Nonce++ before := time.Now() - tx := l2info.PrepareTx("Owner", "Owner", l2info.TransferGas, common.Big0, nil) - err := client.SendTransaction(ctx, tx) + tx := testNode.L2Info.PrepareTx("Owner", "Owner", testNode.L2Info.TransferGas, common.Big0, nil) + err := testNode.L2Client.SendTransaction(ctx, tx) if err == nil { Fatal(t, "No error when nonce was too high") } @@ -91,16 +91,16 @@ func TestSequencerNonceTooHighQueueFull(t *testing.T) { config := arbnode.ConfigDefaultL2Test() config.Sequencer.NonceFailureCacheSize = 5 config.Sequencer.NonceFailureCacheExpiry = time.Minute - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(config).CreateTestNodeOnL2Only(t, false) + defer testNode.L2Node.StopAndWait() count := 15 var completed uint64 for i := 0; i < count; i++ { - l2info.GetInfoWithPrivKey("Owner").Nonce++ - tx := l2info.PrepareTx("Owner", "Owner", l2info.TransferGas, common.Big0, nil) + testNode.L2Info.GetInfoWithPrivKey("Owner").Nonce++ + tx := testNode.L2Info.PrepareTx("Owner", "Owner", testNode.L2Info.TransferGas, common.Big0, nil) go func() { - err := client.SendTransaction(ctx, tx) + err := testNode.L2Client.SendTransaction(ctx, tx) if err == nil { Fatal(t, "No error when nonce was too high") } diff --git a/system_tests/seq_pause_test.go b/system_tests/seq_pause_test.go index fd057c018..8b919d73c 100644 --- a/system_tests/seq_pause_test.go +++ b/system_tests/seq_pause_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/ethereum/go-ethereum/core/types" + "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbnode/execution" ) @@ -16,12 +17,12 @@ func TestSequencerPause(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info1, nodeA, client := CreateTestL2(t, ctx) - defer nodeA.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() const numUsers = 100 - prechecker, ok := nodeA.Execution.TxPublisher.(*execution.TxPreChecker) + prechecker, ok := testNode.L2Node.Execution.TxPublisher.(*execution.TxPreChecker) if !ok { t.Error("prechecker not found on node") } @@ -34,15 +35,15 @@ func TestSequencerPause(t *testing.T) { for num := 0; num < numUsers; num++ { userName := fmt.Sprintf("My_User_%d", num) - l2info1.GenerateAccount(userName) + testNode.L2Info.GenerateAccount(userName) users = append(users, userName) } for _, userName := range users { - tx := l2info1.PrepareTx("Owner", userName, l2info1.TransferGas, big.NewInt(1e16), nil) - err := client.SendTransaction(ctx, tx) + tx := testNode.L2Info.PrepareTx("Owner", userName, testNode.L2Info.TransferGas, big.NewInt(1e16), nil) + err := testNode.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) } @@ -51,7 +52,7 @@ func TestSequencerPause(t *testing.T) { var txs types.Transactions for _, userName := range users { - tx := l2info1.PrepareTx(userName, "Owner", l2info1.TransferGas, big.NewInt(2), nil) + tx := testNode.L2Info.PrepareTx(userName, "Owner", testNode.L2Info.TransferGas, big.NewInt(2), nil) txs = append(txs, tx) } @@ -62,7 +63,7 @@ func TestSequencerPause(t *testing.T) { }(tx) } - _, err := EnsureTxSucceededWithTimeout(ctx, client, txs[0], time.Second) + _, err := EnsureTxSucceededWithTimeout(ctx, testNode.L2Client, txs[0], time.Second) if err == nil { t.Error("tx passed while sequencer paused") } @@ -70,7 +71,7 @@ func TestSequencerPause(t *testing.T) { sequencer.Activate() for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, client, tx) + _, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) } } diff --git a/system_tests/seq_reject_test.go b/system_tests/seq_reject_test.go index 19c06c4bc..811f5669d 100644 --- a/system_tests/seq_reject_test.go +++ b/system_tests/seq_reject_test.go @@ -31,18 +31,18 @@ func TestSequencerRejection(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() feedErrChan := make(chan error, 10) - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true) - defer nodeA.StopAndWait() + testNode1 := NewNodeBuilder(ctx).SetNodeConfig(seqNodeConfig).CreateTestNodeOnL2Only(t, true) + defer testNode1.L2Node.StopAndWait() clientNodeConfig := arbnode.ConfigDefaultL2Test() - port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + port := testNode1.L2Node.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false) - defer nodeB.StopAndWait() + testNode2 := NewNodeBuilder(ctx).SetNodeConfig(clientNodeConfig).CreateTestNodeOnL2Only(t, false) + defer testNode2.L2Node.StopAndWait() - auth := l2info1.GetDefaultTransactOpts("Owner", ctx) - simpleAddr, _ := deploySimple(t, ctx, auth, client1) + auth := testNode1.L2Info.GetDefaultTransactOpts("Owner", ctx) + simpleAddr, _ := testNode1.DeploySimple(t, auth) simpleAbi, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) noopId := simpleAbi.Methods["noop"].ID @@ -51,7 +51,7 @@ func TestSequencerRejection(t *testing.T) { // Generate the accounts before hand to avoid races for user := 0; user < 9; user++ { name := fmt.Sprintf("User%v", user) - l2info1.GenerateAccount(name) + testNode1.L2Info.GenerateAccount(name) } wg := sync.WaitGroup{} @@ -59,24 +59,24 @@ func TestSequencerRejection(t *testing.T) { for user := 0; user < 9; user++ { user := user name := fmt.Sprintf("User%v", user) - tx := l2info1.PrepareTx("Owner", name, l2info1.TransferGas, big.NewInt(params.Ether), nil) + tx := testNode1.L2Info.PrepareTx("Owner", name, testNode1.L2Info.TransferGas, big.NewInt(params.Ether), nil) - err := client1.SendTransaction(ctx, tx) + err := testNode1.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client1, tx) + _, err = EnsureTxSucceeded(ctx, testNode1.L2Client, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client2, tx) + _, err = EnsureTxSucceeded(ctx, testNode2.L2Client, tx) Require(t, err) wg.Add(1) go func() { defer wg.Done() - info := l2info1.GetInfoWithPrivKey(name) + info := testNode1.L2Info.GetInfoWithPrivKey(name) txData := &types.DynamicFeeTx{ To: &simpleAddr, - Gas: l2info1.TransferGas + 10000, - GasFeeCap: arbmath.BigMulByUint(l2info1.GasPrice, 100), + Gas: testNode1.L2Info.TransferGas + 10000, + GasFeeCap: arbmath.BigMulByUint(testNode1.L2Info.GasPrice, 100), Value: common.Big0, } for atomic.LoadInt32(&stopBackground) == 0 { @@ -92,8 +92,8 @@ func TestSequencerRejection(t *testing.T) { txData.Nonce = 1 << 32 expectedErr = "nonce too high" } - tx = l2info1.SignTxAs(name, txData) - err = client1.SendTransaction(ctx, tx) + tx = testNode1.L2Info.SignTxAs(name, txData) + err = testNode1.L2Client.SendTransaction(ctx, tx) if err != nil && (expectedErr == "" || !strings.Contains(err.Error(), expectedErr)) { Require(t, err, "failed to send tx for user", user) } @@ -102,7 +102,7 @@ func TestSequencerRejection(t *testing.T) { } for i := 100; i >= 0; i-- { - block, err := client1.BlockNumber(ctx) + block, err := testNode1.L2Client.BlockNumber(ctx) Require(t, err) if block >= 200 { break @@ -120,11 +120,11 @@ func TestSequencerRejection(t *testing.T) { atomic.StoreInt32(&stopBackground, 1) wg.Wait() - header1, err := client1.HeaderByNumber(ctx, nil) + header1, err := testNode1.L2Client.HeaderByNumber(ctx, nil) Require(t, err) for i := 100; i >= 0; i-- { - header2, err := client2.HeaderByNumber(ctx, header1.Number) + header2, err := testNode2.L2Client.HeaderByNumber(ctx, header1.Number) if err != nil { select { case err := <-feedErrChan: @@ -132,8 +132,8 @@ func TestSequencerRejection(t *testing.T) { case <-time.After(time.Millisecond * 100): } if i == 0 { - client2Block, _ := client2.BlockNumber(ctx) - Fatal(t, "client2 failed to reach client1 block ", header1.Number, ", only reached block", client2Block) + client2Block, _ := testNode2.L2Client.BlockNumber(ctx) + Fatal(t, "Client2 failed to reach client1 block ", header1.Number, ", only reached block", client2Block) } continue } diff --git a/system_tests/seq_whitelist_test.go b/system_tests/seq_whitelist_test.go index 2d671dcdd..351b031ca 100644 --- a/system_tests/seq_whitelist_test.go +++ b/system_tests/seq_whitelist_test.go @@ -18,22 +18,22 @@ func TestSequencerWhitelist(t *testing.T) { config := arbnode.ConfigDefaultL2Test() config.Sequencer.SenderWhitelist = GetTestAddressForAccountName(t, "Owner").String() + "," + GetTestAddressForAccountName(t, "User").String() - l2info, l2node, client := CreateTestL2WithConfig(t, ctx, nil, config, true) - defer l2node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(config).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() - l2info.GenerateAccount("User") - l2info.GenerateAccount("User2") + testNode.L2Info.GenerateAccount("User") + testNode.L2Info.GenerateAccount("User2") // Owner is on the whitelist - TransferBalance(t, "Owner", "User", big.NewInt(params.Ether), l2info, client, ctx) - TransferBalance(t, "Owner", "User2", big.NewInt(params.Ether), l2info, client, ctx) + TransferBalance(t, "Owner", "User", big.NewInt(params.Ether), testNode.L2Info, testNode.L2Client, ctx) + TransferBalance(t, "Owner", "User2", big.NewInt(params.Ether), testNode.L2Info, testNode.L2Client, ctx) // User is on the whitelist - TransferBalance(t, "User", "User2", big.NewInt(params.Ether/10), l2info, client, ctx) + TransferBalance(t, "User", "User2", big.NewInt(params.Ether/10), testNode.L2Info, testNode.L2Client, ctx) // User2 is *not* on the whitelist, therefore this should fail - tx := l2info.PrepareTx("User2", "User", l2info.TransferGas, big.NewInt(params.Ether/10), nil) - err := client.SendTransaction(ctx, tx) + tx := testNode.L2Info.PrepareTx("User2", "User", testNode.L2Info.TransferGas, big.NewInt(params.Ether/10), nil) + err := testNode.L2Client.SendTransaction(ctx, tx) if err == nil { Fatal(t, "transaction from user not on whitelist accepted") } diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index 23c0e44c0..0243c55e5 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -44,28 +44,28 @@ func TestSequencerFeed(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true) - defer nodeA.StopAndWait() + testNode1 := NewNodeBuilder(ctx).SetNodeConfig(seqNodeConfig).CreateTestNodeOnL2Only(t, true) + defer testNode1.L2Node.StopAndWait() clientNodeConfig := arbnode.ConfigDefaultL2Test() - port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + port := testNode1.L2Node.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false) - defer nodeB.StopAndWait() + testNode2 := NewNodeBuilder(ctx).SetNodeConfig(clientNodeConfig).CreateTestNodeOnL2Only(t, false) + defer testNode2.L2Node.StopAndWait() - l2info1.GenerateAccount("User2") + testNode1.L2Info.GenerateAccount("User2") - tx := l2info1.PrepareTx("Owner", "User2", l2info1.TransferGas, big.NewInt(1e12), nil) + tx := testNode1.L2Info.PrepareTx("Owner", "User2", testNode1.L2Info.TransferGas, big.NewInt(1e12), nil) - err := client1.SendTransaction(ctx, tx) + err := testNode1.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client1, tx) + _, err = EnsureTxSucceeded(ctx, testNode1.L2Client, tx) Require(t, err) - _, err = WaitForTx(ctx, client2, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, testNode2.L2Client, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := client2.BalanceAt(ctx, l2info1.GetAddress("User2"), nil) + l2balance, err := testNode2.L2Client.BalanceAt(ctx, testNode1.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) @@ -79,14 +79,14 @@ func TestRelayedSequencerFeed(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true) - defer nodeA.StopAndWait() + testNode1 := NewNodeBuilder(ctx).SetNodeConfig(seqNodeConfig).CreateTestNodeOnL2Only(t, true) + defer testNode1.L2Node.StopAndWait() - bigChainId, err := client1.ChainID(ctx) + bigChainId, err := testNode1.L2Client.ChainID(ctx) Require(t, err) config := relay.ConfigDefault - port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + port := testNode1.L2Node.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port config.Node.Feed.Input = *newBroadcastClientConfigTest(port) config.Node.Feed.Output = *newBroadcasterConfigTest() config.Chain.ID = bigChainId.Uint64() @@ -101,23 +101,23 @@ func TestRelayedSequencerFeed(t *testing.T) { clientNodeConfig := arbnode.ConfigDefaultL2Test() port = currentRelay.GetListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeC, client3 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false) - defer nodeC.StopAndWait() - StartWatchChanErr(t, ctx, feedErrChan, nodeC) + testNode3 := NewNodeBuilder(ctx).SetNodeConfig(clientNodeConfig).CreateTestNodeOnL2Only(t, false) + defer testNode3.L2Node.StopAndWait() + StartWatchChanErr(t, ctx, feedErrChan, testNode3.L2Node) - l2info1.GenerateAccount("User2") + testNode1.L2Info.GenerateAccount("User2") - tx := l2info1.PrepareTx("Owner", "User2", l2info1.TransferGas, big.NewInt(1e12), nil) + tx := testNode1.L2Info.PrepareTx("Owner", "User2", testNode1.L2Info.TransferGas, big.NewInt(1e12), nil) - err = client1.SendTransaction(ctx, tx) + err = testNode1.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client1, tx) + _, err = EnsureTxSucceeded(ctx, testNode1.L2Client, tx) Require(t, err) - _, err = WaitForTx(ctx, client3, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, testNode3.L2Client, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := client3.BalanceAt(ctx, l2info1.GetAddress("User2"), nil) + l2balance, err := testNode3.L2Client.BalanceAt(ctx, testNode1.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) diff --git a/system_tests/transfer_test.go b/system_tests/transfer_test.go index 2e3317907..1c7e7cae1 100644 --- a/system_tests/transfer_test.go +++ b/system_tests/transfer_test.go @@ -8,28 +8,30 @@ import ( "fmt" "math/big" "testing" + + "github.com/offchainlabs/nitro/arbnode" ) func TestTransfer(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, client := CreateTestL2(t, ctx) - defer l2node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) + defer testNode.L2Node.StopAndWait() - l2info.GenerateAccount("User2") + testNode.L2Info.GenerateAccount("User2") - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) + tx := testNode.L2Info.PrepareTx("Owner", "User2", testNode.L2Info.TransferGas, big.NewInt(1e12), nil) - err := client.SendTransaction(ctx, tx) + err := testNode.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) - bal, err := client.BalanceAt(ctx, l2info.GetAddress("Owner"), nil) + bal, err := testNode.L2Client.BalanceAt(ctx, testNode.L2Info.GetAddress("Owner"), nil) Require(t, err) fmt.Println("Owner balance is: ", bal) - bal2, err := client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + bal2, err := testNode.L2Client.BalanceAt(ctx, testNode.L2Info.GetAddress("User2"), nil) Require(t, err) if bal2.Cmp(big.NewInt(1e12)) != 0 { Fatal(t, "Unexpected recipient balance: ", bal2) From 91ff77fef2523cc6344b321d3b96eec76636e5fa Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 26 Sep 2023 16:46:01 -0500 Subject: [PATCH 173/775] update contracts pin --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index bb2ca5313..225b504e6 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit bb2ca53132116a59386b5f5010e711f485162c13 +Subproject commit 225b504e6d801b15dcba93099339e6e74897714e From 3bf7dd0eff91742a65e877890cb00c4dc4fd41d3 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 26 Sep 2023 22:15:14 +0000 Subject: [PATCH 174/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 1a58f1b34..89f53b035 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 1a58f1b34e24ecf1679a21edff0a199305aa82f8 +Subproject commit 89f53b035d7a8b9b1ff8599958bf0c55efcdf718 From 6a9e0c2aa010e16a2c7294edb1cde7df7751d870 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 26 Sep 2023 17:20:37 -0600 Subject: [PATCH 175/775] fix merge errors --- arbnode/node.go | 4 ++-- cmd/nitro/config_test.go | 14 +++++------ cmd/nitro/nitro.go | 10 ++++---- execution/gethexec/node.go | 33 ++++++++++++++------------ system_tests/debugapi_test.go | 2 +- system_tests/recreatestate_rpc_test.go | 15 +++++++----- system_tests/retryable_test.go | 3 ++- system_tests/staker_test.go | 6 +++-- 8 files changed, 48 insertions(+), 39 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index a339f56b0..25bc7bafc 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -414,7 +414,7 @@ func ConfigDefaultL2Test() *Config { type DangerousConfig struct { NoL1Listener bool `koanf:"no-l1-listener"` - NoCoordinator bool `koanf:"no-seq-coordinator"` + NoCoordinator bool `koanf:"no-coordinator"` } var DefaultDangerousConfig = DangerousConfig{ @@ -424,7 +424,7 @@ var DefaultDangerousConfig = DangerousConfig{ func DangerousConfigAddOptions(prefix string, f *flag.FlagSet) { f.Bool(prefix+".no-l1-listener", DefaultDangerousConfig.NoL1Listener, "DANGEROUS! disables listening to L1. To be used in test nodes only") - f.Bool(prefix+".no-seq-coordinator", DefaultDangerousConfig.NoCoordinator, "DANGEROUS! allows sequencing without sequencer-coordinator") + f.Bool(prefix+".no-coordinator", DefaultDangerousConfig.NoCoordinator, "DANGEROUS! allows sequencing without sequencer-coordinator") } type Node struct { diff --git a/cmd/nitro/config_test.go b/cmd/nitro/config_test.go index 5e3f6a8ef..417b25611 100644 --- a/cmd/nitro/config_test.go +++ b/cmd/nitro/config_test.go @@ -69,7 +69,7 @@ func TestReloads(t *testing.T) { config := NodeConfigDefault update := NodeConfigDefault - update.Node.BatchPoster.BatchPollDelay++ + update.Node.BatchPoster.MaxSize++ check(reflect.ValueOf(config), false, "config") Require(t, config.CanReload(&config)) @@ -114,8 +114,8 @@ func TestLiveNodeConfig(t *testing.T) { // check updating the config update := config.ShallowClone() expected := config.ShallowClone() - update.Node.BatchPoster.BatchPollDelay += 2 * time.Millisecond - expected.Node.BatchPoster.BatchPollDelay += 2 * time.Millisecond + update.Node.BatchPoster.MaxSize += 100 + expected.Node.BatchPoster.MaxSize += 100 Require(t, liveConfig.Set(update)) if !reflect.DeepEqual(liveConfig.Get(), expected) { Fail(t, "failed to set config") @@ -150,19 +150,19 @@ func TestLiveNodeConfig(t *testing.T) { // change the config file expected = config.ShallowClone() - expected.Node.BatchPoster.BatchPollDelay += time.Millisecond - jsonConfig = fmt.Sprintf("{\"node\":{\"batch-poster\":{\"poll-delay\":\"%s\"}}, \"chain\":{\"id\":421613}}", expected.Node.BatchPoster.BatchPollDelay.String()) + expected.Node.BatchPoster.MaxSize += 100 + jsonConfig = fmt.Sprintf("{\"node\":{\"batch-poster\":{\"max-size\":\"%d\"}}, \"chain\":{\"id\":421613}}", expected.Node.BatchPoster.MaxSize) Require(t, WriteToConfigFile(configFile, jsonConfig)) // trigger LiveConfig reload Require(t, syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)) if !PollLiveConfigUntilEqual(liveConfig, expected) { - Fail(t, "failed to update config", config.Node.BatchPoster.BatchPollDelay, update.Node.BatchPoster.BatchPollDelay) + Fail(t, "failed to update config", config.Node.BatchPoster.MaxSize, update.Node.BatchPoster.MaxSize) } // change chain.id in the config file (currently non-reloadable) - jsonConfig = fmt.Sprintf("{\"node\":{\"batch-poster\":{\"poll-delay\":\"%s\"}}, \"chain\":{\"id\":421703}}", expected.Node.BatchPoster.BatchPollDelay.String()) + jsonConfig = fmt.Sprintf("{\"node\":{\"batch-poster\":{\"max-size\":\"%d\"}}, \"chain\":{\"id\":421703}}", expected.Node.BatchPoster.MaxSize) Require(t, WriteToConfigFile(configFile, jsonConfig)) // trigger LiveConfig reload diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 03c559ca2..c0abe6d60 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -313,11 +313,11 @@ func mainImpl() int { } } - if nodeConfig.Node.RPC.MaxRecreateStateDepth == arbitrum.UninitializedMaxRecreateStateDepth { - if nodeConfig.Node.Archive { - nodeConfig.Node.RPC.MaxRecreateStateDepth = arbitrum.DefaultArchiveNodeMaxRecreateStateDepth + if nodeConfig.Execution.RPC.MaxRecreateStateDepth == arbitrum.UninitializedMaxRecreateStateDepth { + if nodeConfig.Execution.Archive { + nodeConfig.Execution.RPC.MaxRecreateStateDepth = arbitrum.DefaultArchiveNodeMaxRecreateStateDepth } else { - nodeConfig.Node.RPC.MaxRecreateStateDepth = arbitrum.DefaultNonArchiveNodeMaxRecreateStateDepth + nodeConfig.Execution.RPC.MaxRecreateStateDepth = arbitrum.DefaultNonArchiveNodeMaxRecreateStateDepth } } liveNodeConfig := genericconf.NewLiveConfig[*NodeConfig](args, nodeConfig, func(ctx context.Context, args []string) (*NodeConfig, error) { @@ -818,7 +818,7 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c chainDefaults["init.empty"] = true } if parentChainIsArbitrum { - l2MaxTxSize := execution.DefaultSequencerConfig.MaxTxDataSize + l2MaxTxSize := gethexec.DefaultSequencerConfig.MaxTxDataSize bufferSpace := 5000 if l2MaxTxSize < bufferSpace*2 { return false, fmt.Errorf("not enough room in parent chain max tx size %v for bufferSpace %v * 2", l2MaxTxSize, bufferSpace) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 36a35d2c1..5176eb28d 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/ethdb" @@ -18,6 +19,7 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/execution" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/headerreader" flag "github.com/spf13/pflag" ) @@ -35,9 +37,9 @@ func DangerousConfigAddOptions(prefix string, f *flag.FlagSet) { } type Config struct { - ParentChainReader headerreader.Config `koanf:"l1-reader" reload:"hot"` + ParentChainReader headerreader.Config `koanf:"parent-chain-reader" reload:"hot"` Sequencer SequencerConfig `koanf:"sequencer" reload:"hot"` - RecordingDB arbitrum.RecordingDatabaseConfig `koanf:"recording-database"` + RecordingDatabase arbitrum.RecordingDatabaseConfig `koanf:"recording-database"` TxPreChecker TxPreCheckerConfig `koanf:"tx-pre-checker" reload:"hot"` Forwarder ForwarderConfig `koanf:"forwarder"` ForwardingTarget string `koanf:"forwarding-target"` @@ -70,7 +72,7 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { arbitrum.ConfigAddOptions(prefix+".rpc", f) SequencerConfigAddOptions(prefix+".sequencer", f) arbitrum.RecordingDatabaseConfigAddOptions(prefix+".recording-database", f) - f.String(prefix+".forwarding-target", ConfigDefault.ForwardingTargetImpl, "transaction forwarding target URL, or \"null\" to disable forwarding (iff not sequencer)") + f.String(prefix+".forwarding-target", ConfigDefault.ForwardingTarget, "transaction forwarding target URL, or \"null\" to disable forwarding (iff not sequencer)") AddOptionsForNodeForwarderConfig(prefix+".forwarder", f) TxPreCheckerConfigAddOptions(prefix+".tx-pre-checker", f) CachingConfigAddOptions(prefix+".caching", f) @@ -81,15 +83,15 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { } var ConfigDefault = Config{ - RPC: arbitrum.DefaultConfig, - Sequencer: DefaultSequencerConfig, - RecordingDB: arbitrum.DefaultRecordingDatabaseConfig, - ForwardingTarget: "", - TxPreChecker: DefaultTxPreCheckerConfig, - Archive: false, - TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second - Caching: DefaultCachingConfig, - Dangerous: DefaultDangerousConfig, + RPC: arbitrum.DefaultConfig, + Sequencer: DefaultSequencerConfig, + RecordingDatabase: arbitrum.DefaultRecordingDatabaseConfig, + ForwardingTarget: "", + TxPreChecker: DefaultTxPreCheckerConfig, + Archive: false, + TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second + Caching: DefaultCachingConfig, + Dangerous: DefaultDangerousConfig, } func ConfigDefaultNonSequencerTest() *Config { @@ -135,19 +137,20 @@ func CreateExecutionNode( if err != nil { return nil, err } - recorder := NewBlockRecorder(&config.RecordingDB, execEngine, chainDB) + recorder := NewBlockRecorder(&config.RecordingDatabase, execEngine, chainDB) var txPublisher TransactionPublisher var sequencer *Sequencer var parentChainReader *headerreader.HeaderReader if l1client != nil { - parentChainReader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher().ParentChainReader }) + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) + parentChainReader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher().ParentChainReader }, arbSys) if err != nil { return nil, err } } - fwTarget := config.ForwardingTarget() + fwTarget := config.ForwardingTargetF() if config.Sequencer.Enable { if fwTarget != "" { return nil, errors.New("sequencer and forwarding target both set") diff --git a/system_tests/debugapi_test.go b/system_tests/debugapi_test.go index ff28e2350..17398de26 100644 --- a/system_tests/debugapi_test.go +++ b/system_tests/debugapi_test.go @@ -14,7 +14,7 @@ import ( func TestDebugAPI(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, nil, nil, nil) + _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, nil, nil, nil, nil) defer requireClose(t, l1stack) defer requireClose(t, l2stack) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index 561085c3f..f4ccc5ca9 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -18,6 +18,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util" "github.com/offchainlabs/nitro/util/testhelpers" ) @@ -25,9 +26,10 @@ import ( func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, txCount uint64) (node *arbnode.Node, bc *core.BlockChain, db ethdb.Database, l2client *ethclient.Client, l2info info, cancel func()) { t.Helper() nodeConfig := arbnode.ConfigDefaultL1Test() - nodeConfig.RPC.MaxRecreateStateDepth = maxRecreateStateDepth - nodeConfig.Sequencer.MaxBlockSpeed = 0 - nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 + execConfig := gethexec.ConfigDefaultTest() + execConfig.RPC.MaxRecreateStateDepth = maxRecreateStateDepth + execConfig.Sequencer.MaxBlockSpeed = 0 + execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 cacheConfig := &core.CacheConfig{ // Arbitrum Config Options TriesInMemory: 128, @@ -43,7 +45,7 @@ func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateD SnapshotLimit: 256, SnapshotWait: true, } - l2info, node, l2client, _, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, cacheConfig, nil) + l2info, node, l2client, _, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, execConfig, nil, nil, cacheConfig, nil) cancel = func() { defer requireClose(t, l1stack) defer node.StopAndWait() @@ -60,8 +62,9 @@ func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateD _, err := EnsureTxSucceeded(ctx, l2client, tx) testhelpers.RequireImpl(t, err) } - bc = node.Execution.Backend.ArbInterface().BlockChain() - db = node.Execution.Backend.ChainDb() + exec := getExecNode(t, node) + bc = exec.Backend.ArbInterface().BlockChain() + db = exec.Backend.ChainDb() return } diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index b1dd32d1d..0fc6d24ed 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -21,6 +21,7 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbos/retryables" "github.com/offchainlabs/nitro/arbos/util" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/solgen/go/bridgegen" @@ -802,7 +803,7 @@ func elevateL2Basefee(t *testing.T, ctx context.Context, l2client *ethclient.Cli _, err = precompilesgen.NewArbosTest(common.HexToAddress("0x69"), l2client) Require(t, err, "failed to deploy ArbosTest") - burnAmount := arbnode.ConfigDefaultL1Test().RPC.RPCGasCap + burnAmount := gethexec.ConfigDefaultTest().RPC.RPCGasCap burnTarget := uint64(5 * l2pricing.InitialSpeedLimitPerSecondV6 * l2pricing.InitialBacklogTolerance) for i := uint64(0); i < (burnTarget+burnAmount)/burnAmount; i++ { burnArbGas := arbostestabi.Methods["burnArbGas"] diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index bf393a47b..326b6939c 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -74,10 +74,12 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) l2info.GenerateGenesisAccount("FaultyAddr", common.Big1) } config := arbnode.ConfigDefaultL1Test() - config.Sequencer.Enable = false + execConfig := gethexec.ConfigDefaultTest() + execConfig.Sequencer.Enable = false + config.Sequencer = false config.DelayedSequencer.Enable = false config.BatchPoster.Enable = false - _, l2nodeB := Create2ndNodeWithConfig(t, ctx, l2nodeA, l1stack, l1info, &l2info.ArbInitData, config, gethexec.ConfigDefaultTest(), nil) + _, l2nodeB := Create2ndNodeWithConfig(t, ctx, l2nodeA, l1stack, l1info, &l2info.ArbInitData, config, execConfig, nil) defer l2nodeB.StopAndWait() execNodeB := getExecNode(t, l2nodeB) From 53c1c33fa24ddc0ae569c10f88f60c9784e6042a Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Tue, 26 Sep 2023 20:34:19 -0700 Subject: [PATCH 176/775] mem-limit: count active pages as maybe freeable --- .../resourcemanager/resource_management.go | 41 ++++++++++++++----- .../resource_management_test.go | 30 +++++++++----- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/arbnode/resourcemanager/resource_management.go b/arbnode/resourcemanager/resource_management.go index 4a63d428f..24702349b 100644 --- a/arbnode/resourcemanager/resource_management.go +++ b/arbnode/resourcemanager/resource_management.go @@ -97,7 +97,7 @@ var DefaultConfig = Config{ // ConfigAddOptions adds the configuration options for resourcemanager. func ConfigAddOptions(prefix string, f *pflag.FlagSet) { - f.String(prefix+".mem-free-limit", DefaultConfig.MemFreeLimit, "RPC calls are throttled if free system memory is below this amount, expressed in bytes or multiples of bytes with suffix B, K, M, G") + f.String(prefix+".mem-free-limit", DefaultConfig.MemFreeLimit, "RPC calls are throttled if free system memory excluding the page cache is below this amount, expressed in bytes or multiples of bytes with suffix B, K, M, G. The limit should be set such that sufficient free memory is left for the page cache in order for the system to be performant") } // httpServer implements http.Handler and wraps calls to inner with a resource @@ -168,7 +168,7 @@ func (_ trivialLimitChecker) String() string { return "trivial" } type cgroupsMemoryFiles struct { limitFile, usageFile, statsFile string - inactiveRe *regexp.Regexp + activeRe, inactiveRe *regexp.Regexp } const defaultCgroupsV1MemoryDirectory = "/sys/fs/cgroup/memory/" @@ -178,13 +178,15 @@ var cgroupsV1MemoryFiles = cgroupsMemoryFiles{ limitFile: defaultCgroupsV1MemoryDirectory + "/memory.limit_in_bytes", usageFile: defaultCgroupsV1MemoryDirectory + "/memory.usage_in_bytes", statsFile: defaultCgroupsV1MemoryDirectory + "/memory.stat", - inactiveRe: regexp.MustCompile(`total_inactive_file (\d+)`), + activeRe: regexp.MustCompile(`^total_active_file (\d+)`), + inactiveRe: regexp.MustCompile(`^total_inactive_file (\d+)`), } var cgroupsV2MemoryFiles = cgroupsMemoryFiles{ limitFile: defaultCgroupsV2MemoryDirectory + "/memory.max", usageFile: defaultCgroupsV2MemoryDirectory + "/memory.current", statsFile: defaultCgroupsV2MemoryDirectory + "/memory.stat", - inactiveRe: regexp.MustCompile(`inactive_file (\d+)`), + activeRe: regexp.MustCompile(`^active_file (\d+)`), + inactiveRe: regexp.MustCompile(`^inactive_file (\d+)`), } type cgroupsMemoryLimitChecker struct { @@ -200,12 +202,28 @@ func newCgroupsMemoryLimitChecker(files cgroupsMemoryFiles, memLimitBytes int) * } // isLimitExceeded checks if the system memory free is less than the limit. +// It returns true if the limit is exceeded. // -// See the following page for details of calculating the memory used, -// which is reported as container_memory_working_set_bytes in prometheus: +// container_memory_working_set_bytes in prometheus is calculated as +// memory.usage_in_bytes - inactive page cache bytes, see // https://mihai-albert.com/2022/02/13/out-of-memory-oom-in-kubernetes-part-3-memory-metrics-sources-and-tools-to-collect-them/ +// This metric is used by kubernetes to report memory in use by the pod, +// but memory.usage_in_bytes also includes the active page cache, which +// can be evicted by the kernel when more memory is needed, see +// https://github.com/kubernetes/kubernetes/issues/43916 +// The kernel cannot be guaranteed to move a page from a file from +// active to inactive even when the file is closed, or Nitro is exited. +// For larger chains, Nitro's page cache can grow quite large due to +// the large amount of state that is randomly accessed from disk as each +// block is added. So in checking the limit we also include the active +// page cache. +// +// The limit should be set such that the system has a reasonable amount of +// free memory for the page cache, to avoid cache thrashing on chain state +// access. How much "reasonable" is will depend on access patterns, state +// size, and your application's tolerance for latency. func (c *cgroupsMemoryLimitChecker) isLimitExceeded() (bool, error) { - var limit, usage, inactive int + var limit, usage, active, inactive int var err error if limit, err = readIntFromFile(c.files.limitFile); err != nil { return false, err @@ -213,10 +231,13 @@ func (c *cgroupsMemoryLimitChecker) isLimitExceeded() (bool, error) { if usage, err = readIntFromFile(c.files.usageFile); err != nil { return false, err } - if inactive, err = readInactive(c.files.statsFile, c.files.inactiveRe); err != nil { + if active, err = readFromMemStats(c.files.statsFile, c.files.activeRe); err != nil { + return false, err + } + if inactive, err = readFromMemStats(c.files.statsFile, c.files.inactiveRe); err != nil { return false, err } - return limit-(usage-inactive) <= c.memLimitBytes, nil + return limit-(usage-(active+inactive)) <= c.memLimitBytes, nil } func (c cgroupsMemoryLimitChecker) String() string { @@ -236,7 +257,7 @@ func readIntFromFile(fileName string) (int, error) { return limit, nil } -func readInactive(fileName string, re *regexp.Regexp) (int, error) { +func readFromMemStats(fileName string, re *regexp.Regexp) (int, error) { file, err := os.Open(fileName) if err != nil { return 0, err diff --git a/arbnode/resourcemanager/resource_management_test.go b/arbnode/resourcemanager/resource_management_test.go index e9aa2ab7e..4f52ad017 100644 --- a/arbnode/resourcemanager/resource_management_test.go +++ b/arbnode/resourcemanager/resource_management_test.go @@ -10,7 +10,7 @@ import ( "testing" ) -func updateFakeCgroupFiles(c *cgroupsMemoryLimitChecker, limit, usage, inactive int) error { +func updateFakeCgroupFiles(c *cgroupsMemoryLimitChecker, limit, usage, inactive, active int) error { limitFile, err := os.Create(c.files.limitFile) if err != nil { return err @@ -34,8 +34,8 @@ func updateFakeCgroupFiles(c *cgroupsMemoryLimitChecker, limit, usage, inactive _, err = fmt.Fprintf(statsFile, `total_cache 1029980160 total_rss 1016209408 total_inactive_file %d -total_active_file 321544192 -`, inactive) +total_active_file %d +`, inactive, active) return err } @@ -44,7 +44,8 @@ func makeCgroupsTestDir(cgroupDir string) cgroupsMemoryFiles { limitFile: cgroupDir + "/memory.limit_in_bytes", usageFile: cgroupDir + "/memory.usage_in_bytes", statsFile: cgroupDir + "/memory.stat", - inactiveRe: regexp.MustCompile(`total_inactive_file (\d+)`), + activeRe: regexp.MustCompile(`^total_active_file (\d+)`), + inactiveRe: regexp.MustCompile(`^total_inactive_file (\d+)`), } } @@ -61,6 +62,7 @@ func TestCgroupsMemoryLimit(t *testing.T) { desc string sysLimit int inactive int + active int usage int memLimit string want bool @@ -69,48 +71,54 @@ func TestCgroupsMemoryLimit(t *testing.T) { desc: "limit should be exceeded", sysLimit: 1000, inactive: 50, + active: 25, usage: 1000, - memLimit: "50B", + memLimit: "75B", want: true, }, { desc: "limit should not be exceeded", sysLimit: 1000, inactive: 51, + active: 25, usage: 1000, - memLimit: "50b", + memLimit: "75b", want: false, }, { desc: "limit (MB) should be exceeded", sysLimit: 1000 * 1024 * 1024, inactive: 50 * 1024 * 1024, + active: 25 * 1024 * 1024, usage: 1000 * 1024 * 1024, - memLimit: "50MB", + memLimit: "75MB", want: true, }, { desc: "limit (MB) should not be exceeded", sysLimit: 1000 * 1024 * 1024, inactive: 1 + 50*1024*1024, + active: 25 * 1024 * 1024, usage: 1000 * 1024 * 1024, - memLimit: "50m", + memLimit: "75m", want: false, }, { desc: "limit (GB) should be exceeded", sysLimit: 1000 * 1024 * 1024 * 1024, inactive: 50 * 1024 * 1024 * 1024, + active: 25 * 1024 * 1024 * 1024, usage: 1000 * 1024 * 1024 * 1024, - memLimit: "50G", + memLimit: "75G", want: true, }, { desc: "limit (GB) should not be exceeded", sysLimit: 1000 * 1024 * 1024 * 1024, inactive: 1 + 50*1024*1024*1024, + active: 25 * 1024 * 1024 * 1024, usage: 1000 * 1024 * 1024 * 1024, - memLimit: "50gb", + memLimit: "75gb", want: false, }, } { @@ -121,7 +129,7 @@ func TestCgroupsMemoryLimit(t *testing.T) { t.Fatalf("Parsing memory limit failed: %v", err) } c := newCgroupsMemoryLimitChecker(testFiles, memLimit) - if err := updateFakeCgroupFiles(c, tc.sysLimit, tc.usage, tc.inactive); err != nil { + if err := updateFakeCgroupFiles(c, tc.sysLimit, tc.usage, tc.inactive, tc.active); err != nil { t.Fatalf("Updating cgroup files: %v", err) } exceeded, err := c.isLimitExceeded() From 9e3a8dea3a662edc5a07f79cf9b13547c34b0712 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Tue, 26 Sep 2023 20:47:32 -0700 Subject: [PATCH 177/775] Fix nits from PR#1878 --- arbnode/resourcemanager/resource_management.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arbnode/resourcemanager/resource_management.go b/arbnode/resourcemanager/resource_management.go index 24702349b..b8bbb1f3a 100644 --- a/arbnode/resourcemanager/resource_management.go +++ b/arbnode/resourcemanager/resource_management.go @@ -46,7 +46,7 @@ func Init(conf *Config) error { var c limitChecker c, err := newCgroupsMemoryLimitCheckerIfSupported(limit) if errors.Is(err, errNotSupported) { - log.Error("No method for determining memory usage and limits was discovered, disabled memory limit RPC throttling") + log.Error("no method for determining memory usage and limits was discovered, disabled memory limit RPC throttling") c = &trivialLimitChecker{} } @@ -60,8 +60,7 @@ func parseMemLimit(limitStr string) (int, error) { limit int = 1 s string ) - _, err := fmt.Sscanf(limitStr, "%d%s", &limit, &s) - if err != nil { + if _, err := fmt.Sscanf(limitStr, "%d%s", &limit, &s); err != nil { return 0, err } @@ -76,7 +75,7 @@ func parseMemLimit(limitStr string) (int, error) { limit <<= 40 case "B": default: - return 0, fmt.Errorf("Unsupported memory limit suffix string %s", s) + return 0, fmt.Errorf("unsupported memory limit suffix string %s", s) } return limit, nil @@ -118,7 +117,7 @@ func (s *httpServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { exceeded, err := s.c.isLimitExceeded() limitCheckDurationHistogram.Update(time.Since(start).Nanoseconds()) if err != nil { - log.Error("Error checking memory limit", "err", err, "checker", s.c) + log.Error("error checking memory limit", "err", err, "checker", s.c) } else if exceeded { http.Error(w, "Too many requests", http.StatusTooManyRequests) limitCheckFailureCounter.Inc(1) From 0b32e88456124b635e8db44c9708fdb0185159c1 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 26 Sep 2023 21:54:14 -0600 Subject: [PATCH 178/775] Update arb1 and nova feed URLs to new domain --- cmd/chaininfo/arbitrum_chain_info.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/chaininfo/arbitrum_chain_info.json b/cmd/chaininfo/arbitrum_chain_info.json index e66774d42..051ccd03c 100644 --- a/cmd/chaininfo/arbitrum_chain_info.json +++ b/cmd/chaininfo/arbitrum_chain_info.json @@ -4,7 +4,7 @@ "parent-chain-id": 1, "parent-chain-is-arbitrum": false, "sequencer-url": "https://arb1-sequencer.arbitrum.io/rpc", - "feed-url": "wss://arb1.arbitrum.io/feed", + "feed-url": "wss://arb1-feed.arbitrum.io/feed", "has-genesis-state": true, "chain-config": { @@ -54,7 +54,7 @@ "parent-chain-id": 1, "parent-chain-is-arbitrum": false, "sequencer-url": "https://nova.arbitrum.io/rpc", - "feed-url": "wss://nova.arbitrum.io/feed", + "feed-url": "wss://nova-feed.arbitrum.io/feed", "das-index-url": "https://nova.arbitrum.io/das-servers", "chain-config": { From ecdb0a608834cc5ec2f1e20619181fe06892ca57 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 27 Sep 2023 10:43:10 -0500 Subject: [PATCH 179/775] refactor more impl --- system_tests/aliasing_test.go | 6 +- system_tests/arbtrace_test.go | 8 +- system_tests/batch_poster_test.go | 72 ++++++++-------- system_tests/block_hash_test.go | 10 +-- system_tests/block_validator_test.go | 56 ++++++------- system_tests/common_test.go | 106 ++++++++++++------------ system_tests/contract_tx_test.go | 2 +- system_tests/debugapi_test.go | 8 +- system_tests/delayedinbox_test.go | 14 ++-- system_tests/delayedinboxlong_test.go | 26 +++--- system_tests/estimation_test.go | 6 +- system_tests/fees_test.go | 72 ++++++++-------- system_tests/forwarder_test.go | 19 +++-- system_tests/ipc_test.go | 6 +- system_tests/meaningless_reorg_test.go | 34 ++++---- system_tests/nodeinterface_test.go | 14 ++-- system_tests/recreatestate_rpc_test.go | 24 +++--- system_tests/reorg_resequencing_test.go | 8 +- system_tests/retryable_test.go | 32 +++---- system_tests/seq_coordinator_test.go | 20 ++--- system_tests/seq_whitelist_test.go | 6 +- system_tests/seqcompensation_test.go | 22 ++--- system_tests/seqfeed_test.go | 32 +++---- system_tests/seqinbox_test.go | 58 ++++++------- system_tests/staker_test.go | 86 +++++++++---------- system_tests/twonodes_test.go | 24 +++--- system_tests/twonodeslong_test.go | 68 +++++++-------- 27 files changed, 419 insertions(+), 420 deletions(-) diff --git a/system_tests/aliasing_test.go b/system_tests/aliasing_test.go index 852a75720..d7513fe0c 100644 --- a/system_tests/aliasing_test.go +++ b/system_tests/aliasing_test.go @@ -28,7 +28,7 @@ func TestAliasing(t *testing.T) { auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) user := testNode.L1Info.GetDefaultTransactOpts("User", ctx) - TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), testNode.L2Info, testNode.L2Client, ctx) + testNode.TransferBalanceToViaL2(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18)) simpleAddr, simple := testNode.DeploySimple(t, auth) simpleContract, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) @@ -63,7 +63,7 @@ func TestAliasing(t *testing.T) { data, err := simpleContract.Pack("checkCalls", top, direct, static, delegate, callcode, call) Require(t, err) tx = testNode.L2Info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) - SendSignedTxViaL1(t, ctx, testNode.L1Info, testNode.L1Client, testNode.L2Client, tx) + testNode.SendSignedTxViaL1(t, tx) } testUnsigned := func(top, direct, static, delegate, callcode, call bool) { @@ -73,7 +73,7 @@ func TestAliasing(t *testing.T) { data, err := simpleContract.Pack("checkCalls", top, direct, static, delegate, callcode, call) Require(t, err) tx := testNode.L2Info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) - SendUnsignedTxViaL1(t, ctx, testNode.L1Info, testNode.L1Client, testNode.L2Client, tx) + testNode.SendUnsignedTxViaL1(t, tx) } testL2Signed(true, true, false, false, false, false) diff --git a/system_tests/arbtrace_test.go b/system_tests/arbtrace_test.go index 4aab5c71b..50575500d 100644 --- a/system_tests/arbtrace_test.go +++ b/system_tests/arbtrace_test.go @@ -147,11 +147,11 @@ func TestArbTraceForwarding(t *testing.T) { nodeConfig := arbnode.ConfigDefaultL1Test() nodeConfig.RPC.ClassicRedirect = ipcPath nodeConfig.RPC.ClassicRedirectTimeout = time.Second - _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, nil, nil) - defer requireClose(t, l1stack) - defer requireClose(t, l2stack) + testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer requireClose(t, testNode.L2Stack) - l2rpc, _ := l2stack.Attach() + l2rpc, _ := testNode.L2Stack.Attach() txArgs := callTxArgs{} traceTypes := []string{"trace"} blockNum := rpc.BlockNumberOrHash{} diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 11bf92608..0e1b1816c 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -48,41 +48,41 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { conf := arbnode.ConfigDefaultL1Test() conf.BatchPoster.Enable = false conf.BatchPoster.RedisUrl = redisUrl - l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + testNodeA := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNodeA.L1Stack) + defer testNodeA.L2Node.StopAndWait() - l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, nil) + l2clientB, nodeB := Create2ndNode(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nil) defer nodeB.StopAndWait() - l2info.GenerateAccount("User2") + testNodeA.L2Info.GenerateAccount("User2") var txs []*types.Transaction for i := 0; i < 100; i++ { - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, common.Big1, nil) + tx := testNodeA.L2Info.PrepareTx("Owner", "User2", testNodeA.L2Info.TransferGas, common.Big1, nil) txs = append(txs, tx) - err := l2clientA.SendTransaction(ctx, tx) + err := testNodeA.L2Client.SendTransaction(ctx, tx) Require(t, err) } for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, l2clientA, tx) + _, err := EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) Require(t, err) } firstTxData, err := txs[0].MarshalBinary() Require(t, err) - seqTxOpts := l1info.GetDefaultTransactOpts("Sequencer", ctx) + seqTxOpts := testNodeA.L1Info.GetDefaultTransactOpts("Sequencer", ctx) conf.BatchPoster.Enable = true conf.BatchPoster.MaxSize = len(firstTxData) * 2 - startL1Block, err := l1client.BlockNumber(ctx) + startL1Block, err := testNodeA.L1Client.BlockNumber(ctx) Require(t, err) for i := 0; i < parallelBatchPosters; i++ { // Make a copy of the batch poster config so NewBatchPoster calling Validate() on it doesn't race batchPosterConfig := conf.BatchPoster - batchPoster, err := arbnode.NewBatchPoster(nil, nodeA.L1Reader, nodeA.InboxTracker, nodeA.TxStreamer, nodeA.SyncMonitor, func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, nodeA.DeployInfo, &seqTxOpts, nil) + batchPoster, err := arbnode.NewBatchPoster(nil, testNodeA.L2Node.L1Reader, testNodeA.L2Node.InboxTracker, testNodeA.L2Node.TxStreamer, testNodeA.L2Node.SyncMonitor, func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, testNodeA.L2Node.DeployInfo, &seqTxOpts, nil) Require(t, err) batchPoster.Start(ctx) defer batchPoster.StopAndWait() @@ -90,8 +90,8 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { lastTxHash := txs[len(txs)-1].Hash() for i := 90; i > 0; i-- { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ + testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) time.Sleep(500 * time.Millisecond) _, err := l2clientB.TransactionReceipt(ctx, lastTxHash) @@ -107,9 +107,9 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { // However, setting the clique period to 1 slows everything else (including the L1 deployment for this test) down to a crawl. if false { // Make sure the batch poster is able to post multiple batches in one block - endL1Block, err := l1client.BlockNumber(ctx) + endL1Block, err := testNodeA.L1Client.BlockNumber(ctx) Require(t, err) - seqInbox, err := arbnode.NewSequencerInbox(l1client, nodeA.DeployInfo.SequencerInbox, 0) + seqInbox, err := arbnode.NewSequencerInbox(testNodeA.L1Client, testNodeA.L2Node.DeployInfo.SequencerInbox, 0) Require(t, err) batches, err := seqInbox.LookupBatchesInRange(ctx, new(big.Int).SetUint64(startL1Block), new(big.Int).SetUint64(endL1Block)) Require(t, err) @@ -129,7 +129,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { } } - l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Sign() == 0 { @@ -144,22 +144,22 @@ func TestBatchPosterLargeTx(t *testing.T) { conf := arbnode.ConfigDefaultL1Test() conf.Sequencer.MaxTxDataSize = 110000 - l2info, nodeA, l2clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + testNodeA := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNodeA.L1Stack) + defer testNodeA.L2Node.StopAndWait() - l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, nil) + l2clientB, nodeB := Create2ndNode(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nil) defer nodeB.StopAndWait() data := make([]byte, 100000) _, err := rand.Read(data) Require(t, err) - faucetAddr := l2info.GetAddress("Faucet") - gas := l2info.TransferGas + 20000*uint64(len(data)) - tx := l2info.PrepareTxTo("Faucet", &faucetAddr, gas, common.Big0, data) - err = l2clientA.SendTransaction(ctx, tx) + faucetAddr := testNodeA.L2Info.GetAddress("Faucet") + gas := testNodeA.L2Info.TransferGas + 20000*uint64(len(data)) + tx := testNodeA.L2Info.PrepareTxTo("Faucet", &faucetAddr, gas, common.Big0, data) + err = testNodeA.L2Client.SendTransaction(ctx, tx) Require(t, err) - receiptA, err := EnsureTxSucceeded(ctx, l2clientA, tx) + receiptA, err := EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) Require(t, err) receiptB, err := EnsureTxSucceededWithTimeout(ctx, l2clientB, tx, time.Second*30) Require(t, err) @@ -177,21 +177,21 @@ func TestBatchPosterKeepsUp(t *testing.T) { conf.BatchPoster.CompressionLevel = brotli.BestCompression conf.BatchPoster.MaxDelay = time.Hour conf.RPC.RPCTxFeeCap = 1000. - l2info, nodeA, l2clientA, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() - l2info.GasPrice = big.NewInt(100e9) + testNodeA := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNodeA.L1Stack) + defer testNodeA.L2Node.StopAndWait() + testNodeA.L2Info.GasPrice = big.NewInt(100e9) go func() { data := make([]byte, 90000) _, err := rand.Read(data) Require(t, err) for { - gas := l2info.TransferGas + 20000*uint64(len(data)) - tx := l2info.PrepareTx("Faucet", "Faucet", gas, common.Big0, data) - err = l2clientA.SendTransaction(ctx, tx) + gas := testNodeA.L2Info.TransferGas + 20000*uint64(len(data)) + tx := testNodeA.L2Info.PrepareTx("Faucet", "Faucet", gas, common.Big0, data) + err = testNodeA.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err := EnsureTxSucceeded(ctx, l2clientA, tx) + _, err := EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) Require(t, err) } }() @@ -199,11 +199,11 @@ func TestBatchPosterKeepsUp(t *testing.T) { start := time.Now() for { time.Sleep(time.Second) - batches, err := nodeA.InboxTracker.GetBatchCount() + batches, err := testNodeA.L2Node.InboxTracker.GetBatchCount() Require(t, err) - postedMessages, err := nodeA.InboxTracker.GetBatchMessageCount(batches - 1) + postedMessages, err := testNodeA.L2Node.InboxTracker.GetBatchMessageCount(batches - 1) Require(t, err) - haveMessages, err := nodeA.TxStreamer.GetMessageCount() + haveMessages, err := testNodeA.L2Node.TxStreamer.GetMessageCount() Require(t, err) duration := time.Since(start) fmt.Printf("batches posted: %v over %v (%.2f batches/second)\n", batches, duration, float64(batches)/(float64(duration)/float64(time.Second))) diff --git a/system_tests/block_hash_test.go b/system_tests/block_hash_test.go index 2b8051242..9ce752e65 100644 --- a/system_tests/block_hash_test.go +++ b/system_tests/block_hash_test.go @@ -16,13 +16,13 @@ func TestBlockHash(t *testing.T) { defer cancel() // Even though we don't use the L1, we need to create this node on L1 to get accurate L1 block numbers - l2info, l2node, l2client, _, _, _, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() - auth := l2info.GetDefaultTransactOpts("Faucet", ctx) + auth := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) - _, _, simple, err := mocksgen.DeploySimple(&auth, l2client) + _, _, simple, err := mocksgen.DeploySimple(&auth, testNode.L2Client) Require(t, err) _, err = simple.CheckBlockHashes(&bind.CallOpts{Context: ctx}) diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index fa3d902b1..ae844612f 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -50,20 +50,20 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops delayEvery = workloadLoops / 3 } - l2info, nodeA, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, chainConfig, nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + testNodeA := NewNodeBuilder(ctx).SetIsSequencer(true).SetNodeConfig(l1NodeConfigA).SetChainConfig(chainConfig).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNodeA.L1Stack) + defer testNodeA.L2Node.StopAndWait() - authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) + authorizeDASKeyset(t, ctx, dasSignerKey, testNodeA.L1Info, testNodeA.L1Client) validatorConfig := arbnode.ConfigDefaultL1NonSequencerTest() validatorConfig.BlockValidator.Enable = true validatorConfig.DataAvailability = l1NodeConfigA.DataAvailability validatorConfig.DataAvailability.RPCAggregator.Enable = false AddDefaultValNode(t, ctx, validatorConfig, !arbitrator) - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, validatorConfig, nil) + l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, validatorConfig, nil) defer nodeB.StopAndWait() - l2info.GenerateAccount("User2") + testNodeA.L2Info.GenerateAccount("User2") perTransfer := big.NewInt(1e12) @@ -72,7 +72,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops var tx *types.Transaction if workload == ethSend { - tx = l2info.PrepareTx("Owner", "User2", l2info.TransferGas, perTransfer, nil) + tx = testNodeA.L2Info.PrepareTx("Owner", "User2", testNodeA.L2Info.TransferGas, perTransfer, nil) } else { var contractCode []byte var gas uint64 @@ -86,10 +86,10 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops contractCode = append(contractCode, byte(vm.CODECOPY)) contractCode = append(contractCode, byte(vm.PUSH0)) contractCode = append(contractCode, byte(vm.RETURN)) - basefee := GetBaseFee(t, l2client, ctx) + basefee := testNodeA.GetBaseFeeAtViaL2(t, nil) var err error - gas, err = l2client.EstimateGas(ctx, ethereum.CallMsg{ - From: l2info.GetAddress("Owner"), + gas, err = testNodeA.L2Client.EstimateGas(ctx, ethereum.CallMsg{ + From: testNodeA.L2Info.GetAddress("Owner"), GasPrice: basefee, Value: big.NewInt(0), Data: contractCode, @@ -101,14 +101,14 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops contractCode = append(contractCode, 0x60, 0x00, 0x60, 0x00, 0x52) // PUSH1 0 MSTORE } contractCode = append(contractCode, 0x60, 0x00, 0x56) // JUMP - gas = l2info.TransferGas*2 + l2pricing.InitialPerBlockGasLimitV6 + gas = testNodeA.L2Info.TransferGas*2 + l2pricing.InitialPerBlockGasLimitV6 } - tx = l2info.PrepareTxTo("Owner", nil, gas, common.Big0, contractCode) + tx = testNodeA.L2Info.PrepareTxTo("Owner", nil, gas, common.Big0, contractCode) } - err := l2client.SendTransaction(ctx, tx) + err := testNodeA.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceededWithTimeout(ctx, l2client, tx, time.Second*5) + _, err = EnsureTxSucceededWithTimeout(ctx, testNodeA.L2Client, tx, time.Second*5) if workload != depleteGas { Require(t, err) } @@ -117,40 +117,40 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops } } } else { - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := testNodeA.L2Info.GetDefaultTransactOpts("Owner", ctx) // make auth a chain owner - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), testNodeA.L2Client) Require(t, err) tx, err := arbDebug.BecomeChainOwner(&auth) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) Require(t, err) - arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), l2client) + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), testNodeA.L2Client) Require(t, err) tx, err = arbOwner.ScheduleArbOSUpgrade(&auth, 11, 0) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) Require(t, err) - tx = l2info.PrepareTxTo("Owner", nil, l2info.TransferGas, perTransfer, []byte{byte(vm.PUSH0)}) - err = l2client.SendTransaction(ctx, tx) + tx = testNodeA.L2Info.PrepareTxTo("Owner", nil, testNodeA.L2Info.TransferGas, perTransfer, []byte{byte(vm.PUSH0)}) + err = testNodeA.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceededWithTimeout(ctx, l2client, tx, time.Second*5) + _, err = EnsureTxSucceededWithTimeout(ctx, testNodeA.L2Client, tx, time.Second*5) Require(t, err) } if workload != depleteGas { - delayedTx := l2info.PrepareTx("Owner", "User2", 30002, perTransfer, nil) - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - WrapL2ForDelayed(t, delayedTx, l1info, "User", 100000), + delayedTx := testNodeA.L2Info.PrepareTx("Owner", "User2", 30002, perTransfer, nil) + SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ + WrapL2ForDelayed(t, delayedTx, testNodeA.L1Info, "User", 100000), }) // give the inbox reader a bit of time to pick up the delayed message time.Sleep(time.Millisecond * 500) // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ + testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } @@ -159,7 +159,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops } if workload == ethSend { - l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("User2"), nil) Require(t, err) expectedBalance := new(big.Int).Mul(perTransfer, big.NewInt(int64(workloadLoops+1))) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 8c76baba3..2d242dcd4 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -57,6 +57,9 @@ import ( "github.com/offchainlabs/nitro/util/testhelpers" ) +type info = *BlockchainTestInfo +type client = arbutil.L1Interface + type NodeBuilder struct { // Nodebuilder configuration ctx context.Context @@ -130,20 +133,54 @@ func (b *NodeBuilder) SetIsSequencer(v bool) *NodeBuilder { func (b *NodeBuilder) CreateTestNodeOnL1AndL2(t *testing.T) *NodeBuilder { b.L2Info, b.L2Node, b.L2Client, b.L2Stack, b.L1Info, b.L1Backend, b.L1Client, b.L1Stack = - createTestNodeOnL1WithConfigImpl(t, b.ctx, b.isSequencer, b.nodeConfig, b.chainConfig, b.l2StackConfig, b.cacheConfig, b.L2Info) + createTestNodeOnL1AndL2Impl(t, b.ctx, b.isSequencer, b.nodeConfig, b.chainConfig, b.l2StackConfig, b.cacheConfig, b.L2Info) return b } func (b *NodeBuilder) CreateTestNodeOnL2Only(t *testing.T, takeOwnership bool) *NodeBuilder { - b.L2Info, b.L2Node, b.L2Client = CreateTestL2WithConfig(t, b.ctx, b.L2Info, b.nodeConfig, takeOwnership) + b.L2Info, b.L2Node, b.L2Client = createTestNodeOnL2OnlyImpl(t, b.ctx, b.L2Info, b.nodeConfig, takeOwnership) return b } -func (b *NodeBuilder) DeploySimple(t *testing.T, auth bind.TransactOpts) (common.Address, *mocksgen.Simple) { - return deploySimple(t, b.ctx, auth, b.L2Client) + +func (b *NodeBuilder) SendSignedTxViaL1(t *testing.T, transaction *types.Transaction) *types.Receipt { + return sendSignedTxViaL1Impl(t, b.ctx, b.L1Info, b.L1Client, b.L2Client, transaction) } -type info = *BlockchainTestInfo -type client = arbutil.L1Interface +func (b *NodeBuilder) SendUnsignedTxViaL1(t *testing.T, transaction *types.Transaction) *types.Receipt { + return sendUnsignedTxViaL1Impl(t, b.ctx, b.L1Info, b.L1Client, b.L2Client, transaction) +} + +func (b *NodeBuilder) BridgeBalance(t *testing.T, account string, amount *big.Int) (*types.Transaction, *types.Receipt) { + return bridgeBalanceImpl(t, account, amount, b.L1Info, b.L2Info, b.L1Client, b.L2Client, b.ctx) +} + +func (b *NodeBuilder) TransferBalanceViaL2(t *testing.T, from string, to string, amount *big.Int) (*types.Transaction, *types.Receipt) { + return transferBalanceToImpl(t, from, b.L2Info.GetAddress(to), amount, b.L2Info, b.L2Client, b.ctx) +} + +func (b *NodeBuilder) TransferBalanceViaL1(t *testing.T, from string, to string, amount *big.Int) (*types.Transaction, *types.Receipt) { + return transferBalanceToImpl(t, from, b.L1Info.GetAddress(to), amount, b.L1Info, b.L1Client, b.ctx) +} + +func (b *NodeBuilder) TransferBalanceToViaL2(t *testing.T, from string, to common.Address, amount *big.Int) (*types.Transaction, *types.Receipt) { + return transferBalanceToImpl(t, from, to, amount, b.L2Info, b.L2Client, b.ctx) +} + +func (b *NodeBuilder) TransferBalanceToViaL1(t *testing.T, from string, to common.Address, amount *big.Int) (*types.Transaction, *types.Receipt) { + return transferBalanceToImpl(t, from, to, amount, b.L1Info, b.L1Client, b.ctx) +} + +func (b *NodeBuilder) GetBaseFeeAtViaL2(t *testing.T, blockNum *big.Int) *big.Int { + return getBaseFeeAtImpl(t, b.L2Client, b.ctx, blockNum) +} + +func (b *NodeBuilder) GetBaseFeeAtViaL1(t *testing.T, blockNum *big.Int) *big.Int { + return getBaseFeeAtImpl(t, b.L1Client, b.ctx, blockNum) +} + +func (b *NodeBuilder) DeploySimple(t *testing.T, auth bind.TransactOpts) (common.Address, *mocksgen.Simple) { + return deploySimpleImpl(t, b.ctx, auth, b.L2Client) +} func SendWaitTestTransactions(t *testing.T, ctx context.Context, client client, txs []*types.Transaction) { t.Helper() @@ -156,14 +193,7 @@ func SendWaitTestTransactions(t *testing.T, ctx context.Context, client client, } } -func TransferBalance( - t *testing.T, from, to string, amount *big.Int, l2info info, client client, ctx context.Context, -) (*types.Transaction, *types.Receipt) { - t.Helper() - return TransferBalanceTo(t, from, l2info.GetAddress(to), amount, l2info, client, ctx) -} - -func TransferBalanceTo( +func transferBalanceToImpl( t *testing.T, from string, to common.Address, amount *big.Int, l2info info, client client, ctx context.Context, ) (*types.Transaction, *types.Receipt) { t.Helper() @@ -176,7 +206,7 @@ func TransferBalanceTo( } // if l2client is not nil - will wait until balance appears in l2 -func BridgeBalance( +func bridgeBalanceImpl( t *testing.T, account string, amount *big.Int, l1info info, l2info info, l1client client, l2client client, ctx context.Context, ) (*types.Transaction, *types.Receipt) { t.Helper() @@ -223,7 +253,7 @@ func BridgeBalance( if balance.Cmp(l2Balance) >= 0 { break } - TransferBalance(t, "Faucet", "User", big.NewInt(1), l1info, l1client, ctx) + transferBalanceToImpl(t, "Faucet", l1info.GetAddress("User"), big.NewInt(1), l1info, l1client, ctx) if i > 20 { Fatal(t, "bridging failed") } @@ -234,7 +264,7 @@ func BridgeBalance( return tx, res } -func SendSignedTxViaL1( +func sendSignedTxViaL1Impl( t *testing.T, ctx context.Context, l1info *BlockchainTestInfo, @@ -265,7 +295,7 @@ func SendSignedTxViaL1( return receipt } -func SendUnsignedTxViaL1( +func sendUnsignedTxViaL1Impl( t *testing.T, ctx context.Context, l1info *BlockchainTestInfo, @@ -316,13 +346,7 @@ func SendUnsignedTxViaL1( return receipt } -func GetBaseFee(t *testing.T, client client, ctx context.Context) *big.Int { - header, err := client.HeaderByNumber(ctx, nil) - Require(t, err) - return header.BaseFee -} - -func GetBaseFeeAt(t *testing.T, client client, ctx context.Context, blockNum *big.Int) *big.Int { +func getBaseFeeAtImpl(t *testing.T, client client, ctx context.Context, blockNum *big.Int) *big.Int { header, err := client.HeaderByNumber(ctx, blockNum) Require(t, err) return header.BaseFee @@ -634,33 +658,7 @@ func ClientForStack(t *testing.T, backend *node.Node) *ethclient.Client { } // Create and deploy L1 and arbnode for L2 -func createTestNodeOnL1( - t *testing.T, - ctx context.Context, - isSequencer bool, -) ( - l2info info, node *arbnode.Node, l2client *ethclient.Client, l1info info, - l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node, -) { - return createTestNodeOnL1WithConfig(t, ctx, isSequencer, nil, nil, nil) -} - -func createTestNodeOnL1WithConfig( - t *testing.T, - ctx context.Context, - isSequencer bool, - nodeConfig *arbnode.Config, - chainConfig *params.ChainConfig, - stackConfig *node.Config, -) ( - l2info info, currentNode *arbnode.Node, l2client *ethclient.Client, l1info info, - l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node, -) { - l2info, currentNode, l2client, _, l1info, l1backend, l1client, l1stack = createTestNodeOnL1WithConfigImpl(t, ctx, isSequencer, nodeConfig, chainConfig, stackConfig, nil, nil) - return -} - -func createTestNodeOnL1WithConfigImpl( +func createTestNodeOnL1AndL2Impl( t *testing.T, ctx context.Context, isSequencer bool, @@ -724,7 +722,7 @@ func createTestNodeOnL1WithConfigImpl( // L2 -Only. Enough for tests that needs no interface to L1 // Requires precompiles.AllowDebugPrecompiles = true -func CreateTestL2WithConfig( +func createTestNodeOnL2OnlyImpl( t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, @@ -990,7 +988,7 @@ func getDeadlineTimeout(t *testing.T, defaultTimeout time.Duration) time.Duratio return timeout } -func deploySimple( +func deploySimpleImpl( t *testing.T, ctx context.Context, auth bind.TransactOpts, client *ethclient.Client, ) (common.Address, *mocksgen.Simple) { addr, tx, simple, err := mocksgen.DeploySimple(&auth, client) diff --git a/system_tests/contract_tx_test.go b/system_tests/contract_tx_test.go index ff2912f53..8f6debdf3 100644 --- a/system_tests/contract_tx_test.go +++ b/system_tests/contract_tx_test.go @@ -30,7 +30,7 @@ func TestContractTxDeploy(t *testing.T) { defer testNode.L2Node.StopAndWait() from := common.HexToAddress("0x123412341234") - TransferBalanceTo(t, "Faucet", from, big.NewInt(1e18), testNode.L2Info, testNode.L2Client, ctx) + testNode.TransferBalanceToViaL2(t, "Faucet", from, big.NewInt(1e18)) for stateNonce := uint64(0); stateNonce < 2; stateNonce++ { pos, err := testNode.L2Node.TxStreamer.GetMessageCount() diff --git a/system_tests/debugapi_test.go b/system_tests/debugapi_test.go index ff28e2350..dedf7d294 100644 --- a/system_tests/debugapi_test.go +++ b/system_tests/debugapi_test.go @@ -14,11 +14,11 @@ import ( func TestDebugAPI(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, nil, nil, nil) - defer requireClose(t, l1stack) - defer requireClose(t, l2stack) + testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer requireClose(t, testNode.L2Stack) - l2rpc, _ := l2stack.Attach() + l2rpc, _ := testNode.L2Stack.Attach() var dump state.Dump err := l2rpc.CallContext(ctx, &dump, "debug_dumpBlock", rpc.LatestBlockNumber) diff --git a/system_tests/delayedinbox_test.go b/system_tests/delayedinbox_test.go index e48cb3702..9830a06c7 100644 --- a/system_tests/delayedinbox_test.go +++ b/system_tests/delayedinbox_test.go @@ -38,16 +38,16 @@ func TestDelayInboxSimple(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() - l2info.GenerateAccount("User2") + testNode.L2Info.GenerateAccount("User2") - delayedTx := l2info.PrepareTx("Owner", "User2", 50001, big.NewInt(1e6), nil) - SendSignedTxViaL1(t, ctx, l1info, l1client, l2client, delayedTx) + delayedTx := testNode.L2Info.PrepareTx("Owner", "User2", 50001, big.NewInt(1e6), nil) + testNode.SendSignedTxViaL1(t, delayedTx) - l2balance, err := l2client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := testNode.L2Client.BalanceAt(ctx, testNode.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e6)) != 0 { Fatal(t, "Unexpected balance:", l2balance) diff --git a/system_tests/delayedinboxlong_test.go b/system_tests/delayedinboxlong_test.go index b1c8ea361..cc41220ff 100644 --- a/system_tests/delayedinboxlong_test.go +++ b/system_tests/delayedinboxlong_test.go @@ -25,11 +25,11 @@ func TestDelayInboxLong(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, l2client, l1info, l1backend, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() - l2info.GenerateAccount("User2") + testNode.L2Info.GenerateAccount("User2") fundsPerDelayed := int64(1000000) delayedMessages := int64(0) @@ -42,22 +42,22 @@ func TestDelayInboxLong(t *testing.T) { randNum := rand.Int() % messagesPerDelayed var l1tx *types.Transaction if randNum == 0 { - delayedTx := l2info.PrepareTx("Owner", "User2", 50001, big.NewInt(fundsPerDelayed), nil) - l1tx = WrapL2ForDelayed(t, delayedTx, l1info, "User", 100000) + delayedTx := testNode.L2Info.PrepareTx("Owner", "User2", 50001, big.NewInt(fundsPerDelayed), nil) + l1tx = WrapL2ForDelayed(t, delayedTx, testNode.L1Info, "User", 100000) lastDelayedMessage = delayedTx delayedMessages++ } else { - l1tx = l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) + l1tx = testNode.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) } l1Txs = append(l1Txs, l1tx) } // adding multiple messages in the same AddLocal to get them in the same L1 block - errs := l1backend.TxPool().AddLocals(l1Txs) + errs := testNode.L1Backend.TxPool().AddLocals(l1Txs) for _, err := range errs { Require(t, err) } // Checking every tx is expensive, so we just check the last, assuming that the others succeeded too - _, err := EnsureTxSucceeded(ctx, l1client, l1Txs[len(l1Txs)-1]) + _, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1Txs[len(l1Txs)-1]) Require(t, err) } @@ -68,14 +68,14 @@ func TestDelayInboxLong(t *testing.T) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 100; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, testNode.L1Client, []*types.Transaction{ + testNode.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } - _, err := WaitForTx(ctx, l2client, lastDelayedMessage.Hash(), time.Second*5) + _, err := WaitForTx(ctx, testNode.L2Client, lastDelayedMessage.Hash(), time.Second*5) Require(t, err) - l2balance, err := l2client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := testNode.L2Client.BalanceAt(ctx, testNode.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(fundsPerDelayed*delayedMessages)) != 0 { Fatal(t, "Unexpected balance:", "balance", l2balance, "expected", fundsPerDelayed*delayedMessages) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index 449f816ba..ae3fc39a7 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -78,7 +78,7 @@ func TestEstimate(t *testing.T) { for !equilibrated && numTriesLeft > 0 { // make an empty block to let the gas price update testNode.L2Info.GasPrice = new(big.Int).Mul(testNode.L2Info.GasPrice, big.NewInt(2)) - TransferBalance(t, "Owner", "Owner", common.Big0, testNode.L2Info, testNode.L2Client, ctx) + testNode.TransferBalanceViaL2(t, "Owner", "Owner", common.Big0) // check if the price has equilibrated _, _, _, _, _, setPrice, err := arbGasInfo.GetPricesInWei(&bind.CallOpts{}) @@ -136,7 +136,7 @@ func TestComponentEstimate(t *testing.T) { defer testNode.L2Node.StopAndWait() l1BaseFee := new(big.Int).Set(arbostypes.DefaultInitialL1BaseFee) - l2BaseFee := GetBaseFee(t, testNode.L2Client, ctx) + l2BaseFee := testNode.GetBaseFeeAtViaL2(t, nil) colors.PrintGrey("l1 basefee ", l1BaseFee) colors.PrintGrey("l2 basefee ", l2BaseFee) @@ -146,7 +146,7 @@ func TestComponentEstimate(t *testing.T) { maxFeePerGas := arbmath.BigMulByUfrac(l2BaseFee, 3, 2) testNode.L2Info.GenerateAccount("User") - TransferBalance(t, "Owner", "User", userBalance, testNode.L2Info, testNode.L2Client, ctx) + testNode.TransferBalanceViaL2(t, "Owner", "User", userBalance) from := testNode.L2Info.GetAddress("User") to := testhelpers.RandomAddress() diff --git a/system_tests/fees_test.go b/system_tests/fees_test.go index bdd998357..5093b873d 100644 --- a/system_tests/fees_test.go +++ b/system_tests/fees_test.go @@ -33,19 +33,19 @@ func TestSequencerFeePaid(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, l2client, _, _, _, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() - version := l2node.Execution.ArbInterface.BlockChain().Config().ArbitrumChainParams.InitialArbOSVersion - callOpts := l2info.GetDefaultCallOpts("Owner", ctx) + version := testNode.L2Node.Execution.ArbInterface.BlockChain().Config().ArbitrumChainParams.InitialArbOSVersion + callOpts := testNode.L2Info.GetDefaultCallOpts("Owner", ctx) // get the network fee account - arbOwnerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("0x6b"), l2client) + arbOwnerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("0x6b"), testNode.L2Client) Require(t, err, "failed to deploy contract") - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), testNode.L2Client) Require(t, err, "failed to deploy contract") - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), testNode.L2Client) Require(t, err, "failed to deploy contract") networkFeeAccount, err := arbOwnerPublic.GetNetworkFeeAccount(callOpts) Require(t, err, "could not get the network fee account") @@ -53,24 +53,24 @@ func TestSequencerFeePaid(t *testing.T) { l1Estimate, err := arbGasInfo.GetL1BaseFeeEstimate(callOpts) Require(t, err) - baseFee := GetBaseFee(t, l2client, ctx) - l2info.GasPrice = baseFee + baseFee := testNode.GetBaseFeeAtViaL2(t, nil) + testNode.L2Info.GasPrice = baseFee testFees := func(tip uint64) (*big.Int, *big.Int) { tipCap := arbmath.BigMulByUint(baseFee, tip) - txOpts := l2info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) txOpts.GasTipCap = tipCap gasPrice := arbmath.BigAdd(baseFee, tipCap) - networkBefore := GetBalance(t, ctx, l2client, networkFeeAccount) + networkBefore := GetBalance(t, ctx, testNode.L2Client, networkFeeAccount) tx, err := arbDebug.Events(&txOpts, true, [32]byte{}) Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, l2client, tx) + receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) - networkAfter := GetBalance(t, ctx, l2client, networkFeeAccount) - l1Charge := arbmath.BigMulByUint(l2info.GasPrice, receipt.GasUsedForL1) + networkAfter := GetBalance(t, ctx, testNode.L2Client, networkFeeAccount) + l1Charge := arbmath.BigMulByUint(testNode.L2Info.GasPrice, receipt.GasUsedForL1) // the network should receive // 1. compute costs @@ -92,7 +92,7 @@ func TestSequencerFeePaid(t *testing.T) { l1GasBought := arbmath.BigDiv(l1Charge, l1Estimate).Uint64() l1ChargeExpected := arbmath.BigMulByUint(l1Estimate, txSize*params.TxDataNonZeroGasEIP2028) // L1 gas can only be charged in terms of L2 gas, so subtract off any rounding error from the expected value - l1ChargeExpected.Sub(l1ChargeExpected, new(big.Int).Mod(l1ChargeExpected, l2info.GasPrice)) + l1ChargeExpected.Sub(l1ChargeExpected, new(big.Int).Mod(l1ChargeExpected, testNode.L2Info.GasPrice)) colors.PrintBlue("bytes ", l1GasBought/params.TxDataNonZeroGasEIP2028, txSize) @@ -135,38 +135,38 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { conf := arbnode.ConfigDefaultL1Test() conf.DelayedSequencer.FinalizeDistance = 1 - l2info, node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, chainConfig, nil) - defer requireClose(t, l1stack) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(conf).SetChainConfig(chainConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() - ownerAuth := l2info.GetDefaultTransactOpts("Owner", ctx) + ownerAuth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) // make ownerAuth a chain owner - arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) + arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), testNode.L2Client) Require(t, err) tx, err := arbdebug.BecomeChainOwner(&ownerAuth) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) // use ownerAuth to set the L1 price per unit Require(t, err) - arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), l2client) + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), testNode.L2Client) Require(t, err) tx, err = arbOwner.SetL1PricePerUnit(&ownerAuth, arbmath.UintToBig(initialEstimate)) Require(t, err) - _, err = WaitForTx(ctx, l2client, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, testNode.L2Client, tx.Hash(), time.Second*5) Require(t, err) - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), testNode.L2Client) Require(t, err) lastEstimate, err := arbGasInfo.GetL1BaseFeeEstimate(&bind.CallOpts{Context: ctx}) Require(t, err) - lastBatchCount, err := node.InboxTracker.GetBatchCount() + lastBatchCount, err := testNode.L2Node.InboxTracker.GetBatchCount() Require(t, err) - l1Header, err := l1client.HeaderByNumber(ctx, nil) + l1Header, err := testNode.L1Client.HeaderByNumber(ctx, nil) Require(t, err) - rewardRecipientBalanceBefore := GetBalance(t, ctx, l2client, l1pricing.BatchPosterAddress) + rewardRecipientBalanceBefore := GetBalance(t, ctx, testNode.L2Client, l1pricing.BatchPosterAddress) timesPriceAdjusted := 0 colors.PrintBlue("Initial values") @@ -175,17 +175,17 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { numRetrogradeMoves := 0 for i := 0; i < 256; i++ { - tx, receipt := TransferBalance(t, "Owner", "Owner", common.Big1, l2info, l2client, ctx) - header, err := l2client.HeaderByHash(ctx, receipt.BlockHash) + tx, receipt := testNode.TransferBalanceViaL2(t, "Owner", "Owner", common.Big1) + header, err := testNode.L2Client.HeaderByHash(ctx, receipt.BlockHash) Require(t, err) - TransferBalance(t, "Faucet", "Faucet", common.Big1, l1info, l1client, ctx) // generate l1 traffic + testNode.TransferBalanceViaL1(t, "Faucet", "Faucet", common.Big1) // generate l1 traffic units := compressedTxSize(t, tx) * params.TxDataNonZeroGasEIP2028 estimatedL1FeePerUnit := arbmath.BigDivByUint(arbmath.BigMulByUint(header.BaseFee, receipt.GasUsedForL1), units) if !arbmath.BigEquals(lastEstimate, estimatedL1FeePerUnit) { - l1Header, err = l1client.HeaderByNumber(ctx, nil) + l1Header, err = testNode.L1Client.HeaderByNumber(ctx, nil) Require(t, err) callOpts := &bind.CallOpts{Context: ctx, BlockNumber: receipt.BlockNumber} @@ -234,7 +234,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { // see that the inbox advances for j := 16; j > 0; j-- { - newBatchCount, err := node.InboxTracker.GetBatchCount() + newBatchCount, err := testNode.L2Node.InboxTracker.GetBatchCount() Require(t, err) if newBatchCount > lastBatchCount { colors.PrintGrey("posted new batch ", newBatchCount) @@ -249,7 +249,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { } } - rewardRecipientBalanceAfter := GetBalance(t, ctx, l2client, chainConfig.ArbitrumChainParams.InitialChainOwner) + rewardRecipientBalanceAfter := GetBalance(t, ctx, testNode.L2Client, chainConfig.ArbitrumChainParams.InitialChainOwner) colors.PrintMint("reward recipient balance ", rewardRecipientBalanceBefore, " ➤ ", rewardRecipientBalanceAfter) colors.PrintMint("price changes ", timesPriceAdjusted) @@ -260,7 +260,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { Fatal(t, "reward recipient didn't get paid") } - arbAggregator, err := precompilesgen.NewArbAggregator(common.HexToAddress("0x6d"), l2client) + arbAggregator, err := precompilesgen.NewArbAggregator(common.HexToAddress("0x6d"), testNode.L2Client) Require(t, err) batchPosterAddresses, err := arbAggregator.GetBatchPosters(&bind.CallOpts{Context: ctx}) Require(t, err) @@ -268,7 +268,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { for _, bpAddr := range batchPosterAddresses { if bpAddr != l1pricing.BatchPosterAddress && bpAddr != l1pricing.L1PricerFundsPoolAddress { numReimbursed++ - bal, err := l1client.BalanceAt(ctx, bpAddr, nil) + bal, err := testNode.L1Client.BalanceAt(ctx, bpAddr, nil) Require(t, err) if bal.Sign() == 0 { Fatal(t, "Batch poster balance is zero for", bpAddr) diff --git a/system_tests/forwarder_test.go b/system_tests/forwarder_test.go index 0a954719d..753f067ed 100644 --- a/system_tests/forwarder_test.go +++ b/system_tests/forwarder_test.go @@ -40,9 +40,9 @@ func TestStaticForwarder(t *testing.T) { nodeConfigA := arbnode.ConfigDefaultL1Test() nodeConfigA.BatchPoster.Enable = false - l2info, nodeA, clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfigA, nil, stackConfig) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + testNodeA := NewNodeBuilder(ctx).SetNodeConfig(nodeConfigA).SetL2StackConfig(stackConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNodeA.L1Stack) + defer testNodeA.L2Node.StopAndWait() nodeConfigB := arbnode.ConfigDefaultL1Test() nodeConfigB.Sequencer.Enable = false @@ -51,18 +51,18 @@ func TestStaticForwarder(t *testing.T) { nodeConfigB.ForwardingTarget = ipcPath nodeConfigB.BatchPoster.Enable = false - clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, nodeConfigB, nil) + clientB, nodeB := Create2ndNodeWithConfig(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nodeConfigB, nil) defer nodeB.StopAndWait() - l2info.GenerateAccount("User2") - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, transferAmount, nil) + testNodeA.L2Info.GenerateAccount("User2") + tx := testNodeA.L2Info.PrepareTx("Owner", "User2", testNodeA.L2Info.TransferGas, transferAmount, nil) err := clientB.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, clientA, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) Require(t, err) - l2balance, err := clientA.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := testNodeA.L2Client.BalanceAt(ctx, testNodeA.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(transferAmount) != 0 { @@ -105,7 +105,8 @@ func fallbackSequencer( nodeConfig.SeqCoordinator.Enable = opts.enableSecCoordinator nodeConfig.SeqCoordinator.RedisUrl = opts.redisUrl nodeConfig.SeqCoordinator.MyUrl = opts.ipcPath - return createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, stackConfig) + testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeConfig).SetL2StackConfig(stackConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + return testNode.L2Info, testNode.L2Node, testNode.L2Client, testNode.L1Info, testNode.L1Backend, testNode.L1Client, testNode.L1Stack } func createForwardingNode( diff --git a/system_tests/ipc_test.go b/system_tests/ipc_test.go index 01ecf859d..fbac4156c 100644 --- a/system_tests/ipc_test.go +++ b/system_tests/ipc_test.go @@ -24,9 +24,9 @@ func TestIpcRpc(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, l2node, _, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, nil, stackConf) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetL2StackConfig(stackConf).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() _, err := ethclient.Dial(ipcPath) Require(t, err) diff --git a/system_tests/meaningless_reorg_test.go b/system_tests/meaningless_reorg_test.go index 851bf38ce..b30417a5a 100644 --- a/system_tests/meaningless_reorg_test.go +++ b/system_tests/meaningless_reorg_test.go @@ -20,24 +20,24 @@ func TestMeaninglessBatchReorg(t *testing.T) { defer cancel() conf := arbnode.ConfigDefaultL1Test() conf.BatchPoster.Enable = false - l2Info, arbNode, l2Client, l1Info, l1Backend, l1Client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil) - defer requireClose(t, l1stack) - defer arbNode.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() - seqInbox, err := bridgegen.NewSequencerInbox(l1Info.GetAddress("SequencerInbox"), l1Client) + seqInbox, err := bridgegen.NewSequencerInbox(testNode.L1Info.GetAddress("SequencerInbox"), testNode.L1Client) Require(t, err) - seqOpts := l1Info.GetDefaultTransactOpts("Sequencer", ctx) + seqOpts := testNode.L1Info.GetDefaultTransactOpts("Sequencer", ctx) tx, err := seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(1), nil, big.NewInt(1), common.Address{}) Require(t, err) - batchReceipt, err := EnsureTxSucceeded(ctx, l1Client, tx) + batchReceipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, tx) Require(t, err) for i := 0; ; i++ { if i >= 500 { Fatal(t, "Failed to read batch from L1") } - msgNum, err := arbNode.Execution.ExecEngine.HeadMessageNumber() + msgNum, err := testNode.L2Node.Execution.ExecEngine.HeadMessageNumber() Require(t, err) if msgNum == 1 { break @@ -46,33 +46,33 @@ func TestMeaninglessBatchReorg(t *testing.T) { } time.Sleep(10 * time.Millisecond) } - metadata, err := arbNode.InboxTracker.GetBatchMetadata(1) + metadata, err := testNode.L2Node.InboxTracker.GetBatchMetadata(1) Require(t, err) originalBatchBlock := batchReceipt.BlockNumber.Uint64() if metadata.ParentChainBlock != originalBatchBlock { Fatal(t, "Posted batch in block", originalBatchBlock, "but metadata says L1 block was", metadata.ParentChainBlock) } - _, l2Receipt := TransferBalance(t, "Owner", "Owner", common.Big1, l2Info, l2Client, ctx) + _, l2Receipt := testNode.TransferBalanceViaL2(t, "Owner", "Owner", common.Big1) // Make the reorg larger to force the miner to discard transactions. // The miner usually collects transactions from deleted blocks and puts them in the mempool. // However, this code doesn't run on reorgs larger than 64 blocks for performance reasons. // Therefore, we make a bunch of small blocks to prevent the code from running. for j := uint64(0); j < 70; j++ { - TransferBalance(t, "Faucet", "Faucet", common.Big1, l1Info, l1Client, ctx) + testNode.TransferBalanceViaL1(t, "Faucet", "Faucet", common.Big1) } - parentBlock := l1Backend.BlockChain().GetBlockByNumber(batchReceipt.BlockNumber.Uint64() - 1) - err = l1Backend.BlockChain().ReorgToOldBlock(parentBlock) + parentBlock := testNode.L1Backend.BlockChain().GetBlockByNumber(batchReceipt.BlockNumber.Uint64() - 1) + err = testNode.L1Backend.BlockChain().ReorgToOldBlock(parentBlock) Require(t, err) // Produce a new l1Block so that the batch ends up in a different l1Block than before - TransferBalance(t, "User", "User", common.Big1, l1Info, l1Client, ctx) + testNode.TransferBalanceViaL1(t, "User", "User", common.Big1) tx, err = seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(1), nil, big.NewInt(1), common.Address{}) Require(t, err) - newBatchReceipt, err := EnsureTxSucceeded(ctx, l1Client, tx) + newBatchReceipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, tx) Require(t, err) newBatchBlock := newBatchReceipt.BlockNumber.Uint64() @@ -86,7 +86,7 @@ func TestMeaninglessBatchReorg(t *testing.T) { if i >= 500 { Fatal(t, "Failed to read batch reorg from L1") } - metadata, err = arbNode.InboxTracker.GetBatchMetadata(1) + metadata, err = testNode.L2Node.InboxTracker.GetBatchMetadata(1) Require(t, err) if metadata.ParentChainBlock == newBatchBlock { break @@ -96,10 +96,10 @@ func TestMeaninglessBatchReorg(t *testing.T) { time.Sleep(10 * time.Millisecond) } - _, err = arbNode.InboxReader.GetSequencerMessageBytes(ctx, 1) + _, err = testNode.L2Node.InboxReader.GetSequencerMessageBytes(ctx, 1) Require(t, err) - l2Header, err := l2Client.HeaderByNumber(ctx, l2Receipt.BlockNumber) + l2Header, err := testNode.L2Client.HeaderByNumber(ctx, l2Receipt.BlockNumber) Require(t, err) if l2Header.Hash() != l2Receipt.BlockHash { diff --git a/system_tests/nodeinterface_test.go b/system_tests/nodeinterface_test.go index 167f2204c..2f36fb1d7 100644 --- a/system_tests/nodeinterface_test.go +++ b/system_tests/nodeinterface_test.go @@ -19,23 +19,23 @@ func TestL2BlockRangeForL1(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, l2client, l1info, _, _, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer node.StopAndWait() - user := l1info.GetDefaultTransactOpts("User", ctx) + testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() + user := testNode.L1Info.GetDefaultTransactOpts("User", ctx) numTransactions := 200 for i := 0; i < numTransactions; i++ { - TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), l2info, l2client, ctx) + testNode.TransferBalanceToViaL2(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18)) } - nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, testNode.L2Client) if err != nil { t.Fatalf("Error creating node interface: %v", err) } l1BlockNums := map[uint64]*[2]uint64{} - latestL2, err := l2client.BlockNumber(ctx) + latestL2, err := testNode.L2Client.BlockNumber(ctx) if err != nil { t.Fatalf("Error querying most recent l2 block: %v", err) } diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index 561085c3f..22c4f4724 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -22,7 +22,7 @@ import ( "github.com/offchainlabs/nitro/util/testhelpers" ) -func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, txCount uint64) (node *arbnode.Node, bc *core.BlockChain, db ethdb.Database, l2client *ethclient.Client, l2info info, cancel func()) { +func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateDepth int64, txCount uint64) (*arbnode.Node, *core.BlockChain, ethdb.Database, *ethclient.Client, info, func()) { t.Helper() nodeConfig := arbnode.ConfigDefaultL1Test() nodeConfig.RPC.MaxRecreateStateDepth = maxRecreateStateDepth @@ -43,27 +43,27 @@ func prepareNodeWithHistory(t *testing.T, ctx context.Context, maxRecreateStateD SnapshotLimit: 256, SnapshotWait: true, } - l2info, node, l2client, _, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, cacheConfig, nil) - cancel = func() { - defer requireClose(t, l1stack) - defer node.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeConfig).SetCacheConfig(cacheConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + cancel := func() { + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() } - l2info.GenerateAccount("User2") + testNode.L2Info.GenerateAccount("User2") var txs []*types.Transaction for i := uint64(0); i < txCount; i++ { - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, common.Big1, nil) + tx := testNode.L2Info.PrepareTx("Owner", "User2", testNode.L2Info.TransferGas, common.Big1, nil) txs = append(txs, tx) - err := l2client.SendTransaction(ctx, tx) + err := testNode.L2Client.SendTransaction(ctx, tx) testhelpers.RequireImpl(t, err) } for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, l2client, tx) + _, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) testhelpers.RequireImpl(t, err) } - bc = node.Execution.Backend.ArbInterface().BlockChain() - db = node.Execution.Backend.ChainDb() + bc := testNode.L2Node.Execution.Backend.ArbInterface().BlockChain() + db := testNode.L2Node.Execution.Backend.ChainDb() - return + return testNode.L2Node, bc, db, testNode.L2Client, testNode.L2Info, cancel } func fillHeaderCache(t *testing.T, bc *core.BlockChain, from, to uint64) { diff --git a/system_tests/reorg_resequencing_test.go b/system_tests/reorg_resequencing_test.go index 4f72f9823..0251969e3 100644 --- a/system_tests/reorg_resequencing_test.go +++ b/system_tests/reorg_resequencing_test.go @@ -31,10 +31,10 @@ func TestReorgResequencing(t *testing.T) { testNode.L2Info.GenerateAccount("User2") testNode.L2Info.GenerateAccount("User3") testNode.L2Info.GenerateAccount("User4") - TransferBalance(t, "Owner", "User1", big.NewInt(params.Ether), testNode.L2Info, testNode.L2Client, ctx) - TransferBalance(t, "Owner", "Intermediate", big.NewInt(params.Ether*3), testNode.L2Info, testNode.L2Client, ctx) - TransferBalance(t, "Intermediate", "User2", big.NewInt(params.Ether), testNode.L2Info, testNode.L2Client, ctx) - TransferBalance(t, "Intermediate", "User3", big.NewInt(params.Ether), testNode.L2Info, testNode.L2Client, ctx) + testNode.TransferBalanceViaL2(t, "Owner", "User1", big.NewInt(params.Ether)) + testNode.TransferBalanceViaL2(t, "Owner", "Intermediate", big.NewInt(params.Ether*3)) + testNode.TransferBalanceViaL2(t, "Intermediate", "User2", big.NewInt(params.Ether)) + testNode.TransferBalanceViaL2(t, "Intermediate", "User3", big.NewInt(params.Ether)) // Intermediate does not have exactly 1 ether because of fees accountsWithBalance := []string{"User1", "User2", "User3"} diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index eb7d3528c..61c258893 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -87,7 +87,7 @@ func retryableSetup(t *testing.T) ( // burn some gas so that the faucet's Callvalue + Balance never exceeds a uint256 discard := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - TransferBalance(t, "Faucet", "Burn", discard, testNode.L2Info, testNode.L2Client, ctx) + testNode.TransferBalanceViaL2(t, "Faucet", "Burn", discard) teardown := func() { @@ -289,7 +289,7 @@ func TestSubmissionGasCosts(t *testing.T) { testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, testNode.L2Client, testNode.L2Info) - elevateL2Basefee(t, ctx, testNode.L2Client, testNode.L2Info) + elevateL2Basefee(t, ctx, testNode) usertxopts := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxopts.Value = arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) @@ -502,7 +502,7 @@ func TestArbitrumContractTx(t *testing.T) { testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() faucetL2Addr := util.RemapL1Address(testNode.L1Info.GetAddress("Faucet")) - TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), testNode.L2Info, testNode.L2Client, ctx) + testNode.TransferBalanceToViaL2(t, "Faucet", faucetL2Addr, big.NewInt(1e18)) l2TxOpts := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) l2ContractAddr, _ := testNode.DeploySimple(t, l2TxOpts) @@ -559,7 +559,7 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { faucetL2Addr := util.RemapL1Address(testNode.L1Info.GetAddress("Faucet")) // Transfer balance to Faucet's corresponding L2 address, so that there is // enough balance on its' account for executing L2 transaction. - TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), testNode.L2Info, testNode.L2Client, ctx) + testNode.TransferBalanceToViaL2(t, "Faucet", faucetL2Addr, big.NewInt(1e18)) l2TxOpts := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) contractAddr, _ := testNode.DeploySimple(t, l2TxOpts) @@ -631,7 +631,7 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) - elevateL2Basefee(t, ctx, testNode.L2Client, testNode.L2Info) + elevateL2Basefee(t, ctx, testNode) infraBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) @@ -643,7 +643,7 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { callValue := common.Big0 usertxoptsL1 := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL1.Value = deposit - baseFee := GetBaseFee(t, testNode.L2Client, ctx) + baseFee := testNode.GetBaseFeeAtViaL2(t, nil) l1tx, err := delayedInbox.CreateRetryableTicket( &usertxoptsL1, simpleAddr, @@ -736,7 +736,7 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { Require(t, err) minimumBaseFee, err := arbGasInfo.GetMinimumGasPrice(&bind.CallOpts{Context: ctx}) Require(t, err) - submissionBaseFee := GetBaseFeeAt(t, testNode.L2Client, ctx, submissionReceipt.BlockNumber) + submissionBaseFee := testNode.GetBaseFeeAtViaL2(t, submissionReceipt.BlockNumber) submissionTx, ok := submissionTxOuter.GetInner().(*types.ArbitrumSubmitRetryableTx) if !ok { Fatal(t, "inner tx isn't ArbitrumSubmitRetryableTx") @@ -756,7 +756,7 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { if !ok { Fatal(t, "inner tx isn't ArbitrumRetryTx") } - redeemBaseFee := GetBaseFeeAt(t, testNode.L2Client, ctx, redeemReceipt.BlockNumber) + redeemBaseFee := testNode.GetBaseFeeAtViaL2(t, redeemReceipt.BlockNumber) t.Log("redeem base fee:", redeemBaseFee) // redeem & retry expected fees @@ -792,29 +792,29 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { } // elevateL2Basefee by burning gas exceeding speed limit -func elevateL2Basefee(t *testing.T, ctx context.Context, l2client *ethclient.Client, l2info *BlockchainTestInfo) { - baseFeeBefore := GetBaseFee(t, l2client, ctx) +func elevateL2Basefee(t *testing.T, ctx context.Context, testNode *NodeBuilder) { + baseFeeBefore := testNode.GetBaseFeeAtViaL2(t, nil) colors.PrintBlue("Elevating base fee...") arbostestabi, err := precompilesgen.ArbosTestMetaData.GetAbi() Require(t, err) - _, err = precompilesgen.NewArbosTest(common.HexToAddress("0x69"), l2client) + _, err = precompilesgen.NewArbosTest(common.HexToAddress("0x69"), testNode.L2Client) Require(t, err, "failed to deploy ArbosTest") burnAmount := arbnode.ConfigDefaultL1Test().RPC.RPCGasCap burnTarget := uint64(5 * l2pricing.InitialSpeedLimitPerSecondV6 * l2pricing.InitialBacklogTolerance) for i := uint64(0); i < (burnTarget+burnAmount)/burnAmount; i++ { burnArbGas := arbostestabi.Methods["burnArbGas"] - data, err := burnArbGas.Inputs.Pack(arbmath.UintToBig(burnAmount - l2info.TransferGas)) + data, err := burnArbGas.Inputs.Pack(arbmath.UintToBig(burnAmount - testNode.L2Info.TransferGas)) Require(t, err) input := append([]byte{}, burnArbGas.ID...) input = append(input, data...) to := common.HexToAddress("0x69") - tx := l2info.PrepareTxTo("Faucet", &to, burnAmount, big.NewInt(0), input) - Require(t, l2client.SendTransaction(ctx, tx)) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + tx := testNode.L2Info.PrepareTxTo("Faucet", &to, burnAmount, big.NewInt(0), input) + Require(t, testNode.L2Client.SendTransaction(ctx, tx)) + _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) Require(t, err) } - baseFee := GetBaseFee(t, l2client, ctx) + baseFee := testNode.GetBaseFeeAtViaL2(t, nil) colors.PrintBlue("New base fee: ", baseFee, " diff:", baseFee.Uint64()-baseFeeBefore.Uint64()) } diff --git a/system_tests/seq_coordinator_test.go b/system_tests/seq_coordinator_test.go index 27b7031dc..1e55e1c88 100644 --- a/system_tests/seq_coordinator_test.go +++ b/system_tests/seq_coordinator_test.go @@ -278,9 +278,9 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { initRedisForTest(t, ctx, nodeConfig.SeqCoordinator.RedisUrl, nodeNames) nodeConfig.SeqCoordinator.MyUrl = nodeNames[0] - l2Info, nodeA, clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, params.ArbitrumDevTestChainConfig(), nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + testNodeA := NewNodeBuilder(ctx).SetNodeConfig(nodeConfig).SetChainConfig(params.ArbitrumDevTestChainConfig()).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNodeA.L1Stack) + defer testNodeA.L2Node.StopAndWait() redisClient, err := redisutil.RedisClientFromURL(nodeConfig.SeqCoordinator.RedisUrl) Require(t, err) @@ -297,7 +297,7 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { break } - l2Info.GenerateAccount("User2") + testNodeA.L2Info.GenerateAccount("User2") nodeConfigDup := *nodeConfig nodeConfig = &nodeConfigDup @@ -305,23 +305,23 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { nodeConfig.SeqCoordinator.MyUrl = nodeNames[1] if !successCase { nodeConfig.SeqCoordinator.Signer.ECDSA.AcceptSequencer = false - nodeConfig.SeqCoordinator.Signer.ECDSA.AllowedAddresses = []string{l2Info.GetAddress("User2").Hex()} + nodeConfig.SeqCoordinator.Signer.ECDSA.AllowedAddresses = []string{testNodeA.L2Info.GetAddress("User2").Hex()} } - clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2Info.ArbInitData, nodeConfig, nil) + clientB, nodeB := Create2ndNodeWithConfig(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nodeConfig, nil) defer nodeB.StopAndWait() - tx := l2Info.PrepareTx("Owner", "User2", l2Info.TransferGas, big.NewInt(1e12), nil) + tx := testNodeA.L2Info.PrepareTx("Owner", "User2", testNodeA.L2Info.TransferGas, big.NewInt(1e12), nil) - err = clientA.SendTransaction(ctx, tx) + err = testNodeA.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, clientA, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) Require(t, err) if successCase { _, err = WaitForTx(ctx, clientB, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := clientB.BalanceAt(ctx, l2Info.GetAddress("User2"), nil) + l2balance, err := clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) diff --git a/system_tests/seq_whitelist_test.go b/system_tests/seq_whitelist_test.go index 351b031ca..5275bf9ac 100644 --- a/system_tests/seq_whitelist_test.go +++ b/system_tests/seq_whitelist_test.go @@ -25,11 +25,11 @@ func TestSequencerWhitelist(t *testing.T) { testNode.L2Info.GenerateAccount("User2") // Owner is on the whitelist - TransferBalance(t, "Owner", "User", big.NewInt(params.Ether), testNode.L2Info, testNode.L2Client, ctx) - TransferBalance(t, "Owner", "User2", big.NewInt(params.Ether), testNode.L2Info, testNode.L2Client, ctx) + testNode.TransferBalanceViaL2(t, "Owner", "User", big.NewInt(params.Ether)) + testNode.TransferBalanceViaL2(t, "Owner", "User2", big.NewInt(params.Ether)) // User is on the whitelist - TransferBalance(t, "User", "User2", big.NewInt(params.Ether/10), testNode.L2Info, testNode.L2Client, ctx) + testNode.TransferBalanceViaL2(t, "User", "User2", big.NewInt(params.Ether/10)) // User2 is *not* on the whitelist, therefore this should fail tx := testNode.L2Info.PrepareTx("User2", "User", testNode.L2Info.TransferGas, big.NewInt(params.Ether/10), nil) diff --git a/system_tests/seqcompensation_test.go b/system_tests/seqcompensation_test.go index 362acf6a3..39cf0771a 100644 --- a/system_tests/seqcompensation_test.go +++ b/system_tests/seqcompensation_test.go @@ -18,19 +18,19 @@ func TestSequencerCompensation(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + testNodeA := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNodeA.L1Stack) + defer testNodeA.L2Node.StopAndWait() - l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, nil) + l2clientB, nodeB := Create2ndNode(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nil) defer nodeB.StopAndWait() - l2info.GenerateAccount("User2") + testNodeA.L2Info.GenerateAccount("User2") - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) - err := l2clientA.SendTransaction(ctx, tx) + tx := testNodeA.L2Info.PrepareTx("Owner", "User2", testNodeA.L2Info.TransferGas, big.NewInt(1e12), nil) + err := testNodeA.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2clientA, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) Require(t, err) // give the inbox reader a bit of time to pick up the delayed message @@ -38,8 +38,8 @@ func TestSequencerCompensation(t *testing.T) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ + testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } @@ -47,7 +47,7 @@ func TestSequencerCompensation(t *testing.T) { Require(t, err) // clientB sees balance means sequencer message was sent - l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { Fatal(t, "Unexpected balance:", l2balance) diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index 0243c55e5..e89b8a58b 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -135,11 +135,11 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigA.BatchPoster.Enable = true nodeConfigA.Feed.Output.Enable = false - l2infoA, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfigA, chainConfig, nil) - defer requireClose(t, l1stack, "unable to close l1stack") - defer nodeA.StopAndWait() + testNodeA := NewNodeBuilder(ctx).SetNodeConfig(nodeConfigA).SetChainConfig(chainConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNodeA.L1Stack, "unable to close l1Stack") + defer testNodeA.L2Node.StopAndWait() - authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) + authorizeDASKeyset(t, ctx, dasSignerKey, testNodeA.L1Info, testNodeA.L1Client) // The lying sequencer nodeConfigC := arbnode.ConfigDefaultL1Test() @@ -147,7 +147,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigC.DataAvailability = nodeConfigA.DataAvailability nodeConfigC.DataAvailability.RPCAggregator.Enable = false nodeConfigC.Feed.Output = *newBroadcasterConfigTest() - l2clientC, nodeC := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2infoA.ArbInitData, nodeConfigC, nil) + l2clientC, nodeC := Create2ndNodeWithConfig(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nodeConfigC, nil) defer nodeC.StopAndWait() port := nodeC.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port @@ -158,15 +158,15 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigB.Feed.Input = *newBroadcastClientConfigTest(port) nodeConfigB.DataAvailability = nodeConfigA.DataAvailability nodeConfigB.DataAvailability.RPCAggregator.Enable = false - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2infoA.ArbInitData, nodeConfigB, nil) + l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nodeConfigB, nil) defer nodeB.StopAndWait() - l2infoA.GenerateAccount("FraudUser") - l2infoA.GenerateAccount("RealUser") + testNodeA.L2Info.GenerateAccount("FraudUser") + testNodeA.L2Info.GenerateAccount("RealUser") - fraudTx := l2infoA.PrepareTx("Owner", "FraudUser", l2infoA.TransferGas, big.NewInt(1e12), nil) - l2infoA.GetInfoWithPrivKey("Owner").Nonce -= 1 // Use same l2info object for different l2s - realTx := l2infoA.PrepareTx("Owner", "RealUser", l2infoA.TransferGas, big.NewInt(1e12), nil) + fraudTx := testNodeA.L2Info.PrepareTx("Owner", "FraudUser", testNodeA.L2Info.TransferGas, big.NewInt(1e12), nil) + testNodeA.L2Info.GetInfoWithPrivKey("Owner").Nonce -= 1 // Use same l2info object for different l2s + realTx := testNodeA.L2Info.PrepareTx("Owner", "RealUser", testNodeA.L2Info.TransferGas, big.NewInt(1e12), nil) err := l2clientC.SendTransaction(ctx, fraudTx) if err != nil { @@ -183,7 +183,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { if err != nil { t.Fatal("error waiting for tx:", err) } - l2balance, err := l2clientB.BalanceAt(ctx, l2infoA.GetAddress("FraudUser"), nil) + l2balance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("FraudUser"), nil) if err != nil { t.Fatal("error getting balance:", err) } @@ -192,12 +192,12 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { } // Send the real transaction to client A - err = l2clientA.SendTransaction(ctx, realTx) + err = testNodeA.L2Client.SendTransaction(ctx, realTx) if err != nil { t.Fatal("error sending real transaction:", err) } - _, err = EnsureTxSucceeded(ctx, l2clientA, realTx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, realTx) if err != nil { t.Fatal("error ensuring real transaction succeeded:", err) } @@ -207,7 +207,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { if err != nil { t.Fatal("error waiting for transaction to get to node b:", err) } - l2balanceFraudAcct, err := l2clientB.BalanceAt(ctx, l2infoA.GetAddress("FraudUser"), nil) + l2balanceFraudAcct, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("FraudUser"), nil) if err != nil { t.Fatal("error getting fraud balance:", err) } @@ -215,7 +215,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { t.Fatal("Unexpected balance (fraud acct should be empty) was:", l2balanceFraudAcct) } - l2balanceRealAcct, err := l2clientB.BalanceAt(ctx, l2infoA.GetAddress("RealUser"), nil) + l2balanceRealAcct, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("RealUser"), nil) if err != nil { t.Fatal("error getting real balance:", err) } diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index bf3e7c86c..c7583ff1f 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -47,18 +47,18 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { if validator { conf.BlockValidator.Enable = true } - l2Info, arbNode, _, l1Info, l1backend, l1Client, l1stack := createTestNodeOnL1WithConfig(t, ctx, false, conf, nil, nil) - l2Backend := arbNode.Execution.Backend - defer requireClose(t, l1stack) - defer arbNode.StopAndWait() + testNode := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(false).CreateTestNodeOnL1AndL2(t) + l2Backend := testNode.L2Node.Execution.Backend + defer requireClose(t, testNode.L1Stack) + defer testNode.L2Node.StopAndWait() - l1BlockChain := l1backend.BlockChain() + l1BlockChain := testNode.L1Backend.BlockChain() - seqInbox, err := bridgegen.NewSequencerInbox(l1Info.GetAddress("SequencerInbox"), l1Client) + seqInbox, err := bridgegen.NewSequencerInbox(testNode.L1Info.GetAddress("SequencerInbox"), testNode.L1Client) Require(t, err) - seqOpts := l1Info.GetDefaultTransactOpts("Sequencer", ctx) + seqOpts := testNode.L1Info.GetDefaultTransactOpts("Sequencer", ctx) - ownerAddress := l2Info.GetAddress("Owner") + ownerAddress := testNode.L2Info.GetAddress("Owner") var startL2BlockNumber uint64 = 0 startState, _, err := l2Backend.APIBackend().StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) @@ -91,10 +91,10 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { } var faucetTxs []*types.Transaction for _, acct := range accounts { - l1Info.GenerateAccount(acct) - faucetTxs = append(faucetTxs, l1Info.PrepareTx("Faucet", acct, 30000, big.NewInt(1e16), nil)) + testNode.L1Info.GenerateAccount(acct) + faucetTxs = append(faucetTxs, testNode.L1Info.PrepareTx("Faucet", acct, 30000, big.NewInt(1e16), nil)) } - SendWaitTestTransactions(t, ctx, l1Client, faucetTxs) + SendWaitTestTransactions(t, ctx, testNode.L1Client, faucetTxs) for i := 1; i < seqInboxTestIters; i++ { if i%10 == 0 { @@ -106,7 +106,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { // The miner usually collects transactions from deleted blocks and puts them in the mempool. // However, this code doesn't run on reorgs larger than 64 blocks for performance reasons. // Therefore, we make a bunch of small blocks to prevent the code from running. - padAddr := l1Info.GetAddress("ReorgPadding") + padAddr := testNode.L1Info.GetAddress("ReorgPadding") for j := uint64(0); j < 70; j++ { rawTx := &types.DynamicFeeTx{ To: &padAddr, @@ -115,12 +115,12 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { Value: new(big.Int), Nonce: j, } - tx := l1Info.SignTxAs("ReorgPadding", rawTx) - Require(t, l1Client.SendTransaction(ctx, tx)) - _, _ = EnsureTxSucceeded(ctx, l1Client, tx) + tx := testNode.L1Info.SignTxAs("ReorgPadding", rawTx) + Require(t, testNode.L1Client.SendTransaction(ctx, tx)) + _, _ = EnsureTxSucceeded(ctx, testNode.L1Client, tx) } reorgTargetNumber := blockStates[reorgTo].l1BlockNumber - currentHeader, err := l1Client.HeaderByNumber(ctx, nil) + currentHeader, err := testNode.L1Client.HeaderByNumber(ctx, nil) Require(t, err) if currentHeader.Number.Int64()-int64(reorgTargetNumber) < 65 { Fatal(t, "Less than 65 blocks of difference between current block", currentHeader.Number, "and target", reorgTargetNumber) @@ -135,10 +135,10 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { // Sometimes, this causes it to drop the next tx. // To work around this, we create a sacrificial tx, which may or may not succeed. // Whichever happens, by the end of this block, the miner will have processed the reorg. - tx := l1Info.PrepareTx(fmt.Sprintf("ReorgSacrifice%v", i/10), "Faucet", 30000, big.NewInt(0), nil) - err = l1Client.SendTransaction(ctx, tx) + tx := testNode.L1Info.PrepareTx(fmt.Sprintf("ReorgSacrifice%v", i/10), "Faucet", 30000, big.NewInt(0), nil) + err = testNode.L1Client.SendTransaction(ctx, tx) Require(t, err) - _, _ = WaitForTx(ctx, l1Client, tx.Hash(), time.Second) + _, _ = WaitForTx(ctx, testNode.L1Client, tx.Hash(), time.Second) } else { state := blockStates[len(blockStates)-1] newBalances := make(map[common.Address]*big.Int) @@ -166,10 +166,10 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { var dest common.Address if j == 0 && amount.Cmp(reserveAmount) >= 0 { name := accountName(len(state.accounts)) - if !l2Info.HasAccount(name) { - l2Info.GenerateAccount(name) + if !testNode.L2Info.HasAccount(name) { + testNode.L2Info.GenerateAccount(name) } - dest = l2Info.GetAddress(name) + dest = testNode.L2Info.GetAddress(name) state.accounts = append(state.accounts, dest) state.balances[dest] = big.NewInt(0) } else { @@ -184,7 +184,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { Nonce: state.nonces[source], } state.nonces[source]++ - tx := l2Info.SignTxAs(accountName(sourceNum), rawTx) + tx := testNode.L2Info.SignTxAs(accountName(sourceNum), rawTx) txData, err := tx.MarshalBinary() Require(t, err) var segment []byte @@ -204,7 +204,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { seqNonce := len(blockStates) - 1 for j := 0; ; j++ { - haveNonce, err := l1Client.PendingNonceAt(ctx, seqOpts.From) + haveNonce, err := testNode.L1Client.PendingNonceAt(ctx, seqOpts.From) Require(t, err) if haveNonce == uint64(seqNonce) { break @@ -222,15 +222,15 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { tx, err = seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(int64(len(blockStates))), batchData, big.NewInt(1), common.Address{}) } Require(t, err) - txRes, err := EnsureTxSucceeded(ctx, l1Client, tx) + txRes, err := EnsureTxSucceeded(ctx, testNode.L1Client, tx) if err != nil { // Geth's clique miner is finicky. // Unfortunately this is so rare that I haven't had an opportunity to test this workaround. // Specifically, I suspect there's a race where it thinks there's no txs to put in the new block, // if a new tx arrives at the same time as it tries to create a block. // Resubmit the transaction in an attempt to get the miner going again. - _ = l1Client.SendTransaction(ctx, tx) - txRes, err = EnsureTxSucceeded(ctx, l1Client, tx) + _ = testNode.L1Client.SendTransaction(ctx, tx) + txRes, err = EnsureTxSucceeded(ctx, testNode.L1Client, tx) Require(t, err) } @@ -267,9 +267,9 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { if validator && i%15 == 0 { for i := 0; ; i++ { - expectedPos, err := arbNode.Execution.ExecEngine.BlockNumberToMessageIndex(expectedBlockNumber) + expectedPos, err := testNode.L2Node.Execution.ExecEngine.BlockNumberToMessageIndex(expectedBlockNumber) Require(t, err) - lastValidated := arbNode.BlockValidator.Validated(t) + lastValidated := testNode.L2Node.BlockValidator.Validated(t) if lastValidated == expectedPos+1 { break } else if i >= 1000 { diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 96ea1ee2e..3a45b5390 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -64,9 +64,9 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) types.NewArbitrumSigner(types.NewLondonSigner(l2chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), transferGas, ) - _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, l2chainConfig, nil, nil, l2info) - defer requireClose(t, l1stack) - defer l2nodeA.StopAndWait() + testNodeA := NewNodeBuilder(ctx).SetIsSequencer(true).SetChainConfig(l2chainConfig).SetL2Info(l2info).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNodeA.L1Stack) + defer testNodeA.L2Node.StopAndWait() if faultyStaker { l2info.GenerateGenesisAccount("FaultyAddr", common.Big1) @@ -75,10 +75,10 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) config.Sequencer.Enable = false config.DelayedSequencer.Enable = false config.BatchPoster.Enable = false - _, l2nodeB := Create2ndNodeWithConfig(t, ctx, l2nodeA, l1stack, l1info, &l2info.ArbInitData, config, nil) + _, l2nodeB := Create2ndNodeWithConfig(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &l2info.ArbInitData, config, nil) defer l2nodeB.StopAndWait() - nodeAGenesis := l2nodeA.Execution.Backend.APIBackend().CurrentHeader().Hash() + nodeAGenesis := testNodeA.L2Node.Execution.Backend.APIBackend().CurrentHeader().Hash() nodeBGenesis := l2nodeB.Execution.Backend.APIBackend().CurrentHeader().Hash() if faultyStaker { if nodeAGenesis == nodeBGenesis { @@ -90,51 +90,51 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } } - BridgeBalance(t, "Faucet", big.NewInt(1).Mul(big.NewInt(params.Ether), big.NewInt(10000)), l1info, l2info, l1client, l2clientA, ctx) + testNodeA.BridgeBalance(t, "Faucet", big.NewInt(1).Mul(big.NewInt(params.Ether), big.NewInt(10000))) - deployAuth := l1info.GetDefaultTransactOpts("RollupOwner", ctx) + deployAuth := testNodeA.L1Info.GetDefaultTransactOpts("RollupOwner", ctx) balance := big.NewInt(params.Ether) balance.Mul(balance, big.NewInt(100)) - l1info.GenerateAccount("ValidatorA") - TransferBalance(t, "Faucet", "ValidatorA", balance, l1info, l1client, ctx) - l1authA := l1info.GetDefaultTransactOpts("ValidatorA", ctx) + testNodeA.L1Info.GenerateAccount("ValidatorA") + testNodeA.TransferBalanceViaL1(t, "Faucet", "ValidatorA", balance) + l1authA := testNodeA.L1Info.GetDefaultTransactOpts("ValidatorA", ctx) - l1info.GenerateAccount("ValidatorB") - TransferBalance(t, "Faucet", "ValidatorB", balance, l1info, l1client, ctx) - l1authB := l1info.GetDefaultTransactOpts("ValidatorB", ctx) + testNodeA.L1Info.GenerateAccount("ValidatorB") + testNodeA.TransferBalanceViaL1(t, "Faucet", "ValidatorB", balance) + l1authB := testNodeA.L1Info.GetDefaultTransactOpts("ValidatorB", ctx) - valWalletAddrAPtr, err := staker.GetValidatorWalletContract(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader, true) + valWalletAddrAPtr, err := staker.GetValidatorWalletContract(ctx, testNodeA.L2Node.DeployInfo.ValidatorWalletCreator, 0, &l1authA, testNodeA.L2Node.L1Reader, true) Require(t, err) valWalletAddrA := *valWalletAddrAPtr - valWalletAddrCheck, err := staker.GetValidatorWalletContract(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader, true) + valWalletAddrCheck, err := staker.GetValidatorWalletContract(ctx, testNodeA.L2Node.DeployInfo.ValidatorWalletCreator, 0, &l1authA, testNodeA.L2Node.L1Reader, true) Require(t, err) if valWalletAddrA == *valWalletAddrCheck { Require(t, err, "didn't cache validator wallet address", valWalletAddrA.String(), "vs", valWalletAddrCheck.String()) } - rollup, err := rollupgen.NewRollupAdminLogic(l2nodeA.DeployInfo.Rollup, l1client) + rollup, err := rollupgen.NewRollupAdminLogic(testNodeA.L2Node.DeployInfo.Rollup, testNodeA.L1Client) Require(t, err) tx, err := rollup.SetValidator(&deployAuth, []common.Address{valWalletAddrA, l1authB.From}, []bool{true, true}) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L1Client, tx) Require(t, err) tx, err = rollup.SetMinimumAssertionPeriod(&deployAuth, big.NewInt(1)) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L1Client, tx) Require(t, err) - validatorUtils, err := rollupgen.NewValidatorUtils(l2nodeA.DeployInfo.ValidatorUtils, l1client) + validatorUtils, err := rollupgen.NewValidatorUtils(testNodeA.L2Node.DeployInfo.ValidatorUtils, testNodeA.L1Client) Require(t, err) valConfig := staker.TestL1ValidatorConfig - dpA, err := arbnode.StakerDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) + dpA, err := arbnode.StakerDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), testNodeA.L2Node.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } - valWalletA, err := staker.NewContractValidatorWallet(dpA, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, &l1authA, 0, func(common.Address) {}, func() uint64 { return valConfig.ExtraGas }) + valWalletA, err := staker.NewContractValidatorWallet(dpA, nil, testNodeA.L2Node.DeployInfo.ValidatorWalletCreator, testNodeA.L2Node.DeployInfo.Rollup, testNodeA.L2Node.L1Reader, &l1authA, 0, func(common.Address) {}, func() uint64 { return valConfig.ExtraGas }) Require(t, err) if honestStakerInactive { valConfig.Strategy = "Defensive" @@ -146,11 +146,11 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) blockValidatorConfig := staker.TestBlockValidatorConfig statelessA, err := staker.NewStatelessBlockValidator( - l2nodeA.InboxReader, - l2nodeA.InboxTracker, - l2nodeA.TxStreamer, - l2nodeA.Execution.Recorder, - l2nodeA.ArbDB, + testNodeA.L2Node.InboxReader, + testNodeA.L2Node.InboxTracker, + testNodeA.L2Node.TxStreamer, + testNodeA.L2Node.Execution.Recorder, + testNodeA.L2Node.ArbDB, nil, StaticFetcherFrom(t, &blockValidatorConfig), valStack, @@ -159,7 +159,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) err = statelessA.Start(ctx) Require(t, err) stakerA, err := staker.NewStaker( - l2nodeA.L1Reader, + testNodeA.L2Node.L1Reader, valWalletA, bind.CallOpts{}, valConfig, @@ -167,7 +167,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) statelessA, nil, nil, - l2nodeA.DeployInfo.ValidatorUtils, + testNodeA.L2Node.DeployInfo.ValidatorUtils, nil, ) Require(t, err) @@ -217,15 +217,15 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) err = valWalletB.Initialize(ctx) Require(t, err) } - dpC, err := arbnode.StakerDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) + dpC, err := arbnode.StakerDataposter(rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), testNodeA.L2Node.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } - valWalletC, err := staker.NewContractValidatorWallet(dpC, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, nil, 0, func(common.Address) {}, func() uint64 { return 10000 }) + valWalletC, err := staker.NewContractValidatorWallet(dpC, nil, testNodeA.L2Node.DeployInfo.ValidatorWalletCreator, testNodeA.L2Node.DeployInfo.Rollup, testNodeA.L2Node.L1Reader, nil, 0, func(common.Address) {}, func() uint64 { return 10000 }) Require(t, err) valConfig.Strategy = "Watchtower" stakerC, err := staker.NewStaker( - l2nodeA.L1Reader, + testNodeA.L2Node.L1Reader, valWalletC, bind.CallOpts{}, valConfig, @@ -233,7 +233,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) statelessA, nil, nil, - l2nodeA.DeployInfo.ValidatorUtils, + testNodeA.L2Node.DeployInfo.ValidatorUtils, nil, ) Require(t, err) @@ -246,9 +246,9 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) l2info.GenerateAccount("BackgroundUser") tx = l2info.PrepareTx("Faucet", "BackgroundUser", l2info.TransferGas, balance, nil) - err = l2clientA.SendTransaction(ctx, tx) + err = testNodeA.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2clientA, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) Require(t, err) // Continually make L2 transactions in a background thread @@ -260,7 +260,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) })() go (func() { defer close(backgroundTxsShutdownChan) - err := makeBackgroundTxs(backgroundTxsCtx, l2info, l2clientA) + err := makeBackgroundTxs(backgroundTxsCtx, l2info, testNodeA.L2Client) if !errors.Is(err, context.Canceled) { log.Warn("error making background txs", "err", err) } @@ -303,26 +303,26 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) if !challengeMangerTimedOut { // Upgrade the ChallengeManager contract to an implementation which says challenges are always timed out - mockImpl, tx, _, err := mocksgen.DeployTimedOutChallengeManager(&deployAuth, l1client) + mockImpl, tx, _, err := mocksgen.DeployTimedOutChallengeManager(&deployAuth, testNodeA.L1Client) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L1Client, tx) Require(t, err) managerAddr := valWalletA.ChallengeManagerAddress() // 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 proxyAdminSlot := common.BigToHash(arbmath.BigSub(crypto.Keccak256Hash([]byte("eip1967.proxy.admin")).Big(), common.Big1)) - proxyAdminBytes, err := l1client.StorageAt(ctx, managerAddr, proxyAdminSlot, nil) + proxyAdminBytes, err := testNodeA.L1Client.StorageAt(ctx, managerAddr, proxyAdminSlot, nil) Require(t, err) proxyAdminAddr := common.BytesToAddress(proxyAdminBytes) if proxyAdminAddr == (common.Address{}) { Fatal(t, "failed to get challenge manager proxy admin") } - proxyAdmin, err := mocksgen.NewProxyAdminForBinding(proxyAdminAddr, l1client) + proxyAdmin, err := mocksgen.NewProxyAdminForBinding(proxyAdminAddr, testNodeA.L1Client) Require(t, err) tx, err = proxyAdmin.Upgrade(&deployAuth, managerAddr, mockImpl) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L1Client, tx) Require(t, err) challengeMangerTimedOut = true @@ -342,11 +342,11 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } Require(t, err, "Staker", stakerName, "failed to act") if tx != nil { - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L1Client, tx) Require(t, err, "EnsureTxSucceeded failed for staker", stakerName, "tx") } if faultyStaker { - conflictInfo, err := validatorUtils.FindStakerConflict(&bind.CallOpts{}, l2nodeA.DeployInfo.Rollup, l1authA.From, l1authB.From, big.NewInt(1024)) + conflictInfo, err := validatorUtils.FindStakerConflict(&bind.CallOpts{}, testNodeA.L2Node.DeployInfo.Rollup, l1authA.From, l1authB.From, big.NewInt(1024)) Require(t, err) if staker.ConflictType(conflictInfo.Ty) == staker.CONFLICT_TYPE_FOUND { cancelBackgroundTxs() @@ -378,7 +378,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err) } for j := 0; j < 5; j++ { - TransferBalance(t, "Faucet", "Faucet", common.Big0, l1info, l1client, ctx) + testNodeA.TransferBalanceViaL1(t, "Faucet", "Faucet", common.Big0) } } diff --git a/system_tests/twonodes_test.go b/system_tests/twonodes_test.go index 72de2aa50..b9be59a19 100644 --- a/system_tests/twonodes_test.go +++ b/system_tests/twonodes_test.go @@ -20,24 +20,24 @@ func testTwoNodesSimple(t *testing.T, dasModeStr string) { chainConfig, l1NodeConfigA, lifecycleManager, _, dasSignerKey := setupConfigWithDAS(t, ctx, dasModeStr) defer lifecycleManager.StopAndWaitUntil(time.Second) - l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, chainConfig, nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + testNodeA := NewNodeBuilder(ctx).SetNodeConfig(l1NodeConfigA).SetChainConfig(chainConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNodeA.L1Stack) + defer testNodeA.L2Node.StopAndWait() - authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) + authorizeDASKeyset(t, ctx, dasSignerKey, testNodeA.L1Info, testNodeA.L1Client) l1NodeConfigBDataAvailability := l1NodeConfigA.DataAvailability l1NodeConfigBDataAvailability.RPCAggregator.Enable = false - l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, &l1NodeConfigBDataAvailability) + l2clientB, nodeB := Create2ndNode(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, &l1NodeConfigBDataAvailability) defer nodeB.StopAndWait() - l2info.GenerateAccount("User2") + testNodeA.L2Info.GenerateAccount("User2") - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) + tx := testNodeA.L2Info.PrepareTx("Owner", "User2", testNodeA.L2Info.TransferGas, big.NewInt(1e12), nil) - err := l2clientA.SendTransaction(ctx, tx) + err := testNodeA.L2Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2clientA, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) Require(t, err) // give the inbox reader a bit of time to pick up the delayed message @@ -45,15 +45,15 @@ func testTwoNodesSimple(t *testing.T, dasModeStr string) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ + testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } _, err = WaitForTx(ctx, l2clientB, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { diff --git a/system_tests/twonodeslong_test.go b/system_tests/twonodeslong_test.go index 0cac9d644..2dde9a512 100644 --- a/system_tests/twonodeslong_test.go +++ b/system_tests/twonodeslong_test.go @@ -42,32 +42,32 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { chainConfig, l1NodeConfigA, lifecycleManager, _, dasSignerKey := setupConfigWithDAS(t, ctx, dasModeStr) defer lifecycleManager.StopAndWaitUntil(time.Second) - l2info, nodeA, l2client, l1info, l1backend, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, chainConfig, nil) - defer requireClose(t, l1stack) + testNodeA := NewNodeBuilder(ctx).SetNodeConfig(l1NodeConfigA).SetChainConfig(chainConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, testNodeA.L1Stack) - authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) + authorizeDASKeyset(t, ctx, dasSignerKey, testNodeA.L1Info, testNodeA.L1Client) l1NodeConfigBDataAvailability := l1NodeConfigA.DataAvailability l1NodeConfigBDataAvailability.RPCAggregator.Enable = false - l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, &l1NodeConfigBDataAvailability) + l2clientB, nodeB := Create2ndNode(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, &l1NodeConfigBDataAvailability) defer nodeB.StopAndWait() - l2info.GenerateAccount("DelayedFaucet") - l2info.GenerateAccount("DelayedReceiver") - l2info.GenerateAccount("DirectReceiver") + testNodeA.L2Info.GenerateAccount("DelayedFaucet") + testNodeA.L2Info.GenerateAccount("DelayedReceiver") + testNodeA.L2Info.GenerateAccount("DirectReceiver") - l2info.GenerateAccount("ErrorTxSender") + testNodeA.L2Info.GenerateAccount("ErrorTxSender") - SendWaitTestTransactions(t, ctx, l2client, []*types.Transaction{ - l2info.PrepareTx("Faucet", "ErrorTxSender", l2info.TransferGas, big.NewInt(l2pricing.InitialBaseFeeWei*int64(l2info.TransferGas)), nil), + SendWaitTestTransactions(t, ctx, testNodeA.L2Client, []*types.Transaction{ + testNodeA.L2Info.PrepareTx("Faucet", "ErrorTxSender", testNodeA.L2Info.TransferGas, big.NewInt(l2pricing.InitialBaseFeeWei*int64(testNodeA.L2Info.TransferGas)), nil), }) delayedMsgsToSendMax := big.NewInt(int64(largeLoops * avgDelayedMessagesPerLoop * 10)) delayedFaucetNeeds := new(big.Int).Mul(new(big.Int).Add(fundsPerDelayed, new(big.Int).SetUint64(l2pricing.InitialBaseFeeWei*100000)), delayedMsgsToSendMax) - SendWaitTestTransactions(t, ctx, l2client, []*types.Transaction{ - l2info.PrepareTx("Faucet", "DelayedFaucet", l2info.TransferGas, delayedFaucetNeeds, nil), + SendWaitTestTransactions(t, ctx, testNodeA.L2Client, []*types.Transaction{ + testNodeA.L2Info.PrepareTx("Faucet", "DelayedFaucet", testNodeA.L2Info.TransferGas, delayedFaucetNeeds, nil), }) - delayedFaucetBalance, err := l2client.BalanceAt(ctx, l2info.GetAddress("DelayedFaucet"), nil) + delayedFaucetBalance, err := testNodeA.L2Client.BalanceAt(ctx, testNodeA.L2Info.GetAddress("DelayedFaucet"), nil) Require(t, err) if delayedFaucetBalance.Cmp(delayedFaucetNeeds) != 0 { @@ -85,17 +85,17 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { randNum := rand.Int() % avgTotalL1MessagesPerLoop var l1tx *types.Transaction if randNum < avgDelayedMessagesPerLoop { - delayedTx := l2info.PrepareTx("DelayedFaucet", "DelayedReceiver", 30001, fundsPerDelayed, nil) - l1tx = WrapL2ForDelayed(t, delayedTx, l1info, "User", 100000) + delayedTx := testNodeA.L2Info.PrepareTx("DelayedFaucet", "DelayedReceiver", 30001, fundsPerDelayed, nil) + l1tx = WrapL2ForDelayed(t, delayedTx, testNodeA.L1Info, "User", 100000) delayedTxs = append(delayedTxs, delayedTx) delayedTransfers++ } else { - l1tx = l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) + l1tx = testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) } l1Txs = append(l1Txs, l1tx) } // adding multiple messages in the same AddLocal to get them in the same L1 block - errs := l1backend.TxPool().AddLocals(l1Txs) + errs := testNodeA.L1Backend.TxPool().AddLocals(l1Txs) for _, err := range errs { if err != nil { Fatal(t, err) @@ -104,26 +104,26 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { l2TxsThisTime := rand.Int() % (avgL2MsgsPerLoop * 2) l2Txs := make([]*types.Transaction, 0, l2TxsThisTime) for len(l2Txs) < l2TxsThisTime { - l2Txs = append(l2Txs, l2info.PrepareTx("Faucet", "DirectReceiver", l2info.TransferGas, fundsPerDirect, nil)) + l2Txs = append(l2Txs, testNodeA.L2Info.PrepareTx("Faucet", "DirectReceiver", testNodeA.L2Info.TransferGas, fundsPerDirect, nil)) } - SendWaitTestTransactions(t, ctx, l2client, l2Txs) + SendWaitTestTransactions(t, ctx, testNodeA.L2Client, l2Txs) directTransfers += int64(l2TxsThisTime) if len(l1Txs) > 0 { - _, err := EnsureTxSucceeded(ctx, l1client, l1Txs[len(l1Txs)-1]) + _, err := EnsureTxSucceeded(ctx, testNodeA.L1Client, l1Txs[len(l1Txs)-1]) if err != nil { Fatal(t, err) } } // create bad tx on delayed inbox - l2info.GetInfoWithPrivKey("ErrorTxSender").Nonce = 10 - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - WrapL2ForDelayed(t, l2info.PrepareTx("ErrorTxSender", "DelayedReceiver", 30002, delayedFaucetNeeds, nil), l1info, "User", 100000), + testNodeA.L2Info.GetInfoWithPrivKey("ErrorTxSender").Nonce = 10 + SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ + WrapL2ForDelayed(t, testNodeA.L2Info.PrepareTx("ErrorTxSender", "DelayedReceiver", 30002, delayedFaucetNeeds, nil), testNodeA.L1Info, "User", 100000), }) extrBlocksThisTime := rand.Int() % (avgExtraBlocksPerLoop * 2) for i := 0; i < extrBlocksThisTime; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ + testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } } @@ -137,38 +137,38 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { for i := 0; i < finalPropagateLoops; i++ { var tx *types.Transaction for j := 0; j < 30; j++ { - tx = l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) - err := l1client.SendTransaction(ctx, tx) + tx = testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) + err := testNodeA.L1Client.SendTransaction(ctx, tx) if err != nil { Fatal(t, err) } - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = EnsureTxSucceeded(ctx, testNodeA.L1Client, tx) if err != nil { Fatal(t, err) } } } - _, err = EnsureTxSucceededWithTimeout(ctx, l2client, delayedTxs[len(delayedTxs)-1], time.Second*10) + _, err = EnsureTxSucceededWithTimeout(ctx, testNodeA.L2Client, delayedTxs[len(delayedTxs)-1], time.Second*10) Require(t, err, "Failed waiting for Tx on main node") _, err = EnsureTxSucceededWithTimeout(ctx, l2clientB, delayedTxs[len(delayedTxs)-1], time.Second*10) Require(t, err, "Failed waiting for Tx on secondary node") - delayedBalance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("DelayedReceiver"), nil) + delayedBalance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("DelayedReceiver"), nil) Require(t, err) - directBalance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("DirectReceiver"), nil) + directBalance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("DirectReceiver"), nil) Require(t, err) delayedExpectd := new(big.Int).Mul(fundsPerDelayed, big.NewInt(delayedTransfers)) directExpectd := new(big.Int).Mul(fundsPerDirect, big.NewInt(directTransfers)) if (delayedBalance.Cmp(delayedExpectd) != 0) || (directBalance.Cmp(directExpectd) != 0) { t.Error("delayed balance", delayedBalance, "expected", delayedExpectd, "transfers", delayedTransfers) t.Error("direct balance", directBalance, "expected", directExpectd, "transfers", directTransfers) - ownerBalance, _ := l2clientB.BalanceAt(ctx, l2info.GetAddress("Owner"), nil) - delayedFaucetBalance, _ := l2clientB.BalanceAt(ctx, l2info.GetAddress("DelayedFaucet"), nil) + ownerBalance, _ := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("Owner"), nil) + delayedFaucetBalance, _ := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("DelayedFaucet"), nil) t.Error("owner balance", ownerBalance, "delayed faucet", delayedFaucetBalance) Fatal(t, "Unexpected balance") } - nodeA.StopAndWait() + testNodeA.L2Node.StopAndWait() if nodeB.BlockValidator != nil { lastBlockHeader, err := l2clientB.HeaderByNumber(ctx, nil) From cf809ef57eb846c87c258fe180d4705635982eef Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 27 Sep 2023 10:07:17 -0600 Subject: [PATCH 180/775] Return RollupAddress from NoOp validator wallet --- arbnode/node.go | 2 +- staker/validatorwallet/noop.go | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 91c4e941f..a77ec6df3 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -820,7 +820,7 @@ func createNodeImpl( getExtraGas := func() uint64 { return configFetcher.Get().Staker.ExtraGas } // TODO: factor this out into separate helper, and split rest of node // creation into multiple helpers. - var wallet staker.ValidatorWalletInterface = validatorwallet.NewNoOp(l1client) + var wallet staker.ValidatorWalletInterface = validatorwallet.NewNoOp(l1client, deployInfo.Rollup) if !strings.EqualFold(config.Staker.Strategy, "watchtower") { if config.Staker.UseSmartContractWallet || txOptsValidator == nil { var existingWalletAddress *common.Address diff --git a/staker/validatorwallet/noop.go b/staker/validatorwallet/noop.go index 0a1e66d09..b050ebe86 100644 --- a/staker/validatorwallet/noop.go +++ b/staker/validatorwallet/noop.go @@ -17,11 +17,15 @@ import ( // NoOp validator wallet is used for watchtower mode. type NoOp struct { - l1Client arbutil.L1Interface + l1Client arbutil.L1Interface + rollupAddress common.Address } -func NewNoOp(l1Client arbutil.L1Interface) *NoOp { - return &NoOp{l1Client: l1Client} +func NewNoOp(l1Client arbutil.L1Interface, rollupAddress common.Address) *NoOp { + return &NoOp{ + l1Client: l1Client, + rollupAddress: rollupAddress, + } } func (*NoOp) Initialize(context.Context) error { return nil } @@ -44,7 +48,7 @@ func (*NoOp) TimeoutChallenges(ctx context.Context, challenges []uint64) (*types func (n *NoOp) L1Client() arbutil.L1Interface { return n.l1Client } -func (*NoOp) RollupAddress() common.Address { return common.Address{} } +func (n *NoOp) RollupAddress() common.Address { return n.rollupAddress } func (*NoOp) ChallengeManagerAddress() common.Address { return common.Address{} } From 099fe721de8f3b530d8a57ae007ac6f1785e1ac0 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 27 Sep 2023 10:09:51 -0600 Subject: [PATCH 181/775] Use NoOp validator wallet in watchtower test --- system_tests/staker_test.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 78fa7fa83..36b112d03 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -218,12 +218,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) err = valWalletB.Initialize(ctx) Require(t, err) } - dpC, err := arbnode.StakerDataposter(ctx, rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) - if err != nil { - t.Fatalf("Error creating validator dataposter: %v", err) - } - valWalletC, err := validatorwallet.NewContract(dpC, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, nil, 0, func(common.Address) {}, func() uint64 { return 10000 }) - Require(t, err) + valWalletC := validatorwallet.NewNoOp(l1client, l2nodeA.DeployInfo.Rollup) valConfig.Strategy = "Watchtower" stakerC, err := staker.NewStaker( l2nodeA.L1Reader, From 6eb1fb455e079f6965e04a7fc7228f20c5361ade Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Wed, 27 Sep 2023 11:03:52 -0700 Subject: [PATCH 182/775] Metrics for memory limit and usage --- arbnode/resourcemanager/resource_management.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arbnode/resourcemanager/resource_management.go b/arbnode/resourcemanager/resource_management.go index b8bbb1f3a..d90ce4a43 100644 --- a/arbnode/resourcemanager/resource_management.go +++ b/arbnode/resourcemanager/resource_management.go @@ -24,6 +24,8 @@ var ( limitCheckDurationHistogram = metrics.NewRegisteredHistogram("arb/rpc/limitcheck/duration", nil, metrics.NewBoundedHistogramSample()) limitCheckSuccessCounter = metrics.NewRegisteredCounter("arb/rpc/limitcheck/success", nil) limitCheckFailureCounter = metrics.NewRegisteredCounter("arb/rpc/limitcheck/failure", nil) + nitroMemLimit = metrics.GetOrRegisterGauge("arb/memory/limit", nil) + nitroMemUsage = metrics.GetOrRegisterGauge("arb/memory/usage", nil) errNotSupported = errors.New("not supported") ) @@ -236,7 +238,13 @@ func (c *cgroupsMemoryLimitChecker) isLimitExceeded() (bool, error) { if inactive, err = readFromMemStats(c.files.statsFile, c.files.inactiveRe); err != nil { return false, err } - return limit-(usage-(active+inactive)) <= c.memLimitBytes, nil + + memLimit := limit - c.memLimitBytes + memUsage := usage - (active + inactive) + nitroMemLimit.Update(int64(memLimit)) + nitroMemUsage.Update(int64(memUsage)) + + return memUsage >= memLimit, nil } func (c cgroupsMemoryLimitChecker) String() string { From 85ffd9e97e82802e78296c461c9b4a5ebd6fea5e Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Wed, 27 Sep 2023 11:06:19 -0700 Subject: [PATCH 183/775] Fix capitalization of log messages --- arbnode/resourcemanager/resource_management.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/resourcemanager/resource_management.go b/arbnode/resourcemanager/resource_management.go index d90ce4a43..cb1ae9d6e 100644 --- a/arbnode/resourcemanager/resource_management.go +++ b/arbnode/resourcemanager/resource_management.go @@ -48,7 +48,7 @@ func Init(conf *Config) error { var c limitChecker c, err := newCgroupsMemoryLimitCheckerIfSupported(limit) if errors.Is(err, errNotSupported) { - log.Error("no method for determining memory usage and limits was discovered, disabled memory limit RPC throttling") + log.Error("No method for determining memory usage and limits was discovered, disabled memory limit RPC throttling") c = &trivialLimitChecker{} } @@ -119,7 +119,7 @@ func (s *httpServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { exceeded, err := s.c.isLimitExceeded() limitCheckDurationHistogram.Update(time.Since(start).Nanoseconds()) if err != nil { - log.Error("error checking memory limit", "err", err, "checker", s.c) + log.Error("Error checking memory limit", "err", err, "checker", s.c.String()) } else if exceeded { http.Error(w, "Too many requests", http.StatusTooManyRequests) limitCheckFailureCounter.Inc(1) From c5bcb6e69daea056e39b56309ea196a7e4041a4d Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Wed, 27 Sep 2023 14:17:27 -0700 Subject: [PATCH 184/775] Add `merge_group` to workflows to prepare for merge queues --- .github/workflows/arbitrator-ci.yml | 1 + .github/workflows/arbitrator-skip-ci.yml | 1 + .github/workflows/ci.yml | 1 + .github/workflows/codeql-analysis.yml | 2 ++ .github/workflows/docker.yml | 1 + 5 files changed, 6 insertions(+) diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index ae2517185..f2b141fb4 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -3,6 +3,7 @@ run-name: Arbitrator CI triggered from @${{ github.actor }} of ${{ github.head_r on: workflow_dispatch: + merge_group: pull_request: paths: - 'arbitrator/**' diff --git a/.github/workflows/arbitrator-skip-ci.yml b/.github/workflows/arbitrator-skip-ci.yml index 6dfd962ee..75fb47d0a 100644 --- a/.github/workflows/arbitrator-skip-ci.yml +++ b/.github/workflows/arbitrator-skip-ci.yml @@ -2,6 +2,7 @@ name: Arbitrator skip CI run-name: Arbitrator skip CI triggered from @${{ github.actor }} of ${{ github.head_ref }} on: + merge_group: pull_request: paths-ignore: - 'arbitrator/**' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0f5251f9..0734aecfd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,7 @@ run-name: Go tests CI triggered from @${{ github.actor }} of ${{ github.head_ref on: workflow_dispatch: + merge_group: pull_request: push: branches: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e4aacdcd6..cfb5b6eda 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -14,6 +14,8 @@ name: "CodeQL" on: push: branches: [ "master" ] + merge_group: + branches: [ "master" ] pull_request: # The branches below must be a subset of the branches above branches: [ "master" ] diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d391dd409..6192f65a4 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -3,6 +3,7 @@ run-name: Docker build CI triggered from @${{ github.actor }} of ${{ github.head on: workflow_dispatch: + merge_group: pull_request: push: branches: From d665734eb651a0462a7516c0bb66292f83311ab0 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Wed, 27 Sep 2023 14:55:52 -0700 Subject: [PATCH 185/775] Update contracts pin --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 23fe920ed..f5da19efe 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 23fe920edb52ff1185f7706d59ada82616a0d32a +Subproject commit f5da19efe8a477129c33ba49b11f96ab60e3b1f6 From 01dc7b8e7c151ba0ccd15ddf00b7e4d41eef0c09 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Wed, 27 Sep 2023 15:18:54 -0700 Subject: [PATCH 186/775] Updates for geth v1.12.1 statedb.Commit added a block number field in upstream geth in 88f3d6146, pass in zero to it in InitializeArbosInDatabase. Trie Clean Cache file was removed in upstream geth 59f7b289c, remove our uses of its fields and pruner arguments related to it. The unused error code from stack.Attach() was removed in upstream geth in acc2a2ac61 Tx pool code moved to subpool (legacypool) in upstream geth d40a255e97 period param was removed from core.DeveloperGenesisBlock upstream in ea782809f7 --- arbos/arbosState/initialize.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbos/arbosState/initialize.go b/arbos/arbosState/initialize.go index 9f24d9676..a428cad7f 100644 --- a/arbos/arbosState/initialize.go +++ b/arbos/arbosState/initialize.go @@ -58,7 +58,7 @@ func InitializeArbosInDatabase(db ethdb.Database, initData statetransfer.InitDat } commit := func() (common.Hash, error) { - root, err := statedb.Commit(true) + root, err := statedb.Commit(0, true) if err != nil { return common.Hash{}, err } From 4f1c974f7a53b9a339ca526e0cd695428cfa181e Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Mon, 14 Aug 2023 14:11:52 -0700 Subject: [PATCH 187/775] Plumb batch limit options to geth Upstream implemented limits on the number of requests in a batch and the maximum batch response size. We had already implemented the batch response size limit in our geth fork, but have rolled it back in favor of upstream. This commit adds a nitro option for the batch request limit and takes the existing size limit option and plumbs them through to geth's node.Config. The flags in Nitro are: --rpc.max-batch-response-size --rpc.batch-request-limit --- cmd/genericconf/config.go | 10 +++++++--- cmd/nitro/nitro.go | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cmd/genericconf/config.go b/cmd/genericconf/config.go index 8e75b6177..9c02fbb9a 100644 --- a/cmd/genericconf/config.go +++ b/cmd/genericconf/config.go @@ -8,7 +8,7 @@ import ( "time" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/node" flag "github.com/spf13/pflag" ) @@ -107,16 +107,20 @@ func FileLoggingConfigAddOptions(prefix string, f *flag.FlagSet) { type RpcConfig struct { MaxBatchResponseSize int `koanf:"max-batch-response-size"` + BatchRequestLimit int `koanf:"batch-request-limit"` } var DefaultRpcConfig = RpcConfig{ MaxBatchResponseSize: 10_000_000, // 10MB + BatchRequestLimit: node.DefaultConfig.BatchRequestLimit, } -func (c *RpcConfig) Apply() { - rpc.MaxBatchResponseSize = c.MaxBatchResponseSize +func (c *RpcConfig) Apply(stackConf *node.Config) { + stackConf.BatchResponseMaxSize = c.MaxBatchResponseSize + stackConf.BatchRequestLimit = c.BatchRequestLimit } func RpcConfigAddOptions(prefix string, f *flag.FlagSet) { f.Int(prefix+".max-batch-response-size", DefaultRpcConfig.MaxBatchResponseSize, "the maximum response size for a JSON-RPC request measured in bytes (-1 means no limit)") + f.Int(prefix+".batch-request-limit", DefaultRpcConfig.BatchRequestLimit, "the maximum number of requests in a batch") } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 1a984b525..d3ecc720c 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -162,6 +162,7 @@ func mainImpl() int { stackConf := node.DefaultConfig stackConf.DataDir = nodeConfig.Persistent.Chain stackConf.DBEngine = "leveldb" + nodeConfig.Rpc.Apply(&stackConf) nodeConfig.HTTP.Apply(&stackConf) nodeConfig.WS.Apply(&stackConf) nodeConfig.Auth.Apply(&stackConf) @@ -757,7 +758,6 @@ func ParseNode(ctx context.Context, args []string) (*NodeConfig, *genericconf.Wa if err != nil { return nil, nil, nil, err } - nodeConfig.Rpc.Apply() return &nodeConfig, &l1Wallet, &l2DevWallet, nil } From 1c4810e804b2f0fd11467abe30b93ea77b536f4b Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 27 Sep 2023 23:32:05 +0000 Subject: [PATCH 188/775] improve error fmt --- cmd/conf/database.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/conf/database.go b/cmd/conf/database.go index dcd54784f..b049375d6 100644 --- a/cmd/conf/database.go +++ b/cmd/conf/database.go @@ -92,7 +92,7 @@ func DatabaseInDirectory(path string) bool { func (c *PersistentConfig) Validate() error { // we are validating .db-engine here to avoid unintended behaviour as empty string value also has meaning in geth's node.Config.DBEngine if c.DBEngine != "leveldb" && c.DBEngine != "pebble" { - return fmt.Errorf("Invalid .db-engine choice: \"%v\", allowed \"leveldb\" or \"pebble\"", c.DBEngine) + return fmt.Errorf(`invalid .db-engine choice: %q, allowed "leveldb" or "pebble"`, c.DBEngine) } return nil } From be91de71991c59d1e2d778ccdb7cda996266185d Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 27 Sep 2023 17:42:13 -0600 Subject: [PATCH 189/775] Only warn if we hit an issue polling for batch reverts --- arbnode/batch_poster.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 4f50831e6..57147eb94 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -331,7 +331,7 @@ func (b *BatchPoster) pollForReverts(ctx context.Context) { reverted, err := b.checkReverts(ctx, blockNum) if err != nil { - logLevel := log.Error + logLevel := log.Warn if strings.Contains(err.Error(), "not found") { // Just parent chain node inconsistency // One node sent us a block, but another didn't have it From 7bf3e0550c8ed7cfa1274b476c4ddfadaea90e84 Mon Sep 17 00:00:00 2001 From: Fionna Chan Date: Thu, 28 Sep 2023 08:20:11 +0800 Subject: [PATCH 190/775] Update logo on README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2cfef3de6..67a182ec3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

- Logo + Logo

Arbitrum Nitro

@@ -14,7 +14,7 @@ ## About Arbitrum Nitro -Logo +Logo Nitro is the latest iteration of the Arbitrum technology. It is a fully integrated, complete layer 2 optimistic rollup system, including fraud proofs, the sequencer, the token bridges, From 291f88942c8cf4f22bc093ca11b515224060e2b3 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 28 Sep 2023 10:08:07 -0500 Subject: [PATCH 191/775] address PR comments --- arbcompress/compress_common.go | 2 +- arbcompress/compress_test.go | 2 +- arbitrator/prover/test-cases/go/main.go | 3 +- arbnode/execution/tx_pre_checker.go | 6 ++- arbos/arbosState/arbosstate.go | 52 ++++++++++++++++--------- arbos/block_processor.go | 6 ++- arbos/l1pricing/l1pricing.go | 51 +++++++----------------- arbos/tx_processor.go | 6 ++- nodeInterface/NodeInterface.go | 12 +++++- nodeInterface/virtual-contracts.go | 7 +++- precompiles/ArbOwner.go | 2 +- precompiles/ArbOwnerPublic.go | 2 +- system_tests/fees_test.go | 2 +- system_tests/state_fuzz_test.go | 3 +- 14 files changed, 86 insertions(+), 70 deletions(-) diff --git a/arbcompress/compress_common.go b/arbcompress/compress_common.go index 7d3976d56..990fd2e2b 100644 --- a/arbcompress/compress_common.go +++ b/arbcompress/compress_common.go @@ -10,6 +10,6 @@ func compressedBufferSizeFor(length int) int { return length + (length>>10)*8 + 64 // actual limit is: length + (length >> 14) * 4 + 6 } -func CompressFast(input []byte, level int) ([]byte, error) { +func CompressLevel(input []byte, level int) ([]byte, error) { return compressLevel(input, level) } diff --git a/arbcompress/compress_test.go b/arbcompress/compress_test.go index 88e7eb4eb..21629d966 100644 --- a/arbcompress/compress_test.go +++ b/arbcompress/compress_test.go @@ -27,7 +27,7 @@ func testCompressDecompress(t *testing.T, data []byte) { } testDecompress(t, compressedWell, data) - compressedFast, err := CompressFast(data, 0) + compressedFast, err := CompressLevel(data, 0) if err != nil { t.Fatal(err) } diff --git a/arbitrator/prover/test-cases/go/main.go b/arbitrator/prover/test-cases/go/main.go index 8df8b2255..6efcf2c2d 100644 --- a/arbitrator/prover/test-cases/go/main.go +++ b/arbitrator/prover/test-cases/go/main.go @@ -13,7 +13,6 @@ import ( merkletree "github.com/wealdtech/go-merkletree" "github.com/offchainlabs/nitro/arbcompress" - "github.com/offchainlabs/nitro/arbos/l1pricing" ) // MerkleSample is an example using the Merkle tree to generate and verify proofs. @@ -43,7 +42,7 @@ func MerkleSample(data [][]byte, toproove int) (bool, error) { } func testCompression(data []byte) { - compressed, err := arbcompress.CompressFast(data, l1pricing.InitialBrotliCompressionLevel) + compressed, err := arbcompress.CompressLevel(data, 0) if err != nil { panic(err) } diff --git a/arbnode/execution/tx_pre_checker.go b/arbnode/execution/tx_pre_checker.go index 968a1f266..12471ed19 100644 --- a/arbnode/execution/tx_pre_checker.go +++ b/arbnode/execution/tx_pre_checker.go @@ -188,7 +188,11 @@ func PreCheckTx(bc *core.BlockChain, chainConfig *params.ChainConfig, header *ty if config.Strictness >= TxPreCheckerStrictnessFullValidation && tx.Nonce() > stateNonce { return MakeNonceError(sender, tx.Nonce(), stateNonce) } - dataCost, _ := arbos.L1PricingState().GetPosterInfo(tx, l1pricing.BatchPosterAddress) + brotliCompressionLevel, err := arbos.BrotliCompressionLevel() + if err != nil { + return fmt.Errorf("failed to get brotliCompressionLevel: %w", err) + } + dataCost, _ := arbos.L1PricingState().GetPosterInfo(tx, l1pricing.BatchPosterAddress, brotliCompressionLevel) dataGas := arbmath.BigDiv(dataCost, header.BaseFee) if tx.Gas() < intrinsic+dataGas.Uint64() { return core.ErrIntrinsicGas diff --git a/arbos/arbosState/arbosstate.go b/arbos/arbosState/arbosstate.go index c87d0f224..a47f4e790 100644 --- a/arbos/arbosState/arbosstate.go +++ b/arbos/arbosState/arbosstate.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/offchainlabs/nitro/arbcompress" "github.com/offchainlabs/nitro/arbos/addressSet" "github.com/offchainlabs/nitro/arbos/addressTable" "github.com/offchainlabs/nitro/arbos/arbostypes" @@ -35,23 +36,24 @@ import ( // persisted beyond the end of the test.) type ArbosState struct { - arbosVersion uint64 // version of the ArbOS storage format and semantics - upgradeVersion storage.StorageBackedUint64 // version we're planning to upgrade to, or 0 if not planning to upgrade - upgradeTimestamp storage.StorageBackedUint64 // when to do the planned upgrade - networkFeeAccount storage.StorageBackedAddress - l1PricingState *l1pricing.L1PricingState - l2PricingState *l2pricing.L2PricingState - retryableState *retryables.RetryableState - addressTable *addressTable.AddressTable - chainOwners *addressSet.AddressSet - sendMerkle *merkleAccumulator.MerkleAccumulator - blockhashes *blockhash.Blockhashes - chainId storage.StorageBackedBigInt - chainConfig storage.StorageBackedBytes - genesisBlockNum storage.StorageBackedUint64 - infraFeeAccount storage.StorageBackedAddress - backingStorage *storage.Storage - Burner burn.Burner + arbosVersion uint64 // version of the ArbOS storage format and semantics + upgradeVersion storage.StorageBackedUint64 // version we're planning to upgrade to, or 0 if not planning to upgrade + upgradeTimestamp storage.StorageBackedUint64 // when to do the planned upgrade + networkFeeAccount storage.StorageBackedAddress + l1PricingState *l1pricing.L1PricingState + l2PricingState *l2pricing.L2PricingState + retryableState *retryables.RetryableState + addressTable *addressTable.AddressTable + chainOwners *addressSet.AddressSet + sendMerkle *merkleAccumulator.MerkleAccumulator + blockhashes *blockhash.Blockhashes + chainId storage.StorageBackedBigInt + chainConfig storage.StorageBackedBytes + genesisBlockNum storage.StorageBackedUint64 + infraFeeAccount storage.StorageBackedAddress + brotliCompressionLevel storage.StorageBackedUint64 // brotli compression level used for pricing + backingStorage *storage.Storage + Burner burn.Burner } var ErrUninitializedArbOS = errors.New("ArbOS uninitialized") @@ -82,6 +84,7 @@ func OpenArbosState(stateDB vm.StateDB, burner burn.Burner) (*ArbosState, error) backingStorage.OpenStorageBackedBytes(chainConfigSubspace), backingStorage.OpenStorageBackedUint64(uint64(genesisBlockNumOffset)), backingStorage.OpenStorageBackedAddress(uint64(infraFeeAccountOffset)), + backingStorage.OpenStorageBackedUint64(uint64(brotliCompressionLevelOffset)), backingStorage, burner, }, nil @@ -139,6 +142,7 @@ const ( chainIdOffset genesisBlockNumOffset infraFeeAccountOffset + brotliCompressionLevelOffset ) type SubspaceID []byte @@ -215,6 +219,7 @@ func InitializeArbosState(stateDB vm.StateDB, burner burn.Burner, chainConfig *p chainConfigStorage := sto.OpenStorageBackedBytes(chainConfigSubspace) _ = chainConfigStorage.Set(initMessage.SerializedChainConfig) _ = sto.SetUint64ByUint64(uint64(genesisBlockNumOffset), chainConfig.ArbitrumChainParams.GenesisBlockNum) + _ = sto.SetUint64ByUint64(uint64(brotliCompressionLevelOffset), 0) // default brotliCompressionLevel for fast compression is 0 initialRewardsRecipient := l1pricing.BatchPosterAddress if desiredArbosVersion >= 2 { @@ -328,7 +333,7 @@ func (state *ArbosState) UpgradeArbosVersion( ) } // Update Brotli compression level for fast compression from 0 to 1 - ensure(state.l1PricingState.SetBrotliCompressionLevel(1)) + ensure(state.SetBrotliCompressionLevel(1)) default: return fmt.Errorf( "the chain is upgrading to unsupported ArbOS version %v, %w", @@ -390,6 +395,17 @@ func (state *ArbosState) SetFormatVersion(val uint64) { state.Restrict(state.backingStorage.SetUint64ByUint64(uint64(versionOffset), val)) } +func (state *ArbosState) BrotliCompressionLevel() (uint64, error) { + return state.brotliCompressionLevel.Get() +} + +func (state *ArbosState) SetBrotliCompressionLevel(val uint64) error { + if val <= arbcompress.LEVEL_WELL { + return state.brotliCompressionLevel.Set(val) + } + return errors.New("invalid brotli compression level") +} + func (state *ArbosState) RetryableState() *retryables.RetryableState { return state.retryableState } diff --git a/arbos/block_processor.go b/arbos/block_processor.go index 87ecac9e7..3f7d357af 100644 --- a/arbos/block_processor.go +++ b/arbos/block_processor.go @@ -271,7 +271,11 @@ func ProduceBlockAdvanced( if basefee.Sign() > 0 { dataGas = math.MaxUint64 - posterCost, _ := state.L1PricingState().GetPosterInfo(tx, poster) + brotliCompressionLevel, err := state.BrotliCompressionLevel() + if err != nil { + return nil, nil, fmt.Errorf("failed to get brotliCompressionLevel: %w", err) + } + posterCost, _ := state.L1PricingState().GetPosterInfo(tx, poster, brotliCompressionLevel) posterCostInL2Gas := arbmath.BigDiv(posterCost, basefee) if posterCostInL2Gas.IsUint64() { diff --git a/arbos/l1pricing/l1pricing.go b/arbos/l1pricing/l1pricing.go index b9b9761b0..e506f7690 100644 --- a/arbos/l1pricing/l1pricing.go +++ b/arbos/l1pricing/l1pricing.go @@ -36,9 +36,8 @@ type L1PricingState struct { inertia storage.StorageBackedUint64 perUnitReward storage.StorageBackedUint64 // variables - lastUpdateTime storage.StorageBackedUint64 // timestamp of the last update from L1 that we processed - fundsDueForRewards storage.StorageBackedBigInt - brotliCompressionLevel storage.StorageBackedUint64 // brotli compression level used for pricing + lastUpdateTime storage.StorageBackedUint64 // timestamp of the last update from L1 that we processed + fundsDueForRewards storage.StorageBackedBigInt // funds collected since update are recorded as the balance in account L1PricerFundsPoolAddress unitsSinceUpdate storage.StorageBackedUint64 // calldata units collected for since last update pricePerUnit storage.StorageBackedBigUint // current price per calldata unit @@ -64,7 +63,6 @@ const ( perUnitRewardOffset lastUpdateTimeOffset fundsDueForRewardsOffset - brotliCompressionLevelOffset unitsSinceOffset pricePerUnitOffset lastSurplusOffset @@ -74,11 +72,10 @@ const ( ) const ( - InitialInertia = 10 - InitialPerUnitReward = 10 - InitialPerBatchGasCostV6 = 100_000 - InitialPerBatchGasCostV12 = 210_000 // overriden as part of the upgrade - InitialBrotliCompressionLevel = 0 + InitialInertia = 10 + InitialPerUnitReward = 10 + InitialPerBatchGasCostV6 = 100_000 + InitialPerBatchGasCostV12 = 210_000 // overriden as part of the upgrade ) // one minute at 100000 bytes / sec @@ -115,10 +112,6 @@ func InitializeL1PricingState(sto *storage.Storage, initialRewardsRecipient comm if err := pricePerUnit.SetSaturatingWithWarning(initialL1BaseFee, "initial L1 base fee (storing in price per unit)"); err != nil { return err } - brotliCompressionLevel := sto.OpenStorageBackedUint64(brotliCompressionLevelOffset) - if err := brotliCompressionLevel.Set(InitialBrotliCompressionLevel); err != nil { - return err - } return nil } @@ -132,7 +125,6 @@ func OpenL1PricingState(sto *storage.Storage) *L1PricingState { sto.OpenStorageBackedUint64(perUnitRewardOffset), sto.OpenStorageBackedUint64(lastUpdateTimeOffset), sto.OpenStorageBackedBigInt(fundsDueForRewardsOffset), - sto.OpenStorageBackedUint64(brotliCompressionLevelOffset), sto.OpenStorageBackedUint64(unitsSinceOffset), sto.OpenStorageBackedBigUint(pricePerUnitOffset), sto.OpenStorageBackedBigInt(lastSurplusOffset), @@ -262,17 +254,6 @@ func (ps *L1PricingState) SetL1FeesAvailable(val *big.Int) error { return ps.l1FeesAvailable.SetChecked(val) } -func (ps *L1PricingState) BrotliCompressionLevel() (uint64, error) { - return ps.brotliCompressionLevel.Get() -} - -func (ps *L1PricingState) SetBrotliCompressionLevel(val uint64) error { - if val <= arbcompress.LEVEL_WELL { - return ps.brotliCompressionLevel.Set(val) - } - return errors.New("invalid brotli compression level") -} - func (ps *L1PricingState) AddToL1FeesAvailable(delta *big.Int) (*big.Int, error) { old, err := ps.L1FeesAvailable() if err != nil { @@ -508,7 +489,7 @@ func (ps *L1PricingState) UpdateForBatchPosterSpending( return nil } -func (ps *L1PricingState) getPosterUnitsWithoutCache(tx *types.Transaction, posterAddr common.Address) uint64 { +func (ps *L1PricingState) getPosterUnitsWithoutCache(tx *types.Transaction, posterAddr common.Address, brotliCompressionLevel uint64) uint64 { if posterAddr != BatchPosterAddress { return 0 @@ -519,11 +500,7 @@ func (ps *L1PricingState) getPosterUnitsWithoutCache(tx *types.Transaction, post return 0 } - level, err := ps.BrotliCompressionLevel() - if err != nil { - panic(fmt.Sprintf("failed to get brotli compression level: %v", err)) - } - l1Bytes, err := byteCountAfterBrotliLevel(txBytes, int(level)) + l1Bytes, err := byteCountAfterBrotliLevel(txBytes, int(brotliCompressionLevel)) if err != nil { panic(fmt.Sprintf("failed to compress tx: %v", err)) } @@ -531,13 +508,13 @@ func (ps *L1PricingState) getPosterUnitsWithoutCache(tx *types.Transaction, post } // GetPosterInfo returns the poster cost and the calldata units for a transaction -func (ps *L1PricingState) GetPosterInfo(tx *types.Transaction, poster common.Address) (*big.Int, uint64) { +func (ps *L1PricingState) GetPosterInfo(tx *types.Transaction, poster common.Address, brotliCompressionLevel uint64) (*big.Int, uint64) { if poster != BatchPosterAddress { return common.Big0, 0 } units := atomic.LoadUint64(&tx.CalldataUnits) if units == 0 { - units = ps.getPosterUnitsWithoutCache(tx, poster) + units = ps.getPosterUnitsWithoutCache(tx, poster, brotliCompressionLevel) atomic.StoreUint64(&tx.CalldataUnits, units) } @@ -593,23 +570,23 @@ func makeFakeTxForMessage(message *core.Message) *types.Transaction { }) } -func (ps *L1PricingState) PosterDataCost(message *core.Message, poster common.Address) (*big.Int, uint64) { +func (ps *L1PricingState) PosterDataCost(message *core.Message, poster common.Address, brotliCompressionLevel uint64) (*big.Int, uint64) { tx := message.Tx if tx != nil { - return ps.GetPosterInfo(tx, poster) + return ps.GetPosterInfo(tx, poster, brotliCompressionLevel) } // Otherwise, we don't have an underlying transaction, so we're likely in gas estimation. // We'll instead make a fake tx from the message info we do have, and then pad our cost a bit to be safe. tx = makeFakeTxForMessage(message) - units := ps.getPosterUnitsWithoutCache(tx, poster) + units := ps.getPosterUnitsWithoutCache(tx, poster, brotliCompressionLevel) units = arbmath.UintMulByBips(units+estimationPaddingUnits, arbmath.OneInBips+estimationPaddingBasisPoints) pricePerUnit, _ := ps.PricePerUnit() return am.BigMulByUint(pricePerUnit, units), units } func byteCountAfterBrotliLevel(input []byte, level int) (uint64, error) { - compressed, err := arbcompress.CompressFast(input, level) + compressed, err := arbcompress.CompressLevel(input, level) if err != nil { return 0, err } diff --git a/arbos/tx_processor.go b/arbos/tx_processor.go index 0d44ac548..6ef994d65 100644 --- a/arbos/tx_processor.go +++ b/arbos/tx_processor.go @@ -410,7 +410,11 @@ func (p *TxProcessor) GasChargingHook(gasRemaining *uint64) (common.Address, err // Since tips go to the network, and not to the poster, we use the basefee. // Note, this only determines the amount of gas bought, not the price per gas. - posterCost, calldataUnits := p.state.L1PricingState().PosterDataCost(p.msg, poster) + brotliCompressionLevel, err := p.state.BrotliCompressionLevel() + if err != nil { + return common.Address{}, fmt.Errorf("failed to get brotliCompressionLevel: %w", err) + } + posterCost, calldataUnits := p.state.L1PricingState().PosterDataCost(p.msg, poster, brotliCompressionLevel) if calldataUnits > 0 { p.state.Restrict(p.state.L1PricingState().AddToUnitsSinceUpdate(calldataUnits)) } diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index f13f8ce6c..8351e3192 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -469,7 +469,11 @@ func (n NodeInterface) GasEstimateL1Component( // Compute the fee paid for L1 in L2 terms // See in GasChargingHook that this does not induce truncation error // - feeForL1, _ := pricing.PosterDataCost(msg, l1pricing.BatchPosterAddress) + brotliCompressionLevel, err := c.State.BrotliCompressionLevel() + if err != nil { + return 0, nil, nil, fmt.Errorf("failed to get brotliCompressionLevel: %w", err) + } + feeForL1, _ := pricing.PosterDataCost(msg, l1pricing.BatchPosterAddress, brotliCompressionLevel) feeForL1 = arbmath.BigMulByBips(feeForL1, arbos.GasEstimationL1PricePadding) gasForL1 := arbmath.BigDiv(feeForL1, baseFee).Uint64() return gasForL1, baseFee, l1BaseFeeEstimate, nil @@ -507,7 +511,11 @@ func (n NodeInterface) GasEstimateComponents( if err != nil { return 0, 0, nil, nil, err } - feeForL1, _ := pricing.PosterDataCost(msg, l1pricing.BatchPosterAddress) + brotliCompressionLevel, err := c.State.BrotliCompressionLevel() + if err != nil { + return 0, 0, nil, nil, fmt.Errorf("failed to get brotliCompressionLevel: %w", err) + } + feeForL1, _ := pricing.PosterDataCost(msg, l1pricing.BatchPosterAddress, brotliCompressionLevel) baseFee, err := c.State.L2PricingState().BaseFeeWei() if err != nil { diff --git a/nodeInterface/virtual-contracts.go b/nodeInterface/virtual-contracts.go index ee81c1c3e..71c327517 100644 --- a/nodeInterface/virtual-contracts.go +++ b/nodeInterface/virtual-contracts.go @@ -135,7 +135,12 @@ func init() { return } - posterCost, _ := state.L1PricingState().PosterDataCost(msg, l1pricing.BatchPosterAddress) + brotliCompressionLevel, err := state.BrotliCompressionLevel() + if err != nil { + log.Error("failed to get brotliCompressionLevel", "err", err) + return + } + posterCost, _ := state.L1PricingState().PosterDataCost(msg, l1pricing.BatchPosterAddress, brotliCompressionLevel) posterCostInL2Gas := arbos.GetPosterGas(state, header.BaseFee, msg.TxRunMode, posterCost) *gascap = arbmath.SaturatingUAdd(*gascap, posterCostInL2Gas) } diff --git a/precompiles/ArbOwner.go b/precompiles/ArbOwner.go index 2384bfbd8..166768940 100644 --- a/precompiles/ArbOwner.go +++ b/precompiles/ArbOwner.go @@ -143,7 +143,7 @@ func (con ArbOwner) SetAmortizedCostCapBips(c ctx, evm mech, cap uint64) error { } func (con ArbOwner) SetBrotliCompressionLevel(c ctx, evm mech, level uint64) error { - return c.State.L1PricingState().SetBrotliCompressionLevel(level) + return c.State.SetBrotliCompressionLevel(level) } func (con ArbOwner) ReleaseL1PricerSurplusFunds(c ctx, evm mech, maxWeiToRelease huge) (huge, error) { diff --git a/precompiles/ArbOwnerPublic.go b/precompiles/ArbOwnerPublic.go index 3952f221d..4064f41be 100644 --- a/precompiles/ArbOwnerPublic.go +++ b/precompiles/ArbOwnerPublic.go @@ -50,5 +50,5 @@ func (con ArbOwnerPublic) GetInfraFeeAccount(c ctx, evm mech) (addr, error) { // GetBrotliCompressionLevel gets the current brotli compression level used for fast compression func (con ArbOwnerPublic) GetBrotliCompressionLevel(c ctx, evm mech) (uint64, error) { - return c.State.L1PricingState().BrotliCompressionLevel() + return c.State.BrotliCompressionLevel() } diff --git a/system_tests/fees_test.go b/system_tests/fees_test.go index 21e326e65..ea7edc2ee 100644 --- a/system_tests/fees_test.go +++ b/system_tests/fees_test.go @@ -303,7 +303,7 @@ func TestSequencerPriceAdjustsFrom25Gwei(t *testing.T) { func compressedTxSize(t *testing.T, tx *types.Transaction) uint64 { txBin, err := tx.MarshalBinary() Require(t, err) - compressed, err := arbcompress.CompressFast(txBin, l1pricing.InitialBrotliCompressionLevel) + compressed, err := arbcompress.CompressLevel(txBin, 0) Require(t, err) return uint64(len(compressed)) } diff --git a/system_tests/state_fuzz_test.go b/system_tests/state_fuzz_test.go index 17aad870d..b14215fbf 100644 --- a/system_tests/state_fuzz_test.go +++ b/system_tests/state_fuzz_test.go @@ -24,7 +24,6 @@ import ( "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/arbos/arbosState" "github.com/offchainlabs/nitro/arbos/arbostypes" - "github.com/offchainlabs/nitro/arbos/l1pricing" "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbstate" "github.com/offchainlabs/nitro/statetransfer" @@ -175,7 +174,7 @@ func FuzzStateTransition(f *testing.F) { binary.BigEndian.PutUint64(seqBatch[32:40], uint64(len(delayedMessages))) if compressSeqMsg { seqBatch = append(seqBatch, arbstate.BrotliMessageHeaderByte) - seqMsgCompressed, err := arbcompress.CompressFast(seqMsg, l1pricing.InitialBrotliCompressionLevel) + seqMsgCompressed, err := arbcompress.CompressLevel(seqMsg, 0) if err != nil { panic(fmt.Sprintf("failed to compress sequencer message: %v", err)) } From 356564a8a0be04f40b9803ea7089a5f6952e106c Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 28 Sep 2023 10:21:37 -0500 Subject: [PATCH 192/775] update contracts pin --- Makefile | 2 +- contracts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index ca299df2e..56bf4df3c 100644 --- a/Makefile +++ b/Makefile @@ -212,7 +212,7 @@ $(arbitrator_jit): $(DEP_PREDICATE) .make/cbrotli-lib $(jit_files) $(arbitrator_cases)/rust/target/wasm32-wasi/release/%.wasm: $(arbitrator_cases)/rust/src/bin/%.rs $(arbitrator_cases)/rust/src/lib.rs cargo build --manifest-path $(arbitrator_cases)/rust/Cargo.toml --release --target wasm32-wasi --bin $(patsubst $(arbitrator_cases)/rust/target/wasm32-wasi/release/%.wasm,%, $@) -$(arbitrator_cases)/go/main: $(arbitrator_cases)/go/main.go .make/solgen +$(arbitrator_cases)/go/main: $(arbitrator_cases)/go/main.go cd $(arbitrator_cases)/go && GOOS=js GOARCH=wasm go build main.go $(arbitrator_generated_header): $(DEP_PREDICATE) arbitrator/prover/src/lib.rs arbitrator/prover/src/utils.rs diff --git a/contracts b/contracts index 225b504e6..41c4303a8 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 225b504e6d801b15dcba93099339e6e74897714e +Subproject commit 41c4303a8e0a694da82a5ead0bcbf426c4f3cc6f From ed7c0fc8ba27c7d4922c1e37d119194a5176bc7a Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 28 Sep 2023 10:27:55 -0500 Subject: [PATCH 193/775] update contracts pin --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 41c4303a8..ae11e7a86 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 41c4303a8e0a694da82a5ead0bcbf426c4f3cc6f +Subproject commit ae11e7a86488e28c706e062ae501bfb7157197c1 From 3234af9e88e4e360731b65b3269f5f5c2934d99d Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 28 Sep 2023 10:48:46 -0500 Subject: [PATCH 194/775] fix error message --- arbnode/execution/tx_pre_checker.go | 2 +- arbos/block_processor.go | 2 +- arbos/tx_processor.go | 2 +- nodeInterface/NodeInterface.go | 4 ++-- nodeInterface/virtual-contracts.go | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arbnode/execution/tx_pre_checker.go b/arbnode/execution/tx_pre_checker.go index 12471ed19..7d9e26d16 100644 --- a/arbnode/execution/tx_pre_checker.go +++ b/arbnode/execution/tx_pre_checker.go @@ -190,7 +190,7 @@ func PreCheckTx(bc *core.BlockChain, chainConfig *params.ChainConfig, header *ty } brotliCompressionLevel, err := arbos.BrotliCompressionLevel() if err != nil { - return fmt.Errorf("failed to get brotliCompressionLevel: %w", err) + return fmt.Errorf("failed to get brotli compression level: %w", err) } dataCost, _ := arbos.L1PricingState().GetPosterInfo(tx, l1pricing.BatchPosterAddress, brotliCompressionLevel) dataGas := arbmath.BigDiv(dataCost, header.BaseFee) diff --git a/arbos/block_processor.go b/arbos/block_processor.go index 3f7d357af..6f87864b6 100644 --- a/arbos/block_processor.go +++ b/arbos/block_processor.go @@ -273,7 +273,7 @@ func ProduceBlockAdvanced( dataGas = math.MaxUint64 brotliCompressionLevel, err := state.BrotliCompressionLevel() if err != nil { - return nil, nil, fmt.Errorf("failed to get brotliCompressionLevel: %w", err) + return nil, nil, fmt.Errorf("failed to get brotli compression level: %w", err) } posterCost, _ := state.L1PricingState().GetPosterInfo(tx, poster, brotliCompressionLevel) posterCostInL2Gas := arbmath.BigDiv(posterCost, basefee) diff --git a/arbos/tx_processor.go b/arbos/tx_processor.go index 6ef994d65..3572042a0 100644 --- a/arbos/tx_processor.go +++ b/arbos/tx_processor.go @@ -412,7 +412,7 @@ func (p *TxProcessor) GasChargingHook(gasRemaining *uint64) (common.Address, err brotliCompressionLevel, err := p.state.BrotliCompressionLevel() if err != nil { - return common.Address{}, fmt.Errorf("failed to get brotliCompressionLevel: %w", err) + return common.Address{}, fmt.Errorf("failed to get brotli compression level: %w", err) } posterCost, calldataUnits := p.state.L1PricingState().PosterDataCost(p.msg, poster, brotliCompressionLevel) if calldataUnits > 0 { diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index 8351e3192..d79534583 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -471,7 +471,7 @@ func (n NodeInterface) GasEstimateL1Component( // brotliCompressionLevel, err := c.State.BrotliCompressionLevel() if err != nil { - return 0, nil, nil, fmt.Errorf("failed to get brotliCompressionLevel: %w", err) + return 0, nil, nil, fmt.Errorf("failed to get brotli compression level: %w", err) } feeForL1, _ := pricing.PosterDataCost(msg, l1pricing.BatchPosterAddress, brotliCompressionLevel) feeForL1 = arbmath.BigMulByBips(feeForL1, arbos.GasEstimationL1PricePadding) @@ -513,7 +513,7 @@ func (n NodeInterface) GasEstimateComponents( } brotliCompressionLevel, err := c.State.BrotliCompressionLevel() if err != nil { - return 0, 0, nil, nil, fmt.Errorf("failed to get brotliCompressionLevel: %w", err) + return 0, 0, nil, nil, fmt.Errorf("failed to get brotli compression level: %w", err) } feeForL1, _ := pricing.PosterDataCost(msg, l1pricing.BatchPosterAddress, brotliCompressionLevel) diff --git a/nodeInterface/virtual-contracts.go b/nodeInterface/virtual-contracts.go index 71c327517..ec375699b 100644 --- a/nodeInterface/virtual-contracts.go +++ b/nodeInterface/virtual-contracts.go @@ -137,7 +137,7 @@ func init() { brotliCompressionLevel, err := state.BrotliCompressionLevel() if err != nil { - log.Error("failed to get brotliCompressionLevel", "err", err) + log.Error("failed to get brotli compression level", "err", err) return } posterCost, _ := state.L1PricingState().PosterDataCost(msg, l1pricing.BatchPosterAddress, brotliCompressionLevel) From 520bdb9799cf598a707fe47ce8082a3b558e6372 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Thu, 28 Sep 2023 11:53:21 -0500 Subject: [PATCH 195/775] Update header_reader.go --- util/headerreader/header_reader.go | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index 2bd8f198a..75eb145a4 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -312,18 +312,10 @@ func (s *HeaderReader) logIfHeaderIsOld() { headerTime := time.Since(l1Timetamp) if headerTime >= s.config().OldHeaderTimeout { s.setError(fmt.Errorf("latest header is at least %v old", headerTime)) - // Upgrade the log level from warn to error when losing connection to L1 for too long - if headerTime >= DefaultConfig.OldHeaderTimeout { - log.Error( - "latest L1 block is old", "l1Block", storedHeader.Number, - "l1Timestamp", l1Timetamp, "age", headerTime, - ) - } else { - log.Warn( - "latest L1 block is old", "l1Block", storedHeader.Number, - "l1Timestamp", l1Timetamp, "age", headerTime, - ) - } + log.Error( + "latest L1 block is old", "l1Block", storedHeader.Number, + "l1Timestamp", l1Timetamp, "age", headerTime, + ) } } From 4ec56e30588328303c1f918195e616f49c35d49e Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 28 Sep 2023 20:15:28 +0200 Subject: [PATCH 196/775] Update nitro-contracts ref --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 97cfbe00f..7dc1aa438 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 97cfbe00ff0eea4d7f5f5f3afb01598c19ddabc4 +Subproject commit 7dc1aa43829d9f4afe7251ad28d96a5d0e1d48c7 From 826813e2a8f480458db187d7c2e1c0d95274753a Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Thu, 28 Sep 2023 11:28:23 -0700 Subject: [PATCH 197/775] Update dependancies to make dependabot happy --- go.mod | 69 ++++++++++++++++--------------- go.sum | 126 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 97 insertions(+), 98 deletions(-) diff --git a/go.mod b/go.mod index cc31c4a23..4bc28b950 100644 --- a/go.mod +++ b/go.mod @@ -18,18 +18,21 @@ require ( github.com/cavaliergopher/grab/v3 v3.0.1 github.com/codeclysm/extract/v3 v3.0.2 github.com/dgraph-io/badger/v3 v3.2103.2 + github.com/enescakir/emoji v1.0.0 github.com/ethereum/go-ethereum v1.10.26 github.com/fatih/structtag v1.2.0 + github.com/gdamore/tcell/v2 v2.6.0 github.com/google/go-cmp v0.5.9 - github.com/hashicorp/golang-lru/v2 v2.0.1 - github.com/ipfs/go-cid v0.3.2 + github.com/hashicorp/golang-lru/v2 v2.0.2 + github.com/ipfs/go-cid v0.4.1 github.com/ipfs/go-libipfs v0.6.2 github.com/ipfs/interface-go-ipfs-core v0.11.0 github.com/ipfs/kubo v0.19.1 github.com/knadh/koanf v1.4.0 - github.com/libp2p/go-libp2p v0.26.4 - github.com/multiformats/go-multiaddr v0.8.0 + github.com/libp2p/go-libp2p v0.27.8 + github.com/multiformats/go-multiaddr v0.9.0 github.com/multiformats/go-multihash v0.2.1 + github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 github.com/spf13/pflag v1.0.5 github.com/wealdtech/go-merkletree v1.0.0 golang.org/x/term v0.6.0 @@ -43,7 +46,7 @@ require ( bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc // indirect github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect github.com/DataDog/zstd v1.5.2 // indirect - github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a // indirect + github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1 // indirect @@ -72,7 +75,7 @@ require ( github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 // indirect github.com/cockroachdb/redact v1.1.3 // indirect - github.com/containerd/cgroups v1.0.4 // indirect + github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect @@ -88,29 +91,27 @@ require ( github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/enescakir/emoji v1.0.0 // indirect github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gammazero/deque v0.2.1 // indirect github.com/gdamore/encoding v1.0.0 // indirect - github.com/gdamore/tcell/v2 v2.6.0 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.3.0 // indirect github.com/golang/glog v1.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/flatbuffers v1.12.1 // indirect github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20221203041831-ce31453925ec // indirect + github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect @@ -169,16 +170,16 @@ require ( github.com/jbenet/goprocess v0.1.4 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5 // indirect - github.com/klauspost/compress v1.15.15 // indirect - github.com/klauspost/cpuid/v2 v2.2.3 // indirect - github.com/koron/go-ssdp v0.0.3 // indirect + github.com/klauspost/compress v1.16.4 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/koron/go-ssdp v0.0.4 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-doh-resolver v0.4.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect - github.com/libp2p/go-libp2p-asn-util v0.2.0 // indirect + github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect github.com/libp2p/go-libp2p-kad-dht v0.21.1 // indirect github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect github.com/libp2p/go-libp2p-pubsub v0.9.0 // indirect @@ -196,7 +197,7 @@ require ( github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/miekg/dns v1.1.50 // indirect + github.com/miekg/dns v1.1.53 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect github.com/minio/sha256-simd v1.0.0 // indirect @@ -208,11 +209,11 @@ require ( github.com/multiformats/go-base36 v0.2.0 // indirect github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect - github.com/multiformats/go-multibase v0.1.1 // indirect - github.com/multiformats/go-multicodec v0.7.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multicodec v0.8.1 // indirect github.com/multiformats/go-multistream v0.4.1 // indirect github.com/multiformats/go-varint v0.0.7 // indirect - github.com/onsi/ginkgo/v2 v2.5.1 // indirect + github.com/onsi/ginkgo/v2 v2.9.2 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/openzipkin/zipkin-go v0.4.0 // indirect @@ -221,22 +222,20 @@ require ( github.com/polydawn/refmt v0.89.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.39.0 // indirect + github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-19 v0.2.1 // indirect - github.com/quic-go/qtls-go1-20 v0.1.1 // indirect + github.com/quic-go/qtls-go1-19 v0.3.3 // indirect + github.com/quic-go/qtls-go1-20 v0.2.3 // indirect github.com/quic-go/quic-go v0.33.0 // indirect github.com/quic-go/webtransport-go v0.5.2 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/rhnvrm/simples3 v0.6.1 // indirect - github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 // indirect github.com/rivo/uniseg v0.4.3 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/samber/lo v1.36.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/stretchr/testify v1.8.2 // indirect github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa // indirect @@ -258,17 +257,17 @@ require ( go.opentelemetry.io/otel/trace v1.7.0 // indirect go.opentelemetry.io/proto/otlp v0.16.0 // indirect go.uber.org/atomic v1.10.0 // indirect - go.uber.org/dig v1.15.0 // indirect - go.uber.org/fx v1.18.2 // indirect - go.uber.org/multierr v1.9.0 // indirect + go.uber.org/dig v1.16.1 // indirect + go.uber.org/fx v1.19.2 // indirect + go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.24.0 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect - golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect - golang.org/x/mod v0.9.0 // indirect + golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect + golang.org/x/mod v0.10.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect - google.golang.org/grpc v1.46.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect + google.golang.org/grpc v1.53.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect lukechampine.com/blake3 v1.1.7 // indirect nhooyr.io/websocket v1.8.7 // indirect @@ -300,10 +299,10 @@ require ( github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c - github.com/huin/goupnp v1.0.3 // indirect + github.com/huin/goupnp v1.1.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mitchellh/mapstructure v1.4.2 github.com/mitchellh/pointerstructure v1.2.0 // indirect @@ -315,7 +314,7 @@ require ( github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect - golang.org/x/crypto v0.6.0 + golang.org/x/crypto v0.7.0 golang.org/x/net v0.8.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.7.0 diff --git a/go.sum b/go.sum index 4362d4b01..db3935001 100644 --- a/go.sum +++ b/go.sum @@ -73,8 +73,9 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a h1:E/8AP5dFtMhl5KPJz66Kt9G0n+7Sn41Fy1wv9/jHOrc= github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 h1:iW0a5ljuFxkLGPNem5Ui+KBjFJzKg4Fv2fnxe4dvzpM= github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h1:Y2QMoi1vgtOIfc+6DhrMOGkLoGzqSV2rKp4Sm+opsyA= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= @@ -231,8 +232,8 @@ github.com/codeclysm/extract/v3 v3.0.2 h1:sB4LcE3Php7LkhZwN0n2p8GCwZe92PEQutdbGU github.com/codeclysm/extract/v3 v3.0.2/go.mod h1:NKsw+hqua9H+Rlwy/w/3Qgt9jDonYEgB6wJu+25eOKw= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= -github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= +github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= +github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -402,8 +403,9 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= @@ -474,8 +476,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -517,8 +520,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20221203041831-ce31453925ec h1:fR20TYVVwhK4O7r7y+McjRYyaTH6/vjwJOajE+XhlzM= -github.com/google/pprof v0.0.0-20221203041831-ce31453925ec/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b h1:Qcx5LM0fSiks9uCyFZwDBUasd3lxd1RM0GYpL+Li5o4= +github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -596,8 +599,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru/v2 v2.0.1 h1:5pv5N1lT1fjLg2VQ5KWc7kmucp2x/kvFOnxuVTqZ6x4= -github.com/hashicorp/golang-lru/v2 v2.0.1/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU= +github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -615,8 +618,8 @@ github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c/go.mod h1:SC8Ryt github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= -github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= +github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= +github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -652,8 +655,8 @@ github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67Fexh github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o= -github.com/ipfs/go-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc= -github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw= +github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= +github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q= github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA= github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= @@ -902,21 +905,21 @@ github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU= +github.com/klauspost/compress v1.16.4/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= -github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/knadh/koanf v1.4.0 h1:/k0Bh49SqLyLNfte9r6cvuZWrApOQhglOmhIU3L/zDw= github.com/knadh/koanf v1.4.0/go.mod h1:1cfH5223ZeZUOs8FU2UdTmaNfHpqgtjV0+NHjRO43gs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8= -github.com/koron/go-ssdp v0.0.3/go.mod h1:b2MxI6yh02pKrsyNoQUsk4+YNikaGhe4894J+Q5lDvA= +github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= +github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -960,10 +963,10 @@ github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xS github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= github.com/libp2p/go-libp2p v0.14.3/go.mod h1:d12V4PdKbpL0T1/gsUNN8DfgMuRPDX8bS2QxCZlwRH0= -github.com/libp2p/go-libp2p v0.26.4 h1:VA9ChjN0n1BwwfU/dqx4Zj9ezXtIxGk8FyJPwFONqxs= -github.com/libp2p/go-libp2p v0.26.4/go.mod h1:x75BN32YbwuY0Awm2Uix4d4KOz+/4piInkp4Wr3yOo8= -github.com/libp2p/go-libp2p-asn-util v0.2.0 h1:rg3+Os8jbnO5DxkC7K/Utdi+DkY3q/d1/1q+8WeNAsw= -github.com/libp2p/go-libp2p-asn-util v0.2.0/go.mod h1:WoaWxbHKBymSN41hWSq/lGKJEca7TNm58+gGJi2WsLI= +github.com/libp2p/go-libp2p v0.27.8 h1:IX5x/4yKwyPQeVS2AXHZ3J4YATM9oHBGH1gBc23jBAI= +github.com/libp2p/go-libp2p v0.27.8/go.mod h1:eCFFtd0s5i/EVKR7+5Ki8bM7qwkNW3TPTTSSW9sz8NE= +github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= +github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= @@ -1178,10 +1181,9 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -1198,8 +1200,8 @@ github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= -github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= -github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= +github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw= +github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= @@ -1266,8 +1268,8 @@ github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= -github.com/multiformats/go-multiaddr v0.8.0 h1:aqjksEcqK+iD/Foe1RRFsGZh8+XFiGo7FgUCZlpv3LU= -github.com/multiformats/go-multiaddr v0.8.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= +github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= +github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= @@ -1287,11 +1289,11 @@ github.com/multiformats/go-multiaddr-net v0.1.5/go.mod h1:ilNnaM9HbmVFqsb/qcNysj github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= -github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI= -github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= -github.com/multiformats/go-multicodec v0.7.0 h1:rTUjGOwjlhGHbEMbPoSUJowG1spZTVsITRANCjKTUAQ= -github.com/multiformats/go-multicodec v0.7.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw= +github.com/multiformats/go-multicodec v0.8.1 h1:ycepHwavHafh3grIbR1jIXnKCsFm0fqsfEOsJ8NtKE8= +github.com/multiformats/go-multicodec v0.8.1/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= @@ -1345,8 +1347,8 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw= -github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= +github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= +github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -1354,7 +1356,7 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg= +github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -1426,8 +1428,8 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= -github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -1439,10 +1441,10 @@ github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJf github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A= -github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= -github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk= -github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= +github.com/quic-go/qtls-go1-19 v0.3.3 h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE= +github.com/quic-go/qtls-go1-19 v0.3.3/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= +github.com/quic-go/qtls-go1-20 v0.2.3 h1:m575dovXn1y2ATOb1XrRFcrv0F+EQmlowTkoraNkDPI= +github.com/quic-go/qtls-go1-20 v0.2.3/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0= github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= github.com/quic-go/webtransport-go v0.5.2 h1:GA6Bl6oZY+g/flt00Pnu0XtivSD8vukOu3lYhJjnGEk= @@ -1562,7 +1564,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= @@ -1695,10 +1696,10 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/dig v1.15.0 h1:vq3YWr8zRj1eFGC7Gvf907hE0eRjPTZ1d3xHadD6liE= -go.uber.org/dig v1.15.0/go.mod h1:pKHs0wMynzL6brANhB2hLMro+zalv1osARTviTcqHLM= -go.uber.org/fx v1.18.2 h1:bUNI6oShr+OVFQeU8cDNbnN7VFsu+SsjHzUF51V/GAU= -go.uber.org/fx v1.18.2/go.mod h1:g0V1KMQ66zIRk8bLu3Ea5Jt2w/cHlOIp4wdRsgh0JaY= +go.uber.org/dig v1.16.1 h1:+alNIBsl0qfY0j6epRubp/9obgtrObRAc5aD+6jbWY8= +go.uber.org/dig v1.16.1/go.mod h1:557JTAUZT5bUK0SvCwikmLPPtdQhfvLYtO5tJgQSbnk= +go.uber.org/fx v1.19.2 h1:SyFgYQFr1Wl0AYstE8vyYIzP4bFz2URrScjwC4cwUvY= +go.uber.org/fx v1.19.2/go.mod h1:43G1VcqSzbIv77y00p1DRAsyZS8WdzuYdhZXmEUkMyQ= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= @@ -1707,8 +1708,8 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/ go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= @@ -1754,8 +1755,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1766,8 +1767,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= -golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1792,8 +1793,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1850,7 +1851,6 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -1974,7 +1974,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2062,7 +2061,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= @@ -2138,8 +2136,9 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= @@ -2170,8 +2169,9 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.46.0 h1:oCjezcn6g6A75TGoKYBPgKmVBLexhYLM6MebdrPApP8= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -2186,8 +2186,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 2e778ff3d27c222d4b248d615600dab51a6c09d3 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 28 Sep 2023 15:56:20 -0500 Subject: [PATCH 198/775] update implementation and limit diff to a few testfiles for avoiding merge conflicts --- system_tests/aliasing_test.go | 26 +-- system_tests/arbtrace_test.go | 8 +- system_tests/batch_poster_test.go | 84 ++++---- system_tests/block_hash_test.go | 10 +- system_tests/block_validator_test.go | 56 ++--- system_tests/bloom_test.go | 22 +- system_tests/common_test.go | 258 +++++++++++++++++------ system_tests/conditionaltx_test.go | 128 ++++++------ system_tests/contract_tx_test.go | 17 +- system_tests/debugapi_test.go | 8 +- system_tests/delayedinbox_test.go | 14 +- system_tests/delayedinboxlong_test.go | 26 +-- system_tests/estimation_test.go | 75 ++++--- system_tests/fees_test.go | 72 +++---- system_tests/forwarder_test.go | 19 +- system_tests/infra_fee_test.go | 28 +-- system_tests/initialization_test.go | 6 +- system_tests/ipc_test.go | 6 +- system_tests/log_subscription_test.go | 15 +- system_tests/meaningless_reorg_test.go | 34 +-- system_tests/nodeinterface_test.go | 14 +- system_tests/outbox_test.go | 17 +- system_tests/precompile_test.go | 29 ++- system_tests/recreatestate_rpc_test.go | 20 +- system_tests/reorg_resequencing_test.go | 43 ++-- system_tests/retryable_test.go | 266 ++++++++++++------------ system_tests/seq_coordinator_test.go | 24 +-- system_tests/seq_nonce_test.go | 34 +-- system_tests/seq_pause_test.go | 21 +- system_tests/seq_reject_test.go | 44 ++-- system_tests/seq_whitelist_test.go | 18 +- system_tests/seqcompensation_test.go | 22 +- system_tests/seqfeed_test.go | 80 +++---- system_tests/seqinbox_test.go | 58 +++--- system_tests/staker_test.go | 86 ++++---- system_tests/transfer_test.go | 18 +- system_tests/twonodes_test.go | 24 +-- system_tests/twonodeslong_test.go | 68 +++--- 38 files changed, 960 insertions(+), 838 deletions(-) diff --git a/system_tests/aliasing_test.go b/system_tests/aliasing_test.go index d7513fe0c..5e4e65a2c 100644 --- a/system_tests/aliasing_test.go +++ b/system_tests/aliasing_test.go @@ -22,20 +22,20 @@ func TestAliasing(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() + l2info, node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) + defer requireClose(t, l1stack) + defer node.StopAndWait() - auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) - user := testNode.L1Info.GetDefaultTransactOpts("User", ctx) - testNode.TransferBalanceToViaL2(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18)) + auth := l2info.GetDefaultTransactOpts("Owner", ctx) + user := l1info.GetDefaultTransactOpts("User", ctx) + TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), l2info, l2client, ctx) - simpleAddr, simple := testNode.DeploySimple(t, auth) + simpleAddr, simple := deploySimple(t, ctx, auth, l2client) simpleContract, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) Require(t, err) // Test direct calls - arbsys, err := precompilesgen.NewArbSys(types.ArbSysAddress, testNode.L2Client) + arbsys, err := precompilesgen.NewArbSys(types.ArbSysAddress, l2client) Require(t, err) top, err := arbsys.IsTopLevelCall(nil) Require(t, err) @@ -56,14 +56,14 @@ func TestAliasing(t *testing.T) { // check via L2 tx, err := simple.CheckCalls(&auth, top, direct, static, delegate, callcode, call) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) // check signed txes via L1 data, err := simpleContract.Pack("checkCalls", top, direct, static, delegate, callcode, call) Require(t, err) - tx = testNode.L2Info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) - testNode.SendSignedTxViaL1(t, tx) + tx = l2info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) + SendSignedTxViaL1(t, ctx, l1info, l1client, l2client, tx) } testUnsigned := func(top, direct, static, delegate, callcode, call bool) { @@ -72,8 +72,8 @@ func TestAliasing(t *testing.T) { // check unsigned txes via L1 data, err := simpleContract.Pack("checkCalls", top, direct, static, delegate, callcode, call) Require(t, err) - tx := testNode.L2Info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) - testNode.SendUnsignedTxViaL1(t, tx) + tx := l2info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) + SendUnsignedTxViaL1(t, ctx, l1info, l1client, l2client, tx) } testL2Signed(true, true, false, false, false, false) diff --git a/system_tests/arbtrace_test.go b/system_tests/arbtrace_test.go index 50575500d..78907aa62 100644 --- a/system_tests/arbtrace_test.go +++ b/system_tests/arbtrace_test.go @@ -147,11 +147,11 @@ func TestArbTraceForwarding(t *testing.T) { nodeConfig := arbnode.ConfigDefaultL1Test() nodeConfig.RPC.ClassicRedirect = ipcPath nodeConfig.RPC.ClassicRedirectTimeout = time.Second - testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer requireClose(t, testNode.L2Stack) + _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, nil, nil) + defer requireClose(t, l1stack) + defer requireClose(t, l2stack) - l2rpc, _ := testNode.L2Stack.Attach() + l2rpc, _ := l2stack.Attach() txArgs := callTxArgs{} traceTypes := []string{"trace"} blockNum := rpc.BlockNumberOrHash{} diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index eab175b8e..ef50be6ec 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -48,41 +48,43 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { conf := arbnode.ConfigDefaultL1Test() conf.BatchPoster.Enable = false conf.BatchPoster.RedisUrl = redisUrl - testNodeA := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNodeA.L1Stack) - defer testNodeA.L2Node.StopAndWait() + builder := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true) + l1A, l2A := builder.BuildL2OnL1(t) + // testNodeA := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + defer requireClose(t, l1A.Stack) + defer l2A.Node.StopAndWait() - l2clientB, nodeB := Create2ndNode(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nil) - defer nodeB.StopAndWait() + l2B := builder.Build2ndNodeDAS(t, &l2A.Info.ArbInitData, nil) + defer l2B.Node.StopAndWait() - testNodeA.L2Info.GenerateAccount("User2") + l2A.Info.GenerateAccount("User2") var txs []*types.Transaction for i := 0; i < 100; i++ { - tx := testNodeA.L2Info.PrepareTx("Owner", "User2", testNodeA.L2Info.TransferGas, common.Big1, nil) + tx := l2A.Info.PrepareTx("Owner", "User2", l2A.Info.TransferGas, common.Big1, nil) txs = append(txs, tx) - err := testNodeA.L2Client.SendTransaction(ctx, tx) + err := l2A.Client.SendTransaction(ctx, tx) Require(t, err) } for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) + _, err := EnsureTxSucceeded(ctx, l2A.Client, tx) Require(t, err) } firstTxData, err := txs[0].MarshalBinary() Require(t, err) - seqTxOpts := testNodeA.L1Info.GetDefaultTransactOpts("Sequencer", ctx) + seqTxOpts := l1A.Info.GetDefaultTransactOpts("Sequencer", ctx) conf.BatchPoster.Enable = true conf.BatchPoster.MaxSize = len(firstTxData) * 2 - startL1Block, err := testNodeA.L1Client.BlockNumber(ctx) + startL1Block, err := l1A.Client.BlockNumber(ctx) Require(t, err) for i := 0; i < parallelBatchPosters; i++ { // Make a copy of the batch poster config so NewBatchPoster calling Validate() on it doesn't race batchPosterConfig := conf.BatchPoster - batchPoster, err := arbnode.NewBatchPoster(ctx, nil, testNodeA.L2Node.L1Reader, testNodeA.L2Node.InboxTracker, testNodeA.L2Node.TxStreamer, testNodeA.L2Node.SyncMonitor, func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, testNodeA.L2Node.DeployInfo, &seqTxOpts, nil) + batchPoster, err := arbnode.NewBatchPoster(ctx, nil, l2A.Node.L1Reader, l2A.Node.InboxTracker, l2A.Node.TxStreamer, l2A.Node.SyncMonitor, func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, l2A.Node.DeployInfo, &seqTxOpts, nil) Require(t, err) batchPoster.Start(ctx) defer batchPoster.StopAndWait() @@ -90,11 +92,11 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { lastTxHash := txs[len(txs)-1].Hash() for i := 90; i > 0; i-- { - SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ - testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, l1A.Client, []*types.Transaction{ + l1A.Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) time.Sleep(500 * time.Millisecond) - _, err := l2clientB.TransactionReceipt(ctx, lastTxHash) + _, err := l2B.Client.TransactionReceipt(ctx, lastTxHash) if err == nil { break } @@ -107,9 +109,9 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { // However, setting the clique period to 1 slows everything else (including the L1 deployment for this test) down to a crawl. if false { // Make sure the batch poster is able to post multiple batches in one block - endL1Block, err := testNodeA.L1Client.BlockNumber(ctx) + endL1Block, err := l1A.Client.BlockNumber(ctx) Require(t, err) - seqInbox, err := arbnode.NewSequencerInbox(testNodeA.L1Client, testNodeA.L2Node.DeployInfo.SequencerInbox, 0) + seqInbox, err := arbnode.NewSequencerInbox(l1A.Client, l2A.Node.DeployInfo.SequencerInbox, 0) Require(t, err) batches, err := seqInbox.LookupBatchesInRange(ctx, new(big.Int).SetUint64(startL1Block), new(big.Int).SetUint64(endL1Block)) Require(t, err) @@ -129,7 +131,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { } } - l2balance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("User2"), nil) + l2balance, err := l2B.Client.BalanceAt(ctx, l2A.Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Sign() == 0 { @@ -144,24 +146,25 @@ func TestBatchPosterLargeTx(t *testing.T) { conf := arbnode.ConfigDefaultL1Test() conf.Sequencer.MaxTxDataSize = 110000 - testNodeA := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNodeA.L1Stack) - defer testNodeA.L2Node.StopAndWait() + builder := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true) + l1A, l2A := builder.BuildL2OnL1(t) + defer requireClose(t, l1A.Stack) + defer l2A.Node.StopAndWait() - l2clientB, nodeB := Create2ndNode(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nil) - defer nodeB.StopAndWait() + l2B := builder.Build2ndNodeDAS(t, &l2A.Info.ArbInitData, nil) + defer l2B.Node.StopAndWait() data := make([]byte, 100000) _, err := rand.Read(data) Require(t, err) - faucetAddr := testNodeA.L2Info.GetAddress("Faucet") - gas := testNodeA.L2Info.TransferGas + 20000*uint64(len(data)) - tx := testNodeA.L2Info.PrepareTxTo("Faucet", &faucetAddr, gas, common.Big0, data) - err = testNodeA.L2Client.SendTransaction(ctx, tx) + faucetAddr := l2A.Info.GetAddress("Faucet") + gas := l2A.Info.TransferGas + 20000*uint64(len(data)) + tx := l2A.Info.PrepareTxTo("Faucet", &faucetAddr, gas, common.Big0, data) + err = l2A.Client.SendTransaction(ctx, tx) Require(t, err) - receiptA, err := EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) + receiptA, err := EnsureTxSucceeded(ctx, l2A.Client, tx) Require(t, err) - receiptB, err := EnsureTxSucceededWithTimeout(ctx, l2clientB, tx, time.Second*30) + receiptB, err := EnsureTxSucceededWithTimeout(ctx, l2B.Client, tx, time.Second*30) Require(t, err) if receiptA.BlockHash != receiptB.BlockHash { Fatal(t, "receipt A block hash", receiptA.BlockHash, "does not equal receipt B block hash", receiptB.BlockHash) @@ -177,21 +180,22 @@ func TestBatchPosterKeepsUp(t *testing.T) { conf.BatchPoster.CompressionLevel = brotli.BestCompression conf.BatchPoster.MaxDelay = time.Hour conf.RPC.RPCTxFeeCap = 1000. - testNodeA := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNodeA.L1Stack) - defer testNodeA.L2Node.StopAndWait() - testNodeA.L2Info.GasPrice = big.NewInt(100e9) + builder := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true) + l1A, l2A := builder.BuildL2OnL1(t) + defer requireClose(t, l1A.Stack) + defer l2A.Node.StopAndWait() + l2A.Info.GasPrice = big.NewInt(100e9) go func() { data := make([]byte, 90000) _, err := rand.Read(data) Require(t, err) for { - gas := testNodeA.L2Info.TransferGas + 20000*uint64(len(data)) - tx := testNodeA.L2Info.PrepareTx("Faucet", "Faucet", gas, common.Big0, data) - err = testNodeA.L2Client.SendTransaction(ctx, tx) + gas := l2A.Info.TransferGas + 20000*uint64(len(data)) + tx := l2A.Info.PrepareTx("Faucet", "Faucet", gas, common.Big0, data) + err = l2A.Client.SendTransaction(ctx, tx) Require(t, err) - _, err := EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) + _, err := EnsureTxSucceeded(ctx, l2A.Client, tx) Require(t, err) } }() @@ -199,11 +203,11 @@ func TestBatchPosterKeepsUp(t *testing.T) { start := time.Now() for { time.Sleep(time.Second) - batches, err := testNodeA.L2Node.InboxTracker.GetBatchCount() + batches, err := l2A.Node.InboxTracker.GetBatchCount() Require(t, err) - postedMessages, err := testNodeA.L2Node.InboxTracker.GetBatchMessageCount(batches - 1) + postedMessages, err := l2A.Node.InboxTracker.GetBatchMessageCount(batches - 1) Require(t, err) - haveMessages, err := testNodeA.L2Node.TxStreamer.GetMessageCount() + haveMessages, err := l2A.Node.TxStreamer.GetMessageCount() Require(t, err) duration := time.Since(start) fmt.Printf("batches posted: %v over %v (%.2f batches/second)\n", batches, duration, float64(batches)/(float64(duration)/float64(time.Second))) diff --git a/system_tests/block_hash_test.go b/system_tests/block_hash_test.go index 9ce752e65..2b8051242 100644 --- a/system_tests/block_hash_test.go +++ b/system_tests/block_hash_test.go @@ -16,13 +16,13 @@ func TestBlockHash(t *testing.T) { defer cancel() // Even though we don't use the L1, we need to create this node on L1 to get accurate L1 block numbers - testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() + l2info, l2node, l2client, _, _, _, l1stack := createTestNodeOnL1(t, ctx, true) + defer requireClose(t, l1stack) + defer l2node.StopAndWait() - auth := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) + auth := l2info.GetDefaultTransactOpts("Faucet", ctx) - _, _, simple, err := mocksgen.DeploySimple(&auth, testNode.L2Client) + _, _, simple, err := mocksgen.DeploySimple(&auth, l2client) Require(t, err) _, err = simple.CheckBlockHashes(&bind.CallOpts{Context: ctx}) diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index ae844612f..fa3d902b1 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -50,20 +50,20 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops delayEvery = workloadLoops / 3 } - testNodeA := NewNodeBuilder(ctx).SetIsSequencer(true).SetNodeConfig(l1NodeConfigA).SetChainConfig(chainConfig).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNodeA.L1Stack) - defer testNodeA.L2Node.StopAndWait() + l2info, nodeA, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, chainConfig, nil) + defer requireClose(t, l1stack) + defer nodeA.StopAndWait() - authorizeDASKeyset(t, ctx, dasSignerKey, testNodeA.L1Info, testNodeA.L1Client) + authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) validatorConfig := arbnode.ConfigDefaultL1NonSequencerTest() validatorConfig.BlockValidator.Enable = true validatorConfig.DataAvailability = l1NodeConfigA.DataAvailability validatorConfig.DataAvailability.RPCAggregator.Enable = false AddDefaultValNode(t, ctx, validatorConfig, !arbitrator) - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, validatorConfig, nil) + l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, validatorConfig, nil) defer nodeB.StopAndWait() - testNodeA.L2Info.GenerateAccount("User2") + l2info.GenerateAccount("User2") perTransfer := big.NewInt(1e12) @@ -72,7 +72,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops var tx *types.Transaction if workload == ethSend { - tx = testNodeA.L2Info.PrepareTx("Owner", "User2", testNodeA.L2Info.TransferGas, perTransfer, nil) + tx = l2info.PrepareTx("Owner", "User2", l2info.TransferGas, perTransfer, nil) } else { var contractCode []byte var gas uint64 @@ -86,10 +86,10 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops contractCode = append(contractCode, byte(vm.CODECOPY)) contractCode = append(contractCode, byte(vm.PUSH0)) contractCode = append(contractCode, byte(vm.RETURN)) - basefee := testNodeA.GetBaseFeeAtViaL2(t, nil) + basefee := GetBaseFee(t, l2client, ctx) var err error - gas, err = testNodeA.L2Client.EstimateGas(ctx, ethereum.CallMsg{ - From: testNodeA.L2Info.GetAddress("Owner"), + gas, err = l2client.EstimateGas(ctx, ethereum.CallMsg{ + From: l2info.GetAddress("Owner"), GasPrice: basefee, Value: big.NewInt(0), Data: contractCode, @@ -101,14 +101,14 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops contractCode = append(contractCode, 0x60, 0x00, 0x60, 0x00, 0x52) // PUSH1 0 MSTORE } contractCode = append(contractCode, 0x60, 0x00, 0x56) // JUMP - gas = testNodeA.L2Info.TransferGas*2 + l2pricing.InitialPerBlockGasLimitV6 + gas = l2info.TransferGas*2 + l2pricing.InitialPerBlockGasLimitV6 } - tx = testNodeA.L2Info.PrepareTxTo("Owner", nil, gas, common.Big0, contractCode) + tx = l2info.PrepareTxTo("Owner", nil, gas, common.Big0, contractCode) } - err := testNodeA.L2Client.SendTransaction(ctx, tx) + err := l2client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceededWithTimeout(ctx, testNodeA.L2Client, tx, time.Second*5) + _, err = EnsureTxSucceededWithTimeout(ctx, l2client, tx, time.Second*5) if workload != depleteGas { Require(t, err) } @@ -117,40 +117,40 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops } } } else { - auth := testNodeA.L2Info.GetDefaultTransactOpts("Owner", ctx) + auth := l2info.GetDefaultTransactOpts("Owner", ctx) // make auth a chain owner - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), testNodeA.L2Client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) Require(t, err) tx, err := arbDebug.BecomeChainOwner(&auth) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) - arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), testNodeA.L2Client) + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), l2client) Require(t, err) tx, err = arbOwner.ScheduleArbOSUpgrade(&auth, 11, 0) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) - tx = testNodeA.L2Info.PrepareTxTo("Owner", nil, testNodeA.L2Info.TransferGas, perTransfer, []byte{byte(vm.PUSH0)}) - err = testNodeA.L2Client.SendTransaction(ctx, tx) + tx = l2info.PrepareTxTo("Owner", nil, l2info.TransferGas, perTransfer, []byte{byte(vm.PUSH0)}) + err = l2client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceededWithTimeout(ctx, testNodeA.L2Client, tx, time.Second*5) + _, err = EnsureTxSucceededWithTimeout(ctx, l2client, tx, time.Second*5) Require(t, err) } if workload != depleteGas { - delayedTx := testNodeA.L2Info.PrepareTx("Owner", "User2", 30002, perTransfer, nil) - SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ - WrapL2ForDelayed(t, delayedTx, testNodeA.L1Info, "User", 100000), + delayedTx := l2info.PrepareTx("Owner", "User2", 30002, perTransfer, nil) + SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ + WrapL2ForDelayed(t, delayedTx, l1info, "User", 100000), }) // give the inbox reader a bit of time to pick up the delayed message time.Sleep(time.Millisecond * 500) // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ - testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ + l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } @@ -159,7 +159,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops } if workload == ethSend { - l2balance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("User2"), nil) + l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) Require(t, err) expectedBalance := new(big.Int).Mul(perTransfer, big.NewInt(int64(workloadLoops+1))) diff --git a/system_tests/bloom_test.go b/system_tests/bloom_test.go index c61583adf..9ad3253d4 100644 --- a/system_tests/bloom_test.go +++ b/system_tests/bloom_test.go @@ -28,14 +28,14 @@ func TestBloom(t *testing.T) { nodeconfig := arbnode.ConfigDefaultL2Test() nodeconfig.RPC.BloomBitsBlocks = 256 nodeconfig.RPC.BloomConfirms = 1 - testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeconfig).CreateTestNodeOnL2Only(t, false) - defer testNode.L2Node.StopAndWait() + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, false) + defer node.StopAndWait() - testNode.L2Info.GenerateAccount("User2") + l2info.GenerateAccount("User2") - ownerTxOpts := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) ownerTxOpts.Context = ctx - _, simple := testNode.DeploySimple(t, ownerTxOpts) + _, simple := deploySimple(t, ctx, ownerTxOpts, client) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) @@ -63,7 +63,7 @@ func TestBloom(t *testing.T) { if sendNullEvent { tx, err = simple.EmitNullEvent(&ownerTxOpts) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client, tx) Require(t, err) } @@ -74,7 +74,7 @@ func TestBloom(t *testing.T) { tx, err = simple.Increment(&ownerTxOpts) } Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client, tx) Require(t, err) if i%100 == 0 { t.Log("counts: ", i, "/", countsNum) @@ -82,7 +82,7 @@ func TestBloom(t *testing.T) { } for { - sectionSize, sectionNum := testNode.L2Node.Execution.Backend.APIBackend().BloomStatus() + sectionSize, sectionNum := node.Execution.Backend.APIBackend().BloomStatus() if sectionSize != 256 { Fatal(t, "unexpected section size: ", sectionSize) } @@ -92,14 +92,14 @@ func TestBloom(t *testing.T) { } <-time.After(time.Second) } - lastHeader, err := testNode.L2Client.HeaderByNumber(ctx, nil) + lastHeader, err := client.HeaderByNumber(ctx, nil) Require(t, err) nullEventQuery := ethereum.FilterQuery{ FromBlock: big.NewInt(0), ToBlock: lastHeader.Number, Topics: [][]common.Hash{{simpleABI.Events["NullEvent"].ID}}, } - logs, err := testNode.L2Client.FilterLogs(ctx, nullEventQuery) + logs, err := client.FilterLogs(ctx, nullEventQuery) Require(t, err) if len(logs) != len(nullEventCounts) { Fatal(t, "expected ", len(nullEventCounts), " logs, got ", len(logs)) @@ -107,7 +107,7 @@ func TestBloom(t *testing.T) { incrementEventQuery := ethereum.FilterQuery{ Topics: [][]common.Hash{{simpleABI.Events["CounterEvent"].ID}}, } - logs, err = testNode.L2Client.FilterLogs(ctx, incrementEventQuery) + logs, err = client.FilterLogs(ctx, incrementEventQuery) Require(t, err) if len(logs) != len(eventCounts) { Fatal(t, "expected ", len(eventCounts), " logs, got ", len(logs)) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index cb24555d2..9525d9d6c 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -60,31 +60,75 @@ import ( type info = *BlockchainTestInfo type client = arbutil.L1Interface +type TestClient struct { + // Nodebuilder fields + ctx context.Context + Info info + Client *ethclient.Client + Backend *eth.Ethereum + Stack *node.Node + Node *arbnode.Node +} + +func NewTestClient(ctx context.Context) *TestClient { + return &TestClient{ctx: ctx} +} + +// SetClient is used to initialize *ethclient.Client when users dont want to create TestClients via create methods from nodebuilder +func (tc *TestClient) SetClient(c *ethclient.Client) *TestClient { + tc.Client = c + return tc +} + +// SetInfo is used to initialize *BlockchainTestInfo when users dont want to create TestClients via create methods from nodebuilder +func (tc *TestClient) SetInfo(i info) *TestClient { + tc.Info = i + return tc +} + +func (tc *TestClient) SendSignedTx(t *testing.T, l2Client *ethclient.Client, transaction *types.Transaction) *types.Receipt { + return SendSignedTxViaL1(t, tc.ctx, tc.Info, tc.Client, l2Client, transaction) +} + +func (tc *TestClient) SendUnsignedTx(t *testing.T, l2Client *ethclient.Client, transaction *types.Transaction) *types.Receipt { + return SendUnsignedTxViaL1(t, tc.ctx, tc.Info, tc.Client, l2Client, transaction) +} + +func (tc *TestClient) TransferBalance(t *testing.T, from string, to string, amount *big.Int) (*types.Transaction, *types.Receipt) { + return TransferBalanceTo(t, from, tc.Info.GetAddress(to), amount, tc.Info, tc.Client, tc.ctx) +} + +func (tc *TestClient) TransferBalanceTo(t *testing.T, from string, to common.Address, amount *big.Int) (*types.Transaction, *types.Receipt) { + return TransferBalanceTo(t, from, to, amount, tc.Info, tc.Client, tc.ctx) +} + +func (tc *TestClient) GetBalance(t *testing.T, account common.Address) *big.Int { + return GetBalance(t, tc.ctx, tc.Client, account) +} + +func (tc *TestClient) GetBaseFeeAt(t *testing.T, blockNum *big.Int) *big.Int { + return GetBaseFeeAt(t, tc.Client, tc.ctx, blockNum) +} + +func (tc *TestClient) DeploySimple(t *testing.T, auth bind.TransactOpts) (common.Address, *mocksgen.Simple) { + return deploySimple(t, tc.ctx, auth, tc.Client) +} + type NodeBuilder struct { // Nodebuilder configuration ctx context.Context + Info info chainConfig *params.ChainConfig cacheConfig *core.CacheConfig nodeConfig *arbnode.Config - l1StackConfig *node.Config - l2StackConfig *node.Config + stackConfig *node.Config + cachingConfig *execution.CachingConfig isSequencer bool + takeOwnership bool - // L1 Nodebuilder fields - L1Info info - L1Client *ethclient.Client - L1Backend *eth.Ethereum - L1Stack *node.Node - - // L2 Nodebuilder fields - L2Info info - L2Client *ethclient.Client - L2Backend *eth.Ethereum - L2Node *arbnode.Node - L2Stack *node.Node - L2ChainDB ethdb.Database - L2NodeDB ethdb.Database - L2Blockchain *core.BlockChain + // Created nodes + L1 *TestClient + L2 *TestClient } func NewNodeBuilder(ctx context.Context) *NodeBuilder { @@ -106,23 +150,18 @@ func (b *NodeBuilder) SetCacheConfig(c *core.CacheConfig) *NodeBuilder { return b } -func (b *NodeBuilder) SetL1StackConfig(c *node.Config) *NodeBuilder { - b.l1StackConfig = c - return b -} - -func (b *NodeBuilder) SetL2StackConfig(c *node.Config) *NodeBuilder { - b.l2StackConfig = c +func (b *NodeBuilder) SetStackConfig(c *node.Config) *NodeBuilder { + b.stackConfig = c return b } -func (b *NodeBuilder) SetL1Info(l1Info info) *NodeBuilder { - b.L1Info = l1Info +func (b *NodeBuilder) SetInfo(i info) *NodeBuilder { + b.Info = i return b } -func (b *NodeBuilder) SetL2Info(l2Info info) *NodeBuilder { - b.L2Info = l2Info +func (b *NodeBuilder) SetCachingConfig(c *execution.CachingConfig) *NodeBuilder { + b.cachingConfig = c return b } @@ -131,55 +170,101 @@ func (b *NodeBuilder) SetIsSequencer(v bool) *NodeBuilder { return b } -func (b *NodeBuilder) CreateTestNodeOnL1AndL2(t *testing.T) *NodeBuilder { - b.L2Info, b.L2Node, b.L2Client, b.L2Stack, b.L1Info, b.L1Backend, b.L1Client, b.L1Stack = - createTestNodeOnL1AndL2Impl(t, b.ctx, b.isSequencer, b.nodeConfig, b.chainConfig, b.l2StackConfig, b.L2Info) +func (b *NodeBuilder) SetTakeOwnership(v bool) *NodeBuilder { + b.takeOwnership = v return b } -func (b *NodeBuilder) CreateTestNodeOnL2Only(t *testing.T, takeOwnership bool) *NodeBuilder { - b.L2Info, b.L2Node, b.L2Client = createTestNodeOnL2OnlyImpl(t, b.ctx, b.L2Info, b.nodeConfig, takeOwnership) +func (b *NodeBuilder) ConfigForL2OnL1(isSequencer bool, n *arbnode.Config, c *params.ChainConfig, s *node.Config, i info) *NodeBuilder { + b.isSequencer = isSequencer + b.nodeConfig = n + b.chainConfig = c + b.stackConfig = s + b.Info = i return b } -func (b *NodeBuilder) SendSignedTxViaL1(t *testing.T, transaction *types.Transaction) *types.Receipt { - return sendSignedTxViaL1Impl(t, b.ctx, b.L1Info, b.L1Client, b.L2Client, transaction) +func (b *NodeBuilder) BuildL2OnL1(t *testing.T) (*TestClient, *TestClient) { + l1, l2 := NewTestClient(b.ctx), NewTestClient(b.ctx) + l2.Info, l2.Node, l2.Client, l2.Stack, l1.Info, l1.Backend, l1.Client, l1.Stack = + createTestNodeOnL1WithConfigImpl(t, b.ctx, b.isSequencer, b.nodeConfig, b.chainConfig, b.stackConfig, b.Info) + b.L1, b.L2 = l1, l2 + return l1, l2 } -func (b *NodeBuilder) SendUnsignedTxViaL1(t *testing.T, transaction *types.Transaction) *types.Receipt { - return sendUnsignedTxViaL1Impl(t, b.ctx, b.L1Info, b.L1Client, b.L2Client, transaction) +func (b *NodeBuilder) ConfigForL2(takeOwnership bool, n *arbnode.Config, i info) *NodeBuilder { + b.takeOwnership = takeOwnership + b.nodeConfig = n + b.Info = i + return b } -func (b *NodeBuilder) BridgeBalance(t *testing.T, account string, amount *big.Int) (*types.Transaction, *types.Receipt) { - return bridgeBalanceImpl(t, account, amount, b.L1Info, b.L2Info, b.L1Client, b.L2Client, b.ctx) +func (b *NodeBuilder) BuildL2(t *testing.T) *TestClient { + l2 := NewTestClient(b.ctx) + l2.Info, l2.Node, l2.Client = + CreateTestL2WithConfig(t, b.ctx, b.Info, b.nodeConfig, b.takeOwnership) + b.L2 = l2 + return l2 } -func (b *NodeBuilder) TransferBalanceViaL2(t *testing.T, from string, to string, amount *big.Int) (*types.Transaction, *types.Receipt) { - return transferBalanceToImpl(t, from, b.L2Info.GetAddress(to), amount, b.L2Info, b.L2Client, b.ctx) +func (b *NodeBuilder) Build2ndNode(t *testing.T, initData *statetransfer.ArbosInitializationInfo, nodeConfig *arbnode.Config, stackConfig *node.Config) *TestClient { + if b.L1 == nil { + t.Fatal("builder did not previously build a L1 Node") + } + if b.L2 == nil { + t.Fatal("builder did not previously build a L2 Node") + } + l2 := NewTestClient(b.ctx) + l2.Client, l2.Node = + Create2ndNodeWithConfig(t, b.ctx, b.L2.Node, b.L1.Stack, b.L1.Info, initData, nodeConfig, stackConfig) + return l2 } -func (b *NodeBuilder) TransferBalanceViaL1(t *testing.T, from string, to string, amount *big.Int) (*types.Transaction, *types.Receipt) { - return transferBalanceToImpl(t, from, b.L1Info.GetAddress(to), amount, b.L1Info, b.L1Client, b.ctx) +func (b *NodeBuilder) Build2ndNodeDAS(t *testing.T, initData *statetransfer.ArbosInitializationInfo, dasConfig *das.DataAvailabilityConfig) *TestClient { + if b.L1 == nil { + t.Fatal("builder did not previously build a L1 Node") + } + if b.L2 == nil { + t.Fatal("builder did not previously build a L2 Node") + } + l2 := NewTestClient(b.ctx) + l2.Client, l2.Node = + Create2ndNode(t, b.ctx, b.L2.Node, b.L1.Stack, b.L1.Info, initData, dasConfig) + return l2 } -func (b *NodeBuilder) TransferBalanceToViaL2(t *testing.T, from string, to common.Address, amount *big.Int) (*types.Transaction, *types.Receipt) { - return transferBalanceToImpl(t, from, to, amount, b.L2Info, b.L2Client, b.ctx) +type TestBlockchain struct { + TestClient + // Blockchain fields + ChainDB ethdb.Database + NodeDB ethdb.Database + Blockchain *core.BlockChain } -func (b *NodeBuilder) TransferBalanceToViaL1(t *testing.T, from string, to common.Address, amount *big.Int) (*types.Transaction, *types.Receipt) { - return transferBalanceToImpl(t, from, to, amount, b.L1Info, b.L1Client, b.ctx) +func (b *NodeBuilder) ConfigForL1Blockchain(s *node.Config, i info) *NodeBuilder { + b.stackConfig = s + b.Info = i + return b } -func (b *NodeBuilder) GetBaseFeeAtViaL2(t *testing.T, blockNum *big.Int) *big.Int { - return getBaseFeeAtImpl(t, b.L2Client, b.ctx, blockNum) +func (b *NodeBuilder) BuilL1Blockchain(t *testing.T) *TestBlockchain { + l1 := &TestBlockchain{} + l1.ctx = b.ctx + l1.Info, l1.Client, l1.Backend, l1.Stack = createTestL1BlockChainWithConfig(t, b.Info, b.stackConfig) + return l1 } -func (b *NodeBuilder) GetBaseFeeAtViaL1(t *testing.T, blockNum *big.Int) *big.Int { - return getBaseFeeAtImpl(t, b.L1Client, b.ctx, blockNum) +func (b *NodeBuilder) ConfigForL2Blockchain(s *node.Config, i info) *NodeBuilder { + b.stackConfig = s + b.Info = i + return b } -func (b *NodeBuilder) DeploySimple(t *testing.T, auth bind.TransactOpts) (common.Address, *mocksgen.Simple) { - return deploySimpleImpl(t, b.ctx, auth, b.L2Client) +func (b *NodeBuilder) BuilL2Blockchain(t *testing.T, dataDir string, initMessage *arbostypes.ParsedInitMessage) *TestBlockchain { + l2 := &TestBlockchain{} + l2.Info, l2.Stack, l2.ChainDB, l2.NodeDB, l2.Blockchain = + createL2BlockChainWithStackConfig(t, b.Info, dataDir, b.chainConfig, initMessage, b.stackConfig, b.cachingConfig) + return l2 } func SendWaitTestTransactions(t *testing.T, ctx context.Context, client client, txs []*types.Transaction) { @@ -193,7 +278,14 @@ func SendWaitTestTransactions(t *testing.T, ctx context.Context, client client, } } -func transferBalanceToImpl( +func TransferBalance( + t *testing.T, from, to string, amount *big.Int, l2info info, client client, ctx context.Context, +) (*types.Transaction, *types.Receipt) { + t.Helper() + return TransferBalanceTo(t, from, l2info.GetAddress(to), amount, l2info, client, ctx) +} + +func TransferBalanceTo( t *testing.T, from string, to common.Address, amount *big.Int, l2info info, client client, ctx context.Context, ) (*types.Transaction, *types.Receipt) { t.Helper() @@ -206,7 +298,7 @@ func transferBalanceToImpl( } // if l2client is not nil - will wait until balance appears in l2 -func bridgeBalanceImpl( +func BridgeBalance( t *testing.T, account string, amount *big.Int, l1info info, l2info info, l1client client, l2client client, ctx context.Context, ) (*types.Transaction, *types.Receipt) { t.Helper() @@ -253,7 +345,7 @@ func bridgeBalanceImpl( if balance.Cmp(l2Balance) >= 0 { break } - transferBalanceToImpl(t, "Faucet", l1info.GetAddress("User"), big.NewInt(1), l1info, l1client, ctx) + TransferBalance(t, "Faucet", "User", big.NewInt(1), l1info, l1client, ctx) if i > 20 { Fatal(t, "bridging failed") } @@ -264,7 +356,7 @@ func bridgeBalanceImpl( return tx, res } -func sendSignedTxViaL1Impl( +func SendSignedTxViaL1( t *testing.T, ctx context.Context, l1info *BlockchainTestInfo, @@ -295,7 +387,7 @@ func sendSignedTxViaL1Impl( return receipt } -func sendUnsignedTxViaL1Impl( +func SendUnsignedTxViaL1( t *testing.T, ctx context.Context, l1info *BlockchainTestInfo, @@ -346,7 +438,13 @@ func sendUnsignedTxViaL1Impl( return receipt } -func getBaseFeeAtImpl(t *testing.T, client client, ctx context.Context, blockNum *big.Int) *big.Int { +func GetBaseFee(t *testing.T, client client, ctx context.Context) *big.Int { + header, err := client.HeaderByNumber(ctx, nil) + Require(t, err) + return header.BaseFee +} + +func GetBaseFeeAt(t *testing.T, client client, ctx context.Context, blockNum *big.Int) *big.Int { header, err := client.HeaderByNumber(ctx, blockNum) Require(t, err) return header.BaseFee @@ -662,7 +760,33 @@ func ClientForStack(t *testing.T, backend *node.Node) *ethclient.Client { } // Create and deploy L1 and arbnode for L2 -func createTestNodeOnL1AndL2Impl( +func createTestNodeOnL1( + t *testing.T, + ctx context.Context, + isSequencer bool, +) ( + l2info info, node *arbnode.Node, l2client *ethclient.Client, l1info info, + l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node, +) { + return createTestNodeOnL1WithConfig(t, ctx, isSequencer, nil, nil, nil) +} + +func createTestNodeOnL1WithConfig( + t *testing.T, + ctx context.Context, + isSequencer bool, + nodeConfig *arbnode.Config, + chainConfig *params.ChainConfig, + stackConfig *node.Config, +) ( + l2info info, currentNode *arbnode.Node, l2client *ethclient.Client, l1info info, + l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node, +) { + l2info, currentNode, l2client, _, l1info, l1backend, l1client, l1stack = createTestNodeOnL1WithConfigImpl(t, ctx, isSequencer, nodeConfig, chainConfig, stackConfig, nil) + return +} + +func createTestNodeOnL1WithConfigImpl( t *testing.T, ctx context.Context, isSequencer bool, @@ -725,12 +849,12 @@ func createTestNodeOnL1AndL2Impl( // L2 -Only. Enough for tests that needs no interface to L1 // Requires precompiles.AllowDebugPrecompiles = true -func createTestNodeOnL2OnlyImpl( - t *testing.T, - ctx context.Context, - l2Info *BlockchainTestInfo, - nodeConfig *arbnode.Config, - takeOwnership bool, +func CreateTestL2(t *testing.T, ctx context.Context) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { + return CreateTestL2WithConfig(t, ctx, nil, arbnode.ConfigDefaultL2Test(), true) +} + +func CreateTestL2WithConfig( + t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, takeOwnership bool, ) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { feedErrChan := make(chan error, 10) @@ -993,7 +1117,7 @@ func getDeadlineTimeout(t *testing.T, defaultTimeout time.Duration) time.Duratio return timeout } -func deploySimpleImpl( +func deploySimple( t *testing.T, ctx context.Context, auth bind.TransactOpts, client *ethclient.Client, ) (common.Address, *mocksgen.Simple) { addr, tx, simple, err := mocksgen.DeploySimple(&auth, client) diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index f4b6dd85c..14aa00031 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -203,42 +203,42 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() + l2info, node, l2client, _, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) + defer requireClose(t, l1stack) + defer node.StopAndWait() - auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) - contractAddress1, simple1 := testNode.DeploySimple(t, auth) + auth := l2info.GetDefaultTransactOpts("Owner", ctx) + contractAddress1, simple1 := deploySimple(t, ctx, auth, l2client) tx, err := simple1.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) - contractAddress2, simple2 := testNode.DeploySimple(t, auth) + contractAddress2, simple2 := deploySimple(t, ctx, auth, l2client) tx, err = simple2.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) tx, err = simple2.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) - currentRootHash1 := getStorageRootHash(t, testNode.L2Node, contractAddress1) - currentSlotValueMap1 := getStorageSlotValue(t, testNode.L2Node, contractAddress1) - currentRootHash2 := getStorageRootHash(t, testNode.L2Node, contractAddress2) - currentSlotValueMap2 := getStorageSlotValue(t, testNode.L2Node, contractAddress2) + currentRootHash1 := getStorageRootHash(t, node, contractAddress1) + currentSlotValueMap1 := getStorageSlotValue(t, node, contractAddress1) + currentRootHash2 := getStorageRootHash(t, node, contractAddress2) + currentSlotValueMap2 := getStorageSlotValue(t, node, contractAddress2) - rpcClient, err := testNode.L2Node.Stack.Attach() + rpcClient, err := node.Stack.Attach() Require(t, err) - testNode.L2Info.GenerateAccount("User2") + l2info.GenerateAccount("User2") - testConditionalTxThatShouldSucceed(t, ctx, -1, testNode.L2Info, rpcClient, nil) + testConditionalTxThatShouldSucceed(t, ctx, -1, l2info, rpcClient, nil) for i, options := range getEmptyOptions(contractAddress1) { - testConditionalTxThatShouldSucceed(t, ctx, i, testNode.L2Info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, i, l2info, rpcClient, options) } - block, err := testNode.L1Client.BlockByNumber(ctx, nil) + block, err := l1client.BlockByNumber(ctx, nil) Require(t, err) blockNumber := block.NumberU64() blockTime := block.Time() @@ -249,33 +249,33 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { options1 := dedupOptions(t, append(append(optionsAB, optionsA...), optionsB...)) options1 = optionsDedupProduct(t, options1, getFulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options1 { - testConditionalTxThatShouldSucceed(t, ctx, i, testNode.L2Info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, i, l2info, rpcClient, options) } tx, err = simple1.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) tx, err = simple2.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) previousStorageRootHash1 := currentRootHash1 - currentRootHash1 = getStorageRootHash(t, testNode.L2Node, contractAddress1) + currentRootHash1 = getStorageRootHash(t, node, contractAddress1) if bytes.Equal(previousStorageRootHash1.Bytes(), currentRootHash1.Bytes()) { Fatal(t, "storage root hash didn't change as expected") } - currentSlotValueMap1 = getStorageSlotValue(t, testNode.L2Node, contractAddress1) + currentSlotValueMap1 = getStorageSlotValue(t, node, contractAddress1) previousStorageRootHash2 := currentRootHash2 - currentRootHash2 = getStorageRootHash(t, testNode.L2Node, contractAddress2) + currentRootHash2 = getStorageRootHash(t, node, contractAddress2) if bytes.Equal(previousStorageRootHash2.Bytes(), currentRootHash2.Bytes()) { Fatal(t, "storage root hash didn't change as expected") } - currentSlotValueMap2 = getStorageSlotValue(t, testNode.L2Node, contractAddress2) + currentSlotValueMap2 = getStorageSlotValue(t, node, contractAddress2) - block, err = testNode.L1Client.BlockByNumber(ctx, nil) + block, err = l1client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() blockTime = block.Time() @@ -286,35 +286,35 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { options2 := dedupOptions(t, append(append(optionsCD, optionsC...), optionsD...)) options2 = optionsDedupProduct(t, options2, getFulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options2 { - testConditionalTxThatShouldSucceed(t, ctx, i, testNode.L2Info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, i, l2info, rpcClient, options) } for i, options := range options1 { - testConditionalTxThatShouldFail(t, ctx, i, testNode.L2Info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) } - block, err = testNode.L1Client.BlockByNumber(ctx, nil) + block, err = l1client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() blockTime = block.Time() options3 := optionsDedupProduct(t, options2, getUnfulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options3 { - testConditionalTxThatShouldFail(t, ctx, i, testNode.L2Info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) } options4 := optionsDedupProduct(t, options2, options1) for i, options := range options4 { - testConditionalTxThatShouldFail(t, ctx, i, testNode.L2Info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) } } func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() - rpcClient, err := testNode.L2Node.Stack.Attach() + l2info, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() + rpcClient, err := node.Stack.Attach() Require(t, err) - auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) - contractAddress, simple := testNode.DeploySimple(t, auth) + auth := l2info.GetDefaultTransactOpts("Owner", ctx) + contractAddress, simple := deploySimple(t, ctx, auth, client) simpleContract, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) Require(t, err) @@ -325,11 +325,11 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { var options []*arbitrum_types.ConditionalOptions for i := 0; i < numTxes; i++ { account := fmt.Sprintf("User%v", i) - testNode.L2Info.GenerateAccount(account) - tx := testNode.L2Info.PrepareTx("Owner", account, testNode.L2Info.TransferGas, big.NewInt(1e16), nil) - err := testNode.L2Client.SendTransaction(ctx, tx) + l2info.GenerateAccount(account) + tx := l2info.PrepareTx("Owner", account, l2info.TransferGas, big.NewInt(1e16), nil) + err := client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client, tx) Require(t, err) } for i := numTxes - 1; i >= 0; i-- { @@ -337,7 +337,7 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { data, err := simpleContract.Pack("logAndIncrement", big.NewInt(int64(expected))) Require(t, err) account := fmt.Sprintf("User%v", i) - txes = append(txes, testNode.L2Info.PrepareTxTo(account, &contractAddress, testNode.L2Info.TransferGas, big.NewInt(0), data)) + txes = append(txes, l2info.PrepareTxTo(account, &contractAddress, l2info.TransferGas, big.NewInt(0), data)) options = append(options, &arbitrum_types.ConditionalOptions{KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{contractAddress: {SlotValue: map[common.Hash]common.Hash{{0}: common.BigToHash(big.NewInt(int64(expected)))}}}}) } ctxWithTimeout, cancelCtxWithTimeout := context.WithTimeout(ctx, 5*time.Second) @@ -367,7 +367,7 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { } cancelCtxWithTimeout() wg.Wait() - bc := testNode.L2Node.Execution.Backend.ArbInterface().BlockChain() + bc := node.Execution.Backend.ArbInterface().BlockChain() genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum var receipts types.Receipts @@ -409,34 +409,34 @@ func TestSendRawTransactionConditionalPreCheck(t *testing.T) { nodeConfig.TxPreChecker.RequiredStateAge = 1 nodeConfig.TxPreChecker.RequiredStateMaxBlocks = 2 - testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() - rpcClient, err := testNode.L2Node.Stack.Attach() + l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, nil) + defer requireClose(t, l1stack) + defer node.StopAndWait() + rpcClient, err := node.Stack.Attach() Require(t, err) - testNode.L2Info.GenerateAccount("User2") + l2info.GenerateAccount("User2") - auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + auth := l2info.GetDefaultTransactOpts("Owner", ctx) start := time.Now().Unix() - contractAddress, simple := testNode.DeploySimple(t, auth) + contractAddress, simple := deploySimple(t, ctx, auth, l2client) if time.Since(time.Unix(start, 0)) > 200*time.Millisecond { start++ time.Sleep(time.Until(time.Unix(start, 0))) } tx, err := simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) - currentRootHash := getStorageRootHash(t, testNode.L2Node, contractAddress) + currentRootHash := getStorageRootHash(t, node, contractAddress) options := &arbitrum_types.ConditionalOptions{ KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{ contractAddress: {RootHash: ¤tRootHash}, }, } - testConditionalTxThatShouldFail(t, ctx, 0, testNode.L2Info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, 0, l2info, rpcClient, options, -32003) time.Sleep(time.Until(time.Unix(start+1, 0))) - testConditionalTxThatShouldSucceed(t, ctx, 1, testNode.L2Info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, 1, l2info, rpcClient, options) start = time.Now().Unix() if time.Since(time.Unix(start, 0)) > 200*time.Millisecond { @@ -445,23 +445,23 @@ func TestSendRawTransactionConditionalPreCheck(t *testing.T) { } tx, err = simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) - currentRootHash = getStorageRootHash(t, testNode.L2Node, contractAddress) + currentRootHash = getStorageRootHash(t, node, contractAddress) options = &arbitrum_types.ConditionalOptions{ KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{ contractAddress: {RootHash: ¤tRootHash}, }, } - testConditionalTxThatShouldFail(t, ctx, 2, testNode.L2Info, rpcClient, options, -32003) - tx = testNode.L2Info.PrepareTx("Owner", "User2", testNode.L2Info.TransferGas, big.NewInt(1e12), nil) - Require(t, testNode.L2Client.SendTransaction(ctx, tx)) - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + testConditionalTxThatShouldFail(t, ctx, 2, l2info, rpcClient, options, -32003) + tx = l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) + Require(t, l2client.SendTransaction(ctx, tx)) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) - testConditionalTxThatShouldFail(t, ctx, 3, testNode.L2Info, rpcClient, options, -32003) - tx = testNode.L2Info.PrepareTx("Owner", "User2", testNode.L2Info.TransferGas, big.NewInt(1e12), nil) - Require(t, testNode.L2Client.SendTransaction(ctx, tx)) - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + testConditionalTxThatShouldFail(t, ctx, 3, l2info, rpcClient, options, -32003) + tx = l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) + Require(t, l2client.SendTransaction(ctx, tx)) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) - testConditionalTxThatShouldSucceed(t, ctx, 4, testNode.L2Info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, 4, l2info, rpcClient, options) } diff --git a/system_tests/contract_tx_test.go b/system_tests/contract_tx_test.go index 8f6debdf3..e671dcc6a 100644 --- a/system_tests/contract_tx_test.go +++ b/system_tests/contract_tx_test.go @@ -26,18 +26,19 @@ func TestContractTxDeploy(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, false) - defer testNode.L2Node.StopAndWait() + nodeconfig := arbnode.ConfigDefaultL2Test() + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, false) + defer node.StopAndWait() from := common.HexToAddress("0x123412341234") - testNode.TransferBalanceToViaL2(t, "Faucet", from, big.NewInt(1e18)) + TransferBalanceTo(t, "Faucet", from, big.NewInt(1e18), l2info, client, ctx) for stateNonce := uint64(0); stateNonce < 2; stateNonce++ { - pos, err := testNode.L2Node.TxStreamer.GetMessageCount() + pos, err := node.TxStreamer.GetMessageCount() Require(t, err) var delayedMessagesRead uint64 if pos > 0 { - lastMessage, err := testNode.L2Node.TxStreamer.GetMessage(pos - 1) + lastMessage, err := node.TxStreamer.GetMessage(pos - 1) Require(t, err) delayedMessagesRead = lastMessage.DelayedMessagesRead } @@ -69,7 +70,7 @@ func TestContractTxDeploy(t *testing.T) { l2Msg = append(l2Msg, math.U256Bytes(contractTx.Value)...) l2Msg = append(l2Msg, contractTx.Data...) - err = testNode.L2Node.TxStreamer.AddMessages(pos, true, []arbostypes.MessageWithMetadata{ + err = node.TxStreamer.AddMessages(pos, true, []arbostypes.MessageWithMetadata{ { Message: &arbostypes.L1IncomingMessage{ Header: &arbostypes.L1IncomingMessageHeader{ @@ -90,7 +91,7 @@ func TestContractTxDeploy(t *testing.T) { txHash := types.NewTx(contractTx).Hash() t.Log("made contract tx", contractTx, "with hash", txHash) - receipt, err := WaitForTx(ctx, testNode.L2Client, txHash, time.Second*10) + receipt, err := WaitForTx(ctx, client, txHash, time.Second*10) Require(t, err) if receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "Receipt has non-successful status", receipt.Status) @@ -103,7 +104,7 @@ func TestContractTxDeploy(t *testing.T) { t.Log("deployed contract", receipt.ContractAddress, "from address", from, "with nonce", stateNonce) stateNonce++ - code, err := testNode.L2Client.CodeAt(ctx, receipt.ContractAddress, nil) + code, err := client.CodeAt(ctx, receipt.ContractAddress, nil) Require(t, err) if !bytes.Equal(code, []byte{0xFE}) { Fatal(t, "expected contract", receipt.ContractAddress, "code of 0xFE but got", hex.EncodeToString(code)) diff --git a/system_tests/debugapi_test.go b/system_tests/debugapi_test.go index dedf7d294..03e3dfd40 100644 --- a/system_tests/debugapi_test.go +++ b/system_tests/debugapi_test.go @@ -14,11 +14,11 @@ import ( func TestDebugAPI(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer requireClose(t, testNode.L2Stack) + _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, nil, nil) + defer requireClose(t, l1stack) + defer requireClose(t, l2stack) - l2rpc, _ := testNode.L2Stack.Attach() + l2rpc, _ := l2stack.Attach() var dump state.Dump err := l2rpc.CallContext(ctx, &dump, "debug_dumpBlock", rpc.LatestBlockNumber) diff --git a/system_tests/delayedinbox_test.go b/system_tests/delayedinbox_test.go index 9830a06c7..e48cb3702 100644 --- a/system_tests/delayedinbox_test.go +++ b/system_tests/delayedinbox_test.go @@ -38,16 +38,16 @@ func TestDelayInboxSimple(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() + l2info, l2node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) + defer requireClose(t, l1stack) + defer l2node.StopAndWait() - testNode.L2Info.GenerateAccount("User2") + l2info.GenerateAccount("User2") - delayedTx := testNode.L2Info.PrepareTx("Owner", "User2", 50001, big.NewInt(1e6), nil) - testNode.SendSignedTxViaL1(t, delayedTx) + delayedTx := l2info.PrepareTx("Owner", "User2", 50001, big.NewInt(1e6), nil) + SendSignedTxViaL1(t, ctx, l1info, l1client, l2client, delayedTx) - l2balance, err := testNode.L2Client.BalanceAt(ctx, testNode.L2Info.GetAddress("User2"), nil) + l2balance, err := l2client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e6)) != 0 { Fatal(t, "Unexpected balance:", l2balance) diff --git a/system_tests/delayedinboxlong_test.go b/system_tests/delayedinboxlong_test.go index cc41220ff..b1c8ea361 100644 --- a/system_tests/delayedinboxlong_test.go +++ b/system_tests/delayedinboxlong_test.go @@ -25,11 +25,11 @@ func TestDelayInboxLong(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() + l2info, l2node, l2client, l1info, l1backend, l1client, l1stack := createTestNodeOnL1(t, ctx, true) + defer requireClose(t, l1stack) + defer l2node.StopAndWait() - testNode.L2Info.GenerateAccount("User2") + l2info.GenerateAccount("User2") fundsPerDelayed := int64(1000000) delayedMessages := int64(0) @@ -42,22 +42,22 @@ func TestDelayInboxLong(t *testing.T) { randNum := rand.Int() % messagesPerDelayed var l1tx *types.Transaction if randNum == 0 { - delayedTx := testNode.L2Info.PrepareTx("Owner", "User2", 50001, big.NewInt(fundsPerDelayed), nil) - l1tx = WrapL2ForDelayed(t, delayedTx, testNode.L1Info, "User", 100000) + delayedTx := l2info.PrepareTx("Owner", "User2", 50001, big.NewInt(fundsPerDelayed), nil) + l1tx = WrapL2ForDelayed(t, delayedTx, l1info, "User", 100000) lastDelayedMessage = delayedTx delayedMessages++ } else { - l1tx = testNode.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) + l1tx = l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) } l1Txs = append(l1Txs, l1tx) } // adding multiple messages in the same AddLocal to get them in the same L1 block - errs := testNode.L1Backend.TxPool().AddLocals(l1Txs) + errs := l1backend.TxPool().AddLocals(l1Txs) for _, err := range errs { Require(t, err) } // Checking every tx is expensive, so we just check the last, assuming that the others succeeded too - _, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1Txs[len(l1Txs)-1]) + _, err := EnsureTxSucceeded(ctx, l1client, l1Txs[len(l1Txs)-1]) Require(t, err) } @@ -68,14 +68,14 @@ func TestDelayInboxLong(t *testing.T) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 100; i++ { - SendWaitTestTransactions(t, ctx, testNode.L1Client, []*types.Transaction{ - testNode.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ + l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } - _, err := WaitForTx(ctx, testNode.L2Client, lastDelayedMessage.Hash(), time.Second*5) + _, err := WaitForTx(ctx, l2client, lastDelayedMessage.Hash(), time.Second*5) Require(t, err) - l2balance, err := testNode.L2Client.BalanceAt(ctx, testNode.L2Info.GetAddress("User2"), nil) + l2balance, err := l2client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(fundsPerDelayed*delayedMessages)) != 0 { Fatal(t, "Unexpected balance:", "balance", l2balance, "expected", fundsPerDelayed*delayedMessages) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index ae3fc39a7..26b5a7814 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -13,7 +13,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/node_interfacegen" @@ -27,17 +26,17 @@ func TestDeploy(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + l2info, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() - auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + auth := l2info.GetDefaultTransactOpts("Owner", ctx) auth.GasMargin = 0 // don't adjust, we want to see if the estimate alone is sufficient - _, simple := testNode.DeploySimple(t, auth) + _, simple := deploySimple(t, ctx, auth, client) tx, err := simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client, tx) Require(t, err) counter, err := simple.Counter(&bind.CallOpts{}) @@ -52,24 +51,24 @@ func TestEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + l2info, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() - auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + auth := l2info.GetDefaultTransactOpts("Owner", ctx) auth.GasMargin = 0 // don't adjust, we want to see if the estimate alone is sufficient gasPrice := big.NewInt(params.GWei / 10) // set the gas price - arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), testNode.L2Client) + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), client) Require(t, err, "could not deploy ArbOwner contract") tx, err := arbOwner.SetMinimumL2BaseFee(&auth, gasPrice) Require(t, err, "could not set L2 gas price") - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client, tx) Require(t, err) // connect to arbGasInfo precompile - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), testNode.L2Client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), client) Require(t, err, "could not deploy contract") // wait for price to come to equilibrium @@ -77,8 +76,8 @@ func TestEstimate(t *testing.T) { numTriesLeft := 20 for !equilibrated && numTriesLeft > 0 { // make an empty block to let the gas price update - testNode.L2Info.GasPrice = new(big.Int).Mul(testNode.L2Info.GasPrice, big.NewInt(2)) - testNode.TransferBalanceViaL2(t, "Owner", "Owner", common.Big0) + l2info.GasPrice = new(big.Int).Mul(l2info.GasPrice, big.NewInt(2)) + TransferBalance(t, "Owner", "Owner", common.Big0, l2info, client, ctx) // check if the price has equilibrated _, _, _, _, _, setPrice, err := arbGasInfo.GetPricesInWei(&bind.CallOpts{}) @@ -92,22 +91,22 @@ func TestEstimate(t *testing.T) { Fatal(t, "L2 gas price did not converge", gasPrice) } - initialBalance, err := testNode.L2Client.BalanceAt(ctx, auth.From, nil) + initialBalance, err := client.BalanceAt(ctx, auth.From, nil) Require(t, err, "could not get balance") // deploy a test contract - _, tx, simple, err := mocksgen.DeploySimple(&auth, testNode.L2Client) + _, tx, simple, err := mocksgen.DeploySimple(&auth, client) Require(t, err, "could not deploy contract") - receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) + receipt, err := EnsureTxSucceeded(ctx, client, tx) Require(t, err) - header, err := testNode.L2Client.HeaderByNumber(ctx, receipt.BlockNumber) + header, err := client.HeaderByNumber(ctx, receipt.BlockNumber) Require(t, err, "could not get header") if header.BaseFee.Cmp(gasPrice) != 0 { Fatal(t, "Header has wrong basefee", header.BaseFee, gasPrice) } - balance, err := testNode.L2Client.BalanceAt(ctx, auth.From, nil) + balance, err := client.BalanceAt(ctx, auth.From, nil) Require(t, err, "could not get balance") expectedCost := receipt.GasUsed * gasPrice.Uint64() observedCost := initialBalance.Uint64() - balance.Uint64() @@ -117,7 +116,7 @@ func TestEstimate(t *testing.T) { tx, err = simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client, tx) Require(t, err) counter, err := simple.Counter(&bind.CallOpts{}) @@ -132,11 +131,11 @@ func TestComponentEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + l2info, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() l1BaseFee := new(big.Int).Set(arbostypes.DefaultInitialL1BaseFee) - l2BaseFee := testNode.GetBaseFeeAtViaL2(t, nil) + l2BaseFee := GetBaseFee(t, client, ctx) colors.PrintGrey("l1 basefee ", l1BaseFee) colors.PrintGrey("l2 basefee ", l2BaseFee) @@ -145,10 +144,10 @@ func TestComponentEstimate(t *testing.T) { maxPriorityFeePerGas := big.NewInt(0) maxFeePerGas := arbmath.BigMulByUfrac(l2BaseFee, 3, 2) - testNode.L2Info.GenerateAccount("User") - testNode.TransferBalanceViaL2(t, "Owner", "User", userBalance) + l2info.GenerateAccount("User") + TransferBalance(t, "Owner", "User", userBalance, l2info, client, ctx) - from := testNode.L2Info.GetAddress("User") + from := l2info.GetAddress("User") to := testhelpers.RandomAddress() gas := uint64(100000000) calldata := []byte{0x00, 0x12} @@ -172,7 +171,7 @@ func TestComponentEstimate(t *testing.T) { Value: value, Data: estimateCalldata, } - returnData, err := testNode.L2Client.CallContract(ctx, msg, nil) + returnData, err := client.CallContract(ctx, msg, nil) Require(t, err) outputs, err := nodeMethod.Outputs.Unpack(returnData) @@ -186,8 +185,8 @@ func TestComponentEstimate(t *testing.T) { baseFee, _ := outputs[2].(*big.Int) l1BaseFeeEstimate, _ := outputs[3].(*big.Int) - tx := testNode.L2Info.SignTxAs("User", &types.DynamicFeeTx{ - ChainID: testNode.L2Node.Execution.ArbInterface.BlockChain().Config().ChainID, + tx := l2info.SignTxAs("User", &types.DynamicFeeTx{ + ChainID: node.Execution.ArbInterface.BlockChain().Config().ChainID, Nonce: 0, GasTipCap: maxPriorityFeePerGas, GasFeeCap: maxFeePerGas, @@ -208,8 +207,8 @@ func TestComponentEstimate(t *testing.T) { Fatal(t, baseFee, l2BaseFee.Uint64()) } - Require(t, testNode.L2Client.SendTransaction(ctx, tx)) - receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) + Require(t, client.SendTransaction(ctx, tx)) + receipt, err := EnsureTxSucceeded(ctx, client, tx) Require(t, err) l2Used := receipt.GasUsed - receipt.GasUsedForL1 @@ -224,14 +223,14 @@ func TestDisableL1Charging(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + _, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() addr := common.HexToAddress("0x12345678") - gasWithL1Charging, err := testNode.L2Client.EstimateGas(ctx, ethereum.CallMsg{To: &addr}) + gasWithL1Charging, err := client.EstimateGas(ctx, ethereum.CallMsg{To: &addr}) Require(t, err) - gasWithoutL1Charging, err := testNode.L2Client.EstimateGas(ctx, ethereum.CallMsg{To: &addr, SkipL1Charging: true}) + gasWithoutL1Charging, err := client.EstimateGas(ctx, ethereum.CallMsg{To: &addr, SkipL1Charging: true}) Require(t, err) if gasWithL1Charging <= gasWithoutL1Charging { @@ -241,14 +240,14 @@ func TestDisableL1Charging(t *testing.T) { Fatal(t, "Incorrect gas estimate with disabled L1 charging") } - _, err = testNode.L2Client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithL1Charging}, nil) + _, err = client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithL1Charging}, nil) Require(t, err) - _, err = testNode.L2Client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging}, nil) + _, err = client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging}, nil) if err == nil { Fatal(t, "CallContract passed with insufficient gas") } - _, err = testNode.L2Client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging, SkipL1Charging: true}, nil) + _, err = client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging, SkipL1Charging: true}, nil) Require(t, err) } diff --git a/system_tests/fees_test.go b/system_tests/fees_test.go index 5093b873d..bdd998357 100644 --- a/system_tests/fees_test.go +++ b/system_tests/fees_test.go @@ -33,19 +33,19 @@ func TestSequencerFeePaid(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() + l2info, l2node, l2client, _, _, _, l1stack := createTestNodeOnL1(t, ctx, true) + defer requireClose(t, l1stack) + defer l2node.StopAndWait() - version := testNode.L2Node.Execution.ArbInterface.BlockChain().Config().ArbitrumChainParams.InitialArbOSVersion - callOpts := testNode.L2Info.GetDefaultCallOpts("Owner", ctx) + version := l2node.Execution.ArbInterface.BlockChain().Config().ArbitrumChainParams.InitialArbOSVersion + callOpts := l2info.GetDefaultCallOpts("Owner", ctx) // get the network fee account - arbOwnerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("0x6b"), testNode.L2Client) + arbOwnerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("0x6b"), l2client) Require(t, err, "failed to deploy contract") - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), testNode.L2Client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) Require(t, err, "failed to deploy contract") - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), testNode.L2Client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) Require(t, err, "failed to deploy contract") networkFeeAccount, err := arbOwnerPublic.GetNetworkFeeAccount(callOpts) Require(t, err, "could not get the network fee account") @@ -53,24 +53,24 @@ func TestSequencerFeePaid(t *testing.T) { l1Estimate, err := arbGasInfo.GetL1BaseFeeEstimate(callOpts) Require(t, err) - baseFee := testNode.GetBaseFeeAtViaL2(t, nil) - testNode.L2Info.GasPrice = baseFee + baseFee := GetBaseFee(t, l2client, ctx) + l2info.GasPrice = baseFee testFees := func(tip uint64) (*big.Int, *big.Int) { tipCap := arbmath.BigMulByUint(baseFee, tip) - txOpts := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := l2info.GetDefaultTransactOpts("Faucet", ctx) txOpts.GasTipCap = tipCap gasPrice := arbmath.BigAdd(baseFee, tipCap) - networkBefore := GetBalance(t, ctx, testNode.L2Client, networkFeeAccount) + networkBefore := GetBalance(t, ctx, l2client, networkFeeAccount) tx, err := arbDebug.Events(&txOpts, true, [32]byte{}) Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) + receipt, err := EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) - networkAfter := GetBalance(t, ctx, testNode.L2Client, networkFeeAccount) - l1Charge := arbmath.BigMulByUint(testNode.L2Info.GasPrice, receipt.GasUsedForL1) + networkAfter := GetBalance(t, ctx, l2client, networkFeeAccount) + l1Charge := arbmath.BigMulByUint(l2info.GasPrice, receipt.GasUsedForL1) // the network should receive // 1. compute costs @@ -92,7 +92,7 @@ func TestSequencerFeePaid(t *testing.T) { l1GasBought := arbmath.BigDiv(l1Charge, l1Estimate).Uint64() l1ChargeExpected := arbmath.BigMulByUint(l1Estimate, txSize*params.TxDataNonZeroGasEIP2028) // L1 gas can only be charged in terms of L2 gas, so subtract off any rounding error from the expected value - l1ChargeExpected.Sub(l1ChargeExpected, new(big.Int).Mod(l1ChargeExpected, testNode.L2Info.GasPrice)) + l1ChargeExpected.Sub(l1ChargeExpected, new(big.Int).Mod(l1ChargeExpected, l2info.GasPrice)) colors.PrintBlue("bytes ", l1GasBought/params.TxDataNonZeroGasEIP2028, txSize) @@ -135,38 +135,38 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { conf := arbnode.ConfigDefaultL1Test() conf.DelayedSequencer.FinalizeDistance = 1 - testNode := NewNodeBuilder(ctx).SetNodeConfig(conf).SetChainConfig(chainConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() + l2info, node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, chainConfig, nil) + defer requireClose(t, l1stack) + defer node.StopAndWait() - ownerAuth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + ownerAuth := l2info.GetDefaultTransactOpts("Owner", ctx) // make ownerAuth a chain owner - arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), testNode.L2Client) + arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) Require(t, err) tx, err := arbdebug.BecomeChainOwner(&ownerAuth) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2client, tx) // use ownerAuth to set the L1 price per unit Require(t, err) - arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), testNode.L2Client) + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), l2client) Require(t, err) tx, err = arbOwner.SetL1PricePerUnit(&ownerAuth, arbmath.UintToBig(initialEstimate)) Require(t, err) - _, err = WaitForTx(ctx, testNode.L2Client, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, l2client, tx.Hash(), time.Second*5) Require(t, err) - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), testNode.L2Client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) Require(t, err) lastEstimate, err := arbGasInfo.GetL1BaseFeeEstimate(&bind.CallOpts{Context: ctx}) Require(t, err) - lastBatchCount, err := testNode.L2Node.InboxTracker.GetBatchCount() + lastBatchCount, err := node.InboxTracker.GetBatchCount() Require(t, err) - l1Header, err := testNode.L1Client.HeaderByNumber(ctx, nil) + l1Header, err := l1client.HeaderByNumber(ctx, nil) Require(t, err) - rewardRecipientBalanceBefore := GetBalance(t, ctx, testNode.L2Client, l1pricing.BatchPosterAddress) + rewardRecipientBalanceBefore := GetBalance(t, ctx, l2client, l1pricing.BatchPosterAddress) timesPriceAdjusted := 0 colors.PrintBlue("Initial values") @@ -175,17 +175,17 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { numRetrogradeMoves := 0 for i := 0; i < 256; i++ { - tx, receipt := testNode.TransferBalanceViaL2(t, "Owner", "Owner", common.Big1) - header, err := testNode.L2Client.HeaderByHash(ctx, receipt.BlockHash) + tx, receipt := TransferBalance(t, "Owner", "Owner", common.Big1, l2info, l2client, ctx) + header, err := l2client.HeaderByHash(ctx, receipt.BlockHash) Require(t, err) - testNode.TransferBalanceViaL1(t, "Faucet", "Faucet", common.Big1) // generate l1 traffic + TransferBalance(t, "Faucet", "Faucet", common.Big1, l1info, l1client, ctx) // generate l1 traffic units := compressedTxSize(t, tx) * params.TxDataNonZeroGasEIP2028 estimatedL1FeePerUnit := arbmath.BigDivByUint(arbmath.BigMulByUint(header.BaseFee, receipt.GasUsedForL1), units) if !arbmath.BigEquals(lastEstimate, estimatedL1FeePerUnit) { - l1Header, err = testNode.L1Client.HeaderByNumber(ctx, nil) + l1Header, err = l1client.HeaderByNumber(ctx, nil) Require(t, err) callOpts := &bind.CallOpts{Context: ctx, BlockNumber: receipt.BlockNumber} @@ -234,7 +234,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { // see that the inbox advances for j := 16; j > 0; j-- { - newBatchCount, err := testNode.L2Node.InboxTracker.GetBatchCount() + newBatchCount, err := node.InboxTracker.GetBatchCount() Require(t, err) if newBatchCount > lastBatchCount { colors.PrintGrey("posted new batch ", newBatchCount) @@ -249,7 +249,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { } } - rewardRecipientBalanceAfter := GetBalance(t, ctx, testNode.L2Client, chainConfig.ArbitrumChainParams.InitialChainOwner) + rewardRecipientBalanceAfter := GetBalance(t, ctx, l2client, chainConfig.ArbitrumChainParams.InitialChainOwner) colors.PrintMint("reward recipient balance ", rewardRecipientBalanceBefore, " ➤ ", rewardRecipientBalanceAfter) colors.PrintMint("price changes ", timesPriceAdjusted) @@ -260,7 +260,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { Fatal(t, "reward recipient didn't get paid") } - arbAggregator, err := precompilesgen.NewArbAggregator(common.HexToAddress("0x6d"), testNode.L2Client) + arbAggregator, err := precompilesgen.NewArbAggregator(common.HexToAddress("0x6d"), l2client) Require(t, err) batchPosterAddresses, err := arbAggregator.GetBatchPosters(&bind.CallOpts{Context: ctx}) Require(t, err) @@ -268,7 +268,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { for _, bpAddr := range batchPosterAddresses { if bpAddr != l1pricing.BatchPosterAddress && bpAddr != l1pricing.L1PricerFundsPoolAddress { numReimbursed++ - bal, err := testNode.L1Client.BalanceAt(ctx, bpAddr, nil) + bal, err := l1client.BalanceAt(ctx, bpAddr, nil) Require(t, err) if bal.Sign() == 0 { Fatal(t, "Batch poster balance is zero for", bpAddr) diff --git a/system_tests/forwarder_test.go b/system_tests/forwarder_test.go index 753f067ed..0a954719d 100644 --- a/system_tests/forwarder_test.go +++ b/system_tests/forwarder_test.go @@ -40,9 +40,9 @@ func TestStaticForwarder(t *testing.T) { nodeConfigA := arbnode.ConfigDefaultL1Test() nodeConfigA.BatchPoster.Enable = false - testNodeA := NewNodeBuilder(ctx).SetNodeConfig(nodeConfigA).SetL2StackConfig(stackConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNodeA.L1Stack) - defer testNodeA.L2Node.StopAndWait() + l2info, nodeA, clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfigA, nil, stackConfig) + defer requireClose(t, l1stack) + defer nodeA.StopAndWait() nodeConfigB := arbnode.ConfigDefaultL1Test() nodeConfigB.Sequencer.Enable = false @@ -51,18 +51,18 @@ func TestStaticForwarder(t *testing.T) { nodeConfigB.ForwardingTarget = ipcPath nodeConfigB.BatchPoster.Enable = false - clientB, nodeB := Create2ndNodeWithConfig(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nodeConfigB, nil) + clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, nodeConfigB, nil) defer nodeB.StopAndWait() - testNodeA.L2Info.GenerateAccount("User2") - tx := testNodeA.L2Info.PrepareTx("Owner", "User2", testNodeA.L2Info.TransferGas, transferAmount, nil) + l2info.GenerateAccount("User2") + tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, transferAmount, nil) err := clientB.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, clientA, tx) Require(t, err) - l2balance, err := testNodeA.L2Client.BalanceAt(ctx, testNodeA.L2Info.GetAddress("User2"), nil) + l2balance, err := clientA.BalanceAt(ctx, l2info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(transferAmount) != 0 { @@ -105,8 +105,7 @@ func fallbackSequencer( nodeConfig.SeqCoordinator.Enable = opts.enableSecCoordinator nodeConfig.SeqCoordinator.RedisUrl = opts.redisUrl nodeConfig.SeqCoordinator.MyUrl = opts.ipcPath - testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeConfig).SetL2StackConfig(stackConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - return testNode.L2Info, testNode.L2Node, testNode.L2Client, testNode.L1Info, testNode.L1Backend, testNode.L1Client, testNode.L1Stack + return createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, stackConfig) } func createForwardingNode( diff --git a/system_tests/infra_fee_test.go b/system_tests/infra_fee_test.go index 10f43547f..89f869576 100644 --- a/system_tests/infra_fee_test.go +++ b/system_tests/infra_fee_test.go @@ -25,45 +25,45 @@ func TestInfraFee(t *testing.T) { defer cancel() nodeconfig := arbnode.ConfigDefaultL2Test() - testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeconfig).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, true) + defer node.StopAndWait() - testNode.L2Info.GenerateAccount("User2") + l2info.GenerateAccount("User2") - ownerTxOpts := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) ownerTxOpts.Context = ctx - ownerCallOpts := testNode.L2Info.GetDefaultCallOpts("Owner", ctx) + ownerCallOpts := l2info.GetDefaultCallOpts("Owner", ctx) - arbowner, err := precompilesgen.NewArbOwner(common.HexToAddress("70"), testNode.L2Client) + arbowner, err := precompilesgen.NewArbOwner(common.HexToAddress("70"), client) Require(t, err) - arbownerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("6b"), testNode.L2Client) + arbownerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("6b"), client) Require(t, err) networkFeeAddr, err := arbownerPublic.GetNetworkFeeAccount(ownerCallOpts) Require(t, err) infraFeeAddr := common.BytesToAddress(crypto.Keccak256([]byte{3, 2, 6})) tx, err := arbowner.SetInfraFeeAccount(&ownerTxOpts, infraFeeAddr) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client, tx) Require(t, err) - _, simple := testNode.DeploySimple(t, ownerTxOpts) + _, simple := deploySimple(t, ctx, ownerTxOpts, client) - netFeeBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) + netFeeBalanceBefore, err := client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - infraFeeBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) + infraFeeBalanceBefore, err := client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) tx, err = simple.Increment(&ownerTxOpts) Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) + receipt, err := EnsureTxSucceeded(ctx, client, tx) Require(t, err) l2GasUsed := receipt.GasUsed - receipt.GasUsedForL1 expectedFunds := arbmath.BigMulByUint(arbmath.UintToBig(l2pricing.InitialBaseFeeWei), l2GasUsed) expectedBalanceAfter := arbmath.BigAdd(infraFeeBalanceBefore, expectedFunds) - netFeeBalanceAfter, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) + netFeeBalanceAfter, err := client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - infraFeeBalanceAfter, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) + infraFeeBalanceAfter, err := client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) if !arbmath.BigEquals(netFeeBalanceBefore, netFeeBalanceAfter) { diff --git a/system_tests/initialization_test.go b/system_tests/initialization_test.go index cec68d693..c7797d35e 100644 --- a/system_tests/initialization_test.go +++ b/system_tests/initialization_test.go @@ -63,14 +63,14 @@ func TestInitContract(t *testing.T) { l2info.ArbInitData.Accounts = append(l2info.ArbInitData.Accounts, accountInfo) expectedSums[accountAddress] = sum } - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).SetL2Info(l2info).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + _, node, client := CreateTestL2WithConfig(t, ctx, l2info, arbnode.ConfigDefaultL2Test(), true) + defer node.StopAndWait() for accountAddress, sum := range expectedSums { msg := ethereum.CallMsg{ To: &accountAddress, } - res, err := testNode.L2Client.CallContract(ctx, msg, big.NewInt(0)) + res, err := client.CallContract(ctx, msg, big.NewInt(0)) Require(t, err) resBig := new(big.Int).SetBytes(res) if resBig.Cmp(sum) != 0 { diff --git a/system_tests/ipc_test.go b/system_tests/ipc_test.go index fbac4156c..01ecf859d 100644 --- a/system_tests/ipc_test.go +++ b/system_tests/ipc_test.go @@ -24,9 +24,9 @@ func TestIpcRpc(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetL2StackConfig(stackConf).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() + _, l2node, _, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, nil, stackConf) + defer requireClose(t, l1stack) + defer l2node.StopAndWait() _, err := ethclient.Dial(ipcPath) Require(t, err) diff --git a/system_tests/log_subscription_test.go b/system_tests/log_subscription_test.go index c64737bdc..5ee1732fb 100644 --- a/system_tests/log_subscription_test.go +++ b/system_tests/log_subscription_test.go @@ -12,7 +12,6 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" ) @@ -20,21 +19,21 @@ func TestLogSubscription(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + l2info, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() - auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) - arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, testNode.L2Client) + auth := l2info.GetDefaultTransactOpts("Owner", ctx) + arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, client) Require(t, err) logChan := make(chan types.Log, 128) - subscription, err := testNode.L2Client.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, logChan) + subscription, err := client.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, logChan) Require(t, err) defer subscription.Unsubscribe() tx, err := arbSys.WithdrawEth(&auth, common.Address{}) Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) + receipt, err := EnsureTxSucceeded(ctx, client, tx) Require(t, err) if len(receipt.Logs) != 1 { @@ -53,6 +52,6 @@ func TestLogSubscription(t *testing.T) { if !reflect.DeepEqual(receiptLog, subscriptionLog) { Fatal(t, "Receipt log", receiptLog, "is different than subscription log", subscriptionLog) } - _, err = testNode.L2Client.BlockByHash(ctx, subscriptionLog.BlockHash) + _, err = client.BlockByHash(ctx, subscriptionLog.BlockHash) Require(t, err) } diff --git a/system_tests/meaningless_reorg_test.go b/system_tests/meaningless_reorg_test.go index b30417a5a..851bf38ce 100644 --- a/system_tests/meaningless_reorg_test.go +++ b/system_tests/meaningless_reorg_test.go @@ -20,24 +20,24 @@ func TestMeaninglessBatchReorg(t *testing.T) { defer cancel() conf := arbnode.ConfigDefaultL1Test() conf.BatchPoster.Enable = false - testNode := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() + l2Info, arbNode, l2Client, l1Info, l1Backend, l1Client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil) + defer requireClose(t, l1stack) + defer arbNode.StopAndWait() - seqInbox, err := bridgegen.NewSequencerInbox(testNode.L1Info.GetAddress("SequencerInbox"), testNode.L1Client) + seqInbox, err := bridgegen.NewSequencerInbox(l1Info.GetAddress("SequencerInbox"), l1Client) Require(t, err) - seqOpts := testNode.L1Info.GetDefaultTransactOpts("Sequencer", ctx) + seqOpts := l1Info.GetDefaultTransactOpts("Sequencer", ctx) tx, err := seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(1), nil, big.NewInt(1), common.Address{}) Require(t, err) - batchReceipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, tx) + batchReceipt, err := EnsureTxSucceeded(ctx, l1Client, tx) Require(t, err) for i := 0; ; i++ { if i >= 500 { Fatal(t, "Failed to read batch from L1") } - msgNum, err := testNode.L2Node.Execution.ExecEngine.HeadMessageNumber() + msgNum, err := arbNode.Execution.ExecEngine.HeadMessageNumber() Require(t, err) if msgNum == 1 { break @@ -46,33 +46,33 @@ func TestMeaninglessBatchReorg(t *testing.T) { } time.Sleep(10 * time.Millisecond) } - metadata, err := testNode.L2Node.InboxTracker.GetBatchMetadata(1) + metadata, err := arbNode.InboxTracker.GetBatchMetadata(1) Require(t, err) originalBatchBlock := batchReceipt.BlockNumber.Uint64() if metadata.ParentChainBlock != originalBatchBlock { Fatal(t, "Posted batch in block", originalBatchBlock, "but metadata says L1 block was", metadata.ParentChainBlock) } - _, l2Receipt := testNode.TransferBalanceViaL2(t, "Owner", "Owner", common.Big1) + _, l2Receipt := TransferBalance(t, "Owner", "Owner", common.Big1, l2Info, l2Client, ctx) // Make the reorg larger to force the miner to discard transactions. // The miner usually collects transactions from deleted blocks and puts them in the mempool. // However, this code doesn't run on reorgs larger than 64 blocks for performance reasons. // Therefore, we make a bunch of small blocks to prevent the code from running. for j := uint64(0); j < 70; j++ { - testNode.TransferBalanceViaL1(t, "Faucet", "Faucet", common.Big1) + TransferBalance(t, "Faucet", "Faucet", common.Big1, l1Info, l1Client, ctx) } - parentBlock := testNode.L1Backend.BlockChain().GetBlockByNumber(batchReceipt.BlockNumber.Uint64() - 1) - err = testNode.L1Backend.BlockChain().ReorgToOldBlock(parentBlock) + parentBlock := l1Backend.BlockChain().GetBlockByNumber(batchReceipt.BlockNumber.Uint64() - 1) + err = l1Backend.BlockChain().ReorgToOldBlock(parentBlock) Require(t, err) // Produce a new l1Block so that the batch ends up in a different l1Block than before - testNode.TransferBalanceViaL1(t, "User", "User", common.Big1) + TransferBalance(t, "User", "User", common.Big1, l1Info, l1Client, ctx) tx, err = seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(1), nil, big.NewInt(1), common.Address{}) Require(t, err) - newBatchReceipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, tx) + newBatchReceipt, err := EnsureTxSucceeded(ctx, l1Client, tx) Require(t, err) newBatchBlock := newBatchReceipt.BlockNumber.Uint64() @@ -86,7 +86,7 @@ func TestMeaninglessBatchReorg(t *testing.T) { if i >= 500 { Fatal(t, "Failed to read batch reorg from L1") } - metadata, err = testNode.L2Node.InboxTracker.GetBatchMetadata(1) + metadata, err = arbNode.InboxTracker.GetBatchMetadata(1) Require(t, err) if metadata.ParentChainBlock == newBatchBlock { break @@ -96,10 +96,10 @@ func TestMeaninglessBatchReorg(t *testing.T) { time.Sleep(10 * time.Millisecond) } - _, err = testNode.L2Node.InboxReader.GetSequencerMessageBytes(ctx, 1) + _, err = arbNode.InboxReader.GetSequencerMessageBytes(ctx, 1) Require(t, err) - l2Header, err := testNode.L2Client.HeaderByNumber(ctx, l2Receipt.BlockNumber) + l2Header, err := l2Client.HeaderByNumber(ctx, l2Receipt.BlockNumber) Require(t, err) if l2Header.Hash() != l2Receipt.BlockHash { diff --git a/system_tests/nodeinterface_test.go b/system_tests/nodeinterface_test.go index 2f36fb1d7..167f2204c 100644 --- a/system_tests/nodeinterface_test.go +++ b/system_tests/nodeinterface_test.go @@ -19,23 +19,23 @@ func TestL2BlockRangeForL1(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() - user := testNode.L1Info.GetDefaultTransactOpts("User", ctx) + l2info, node, l2client, l1info, _, _, l1stack := createTestNodeOnL1(t, ctx, true) + defer requireClose(t, l1stack) + defer node.StopAndWait() + user := l1info.GetDefaultTransactOpts("User", ctx) numTransactions := 200 for i := 0; i < numTransactions; i++ { - testNode.TransferBalanceToViaL2(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18)) + TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), l2info, l2client, ctx) } - nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, testNode.L2Client) + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) if err != nil { t.Fatalf("Error creating node interface: %v", err) } l1BlockNums := map[uint64]*[2]uint64{} - latestL2, err := testNode.L2Client.BlockNumber(ctx) + latestL2, err := l2client.BlockNumber(ctx) if err != nil { t.Fatalf("Error querying most recent l2 block: %v", err) } diff --git a/system_tests/outbox_test.go b/system_tests/outbox_test.go index e0db03411..6b43cc83b 100644 --- a/system_tests/outbox_test.go +++ b/system_tests/outbox_test.go @@ -16,7 +16,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/gethhook" "github.com/offchainlabs/nitro/solgen/go/node_interfacegen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" @@ -36,14 +35,14 @@ func TestOutboxProofs(t *testing.T) { withdrawTopic := arbSysAbi.Events["L2ToL1Tx"].ID merkleTopic := arbSysAbi.Events["SendMerkleUpdate"].ID - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + l2info, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() - auth := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) + auth := l2info.GetDefaultTransactOpts("Owner", ctx) - arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, testNode.L2Client) + arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, client) Require(t, err) - nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, testNode.L2Client) + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, client) Require(t, err) txnCount := int64(1 + rand.Intn(16)) @@ -72,7 +71,7 @@ func TestOutboxProofs(t *testing.T) { txns = append(txns, tx.Hash()) time.Sleep(4 * time.Millisecond) // Geth takes a few ms for the receipt to show up - _, err = testNode.L2Client.TransactionReceipt(ctx, tx.Hash()) + _, err = client.TransactionReceipt(ctx, tx.Hash()) if err == nil { merkleState, err := arbSys.SendMerkleTreeState(&bind.CallOpts{}) Require(t, err, "could not get merkle root") @@ -87,7 +86,7 @@ func TestOutboxProofs(t *testing.T) { for _, tx := range txns { var receipt *types.Receipt - receipt, err = testNode.L2Client.TransactionReceipt(ctx, tx) + receipt, err = client.TransactionReceipt(ctx, tx) Require(t, err, "No receipt for txn") if receipt.Status != types.ReceiptStatusSuccessful { @@ -188,7 +187,7 @@ func TestOutboxProofs(t *testing.T) { // in one lookup, query geth for all the data we need to construct a proof var logs []types.Log if len(query) > 0 { - logs, err = testNode.L2Client.FilterLogs(ctx, ethereum.FilterQuery{ + logs, err = client.FilterLogs(ctx, ethereum.FilterQuery{ Addresses: []common.Address{ types.ArbSysAddress, }, diff --git a/system_tests/precompile_test.go b/system_tests/precompile_test.go index 261c45035..ad08ff747 100644 --- a/system_tests/precompile_test.go +++ b/system_tests/precompile_test.go @@ -11,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/params" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" @@ -22,10 +21,10 @@ func TestPurePrecompileMethodCalls(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + _, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() - arbSys, err := precompilesgen.NewArbSys(common.HexToAddress("0x64"), testNode.L2Client) + arbSys, err := precompilesgen.NewArbSys(common.HexToAddress("0x64"), client) Require(t, err, "could not deploy ArbSys contract") chainId, err := arbSys.ArbChainID(&bind.CallOpts{}) Require(t, err, "failed to get the ChainID") @@ -38,10 +37,10 @@ func TestViewLogReverts(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + _, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), testNode.L2Client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) Require(t, err, "could not deploy ArbSys contract") err = arbDebug.EventsView(nil) @@ -54,11 +53,11 @@ func TestCustomSolidityErrors(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + _, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() callOpts := &bind.CallOpts{Context: ctx} - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), testNode.L2Client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) Require(t, err, "could not bind ArbDebug contract") customError := arbDebug.CustomRevert(callOpts, 1024) if customError == nil { @@ -70,7 +69,7 @@ func TestCustomSolidityErrors(t *testing.T) { Fatal(t, observedMessage) } - arbSys, err := precompilesgen.NewArbSys(arbos.ArbSysAddress, testNode.L2Client) + arbSys, err := precompilesgen.NewArbSys(arbos.ArbSysAddress, client) Require(t, err, "could not bind ArbSys contract") _, customError = arbSys.ArbBlockHash(callOpts, big.NewInt(1e9)) if customError == nil { @@ -87,11 +86,11 @@ func TestPrecompileErrorGasLeft(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + info, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() - auth := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) - _, _, simple, err := mocksgen.DeploySimple(&auth, testNode.L2Client) + auth := info.GetDefaultTransactOpts("Faucet", ctx) + _, _, simple, err := mocksgen.DeploySimple(&auth, client) Require(t, err) assertNotAllGasConsumed := func(to common.Address, input []byte) { diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index 5224f21bf..dbf68c847 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -21,26 +21,26 @@ import ( "github.com/offchainlabs/nitro/util" ) -func prepareNodeWithHistory(t *testing.T, ctx context.Context, nodeConfig *arbnode.Config, txCount uint64) (*arbnode.Node, *execution.ExecutionNode, *ethclient.Client, func()) { +func prepareNodeWithHistory(t *testing.T, ctx context.Context, nodeConfig *arbnode.Config, txCount uint64) (node *arbnode.Node, executionNode *execution.ExecutionNode, l2client *ethclient.Client, cancel func()) { t.Helper() - testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - cancel := func() { - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() + l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, nil) + cancel = func() { + defer requireClose(t, l1stack) + defer node.StopAndWait() } - testNode.L2Info.GenerateAccount("User2") + l2info.GenerateAccount("User2") var txs []*types.Transaction for i := uint64(0); i < txCount; i++ { - tx := testNode.L2Info.PrepareTx("Owner", "User2", testNode.L2Info.TransferGas, common.Big1, nil) + tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, common.Big1, nil) txs = append(txs, tx) - err := testNode.L2Client.SendTransaction(ctx, tx) + err := l2client.SendTransaction(ctx, tx) Require(t, err) } for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err := EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) } - return testNode.L2Node, testNode.L2Node.Execution, testNode.L2Client, cancel + return node, node.Execution, l2client, cancel } func fillHeaderCache(t *testing.T, bc *core.BlockChain, from, to uint64) { diff --git a/system_tests/reorg_resequencing_test.go b/system_tests/reorg_resequencing_test.go index 0251969e3..f132d4648 100644 --- a/system_tests/reorg_resequencing_test.go +++ b/system_tests/reorg_resequencing_test.go @@ -11,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/params" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/arbostypes" ) @@ -20,27 +19,27 @@ func TestReorgResequencing(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + l2info, node, client := CreateTestL2(t, ctx) + defer node.StopAndWait() - startMsgCount, err := testNode.L2Node.TxStreamer.GetMessageCount() + startMsgCount, err := node.TxStreamer.GetMessageCount() Require(t, err) - testNode.L2Info.GenerateAccount("Intermediate") - testNode.L2Info.GenerateAccount("User1") - testNode.L2Info.GenerateAccount("User2") - testNode.L2Info.GenerateAccount("User3") - testNode.L2Info.GenerateAccount("User4") - testNode.TransferBalanceViaL2(t, "Owner", "User1", big.NewInt(params.Ether)) - testNode.TransferBalanceViaL2(t, "Owner", "Intermediate", big.NewInt(params.Ether*3)) - testNode.TransferBalanceViaL2(t, "Intermediate", "User2", big.NewInt(params.Ether)) - testNode.TransferBalanceViaL2(t, "Intermediate", "User3", big.NewInt(params.Ether)) + l2info.GenerateAccount("Intermediate") + l2info.GenerateAccount("User1") + l2info.GenerateAccount("User2") + l2info.GenerateAccount("User3") + l2info.GenerateAccount("User4") + TransferBalance(t, "Owner", "User1", big.NewInt(params.Ether), l2info, client, ctx) + TransferBalance(t, "Owner", "Intermediate", big.NewInt(params.Ether*3), l2info, client, ctx) + TransferBalance(t, "Intermediate", "User2", big.NewInt(params.Ether), l2info, client, ctx) + TransferBalance(t, "Intermediate", "User3", big.NewInt(params.Ether), l2info, client, ctx) // Intermediate does not have exactly 1 ether because of fees accountsWithBalance := []string{"User1", "User2", "User3"} verifyBalances := func(scenario string) { for _, account := range accountsWithBalance { - balance, err := testNode.L2Client.BalanceAt(ctx, testNode.L2Info.GetAddress(account), nil) + balance, err := client.BalanceAt(ctx, l2info.GetAddress(account), nil) Require(t, err) if balance.Int64() != params.Ether { Fatal(t, "expected account", account, "to have a balance of 1 ether but instead it has", balance, "wei "+scenario) @@ -49,15 +48,15 @@ func TestReorgResequencing(t *testing.T) { } verifyBalances("before reorg") - err = testNode.L2Node.TxStreamer.ReorgTo(startMsgCount) + err = node.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = testNode.L2Node.Execution.ExecEngine.HeadMessageNumberSync(t) + _, err = node.Execution.ExecEngine.HeadMessageNumberSync(t) Require(t, err) verifyBalances("after empty reorg") - prevMessage, err := testNode.L2Node.TxStreamer.GetMessage(startMsgCount - 1) + prevMessage, err := node.TxStreamer.GetMessage(startMsgCount - 1) Require(t, err) delayedIndexHash := common.BigToHash(big.NewInt(int64(prevMessage.DelayedMessagesRead))) newMessage := &arbostypes.L1IncomingMessage{ @@ -69,24 +68,24 @@ func TestReorgResequencing(t *testing.T) { RequestId: &delayedIndexHash, L1BaseFee: common.Big0, }, - L2msg: append(testNode.L2Info.GetAddress("User4").Bytes(), math.U256Bytes(big.NewInt(params.Ether))...), + L2msg: append(l2info.GetAddress("User4").Bytes(), math.U256Bytes(big.NewInt(params.Ether))...), } - err = testNode.L2Node.TxStreamer.AddMessages(startMsgCount, true, []arbostypes.MessageWithMetadata{{ + err = node.TxStreamer.AddMessages(startMsgCount, true, []arbostypes.MessageWithMetadata{{ Message: newMessage, DelayedMessagesRead: prevMessage.DelayedMessagesRead + 1, }}) Require(t, err) - _, err = testNode.L2Node.Execution.ExecEngine.HeadMessageNumberSync(t) + _, err = node.Execution.ExecEngine.HeadMessageNumberSync(t) Require(t, err) accountsWithBalance = append(accountsWithBalance, "User4") verifyBalances("after reorg with new deposit") - err = testNode.L2Node.TxStreamer.ReorgTo(startMsgCount) + err = node.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = testNode.L2Node.Execution.ExecEngine.HeadMessageNumberSync(t) + _, err = node.Execution.ExecEngine.HeadMessageNumberSync(t) Require(t, err) verifyBalances("after second empty reorg") diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 61c258893..b1dd32d1d 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -32,22 +32,25 @@ import ( ) func retryableSetup(t *testing.T) ( - *NodeBuilder, + *BlockchainTestInfo, + *BlockchainTestInfo, + *ethclient.Client, + *ethclient.Client, *bridgegen.Inbox, func(*types.Receipt) *types.Transaction, context.Context, func(), ) { ctx, cancel := context.WithCancel(context.Background()) - testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + l2info, l2node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - testNode.L2Info.GenerateAccount("User2") - testNode.L2Info.GenerateAccount("Beneficiary") - testNode.L2Info.GenerateAccount("Burn") + l2info.GenerateAccount("User2") + l2info.GenerateAccount("Beneficiary") + l2info.GenerateAccount("Burn") - delayedInbox, err := bridgegen.NewInbox(testNode.L1Info.GetAddress("Inbox"), testNode.L1Client) + delayedInbox, err := bridgegen.NewInbox(l1info.GetAddress("Inbox"), l1client) Require(t, err) - delayedBridge, err := arbnode.NewDelayedBridge(testNode.L1Client, testNode.L1Info.GetAddress("Bridge"), 0) + delayedBridge, err := arbnode.NewDelayedBridge(l1client, l1info.GetAddress("Bridge"), 0) Require(t, err) lookupL2Tx := func(l1Receipt *types.Receipt) *types.Transaction { @@ -87,15 +90,15 @@ func retryableSetup(t *testing.T) ( // burn some gas so that the faucet's Callvalue + Balance never exceeds a uint256 discard := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - testNode.TransferBalanceViaL2(t, "Faucet", "Burn", discard) + TransferBalance(t, "Faucet", "Burn", discard, l2info, l2client, ctx) teardown := func() { // check the integrity of the RPC - blockNum, err := testNode.L2Client.BlockNumber(ctx) + blockNum, err := l2client.BlockNumber(ctx) Require(t, err, "failed to get L2 block number") for number := uint64(0); number < blockNum; number++ { - block, err := testNode.L2Client.BlockByNumber(ctx, arbmath.UintToBig(number)) + block, err := l2client.BlockByNumber(ctx, arbmath.UintToBig(number)) Require(t, err, "failed to get L2 block", number, "of", blockNum) if block.Number().Uint64() != number { Fatal(t, "block number mismatch", number, block.Number().Uint64()) @@ -104,20 +107,19 @@ func retryableSetup(t *testing.T) ( cancel() - testNode.L2Node.StopAndWait() - requireClose(t, testNode.L1Stack) + l2node.StopAndWait() + requireClose(t, l1stack) } - return testNode, delayedInbox, lookupL2Tx, ctx, teardown + return l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown } func TestRetryableNoExist(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() + _, node, l2client := CreateTestL2(t, ctx) + defer node.StopAndWait() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() - - arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), testNode.L2Client) + arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) Require(t, err) _, err = arbRetryableTx.GetTimeout(&bind.CallOpts{}, common.Hash{}) if err.Error() != "execution reverted: error NoTicketWithID()" { @@ -127,20 +129,20 @@ func TestRetryableNoExist(t *testing.T) { func TestSubmitRetryableImmediateSuccess(t *testing.T) { t.Parallel() - testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - user2Address := testNode.L2Info.GetAddress("User2") - beneficiaryAddress := testNode.L2Info.GetAddress("Beneficiary") + user2Address := l2info.GetAddress("User2") + beneficiaryAddress := l2info.GetAddress("Beneficiary") deposit := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) callValue := big.NewInt(1e6) - nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, testNode.L2Client) + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) Require(t, err, "failed to deploy NodeInterface") // estimate the gas needed to auto redeem the retryable - usertxoptsL2 := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL2 := l2info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL2.NoSend = true usertxoptsL2.GasMargin = 0 tx, err := nodeInterface.EstimateRetryableTicket( @@ -158,7 +160,7 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { colors.PrintBlue("estimate: ", estimate) // submit & auto redeem the retryable using the gas estimate - usertxoptsL1 := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL1 := l1info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL1.Value = deposit l1tx, err := delayedInbox.CreateRetryableTicket( &usertxoptsL1, @@ -173,21 +175,21 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) + l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) + waitForL1DelayBlocks(t, ctx, l1client, l1info) - receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, lookupL2Tx(l1Receipt)) + receipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) Require(t, err) if receipt.Status != types.ReceiptStatusSuccessful { Fatal(t) } - l2balance, err := testNode.L2Client.BalanceAt(ctx, testNode.L2Info.GetAddress("User2"), nil) + l2balance, err := l2client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) Require(t, err) if !arbmath.BigEquals(l2balance, big.NewInt(1e6)) { @@ -197,18 +199,18 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { func TestSubmitRetryableFailThenRetry(t *testing.T) { t.Parallel() - testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - ownerTxOpts := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) - usertxopts := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) + ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) + usertxopts := l1info.GetDefaultTransactOpts("Faucet", ctx) usertxopts.Value = arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - simpleAddr, simple := testNode.DeploySimple(t, ownerTxOpts) + simpleAddr, simple := deploySimple(t, ctx, ownerTxOpts, l2client) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) - beneficiaryAddress := testNode.L2Info.GetAddress("Beneficiary") + beneficiaryAddress := l2info.GetAddress("Beneficiary") l1tx, err := delayedInbox.CreateRetryableTicket( &usertxopts, simpleAddr, @@ -223,15 +225,15 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) + l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) + waitForL1DelayBlocks(t, ctx, l1client, l1info) - receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, lookupL2Tx(l1Receipt)) + receipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) Require(t, err) if len(receipt.Logs) != 2 { Fatal(t, len(receipt.Logs)) @@ -240,23 +242,23 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { firstRetryTxId := receipt.Logs[1].Topics[2] // get receipt for the auto redeem, make sure it failed - receipt, err = WaitForTx(ctx, testNode.L2Client, firstRetryTxId, time.Second*5) + receipt, err = WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) Require(t, err) if receipt.Status != types.ReceiptStatusFailed { Fatal(t, receipt.GasUsed) } - arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), testNode.L2Client) + arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) Require(t, err) tx, err := arbRetryableTx.Redeem(&ownerTxOpts, ticketId) Require(t, err) - receipt, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + receipt, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) retryTxId := receipt.Logs[0].Topics[2] // check the receipt for the retry - receipt, err = WaitForTx(ctx, testNode.L2Client, retryTxId, time.Second*1) + receipt, err = WaitForTx(ctx, l2client, retryTxId, time.Second*1) Require(t, err) if receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, receipt.Status) @@ -286,32 +288,32 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { func TestSubmissionGasCosts(t *testing.T) { t.Parallel() - testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, testNode.L2Client, testNode.L2Info) - elevateL2Basefee(t, ctx, testNode) + infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, l2client, l2info) + elevateL2Basefee(t, ctx, l2client, l2info) - usertxopts := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) + usertxopts := l1info.GetDefaultTransactOpts("Faucet", ctx) usertxopts.Value = arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - testNode.L2Info.GenerateAccount("Refund") - testNode.L2Info.GenerateAccount("Receive") - faucetAddress := util.RemapL1Address(testNode.L1Info.GetAddress("Faucet")) - beneficiaryAddress := testNode.L2Info.GetAddress("Beneficiary") - feeRefundAddress := testNode.L2Info.GetAddress("Refund") - receiveAddress := testNode.L2Info.GetAddress("Receive") + l2info.GenerateAccount("Refund") + l2info.GenerateAccount("Receive") + faucetAddress := util.RemapL1Address(l1info.GetAddress("Faucet")) + beneficiaryAddress := l2info.GetAddress("Beneficiary") + feeRefundAddress := l2info.GetAddress("Refund") + receiveAddress := l2info.GetAddress("Receive") colors.PrintBlue("Faucet ", faucetAddress) colors.PrintBlue("Receive ", receiveAddress) colors.PrintBlue("Beneficiary ", beneficiaryAddress) colors.PrintBlue("Fee Refund ", feeRefundAddress) - fundsBeforeSubmit, err := testNode.L2Client.BalanceAt(ctx, faucetAddress, nil) + fundsBeforeSubmit, err := l2client.BalanceAt(ctx, faucetAddress, nil) Require(t, err) - infraBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceBefore, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceBefore, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) usefulGas := params.TxGas @@ -335,28 +337,28 @@ func TestSubmissionGasCosts(t *testing.T) { ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) + l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) + waitForL1DelayBlocks(t, ctx, l1client, l1info) submissionTxOuter := lookupL2Tx(l1Receipt) - submissionReceipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, submissionTxOuter) + submissionReceipt, err := EnsureTxSucceeded(ctx, l2client, submissionTxOuter) Require(t, err) if len(submissionReceipt.Logs) != 2 { Fatal(t, "Unexpected number of logs:", len(submissionReceipt.Logs)) } firstRetryTxId := submissionReceipt.Logs[1].Topics[2] // get receipt for the auto redeem - redeemReceipt, err := WaitForTx(ctx, testNode.L2Client, firstRetryTxId, time.Second*5) + redeemReceipt, err := WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) Require(t, err) if redeemReceipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "first retry tx failed") } - redeemBlock, err := testNode.L2Client.HeaderByNumber(ctx, redeemReceipt.BlockNumber) + redeemBlock, err := l2client.HeaderByNumber(ctx, redeemReceipt.BlockNumber) Require(t, err) l2BaseFee := redeemBlock.BaseFee @@ -364,18 +366,18 @@ func TestSubmissionGasCosts(t *testing.T) { excessWei := arbmath.BigMulByUint(l2BaseFee, excessGasLimit) excessWei.Add(excessWei, arbmath.BigMul(excessGasPrice, retryableGas)) - fundsAfterSubmit, err := testNode.L2Client.BalanceAt(ctx, faucetAddress, nil) + fundsAfterSubmit, err := l2client.BalanceAt(ctx, faucetAddress, nil) Require(t, err) - beneficiaryFunds, err := testNode.L2Client.BalanceAt(ctx, beneficiaryAddress, nil) + beneficiaryFunds, err := l2client.BalanceAt(ctx, beneficiaryAddress, nil) Require(t, err) - refundFunds, err := testNode.L2Client.BalanceAt(ctx, feeRefundAddress, nil) + refundFunds, err := l2client.BalanceAt(ctx, feeRefundAddress, nil) Require(t, err) - receiveFunds, err := testNode.L2Client.BalanceAt(ctx, receiveAddress, nil) + receiveFunds, err := l2client.BalanceAt(ctx, receiveAddress, nil) Require(t, err) - infraBalanceAfter, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceAfter, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceAfter, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceAfter, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) colors.PrintBlue("CallGas ", retryableGas) @@ -422,7 +424,7 @@ func TestSubmissionGasCosts(t *testing.T) { Fatal(t, "Supplied gas was improperly deducted\n", fundsBeforeSubmit, "\n", fundsAfterSubmit) } - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), testNode.L2Client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) Require(t, err) minimumBaseFee, err := arbGasInfo.GetMinimumGasPrice(&bind.CallOpts{Context: ctx}) Require(t, err) @@ -458,17 +460,17 @@ func waitForL1DelayBlocks(t *testing.T, ctx context.Context, l1client *ethclient func TestDepositETH(t *testing.T) { t.Parallel() - testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + _, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - faucetAddr := testNode.L1Info.GetAddress("Faucet") + faucetAddr := l1info.GetAddress("Faucet") - oldBalance, err := testNode.L2Client.BalanceAt(ctx, faucetAddr, nil) + oldBalance, err := l2client.BalanceAt(ctx, faucetAddr, nil) if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", faucetAddr, err) } - txOpts := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := l1info.GetDefaultTransactOpts("Faucet", ctx) txOpts.Value = big.NewInt(13) l1tx, err := delayedInbox.DepositEth0(&txOpts) @@ -476,20 +478,20 @@ func TestDepositETH(t *testing.T) { t.Fatalf("DepositEth0() unexected error: %v", err) } - l1Receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) + l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) if err != nil { t.Fatalf("EnsureTxSucceeded() unexpected error: %v", err) } if l1Receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("Got transaction status: %v, want: %v", l1Receipt.Status, types.ReceiptStatusSuccessful) } - waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) + waitForL1DelayBlocks(t, ctx, l1client, l1info) - l2Receipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, lookupL2Tx(l1Receipt)) + l2Receipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) if err != nil { t.Fatalf("EnsureTxSucceeded unexpected error: %v", err) } - newBalance, err := testNode.L2Client.BalanceAt(ctx, faucetAddr, l2Receipt.BlockNumber) + newBalance, err := l2client.BalanceAt(ctx, faucetAddr, l2Receipt.BlockNumber) if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", faucetAddr, err) } @@ -499,13 +501,13 @@ func TestDepositETH(t *testing.T) { } func TestArbitrumContractTx(t *testing.T) { - testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + l2Info, l1Info, l2Client, l1Client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - faucetL2Addr := util.RemapL1Address(testNode.L1Info.GetAddress("Faucet")) - testNode.TransferBalanceToViaL2(t, "Faucet", faucetL2Addr, big.NewInt(1e18)) + faucetL2Addr := util.RemapL1Address(l1Info.GetAddress("Faucet")) + TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), l2Info, l2Client, ctx) - l2TxOpts := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) - l2ContractAddr, _ := testNode.DeploySimple(t, l2TxOpts) + l2TxOpts := l2Info.GetDefaultTransactOpts("Faucet", ctx) + l2ContractAddr, _ := deploySimple(t, ctx, l2TxOpts, l2Client) l2ContractABI, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) if err != nil { t.Fatalf("Error parsing contract ABI: %v", err) @@ -515,15 +517,15 @@ func TestArbitrumContractTx(t *testing.T) { t.Fatalf("Error packing method's call data: %v", err) } unsignedTx := types.NewTx(&types.ArbitrumContractTx{ - ChainId: testNode.L2Info.Signer.ChainID(), + ChainId: l2Info.Signer.ChainID(), From: faucetL2Addr, - GasFeeCap: testNode.L2Info.GasPrice.Mul(testNode.L2Info.GasPrice, big.NewInt(2)), + GasFeeCap: l2Info.GasPrice.Mul(l2Info.GasPrice, big.NewInt(2)), Gas: 1e6, To: &l2ContractAddr, Value: common.Big0, Data: data, }) - txOpts := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := l1Info.GetDefaultTransactOpts("Faucet", ctx) l1tx, err := delayedInbox.SendContractTransaction( &txOpts, arbmath.UintToBig(unsignedTx.Gas()), @@ -535,15 +537,15 @@ func TestArbitrumContractTx(t *testing.T) { if err != nil { t.Fatalf("Error sending unsigned transaction: %v", err) } - receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) + receipt, err := EnsureTxSucceeded(ctx, l1Client, l1tx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", l1tx.Hash(), err) } if receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("L1 transaction: %v has failed", l1tx.Hash()) } - waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) - receipt, err = EnsureTxSucceeded(ctx, testNode.L2Client, lookupL2Tx(receipt)) + waitForL1DelayBlocks(t, ctx, l1Client, l1Info) + receipt, err = EnsureTxSucceeded(ctx, l2Client, lookupL2Tx(receipt)) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", unsignedTx.Hash(), err) } @@ -552,17 +554,17 @@ func TestArbitrumContractTx(t *testing.T) { func TestL1FundedUnsignedTransaction(t *testing.T) { t.Parallel() ctx := context.Background() - testNode := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() + l2Info, node, l2Client, l1Info, _, l1Client, l1Stack := createTestNodeOnL1(t, ctx, true) + defer requireClose(t, l1Stack) + defer node.StopAndWait() - faucetL2Addr := util.RemapL1Address(testNode.L1Info.GetAddress("Faucet")) + faucetL2Addr := util.RemapL1Address(l1Info.GetAddress("Faucet")) // Transfer balance to Faucet's corresponding L2 address, so that there is // enough balance on its' account for executing L2 transaction. - testNode.TransferBalanceToViaL2(t, "Faucet", faucetL2Addr, big.NewInt(1e18)) + TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), l2Info, l2Client, ctx) - l2TxOpts := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) - contractAddr, _ := testNode.DeploySimple(t, l2TxOpts) + l2TxOpts := l2Info.GetDefaultTransactOpts("Faucet", ctx) + contractAddr, _ := deploySimple(t, ctx, l2TxOpts, l2Client) contractABI, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) if err != nil { t.Fatalf("Error parsing contract ABI: %v", err) @@ -571,27 +573,27 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { if err != nil { t.Fatalf("Error packing method's call data: %v", err) } - nonce, err := testNode.L2Client.NonceAt(ctx, faucetL2Addr, nil) + nonce, err := l2Client.NonceAt(ctx, faucetL2Addr, nil) if err != nil { t.Fatalf("Error getting nonce at address: %v, error: %v", faucetL2Addr, err) } unsignedTx := types.NewTx(&types.ArbitrumUnsignedTx{ - ChainId: testNode.L2Info.Signer.ChainID(), + ChainId: l2Info.Signer.ChainID(), From: faucetL2Addr, Nonce: nonce, - GasFeeCap: testNode.L2Info.GasPrice, + GasFeeCap: l2Info.GasPrice, Gas: 1e6, To: &contractAddr, Value: common.Big0, Data: data, }) - delayedInbox, err := bridgegen.NewInbox(testNode.L1Info.GetAddress("Inbox"), testNode.L1Client) + delayedInbox, err := bridgegen.NewInbox(l1Info.GetAddress("Inbox"), l1Client) if err != nil { t.Fatalf("Error getting Go binding of L1 Inbox contract: %v", err) } - txOpts := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := l1Info.GetDefaultTransactOpts("Faucet", ctx) l1tx, err := delayedInbox.SendUnsignedTransaction( &txOpts, arbmath.UintToBig(unsignedTx.Gas()), @@ -604,15 +606,15 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { if err != nil { t.Fatalf("Error sending unsigned transaction: %v", err) } - receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) + receipt, err := EnsureTxSucceeded(ctx, l1Client, l1tx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", l1tx.Hash(), err) } if receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("L1 transaction: %v has failed", l1tx.Hash()) } - waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) - receipt, err = EnsureTxSucceeded(ctx, testNode.L2Client, unsignedTx) + waitForL1DelayBlocks(t, ctx, l1Client, l1Info) + receipt, err = EnsureTxSucceeded(ctx, l2Client, unsignedTx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", unsignedTx.Hash(), err) } @@ -622,28 +624,28 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { } func TestRetryableSubmissionAndRedeemFees(t *testing.T) { - testNode, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, testNode.L2Client, testNode.L2Info) + infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, l2client, l2info) - ownerTxOpts := testNode.L2Info.GetDefaultTransactOpts("Owner", ctx) - simpleAddr, simple := testNode.DeploySimple(t, ownerTxOpts) + ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) + simpleAddr, simple := deploySimple(t, ctx, ownerTxOpts, l2client) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) - elevateL2Basefee(t, ctx, testNode) + elevateL2Basefee(t, ctx, l2client, l2info) - infraBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceBefore, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceBefore, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceBefore, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - beneficiaryAddress := testNode.L2Info.GetAddress("Beneficiary") + beneficiaryAddress := l2info.GetAddress("Beneficiary") deposit := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) callValue := common.Big0 - usertxoptsL1 := testNode.L1Info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL1 := l1info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL1.Value = deposit - baseFee := testNode.GetBaseFeeAtViaL2(t, nil) + baseFee := GetBaseFee(t, l2client, ctx) l1tx, err := delayedInbox.CreateRetryableTicket( &usertxoptsL1, simpleAddr, @@ -657,16 +659,16 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { simpleABI.Methods["incrementRedeem"].ID, ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, testNode.L1Client, l1tx) + l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, testNode.L1Client, testNode.L1Info) + waitForL1DelayBlocks(t, ctx, l1client, l1info) submissionTxOuter := lookupL2Tx(l1Receipt) - submissionReceipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, submissionTxOuter) + submissionReceipt, err := EnsureTxSucceeded(ctx, l2client, submissionTxOuter) Require(t, err) if len(submissionReceipt.Logs) != 2 { Fatal(t, len(submissionReceipt.Logs)) @@ -674,36 +676,36 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { ticketId := submissionReceipt.Logs[0].Topics[1] firstRetryTxId := submissionReceipt.Logs[1].Topics[2] // get receipt for the auto redeem, make sure it failed - autoRedeemReceipt, err := WaitForTx(ctx, testNode.L2Client, firstRetryTxId, time.Second*5) + autoRedeemReceipt, err := WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) Require(t, err) if autoRedeemReceipt.Status != types.ReceiptStatusFailed { Fatal(t, "first retry tx shouldn't have succeeded") } - infraBalanceAfterSubmission, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceAfterSubmission, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceAfterSubmission, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceAfterSubmission, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - usertxoptsL2 := testNode.L2Info.GetDefaultTransactOpts("Faucet", ctx) - arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), testNode.L2Client) + usertxoptsL2 := l2info.GetDefaultTransactOpts("Faucet", ctx) + arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) Require(t, err) tx, err := arbRetryableTx.Redeem(&usertxoptsL2, ticketId) Require(t, err) - redeemReceipt, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) + redeemReceipt, err := EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) retryTxId := redeemReceipt.Logs[0].Topics[2] // check the receipt for the retry - retryReceipt, err := WaitForTx(ctx, testNode.L2Client, retryTxId, time.Second*1) + retryReceipt, err := WaitForTx(ctx, l2client, retryTxId, time.Second*1) Require(t, err) if retryReceipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "retry failed") } - infraBalanceAfterRedeem, err := testNode.L2Client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceAfterRedeem, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceAfterRedeem, err := testNode.L2Client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceAfterRedeem, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) // verify that the increment happened, so we know the retry succeeded @@ -732,11 +734,11 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { infraRedeemFee := arbmath.BigSub(infraBalanceAfterRedeem, infraBalanceAfterSubmission) networkRedeemFee := arbmath.BigSub(networkBalanceAfterRedeem, networkBalanceAfterSubmission) - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), testNode.L2Client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) Require(t, err) minimumBaseFee, err := arbGasInfo.GetMinimumGasPrice(&bind.CallOpts{Context: ctx}) Require(t, err) - submissionBaseFee := testNode.GetBaseFeeAtViaL2(t, submissionReceipt.BlockNumber) + submissionBaseFee := GetBaseFeeAt(t, l2client, ctx, submissionReceipt.BlockNumber) submissionTx, ok := submissionTxOuter.GetInner().(*types.ArbitrumSubmitRetryableTx) if !ok { Fatal(t, "inner tx isn't ArbitrumSubmitRetryableTx") @@ -750,13 +752,13 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { retryableSubmissionFee, ) - retryTxOuter, _, err := testNode.L2Client.TransactionByHash(ctx, retryTxId) + retryTxOuter, _, err := l2client.TransactionByHash(ctx, retryTxId) Require(t, err) retryTx, ok := retryTxOuter.GetInner().(*types.ArbitrumRetryTx) if !ok { Fatal(t, "inner tx isn't ArbitrumRetryTx") } - redeemBaseFee := testNode.GetBaseFeeAtViaL2(t, redeemReceipt.BlockNumber) + redeemBaseFee := GetBaseFeeAt(t, l2client, ctx, redeemReceipt.BlockNumber) t.Log("redeem base fee:", redeemBaseFee) // redeem & retry expected fees @@ -792,29 +794,29 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { } // elevateL2Basefee by burning gas exceeding speed limit -func elevateL2Basefee(t *testing.T, ctx context.Context, testNode *NodeBuilder) { - baseFeeBefore := testNode.GetBaseFeeAtViaL2(t, nil) +func elevateL2Basefee(t *testing.T, ctx context.Context, l2client *ethclient.Client, l2info *BlockchainTestInfo) { + baseFeeBefore := GetBaseFee(t, l2client, ctx) colors.PrintBlue("Elevating base fee...") arbostestabi, err := precompilesgen.ArbosTestMetaData.GetAbi() Require(t, err) - _, err = precompilesgen.NewArbosTest(common.HexToAddress("0x69"), testNode.L2Client) + _, err = precompilesgen.NewArbosTest(common.HexToAddress("0x69"), l2client) Require(t, err, "failed to deploy ArbosTest") burnAmount := arbnode.ConfigDefaultL1Test().RPC.RPCGasCap burnTarget := uint64(5 * l2pricing.InitialSpeedLimitPerSecondV6 * l2pricing.InitialBacklogTolerance) for i := uint64(0); i < (burnTarget+burnAmount)/burnAmount; i++ { burnArbGas := arbostestabi.Methods["burnArbGas"] - data, err := burnArbGas.Inputs.Pack(arbmath.UintToBig(burnAmount - testNode.L2Info.TransferGas)) + data, err := burnArbGas.Inputs.Pack(arbmath.UintToBig(burnAmount - l2info.TransferGas)) Require(t, err) input := append([]byte{}, burnArbGas.ID...) input = append(input, data...) to := common.HexToAddress("0x69") - tx := testNode.L2Info.PrepareTxTo("Faucet", &to, burnAmount, big.NewInt(0), input) - Require(t, testNode.L2Client.SendTransaction(ctx, tx)) - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + tx := l2info.PrepareTxTo("Faucet", &to, burnAmount, big.NewInt(0), input) + Require(t, l2client.SendTransaction(ctx, tx)) + _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) } - baseFee := testNode.GetBaseFeeAtViaL2(t, nil) + baseFee := GetBaseFee(t, l2client, ctx) colors.PrintBlue("New base fee: ", baseFee, " diff:", baseFee.Uint64()-baseFeeBefore.Uint64()) } diff --git a/system_tests/seq_coordinator_test.go b/system_tests/seq_coordinator_test.go index 1e55e1c88..b1f50c943 100644 --- a/system_tests/seq_coordinator_test.go +++ b/system_tests/seq_coordinator_test.go @@ -62,8 +62,8 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { createStartNode := func(nodeNum int) { nodeConfig.SeqCoordinator.MyUrl = nodeNames[nodeNum] - testNode := NewNodeBuilder(ctx).SetNodeConfig(nodeConfig).SetL2Info(l2Info).CreateTestNodeOnL2Only(t, false) - nodes[nodeNum] = testNode.L2Node + _, node, _ := CreateTestL2WithConfig(t, ctx, l2Info, nodeConfig, false) + nodes[nodeNum] = node } trySequencing := func(nodeNum int) bool { @@ -278,9 +278,9 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { initRedisForTest(t, ctx, nodeConfig.SeqCoordinator.RedisUrl, nodeNames) nodeConfig.SeqCoordinator.MyUrl = nodeNames[0] - testNodeA := NewNodeBuilder(ctx).SetNodeConfig(nodeConfig).SetChainConfig(params.ArbitrumDevTestChainConfig()).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNodeA.L1Stack) - defer testNodeA.L2Node.StopAndWait() + l2Info, nodeA, clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, params.ArbitrumDevTestChainConfig(), nil) + defer requireClose(t, l1stack) + defer nodeA.StopAndWait() redisClient, err := redisutil.RedisClientFromURL(nodeConfig.SeqCoordinator.RedisUrl) Require(t, err) @@ -297,7 +297,7 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { break } - testNodeA.L2Info.GenerateAccount("User2") + l2Info.GenerateAccount("User2") nodeConfigDup := *nodeConfig nodeConfig = &nodeConfigDup @@ -305,23 +305,23 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { nodeConfig.SeqCoordinator.MyUrl = nodeNames[1] if !successCase { nodeConfig.SeqCoordinator.Signer.ECDSA.AcceptSequencer = false - nodeConfig.SeqCoordinator.Signer.ECDSA.AllowedAddresses = []string{testNodeA.L2Info.GetAddress("User2").Hex()} + nodeConfig.SeqCoordinator.Signer.ECDSA.AllowedAddresses = []string{l2Info.GetAddress("User2").Hex()} } - clientB, nodeB := Create2ndNodeWithConfig(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nodeConfig, nil) + clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2Info.ArbInitData, nodeConfig, nil) defer nodeB.StopAndWait() - tx := testNodeA.L2Info.PrepareTx("Owner", "User2", testNodeA.L2Info.TransferGas, big.NewInt(1e12), nil) + tx := l2Info.PrepareTx("Owner", "User2", l2Info.TransferGas, big.NewInt(1e12), nil) - err = testNodeA.L2Client.SendTransaction(ctx, tx) + err = clientA.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, clientA, tx) Require(t, err) if successCase { _, err = WaitForTx(ctx, clientB, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("User2"), nil) + l2balance, err := clientB.BalanceAt(ctx, l2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) diff --git a/system_tests/seq_nonce_test.go b/system_tests/seq_nonce_test.go index 18363b998..968f14136 100644 --- a/system_tests/seq_nonce_test.go +++ b/system_tests/seq_nonce_test.go @@ -26,10 +26,10 @@ func TestSequencerParallelNonces(t *testing.T) { config := arbnode.ConfigDefaultL2Test() config.Sequencer.NonceFailureCacheExpiry = time.Minute - testNode := NewNodeBuilder(ctx).SetNodeConfig(config).CreateTestNodeOnL2Only(t, false) - defer testNode.L2Node.StopAndWait() + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false) + defer node.StopAndWait() - testNode.L2Info.GenerateAccount("Destination") + l2info.GenerateAccount("Destination") wg := sync.WaitGroup{} for thread := 0; thread < 10; thread++ { @@ -37,11 +37,11 @@ func TestSequencerParallelNonces(t *testing.T) { go func() { defer wg.Done() for i := 0; i < 10; i++ { - tx := testNode.L2Info.PrepareTx("Owner", "Destination", testNode.L2Info.TransferGas, common.Big1, nil) + tx := l2info.PrepareTx("Owner", "Destination", l2info.TransferGas, common.Big1, nil) // Sleep a random amount of time up to 20 milliseconds time.Sleep(time.Millisecond * time.Duration(rand.Intn(20))) t.Log("Submitting transaction with nonce", tx.Nonce()) - err := testNode.L2Client.SendTransaction(ctx, tx) + err := client.SendTransaction(ctx, tx) Require(t, err) t.Log("Got response for transaction with nonce", tx.Nonce()) } @@ -49,8 +49,8 @@ func TestSequencerParallelNonces(t *testing.T) { } wg.Wait() - addr := testNode.L2Info.GetAddress("Destination") - balance, err := testNode.L2Client.BalanceAt(ctx, addr, nil) + addr := l2info.GetAddress("Destination") + balance, err := client.BalanceAt(ctx, addr, nil) Require(t, err) if !arbmath.BigEquals(balance, big.NewInt(100)) { Fatal(t, "Unexpected user balance", balance) @@ -63,14 +63,14 @@ func TestSequencerNonceTooHigh(t *testing.T) { defer cancel() config := arbnode.ConfigDefaultL2Test() - testNode := NewNodeBuilder(ctx).SetNodeConfig(config).CreateTestNodeOnL2Only(t, false) - defer testNode.L2Node.StopAndWait() + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false) + defer node.StopAndWait() - testNode.L2Info.GetInfoWithPrivKey("Owner").Nonce++ + l2info.GetInfoWithPrivKey("Owner").Nonce++ before := time.Now() - tx := testNode.L2Info.PrepareTx("Owner", "Owner", testNode.L2Info.TransferGas, common.Big0, nil) - err := testNode.L2Client.SendTransaction(ctx, tx) + tx := l2info.PrepareTx("Owner", "Owner", l2info.TransferGas, common.Big0, nil) + err := client.SendTransaction(ctx, tx) if err == nil { Fatal(t, "No error when nonce was too high") } @@ -91,16 +91,16 @@ func TestSequencerNonceTooHighQueueFull(t *testing.T) { config := arbnode.ConfigDefaultL2Test() config.Sequencer.NonceFailureCacheSize = 5 config.Sequencer.NonceFailureCacheExpiry = time.Minute - testNode := NewNodeBuilder(ctx).SetNodeConfig(config).CreateTestNodeOnL2Only(t, false) - defer testNode.L2Node.StopAndWait() + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, config, false) + defer node.StopAndWait() count := 15 var completed uint64 for i := 0; i < count; i++ { - testNode.L2Info.GetInfoWithPrivKey("Owner").Nonce++ - tx := testNode.L2Info.PrepareTx("Owner", "Owner", testNode.L2Info.TransferGas, common.Big0, nil) + l2info.GetInfoWithPrivKey("Owner").Nonce++ + tx := l2info.PrepareTx("Owner", "Owner", l2info.TransferGas, common.Big0, nil) go func() { - err := testNode.L2Client.SendTransaction(ctx, tx) + err := client.SendTransaction(ctx, tx) if err == nil { Fatal(t, "No error when nonce was too high") } diff --git a/system_tests/seq_pause_test.go b/system_tests/seq_pause_test.go index 8b919d73c..fd057c018 100644 --- a/system_tests/seq_pause_test.go +++ b/system_tests/seq_pause_test.go @@ -8,7 +8,6 @@ import ( "time" "github.com/ethereum/go-ethereum/core/types" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbnode/execution" ) @@ -17,12 +16,12 @@ func TestSequencerPause(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + l2info1, nodeA, client := CreateTestL2(t, ctx) + defer nodeA.StopAndWait() const numUsers = 100 - prechecker, ok := testNode.L2Node.Execution.TxPublisher.(*execution.TxPreChecker) + prechecker, ok := nodeA.Execution.TxPublisher.(*execution.TxPreChecker) if !ok { t.Error("prechecker not found on node") } @@ -35,15 +34,15 @@ func TestSequencerPause(t *testing.T) { for num := 0; num < numUsers; num++ { userName := fmt.Sprintf("My_User_%d", num) - testNode.L2Info.GenerateAccount(userName) + l2info1.GenerateAccount(userName) users = append(users, userName) } for _, userName := range users { - tx := testNode.L2Info.PrepareTx("Owner", userName, testNode.L2Info.TransferGas, big.NewInt(1e16), nil) - err := testNode.L2Client.SendTransaction(ctx, tx) + tx := l2info1.PrepareTx("Owner", userName, l2info1.TransferGas, big.NewInt(1e16), nil) + err := client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client, tx) Require(t, err) } @@ -52,7 +51,7 @@ func TestSequencerPause(t *testing.T) { var txs types.Transactions for _, userName := range users { - tx := testNode.L2Info.PrepareTx(userName, "Owner", testNode.L2Info.TransferGas, big.NewInt(2), nil) + tx := l2info1.PrepareTx(userName, "Owner", l2info1.TransferGas, big.NewInt(2), nil) txs = append(txs, tx) } @@ -63,7 +62,7 @@ func TestSequencerPause(t *testing.T) { }(tx) } - _, err := EnsureTxSucceededWithTimeout(ctx, testNode.L2Client, txs[0], time.Second) + _, err := EnsureTxSucceededWithTimeout(ctx, client, txs[0], time.Second) if err == nil { t.Error("tx passed while sequencer paused") } @@ -71,7 +70,7 @@ func TestSequencerPause(t *testing.T) { sequencer.Activate() for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err := EnsureTxSucceeded(ctx, client, tx) Require(t, err) } } diff --git a/system_tests/seq_reject_test.go b/system_tests/seq_reject_test.go index 811f5669d..19c06c4bc 100644 --- a/system_tests/seq_reject_test.go +++ b/system_tests/seq_reject_test.go @@ -31,18 +31,18 @@ func TestSequencerRejection(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() feedErrChan := make(chan error, 10) - testNode1 := NewNodeBuilder(ctx).SetNodeConfig(seqNodeConfig).CreateTestNodeOnL2Only(t, true) - defer testNode1.L2Node.StopAndWait() + l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true) + defer nodeA.StopAndWait() clientNodeConfig := arbnode.ConfigDefaultL2Test() - port := testNode1.L2Node.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - testNode2 := NewNodeBuilder(ctx).SetNodeConfig(clientNodeConfig).CreateTestNodeOnL2Only(t, false) - defer testNode2.L2Node.StopAndWait() + _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false) + defer nodeB.StopAndWait() - auth := testNode1.L2Info.GetDefaultTransactOpts("Owner", ctx) - simpleAddr, _ := testNode1.DeploySimple(t, auth) + auth := l2info1.GetDefaultTransactOpts("Owner", ctx) + simpleAddr, _ := deploySimple(t, ctx, auth, client1) simpleAbi, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) noopId := simpleAbi.Methods["noop"].ID @@ -51,7 +51,7 @@ func TestSequencerRejection(t *testing.T) { // Generate the accounts before hand to avoid races for user := 0; user < 9; user++ { name := fmt.Sprintf("User%v", user) - testNode1.L2Info.GenerateAccount(name) + l2info1.GenerateAccount(name) } wg := sync.WaitGroup{} @@ -59,24 +59,24 @@ func TestSequencerRejection(t *testing.T) { for user := 0; user < 9; user++ { user := user name := fmt.Sprintf("User%v", user) - tx := testNode1.L2Info.PrepareTx("Owner", name, testNode1.L2Info.TransferGas, big.NewInt(params.Ether), nil) + tx := l2info1.PrepareTx("Owner", name, l2info1.TransferGas, big.NewInt(params.Ether), nil) - err := testNode1.L2Client.SendTransaction(ctx, tx) + err := client1.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNode1.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client1, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNode2.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client2, tx) Require(t, err) wg.Add(1) go func() { defer wg.Done() - info := testNode1.L2Info.GetInfoWithPrivKey(name) + info := l2info1.GetInfoWithPrivKey(name) txData := &types.DynamicFeeTx{ To: &simpleAddr, - Gas: testNode1.L2Info.TransferGas + 10000, - GasFeeCap: arbmath.BigMulByUint(testNode1.L2Info.GasPrice, 100), + Gas: l2info1.TransferGas + 10000, + GasFeeCap: arbmath.BigMulByUint(l2info1.GasPrice, 100), Value: common.Big0, } for atomic.LoadInt32(&stopBackground) == 0 { @@ -92,8 +92,8 @@ func TestSequencerRejection(t *testing.T) { txData.Nonce = 1 << 32 expectedErr = "nonce too high" } - tx = testNode1.L2Info.SignTxAs(name, txData) - err = testNode1.L2Client.SendTransaction(ctx, tx) + tx = l2info1.SignTxAs(name, txData) + err = client1.SendTransaction(ctx, tx) if err != nil && (expectedErr == "" || !strings.Contains(err.Error(), expectedErr)) { Require(t, err, "failed to send tx for user", user) } @@ -102,7 +102,7 @@ func TestSequencerRejection(t *testing.T) { } for i := 100; i >= 0; i-- { - block, err := testNode1.L2Client.BlockNumber(ctx) + block, err := client1.BlockNumber(ctx) Require(t, err) if block >= 200 { break @@ -120,11 +120,11 @@ func TestSequencerRejection(t *testing.T) { atomic.StoreInt32(&stopBackground, 1) wg.Wait() - header1, err := testNode1.L2Client.HeaderByNumber(ctx, nil) + header1, err := client1.HeaderByNumber(ctx, nil) Require(t, err) for i := 100; i >= 0; i-- { - header2, err := testNode2.L2Client.HeaderByNumber(ctx, header1.Number) + header2, err := client2.HeaderByNumber(ctx, header1.Number) if err != nil { select { case err := <-feedErrChan: @@ -132,8 +132,8 @@ func TestSequencerRejection(t *testing.T) { case <-time.After(time.Millisecond * 100): } if i == 0 { - client2Block, _ := testNode2.L2Client.BlockNumber(ctx) - Fatal(t, "Client2 failed to reach client1 block ", header1.Number, ", only reached block", client2Block) + client2Block, _ := client2.BlockNumber(ctx) + Fatal(t, "client2 failed to reach client1 block ", header1.Number, ", only reached block", client2Block) } continue } diff --git a/system_tests/seq_whitelist_test.go b/system_tests/seq_whitelist_test.go index 5275bf9ac..2d671dcdd 100644 --- a/system_tests/seq_whitelist_test.go +++ b/system_tests/seq_whitelist_test.go @@ -18,22 +18,22 @@ func TestSequencerWhitelist(t *testing.T) { config := arbnode.ConfigDefaultL2Test() config.Sequencer.SenderWhitelist = GetTestAddressForAccountName(t, "Owner").String() + "," + GetTestAddressForAccountName(t, "User").String() - testNode := NewNodeBuilder(ctx).SetNodeConfig(config).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + l2info, l2node, client := CreateTestL2WithConfig(t, ctx, nil, config, true) + defer l2node.StopAndWait() - testNode.L2Info.GenerateAccount("User") - testNode.L2Info.GenerateAccount("User2") + l2info.GenerateAccount("User") + l2info.GenerateAccount("User2") // Owner is on the whitelist - testNode.TransferBalanceViaL2(t, "Owner", "User", big.NewInt(params.Ether)) - testNode.TransferBalanceViaL2(t, "Owner", "User2", big.NewInt(params.Ether)) + TransferBalance(t, "Owner", "User", big.NewInt(params.Ether), l2info, client, ctx) + TransferBalance(t, "Owner", "User2", big.NewInt(params.Ether), l2info, client, ctx) // User is on the whitelist - testNode.TransferBalanceViaL2(t, "User", "User2", big.NewInt(params.Ether/10)) + TransferBalance(t, "User", "User2", big.NewInt(params.Ether/10), l2info, client, ctx) // User2 is *not* on the whitelist, therefore this should fail - tx := testNode.L2Info.PrepareTx("User2", "User", testNode.L2Info.TransferGas, big.NewInt(params.Ether/10), nil) - err := testNode.L2Client.SendTransaction(ctx, tx) + tx := l2info.PrepareTx("User2", "User", l2info.TransferGas, big.NewInt(params.Ether/10), nil) + err := client.SendTransaction(ctx, tx) if err == nil { Fatal(t, "transaction from user not on whitelist accepted") } diff --git a/system_tests/seqcompensation_test.go b/system_tests/seqcompensation_test.go index 39cf0771a..362acf6a3 100644 --- a/system_tests/seqcompensation_test.go +++ b/system_tests/seqcompensation_test.go @@ -18,19 +18,19 @@ func TestSequencerCompensation(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNodeA := NewNodeBuilder(ctx).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNodeA.L1Stack) - defer testNodeA.L2Node.StopAndWait() + l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) + defer requireClose(t, l1stack) + defer nodeA.StopAndWait() - l2clientB, nodeB := Create2ndNode(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nil) + l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, nil) defer nodeB.StopAndWait() - testNodeA.L2Info.GenerateAccount("User2") + l2info.GenerateAccount("User2") - tx := testNodeA.L2Info.PrepareTx("Owner", "User2", testNodeA.L2Info.TransferGas, big.NewInt(1e12), nil) - err := testNodeA.L2Client.SendTransaction(ctx, tx) + tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) + err := l2clientA.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2clientA, tx) Require(t, err) // give the inbox reader a bit of time to pick up the delayed message @@ -38,8 +38,8 @@ func TestSequencerCompensation(t *testing.T) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ - testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ + l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } @@ -47,7 +47,7 @@ func TestSequencerCompensation(t *testing.T) { Require(t, err) // clientB sees balance means sequencer message was sent - l2balance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("User2"), nil) + l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { Fatal(t, "Unexpected balance:", l2balance) diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index e89b8a58b..23c0e44c0 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -44,28 +44,28 @@ func TestSequencerFeed(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - testNode1 := NewNodeBuilder(ctx).SetNodeConfig(seqNodeConfig).CreateTestNodeOnL2Only(t, true) - defer testNode1.L2Node.StopAndWait() + l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true) + defer nodeA.StopAndWait() clientNodeConfig := arbnode.ConfigDefaultL2Test() - port := testNode1.L2Node.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - testNode2 := NewNodeBuilder(ctx).SetNodeConfig(clientNodeConfig).CreateTestNodeOnL2Only(t, false) - defer testNode2.L2Node.StopAndWait() + _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false) + defer nodeB.StopAndWait() - testNode1.L2Info.GenerateAccount("User2") + l2info1.GenerateAccount("User2") - tx := testNode1.L2Info.PrepareTx("Owner", "User2", testNode1.L2Info.TransferGas, big.NewInt(1e12), nil) + tx := l2info1.PrepareTx("Owner", "User2", l2info1.TransferGas, big.NewInt(1e12), nil) - err := testNode1.L2Client.SendTransaction(ctx, tx) + err := client1.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNode1.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client1, tx) Require(t, err) - _, err = WaitForTx(ctx, testNode2.L2Client, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, client2, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := testNode2.L2Client.BalanceAt(ctx, testNode1.L2Info.GetAddress("User2"), nil) + l2balance, err := client2.BalanceAt(ctx, l2info1.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) @@ -79,14 +79,14 @@ func TestRelayedSequencerFeed(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - testNode1 := NewNodeBuilder(ctx).SetNodeConfig(seqNodeConfig).CreateTestNodeOnL2Only(t, true) - defer testNode1.L2Node.StopAndWait() + l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, true) + defer nodeA.StopAndWait() - bigChainId, err := testNode1.L2Client.ChainID(ctx) + bigChainId, err := client1.ChainID(ctx) Require(t, err) config := relay.ConfigDefault - port := testNode1.L2Node.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port config.Node.Feed.Input = *newBroadcastClientConfigTest(port) config.Node.Feed.Output = *newBroadcasterConfigTest() config.Chain.ID = bigChainId.Uint64() @@ -101,23 +101,23 @@ func TestRelayedSequencerFeed(t *testing.T) { clientNodeConfig := arbnode.ConfigDefaultL2Test() port = currentRelay.GetListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - testNode3 := NewNodeBuilder(ctx).SetNodeConfig(clientNodeConfig).CreateTestNodeOnL2Only(t, false) - defer testNode3.L2Node.StopAndWait() - StartWatchChanErr(t, ctx, feedErrChan, testNode3.L2Node) + _, nodeC, client3 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, false) + defer nodeC.StopAndWait() + StartWatchChanErr(t, ctx, feedErrChan, nodeC) - testNode1.L2Info.GenerateAccount("User2") + l2info1.GenerateAccount("User2") - tx := testNode1.L2Info.PrepareTx("Owner", "User2", testNode1.L2Info.TransferGas, big.NewInt(1e12), nil) + tx := l2info1.PrepareTx("Owner", "User2", l2info1.TransferGas, big.NewInt(1e12), nil) - err = testNode1.L2Client.SendTransaction(ctx, tx) + err = client1.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNode1.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client1, tx) Require(t, err) - _, err = WaitForTx(ctx, testNode3.L2Client, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, client3, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := testNode3.L2Client.BalanceAt(ctx, testNode1.L2Info.GetAddress("User2"), nil) + l2balance, err := client3.BalanceAt(ctx, l2info1.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) @@ -135,11 +135,11 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigA.BatchPoster.Enable = true nodeConfigA.Feed.Output.Enable = false - testNodeA := NewNodeBuilder(ctx).SetNodeConfig(nodeConfigA).SetChainConfig(chainConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNodeA.L1Stack, "unable to close l1Stack") - defer testNodeA.L2Node.StopAndWait() + l2infoA, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfigA, chainConfig, nil) + defer requireClose(t, l1stack, "unable to close l1stack") + defer nodeA.StopAndWait() - authorizeDASKeyset(t, ctx, dasSignerKey, testNodeA.L1Info, testNodeA.L1Client) + authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) // The lying sequencer nodeConfigC := arbnode.ConfigDefaultL1Test() @@ -147,7 +147,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigC.DataAvailability = nodeConfigA.DataAvailability nodeConfigC.DataAvailability.RPCAggregator.Enable = false nodeConfigC.Feed.Output = *newBroadcasterConfigTest() - l2clientC, nodeC := Create2ndNodeWithConfig(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nodeConfigC, nil) + l2clientC, nodeC := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2infoA.ArbInitData, nodeConfigC, nil) defer nodeC.StopAndWait() port := nodeC.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port @@ -158,15 +158,15 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigB.Feed.Input = *newBroadcastClientConfigTest(port) nodeConfigB.DataAvailability = nodeConfigA.DataAvailability nodeConfigB.DataAvailability.RPCAggregator.Enable = false - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, nodeConfigB, nil) + l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2infoA.ArbInitData, nodeConfigB, nil) defer nodeB.StopAndWait() - testNodeA.L2Info.GenerateAccount("FraudUser") - testNodeA.L2Info.GenerateAccount("RealUser") + l2infoA.GenerateAccount("FraudUser") + l2infoA.GenerateAccount("RealUser") - fraudTx := testNodeA.L2Info.PrepareTx("Owner", "FraudUser", testNodeA.L2Info.TransferGas, big.NewInt(1e12), nil) - testNodeA.L2Info.GetInfoWithPrivKey("Owner").Nonce -= 1 // Use same l2info object for different l2s - realTx := testNodeA.L2Info.PrepareTx("Owner", "RealUser", testNodeA.L2Info.TransferGas, big.NewInt(1e12), nil) + fraudTx := l2infoA.PrepareTx("Owner", "FraudUser", l2infoA.TransferGas, big.NewInt(1e12), nil) + l2infoA.GetInfoWithPrivKey("Owner").Nonce -= 1 // Use same l2info object for different l2s + realTx := l2infoA.PrepareTx("Owner", "RealUser", l2infoA.TransferGas, big.NewInt(1e12), nil) err := l2clientC.SendTransaction(ctx, fraudTx) if err != nil { @@ -183,7 +183,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { if err != nil { t.Fatal("error waiting for tx:", err) } - l2balance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("FraudUser"), nil) + l2balance, err := l2clientB.BalanceAt(ctx, l2infoA.GetAddress("FraudUser"), nil) if err != nil { t.Fatal("error getting balance:", err) } @@ -192,12 +192,12 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { } // Send the real transaction to client A - err = testNodeA.L2Client.SendTransaction(ctx, realTx) + err = l2clientA.SendTransaction(ctx, realTx) if err != nil { t.Fatal("error sending real transaction:", err) } - _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, realTx) + _, err = EnsureTxSucceeded(ctx, l2clientA, realTx) if err != nil { t.Fatal("error ensuring real transaction succeeded:", err) } @@ -207,7 +207,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { if err != nil { t.Fatal("error waiting for transaction to get to node b:", err) } - l2balanceFraudAcct, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("FraudUser"), nil) + l2balanceFraudAcct, err := l2clientB.BalanceAt(ctx, l2infoA.GetAddress("FraudUser"), nil) if err != nil { t.Fatal("error getting fraud balance:", err) } @@ -215,7 +215,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { t.Fatal("Unexpected balance (fraud acct should be empty) was:", l2balanceFraudAcct) } - l2balanceRealAcct, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("RealUser"), nil) + l2balanceRealAcct, err := l2clientB.BalanceAt(ctx, l2infoA.GetAddress("RealUser"), nil) if err != nil { t.Fatal("error getting real balance:", err) } diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index c7583ff1f..bf3e7c86c 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -47,18 +47,18 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { if validator { conf.BlockValidator.Enable = true } - testNode := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(false).CreateTestNodeOnL1AndL2(t) - l2Backend := testNode.L2Node.Execution.Backend - defer requireClose(t, testNode.L1Stack) - defer testNode.L2Node.StopAndWait() + l2Info, arbNode, _, l1Info, l1backend, l1Client, l1stack := createTestNodeOnL1WithConfig(t, ctx, false, conf, nil, nil) + l2Backend := arbNode.Execution.Backend + defer requireClose(t, l1stack) + defer arbNode.StopAndWait() - l1BlockChain := testNode.L1Backend.BlockChain() + l1BlockChain := l1backend.BlockChain() - seqInbox, err := bridgegen.NewSequencerInbox(testNode.L1Info.GetAddress("SequencerInbox"), testNode.L1Client) + seqInbox, err := bridgegen.NewSequencerInbox(l1Info.GetAddress("SequencerInbox"), l1Client) Require(t, err) - seqOpts := testNode.L1Info.GetDefaultTransactOpts("Sequencer", ctx) + seqOpts := l1Info.GetDefaultTransactOpts("Sequencer", ctx) - ownerAddress := testNode.L2Info.GetAddress("Owner") + ownerAddress := l2Info.GetAddress("Owner") var startL2BlockNumber uint64 = 0 startState, _, err := l2Backend.APIBackend().StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) @@ -91,10 +91,10 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { } var faucetTxs []*types.Transaction for _, acct := range accounts { - testNode.L1Info.GenerateAccount(acct) - faucetTxs = append(faucetTxs, testNode.L1Info.PrepareTx("Faucet", acct, 30000, big.NewInt(1e16), nil)) + l1Info.GenerateAccount(acct) + faucetTxs = append(faucetTxs, l1Info.PrepareTx("Faucet", acct, 30000, big.NewInt(1e16), nil)) } - SendWaitTestTransactions(t, ctx, testNode.L1Client, faucetTxs) + SendWaitTestTransactions(t, ctx, l1Client, faucetTxs) for i := 1; i < seqInboxTestIters; i++ { if i%10 == 0 { @@ -106,7 +106,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { // The miner usually collects transactions from deleted blocks and puts them in the mempool. // However, this code doesn't run on reorgs larger than 64 blocks for performance reasons. // Therefore, we make a bunch of small blocks to prevent the code from running. - padAddr := testNode.L1Info.GetAddress("ReorgPadding") + padAddr := l1Info.GetAddress("ReorgPadding") for j := uint64(0); j < 70; j++ { rawTx := &types.DynamicFeeTx{ To: &padAddr, @@ -115,12 +115,12 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { Value: new(big.Int), Nonce: j, } - tx := testNode.L1Info.SignTxAs("ReorgPadding", rawTx) - Require(t, testNode.L1Client.SendTransaction(ctx, tx)) - _, _ = EnsureTxSucceeded(ctx, testNode.L1Client, tx) + tx := l1Info.SignTxAs("ReorgPadding", rawTx) + Require(t, l1Client.SendTransaction(ctx, tx)) + _, _ = EnsureTxSucceeded(ctx, l1Client, tx) } reorgTargetNumber := blockStates[reorgTo].l1BlockNumber - currentHeader, err := testNode.L1Client.HeaderByNumber(ctx, nil) + currentHeader, err := l1Client.HeaderByNumber(ctx, nil) Require(t, err) if currentHeader.Number.Int64()-int64(reorgTargetNumber) < 65 { Fatal(t, "Less than 65 blocks of difference between current block", currentHeader.Number, "and target", reorgTargetNumber) @@ -135,10 +135,10 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { // Sometimes, this causes it to drop the next tx. // To work around this, we create a sacrificial tx, which may or may not succeed. // Whichever happens, by the end of this block, the miner will have processed the reorg. - tx := testNode.L1Info.PrepareTx(fmt.Sprintf("ReorgSacrifice%v", i/10), "Faucet", 30000, big.NewInt(0), nil) - err = testNode.L1Client.SendTransaction(ctx, tx) + tx := l1Info.PrepareTx(fmt.Sprintf("ReorgSacrifice%v", i/10), "Faucet", 30000, big.NewInt(0), nil) + err = l1Client.SendTransaction(ctx, tx) Require(t, err) - _, _ = WaitForTx(ctx, testNode.L1Client, tx.Hash(), time.Second) + _, _ = WaitForTx(ctx, l1Client, tx.Hash(), time.Second) } else { state := blockStates[len(blockStates)-1] newBalances := make(map[common.Address]*big.Int) @@ -166,10 +166,10 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { var dest common.Address if j == 0 && amount.Cmp(reserveAmount) >= 0 { name := accountName(len(state.accounts)) - if !testNode.L2Info.HasAccount(name) { - testNode.L2Info.GenerateAccount(name) + if !l2Info.HasAccount(name) { + l2Info.GenerateAccount(name) } - dest = testNode.L2Info.GetAddress(name) + dest = l2Info.GetAddress(name) state.accounts = append(state.accounts, dest) state.balances[dest] = big.NewInt(0) } else { @@ -184,7 +184,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { Nonce: state.nonces[source], } state.nonces[source]++ - tx := testNode.L2Info.SignTxAs(accountName(sourceNum), rawTx) + tx := l2Info.SignTxAs(accountName(sourceNum), rawTx) txData, err := tx.MarshalBinary() Require(t, err) var segment []byte @@ -204,7 +204,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { seqNonce := len(blockStates) - 1 for j := 0; ; j++ { - haveNonce, err := testNode.L1Client.PendingNonceAt(ctx, seqOpts.From) + haveNonce, err := l1Client.PendingNonceAt(ctx, seqOpts.From) Require(t, err) if haveNonce == uint64(seqNonce) { break @@ -222,15 +222,15 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { tx, err = seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(int64(len(blockStates))), batchData, big.NewInt(1), common.Address{}) } Require(t, err) - txRes, err := EnsureTxSucceeded(ctx, testNode.L1Client, tx) + txRes, err := EnsureTxSucceeded(ctx, l1Client, tx) if err != nil { // Geth's clique miner is finicky. // Unfortunately this is so rare that I haven't had an opportunity to test this workaround. // Specifically, I suspect there's a race where it thinks there's no txs to put in the new block, // if a new tx arrives at the same time as it tries to create a block. // Resubmit the transaction in an attempt to get the miner going again. - _ = testNode.L1Client.SendTransaction(ctx, tx) - txRes, err = EnsureTxSucceeded(ctx, testNode.L1Client, tx) + _ = l1Client.SendTransaction(ctx, tx) + txRes, err = EnsureTxSucceeded(ctx, l1Client, tx) Require(t, err) } @@ -267,9 +267,9 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { if validator && i%15 == 0 { for i := 0; ; i++ { - expectedPos, err := testNode.L2Node.Execution.ExecEngine.BlockNumberToMessageIndex(expectedBlockNumber) + expectedPos, err := arbNode.Execution.ExecEngine.BlockNumberToMessageIndex(expectedBlockNumber) Require(t, err) - lastValidated := testNode.L2Node.BlockValidator.Validated(t) + lastValidated := arbNode.BlockValidator.Validated(t) if lastValidated == expectedPos+1 { break } else if i >= 1000 { diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index e03cd15b8..78fa7fa83 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -65,9 +65,9 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) types.NewArbitrumSigner(types.NewLondonSigner(l2chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), transferGas, ) - testNodeA := NewNodeBuilder(ctx).SetIsSequencer(true).SetChainConfig(l2chainConfig).SetL2Info(l2info).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNodeA.L1Stack) - defer testNodeA.L2Node.StopAndWait() + _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, l2chainConfig, nil, l2info) + defer requireClose(t, l1stack) + defer l2nodeA.StopAndWait() if faultyStaker { l2info.GenerateGenesisAccount("FaultyAddr", common.Big1) @@ -76,10 +76,10 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) config.Sequencer.Enable = false config.DelayedSequencer.Enable = false config.BatchPoster.Enable = false - _, l2nodeB := Create2ndNodeWithConfig(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &l2info.ArbInitData, config, nil) + _, l2nodeB := Create2ndNodeWithConfig(t, ctx, l2nodeA, l1stack, l1info, &l2info.ArbInitData, config, nil) defer l2nodeB.StopAndWait() - nodeAGenesis := testNodeA.L2Node.Execution.Backend.APIBackend().CurrentHeader().Hash() + nodeAGenesis := l2nodeA.Execution.Backend.APIBackend().CurrentHeader().Hash() nodeBGenesis := l2nodeB.Execution.Backend.APIBackend().CurrentHeader().Hash() if faultyStaker { if nodeAGenesis == nodeBGenesis { @@ -91,51 +91,51 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } } - testNodeA.BridgeBalance(t, "Faucet", big.NewInt(1).Mul(big.NewInt(params.Ether), big.NewInt(10000))) + BridgeBalance(t, "Faucet", big.NewInt(1).Mul(big.NewInt(params.Ether), big.NewInt(10000)), l1info, l2info, l1client, l2clientA, ctx) - deployAuth := testNodeA.L1Info.GetDefaultTransactOpts("RollupOwner", ctx) + deployAuth := l1info.GetDefaultTransactOpts("RollupOwner", ctx) balance := big.NewInt(params.Ether) balance.Mul(balance, big.NewInt(100)) - testNodeA.L1Info.GenerateAccount("ValidatorA") - testNodeA.TransferBalanceViaL1(t, "Faucet", "ValidatorA", balance) - l1authA := testNodeA.L1Info.GetDefaultTransactOpts("ValidatorA", ctx) + l1info.GenerateAccount("ValidatorA") + TransferBalance(t, "Faucet", "ValidatorA", balance, l1info, l1client, ctx) + l1authA := l1info.GetDefaultTransactOpts("ValidatorA", ctx) - testNodeA.L1Info.GenerateAccount("ValidatorB") - testNodeA.TransferBalanceViaL1(t, "Faucet", "ValidatorB", balance) - l1authB := testNodeA.L1Info.GetDefaultTransactOpts("ValidatorB", ctx) + l1info.GenerateAccount("ValidatorB") + TransferBalance(t, "Faucet", "ValidatorB", balance, l1info, l1client, ctx) + l1authB := l1info.GetDefaultTransactOpts("ValidatorB", ctx) - valWalletAddrAPtr, err := validatorwallet.GetValidatorWalletContract(ctx, testNodeA.L2Node.DeployInfo.ValidatorWalletCreator, 0, &l1authA, testNodeA.L2Node.L1Reader, true) + valWalletAddrAPtr, err := validatorwallet.GetValidatorWalletContract(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader, true) Require(t, err) valWalletAddrA := *valWalletAddrAPtr - valWalletAddrCheck, err := validatorwallet.GetValidatorWalletContract(ctx, testNodeA.L2Node.DeployInfo.ValidatorWalletCreator, 0, &l1authA, testNodeA.L2Node.L1Reader, true) + valWalletAddrCheck, err := validatorwallet.GetValidatorWalletContract(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader, true) Require(t, err) if valWalletAddrA == *valWalletAddrCheck { Require(t, err, "didn't cache validator wallet address", valWalletAddrA.String(), "vs", valWalletAddrCheck.String()) } - rollup, err := rollupgen.NewRollupAdminLogic(testNodeA.L2Node.DeployInfo.Rollup, testNodeA.L1Client) + rollup, err := rollupgen.NewRollupAdminLogic(l2nodeA.DeployInfo.Rollup, l1client) Require(t, err) tx, err := rollup.SetValidator(&deployAuth, []common.Address{valWalletAddrA, l1authB.From}, []bool{true, true}) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNodeA.L1Client, tx) + _, err = EnsureTxSucceeded(ctx, l1client, tx) Require(t, err) tx, err = rollup.SetMinimumAssertionPeriod(&deployAuth, big.NewInt(1)) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNodeA.L1Client, tx) + _, err = EnsureTxSucceeded(ctx, l1client, tx) Require(t, err) - validatorUtils, err := rollupgen.NewValidatorUtils(testNodeA.L2Node.DeployInfo.ValidatorUtils, testNodeA.L1Client) + validatorUtils, err := rollupgen.NewValidatorUtils(l2nodeA.DeployInfo.ValidatorUtils, l1client) Require(t, err) valConfig := staker.TestL1ValidatorConfig - dpA, err := arbnode.StakerDataposter(ctx, rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), testNodeA.L2Node.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) + dpA, err := arbnode.StakerDataposter(ctx, rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } - valWalletA, err := validatorwallet.NewContract(dpA, nil, testNodeA.L2Node.DeployInfo.ValidatorWalletCreator, testNodeA.L2Node.DeployInfo.Rollup, testNodeA.L2Node.L1Reader, &l1authA, 0, func(common.Address) {}, func() uint64 { return valConfig.ExtraGas }) + valWalletA, err := validatorwallet.NewContract(dpA, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, &l1authA, 0, func(common.Address) {}, func() uint64 { return valConfig.ExtraGas }) Require(t, err) if honestStakerInactive { valConfig.Strategy = "Defensive" @@ -147,11 +147,11 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) blockValidatorConfig := staker.TestBlockValidatorConfig statelessA, err := staker.NewStatelessBlockValidator( - testNodeA.L2Node.InboxReader, - testNodeA.L2Node.InboxTracker, - testNodeA.L2Node.TxStreamer, - testNodeA.L2Node.Execution.Recorder, - testNodeA.L2Node.ArbDB, + l2nodeA.InboxReader, + l2nodeA.InboxTracker, + l2nodeA.TxStreamer, + l2nodeA.Execution.Recorder, + l2nodeA.ArbDB, nil, StaticFetcherFrom(t, &blockValidatorConfig), valStack, @@ -160,7 +160,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) err = statelessA.Start(ctx) Require(t, err) stakerA, err := staker.NewStaker( - testNodeA.L2Node.L1Reader, + l2nodeA.L1Reader, valWalletA, bind.CallOpts{}, valConfig, @@ -168,7 +168,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) statelessA, nil, nil, - testNodeA.L2Node.DeployInfo.ValidatorUtils, + l2nodeA.DeployInfo.ValidatorUtils, nil, ) Require(t, err) @@ -218,15 +218,15 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) err = valWalletB.Initialize(ctx) Require(t, err) } - dpC, err := arbnode.StakerDataposter(ctx, rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), testNodeA.L2Node.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) + dpC, err := arbnode.StakerDataposter(ctx, rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } - valWalletC, err := validatorwallet.NewContract(dpC, nil, testNodeA.L2Node.DeployInfo.ValidatorWalletCreator, testNodeA.L2Node.DeployInfo.Rollup, testNodeA.L2Node.L1Reader, nil, 0, func(common.Address) {}, func() uint64 { return 10000 }) + valWalletC, err := validatorwallet.NewContract(dpC, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, nil, 0, func(common.Address) {}, func() uint64 { return 10000 }) Require(t, err) valConfig.Strategy = "Watchtower" stakerC, err := staker.NewStaker( - testNodeA.L2Node.L1Reader, + l2nodeA.L1Reader, valWalletC, bind.CallOpts{}, valConfig, @@ -234,7 +234,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) statelessA, nil, nil, - testNodeA.L2Node.DeployInfo.ValidatorUtils, + l2nodeA.DeployInfo.ValidatorUtils, nil, ) Require(t, err) @@ -247,9 +247,9 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) l2info.GenerateAccount("BackgroundUser") tx = l2info.PrepareTx("Faucet", "BackgroundUser", l2info.TransferGas, balance, nil) - err = testNodeA.L2Client.SendTransaction(ctx, tx) + err = l2clientA.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2clientA, tx) Require(t, err) // Continually make L2 transactions in a background thread @@ -261,7 +261,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) })() go (func() { defer close(backgroundTxsShutdownChan) - err := makeBackgroundTxs(backgroundTxsCtx, l2info, testNodeA.L2Client) + err := makeBackgroundTxs(backgroundTxsCtx, l2info, l2clientA) if !errors.Is(err, context.Canceled) { log.Warn("error making background txs", "err", err) } @@ -304,26 +304,26 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) if !challengeMangerTimedOut { // Upgrade the ChallengeManager contract to an implementation which says challenges are always timed out - mockImpl, tx, _, err := mocksgen.DeployTimedOutChallengeManager(&deployAuth, testNodeA.L1Client) + mockImpl, tx, _, err := mocksgen.DeployTimedOutChallengeManager(&deployAuth, l1client) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNodeA.L1Client, tx) + _, err = EnsureTxSucceeded(ctx, l1client, tx) Require(t, err) managerAddr := valWalletA.ChallengeManagerAddress() // 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 proxyAdminSlot := common.BigToHash(arbmath.BigSub(crypto.Keccak256Hash([]byte("eip1967.proxy.admin")).Big(), common.Big1)) - proxyAdminBytes, err := testNodeA.L1Client.StorageAt(ctx, managerAddr, proxyAdminSlot, nil) + proxyAdminBytes, err := l1client.StorageAt(ctx, managerAddr, proxyAdminSlot, nil) Require(t, err) proxyAdminAddr := common.BytesToAddress(proxyAdminBytes) if proxyAdminAddr == (common.Address{}) { Fatal(t, "failed to get challenge manager proxy admin") } - proxyAdmin, err := mocksgen.NewProxyAdminForBinding(proxyAdminAddr, testNodeA.L1Client) + proxyAdmin, err := mocksgen.NewProxyAdminForBinding(proxyAdminAddr, l1client) Require(t, err) tx, err = proxyAdmin.Upgrade(&deployAuth, managerAddr, mockImpl) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNodeA.L1Client, tx) + _, err = EnsureTxSucceeded(ctx, l1client, tx) Require(t, err) challengeMangerTimedOut = true @@ -343,11 +343,11 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } Require(t, err, "Staker", stakerName, "failed to act") if tx != nil { - _, err = EnsureTxSucceeded(ctx, testNodeA.L1Client, tx) + _, err = EnsureTxSucceeded(ctx, l1client, tx) Require(t, err, "EnsureTxSucceeded failed for staker", stakerName, "tx") } if faultyStaker { - conflictInfo, err := validatorUtils.FindStakerConflict(&bind.CallOpts{}, testNodeA.L2Node.DeployInfo.Rollup, l1authA.From, l1authB.From, big.NewInt(1024)) + conflictInfo, err := validatorUtils.FindStakerConflict(&bind.CallOpts{}, l2nodeA.DeployInfo.Rollup, l1authA.From, l1authB.From, big.NewInt(1024)) Require(t, err) if staker.ConflictType(conflictInfo.Ty) == staker.CONFLICT_TYPE_FOUND { cancelBackgroundTxs() @@ -379,7 +379,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err) } for j := 0; j < 5; j++ { - testNodeA.TransferBalanceViaL1(t, "Faucet", "Faucet", common.Big0) + TransferBalance(t, "Faucet", "Faucet", common.Big0, l1info, l1client, ctx) } } diff --git a/system_tests/transfer_test.go b/system_tests/transfer_test.go index 1c7e7cae1..2e3317907 100644 --- a/system_tests/transfer_test.go +++ b/system_tests/transfer_test.go @@ -8,30 +8,28 @@ import ( "fmt" "math/big" "testing" - - "github.com/offchainlabs/nitro/arbnode" ) func TestTransfer(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - testNode := NewNodeBuilder(ctx).SetNodeConfig(arbnode.ConfigDefaultL2Test()).CreateTestNodeOnL2Only(t, true) - defer testNode.L2Node.StopAndWait() + l2info, l2node, client := CreateTestL2(t, ctx) + defer l2node.StopAndWait() - testNode.L2Info.GenerateAccount("User2") + l2info.GenerateAccount("User2") - tx := testNode.L2Info.PrepareTx("Owner", "User2", testNode.L2Info.TransferGas, big.NewInt(1e12), nil) + tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) - err := testNode.L2Client.SendTransaction(ctx, tx) + err := client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNode.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, client, tx) Require(t, err) - bal, err := testNode.L2Client.BalanceAt(ctx, testNode.L2Info.GetAddress("Owner"), nil) + bal, err := client.BalanceAt(ctx, l2info.GetAddress("Owner"), nil) Require(t, err) fmt.Println("Owner balance is: ", bal) - bal2, err := testNode.L2Client.BalanceAt(ctx, testNode.L2Info.GetAddress("User2"), nil) + bal2, err := client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) Require(t, err) if bal2.Cmp(big.NewInt(1e12)) != 0 { Fatal(t, "Unexpected recipient balance: ", bal2) diff --git a/system_tests/twonodes_test.go b/system_tests/twonodes_test.go index b9be59a19..72de2aa50 100644 --- a/system_tests/twonodes_test.go +++ b/system_tests/twonodes_test.go @@ -20,24 +20,24 @@ func testTwoNodesSimple(t *testing.T, dasModeStr string) { chainConfig, l1NodeConfigA, lifecycleManager, _, dasSignerKey := setupConfigWithDAS(t, ctx, dasModeStr) defer lifecycleManager.StopAndWaitUntil(time.Second) - testNodeA := NewNodeBuilder(ctx).SetNodeConfig(l1NodeConfigA).SetChainConfig(chainConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNodeA.L1Stack) - defer testNodeA.L2Node.StopAndWait() + l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, chainConfig, nil) + defer requireClose(t, l1stack) + defer nodeA.StopAndWait() - authorizeDASKeyset(t, ctx, dasSignerKey, testNodeA.L1Info, testNodeA.L1Client) + authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) l1NodeConfigBDataAvailability := l1NodeConfigA.DataAvailability l1NodeConfigBDataAvailability.RPCAggregator.Enable = false - l2clientB, nodeB := Create2ndNode(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, &l1NodeConfigBDataAvailability) + l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, &l1NodeConfigBDataAvailability) defer nodeB.StopAndWait() - testNodeA.L2Info.GenerateAccount("User2") + l2info.GenerateAccount("User2") - tx := testNodeA.L2Info.PrepareTx("Owner", "User2", testNodeA.L2Info.TransferGas, big.NewInt(1e12), nil) + tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) - err := testNodeA.L2Client.SendTransaction(ctx, tx) + err := l2clientA.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, testNodeA.L2Client, tx) + _, err = EnsureTxSucceeded(ctx, l2clientA, tx) Require(t, err) // give the inbox reader a bit of time to pick up the delayed message @@ -45,15 +45,15 @@ func testTwoNodesSimple(t *testing.T, dasModeStr string) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ - testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ + l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } _, err = WaitForTx(ctx, l2clientB, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("User2"), nil) + l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { diff --git a/system_tests/twonodeslong_test.go b/system_tests/twonodeslong_test.go index 2dde9a512..0cac9d644 100644 --- a/system_tests/twonodeslong_test.go +++ b/system_tests/twonodeslong_test.go @@ -42,32 +42,32 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { chainConfig, l1NodeConfigA, lifecycleManager, _, dasSignerKey := setupConfigWithDAS(t, ctx, dasModeStr) defer lifecycleManager.StopAndWaitUntil(time.Second) - testNodeA := NewNodeBuilder(ctx).SetNodeConfig(l1NodeConfigA).SetChainConfig(chainConfig).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) - defer requireClose(t, testNodeA.L1Stack) + l2info, nodeA, l2client, l1info, l1backend, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, chainConfig, nil) + defer requireClose(t, l1stack) - authorizeDASKeyset(t, ctx, dasSignerKey, testNodeA.L1Info, testNodeA.L1Client) + authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) l1NodeConfigBDataAvailability := l1NodeConfigA.DataAvailability l1NodeConfigBDataAvailability.RPCAggregator.Enable = false - l2clientB, nodeB := Create2ndNode(t, ctx, testNodeA.L2Node, testNodeA.L1Stack, testNodeA.L1Info, &testNodeA.L2Info.ArbInitData, &l1NodeConfigBDataAvailability) + l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, &l1NodeConfigBDataAvailability) defer nodeB.StopAndWait() - testNodeA.L2Info.GenerateAccount("DelayedFaucet") - testNodeA.L2Info.GenerateAccount("DelayedReceiver") - testNodeA.L2Info.GenerateAccount("DirectReceiver") + l2info.GenerateAccount("DelayedFaucet") + l2info.GenerateAccount("DelayedReceiver") + l2info.GenerateAccount("DirectReceiver") - testNodeA.L2Info.GenerateAccount("ErrorTxSender") + l2info.GenerateAccount("ErrorTxSender") - SendWaitTestTransactions(t, ctx, testNodeA.L2Client, []*types.Transaction{ - testNodeA.L2Info.PrepareTx("Faucet", "ErrorTxSender", testNodeA.L2Info.TransferGas, big.NewInt(l2pricing.InitialBaseFeeWei*int64(testNodeA.L2Info.TransferGas)), nil), + SendWaitTestTransactions(t, ctx, l2client, []*types.Transaction{ + l2info.PrepareTx("Faucet", "ErrorTxSender", l2info.TransferGas, big.NewInt(l2pricing.InitialBaseFeeWei*int64(l2info.TransferGas)), nil), }) delayedMsgsToSendMax := big.NewInt(int64(largeLoops * avgDelayedMessagesPerLoop * 10)) delayedFaucetNeeds := new(big.Int).Mul(new(big.Int).Add(fundsPerDelayed, new(big.Int).SetUint64(l2pricing.InitialBaseFeeWei*100000)), delayedMsgsToSendMax) - SendWaitTestTransactions(t, ctx, testNodeA.L2Client, []*types.Transaction{ - testNodeA.L2Info.PrepareTx("Faucet", "DelayedFaucet", testNodeA.L2Info.TransferGas, delayedFaucetNeeds, nil), + SendWaitTestTransactions(t, ctx, l2client, []*types.Transaction{ + l2info.PrepareTx("Faucet", "DelayedFaucet", l2info.TransferGas, delayedFaucetNeeds, nil), }) - delayedFaucetBalance, err := testNodeA.L2Client.BalanceAt(ctx, testNodeA.L2Info.GetAddress("DelayedFaucet"), nil) + delayedFaucetBalance, err := l2client.BalanceAt(ctx, l2info.GetAddress("DelayedFaucet"), nil) Require(t, err) if delayedFaucetBalance.Cmp(delayedFaucetNeeds) != 0 { @@ -85,17 +85,17 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { randNum := rand.Int() % avgTotalL1MessagesPerLoop var l1tx *types.Transaction if randNum < avgDelayedMessagesPerLoop { - delayedTx := testNodeA.L2Info.PrepareTx("DelayedFaucet", "DelayedReceiver", 30001, fundsPerDelayed, nil) - l1tx = WrapL2ForDelayed(t, delayedTx, testNodeA.L1Info, "User", 100000) + delayedTx := l2info.PrepareTx("DelayedFaucet", "DelayedReceiver", 30001, fundsPerDelayed, nil) + l1tx = WrapL2ForDelayed(t, delayedTx, l1info, "User", 100000) delayedTxs = append(delayedTxs, delayedTx) delayedTransfers++ } else { - l1tx = testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) + l1tx = l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) } l1Txs = append(l1Txs, l1tx) } // adding multiple messages in the same AddLocal to get them in the same L1 block - errs := testNodeA.L1Backend.TxPool().AddLocals(l1Txs) + errs := l1backend.TxPool().AddLocals(l1Txs) for _, err := range errs { if err != nil { Fatal(t, err) @@ -104,26 +104,26 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { l2TxsThisTime := rand.Int() % (avgL2MsgsPerLoop * 2) l2Txs := make([]*types.Transaction, 0, l2TxsThisTime) for len(l2Txs) < l2TxsThisTime { - l2Txs = append(l2Txs, testNodeA.L2Info.PrepareTx("Faucet", "DirectReceiver", testNodeA.L2Info.TransferGas, fundsPerDirect, nil)) + l2Txs = append(l2Txs, l2info.PrepareTx("Faucet", "DirectReceiver", l2info.TransferGas, fundsPerDirect, nil)) } - SendWaitTestTransactions(t, ctx, testNodeA.L2Client, l2Txs) + SendWaitTestTransactions(t, ctx, l2client, l2Txs) directTransfers += int64(l2TxsThisTime) if len(l1Txs) > 0 { - _, err := EnsureTxSucceeded(ctx, testNodeA.L1Client, l1Txs[len(l1Txs)-1]) + _, err := EnsureTxSucceeded(ctx, l1client, l1Txs[len(l1Txs)-1]) if err != nil { Fatal(t, err) } } // create bad tx on delayed inbox - testNodeA.L2Info.GetInfoWithPrivKey("ErrorTxSender").Nonce = 10 - SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ - WrapL2ForDelayed(t, testNodeA.L2Info.PrepareTx("ErrorTxSender", "DelayedReceiver", 30002, delayedFaucetNeeds, nil), testNodeA.L1Info, "User", 100000), + l2info.GetInfoWithPrivKey("ErrorTxSender").Nonce = 10 + SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ + WrapL2ForDelayed(t, l2info.PrepareTx("ErrorTxSender", "DelayedReceiver", 30002, delayedFaucetNeeds, nil), l1info, "User", 100000), }) extrBlocksThisTime := rand.Int() % (avgExtraBlocksPerLoop * 2) for i := 0; i < extrBlocksThisTime; i++ { - SendWaitTestTransactions(t, ctx, testNodeA.L1Client, []*types.Transaction{ - testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ + l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } } @@ -137,38 +137,38 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { for i := 0; i < finalPropagateLoops; i++ { var tx *types.Transaction for j := 0; j < 30; j++ { - tx = testNodeA.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) - err := testNodeA.L1Client.SendTransaction(ctx, tx) + tx = l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) + err := l1client.SendTransaction(ctx, tx) if err != nil { Fatal(t, err) } - _, err = EnsureTxSucceeded(ctx, testNodeA.L1Client, tx) + _, err = EnsureTxSucceeded(ctx, l1client, tx) if err != nil { Fatal(t, err) } } } - _, err = EnsureTxSucceededWithTimeout(ctx, testNodeA.L2Client, delayedTxs[len(delayedTxs)-1], time.Second*10) + _, err = EnsureTxSucceededWithTimeout(ctx, l2client, delayedTxs[len(delayedTxs)-1], time.Second*10) Require(t, err, "Failed waiting for Tx on main node") _, err = EnsureTxSucceededWithTimeout(ctx, l2clientB, delayedTxs[len(delayedTxs)-1], time.Second*10) Require(t, err, "Failed waiting for Tx on secondary node") - delayedBalance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("DelayedReceiver"), nil) + delayedBalance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("DelayedReceiver"), nil) Require(t, err) - directBalance, err := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("DirectReceiver"), nil) + directBalance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("DirectReceiver"), nil) Require(t, err) delayedExpectd := new(big.Int).Mul(fundsPerDelayed, big.NewInt(delayedTransfers)) directExpectd := new(big.Int).Mul(fundsPerDirect, big.NewInt(directTransfers)) if (delayedBalance.Cmp(delayedExpectd) != 0) || (directBalance.Cmp(directExpectd) != 0) { t.Error("delayed balance", delayedBalance, "expected", delayedExpectd, "transfers", delayedTransfers) t.Error("direct balance", directBalance, "expected", directExpectd, "transfers", directTransfers) - ownerBalance, _ := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("Owner"), nil) - delayedFaucetBalance, _ := l2clientB.BalanceAt(ctx, testNodeA.L2Info.GetAddress("DelayedFaucet"), nil) + ownerBalance, _ := l2clientB.BalanceAt(ctx, l2info.GetAddress("Owner"), nil) + delayedFaucetBalance, _ := l2clientB.BalanceAt(ctx, l2info.GetAddress("DelayedFaucet"), nil) t.Error("owner balance", ownerBalance, "delayed faucet", delayedFaucetBalance) Fatal(t, "Unexpected balance") } - testNodeA.L2Node.StopAndWait() + nodeA.StopAndWait() if nodeB.BlockValidator != nil { lastBlockHeader, err := l2clientB.HeaderByNumber(ctx, nil) From 0e7ddcc82c573604e5ec8aedaab45e9addb9dbb7 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 28 Sep 2023 16:08:02 -0600 Subject: [PATCH 199/775] fix review comments --- arbnode/node.go | 32 +++++++--------- arbnode/seq_coordinator.go | 10 ++++- arbnode/sync_monitor.go | 6 ++- cmd/nitro/nitro.go | 24 ++++-------- execution/gethexec/node.go | 51 +++++++++++++++----------- execution/interface.go | 3 ++ system_tests/common_test.go | 1 + system_tests/recreatestate_rpc_test.go | 1 + 8 files changed, 67 insertions(+), 61 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 25bc7bafc..ec2f28b77 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -376,7 +376,7 @@ func ConfigDefaultL1Test() *Config { config.BatchPoster = TestBatchPosterConfig config.SeqCoordinator = TestSeqCoordinatorConfig config.Sequencer = true - config.Dangerous.NoCoordinator = true + config.Dangerous.NoSequencerCoordinator = true return config } @@ -413,18 +413,18 @@ func ConfigDefaultL2Test() *Config { } type DangerousConfig struct { - NoL1Listener bool `koanf:"no-l1-listener"` - NoCoordinator bool `koanf:"no-coordinator"` + NoL1Listener bool `koanf:"no-l1-listener"` + NoSequencerCoordinator bool `koanf:"no-sequencer-coordinator"` } var DefaultDangerousConfig = DangerousConfig{ - NoL1Listener: false, - NoCoordinator: false, + NoL1Listener: false, + NoSequencerCoordinator: false, } func DangerousConfigAddOptions(prefix string, f *flag.FlagSet) { f.Bool(prefix+".no-l1-listener", DefaultDangerousConfig.NoL1Listener, "DANGEROUS! disables listening to L1. To be used in test nodes only") - f.Bool(prefix+".no-coordinator", DefaultDangerousConfig.NoCoordinator, "DANGEROUS! allows sequencing without sequencer-coordinator") + f.Bool(prefix+".no-sequencer-coordinator", DefaultDangerousConfig.NoSequencerCoordinator, "DANGEROUS! allows sequencing without sequencer-coordinator") } type Node struct { @@ -606,8 +606,8 @@ func createNodeImpl( if err != nil { return nil, err } - } else if config.Sequencer && !config.Dangerous.NoCoordinator { - return nil, errors.New("sequencer must be enabled with coordinator, unless dangerous.no-coordinator set") + } else if config.Sequencer && !config.Dangerous.NoSequencerCoordinator { + return nil, errors.New("sequencer must be enabled with coordinator, unless dangerous.no-sequencer-coordinator set") } dbs := []ethdb.Database{arbDb} maintenanceRunner, err := NewMaintenanceRunner(func() *MaintenanceConfig { return &configFetcher.Get().Maintenance }, coordinator, dbs, exec) @@ -929,11 +929,9 @@ func (n *Node) Start(ctx context.Context) error { if err != nil { return fmt.Errorf("error starting geth stack: %w", err) } - if execClient != nil { - err := execClient.Start(ctx) - if err != nil { - return fmt.Errorf("error starting exec client: %w", err) - } + err = n.Execution.Start(ctx) + if err != nil { + return fmt.Errorf("error starting exec client: %w", err) } if n.InboxTracker != nil { err = n.InboxTracker.Initialize() @@ -1038,12 +1036,8 @@ func (n *Node) Start(ctx context.Context) error { } func (n *Node) StopAndWait() { - execClient, ok := n.Execution.(*gethexec.ExecutionNode) - if !ok { - execClient = nil - } - if execClient != nil { - execClient.StopAndWait() + if n.Execution != nil { + n.Execution.StopAndWait() } if n.MaintenanceRunner != nil && n.MaintenanceRunner.Started() { n.MaintenanceRunner.StopAndWait() diff --git a/arbnode/seq_coordinator.go b/arbnode/seq_coordinator.go index 34197eea7..2339935e1 100644 --- a/arbnode/seq_coordinator.go +++ b/arbnode/seq_coordinator.go @@ -132,8 +132,14 @@ var TestSeqCoordinatorConfig = SeqCoordinatorConfig{ Signer: signature.DefaultSignVerifyConfig, } -func NewSeqCoordinator(dataSigner signature.DataSignerFunc, bpvalidator *contracts.BatchPosterVerifier, streamer *TransactionStreamer, sequencer execution.ExecutionSequencer, - sync *SyncMonitor, config SeqCoordinatorConfig) (*SeqCoordinator, error) { +func NewSeqCoordinator( + dataSigner signature.DataSignerFunc, + bpvalidator *contracts.BatchPosterVerifier, + streamer *TransactionStreamer, + sequencer execution.ExecutionSequencer, + sync *SyncMonitor, + config SeqCoordinatorConfig, +) (*SeqCoordinator, error) { redisCoordinator, err := redisutil.NewRedisCoordinator(config.RedisUrl) if err != nil { return nil, err diff --git a/arbnode/sync_monitor.go b/arbnode/sync_monitor.go index bd9b24529..598ea4fb3 100644 --- a/arbnode/sync_monitor.go +++ b/arbnode/sync_monitor.go @@ -67,12 +67,14 @@ func (s *SyncMonitor) SyncProgressMap() map[string]interface{} { } res["broadcasterQueuedMessagesPos"] = broadcasterQueuedMessagesPos - builtMessageCount, err := s.txStreamer.exec.HeadMessageNumber() + builtMessageCount, err := s.exec.HeadMessageNumber() if err != nil { - res["blockMessageToMessageCountError"] = err.Error() + res["builtMessageCountError"] = err.Error() syncing = true builtMessageCount = 0 } else { + blockNum := s.exec.MessageIndexToBlockNumber(builtMessageCount) + res["blockNum"] = blockNum builtMessageCount++ res["messageOfLastBlock"] = builtMessageCount } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 560a68b8b..587cb884d 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -203,10 +203,6 @@ func mainImpl() int { fmt.Fprintf(os.Stderr, "Error initializing logging: %v\n", err) return 1 } - if nodeConfig.Execution.Archive { - log.Warn("--node.archive has been deprecated. Please use --node.caching.archive instead.") - nodeConfig.Execution.Caching.Archive = true - } log.Info("Running Arbitrum nitro node", "revision", vcsRevision, "vcs.time", vcsTime) @@ -218,18 +214,12 @@ func mainImpl() int { nodeConfig.Node.ParentChainReader.Enable = true } - if nodeConfig.Execution.Sequencer.Enable { - if nodeConfig.Execution.ForwardingTargetF() != "" { - flag.Usage() - log.Crit("forwarding-target cannot be set when sequencer is enabled") - } - if nodeConfig.Node.ParentChainReader.Enable && nodeConfig.Node.InboxReader.HardReorg { - flag.Usage() - log.Crit("hard reorgs cannot safely be enabled with sequencer mode enabled") - } - } else if nodeConfig.Execution.ForwardingTarget == "" { + if nodeConfig.Execution.Sequencer.Enable && nodeConfig.Node.ParentChainReader.Enable && nodeConfig.Node.InboxReader.HardReorg { flag.Usage() - log.Crit("forwarding-target unset, and not sequencer (can set to \"null\" to disable forwarding)") + log.Crit("hard reorgs cannot safely be enabled with sequencer mode enabled") + } + if nodeConfig.Execution.Sequencer.Enable != nodeConfig.Node.Sequencer { + log.Error("consensus and execution must agree if sequencing is enabled or not", "Execution.Sequencer.Enable", nodeConfig.Execution.Sequencer.Enable, "Node.Sequencer", nodeConfig.Node.Sequencer) } var l1TransactionOpts *bind.TransactOpts @@ -314,7 +304,7 @@ func mainImpl() int { } if nodeConfig.Execution.RPC.MaxRecreateStateDepth == arbitrum.UninitializedMaxRecreateStateDepth { - if nodeConfig.Execution.Archive { + if nodeConfig.Execution.Caching.Archive { nodeConfig.Execution.RPC.MaxRecreateStateDepth = arbitrum.DefaultArchiveNodeMaxRecreateStateDepth } else { nodeConfig.Execution.RPC.MaxRecreateStateDepth = arbitrum.DefaultNonArchiveNodeMaxRecreateStateDepth @@ -764,7 +754,7 @@ func ParseNode(ctx context.Context, args []string) (*NodeConfig, *genericconf.Wa nodeConfig.ParentChain.Wallet = genericconf.WalletConfigDefault nodeConfig.Chain.DevWallet = genericconf.WalletConfigDefault - if nodeConfig.Execution.Archive { + if nodeConfig.Execution.Caching.Archive { nodeConfig.Node.MessagePruner.Enable = false } err = nodeConfig.Validate() diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 5176eb28d..b29309cdb 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "sync/atomic" "testing" "github.com/ethereum/go-ethereum/arbitrum" @@ -45,25 +46,26 @@ type Config struct { ForwardingTarget string `koanf:"forwarding-target"` Caching CachingConfig `koanf:"caching"` RPC arbitrum.Config `koanf:"rpc"` - Archive bool `koanf:"archive"` TxLookupLimit uint64 `koanf:"tx-lookup-limit"` Dangerous DangerousConfig `koanf:"dangerous"` -} - -func (c *Config) ForwardingTargetF() string { - if c.ForwardingTarget == "null" { - return "" - } - return c.ForwardingTarget + forwardingTarget string } func (c *Config) Validate() error { if err := c.Sequencer.Validate(); err != nil { return err } - if err := c.Sequencer.Validate(); err != nil { - return err + if !c.Sequencer.Enable && c.ForwardingTarget == "" { + return errors.New("ForwardingTarget not set and not sequencer (can use \"null\")") + } + if c.ForwardingTarget == "null" { + c.forwardingTarget = "" + } else { + c.forwardingTarget = c.ForwardingTarget + } + if c.forwardingTarget != "" && c.Sequencer.Enable { + return errors.New("ForwardingTarget set and sequencer enabled") } return nil } @@ -77,8 +79,6 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { TxPreCheckerConfigAddOptions(prefix+".tx-pre-checker", f) CachingConfigAddOptions(prefix+".caching", 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)") - archiveMsg := fmt.Sprintf("retain past block state (deprecated, please use %v.caching.archive)", prefix) - f.Bool(prefix+".archive", ConfigDefault.Archive, archiveMsg) DangerousConfigAddOptions(prefix+".dangerous", f) } @@ -88,7 +88,6 @@ var ConfigDefault = Config{ RecordingDatabase: arbitrum.DefaultRecordingDatabaseConfig, ForwardingTarget: "", TxPreChecker: DefaultTxPreCheckerConfig, - Archive: false, TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second Caching: DefaultCachingConfig, Dangerous: DefaultDangerousConfig, @@ -98,6 +97,9 @@ func ConfigDefaultNonSequencerTest() *Config { config := ConfigDefault config.Sequencer.Enable = false config.Forwarder = DefaultTestForwarderConfig + config.ForwardingTarget = "null" + + _ = config.Validate() return &config } @@ -105,6 +107,9 @@ func ConfigDefaultNonSequencerTest() *Config { func ConfigDefaultTest() *Config { config := ConfigDefault config.Sequencer = TestSequencerConfig + config.ForwardingTarget = "null" + + _ = config.Validate() return &config } @@ -122,6 +127,7 @@ type ExecutionNode struct { TxPublisher TransactionPublisher ConfigFetcher ConfigFetcher ParentChainReader *headerreader.HeaderReader + started atomic.Bool } func CreateExecutionNode( @@ -150,11 +156,7 @@ func CreateExecutionNode( } } - fwTarget := config.ForwardingTargetF() if config.Sequencer.Enable { - if fwTarget != "" { - return nil, errors.New("sequencer and forwarding target both set") - } seqConfigFetcher := func() *SequencerConfig { return &configFetcher().Sequencer } sequencer, err = NewSequencer(execEngine, parentChainReader, seqConfigFetcher) if err != nil { @@ -163,11 +165,11 @@ func CreateExecutionNode( txPublisher = sequencer } else { if config.Forwarder.RedisUrl != "" { - txPublisher = NewRedisTxForwarder(fwTarget, &config.Forwarder) - } else if fwTarget == "" { + txPublisher = NewRedisTxForwarder(config.forwardingTarget, &config.Forwarder) + } else if config.forwardingTarget == "" { txPublisher = NewTxDropper() } else { - txPublisher = NewForwarder(fwTarget, &config.Forwarder) + txPublisher = NewForwarder(config.forwardingTarget, &config.Forwarder) } } @@ -252,7 +254,11 @@ func (n *ExecutionNode) Initialize(ctx context.Context, arbnode interface{}, syn return nil } +// not thread safe func (n *ExecutionNode) Start(ctx context.Context) error { + if n.started.Swap(true) { + return errors.New("already started") + } // TODO after separation // err := n.Stack.Start() // if err != nil { @@ -270,6 +276,9 @@ func (n *ExecutionNode) Start(ctx context.Context) error { } func (n *ExecutionNode) StopAndWait() { + if !n.started.Load() { + return + } // TODO after separation // n.Stack.StopRPC() // does nothing if not running if n.TxPublisher.Started() { @@ -342,7 +351,7 @@ func (n *ExecutionNode) ForwardTo(url string) error { if n.Sequencer != nil { return n.Sequencer.ForwardTo(url) } else { - return errors.New("forwardTo not supported - sequencer not acrtive") + return errors.New("forwardTo not supported - sequencer not active") } } func (n *ExecutionNode) SetTransactionStreamer(streamer execution.TransactionStreamer) { diff --git a/execution/interface.go b/execution/interface.go index e6895bc14..ef9409b9c 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -62,6 +62,9 @@ type FullExecutionClient interface { ExecutionRecorder ExecutionSequencer + Start(ctx context.Context) error + StopAndWait() + Maintenance() error // TODO: only used to get safe/finalized block numbers diff --git a/system_tests/common_test.go b/system_tests/common_test.go index a31c354cd..19357c5b7 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -797,6 +797,7 @@ func Create2ndNodeWithConfig( AddDefaultValNode(t, ctx, nodeConfig, true) + Require(t, execConfig.Validate()) configFetcher := func() *gethexec.Config { return execConfig } currentExec, err := gethexec.CreateExecutionNode(ctx, l2stack, l2chainDb, l2blockchain, l1client, configFetcher) Require(t, err) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index 9e23ccdff..28e72b065 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -338,6 +338,7 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig feedErrChan := make(chan error, 10) l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, nil, t.TempDir(), params.ArbitrumDevTestChainConfig(), &execConfig.Caching) + Require(t, execConfig.Validate()) execConfigFetcher := func() *gethexec.Config { return execConfig } execNode, err := gethexec.CreateExecutionNode(ctx1, stack, chainDb, blockchain, nil, execConfigFetcher) Require(t, err) From 470ed2a64bd0949dd8f7469f29f0177e9d8b1ca7 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 28 Sep 2023 18:16:10 -0600 Subject: [PATCH 200/775] Bump go-ethereum pin to latest master --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 89f53b035..921163a16 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 89f53b035d7a8b9b1ff8599958bf0c55efcdf718 +Subproject commit 921163a16b537c08b1a383663ce2c4f3bd84a3a0 From 6ecadc3ffb613d8e1b915e89312c2d44b7ec5853 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 28 Sep 2023 20:19:23 -0600 Subject: [PATCH 201/775] Add wavmio preimage test to go prover test --- Makefile | 2 +- arbitrator/prover/test-cases/go/main.go | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 38ffb9620..422110096 100644 --- a/Makefile +++ b/Makefile @@ -295,7 +295,7 @@ contracts/test/prover/proofs/rust-%.json: $(arbitrator_cases)/rust/target/wasm32 $(arbitrator_prover_bin) $< $(arbitrator_wasm_lib_flags_nogo) -o $@ -b --allow-hostapi --require-success --inbox-add-stub-headers --inbox $(arbitrator_cases)/rust/data/msg0.bin --inbox $(arbitrator_cases)/rust/data/msg1.bin --delayed-inbox $(arbitrator_cases)/rust/data/msg0.bin --delayed-inbox $(arbitrator_cases)/rust/data/msg1.bin --preimages $(arbitrator_cases)/rust/data/preimages.bin contracts/test/prover/proofs/go.json: $(arbitrator_cases)/go/main $(arbitrator_prover_bin) $(arbitrator_wasm_libs) - $(arbitrator_prover_bin) $< $(arbitrator_wasm_lib_flags) -o $@ -i 5000000 --require-success + $(arbitrator_prover_bin) $< $(arbitrator_wasm_lib_flags) -o $@ -i 5000000 --require-success --preimages $(arbitrator_cases)/rust/data/preimages.bin # avoid testing read-inboxmsg-10 in onestepproofs. It's used for go challenge testing. contracts/test/prover/proofs/read-inboxmsg-10.json: diff --git a/arbitrator/prover/test-cases/go/main.go b/arbitrator/prover/test-cases/go/main.go index a5a1028fb..7ac669f8a 100644 --- a/arbitrator/prover/test-cases/go/main.go +++ b/arbitrator/prover/test-cases/go/main.go @@ -5,14 +5,18 @@ package main import ( "bytes" + "encoding/hex" "fmt" "os" "runtime" "time" + "github.com/ethereum/go-ethereum/common" merkletree "github.com/wealdtech/go-merkletree" "github.com/offchainlabs/nitro/arbcompress" + "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/wavmio" ) // MerkleSample is an example using the Merkle tree to generate and verify proofs. @@ -95,4 +99,19 @@ func main() { testCompression([]byte("This is a test string la la la la la la la la la la")) println("test compression passed!\n") + + checkPreimage := func(ty arbutil.PreimageType, hash common.Hash) { + preimage, err := wavmio.ResolveTypedPreimage(ty, hash) + if err != nil { + panic(fmt.Sprintf("failed to resolve preimage of type %v: %v", ty, err)) + } + if !bytes.Equal(preimage, []byte("hello world")) { + panic(fmt.Sprintf("got wrong preimage of type %v: %v", ty, hex.EncodeToString(preimage))) + } + } + + checkPreimage(arbutil.Keccak256PreimageType, common.HexToHash("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad")) + checkPreimage(arbutil.Sha2_256PreimageType, common.HexToHash("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9")) + + println("verified preimage resolution!\n") } From ff1ea776401e4cf6cd579abc5692a84b87c8eb25 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 29 Sep 2023 18:16:12 +0530 Subject: [PATCH 202/775] minor fix --- arbnode/redislock/redis.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/redislock/redis.go b/arbnode/redislock/redis.go index c02476f04..c8252e059 100644 --- a/arbnode/redislock/redis.go +++ b/arbnode/redislock/redis.go @@ -42,7 +42,7 @@ func AddConfigOptions(prefix string, f *flag.FlagSet) { f.String(prefix+".my-id", "", "this node's id prefix when acquiring the lock (optional)") f.Duration(prefix+".lockout-duration", DefaultCfg.LockoutDuration, "how long lock is held") f.Duration(prefix+".refresh-duration", DefaultCfg.RefreshDuration, "how long between consecutive calls to redis") - f.String(prefix+".key", prefix+".simple-lock-key", "key for lock") + f.String(prefix+".key", DefaultCfg.Key, "key for lock") f.Bool(prefix+".background-lock", DefaultCfg.BackgroundLock, "should node always try grabing lock in background") } From 0f75e8f652eabfce22cac78bf537ad3dd4f7080f Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 29 Sep 2023 18:19:56 +0530 Subject: [PATCH 203/775] minor fix --- contracts | 2 +- das/das.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts b/contracts index b16bf0b73..ae11e7a86 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit b16bf0b737468382854dac28346fec8b65b55989 +Subproject commit ae11e7a86488e28c706e062ae501bfb7157197c1 diff --git a/das/das.go b/das/das.go index f05bdb7f3..9133b73ea 100644 --- a/das/das.go +++ b/das/das.go @@ -69,7 +69,7 @@ var DefaultDataAvailabilityConfig = DataAvailabilityConfig{ RestAggregator: DefaultRestfulClientAggregatorConfig, ParentChainConnectionAttempts: 15, PanicOnError: false, - IpfsStorageServiceConfig: DefaultIpfsStorageServiceConfig, + IpfsStorage: DefaultIpfsStorageServiceConfig, } func OptionalAddressFromString(s string) (*common.Address, error) { From ed37574632a4cea67ddff98f4a20213589d06e36 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 29 Sep 2023 18:20:34 +0530 Subject: [PATCH 204/775] minor fix --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index ae11e7a86..b16bf0b73 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit ae11e7a86488e28c706e062ae501bfb7157197c1 +Subproject commit b16bf0b737468382854dac28346fec8b65b55989 From 1f549cdb486cfc8f9a46360a07149e754d4beb57 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 29 Sep 2023 18:41:48 +0530 Subject: [PATCH 205/775] minor fix --- arbnode/batch_poster.go | 2 +- arbnode/dataposter/data_poster.go | 30 +++++++++++++++--------------- arbnode/maintenance.go | 1 + arbnode/node.go | 1 + staker/staker.go | 2 +- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 073c29931..659d3256e 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -164,7 +164,7 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".l1-block-bound", DefaultBatchPosterConfig.L1BlockBound, "only post messages to batches when they're within the max future block/timestamp as of this L1 block tag (\"safe\", \"finalized\", \"latest\", or \"ignore\" to ignore this check)") f.Duration(prefix+".l1-block-bound-bypass", DefaultBatchPosterConfig.L1BlockBoundBypass, "post batches even if not within the layer 1 future bounds if we're within this margin of the max delay") redislock.AddConfigOptions(prefix+".redis-lock", f) - dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f) + dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f, dataposter.DefaultDataPosterConfig) genericconf.WalletConfigAddOptions(prefix+".parent-chain-wallet", f, DefaultBatchPosterConfig.ParentChainWallet.Pathname) } diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 3b563e965..aa0a710f9 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -661,21 +661,21 @@ type DangerousConfig struct { // that flags can be reloaded dynamically. type ConfigFetcher func() *DataPosterConfig -func DataPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { - f.String(prefix+".replacement-times", DefaultDataPosterConfig.ReplacementTimes, "comma-separated list of durations since first posting to attempt a replace-by-fee") - f.Bool(prefix+".wait-for-l1-finality", DefaultDataPosterConfig.WaitForL1Finality, "only treat a transaction as confirmed after L1 finality has been achieved (recommended)") - f.Uint64(prefix+".max-mempool-transactions", DefaultDataPosterConfig.MaxMempoolTransactions, "the maximum number of transactions to have queued in the mempool at once (0 = unlimited)") - f.Int(prefix+".max-queued-transactions", DefaultDataPosterConfig.MaxQueuedTransactions, "the maximum number of unconfirmed transactions to track at once (0 = unlimited)") - f.Float64(prefix+".target-price-gwei", DefaultDataPosterConfig.TargetPriceGwei, "the target price to use for maximum fee cap calculation") - f.Float64(prefix+".urgency-gwei", DefaultDataPosterConfig.UrgencyGwei, "the urgency to use for maximum fee cap calculation") - f.Float64(prefix+".min-fee-cap-gwei", DefaultDataPosterConfig.MinFeeCapGwei, "the minimum fee cap to post transactions at") - f.Float64(prefix+".min-tip-cap-gwei", DefaultDataPosterConfig.MinTipCapGwei, "the minimum tip cap to post transactions at") - f.Float64(prefix+".max-tip-cap-gwei", DefaultDataPosterConfig.MaxTipCapGwei, "the maximum tip cap to post transactions at") - f.Uint64(prefix+".nonce-rbf-soft-confs", DefaultDataPosterConfig.NonceRbfSoftConfs, "the maximum probable reorg depth, used to determine when a transaction will no longer likely need replaced-by-fee") - f.Bool(prefix+".allocate-mempool-balance", DefaultDataPosterConfig.AllocateMempoolBalance, "if true, don't put transactions in the mempool that spend a total greater than the batch poster's balance") - f.Bool(prefix+".use-db-storage", DefaultDataPosterConfig.UseDBStorage, "uses database storage when enabled") - f.Bool(prefix+".use-noop-storage", DefaultDataPosterConfig.UseNoOpStorage, "uses noop storage, it doesn't store anything") - f.Bool(prefix+".legacy-storage-encoding", DefaultDataPosterConfig.LegacyStorageEncoding, "encodes items in a legacy way (as it was before dropping generics)") +func DataPosterConfigAddOptions(prefix string, f *pflag.FlagSet, defaultDataPosterConfig DataPosterConfig) { + f.String(prefix+".replacement-times", defaultDataPosterConfig.ReplacementTimes, "comma-separated list of durations since first posting to attempt a replace-by-fee") + f.Bool(prefix+".wait-for-l1-finality", defaultDataPosterConfig.WaitForL1Finality, "only treat a transaction as confirmed after L1 finality has been achieved (recommended)") + f.Uint64(prefix+".max-mempool-transactions", defaultDataPosterConfig.MaxMempoolTransactions, "the maximum number of transactions to have queued in the mempool at once (0 = unlimited)") + f.Int(prefix+".max-queued-transactions", defaultDataPosterConfig.MaxQueuedTransactions, "the maximum number of unconfirmed transactions to track at once (0 = unlimited)") + f.Float64(prefix+".target-price-gwei", defaultDataPosterConfig.TargetPriceGwei, "the target price to use for maximum fee cap calculation") + f.Float64(prefix+".urgency-gwei", defaultDataPosterConfig.UrgencyGwei, "the urgency to use for maximum fee cap calculation") + f.Float64(prefix+".min-fee-cap-gwei", defaultDataPosterConfig.MinFeeCapGwei, "the minimum fee cap to post transactions at") + f.Float64(prefix+".min-tip-cap-gwei", defaultDataPosterConfig.MinTipCapGwei, "the minimum tip cap to post transactions at") + f.Float64(prefix+".max-tip-cap-gwei", defaultDataPosterConfig.MaxTipCapGwei, "the maximum tip cap to post transactions at") + f.Uint64(prefix+".nonce-rbf-soft-confs", defaultDataPosterConfig.NonceRbfSoftConfs, "the maximum probable reorg depth, used to determine when a transaction will no longer likely need replaced-by-fee") + f.Bool(prefix+".allocate-mempool-balance", defaultDataPosterConfig.AllocateMempoolBalance, "if true, don't put transactions in the mempool that spend a total greater than the batch poster's balance") + f.Bool(prefix+".use-db-storage", defaultDataPosterConfig.UseDBStorage, "uses database storage when enabled") + f.Bool(prefix+".use-noop-storage", defaultDataPosterConfig.UseNoOpStorage, "uses noop storage, it doesn't store anything") + f.Bool(prefix+".legacy-storage-encoding", defaultDataPosterConfig.LegacyStorageEncoding, "encodes items in a legacy way (as it was before dropping generics)") signature.SimpleHmacConfigAddOptions(prefix+".redis-signer", f) addDangerousOptions(prefix+".dangerous", f) diff --git a/arbnode/maintenance.go b/arbnode/maintenance.go index 2b1837a25..b95e9bd86 100644 --- a/arbnode/maintenance.go +++ b/arbnode/maintenance.go @@ -76,6 +76,7 @@ func MaintenanceConfigAddOptions(prefix string, f *flag.FlagSet) { var DefaultMaintenanceConfig = MaintenanceConfig{ TimeOfDay: "", + Lock: redislock.DefaultCfg, minutesAfterMidnight: 0, } diff --git a/arbnode/node.go b/arbnode/node.go index fd2c2d927..efdb8e65d 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -410,6 +410,7 @@ var ConfigDefault = Config{ Caching: execution.DefaultCachingConfig, TransactionStreamer: DefaultTransactionStreamerConfig, ResourceMgmt: resourcemanager.DefaultConfig, + Maintenance: DefaultMaintenanceConfig, } func ConfigDefaultL1Test() *Config { diff --git a/staker/staker.go b/staker/staker.go index d52d1adc7..4148d0a20 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -203,7 +203,7 @@ func L1ValidatorConfigAddOptions(prefix string, f *flag.FlagSet) { f.String(prefix+".gas-refunder-address", DefaultL1ValidatorConfig.GasRefunderAddress, "The gas refunder contract address (optional)") f.String(prefix+".redis-url", DefaultL1ValidatorConfig.RedisUrl, "redis url for L1 validator") f.Uint64(prefix+".extra-gas", DefaultL1ValidatorConfig.ExtraGas, "use this much more gas than estimation says is necessary to post transactions") - dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f) + dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f, dataposter.DefaultDataPosterConfigForValidator) redislock.AddConfigOptions(prefix+".redis-lock", f) DangerousConfigAddOptions(prefix+".dangerous", f) genericconf.WalletConfigAddOptions(prefix+".parent-chain-wallet", f, DefaultL1ValidatorConfig.ParentChainWallet.Pathname) From b725fece91ebfdf29c4796933d72c3fcf4158e66 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 29 Sep 2023 19:07:57 +0530 Subject: [PATCH 206/775] Changes based on PR comments --- system_tests/common_test.go | 4 ++-- system_tests/conditionaltx_test.go | 2 +- system_tests/estimation_test.go | 11 ++++++----- system_tests/log_subscription_test.go | 2 +- system_tests/outbox_test.go | 2 +- system_tests/precompile_test.go | 8 ++++---- system_tests/reorg_resequencing_test.go | 2 +- system_tests/retryable_test.go | 2 +- system_tests/seq_pause_test.go | 2 +- system_tests/transfer_test.go | 2 +- 10 files changed, 19 insertions(+), 18 deletions(-) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index f1922c734..20e78f9d2 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -642,8 +642,8 @@ func createTestNodeOnL1WithConfigImpl( // L2 -Only. Enough for tests that needs no interface to L1 // Requires precompiles.AllowDebugPrecompiles = true -func CreateTestL2(t *testing.T, ctx context.Context, chainConfig *params.ChainConfig) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { - return CreateTestL2WithConfig(t, ctx, nil, arbnode.ConfigDefaultL2Test(), true, chainConfig) +func CreateTestL2(t *testing.T, ctx context.Context) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { + return CreateTestL2WithConfig(t, ctx, nil, arbnode.ConfigDefaultL2Test(), true, nil) } func CreateTestL2WithConfig( diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index d2faf5c3e..14aa00031 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -308,7 +308,7 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx, nil) + l2info, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() rpcClient, err := node.Stack.Attach() Require(t, err) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index 4d5c4a8d0..18dda4d84 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -5,6 +5,7 @@ package arbtest import ( "context" + "github.com/offchainlabs/nitro/arbnode" "math/big" "testing" @@ -26,7 +27,7 @@ func TestDeploy(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx, nil) + l2info, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) @@ -51,7 +52,7 @@ func TestEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx, nil) + l2info, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) @@ -131,7 +132,7 @@ func TestDifficultyForLatestArbOS(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx, nil) + l2info, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) @@ -153,7 +154,7 @@ func TestDifficultyForArbOSTen(t *testing.T) { chainConfig := params.ArbitrumDevTestChainConfig() chainConfig.ArbitrumChainParams.InitialArbOSVersion = 10 - l2info, node, client := CreateTestL2(t, ctx, chainConfig) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, arbnode.ConfigDefaultL2Test(), true, chainConfig) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) @@ -173,7 +174,7 @@ func TestComponentEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx, nil) + l2info, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() l1BaseFee := new(big.Int).Set(arbostypes.DefaultInitialL1BaseFee) diff --git a/system_tests/log_subscription_test.go b/system_tests/log_subscription_test.go index 54ad0fe5e..5ee1732fb 100644 --- a/system_tests/log_subscription_test.go +++ b/system_tests/log_subscription_test.go @@ -19,7 +19,7 @@ func TestLogSubscription(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx, nil) + l2info, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) diff --git a/system_tests/outbox_test.go b/system_tests/outbox_test.go index d79f74c5b..6b43cc83b 100644 --- a/system_tests/outbox_test.go +++ b/system_tests/outbox_test.go @@ -35,7 +35,7 @@ func TestOutboxProofs(t *testing.T) { withdrawTopic := arbSysAbi.Events["L2ToL1Tx"].ID merkleTopic := arbSysAbi.Events["SendMerkleUpdate"].ID - l2info, node, client := CreateTestL2(t, ctx, nil) + l2info, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) diff --git a/system_tests/precompile_test.go b/system_tests/precompile_test.go index 66feccf46..ad08ff747 100644 --- a/system_tests/precompile_test.go +++ b/system_tests/precompile_test.go @@ -21,7 +21,7 @@ func TestPurePrecompileMethodCalls(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx, nil) + _, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() arbSys, err := precompilesgen.NewArbSys(common.HexToAddress("0x64"), client) @@ -37,7 +37,7 @@ func TestViewLogReverts(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx, nil) + _, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) @@ -53,7 +53,7 @@ func TestCustomSolidityErrors(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx, nil) + _, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() callOpts := &bind.CallOpts{Context: ctx} @@ -86,7 +86,7 @@ func TestPrecompileErrorGasLeft(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - info, node, client := CreateTestL2(t, ctx, nil) + info, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() auth := info.GetDefaultTransactOpts("Faucet", ctx) diff --git a/system_tests/reorg_resequencing_test.go b/system_tests/reorg_resequencing_test.go index c3a46b139..f132d4648 100644 --- a/system_tests/reorg_resequencing_test.go +++ b/system_tests/reorg_resequencing_test.go @@ -19,7 +19,7 @@ func TestReorgResequencing(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx, nil) + l2info, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() startMsgCount, err := node.TxStreamer.GetMessageCount() diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 674b2311c..b1dd32d1d 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -116,7 +116,7 @@ func retryableSetup(t *testing.T) ( func TestRetryableNoExist(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, l2client := CreateTestL2(t, ctx, nil) + _, node, l2client := CreateTestL2(t, ctx) defer node.StopAndWait() arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) diff --git a/system_tests/seq_pause_test.go b/system_tests/seq_pause_test.go index 2bd0139fc..fd057c018 100644 --- a/system_tests/seq_pause_test.go +++ b/system_tests/seq_pause_test.go @@ -16,7 +16,7 @@ func TestSequencerPause(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info1, nodeA, client := CreateTestL2(t, ctx, nil) + l2info1, nodeA, client := CreateTestL2(t, ctx) defer nodeA.StopAndWait() const numUsers = 100 diff --git a/system_tests/transfer_test.go b/system_tests/transfer_test.go index b7328f2b7..2e3317907 100644 --- a/system_tests/transfer_test.go +++ b/system_tests/transfer_test.go @@ -13,7 +13,7 @@ import ( func TestTransfer(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, client := CreateTestL2(t, ctx, nil) + l2info, l2node, client := CreateTestL2(t, ctx) defer l2node.StopAndWait() l2info.GenerateAccount("User2") From 104011baa98589ab49993fb2a701a0be7d4de4de Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 29 Sep 2023 16:56:48 -0500 Subject: [PATCH 207/775] Update builder pattern --- system_tests/batch_poster_test.go | 49 +++--- system_tests/bloom_test.go | 31 ++-- system_tests/common_test.go | 202 ++++++++++------------- system_tests/full_challenge_impl_test.go | 75 +++++---- 4 files changed, 170 insertions(+), 187 deletions(-) diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index ef50be6ec..e063db998 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -45,16 +45,19 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { parallelBatchPosters = 4 } - conf := arbnode.ConfigDefaultL1Test() - conf.BatchPoster.Enable = false - conf.BatchPoster.RedisUrl = redisUrl - builder := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true) - l1A, l2A := builder.BuildL2OnL1(t) - // testNodeA := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true).CreateTestNodeOnL1AndL2(t) + builder := NewNodeBuilder(ctx).DefaultConfig(true, nil, nil) + builder.nodeConfig.BatchPoster.Enable = false + builder.nodeConfig.BatchPoster.RedisUrl = redisUrl + builder.Build(t) + l1A, l2A := builder.L1, builder.L2 + defer requireClose(t, l1A.Stack) defer l2A.Node.StopAndWait() - l2B := builder.Build2ndNodeDAS(t, &l2A.Info.ArbInitData, nil) + params := make(SecondNodeParams) + params["initData"] = &l2A.Info.ArbInitData + params["dasConfig"] = nil + l2B := builder.Build2ndNode(t, params) defer l2B.Node.StopAndWait() l2A.Info.GenerateAccount("User2") @@ -77,13 +80,13 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { firstTxData, err := txs[0].MarshalBinary() Require(t, err) seqTxOpts := l1A.Info.GetDefaultTransactOpts("Sequencer", ctx) - conf.BatchPoster.Enable = true - conf.BatchPoster.MaxSize = len(firstTxData) * 2 + builder.nodeConfig.BatchPoster.Enable = true + builder.nodeConfig.BatchPoster.MaxSize = len(firstTxData) * 2 startL1Block, err := l1A.Client.BlockNumber(ctx) Require(t, err) for i := 0; i < parallelBatchPosters; i++ { // Make a copy of the batch poster config so NewBatchPoster calling Validate() on it doesn't race - batchPosterConfig := conf.BatchPoster + batchPosterConfig := builder.nodeConfig.BatchPoster batchPoster, err := arbnode.NewBatchPoster(ctx, nil, l2A.Node.L1Reader, l2A.Node.InboxTracker, l2A.Node.TxStreamer, l2A.Node.SyncMonitor, func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, l2A.Node.DeployInfo, &seqTxOpts, nil) Require(t, err) batchPoster.Start(ctx) @@ -144,14 +147,18 @@ func TestBatchPosterLargeTx(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - conf := arbnode.ConfigDefaultL1Test() - conf.Sequencer.MaxTxDataSize = 110000 - builder := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true) - l1A, l2A := builder.BuildL2OnL1(t) + builder := NewNodeBuilder(ctx).DefaultConfig(true, nil, nil) + builder.nodeConfig.Sequencer.MaxTxDataSize = 110000 + builder.Build(t) + + l1A, l2A := builder.L1, builder.L2 defer requireClose(t, l1A.Stack) defer l2A.Node.StopAndWait() - l2B := builder.Build2ndNodeDAS(t, &l2A.Info.ArbInitData, nil) + params := make(SecondNodeParams) + params["initData"] = &l2A.Info.ArbInitData + params["dasConfig"] = nil + l2B := builder.Build2ndNode(t, params) defer l2B.Node.StopAndWait() data := make([]byte, 100000) @@ -176,12 +183,12 @@ func TestBatchPosterKeepsUp(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - conf := arbnode.ConfigDefaultL1Test() - conf.BatchPoster.CompressionLevel = brotli.BestCompression - conf.BatchPoster.MaxDelay = time.Hour - conf.RPC.RPCTxFeeCap = 1000. - builder := NewNodeBuilder(ctx).SetNodeConfig(conf).SetIsSequencer(true) - l1A, l2A := builder.BuildL2OnL1(t) + builder := NewNodeBuilder(ctx).DefaultConfig(true, nil, nil) + builder.nodeConfig.BatchPoster.CompressionLevel = brotli.BestCompression + builder.nodeConfig.BatchPoster.MaxDelay = time.Hour + builder.nodeConfig.RPC.RPCTxFeeCap = 1000. + builder.Build(t) + l1A, l2A := builder.L1, builder.L2 defer requireClose(t, l1A.Stack) defer l2A.Node.StopAndWait() l2A.Info.GasPrice = big.NewInt(100e9) diff --git a/system_tests/bloom_test.go b/system_tests/bloom_test.go index 9ad3253d4..6e1c6b0ab 100644 --- a/system_tests/bloom_test.go +++ b/system_tests/bloom_test.go @@ -17,7 +17,6 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/solgen/go/mocksgen" ) @@ -25,17 +24,19 @@ func TestBloom(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - nodeconfig := arbnode.ConfigDefaultL2Test() - nodeconfig.RPC.BloomBitsBlocks = 256 - nodeconfig.RPC.BloomConfirms = 1 - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, false) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(false, nil, nil) + builder.nodeConfig.RPC.BloomBitsBlocks = 256 + builder.nodeConfig.RPC.BloomConfirms = 1 + builder.takeOwnership = false + builder.Build(t) - l2info.GenerateAccount("User2") + defer builder.L2.Node.StopAndWait() - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) + builder.L2.Info.GenerateAccount("User2") + + ownerTxOpts := builder.L2.Info.GetDefaultTransactOpts("Owner", ctx) ownerTxOpts.Context = ctx - _, simple := deploySimple(t, ctx, ownerTxOpts, client) + _, simple := deploySimple(t, ctx, ownerTxOpts, builder.L2.Client) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) @@ -63,7 +64,7 @@ func TestBloom(t *testing.T) { if sendNullEvent { tx, err = simple.EmitNullEvent(&ownerTxOpts) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, builder.L2.Client, tx) Require(t, err) } @@ -74,7 +75,7 @@ func TestBloom(t *testing.T) { tx, err = simple.Increment(&ownerTxOpts) } Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, builder.L2.Client, tx) Require(t, err) if i%100 == 0 { t.Log("counts: ", i, "/", countsNum) @@ -82,7 +83,7 @@ func TestBloom(t *testing.T) { } for { - sectionSize, sectionNum := node.Execution.Backend.APIBackend().BloomStatus() + sectionSize, sectionNum := builder.L2.Node.Execution.Backend.APIBackend().BloomStatus() if sectionSize != 256 { Fatal(t, "unexpected section size: ", sectionSize) } @@ -92,14 +93,14 @@ func TestBloom(t *testing.T) { } <-time.After(time.Second) } - lastHeader, err := client.HeaderByNumber(ctx, nil) + lastHeader, err := builder.L2.Client.HeaderByNumber(ctx, nil) Require(t, err) nullEventQuery := ethereum.FilterQuery{ FromBlock: big.NewInt(0), ToBlock: lastHeader.Number, Topics: [][]common.Hash{{simpleABI.Events["NullEvent"].ID}}, } - logs, err := client.FilterLogs(ctx, nullEventQuery) + logs, err := builder.L2.Client.FilterLogs(ctx, nullEventQuery) Require(t, err) if len(logs) != len(nullEventCounts) { Fatal(t, "expected ", len(nullEventCounts), " logs, got ", len(logs)) @@ -107,7 +108,7 @@ func TestBloom(t *testing.T) { incrementEventQuery := ethereum.FilterQuery{ Topics: [][]common.Hash{{simpleABI.Events["CounterEvent"].ID}}, } - logs, err = client.FilterLogs(ctx, incrementEventQuery) + logs, err = builder.L2.Client.FilterLogs(ctx, incrementEventQuery) Require(t, err) if len(logs) != len(eventCounts) { Fatal(t, "expected ", len(eventCounts), " logs, got ", len(logs)) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 9525d9d6c..56576f9d1 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -74,18 +74,6 @@ func NewTestClient(ctx context.Context) *TestClient { return &TestClient{ctx: ctx} } -// SetClient is used to initialize *ethclient.Client when users dont want to create TestClients via create methods from nodebuilder -func (tc *TestClient) SetClient(c *ethclient.Client) *TestClient { - tc.Client = c - return tc -} - -// SetInfo is used to initialize *BlockchainTestInfo when users dont want to create TestClients via create methods from nodebuilder -func (tc *TestClient) SetInfo(i info) *TestClient { - tc.Info = i - return tc -} - func (tc *TestClient) SendSignedTx(t *testing.T, l2Client *ethclient.Client, transaction *types.Transaction) *types.Receipt { return SendSignedTxViaL1(t, tc.ctx, tc.Info, tc.Client, l2Client, transaction) } @@ -110,21 +98,31 @@ func (tc *TestClient) GetBaseFeeAt(t *testing.T, blockNum *big.Int) *big.Int { return GetBaseFeeAt(t, tc.Client, tc.ctx, blockNum) } +func (tc *TestClient) SendWaitTestTransactions(t *testing.T, txs []*types.Transaction) { + SendWaitTestTransactions(t, tc.ctx, tc.Client, txs) +} + func (tc *TestClient) DeploySimple(t *testing.T, auth bind.TransactOpts) (common.Address, *mocksgen.Simple) { return deploySimple(t, tc.ctx, auth, tc.Client) } type NodeBuilder struct { - // Nodebuilder configuration + // NodeBuilder configuration ctx context.Context Info info chainConfig *params.ChainConfig - cacheConfig *core.CacheConfig nodeConfig *arbnode.Config stackConfig *node.Config cachingConfig *execution.CachingConfig + + // NodeBuiilder Node parameters isSequencer bool takeOwnership bool + withL1 bool + + // NodeBuiilder Blockchain parameters + dataDir string + initMessage *arbostypes.ParsedInitMessage // Created nodes L1 *TestClient @@ -135,136 +133,108 @@ func NewNodeBuilder(ctx context.Context) *NodeBuilder { return &NodeBuilder{ctx: ctx} } -func (b *NodeBuilder) SetChainConfig(c *params.ChainConfig) *NodeBuilder { - b.chainConfig = c - return b -} - -func (b *NodeBuilder) SetNodeConfig(c *arbnode.Config) *NodeBuilder { - b.nodeConfig = c - return b -} - -func (b *NodeBuilder) SetCacheConfig(c *core.CacheConfig) *NodeBuilder { - b.cacheConfig = c - return b -} - -func (b *NodeBuilder) SetStackConfig(c *node.Config) *NodeBuilder { - b.stackConfig = c - return b -} - -func (b *NodeBuilder) SetInfo(i info) *NodeBuilder { - b.Info = i - return b -} - -func (b *NodeBuilder) SetCachingConfig(c *execution.CachingConfig) *NodeBuilder { - b.cachingConfig = c - return b -} - -func (b *NodeBuilder) SetIsSequencer(v bool) *NodeBuilder { - b.isSequencer = v - return b -} - -func (b *NodeBuilder) SetTakeOwnership(v bool) *NodeBuilder { - b.takeOwnership = v - return b -} - -func (b *NodeBuilder) ConfigForL2OnL1(isSequencer bool, n *arbnode.Config, c *params.ChainConfig, s *node.Config, i info) *NodeBuilder { - b.isSequencer = isSequencer - b.nodeConfig = n - b.chainConfig = c - b.stackConfig = s - b.Info = i +func (b *NodeBuilder) DefaultConfig(withL1 bool, n *arbnode.Config, c *params.ChainConfig) *NodeBuilder { + // most used values across current tests are set here as default + b.withL1 = withL1 + if withL1 { + b.isSequencer = true + b.nodeConfig = arbnode.ConfigDefaultL1Test() + if n != nil { + b.nodeConfig = n + } + b.chainConfig = c + } else { + b.takeOwnership = true + b.nodeConfig = arbnode.ConfigDefaultL2Test() + if n != nil { + b.nodeConfig = n + } + b.chainConfig = c + } return b } -func (b *NodeBuilder) BuildL2OnL1(t *testing.T) (*TestClient, *TestClient) { - l1, l2 := NewTestClient(b.ctx), NewTestClient(b.ctx) - l2.Info, l2.Node, l2.Client, l2.Stack, l1.Info, l1.Backend, l1.Client, l1.Stack = - createTestNodeOnL1WithConfigImpl(t, b.ctx, b.isSequencer, b.nodeConfig, b.chainConfig, b.stackConfig, b.Info) - b.L1, b.L2 = l1, l2 - return l1, l2 -} - -func (b *NodeBuilder) ConfigForL2(takeOwnership bool, n *arbnode.Config, i info) *NodeBuilder { - b.takeOwnership = takeOwnership - b.nodeConfig = n - b.Info = i +func (b *NodeBuilder) Build(t *testing.T) *NodeBuilder { + if b.withL1 { + l1, l2 := NewTestClient(b.ctx), NewTestClient(b.ctx) + l2.Info, l2.Node, l2.Client, l2.Stack, l1.Info, l1.Backend, l1.Client, l1.Stack = + createTestNodeOnL1WithConfigImpl(t, b.ctx, b.isSequencer, b.nodeConfig, b.chainConfig, b.stackConfig, b.Info) + b.L1, b.L2 = l1, l2 + } else { + l2 := NewTestClient(b.ctx) + l2.Info, l2.Node, l2.Client = + CreateTestL2WithConfig(t, b.ctx, b.Info, b.nodeConfig, b.takeOwnership) + b.L2 = l2 + } return b } -func (b *NodeBuilder) BuildL2(t *testing.T) *TestClient { - l2 := NewTestClient(b.ctx) - l2.Info, l2.Node, l2.Client = - CreateTestL2WithConfig(t, b.ctx, b.Info, b.nodeConfig, b.takeOwnership) - b.L2 = l2 - return l2 -} +type SecondNodeParams map[string]interface{} -func (b *NodeBuilder) Build2ndNode(t *testing.T, initData *statetransfer.ArbosInitializationInfo, nodeConfig *arbnode.Config, stackConfig *node.Config) *TestClient { +func (b *NodeBuilder) Build2ndNode(t *testing.T, params SecondNodeParams) *TestClient { if b.L1 == nil { t.Fatal("builder did not previously build a L1 Node") } if b.L2 == nil { t.Fatal("builder did not previously build a L2 Node") } - l2 := NewTestClient(b.ctx) - l2.Client, l2.Node = - Create2ndNodeWithConfig(t, b.ctx, b.L2.Node, b.L1.Stack, b.L1.Info, initData, nodeConfig, stackConfig) - return l2 -} - -func (b *NodeBuilder) Build2ndNodeDAS(t *testing.T, initData *statetransfer.ArbosInitializationInfo, dasConfig *das.DataAvailabilityConfig) *TestClient { - if b.L1 == nil { - t.Fatal("builder did not previously build a L1 Node") + if _, ok := params["dasConfig"]; ok { + nodeConf := arbnode.ConfigDefaultL1NonSequencerTest() + if params["dasConfig"] == nil { + nodeConf.DataAvailability.Enable = false + } else { + nodeConf.DataAvailability = *params["dasConfig"].(*das.DataAvailabilityConfig) + } + params["nodeConfig"] = nodeConf + } else if _, ok := params["nodeConfig"]; !ok { + params["nodeConfig"] = b.nodeConfig } - if b.L2 == nil { - t.Fatal("builder did not previously build a L2 Node") + if _, ok := params["stackConfig"]; !ok { + params["stackConfig"] = b.stackConfig } + l2 := NewTestClient(b.ctx) l2.Client, l2.Node = - Create2ndNode(t, b.ctx, b.L2.Node, b.L1.Stack, b.L1.Info, initData, dasConfig) + Create2ndNodeWithConfig(t, b.ctx, b.L2.Node, b.L1.Stack, b.L1.Info, + params["initData"].(*statetransfer.ArbosInitializationInfo), + params["nodeConfig"].(*arbnode.Config), + params["stackConfig"].(*node.Config)) return l2 } -type TestBlockchain struct { - TestClient - // Blockchain fields - ChainDB ethdb.Database - NodeDB ethdb.Database - Blockchain *core.BlockChain +func (b *NodeBuilder) BuildL1Blockchain(t *testing.T) *TestBlockchain { + l1 := NewTestBlockchain(b.ctx) + l1.Info, l1.Client, l1.Backend, l1.Stack = createTestL1BlockChain(t, b.Info) + return l1 } -func (b *NodeBuilder) ConfigForL1Blockchain(s *node.Config, i info) *NodeBuilder { - b.stackConfig = s - b.Info = i - return b +func (b *NodeBuilder) BuildL2Blockchain(t *testing.T) *TestBlockchain { + l2 := NewTestBlockchain(b.ctx) + l2.Info, l2.Stack, l2.ChainDB, l2.NodeDB, l2.Blockchain = + createL2BlockChainWithStackConfig(t, b.Info, b.dataDir, b.chainConfig, b.initMessage, b.stackConfig, b.cachingConfig) + return l2 } -func (b *NodeBuilder) BuilL1Blockchain(t *testing.T) *TestBlockchain { - l1 := &TestBlockchain{} - l1.ctx = b.ctx - l1.Info, l1.Client, l1.Backend, l1.Stack = createTestL1BlockChainWithConfig(t, b.Info, b.stackConfig) - return l1 +func (b *NodeBuilder) BridgeBalance(t *testing.T, account string, amount *big.Int) (*types.Transaction, *types.Receipt) { + return BridgeBalance(t, account, amount, b.L1.Info, b.L2.Info, b.L1.Client, b.L2.Client, b.ctx) } -func (b *NodeBuilder) ConfigForL2Blockchain(s *node.Config, i info) *NodeBuilder { - b.stackConfig = s - b.Info = i - return b +type TestBlockchain struct { + TestClient + // Blockchain fields + chainConfig *params.ChainConfig + ChainDB ethdb.Database + NodeDB ethdb.Database + Blockchain *core.BlockChain } -func (b *NodeBuilder) BuilL2Blockchain(t *testing.T, dataDir string, initMessage *arbostypes.ParsedInitMessage) *TestBlockchain { - l2 := &TestBlockchain{} - l2.Info, l2.Stack, l2.ChainDB, l2.NodeDB, l2.Blockchain = - createL2BlockChainWithStackConfig(t, b.Info, dataDir, b.chainConfig, initMessage, b.stackConfig, b.cachingConfig) - return l2 +func NewTestBlockchain(ctx context.Context) *TestBlockchain { + tc := NewTestClient(ctx) + return &TestBlockchain{TestClient: *tc} +} + +func (tb *TestBlockchain) Deploy(t *testing.T) (*chaininfo.RollupAddresses, *arbostypes.ParsedInitMessage) { + return DeployOnTestL1(t, tb.ctx, tb.Info, tb.Client, tb.chainConfig) } func SendWaitTestTransactions(t *testing.T, ctx context.Context, client client, txs []*types.Transaction) { diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index b64a655c3..c5bb78e0d 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -241,7 +241,9 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall l1Info.GenerateGenesisAccount("sequencer", initialBalance) chainConfig := params.ArbitrumDevTestChainConfig() - l1Info, l1Backend, _, _ := createTestL1BlockChain(t, l1Info) + builder := NewNodeBuilder(ctx).DefaultConfig(false, nil, chainConfig) + builder.Info = l1Info + tbL1 := builder.BuildL1Blockchain(t) conf := arbnode.ConfigDefaultL1Test() conf.BlockValidator.Enable = false conf.BatchPoster.Enable = false @@ -257,61 +259,64 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall configByValidationNode(t, conf, valStack) fatalErrChan := make(chan error, 10) - asserterRollupAddresses, initMessage := DeployOnTestL1(t, ctx, l1Info, l1Backend, chainConfig) + tbL1.chainConfig = chainConfig + asserterRollupAddresses, initMessage := tbL1.Deploy(t) - deployerTxOpts := l1Info.GetDefaultTransactOpts("deployer", ctx) - sequencerTxOpts := l1Info.GetDefaultTransactOpts("sequencer", ctx) - asserterTxOpts := l1Info.GetDefaultTransactOpts("asserter", ctx) - challengerTxOpts := l1Info.GetDefaultTransactOpts("challenger", ctx) + deployerTxOpts := tbL1.Info.GetDefaultTransactOpts("deployer", ctx) + sequencerTxOpts := tbL1.Info.GetDefaultTransactOpts("sequencer", ctx) + asserterTxOpts := tbL1.Info.GetDefaultTransactOpts("asserter", ctx) + challengerTxOpts := tbL1.Info.GetDefaultTransactOpts("challenger", ctx) - asserterBridgeAddr, asserterSeqInbox, asserterSeqInboxAddr := setupSequencerInboxStub(ctx, t, l1Info, l1Backend, chainConfig) - challengerBridgeAddr, challengerSeqInbox, challengerSeqInboxAddr := setupSequencerInboxStub(ctx, t, l1Info, l1Backend, chainConfig) + asserterBridgeAddr, asserterSeqInbox, asserterSeqInboxAddr := setupSequencerInboxStub(ctx, t, tbL1.Info, tbL1.Client, chainConfig) + challengerBridgeAddr, challengerSeqInbox, challengerSeqInboxAddr := setupSequencerInboxStub(ctx, t, tbL1.Info, tbL1.Client, chainConfig) - asserterL2Info, asserterL2Stack, asserterL2ChainDb, asserterL2ArbDb, asserterL2Blockchain := createL2BlockChainWithStackConfig(t, nil, "", chainConfig, initMessage, nil, nil) + builder.initMessage = initMessage + builder.Info = nil + asserterL2tb := builder.BuildL2Blockchain(t) asserterRollupAddresses.Bridge = asserterBridgeAddr asserterRollupAddresses.SequencerInbox = asserterSeqInboxAddr - asserterL2, err := arbnode.CreateNode(ctx, asserterL2Stack, asserterL2ChainDb, asserterL2ArbDb, NewFetcherFromConfig(conf), asserterL2Blockchain, l1Backend, asserterRollupAddresses, nil, nil, nil, fatalErrChan) + asserterL2, err := arbnode.CreateNode(ctx, asserterL2tb.Stack, asserterL2tb.ChainDB, asserterL2tb.NodeDB, NewFetcherFromConfig(conf), asserterL2tb.Blockchain, tbL1.Client, asserterRollupAddresses, nil, nil, nil, fatalErrChan) Require(t, err) err = asserterL2.Start(ctx) Require(t, err) - challengerL2Info, challengerL2Stack, challengerL2ChainDb, challengerL2ArbDb, challengerL2Blockchain := createL2BlockChainWithStackConfig(t, nil, "", chainConfig, initMessage, nil, nil) + challengerL2tb := builder.BuildL2Blockchain(t) challengerRollupAddresses := *asserterRollupAddresses challengerRollupAddresses.Bridge = challengerBridgeAddr challengerRollupAddresses.SequencerInbox = challengerSeqInboxAddr - challengerL2, err := arbnode.CreateNode(ctx, challengerL2Stack, challengerL2ChainDb, challengerL2ArbDb, NewFetcherFromConfig(conf), challengerL2Blockchain, l1Backend, &challengerRollupAddresses, nil, nil, nil, fatalErrChan) + challengerL2, err := arbnode.CreateNode(ctx, challengerL2tb.Stack, challengerL2tb.ChainDB, challengerL2tb.NodeDB, NewFetcherFromConfig(conf), challengerL2tb.Blockchain, tbL1.Client, &challengerRollupAddresses, nil, nil, nil, fatalErrChan) Require(t, err) err = challengerL2.Start(ctx) Require(t, err) - asserterL2Info.GenerateAccount("Destination") - challengerL2Info.SetFullAccountInfo("Destination", asserterL2Info.GetInfoWithPrivKey("Destination")) + asserterL2tb.Info.GenerateAccount("Destination") + challengerL2tb.Info.SetFullAccountInfo("Destination", asserterL2tb.Info.GetInfoWithPrivKey("Destination")) if challengeMsgIdx < 1 || challengeMsgIdx > 3*makeBatch_MsgsPerBatch { Fatal(t, "challengeMsgIdx illegal") } // seqNum := common.Big2 - makeBatch(t, asserterL2, asserterL2Info, l1Backend, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) - makeBatch(t, challengerL2, challengerL2Info, l1Backend, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-1) + makeBatch(t, asserterL2, asserterL2tb.Info, tbL1.Client, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) + makeBatch(t, challengerL2, challengerL2tb.Info, tbL1.Client, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-1) // seqNum.Add(seqNum, common.Big1) - makeBatch(t, asserterL2, asserterL2Info, l1Backend, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) - makeBatch(t, challengerL2, challengerL2Info, l1Backend, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-makeBatch_MsgsPerBatch-1) + makeBatch(t, asserterL2, asserterL2tb.Info, tbL1.Client, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) + makeBatch(t, challengerL2, challengerL2tb.Info, tbL1.Client, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-makeBatch_MsgsPerBatch-1) // seqNum.Add(seqNum, common.Big1) - makeBatch(t, asserterL2, asserterL2Info, l1Backend, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) - makeBatch(t, challengerL2, challengerL2Info, l1Backend, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-makeBatch_MsgsPerBatch*2-1) + makeBatch(t, asserterL2, asserterL2tb.Info, tbL1.Client, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) + makeBatch(t, challengerL2, challengerL2tb.Info, tbL1.Client, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-makeBatch_MsgsPerBatch*2-1) trueSeqInboxAddr := challengerSeqInboxAddr trueDelayedBridge := challengerBridgeAddr - expectedWinner := l1Info.GetAddress("challenger") + expectedWinner := tbL1.Info.GetAddress("challenger") if asserterIsCorrect { trueSeqInboxAddr = asserterSeqInboxAddr trueDelayedBridge = asserterBridgeAddr - expectedWinner = l1Info.GetAddress("asserter") + expectedWinner = tbL1.Info.GetAddress("asserter") } - ospEntry := DeployOneStepProofEntry(t, ctx, &deployerTxOpts, l1Backend) + ospEntry := DeployOneStepProofEntry(t, ctx, &deployerTxOpts, tbL1.Client) locator, err := server_common.NewMachineLocator("") if err != nil { @@ -354,7 +359,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall t, ctx, &deployerTxOpts, - l1Backend, + tbL1.Client, ospEntry, trueSeqInboxAddr, trueDelayedBridge, @@ -362,13 +367,13 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall asserterStartGlobalState, asserterEndGlobalState, numBlocks, - l1Info.GetAddress("asserter"), - l1Info.GetAddress("challenger"), + tbL1.Info.GetAddress("asserter"), + tbL1.Info.GetAddress("challenger"), ) - confirmLatestBlock(ctx, t, l1Info, l1Backend) + confirmLatestBlock(ctx, t, tbL1.Info, tbL1.Client) - asserterValidator, err := staker.NewStatelessBlockValidator(asserterL2.InboxReader, asserterL2.InboxTracker, asserterL2.TxStreamer, asserterL2.Execution.Recorder, asserterL2ArbDb, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) + asserterValidator, err := staker.NewStatelessBlockValidator(asserterL2.InboxReader, asserterL2.InboxTracker, asserterL2.TxStreamer, asserterL2.Execution.Recorder, asserterL2tb.NodeDB, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) if err != nil { Fatal(t, err) } @@ -381,11 +386,11 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall Fatal(t, err) } defer asserterValidator.Stop() - asserterManager, err := staker.NewChallengeManager(ctx, l1Backend, &asserterTxOpts, asserterTxOpts.From, challengeManagerAddr, 1, asserterValidator, 0, 0) + asserterManager, err := staker.NewChallengeManager(ctx, tbL1.Client, &asserterTxOpts, asserterTxOpts.From, challengeManagerAddr, 1, asserterValidator, 0, 0) if err != nil { Fatal(t, err) } - challengerValidator, err := staker.NewStatelessBlockValidator(challengerL2.InboxReader, challengerL2.InboxTracker, challengerL2.TxStreamer, challengerL2.Execution.Recorder, challengerL2ArbDb, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) + challengerValidator, err := staker.NewStatelessBlockValidator(challengerL2.InboxReader, challengerL2.InboxTracker, challengerL2.TxStreamer, challengerL2.Execution.Recorder, challengerL2tb.NodeDB, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) if err != nil { Fatal(t, err) } @@ -398,7 +403,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall Fatal(t, err) } defer challengerValidator.Stop() - challengerManager, err := staker.NewChallengeManager(ctx, l1Backend, &challengerTxOpts, challengerTxOpts.From, challengeManagerAddr, 1, challengerValidator, 0, 0) + challengerManager, err := staker.NewChallengeManager(ctx, tbL1.Client, &challengerTxOpts, challengerTxOpts.From, challengeManagerAddr, 1, challengerValidator, 0, 0) if err != nil { Fatal(t, err) } @@ -410,8 +415,8 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall // This might make gas estimation undersestimate next move. // Invoke a new L1 block, with a new timestamp, before estimating. time.Sleep(time.Second) - SendWaitTestTransactions(t, ctx, l1Backend, []*types.Transaction{ - l1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, tbL1.Client, []*types.Transaction{ + tbL1.Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) if i%2 == 0 { @@ -446,7 +451,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall } } - _, err = EnsureTxSucceeded(ctx, l1Backend, tx) + _, err = EnsureTxSucceeded(ctx, tbL1.Client, tx) if err != nil { if !currentCorrect && strings.Contains(err.Error(), "BAD_SEQINBOX_MESSAGE") { t.Log("challenge complete! Tx failed as expected:", err) @@ -455,7 +460,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall Fatal(t, err) } - confirmLatestBlock(ctx, t, l1Info, l1Backend) + confirmLatestBlock(ctx, t, tbL1.Info, tbL1.Client) winner, err := resultReceiver.Winner(&bind.CallOpts{}) if err != nil { From ade75d9467f48c1068fe75d9b3404cb4a231ac1f Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 29 Sep 2023 17:00:39 -0500 Subject: [PATCH 208/775] fix typo --- system_tests/common_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 56576f9d1..11d8a57cf 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -61,7 +61,6 @@ type info = *BlockchainTestInfo type client = arbutil.L1Interface type TestClient struct { - // Nodebuilder fields ctx context.Context Info info Client *ethclient.Client @@ -115,12 +114,12 @@ type NodeBuilder struct { stackConfig *node.Config cachingConfig *execution.CachingConfig - // NodeBuiilder Node parameters + // L1, L2 Node parameters isSequencer bool takeOwnership bool withL1 bool - // NodeBuiilder Blockchain parameters + // Blockchain parameters dataDir string initMessage *arbostypes.ParsedInitMessage From 8c1b55eebeac4df0ec9957a93cc452cb1b4799a3 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 29 Sep 2023 21:58:25 -0600 Subject: [PATCH 209/775] Disable skipping saving state in archive node by default --- arbnode/execution/blockchain.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arbnode/execution/blockchain.go b/arbnode/execution/blockchain.go index 230902726..00a59f068 100644 --- a/arbnode/execution/blockchain.go +++ b/arbnode/execution/blockchain.go @@ -49,8 +49,8 @@ func CachingConfigAddOptions(prefix string, f *flag.FlagSet) { f.Int(prefix+".snapshot-cache", DefaultCachingConfig.SnapshotCache, "amount of memory in megabytes to cache state snapshots with") f.Int(prefix+".database-cache", DefaultCachingConfig.DatabaseCache, "amount of memory in megabytes to cache database contents with") f.Uint64(prefix+".snapshot-restore-gas-limit", DefaultCachingConfig.SnapshotRestoreGasLimit, "maximum gas rolled back to recover snapshot") - f.Uint32(prefix+".max-number-of-blocks-to-skip-state-saving", DefaultCachingConfig.MaxNumberOfBlocksToSkipStateSaving, "maximum number of blocks to skip state saving to persistent storage (archive node only)") - f.Uint64(prefix+".max-amount-of-gas-to-skip-state-saving", DefaultCachingConfig.MaxAmountOfGasToSkipStateSaving, "maximum amount of gas in blocks to skip saving state to Persistent storage (archive node only)") + f.Uint32(prefix+".max-number-of-blocks-to-skip-state-saving", DefaultCachingConfig.MaxNumberOfBlocksToSkipStateSaving, "maximum number of blocks to skip state saving to persistent storage (archive node only) -- warning: this option seems to cause issues") + f.Uint64(prefix+".max-amount-of-gas-to-skip-state-saving", DefaultCachingConfig.MaxAmountOfGasToSkipStateSaving, "maximum amount of gas in blocks to skip saving state to Persistent storage (archive node only) -- warning: this option seems to cause issues") } var DefaultCachingConfig = CachingConfig{ @@ -63,8 +63,8 @@ var DefaultCachingConfig = CachingConfig{ SnapshotCache: 400, DatabaseCache: 2048, SnapshotRestoreGasLimit: 300_000_000_000, - MaxNumberOfBlocksToSkipStateSaving: 127, - MaxAmountOfGasToSkipStateSaving: 15 * 1000 * 1000, + MaxNumberOfBlocksToSkipStateSaving: 0, + MaxAmountOfGasToSkipStateSaving: 0, } func DefaultCacheConfigFor(stack *node.Node, cachingConfig *CachingConfig) *core.CacheConfig { From 5658dfa5e07b3aea36c2ff03f0722473e69f9d38 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 2 Oct 2023 14:15:18 -0500 Subject: [PATCH 210/775] address PR comments --- system_tests/batch_poster_test.go | 61 +++++------ system_tests/bloom_test.go | 10 +- system_tests/common_test.go | 127 ++++++++++++++--------- system_tests/full_challenge_impl_test.go | 20 ++-- 4 files changed, 120 insertions(+), 98 deletions(-) diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index e063db998..4cb9271c5 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -45,27 +45,25 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { parallelBatchPosters = 4 } - builder := NewNodeBuilder(ctx).DefaultConfig(true, nil, nil) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) builder.nodeConfig.BatchPoster.Enable = false builder.nodeConfig.BatchPoster.RedisUrl = redisUrl - builder.Build(t) + cleanup := builder.Build(t) + defer cleanup() l1A, l2A := builder.L1, builder.L2 - defer requireClose(t, l1A.Stack) - defer l2A.Node.StopAndWait() - params := make(SecondNodeParams) - params["initData"] = &l2A.Info.ArbInitData + params["nodeConfig"] = nil params["dasConfig"] = nil - l2B := builder.Build2ndNode(t, params) - defer l2B.Node.StopAndWait() + l2B, cleanup2nd := builder.Build2ndNode(t, params) + defer cleanup2nd() - l2A.Info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") var txs []*types.Transaction for i := 0; i < 100; i++ { - tx := l2A.Info.PrepareTx("Owner", "User2", l2A.Info.TransferGas, common.Big1, nil) + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) txs = append(txs, tx) err := l2A.Client.SendTransaction(ctx, tx) @@ -79,7 +77,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { firstTxData, err := txs[0].MarshalBinary() Require(t, err) - seqTxOpts := l1A.Info.GetDefaultTransactOpts("Sequencer", ctx) + seqTxOpts := builder.L1Info.GetDefaultTransactOpts("Sequencer", ctx) builder.nodeConfig.BatchPoster.Enable = true builder.nodeConfig.BatchPoster.MaxSize = len(firstTxData) * 2 startL1Block, err := l1A.Client.BlockNumber(ctx) @@ -96,7 +94,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { lastTxHash := txs[len(txs)-1].Hash() for i := 90; i > 0; i-- { SendWaitTestTransactions(t, ctx, l1A.Client, []*types.Transaction{ - l1A.Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) time.Sleep(500 * time.Millisecond) _, err := l2B.Client.TransactionReceipt(ctx, lastTxHash) @@ -134,7 +132,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { } } - l2balance, err := l2B.Client.BalanceAt(ctx, l2A.Info.GetAddress("User2"), nil) + l2balance, err := l2B.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Sign() == 0 { @@ -147,26 +145,24 @@ func TestBatchPosterLargeTx(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - builder := NewNodeBuilder(ctx).DefaultConfig(true, nil, nil) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) builder.nodeConfig.Sequencer.MaxTxDataSize = 110000 - builder.Build(t) - - l1A, l2A := builder.L1, builder.L2 - defer requireClose(t, l1A.Stack) - defer l2A.Node.StopAndWait() + cleanup := builder.Build(t) + defer cleanup() + l2A := builder.L2 params := make(SecondNodeParams) - params["initData"] = &l2A.Info.ArbInitData + params["nodeConfig"] = nil params["dasConfig"] = nil - l2B := builder.Build2ndNode(t, params) - defer l2B.Node.StopAndWait() + l2B, cleanup2nd := builder.Build2ndNode(t, params) + defer cleanup2nd() data := make([]byte, 100000) _, err := rand.Read(data) Require(t, err) - faucetAddr := l2A.Info.GetAddress("Faucet") - gas := l2A.Info.TransferGas + 20000*uint64(len(data)) - tx := l2A.Info.PrepareTxTo("Faucet", &faucetAddr, gas, common.Big0, data) + faucetAddr := builder.L2Info.GetAddress("Faucet") + gas := builder.L2Info.TransferGas + 20000*uint64(len(data)) + tx := builder.L2Info.PrepareTxTo("Faucet", &faucetAddr, gas, common.Big0, data) err = l2A.Client.SendTransaction(ctx, tx) Require(t, err) receiptA, err := EnsureTxSucceeded(ctx, l2A.Client, tx) @@ -183,23 +179,22 @@ func TestBatchPosterKeepsUp(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - builder := NewNodeBuilder(ctx).DefaultConfig(true, nil, nil) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) builder.nodeConfig.BatchPoster.CompressionLevel = brotli.BestCompression builder.nodeConfig.BatchPoster.MaxDelay = time.Hour builder.nodeConfig.RPC.RPCTxFeeCap = 1000. - builder.Build(t) - l1A, l2A := builder.L1, builder.L2 - defer requireClose(t, l1A.Stack) - defer l2A.Node.StopAndWait() - l2A.Info.GasPrice = big.NewInt(100e9) + cleanup := builder.Build(t) + defer cleanup() + l2A := builder.L2 + builder.L2Info.GasPrice = big.NewInt(100e9) go func() { data := make([]byte, 90000) _, err := rand.Read(data) Require(t, err) for { - gas := l2A.Info.TransferGas + 20000*uint64(len(data)) - tx := l2A.Info.PrepareTx("Faucet", "Faucet", gas, common.Big0, data) + gas := builder.L2Info.TransferGas + 20000*uint64(len(data)) + tx := builder.L2Info.PrepareTx("Faucet", "Faucet", gas, common.Big0, data) err = l2A.Client.SendTransaction(ctx, tx) Require(t, err) _, err := EnsureTxSucceeded(ctx, l2A.Client, tx) diff --git a/system_tests/bloom_test.go b/system_tests/bloom_test.go index 6e1c6b0ab..4c1fac707 100644 --- a/system_tests/bloom_test.go +++ b/system_tests/bloom_test.go @@ -24,17 +24,17 @@ func TestBloom(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - builder := NewNodeBuilder(ctx).DefaultConfig(false, nil, nil) + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) builder.nodeConfig.RPC.BloomBitsBlocks = 256 builder.nodeConfig.RPC.BloomConfirms = 1 builder.takeOwnership = false - builder.Build(t) + cleanup := builder.Build(t) - defer builder.L2.Node.StopAndWait() + defer cleanup() - builder.L2.Info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - ownerTxOpts := builder.L2.Info.GetDefaultTransactOpts("Owner", ctx) + ownerTxOpts := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) ownerTxOpts.Context = ctx _, simple := deploySimple(t, ctx, ownerTxOpts, builder.L2.Client) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 11d8a57cf..c80044f9e 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -62,31 +62,31 @@ type client = arbutil.L1Interface type TestClient struct { ctx context.Context - Info info Client *ethclient.Client Backend *eth.Ethereum Stack *node.Node Node *arbnode.Node + cleanup func() // having cleanup() field makes cleanup customizable from default cleanup methods after calling build } func NewTestClient(ctx context.Context) *TestClient { return &TestClient{ctx: ctx} } -func (tc *TestClient) SendSignedTx(t *testing.T, l2Client *ethclient.Client, transaction *types.Transaction) *types.Receipt { - return SendSignedTxViaL1(t, tc.ctx, tc.Info, tc.Client, l2Client, transaction) +func (tc *TestClient) SendSignedTx(t *testing.T, l2Client *ethclient.Client, transaction *types.Transaction, i info) *types.Receipt { + return SendSignedTxViaL1(t, tc.ctx, i, tc.Client, l2Client, transaction) } -func (tc *TestClient) SendUnsignedTx(t *testing.T, l2Client *ethclient.Client, transaction *types.Transaction) *types.Receipt { - return SendUnsignedTxViaL1(t, tc.ctx, tc.Info, tc.Client, l2Client, transaction) +func (tc *TestClient) SendUnsignedTx(t *testing.T, l2Client *ethclient.Client, transaction *types.Transaction, i info) *types.Receipt { + return SendUnsignedTxViaL1(t, tc.ctx, i, tc.Client, l2Client, transaction) } -func (tc *TestClient) TransferBalance(t *testing.T, from string, to string, amount *big.Int) (*types.Transaction, *types.Receipt) { - return TransferBalanceTo(t, from, tc.Info.GetAddress(to), amount, tc.Info, tc.Client, tc.ctx) +func (tc *TestClient) TransferBalance(t *testing.T, from string, to string, amount *big.Int, i info) (*types.Transaction, *types.Receipt) { + return TransferBalanceTo(t, from, i.GetAddress(to), amount, i, tc.Client, tc.ctx) } -func (tc *TestClient) TransferBalanceTo(t *testing.T, from string, to common.Address, amount *big.Int) (*types.Transaction, *types.Receipt) { - return TransferBalanceTo(t, from, to, amount, tc.Info, tc.Client, tc.ctx) +func (tc *TestClient) TransferBalanceTo(t *testing.T, from string, to common.Address, amount *big.Int, i info) (*types.Transaction, *types.Receipt) { + return TransferBalanceTo(t, from, to, amount, i, tc.Client, tc.ctx) } func (tc *TestClient) GetBalance(t *testing.T, account common.Address) *big.Int { @@ -108,11 +108,13 @@ func (tc *TestClient) DeploySimple(t *testing.T, auth bind.TransactOpts) (common type NodeBuilder struct { // NodeBuilder configuration ctx context.Context - Info info chainConfig *params.ChainConfig nodeConfig *arbnode.Config - stackConfig *node.Config cachingConfig *execution.CachingConfig + L1StackConfig *node.Config + L2StackConfig *node.Config + L1Info info + L2Info info // L1, L2 Node parameters isSequencer bool @@ -126,96 +128,122 @@ type NodeBuilder struct { // Created nodes L1 *TestClient L2 *TestClient + + // Created Blockchains + L1B *TestBlockchain + L2B *TestBlockchain } func NewNodeBuilder(ctx context.Context) *NodeBuilder { return &NodeBuilder{ctx: ctx} } -func (b *NodeBuilder) DefaultConfig(withL1 bool, n *arbnode.Config, c *params.ChainConfig) *NodeBuilder { +func (b *NodeBuilder) DefaultConfig(t *testing.T, withL1 bool) *NodeBuilder { // most used values across current tests are set here as default b.withL1 = withL1 if withL1 { b.isSequencer = true b.nodeConfig = arbnode.ConfigDefaultL1Test() - if n != nil { - b.nodeConfig = n - } - b.chainConfig = c } else { b.takeOwnership = true b.nodeConfig = arbnode.ConfigDefaultL2Test() - if n != nil { - b.nodeConfig = n - } - b.chainConfig = c } + b.chainConfig = params.ArbitrumDevTestChainConfig() + b.L1Info = NewL1TestInfo(t) + b.L2Info = NewArbTestInfo(t, b.chainConfig.ChainID) + b.L1StackConfig = stackConfigForTest(t) return b } -func (b *NodeBuilder) Build(t *testing.T) *NodeBuilder { +func (b *NodeBuilder) Build(t *testing.T) func() { if b.withL1 { l1, l2 := NewTestClient(b.ctx), NewTestClient(b.ctx) - l2.Info, l2.Node, l2.Client, l2.Stack, l1.Info, l1.Backend, l1.Client, l1.Stack = - createTestNodeOnL1WithConfigImpl(t, b.ctx, b.isSequencer, b.nodeConfig, b.chainConfig, b.stackConfig, b.Info) + b.L2Info, l2.Node, l2.Client, l2.Stack, b.L1Info, l1.Backend, l1.Client, l1.Stack = + createTestNodeOnL1WithConfigImpl(t, b.ctx, b.isSequencer, b.nodeConfig, b.chainConfig, b.L2StackConfig, b.L2Info) b.L1, b.L2 = l1, l2 + b.L1.cleanup = func() { requireClose(t, b.L1.Stack) } } else { l2 := NewTestClient(b.ctx) - l2.Info, l2.Node, l2.Client = - CreateTestL2WithConfig(t, b.ctx, b.Info, b.nodeConfig, b.takeOwnership) + b.L2Info, l2.Node, l2.Client = + CreateTestL2WithConfig(t, b.ctx, b.L2Info, b.nodeConfig, b.takeOwnership) b.L2 = l2 } - return b + b.L2.cleanup = func() { b.L2.Node.StopAndWait() } + return func() { + b.L2.cleanup() + if b.L1 != nil && b.L1.cleanup != nil { + b.L1.cleanup() + } + } } type SecondNodeParams map[string]interface{} -func (b *NodeBuilder) Build2ndNode(t *testing.T, params SecondNodeParams) *TestClient { - if b.L1 == nil { - t.Fatal("builder did not previously build a L1 Node") - } +func (b *NodeBuilder) Build2ndNode(t *testing.T, params SecondNodeParams) (*TestClient, func()) { if b.L2 == nil { t.Fatal("builder did not previously build a L2 Node") } + if _, ok := params["nodeConfig"]; !ok { + params["nodeConfig"] = b.nodeConfig + } else if params["nodeConfig"] == nil { + params["nodeConfig"] = arbnode.ConfigDefaultL1NonSequencerTest() + } if _, ok := params["dasConfig"]; ok { - nodeConf := arbnode.ConfigDefaultL1NonSequencerTest() if params["dasConfig"] == nil { - nodeConf.DataAvailability.Enable = false + params["nodeConfig"].(*arbnode.Config). + DataAvailability.Enable = false } else { - nodeConf.DataAvailability = *params["dasConfig"].(*das.DataAvailabilityConfig) + params["nodeConfig"].(*arbnode.Config). + DataAvailability = *params["dasConfig"].(*das.DataAvailabilityConfig) } - params["nodeConfig"] = nodeConf - } else if _, ok := params["nodeConfig"]; !ok { - params["nodeConfig"] = b.nodeConfig } if _, ok := params["stackConfig"]; !ok { - params["stackConfig"] = b.stackConfig + params["stackConfig"] = b.L2StackConfig + } + if _, ok := params["initData"]; !ok { + params["initData"] = &b.L2Info.ArbInitData } + var s *node.Node + var i info + if b.withL1 { + if b.L1 == nil { + t.Fatal("builder did not previously build a L1 Node") + } + s, i = b.L1.Stack, b.L1Info + } else { + if b.L1B == nil { + t.Fatal("builder did not previously build L1 Blockchain") + } + s, i = b.L1B.Stack, b.L1B.Info + } l2 := NewTestClient(b.ctx) l2.Client, l2.Node = - Create2ndNodeWithConfig(t, b.ctx, b.L2.Node, b.L1.Stack, b.L1.Info, + Create2ndNodeWithConfig(t, b.ctx, b.L2.Node, s, i, params["initData"].(*statetransfer.ArbosInitializationInfo), params["nodeConfig"].(*arbnode.Config), params["stackConfig"].(*node.Config)) - return l2 + l2.cleanup = func() { l2.Node.StopAndWait() } + return l2, func() { l2.cleanup() } } -func (b *NodeBuilder) BuildL1Blockchain(t *testing.T) *TestBlockchain { - l1 := NewTestBlockchain(b.ctx) - l1.Info, l1.Client, l1.Backend, l1.Stack = createTestL1BlockChain(t, b.Info) - return l1 +func (b *NodeBuilder) BuildL1Blockchain(t *testing.T) *NodeBuilder { + l1B := NewTestBlockchain(b.ctx) + l1B.Info, l1B.Client, l1B.Backend, l1B.Stack = createTestL1BlockChainWithConfig(t, b.L1Info, b.L1StackConfig) + b.L1B = l1B + return b } -func (b *NodeBuilder) BuildL2Blockchain(t *testing.T) *TestBlockchain { - l2 := NewTestBlockchain(b.ctx) - l2.Info, l2.Stack, l2.ChainDB, l2.NodeDB, l2.Blockchain = - createL2BlockChainWithStackConfig(t, b.Info, b.dataDir, b.chainConfig, b.initMessage, b.stackConfig, b.cachingConfig) - return l2 +func (b *NodeBuilder) BuildL2Blockchain(t *testing.T) *NodeBuilder { + l2B := NewTestBlockchain(b.ctx) + l2B.Info, l2B.Stack, l2B.ChainDB, l2B.NodeDB, l2B.Blockchain = + createL2BlockChainWithStackConfig(t, b.L2Info, b.dataDir, b.chainConfig, b.initMessage, b.L2StackConfig, b.cachingConfig) + b.L2B = l2B + return b } func (b *NodeBuilder) BridgeBalance(t *testing.T, account string, amount *big.Int) (*types.Transaction, *types.Receipt) { - return BridgeBalance(t, account, amount, b.L1.Info, b.L2.Info, b.L1.Client, b.L2.Client, b.ctx) + return BridgeBalance(t, account, amount, b.L1Info, b.L2Info, b.L1.Client, b.L2.Client, b.ctx) } type TestBlockchain struct { @@ -225,6 +253,7 @@ type TestBlockchain struct { ChainDB ethdb.Database NodeDB ethdb.Database Blockchain *core.BlockChain + Info info } func NewTestBlockchain(ctx context.Context) *TestBlockchain { diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index c5bb78e0d..3be386f9c 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -234,16 +234,14 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall defer cancel() initialBalance := new(big.Int).Lsh(big.NewInt(1), 200) - l1Info := NewL1TestInfo(t) - l1Info.GenerateGenesisAccount("deployer", initialBalance) - l1Info.GenerateGenesisAccount("asserter", initialBalance) - l1Info.GenerateGenesisAccount("challenger", initialBalance) - l1Info.GenerateGenesisAccount("sequencer", initialBalance) chainConfig := params.ArbitrumDevTestChainConfig() - builder := NewNodeBuilder(ctx).DefaultConfig(false, nil, chainConfig) - builder.Info = l1Info - tbL1 := builder.BuildL1Blockchain(t) + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.L1Info.GenerateGenesisAccount("deployer", initialBalance) + builder.L1Info.GenerateGenesisAccount("asserter", initialBalance) + builder.L1Info.GenerateGenesisAccount("challenger", initialBalance) + builder.L1Info.GenerateGenesisAccount("sequencer", initialBalance) + tbL1 := builder.BuildL1Blockchain(t).L1B conf := arbnode.ConfigDefaultL1Test() conf.BlockValidator.Enable = false conf.BatchPoster.Enable = false @@ -271,8 +269,8 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall challengerBridgeAddr, challengerSeqInbox, challengerSeqInboxAddr := setupSequencerInboxStub(ctx, t, tbL1.Info, tbL1.Client, chainConfig) builder.initMessage = initMessage - builder.Info = nil - asserterL2tb := builder.BuildL2Blockchain(t) + builder.L2Info = nil + asserterL2tb := builder.BuildL2Blockchain(t).L2B asserterRollupAddresses.Bridge = asserterBridgeAddr asserterRollupAddresses.SequencerInbox = asserterSeqInboxAddr asserterL2, err := arbnode.CreateNode(ctx, asserterL2tb.Stack, asserterL2tb.ChainDB, asserterL2tb.NodeDB, NewFetcherFromConfig(conf), asserterL2tb.Blockchain, tbL1.Client, asserterRollupAddresses, nil, nil, nil, fatalErrChan) @@ -280,7 +278,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall err = asserterL2.Start(ctx) Require(t, err) - challengerL2tb := builder.BuildL2Blockchain(t) + challengerL2tb := builder.BuildL2Blockchain(t).L2B challengerRollupAddresses := *asserterRollupAddresses challengerRollupAddresses.Bridge = challengerBridgeAddr challengerRollupAddresses.SequencerInbox = challengerSeqInboxAddr From 0073aa24c662c41efac6cc908e4f888e6964a4f1 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Mon, 2 Oct 2023 18:11:23 -0700 Subject: [PATCH 211/775] Updates for v1.12.1 merge Modifications for upstream geth changes: - stack.Attach returns one parameter. - TrieCache removed - txpool.AddLocals replaced by Add, needs wrapped txs --- arbnode/execution/blockchain.go | 2 - cmd/nitro/init.go | 5 +- go.mod | 43 +++++++------ go.sum | 88 +++++++++++++++++---------- system_tests/arbtrace_test.go | 2 +- system_tests/common_test.go | 13 ++-- system_tests/conditionaltx_test.go | 9 +-- system_tests/debugapi_test.go | 2 +- system_tests/delayedinboxlong_test.go | 9 ++- system_tests/retryable_test.go | 2 + system_tests/twonodeslong_test.go | 9 ++- 11 files changed, 109 insertions(+), 75 deletions(-) diff --git a/arbnode/execution/blockchain.go b/arbnode/execution/blockchain.go index 230902726..57c0e3053 100644 --- a/arbnode/execution/blockchain.go +++ b/arbnode/execution/blockchain.go @@ -75,8 +75,6 @@ func DefaultCacheConfigFor(stack *node.Node, cachingConfig *CachingConfig) *core return &core.CacheConfig{ TrieCleanLimit: cachingConfig.TrieCleanCache, - TrieCleanJournal: stack.ResolvePath(baseConf.TrieCleanCacheJournal), - TrieCleanRejournal: baseConf.TrieCleanCacheRejournal, TrieCleanNoPrefetch: baseConf.NoPrefetch, TrieDirtyLimit: cachingConfig.TrieDirtyCache, TrieDirtyDisabled: cachingConfig.Archive, diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index bdba7c121..96ef95df5 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -420,17 +420,16 @@ func findImportantRoots(ctx context.Context, chainDb ethdb.Database, stack *node } func pruneChainDb(ctx context.Context, chainDb ethdb.Database, stack *node.Node, nodeConfig *NodeConfig, cacheConfig *core.CacheConfig, l1Client arbutil.L1Interface, rollupAddrs chaininfo.RollupAddresses) error { - trieCachePath := cacheConfig.TrieCleanJournal config := &nodeConfig.Init if config.Prune == "" { - return pruner.RecoverPruning(stack.InstanceDir(), chainDb, trieCachePath) + return pruner.RecoverPruning(stack.InstanceDir(), chainDb) } root, err := findImportantRoots(ctx, chainDb, stack, nodeConfig, cacheConfig, l1Client, rollupAddrs) if err != nil { return fmt.Errorf("failed to find root to retain for pruning: %w", err) } - pruner, err := pruner.NewPruner(chainDb, pruner.Config{Datadir: stack.InstanceDir(), Cachedir: trieCachePath, BloomSize: config.PruneBloomSize}) + pruner, err := pruner.NewPruner(chainDb, pruner.Config{Datadir: stack.InstanceDir(), BloomSize: config.PruneBloomSize}) if err != nil { return err } diff --git a/go.mod b/go.mod index cc31c4a23..ba5fe5063 100644 --- a/go.mod +++ b/go.mod @@ -18,8 +18,10 @@ require ( github.com/cavaliergopher/grab/v3 v3.0.1 github.com/codeclysm/extract/v3 v3.0.2 github.com/dgraph-io/badger/v3 v3.2103.2 + github.com/enescakir/emoji v1.0.0 github.com/ethereum/go-ethereum v1.10.26 github.com/fatih/structtag v1.2.0 + github.com/gdamore/tcell/v2 v2.6.0 github.com/google/go-cmp v0.5.9 github.com/hashicorp/golang-lru/v2 v2.0.1 github.com/ipfs/go-cid v0.3.2 @@ -30,10 +32,11 @@ require ( github.com/libp2p/go-libp2p v0.26.4 github.com/multiformats/go-multiaddr v0.8.0 github.com/multiformats/go-multihash v0.2.1 + github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 github.com/spf13/pflag v1.0.5 github.com/wealdtech/go-merkletree v1.0.0 - golang.org/x/term v0.6.0 - golang.org/x/tools v0.7.0 + golang.org/x/term v0.8.0 + golang.org/x/tools v0.9.1 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) @@ -61,6 +64,7 @@ require ( github.com/aws/smithy-go v1.11.2 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect @@ -72,10 +76,13 @@ require ( github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 // indirect github.com/cockroachdb/redact v1.1.3 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.10.0 // indirect github.com/containerd/cgroups v1.0.4 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect + github.com/crate-crypto/go-kzg-4844 v0.3.0 // indirect github.com/cskr/pubsub v1.0.2 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect @@ -84,18 +91,17 @@ require ( github.com/dgraph-io/ristretto v0.1.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7 // indirect + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/enescakir/emoji v1.0.0 // indirect + github.com/ethereum/c-kzg-4844 v0.3.0 // indirect github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gammazero/deque v0.2.1 // indirect github.com/gdamore/encoding v1.0.0 // indirect - github.com/gdamore/tcell/v2 v2.6.0 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -110,7 +116,7 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/flatbuffers v1.12.1 // indirect github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20221203041831-ce31453925ec // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect @@ -118,6 +124,7 @@ require ( github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect github.com/ipfs/go-block-format v0.1.1 // indirect @@ -203,6 +210,7 @@ require ( github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect @@ -230,14 +238,14 @@ require ( github.com/quic-go/webtransport-go v0.5.2 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/rhnvrm/simples3 v0.6.1 // indirect - github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 // indirect github.com/rivo/uniseg v0.4.3 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/samber/lo v1.36.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/stretchr/testify v1.8.2 // indirect - github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect + github.com/supranational/blst v0.3.11-0.20230406105308-e9dfc5ee724b // indirect + github.com/urfave/cli/v2 v2.24.1 // indirect github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa // indirect github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect @@ -263,8 +271,8 @@ require ( go.uber.org/multierr v1.9.0 // indirect go.uber.org/zap v1.24.0 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect - golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect - golang.org/x/mod v0.9.0 // indirect + golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect + golang.org/x/mod v0.10.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/grpc v1.46.0 // indirect @@ -272,6 +280,7 @@ require ( gopkg.in/square/go-jose.v2 v2.5.1 // indirect lukechampine.com/blake3 v1.1.7 // indirect nhooyr.io/websocket v1.8.7 // indirect + rsc.io/tmplfunc v0.0.3 // indirect ) require ( @@ -299,7 +308,7 @@ require ( github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect - github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c + github.com/holiman/uint256 v1.2.3 github.com/huin/goupnp v1.0.3 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -315,11 +324,11 @@ require ( github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect - golang.org/x/crypto v0.6.0 - golang.org/x/net v0.8.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.7.0 - golang.org/x/text v0.8.0 // indirect - golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect + golang.org/x/crypto v0.9.0 + golang.org/x/net v0.10.0 // indirect + golang.org/x/sync v0.3.0 // indirect + golang.org/x/sys v0.9.0 + golang.org/x/text v0.9.0 // indirect + golang.org/x/time v0.3.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect ) diff --git a/go.sum b/go.sum index 4362d4b01..69e13ca60 100644 --- a/go.sum +++ b/go.sum @@ -45,7 +45,7 @@ github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOv github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= @@ -157,6 +157,8 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= +github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= @@ -201,8 +203,11 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -230,6 +235,10 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE github.com/codeclysm/extract/v3 v3.0.2 h1:sB4LcE3Php7LkhZwN0n2p8GCwZe92PEQutdbGURf5xc= github.com/codeclysm/extract/v3 v3.0.2/go.mod h1:NKsw+hqua9H+Rlwy/w/3Qgt9jDonYEgB6wJu+25eOKw= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.10.0 h1:zRh22SR7o4K35SoNqouS9J/TKHTyU2QWaj5ldehyXtA= +github.com/consensys/gnark-crypto v0.10.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= @@ -250,6 +259,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= +github.com/crate-crypto/go-kzg-4844 v0.3.0 h1:UBlWE0CgyFqqzTI+IFyCzA7A3Zw4iip6uzRv5NIXG0A= +github.com/crate-crypto/go-kzg-4844 v0.3.0/go.mod h1:SBP7ikXEgDnUPONgm33HtuDZEDtWa3L4QtN1ocJSEQ4= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= @@ -291,8 +302,8 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7 h1:kgvzE5wLsLa7XKfV85VZl40QXaMCaeFtHpPwJ8fhotY= -github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -322,6 +333,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethereum/c-kzg-4844 v0.3.0 h1:3Y3hD6l5i0dEYsBL50C+Om644kve3pNqoAcvE26o9zI= +github.com/ethereum/c-kzg-4844 v0.3.0/go.mod h1:WI2Nd82DMZAAZI1wV2neKGost9EKjvbpQR9OqE5Qqa8= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= @@ -517,9 +530,10 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20221203041831-ce31453925ec h1:fR20TYVVwhK4O7r7y+McjRYyaTH6/vjwJOajE+XhlzM= -github.com/google/pprof v0.0.0-20221203041831-ce31453925ec/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -608,10 +622,12 @@ github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoI github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= -github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= +github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= +github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= @@ -620,6 +636,7 @@ github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixH github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= @@ -932,6 +949,7 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ= @@ -1181,7 +1199,6 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -1236,6 +1253,9 @@ github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8oh github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1563,6 +1583,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/supranational/blst v0.3.11-0.20230406105308-e9dfc5ee724b h1:u49mjRnygnB34h8OKbnNJFVUtWSKIKb1KukdV8bILUM= +github.com/supranational/blst v0.3.11-0.20230406105308-e9dfc5ee724b/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= @@ -1588,8 +1610,8 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= +github.com/urfave/cli/v2 v2.24.1 h1:/QYYr7g0EhwXEML8jO+8OYt5trPnLHS0p3mrgExJ5NU= +github.com/urfave/cli/v2 v2.24.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -1754,8 +1776,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1766,8 +1788,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= -golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= +golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1792,8 +1814,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1854,8 +1876,8 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1877,8 +1899,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1968,22 +1990,21 @@ golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1993,16 +2014,17 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2064,8 +2086,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2256,6 +2278,8 @@ pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= diff --git a/system_tests/arbtrace_test.go b/system_tests/arbtrace_test.go index 78907aa62..1db058fcd 100644 --- a/system_tests/arbtrace_test.go +++ b/system_tests/arbtrace_test.go @@ -151,7 +151,7 @@ func TestArbTraceForwarding(t *testing.T) { defer requireClose(t, l1stack) defer requireClose(t, l2stack) - l2rpc, _ := l2stack.Attach() + l2rpc := l2stack.Attach() txArgs := callTxArgs{} traceTypes := []string{"trace"} blockNum := rpc.BlockNumberOrHash{} diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 7bc1c1175..c4ee904fd 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -404,7 +404,7 @@ func createTestL1BlockChainWithConfig(t *testing.T, l1info info, stackConfig *no nodeConf := ethconfig.Defaults nodeConf.NetworkId = chainConfig.ChainID.Uint64() - l1Genesis := core.DeveloperGenesisBlock(0, 15_000_000, l1info.GetAddress("Faucet")) + l1Genesis := core.DeveloperGenesisBlock(15_000_000, l1info.GetAddress("Faucet")) infoGenesis := l1info.GetGenesisAlloc() for acct, info := range infoGenesis { l1Genesis.Alloc[acct] = info @@ -435,8 +435,7 @@ func createTestL1BlockChainWithConfig(t *testing.T, l1info info, stackConfig *no Require(t, stack.Start()) Require(t, l1backend.StartMining()) - rpcClient, err := stack.Attach() - Require(t, err) + rpcClient := stack.Attach() l1Client := ethclient.NewClient(rpcClient) @@ -547,8 +546,7 @@ func createL2BlockChainWithStackConfig( } func ClientForStack(t *testing.T, backend *node.Node) *ethclient.Client { - rpcClient, err := backend.Attach() - Require(t, err) + rpcClient := backend.Attach() return ethclient.NewClient(rpcClient) } @@ -736,10 +734,7 @@ func Create2ndNodeWithConfig( stackConfig *node.Config, ) (*ethclient.Client, *arbnode.Node) { feedErrChan := make(chan error, 10) - l1rpcClient, err := l1stack.Attach() - if err != nil { - Fatal(t, err) - } + l1rpcClient := l1stack.Attach() l1client := ethclient.NewClient(l1rpcClient) if stackConfig == nil { diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index 14aa00031..760ec2735 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -228,8 +228,7 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { currentRootHash2 := getStorageRootHash(t, node, contractAddress2) currentSlotValueMap2 := getStorageSlotValue(t, node, contractAddress2) - rpcClient, err := node.Stack.Attach() - Require(t, err) + rpcClient := node.Stack.Attach() l2info.GenerateAccount("User2") @@ -310,8 +309,7 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { defer cancel() l2info, node, client := CreateTestL2(t, ctx) defer node.StopAndWait() - rpcClient, err := node.Stack.Attach() - Require(t, err) + rpcClient := node.Stack.Attach() auth := l2info.GetDefaultTransactOpts("Owner", ctx) contractAddress, simple := deploySimple(t, ctx, auth, client) @@ -412,8 +410,7 @@ func TestSendRawTransactionConditionalPreCheck(t *testing.T) { l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, nil) defer requireClose(t, l1stack) defer node.StopAndWait() - rpcClient, err := node.Stack.Attach() - Require(t, err) + rpcClient := node.Stack.Attach() l2info.GenerateAccount("User2") diff --git a/system_tests/debugapi_test.go b/system_tests/debugapi_test.go index 03e3dfd40..f24314eab 100644 --- a/system_tests/debugapi_test.go +++ b/system_tests/debugapi_test.go @@ -18,7 +18,7 @@ func TestDebugAPI(t *testing.T) { defer requireClose(t, l1stack) defer requireClose(t, l2stack) - l2rpc, _ := l2stack.Attach() + l2rpc := l2stack.Attach() var dump state.Dump err := l2rpc.CallContext(ctx, &dump, "debug_dumpBlock", rpc.LatestBlockNumber) diff --git a/system_tests/delayedinboxlong_test.go b/system_tests/delayedinboxlong_test.go index b1c8ea361..994fbdd68 100644 --- a/system_tests/delayedinboxlong_test.go +++ b/system_tests/delayedinboxlong_test.go @@ -14,6 +14,7 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" ) @@ -51,8 +52,12 @@ func TestDelayInboxLong(t *testing.T) { } l1Txs = append(l1Txs, l1tx) } - // adding multiple messages in the same AddLocal to get them in the same L1 block - errs := l1backend.TxPool().AddLocals(l1Txs) + wrappedL1Txs := make([]*txpool.Transaction, 0, messagesPerAddLocal) + for _, tx := range l1Txs { + wrappedL1Txs = append(wrappedL1Txs, &txpool.Transaction{Tx: tx}) + } + // adding multiple messages in the same Add with local=true to get them in the same L1 block + errs := l1backend.TxPool().Add(wrappedL1Txs, true, false) for _, err := range errs { Require(t, err) } diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index b1dd32d1d..63876f1f4 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos" @@ -29,6 +30,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/colors" + "github.com/offchainlabs/nitro/util/testhelpers" ) func retryableSetup(t *testing.T) ( diff --git a/system_tests/twonodeslong_test.go b/system_tests/twonodeslong_test.go index 0cac9d644..50af61360 100644 --- a/system_tests/twonodeslong_test.go +++ b/system_tests/twonodeslong_test.go @@ -17,6 +17,7 @@ import ( "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbutil" + "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" ) @@ -94,8 +95,12 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { } l1Txs = append(l1Txs, l1tx) } - // adding multiple messages in the same AddLocal to get them in the same L1 block - errs := l1backend.TxPool().AddLocals(l1Txs) + wrappedL1Txs := make([]*txpool.Transaction, 0, l1TxsThisTime) + for _, tx := range l1Txs { + wrappedL1Txs = append(wrappedL1Txs, &txpool.Transaction{Tx: tx}) + } + // adding multiple messages in the same Add with local=true to get them in the same L1 block + errs := l1backend.TxPool().Add(wrappedL1Txs, true, false) for _, err := range errs { if err != nil { Fatal(t, err) From c7ba88c842d6aaf1f40ce00de2dda66d3c124c21 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 3 Oct 2023 15:18:14 -0500 Subject: [PATCH 212/775] handle defaults --- system_tests/common_test.go | 47 +++++++++--------------- system_tests/das_test.go | 4 +- system_tests/forwarder_test.go | 8 ++-- system_tests/full_challenge_impl_test.go | 2 + system_tests/ipc_test.go | 2 +- 5 files changed, 27 insertions(+), 36 deletions(-) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index c80044f9e..cd922336c 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -8,7 +8,6 @@ import ( "context" "encoding/hex" "encoding/json" - "fmt" "math/big" "net" "os" @@ -151,7 +150,9 @@ func (b *NodeBuilder) DefaultConfig(t *testing.T, withL1 bool) *NodeBuilder { b.chainConfig = params.ArbitrumDevTestChainConfig() b.L1Info = NewL1TestInfo(t) b.L2Info = NewArbTestInfo(t, b.chainConfig.ChainID) - b.L1StackConfig = stackConfigForTest(t) + b.dataDir = t.TempDir() + b.L1StackConfig = createStackConfigForTest(b.dataDir) + b.L2StackConfig = createStackConfigForTest(b.dataDir) return b } @@ -199,6 +200,8 @@ func (b *NodeBuilder) Build2ndNode(t *testing.T, params SecondNodeParams) (*Test } if _, ok := params["stackConfig"]; !ok { params["stackConfig"] = b.L2StackConfig + // should use different dataDir from the previously used ones + params["stackConfig"].(*node.Config).DataDir = t.TempDir() } if _, ok := params["initData"]; !ok { params["initData"] = &b.L2Info.ArbInitData @@ -495,33 +498,19 @@ func createTestL1BlockChain(t *testing.T, l1info info) (info, *ethclient.Client, return createTestL1BlockChainWithConfig(t, l1info, nil) } -func stackConfigForTest(t *testing.T) *node.Config { - stackConfig := node.DefaultConfig - stackConfig.HTTPPort = 0 - stackConfig.WSPort = 0 - stackConfig.UseLightweightKDF = true - stackConfig.P2P.ListenAddr = "" - stackConfig.P2P.NoDial = true - stackConfig.P2P.NoDiscovery = true - stackConfig.P2P.NAT = nil - stackConfig.DataDir = t.TempDir() - return &stackConfig -} - -func createDefaultStackForTest(dataDir string) (*node.Node, error) { +func createStackConfigForTest(dataDir string) *node.Config { stackConf := node.DefaultConfig - var err error stackConf.DataDir = dataDir + stackConf.UseLightweightKDF = true + stackConf.WSPort = 0 + stackConf.HTTPPort = 0 stackConf.HTTPHost = "" stackConf.HTTPModules = append(stackConf.HTTPModules, "eth") stackConf.P2P.NoDiscovery = true + stackConf.P2P.NoDial = true stackConf.P2P.ListenAddr = "" - - stack, err := node.New(&stackConf) - if err != nil { - return nil, fmt.Errorf("error creating protocol stack: %w", err) - } - return stack, nil + stackConf.P2P.NAT = nil + return &stackConf } func createTestValidationNode(t *testing.T, ctx context.Context, config *valnode.Config) (*valnode.ValidationNode, *node.Node) { @@ -597,7 +586,7 @@ func createTestL1BlockChainWithConfig(t *testing.T, l1info info, stackConfig *no l1info = NewL1TestInfo(t) } if stackConfig == nil { - stackConfig = stackConfigForTest(t) + stackConfig = createStackConfigForTest(t.TempDir()) } l1info.GenerateAccount("Faucet") @@ -718,12 +707,10 @@ func createL2BlockChainWithStackConfig( var stack *node.Node var err error if stackConfig == nil { - stack, err = createDefaultStackForTest(dataDir) - Require(t, err) - } else { - stack, err = node.New(stackConfig) - Require(t, err) + stackConfig = createStackConfigForTest(dataDir) } + stack, err = node.New(stackConfig) + Require(t, err) chainDb, err := stack.OpenDatabase("chaindb", 0, 0, "", false) Require(t, err) @@ -948,7 +935,7 @@ func Create2ndNodeWithConfig( l1client := ethclient.NewClient(l1rpcClient) if stackConfig == nil { - stackConfig = stackConfigForTest(t) + stackConfig = createStackConfigForTest(t.TempDir()) } l2stack, err := node.New(stackConfig) Require(t, err) diff --git a/system_tests/das_test.go b/system_tests/das_test.go index 8889d2d53..f4c880632 100644 --- a/system_tests/das_test.go +++ b/system_tests/das_test.go @@ -19,6 +19,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbnode" @@ -169,7 +170,8 @@ func TestDASRekey(t *testing.T) { // Restart the node on the new keyset against the new DAS server running on the same disk as the first with new keys - l2stackA, err := createDefaultStackForTest(nodeDir) + stackConfig := createStackConfigForTest(nodeDir) + l2stackA, err := node.New(stackConfig) Require(t, err) l2chainDb, err := l2stackA.OpenDatabase("chaindb", 0, 0, "", false) diff --git a/system_tests/forwarder_test.go b/system_tests/forwarder_test.go index 0a954719d..8108ad2d1 100644 --- a/system_tests/forwarder_test.go +++ b/system_tests/forwarder_test.go @@ -35,7 +35,7 @@ func TestStaticForwarder(t *testing.T) { ipcPath := tmpPath(t, "test.ipc") ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath - stackConfig := stackConfigForTest(t) + stackConfig := createStackConfigForTest(t.TempDir()) ipcConfig.Apply(stackConfig) nodeConfigA := arbnode.ConfigDefaultL1Test() nodeConfigA.BatchPoster.Enable = false @@ -97,7 +97,7 @@ func fallbackSequencer( ctx context.Context, t *testing.T, opts *fallbackSequencerOpts, ) (l2info info, currentNode *arbnode.Node, l2client *ethclient.Client, l1info info, l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node) { - stackConfig := stackConfigForTest(t) + stackConfig := createStackConfigForTest(t.TempDir()) ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = opts.ipcPath ipcConfig.Apply(stackConfig) @@ -118,7 +118,7 @@ func createForwardingNode( redisUrl string, fallbackPath string, ) (*ethclient.Client, *arbnode.Node) { - stackConfig := stackConfigForTest(t) + stackConfig := createStackConfigForTest(t.TempDir()) if ipcPath != "" { ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath @@ -144,7 +144,7 @@ func createSequencer( ipcPath string, redisUrl string, ) (*ethclient.Client, *arbnode.Node) { - stackConfig := stackConfigForTest(t) + stackConfig := createStackConfigForTest(t.TempDir()) ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath ipcConfig.Apply(stackConfig) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index 3be386f9c..ebe8cfc98 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -270,6 +270,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall builder.initMessage = initMessage builder.L2Info = nil + builder.L2StackConfig.DataDir = t.TempDir() asserterL2tb := builder.BuildL2Blockchain(t).L2B asserterRollupAddresses.Bridge = asserterBridgeAddr asserterRollupAddresses.SequencerInbox = asserterSeqInboxAddr @@ -278,6 +279,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall err = asserterL2.Start(ctx) Require(t, err) + builder.L2StackConfig.DataDir = t.TempDir() challengerL2tb := builder.BuildL2Blockchain(t).L2B challengerRollupAddresses := *asserterRollupAddresses challengerRollupAddresses.Bridge = challengerBridgeAddr diff --git a/system_tests/ipc_test.go b/system_tests/ipc_test.go index 01ecf859d..095f8e28a 100644 --- a/system_tests/ipc_test.go +++ b/system_tests/ipc_test.go @@ -18,7 +18,7 @@ func TestIpcRpc(t *testing.T) { ipcConfig := genericconf.IPCConfigDefault ipcConfig.Path = ipcPath - stackConf := stackConfigForTest(t) + stackConf := createStackConfigForTest(t.TempDir()) ipcConfig.Apply(stackConf) ctx, cancel := context.WithCancel(context.Background()) From c6b5153886287c7a1b6dbd2d2fb80c25464fad89 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Tue, 3 Oct 2023 18:59:23 -0700 Subject: [PATCH 213/775] Use SimulatedBeacon for test L1s v1.12.1 geth changes the default ChainConfig returned with DeveloperGenesisBlock from AllCliqueProtocolChanges to AllDevChainProtocolChanges. Since the dev chain config is not set to clique mode and is set as post-TTD with TTD=0, there needs to be a non-ethhash based consensus engine running in order for blocks to be produced. See the upstream geth change here: https://github.com/ethereum/go-ethereum/pull/27327 This commit copies the initailization code for how geth is started up in dev mode with the simulated beacon node to our test L1 setup code. It also enables FullSync mode on the L1, since otherwise SimluatedBeacon.sealBlock would fail when calling the ConsensusAPI.ForkChoiceUpdatedV2 as it would still be syncing if it was in SnapSync mode. UseMergeFinality was also disabled on the TestDelayedSequencerConfig since the SimulatedBeacon seems to have different finalization behavior. --- arbnode/delayed_sequencer.go | 2 +- go-ethereum | 2 +- system_tests/common_test.go | 9 +++++++++ system_tests/retryable_test.go | 2 -- system_tests/wrap_transaction_test.go | 2 +- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/arbnode/delayed_sequencer.go b/arbnode/delayed_sequencer.go index aa6d43785..39cdebf2a 100644 --- a/arbnode/delayed_sequencer.go +++ b/arbnode/delayed_sequencer.go @@ -60,7 +60,7 @@ var TestDelayedSequencerConfig = DelayedSequencerConfig{ Enable: true, FinalizeDistance: 20, RequireFullFinality: false, - UseMergeFinality: true, + UseMergeFinality: false, } func NewDelayedSequencer(l1Reader *headerreader.HeaderReader, reader *InboxReader, exec *execution.ExecutionEngine, coordinator *SeqCoordinator, config DelayedSequencerConfigFetcher) (*DelayedSequencer, error) { diff --git a/go-ethereum b/go-ethereum index 89f53b035..90dbc8edb 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 89f53b035d7a8b9b1ff8599958bf0c55efcdf718 +Subproject commit 90dbc8edbe96aeb0c5c372cc7289373ee66d3351 diff --git a/system_tests/common_test.go b/system_tests/common_test.go index c4ee904fd..6cc032c9d 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -37,6 +37,8 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/eth/catalyst" + "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/ethclient" @@ -412,9 +414,16 @@ func createTestL1BlockChainWithConfig(t *testing.T, l1info info, stackConfig *no l1Genesis.BaseFee = big.NewInt(50 * params.GWei) nodeConf.Genesis = l1Genesis nodeConf.Miner.Etherbase = l1info.GetAddress("Faucet") + nodeConf.SyncMode = downloader.FullSync l1backend, err := eth.New(stack, &nodeConf) Require(t, err) + + simBeacon, err := catalyst.NewSimulatedBeacon(0, l1backend) + Require(t, err) + catalyst.RegisterSimulatedBeaconAPIs(stack, simBeacon) + stack.RegisterLifecycle(simBeacon) + tempKeyStore := keystore.NewPlaintextKeyStore(t.TempDir()) faucetAccount, err := tempKeyStore.ImportECDSA(l1info.Accounts["Faucet"].PrivateKey, "passphrase") Require(t, err) diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 63876f1f4..b1dd32d1d 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -15,7 +15,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos" @@ -30,7 +29,6 @@ import ( "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/colors" - "github.com/offchainlabs/nitro/util/testhelpers" ) func retryableSetup(t *testing.T) ( diff --git a/system_tests/wrap_transaction_test.go b/system_tests/wrap_transaction_test.go index 1eae2396b..e4ce6a4bb 100644 --- a/system_tests/wrap_transaction_test.go +++ b/system_tests/wrap_transaction_test.go @@ -79,7 +79,7 @@ func EnsureTxSucceeded(ctx context.Context, client arbutil.L1Interface, tx *type func EnsureTxSucceededWithTimeout(ctx context.Context, client arbutil.L1Interface, tx *types.Transaction, timeout time.Duration) (*types.Receipt, error) { txRes, err := WaitForTx(ctx, client, tx.Hash(), timeout) if err != nil { - return nil, fmt.Errorf("waitFoxTx got: %w", err) + return nil, fmt.Errorf("waitFoxTx (tx=%s) got: %w", tx.Hash().Hex(), err) } return txRes, arbutil.DetailTxError(ctx, client, tx, txRes) } From e09ddd66f98ded8a6bde960ecb970697d6539848 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 4 Oct 2023 11:00:05 -0600 Subject: [PATCH 214/775] update geth: for PR review --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 59ec2cbc8..b4221631e 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 59ec2cbc8fbd7081bd7b35af1b1a7c8b5798f4f6 +Subproject commit b4221631e1e5eac86f01582bd74234e3c0f7f5c7 From 098ca99b1306f231a73d7a377d9d3c1a04bb4414 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 4 Oct 2023 14:00:27 -0500 Subject: [PATCH 215/775] address PR comments --- system_tests/batch_poster_test.go | 10 +- system_tests/common_test.go | 121 ++++++++++------------- system_tests/full_challenge_impl_test.go | 52 +++++----- 3 files changed, 83 insertions(+), 100 deletions(-) diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 4cb9271c5..ae7cb660f 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -52,10 +52,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { defer cleanup() l1A, l2A := builder.L1, builder.L2 - params := make(SecondNodeParams) - params["nodeConfig"] = nil - params["dasConfig"] = nil - l2B, cleanup2nd := builder.Build2ndNode(t, params) + l2B, cleanup2nd := builder.Build2ndNode(t, &SecondNodeParams{}) defer cleanup2nd() builder.L2Info.GenerateAccount("User2") @@ -151,10 +148,7 @@ func TestBatchPosterLargeTx(t *testing.T) { defer cleanup() l2A := builder.L2 - params := make(SecondNodeParams) - params["nodeConfig"] = nil - params["dasConfig"] = nil - l2B, cleanup2nd := builder.Build2ndNode(t, params) + l2B, cleanup2nd := builder.Build2ndNode(t, &SecondNodeParams{}) defer cleanup2nd() data := make([]byte, 100000) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index cd922336c..5349c85d7 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -59,33 +59,48 @@ import ( type info = *BlockchainTestInfo type client = arbutil.L1Interface +type SecondNodeParams struct { + nodeConfig *arbnode.Config + stackConfig *node.Config + dasConfig *das.DataAvailabilityConfig + initData *statetransfer.ArbosInitializationInfo + useBuilderNodeConfig bool +} + type TestClient struct { ctx context.Context Client *ethclient.Client Backend *eth.Ethereum Stack *node.Node Node *arbnode.Node - cleanup func() // having cleanup() field makes cleanup customizable from default cleanup methods after calling build + + // Blockchain specific fields + ChainDB ethdb.Database + NodeDB ethdb.Database + Blockchain *core.BlockChain + + // having cleanup() field makes cleanup customizable from default cleanup methods after calling build + cleanup func() } func NewTestClient(ctx context.Context) *TestClient { return &TestClient{ctx: ctx} } -func (tc *TestClient) SendSignedTx(t *testing.T, l2Client *ethclient.Client, transaction *types.Transaction, i info) *types.Receipt { - return SendSignedTxViaL1(t, tc.ctx, i, tc.Client, l2Client, transaction) +func (tc *TestClient) SendSignedTx(t *testing.T, l2Client *ethclient.Client, transaction *types.Transaction, lInfo info) *types.Receipt { + return SendSignedTxViaL1(t, tc.ctx, lInfo, tc.Client, l2Client, transaction) } -func (tc *TestClient) SendUnsignedTx(t *testing.T, l2Client *ethclient.Client, transaction *types.Transaction, i info) *types.Receipt { - return SendUnsignedTxViaL1(t, tc.ctx, i, tc.Client, l2Client, transaction) +func (tc *TestClient) SendUnsignedTx(t *testing.T, l2Client *ethclient.Client, transaction *types.Transaction, lInfo info) *types.Receipt { + return SendUnsignedTxViaL1(t, tc.ctx, lInfo, tc.Client, l2Client, transaction) } -func (tc *TestClient) TransferBalance(t *testing.T, from string, to string, amount *big.Int, i info) (*types.Transaction, *types.Receipt) { - return TransferBalanceTo(t, from, i.GetAddress(to), amount, i, tc.Client, tc.ctx) +func (tc *TestClient) TransferBalance(t *testing.T, from string, to string, amount *big.Int, lInfo info) (*types.Transaction, *types.Receipt) { + return TransferBalanceTo(t, from, lInfo.GetAddress(to), amount, lInfo, tc.Client, tc.ctx) } -func (tc *TestClient) TransferBalanceTo(t *testing.T, from string, to common.Address, amount *big.Int, i info) (*types.Transaction, *types.Receipt) { - return TransferBalanceTo(t, from, to, amount, i, tc.Client, tc.ctx) +func (tc *TestClient) TransferBalanceTo(t *testing.T, from string, to common.Address, amount *big.Int, lInfo info) (*types.Transaction, *types.Receipt) { + return TransferBalanceTo(t, from, to, amount, lInfo, tc.Client, tc.ctx) } func (tc *TestClient) GetBalance(t *testing.T, account common.Address) *big.Int { @@ -110,8 +125,8 @@ type NodeBuilder struct { chainConfig *params.ChainConfig nodeConfig *arbnode.Config cachingConfig *execution.CachingConfig - L1StackConfig *node.Config - L2StackConfig *node.Config + l1StackConfig *node.Config + l2StackConfig *node.Config L1Info info L2Info info @@ -129,8 +144,8 @@ type NodeBuilder struct { L2 *TestClient // Created Blockchains - L1B *TestBlockchain - L2B *TestBlockchain + L1B *TestClient + L2B *TestClient } func NewNodeBuilder(ctx context.Context) *NodeBuilder { @@ -151,8 +166,8 @@ func (b *NodeBuilder) DefaultConfig(t *testing.T, withL1 bool) *NodeBuilder { b.L1Info = NewL1TestInfo(t) b.L2Info = NewArbTestInfo(t, b.chainConfig.ChainID) b.dataDir = t.TempDir() - b.L1StackConfig = createStackConfigForTest(b.dataDir) - b.L2StackConfig = createStackConfigForTest(b.dataDir) + b.l1StackConfig = createStackConfigForTest(b.dataDir) + b.l2StackConfig = createStackConfigForTest(b.dataDir) return b } @@ -160,7 +175,7 @@ func (b *NodeBuilder) Build(t *testing.T) func() { if b.withL1 { l1, l2 := NewTestClient(b.ctx), NewTestClient(b.ctx) b.L2Info, l2.Node, l2.Client, l2.Stack, b.L1Info, l1.Backend, l1.Client, l1.Stack = - createTestNodeOnL1WithConfigImpl(t, b.ctx, b.isSequencer, b.nodeConfig, b.chainConfig, b.L2StackConfig, b.L2Info) + createTestNodeOnL1WithConfigImpl(t, b.ctx, b.isSequencer, b.nodeConfig, b.chainConfig, b.l2StackConfig, b.L2Info) b.L1, b.L2 = l1, l2 b.L1.cleanup = func() { requireClose(t, b.L1.Stack) } } else { @@ -178,69 +193,60 @@ func (b *NodeBuilder) Build(t *testing.T) func() { } } -type SecondNodeParams map[string]interface{} - -func (b *NodeBuilder) Build2ndNode(t *testing.T, params SecondNodeParams) (*TestClient, func()) { +func (b *NodeBuilder) Build2ndNode(t *testing.T, params *SecondNodeParams) (*TestClient, func()) { if b.L2 == nil { t.Fatal("builder did not previously build a L2 Node") } - if _, ok := params["nodeConfig"]; !ok { - params["nodeConfig"] = b.nodeConfig - } else if params["nodeConfig"] == nil { - params["nodeConfig"] = arbnode.ConfigDefaultL1NonSequencerTest() - } - if _, ok := params["dasConfig"]; ok { - if params["dasConfig"] == nil { - params["nodeConfig"].(*arbnode.Config). - DataAvailability.Enable = false + if params.nodeConfig == nil { + if params.useBuilderNodeConfig { + params.nodeConfig = b.nodeConfig } else { - params["nodeConfig"].(*arbnode.Config). - DataAvailability = *params["dasConfig"].(*das.DataAvailabilityConfig) + params.nodeConfig = arbnode.ConfigDefaultL1NonSequencerTest() } } - if _, ok := params["stackConfig"]; !ok { - params["stackConfig"] = b.L2StackConfig + if params.dasConfig != nil { + params.nodeConfig.DataAvailability = *params.dasConfig + } + if params.stackConfig == nil { + params.stackConfig = b.l2StackConfig // should use different dataDir from the previously used ones - params["stackConfig"].(*node.Config).DataDir = t.TempDir() + params.stackConfig.DataDir = t.TempDir() } - if _, ok := params["initData"]; !ok { - params["initData"] = &b.L2Info.ArbInitData + if params.initData == nil { + params.initData = &b.L2Info.ArbInitData } - var s *node.Node - var i info + var stack *node.Node + var l1Info info if b.withL1 { if b.L1 == nil { t.Fatal("builder did not previously build a L1 Node") } - s, i = b.L1.Stack, b.L1Info + stack, l1Info = b.L1.Stack, b.L1Info } else { if b.L1B == nil { t.Fatal("builder did not previously build L1 Blockchain") } - s, i = b.L1B.Stack, b.L1B.Info + stack, l1Info = b.L1B.Stack, b.L1Info } l2 := NewTestClient(b.ctx) l2.Client, l2.Node = - Create2ndNodeWithConfig(t, b.ctx, b.L2.Node, s, i, - params["initData"].(*statetransfer.ArbosInitializationInfo), - params["nodeConfig"].(*arbnode.Config), - params["stackConfig"].(*node.Config)) + Create2ndNodeWithConfig(t, b.ctx, b.L2.Node, stack, l1Info, params.initData, params.nodeConfig, params.stackConfig) l2.cleanup = func() { l2.Node.StopAndWait() } return l2, func() { l2.cleanup() } } func (b *NodeBuilder) BuildL1Blockchain(t *testing.T) *NodeBuilder { - l1B := NewTestBlockchain(b.ctx) - l1B.Info, l1B.Client, l1B.Backend, l1B.Stack = createTestL1BlockChainWithConfig(t, b.L1Info, b.L1StackConfig) + l1B := NewTestClient(b.ctx) + b.L1Info, l1B.Client, l1B.Backend, l1B.Stack = createTestL1BlockChainWithConfig(t, b.L1Info, b.l1StackConfig) b.L1B = l1B return b } func (b *NodeBuilder) BuildL2Blockchain(t *testing.T) *NodeBuilder { - l2B := NewTestBlockchain(b.ctx) - l2B.Info, l2B.Stack, l2B.ChainDB, l2B.NodeDB, l2B.Blockchain = - createL2BlockChainWithStackConfig(t, b.L2Info, b.dataDir, b.chainConfig, b.initMessage, b.L2StackConfig, b.cachingConfig) + l2B := NewTestClient(b.ctx) + b.L2Info, l2B.Stack, l2B.ChainDB, l2B.NodeDB, l2B.Blockchain = + createL2BlockChainWithStackConfig(t, b.L2Info, b.dataDir, b.chainConfig, b.initMessage, b.l2StackConfig, b.cachingConfig) b.L2B = l2B return b } @@ -249,25 +255,6 @@ func (b *NodeBuilder) BridgeBalance(t *testing.T, account string, amount *big.In return BridgeBalance(t, account, amount, b.L1Info, b.L2Info, b.L1.Client, b.L2.Client, b.ctx) } -type TestBlockchain struct { - TestClient - // Blockchain fields - chainConfig *params.ChainConfig - ChainDB ethdb.Database - NodeDB ethdb.Database - Blockchain *core.BlockChain - Info info -} - -func NewTestBlockchain(ctx context.Context) *TestBlockchain { - tc := NewTestClient(ctx) - return &TestBlockchain{TestClient: *tc} -} - -func (tb *TestBlockchain) Deploy(t *testing.T) (*chaininfo.RollupAddresses, *arbostypes.ParsedInitMessage) { - return DeployOnTestL1(t, tb.ctx, tb.Info, tb.Client, tb.chainConfig) -} - func SendWaitTestTransactions(t *testing.T, ctx context.Context, client client, txs []*types.Transaction) { t.Helper() for _, tx := range txs { diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index ebe8cfc98..91ddcc2aa 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -257,21 +257,21 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall configByValidationNode(t, conf, valStack) fatalErrChan := make(chan error, 10) - tbL1.chainConfig = chainConfig - asserterRollupAddresses, initMessage := tbL1.Deploy(t) + asserterRollupAddresses, initMessage := DeployOnTestL1(t, ctx, builder.L1Info, tbL1.Client, chainConfig) - deployerTxOpts := tbL1.Info.GetDefaultTransactOpts("deployer", ctx) - sequencerTxOpts := tbL1.Info.GetDefaultTransactOpts("sequencer", ctx) - asserterTxOpts := tbL1.Info.GetDefaultTransactOpts("asserter", ctx) - challengerTxOpts := tbL1.Info.GetDefaultTransactOpts("challenger", ctx) + deployerTxOpts := builder.L1Info.GetDefaultTransactOpts("deployer", ctx) + sequencerTxOpts := builder.L1Info.GetDefaultTransactOpts("sequencer", ctx) + asserterTxOpts := builder.L1Info.GetDefaultTransactOpts("asserter", ctx) + challengerTxOpts := builder.L1Info.GetDefaultTransactOpts("challenger", ctx) - asserterBridgeAddr, asserterSeqInbox, asserterSeqInboxAddr := setupSequencerInboxStub(ctx, t, tbL1.Info, tbL1.Client, chainConfig) - challengerBridgeAddr, challengerSeqInbox, challengerSeqInboxAddr := setupSequencerInboxStub(ctx, t, tbL1.Info, tbL1.Client, chainConfig) + asserterBridgeAddr, asserterSeqInbox, asserterSeqInboxAddr := setupSequencerInboxStub(ctx, t, builder.L1Info, tbL1.Client, chainConfig) + challengerBridgeAddr, challengerSeqInbox, challengerSeqInboxAddr := setupSequencerInboxStub(ctx, t, builder.L1Info, tbL1.Client, chainConfig) builder.initMessage = initMessage builder.L2Info = nil - builder.L2StackConfig.DataDir = t.TempDir() + builder.l2StackConfig.DataDir = t.TempDir() asserterL2tb := builder.BuildL2Blockchain(t).L2B + asserterL2tbInfo := builder.L2Info asserterRollupAddresses.Bridge = asserterBridgeAddr asserterRollupAddresses.SequencerInbox = asserterSeqInboxAddr asserterL2, err := arbnode.CreateNode(ctx, asserterL2tb.Stack, asserterL2tb.ChainDB, asserterL2tb.NodeDB, NewFetcherFromConfig(conf), asserterL2tb.Blockchain, tbL1.Client, asserterRollupAddresses, nil, nil, nil, fatalErrChan) @@ -279,8 +279,10 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall err = asserterL2.Start(ctx) Require(t, err) - builder.L2StackConfig.DataDir = t.TempDir() + builder.L2Info = nil + builder.l2StackConfig.DataDir = t.TempDir() challengerL2tb := builder.BuildL2Blockchain(t).L2B + challengerL2tbInfo := builder.L2Info challengerRollupAddresses := *asserterRollupAddresses challengerRollupAddresses.Bridge = challengerBridgeAddr challengerRollupAddresses.SequencerInbox = challengerSeqInboxAddr @@ -289,32 +291,32 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall err = challengerL2.Start(ctx) Require(t, err) - asserterL2tb.Info.GenerateAccount("Destination") - challengerL2tb.Info.SetFullAccountInfo("Destination", asserterL2tb.Info.GetInfoWithPrivKey("Destination")) + asserterL2tbInfo.GenerateAccount("Destination") + challengerL2tbInfo.SetFullAccountInfo("Destination", asserterL2tbInfo.GetInfoWithPrivKey("Destination")) if challengeMsgIdx < 1 || challengeMsgIdx > 3*makeBatch_MsgsPerBatch { Fatal(t, "challengeMsgIdx illegal") } // seqNum := common.Big2 - makeBatch(t, asserterL2, asserterL2tb.Info, tbL1.Client, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) - makeBatch(t, challengerL2, challengerL2tb.Info, tbL1.Client, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-1) + makeBatch(t, asserterL2, asserterL2tbInfo, tbL1.Client, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) + makeBatch(t, challengerL2, challengerL2tbInfo, tbL1.Client, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-1) // seqNum.Add(seqNum, common.Big1) - makeBatch(t, asserterL2, asserterL2tb.Info, tbL1.Client, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) - makeBatch(t, challengerL2, challengerL2tb.Info, tbL1.Client, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-makeBatch_MsgsPerBatch-1) + makeBatch(t, asserterL2, asserterL2tbInfo, tbL1.Client, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) + makeBatch(t, challengerL2, challengerL2tbInfo, tbL1.Client, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-makeBatch_MsgsPerBatch-1) // seqNum.Add(seqNum, common.Big1) - makeBatch(t, asserterL2, asserterL2tb.Info, tbL1.Client, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) - makeBatch(t, challengerL2, challengerL2tb.Info, tbL1.Client, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-makeBatch_MsgsPerBatch*2-1) + makeBatch(t, asserterL2, asserterL2tbInfo, tbL1.Client, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) + makeBatch(t, challengerL2, challengerL2tbInfo, tbL1.Client, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-makeBatch_MsgsPerBatch*2-1) trueSeqInboxAddr := challengerSeqInboxAddr trueDelayedBridge := challengerBridgeAddr - expectedWinner := tbL1.Info.GetAddress("challenger") + expectedWinner := builder.L1Info.GetAddress("challenger") if asserterIsCorrect { trueSeqInboxAddr = asserterSeqInboxAddr trueDelayedBridge = asserterBridgeAddr - expectedWinner = tbL1.Info.GetAddress("asserter") + expectedWinner = builder.L1Info.GetAddress("asserter") } ospEntry := DeployOneStepProofEntry(t, ctx, &deployerTxOpts, tbL1.Client) @@ -367,11 +369,11 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall asserterStartGlobalState, asserterEndGlobalState, numBlocks, - tbL1.Info.GetAddress("asserter"), - tbL1.Info.GetAddress("challenger"), + builder.L1Info.GetAddress("asserter"), + builder.L1Info.GetAddress("challenger"), ) - confirmLatestBlock(ctx, t, tbL1.Info, tbL1.Client) + confirmLatestBlock(ctx, t, builder.L1Info, tbL1.Client) asserterValidator, err := staker.NewStatelessBlockValidator(asserterL2.InboxReader, asserterL2.InboxTracker, asserterL2.TxStreamer, asserterL2.Execution.Recorder, asserterL2tb.NodeDB, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) if err != nil { @@ -416,7 +418,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall // Invoke a new L1 block, with a new timestamp, before estimating. time.Sleep(time.Second) SendWaitTestTransactions(t, ctx, tbL1.Client, []*types.Transaction{ - tbL1.Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) if i%2 == 0 { @@ -460,7 +462,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall Fatal(t, err) } - confirmLatestBlock(ctx, t, tbL1.Info, tbL1.Client) + confirmLatestBlock(ctx, t, builder.L1Info, tbL1.Client) winner, err := resultReceiver.Winner(&bind.CallOpts{}) if err != nil { From add21a96ffac4a91b7df7afd405c7e99e1ffbe0e Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Wed, 4 Oct 2023 12:12:45 -0700 Subject: [PATCH 216/775] Batch txs rather than on-demand L1 blocks for tests SimulatedBeacon creates a block per tx when running in on-demand mode, and then increments the block timestamps by one if they would've been for the same time, which can break assumptions in a lot of our tests, for example conditional tx tests that set time range restrictions on the txs. By setting SimulatedBeacon's delay to 1s, this allows it to batch multiple txs into a block and avoid this problem. --- system_tests/common_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 6cc032c9d..c5f92515a 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -419,7 +419,7 @@ func createTestL1BlockChainWithConfig(t *testing.T, l1info info, stackConfig *no l1backend, err := eth.New(stack, &nodeConf) Require(t, err) - simBeacon, err := catalyst.NewSimulatedBeacon(0, l1backend) + simBeacon, err := catalyst.NewSimulatedBeacon(1, l1backend) Require(t, err) catalyst.RegisterSimulatedBeaconAPIs(stack, simBeacon) stack.RegisterLifecycle(simBeacon) From 5da33e78aaafb57045507a7e8609cac496f34b34 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 4 Oct 2023 14:52:39 -0500 Subject: [PATCH 217/775] remove buildL1/L2 blockchain fns --- system_tests/common_test.go | 35 +--------- system_tests/full_challenge_impl_test.go | 87 +++++++++++------------- 2 files changed, 41 insertions(+), 81 deletions(-) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 5349c85d7..a1d1a4578 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -74,11 +74,6 @@ type TestClient struct { Stack *node.Node Node *arbnode.Node - // Blockchain specific fields - ChainDB ethdb.Database - NodeDB ethdb.Database - Blockchain *core.BlockChain - // having cleanup() field makes cleanup customizable from default cleanup methods after calling build cleanup func() } @@ -124,28 +119,20 @@ type NodeBuilder struct { ctx context.Context chainConfig *params.ChainConfig nodeConfig *arbnode.Config - cachingConfig *execution.CachingConfig l1StackConfig *node.Config l2StackConfig *node.Config L1Info info L2Info info // L1, L2 Node parameters + dataDir string isSequencer bool takeOwnership bool withL1 bool - // Blockchain parameters - dataDir string - initMessage *arbostypes.ParsedInitMessage - // Created nodes L1 *TestClient L2 *TestClient - - // Created Blockchains - L1B *TestClient - L2B *TestClient } func NewNodeBuilder(ctx context.Context) *NodeBuilder { @@ -223,11 +210,6 @@ func (b *NodeBuilder) Build2ndNode(t *testing.T, params *SecondNodeParams) (*Tes t.Fatal("builder did not previously build a L1 Node") } stack, l1Info = b.L1.Stack, b.L1Info - } else { - if b.L1B == nil { - t.Fatal("builder did not previously build L1 Blockchain") - } - stack, l1Info = b.L1B.Stack, b.L1Info } l2 := NewTestClient(b.ctx) l2.Client, l2.Node = @@ -236,21 +218,6 @@ func (b *NodeBuilder) Build2ndNode(t *testing.T, params *SecondNodeParams) (*Tes return l2, func() { l2.cleanup() } } -func (b *NodeBuilder) BuildL1Blockchain(t *testing.T) *NodeBuilder { - l1B := NewTestClient(b.ctx) - b.L1Info, l1B.Client, l1B.Backend, l1B.Stack = createTestL1BlockChainWithConfig(t, b.L1Info, b.l1StackConfig) - b.L1B = l1B - return b -} - -func (b *NodeBuilder) BuildL2Blockchain(t *testing.T) *NodeBuilder { - l2B := NewTestClient(b.ctx) - b.L2Info, l2B.Stack, l2B.ChainDB, l2B.NodeDB, l2B.Blockchain = - createL2BlockChainWithStackConfig(t, b.L2Info, b.dataDir, b.chainConfig, b.initMessage, b.l2StackConfig, b.cachingConfig) - b.L2B = l2B - return b -} - func (b *NodeBuilder) BridgeBalance(t *testing.T, account string, amount *big.Int) (*types.Transaction, *types.Receipt) { return BridgeBalance(t, account, amount, b.L1Info, b.L2Info, b.L1.Client, b.L2.Client, b.ctx) } diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index 91ddcc2aa..b64a655c3 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -234,14 +234,14 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall defer cancel() initialBalance := new(big.Int).Lsh(big.NewInt(1), 200) + l1Info := NewL1TestInfo(t) + l1Info.GenerateGenesisAccount("deployer", initialBalance) + l1Info.GenerateGenesisAccount("asserter", initialBalance) + l1Info.GenerateGenesisAccount("challenger", initialBalance) + l1Info.GenerateGenesisAccount("sequencer", initialBalance) chainConfig := params.ArbitrumDevTestChainConfig() - builder := NewNodeBuilder(ctx).DefaultConfig(t, false) - builder.L1Info.GenerateGenesisAccount("deployer", initialBalance) - builder.L1Info.GenerateGenesisAccount("asserter", initialBalance) - builder.L1Info.GenerateGenesisAccount("challenger", initialBalance) - builder.L1Info.GenerateGenesisAccount("sequencer", initialBalance) - tbL1 := builder.BuildL1Blockchain(t).L1B + l1Info, l1Backend, _, _ := createTestL1BlockChain(t, l1Info) conf := arbnode.ConfigDefaultL1Test() conf.BlockValidator.Enable = false conf.BatchPoster.Enable = false @@ -257,68 +257,61 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall configByValidationNode(t, conf, valStack) fatalErrChan := make(chan error, 10) - asserterRollupAddresses, initMessage := DeployOnTestL1(t, ctx, builder.L1Info, tbL1.Client, chainConfig) + asserterRollupAddresses, initMessage := DeployOnTestL1(t, ctx, l1Info, l1Backend, chainConfig) - deployerTxOpts := builder.L1Info.GetDefaultTransactOpts("deployer", ctx) - sequencerTxOpts := builder.L1Info.GetDefaultTransactOpts("sequencer", ctx) - asserterTxOpts := builder.L1Info.GetDefaultTransactOpts("asserter", ctx) - challengerTxOpts := builder.L1Info.GetDefaultTransactOpts("challenger", ctx) + deployerTxOpts := l1Info.GetDefaultTransactOpts("deployer", ctx) + sequencerTxOpts := l1Info.GetDefaultTransactOpts("sequencer", ctx) + asserterTxOpts := l1Info.GetDefaultTransactOpts("asserter", ctx) + challengerTxOpts := l1Info.GetDefaultTransactOpts("challenger", ctx) - asserterBridgeAddr, asserterSeqInbox, asserterSeqInboxAddr := setupSequencerInboxStub(ctx, t, builder.L1Info, tbL1.Client, chainConfig) - challengerBridgeAddr, challengerSeqInbox, challengerSeqInboxAddr := setupSequencerInboxStub(ctx, t, builder.L1Info, tbL1.Client, chainConfig) + asserterBridgeAddr, asserterSeqInbox, asserterSeqInboxAddr := setupSequencerInboxStub(ctx, t, l1Info, l1Backend, chainConfig) + challengerBridgeAddr, challengerSeqInbox, challengerSeqInboxAddr := setupSequencerInboxStub(ctx, t, l1Info, l1Backend, chainConfig) - builder.initMessage = initMessage - builder.L2Info = nil - builder.l2StackConfig.DataDir = t.TempDir() - asserterL2tb := builder.BuildL2Blockchain(t).L2B - asserterL2tbInfo := builder.L2Info + asserterL2Info, asserterL2Stack, asserterL2ChainDb, asserterL2ArbDb, asserterL2Blockchain := createL2BlockChainWithStackConfig(t, nil, "", chainConfig, initMessage, nil, nil) asserterRollupAddresses.Bridge = asserterBridgeAddr asserterRollupAddresses.SequencerInbox = asserterSeqInboxAddr - asserterL2, err := arbnode.CreateNode(ctx, asserterL2tb.Stack, asserterL2tb.ChainDB, asserterL2tb.NodeDB, NewFetcherFromConfig(conf), asserterL2tb.Blockchain, tbL1.Client, asserterRollupAddresses, nil, nil, nil, fatalErrChan) + asserterL2, err := arbnode.CreateNode(ctx, asserterL2Stack, asserterL2ChainDb, asserterL2ArbDb, NewFetcherFromConfig(conf), asserterL2Blockchain, l1Backend, asserterRollupAddresses, nil, nil, nil, fatalErrChan) Require(t, err) err = asserterL2.Start(ctx) Require(t, err) - builder.L2Info = nil - builder.l2StackConfig.DataDir = t.TempDir() - challengerL2tb := builder.BuildL2Blockchain(t).L2B - challengerL2tbInfo := builder.L2Info + challengerL2Info, challengerL2Stack, challengerL2ChainDb, challengerL2ArbDb, challengerL2Blockchain := createL2BlockChainWithStackConfig(t, nil, "", chainConfig, initMessage, nil, nil) challengerRollupAddresses := *asserterRollupAddresses challengerRollupAddresses.Bridge = challengerBridgeAddr challengerRollupAddresses.SequencerInbox = challengerSeqInboxAddr - challengerL2, err := arbnode.CreateNode(ctx, challengerL2tb.Stack, challengerL2tb.ChainDB, challengerL2tb.NodeDB, NewFetcherFromConfig(conf), challengerL2tb.Blockchain, tbL1.Client, &challengerRollupAddresses, nil, nil, nil, fatalErrChan) + challengerL2, err := arbnode.CreateNode(ctx, challengerL2Stack, challengerL2ChainDb, challengerL2ArbDb, NewFetcherFromConfig(conf), challengerL2Blockchain, l1Backend, &challengerRollupAddresses, nil, nil, nil, fatalErrChan) Require(t, err) err = challengerL2.Start(ctx) Require(t, err) - asserterL2tbInfo.GenerateAccount("Destination") - challengerL2tbInfo.SetFullAccountInfo("Destination", asserterL2tbInfo.GetInfoWithPrivKey("Destination")) + asserterL2Info.GenerateAccount("Destination") + challengerL2Info.SetFullAccountInfo("Destination", asserterL2Info.GetInfoWithPrivKey("Destination")) if challengeMsgIdx < 1 || challengeMsgIdx > 3*makeBatch_MsgsPerBatch { Fatal(t, "challengeMsgIdx illegal") } // seqNum := common.Big2 - makeBatch(t, asserterL2, asserterL2tbInfo, tbL1.Client, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) - makeBatch(t, challengerL2, challengerL2tbInfo, tbL1.Client, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-1) + makeBatch(t, asserterL2, asserterL2Info, l1Backend, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) + makeBatch(t, challengerL2, challengerL2Info, l1Backend, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-1) // seqNum.Add(seqNum, common.Big1) - makeBatch(t, asserterL2, asserterL2tbInfo, tbL1.Client, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) - makeBatch(t, challengerL2, challengerL2tbInfo, tbL1.Client, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-makeBatch_MsgsPerBatch-1) + makeBatch(t, asserterL2, asserterL2Info, l1Backend, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) + makeBatch(t, challengerL2, challengerL2Info, l1Backend, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-makeBatch_MsgsPerBatch-1) // seqNum.Add(seqNum, common.Big1) - makeBatch(t, asserterL2, asserterL2tbInfo, tbL1.Client, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) - makeBatch(t, challengerL2, challengerL2tbInfo, tbL1.Client, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-makeBatch_MsgsPerBatch*2-1) + makeBatch(t, asserterL2, asserterL2Info, l1Backend, &sequencerTxOpts, asserterSeqInbox, asserterSeqInboxAddr, -1) + makeBatch(t, challengerL2, challengerL2Info, l1Backend, &sequencerTxOpts, challengerSeqInbox, challengerSeqInboxAddr, challengeMsgIdx-makeBatch_MsgsPerBatch*2-1) trueSeqInboxAddr := challengerSeqInboxAddr trueDelayedBridge := challengerBridgeAddr - expectedWinner := builder.L1Info.GetAddress("challenger") + expectedWinner := l1Info.GetAddress("challenger") if asserterIsCorrect { trueSeqInboxAddr = asserterSeqInboxAddr trueDelayedBridge = asserterBridgeAddr - expectedWinner = builder.L1Info.GetAddress("asserter") + expectedWinner = l1Info.GetAddress("asserter") } - ospEntry := DeployOneStepProofEntry(t, ctx, &deployerTxOpts, tbL1.Client) + ospEntry := DeployOneStepProofEntry(t, ctx, &deployerTxOpts, l1Backend) locator, err := server_common.NewMachineLocator("") if err != nil { @@ -361,7 +354,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall t, ctx, &deployerTxOpts, - tbL1.Client, + l1Backend, ospEntry, trueSeqInboxAddr, trueDelayedBridge, @@ -369,13 +362,13 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall asserterStartGlobalState, asserterEndGlobalState, numBlocks, - builder.L1Info.GetAddress("asserter"), - builder.L1Info.GetAddress("challenger"), + l1Info.GetAddress("asserter"), + l1Info.GetAddress("challenger"), ) - confirmLatestBlock(ctx, t, builder.L1Info, tbL1.Client) + confirmLatestBlock(ctx, t, l1Info, l1Backend) - asserterValidator, err := staker.NewStatelessBlockValidator(asserterL2.InboxReader, asserterL2.InboxTracker, asserterL2.TxStreamer, asserterL2.Execution.Recorder, asserterL2tb.NodeDB, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) + asserterValidator, err := staker.NewStatelessBlockValidator(asserterL2.InboxReader, asserterL2.InboxTracker, asserterL2.TxStreamer, asserterL2.Execution.Recorder, asserterL2ArbDb, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) if err != nil { Fatal(t, err) } @@ -388,11 +381,11 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall Fatal(t, err) } defer asserterValidator.Stop() - asserterManager, err := staker.NewChallengeManager(ctx, tbL1.Client, &asserterTxOpts, asserterTxOpts.From, challengeManagerAddr, 1, asserterValidator, 0, 0) + asserterManager, err := staker.NewChallengeManager(ctx, l1Backend, &asserterTxOpts, asserterTxOpts.From, challengeManagerAddr, 1, asserterValidator, 0, 0) if err != nil { Fatal(t, err) } - challengerValidator, err := staker.NewStatelessBlockValidator(challengerL2.InboxReader, challengerL2.InboxTracker, challengerL2.TxStreamer, challengerL2.Execution.Recorder, challengerL2tb.NodeDB, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) + challengerValidator, err := staker.NewStatelessBlockValidator(challengerL2.InboxReader, challengerL2.InboxTracker, challengerL2.TxStreamer, challengerL2.Execution.Recorder, challengerL2ArbDb, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) if err != nil { Fatal(t, err) } @@ -405,7 +398,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall Fatal(t, err) } defer challengerValidator.Stop() - challengerManager, err := staker.NewChallengeManager(ctx, tbL1.Client, &challengerTxOpts, challengerTxOpts.From, challengeManagerAddr, 1, challengerValidator, 0, 0) + challengerManager, err := staker.NewChallengeManager(ctx, l1Backend, &challengerTxOpts, challengerTxOpts.From, challengeManagerAddr, 1, challengerValidator, 0, 0) if err != nil { Fatal(t, err) } @@ -417,8 +410,8 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall // This might make gas estimation undersestimate next move. // Invoke a new L1 block, with a new timestamp, before estimating. time.Sleep(time.Second) - SendWaitTestTransactions(t, ctx, tbL1.Client, []*types.Transaction{ - builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + SendWaitTestTransactions(t, ctx, l1Backend, []*types.Transaction{ + l1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) if i%2 == 0 { @@ -453,7 +446,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall } } - _, err = EnsureTxSucceeded(ctx, tbL1.Client, tx) + _, err = EnsureTxSucceeded(ctx, l1Backend, tx) if err != nil { if !currentCorrect && strings.Contains(err.Error(), "BAD_SEQINBOX_MESSAGE") { t.Log("challenge complete! Tx failed as expected:", err) @@ -462,7 +455,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall Fatal(t, err) } - confirmLatestBlock(ctx, t, builder.L1Info, tbL1.Client) + confirmLatestBlock(ctx, t, l1Info, l1Backend) winner, err := resultReceiver.Winner(&bind.CallOpts{}) if err != nil { From 31c048b41c528105cd6891d2061232b5bd00054a Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 4 Oct 2023 15:58:26 -0500 Subject: [PATCH 218/775] refactor Build2ndNode --- system_tests/common_test.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index cc205862a..01e44dc80 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -187,6 +187,9 @@ func (b *NodeBuilder) Build2ndNode(t *testing.T, params *SecondNodeParams) (*Tes if b.L2 == nil { t.Fatal("builder did not previously build a L2 Node") } + if b.withL1 && b.L1 == nil { + t.Fatal("builder did not previously build a L1 Node") + } if params.nodeConfig == nil { if params.useBuilderNodeConfig { params.nodeConfig = b.nodeConfig @@ -209,17 +212,9 @@ func (b *NodeBuilder) Build2ndNode(t *testing.T, params *SecondNodeParams) (*Tes params.execConfig = b.execConfig } - var stack *node.Node - var l1Info info - if b.withL1 { - if b.L1 == nil { - t.Fatal("builder did not previously build a L1 Node") - } - stack, l1Info = b.L1.Stack, b.L1Info - } l2 := NewTestClient(b.ctx) l2.Client, l2.Node = - Create2ndNodeWithConfig(t, b.ctx, b.L2.Node, stack, l1Info, params.initData, params.nodeConfig, params.execConfig, params.stackConfig) + Create2ndNodeWithConfig(t, b.ctx, b.L2.Node, b.L1.Stack, b.L1Info, params.initData, params.nodeConfig, params.execConfig, params.stackConfig) l2.cleanup = func() { l2.Node.StopAndWait() } return l2, func() { l2.cleanup() } } From 5fb1a3368b07b8c5365f5efba5c0a40958045b69 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 5 Oct 2023 17:13:56 +0200 Subject: [PATCH 219/775] Add access lists for batchposter transactions to reduce cold memory access cost --- arbnode/batch_poster.go | 87 ++++++++++++++++++++++---- arbnode/dataposter/data_poster.go | 18 +++--- arbutil/hash.go | 17 +++++ arbutil/hash_test.go | 49 +++++++++++++++ cmd/chaininfo/arbitrum_chain_info.json | 1 + 5 files changed, 154 insertions(+), 18 deletions(-) create mode 100644 arbutil/hash.go create mode 100644 arbutil/hash_test.go diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index c84809951..d03ad3b17 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -66,6 +66,8 @@ type BatchPoster struct { syncMonitor *SyncMonitor seqInboxABI *abi.ABI seqInboxAddr common.Address + bridgeAddr common.Address + gasRefunderAddr common.Address building *buildingBatch daWriter das.DataAvailabilityServiceWriter dataPoster *dataposter.DataPoster @@ -238,17 +240,19 @@ func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader * return nil, err } b := &BatchPoster{ - l1Reader: l1Reader, - inbox: inbox, - streamer: streamer, - syncMonitor: syncMonitor, - config: config, - bridge: bridge, - seqInbox: seqInbox, - seqInboxABI: seqInboxABI, - seqInboxAddr: deployInfo.SequencerInbox, - daWriter: daWriter, - redisLock: redisLock, + l1Reader: l1Reader, + inbox: inbox, + streamer: streamer, + syncMonitor: syncMonitor, + config: config, + bridge: bridge, + seqInbox: seqInbox, + seqInboxABI: seqInboxABI, + seqInboxAddr: deployInfo.SequencerInbox, + gasRefunderAddr: config().gasRefunder, + bridgeAddr: deployInfo.Bridge, + daWriter: daWriter, + redisLock: redisLock, } dataPosterConfigFetcher := func() *dataposter.DataPosterConfig { return &config().DataPoster @@ -263,6 +267,7 @@ func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader * Config: dataPosterConfigFetcher, MetadataRetriever: b.getBatchPosterPosition, RedisKey: "data-poster.queue", + AccessList: b.accessList(), }, ) if err != nil { @@ -271,6 +276,66 @@ func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader * return b, nil } +func (b *BatchPoster) accessList() types.AccessList { + l := types.AccessList{ + types.AccessTuple{ + // Bridge contract address. + Address: b.seqInboxAddr, + StorageKeys: []common.Hash{ + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), // totalDelayedMessagesRead + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"), // bridge + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000004"), // maxTimeVariation.delayBlocks + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000005"), // maxTimeVariation.futureBlocks + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000006"), // maxTimeVariation.delaySeconds + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000007"), // maxTimeVariation.futureSeconds + // ADMIN_SLOT from OpenZeppelin, keccak-256 hash of + // "eip1967.proxy.admin" subtracted by 1. + common.HexToHash("0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"), + // IMPLEMENTATION_SLOT from OpenZeppelin, keccak-256 hash + // of "eip1967.proxy.implementation" subtracted by 1. + common.HexToHash("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"), + common.HexToHash("0xa10aa54071443520884ed767b0684edf43acec528b7da83ab38ce60126562660"), // isBatchPoster[batchPosterAddr] + }, + }, + types.AccessTuple{ + Address: b.bridgeAddr, + StorageKeys: []common.Hash{ + common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000000a"), // sequencerReportedSubMessageCount + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000007"), // sequencerInboxAccs.length + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000006"), // delayedInboxAccs.length + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000009"), // sequencerInbox + // ADMIN_SLOT from OpenZeppelin, keccak-256 hash of + // "eip1967.proxy.admin" subtracted by 1. + common.HexToHash("0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"), + // IMPLEMENTATION_SLOT from OpenZeppelin, keccak-256 hash + // of "eip1967.proxy.implementation" subtracted by 1. + common.HexToHash("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"), + // TODO: add dynamic storage slots for: + // - sequencerInboxAccs[sequencerInboxAccs.length - 1]; + // - sequencerInboxAccs.push(...); + // - delayedInboxAccs[afterDelayedMessagesRead - 1]; + // May change when transaction is actually executed: + // - delayedInboxAccs[delayedInboxAccs.length - 1] + // - delayedInboxAccs.push(...); + }, + }, + } + if (b.gasRefunderAddr != common.Address{}) { + l = append(l, types.AccessTuple{ + Address: b.gasRefunderAddr, + StorageKeys: []common.Hash{ + // CommonParameters.{maxRefundeeBalance, extraGasMargin, calldataCost, maxGasTip} + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000004"), + // CommonParameters.{maxGasCost, maxSingleGasUsage} + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000005"), + common.HexToHash("0xe85fd79f89ff278fc57d40aecb7947873df9f0beac531c8f71a98f630e1eab62"), // allowedRefundees[refundee] + common.HexToHash("0x7686888b19bb7b75e46bb1aa328b65150743f4899443d722f0adf8e252ccda41"), // allowedContracts[msg.sender] + }, + }) + } + return l +} + // checkRevert checks blocks with number in range [from, to] whether they // contain reverted batch_poster transaction. // It returns true if it finds batch posting needs to halt, which is true if a batch reverts diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 3b563e965..e49a2194e 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -64,6 +64,7 @@ type DataPoster struct { nonce uint64 queue QueueStorage errorCount map[uint64]int // number of consecutive intermittent errors rbf-ing or sending, per nonce + accessList types.AccessList } type AttemptLocker interface { @@ -100,6 +101,7 @@ type DataPosterOpts struct { Config ConfigFetcher MetadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error) RedisKey string // Redis storage key + AccessList types.AccessList } func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, error) { @@ -150,6 +152,7 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro queue: queue, redisLock: opts.RedisLock, errorCount: make(map[uint64]int), + accessList: opts.AccessList, }, nil } @@ -362,13 +365,14 @@ func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Tim return nil, err } inner := types.DynamicFeeTx{ - Nonce: nonce, - GasTipCap: tipCap, - GasFeeCap: feeCap, - Gas: gasLimit, - To: &to, - Value: value, - Data: calldata, + Nonce: nonce, + GasTipCap: tipCap, + GasFeeCap: feeCap, + Gas: gasLimit, + To: &to, + Value: value, + Data: calldata, + AccessList: p.accessList, } fullTx, err := p.signer(p.sender, types.NewTx(&inner)) if err != nil { diff --git a/arbutil/hash.go b/arbutil/hash.go new file mode 100644 index 000000000..4ab93b61e --- /dev/null +++ b/arbutil/hash.go @@ -0,0 +1,17 @@ +package arbutil + +import ( + "github.com/ethereum/go-ethereum/common" + "golang.org/x/crypto/sha3" +) + +// slotAddress pads each argument to 32 bytes, concatenates and returns +// keccak256 hashe of the result. +func slotAddress(args ...[]byte) []byte { + hash := sha3.NewLegacyKeccak256() + for _, arg := range args { + // fmt.Printf("%x\n", common.BytesToHash(arg).Bytes()) + hash.Write(common.BytesToHash(arg).Bytes()) + } + return hash.Sum(nil) +} diff --git a/arbutil/hash_test.go b/arbutil/hash_test.go new file mode 100644 index 000000000..bc25fb21a --- /dev/null +++ b/arbutil/hash_test.go @@ -0,0 +1,49 @@ +package arbutil + +import ( + "bytes" + "testing" + + "github.com/ethereum/go-ethereum/common" +) + +func TestSlotAddress(t *testing.T) { + for _, tc := range []struct { + name string + args [][]byte + want []byte + }{ + { + name: "isBatchPoster[batchPosterAddr]", // Keccak256(addr, 3) + args: [][]byte{ + common.FromHex("0xC1b634853Cb333D3aD8663715b08f41A3Aec47cc"), // batch poster address + {3}, + }, + want: common.HexToHash("0xa10aa54071443520884ed767b0684edf43acec528b7da83ab38ce60126562660").Bytes(), + }, + { + name: "allowedContracts[msg.sender]", // Keccak256(msg.sender, 1) + args: [][]byte{ + common.FromHex("0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6"), // sequencer address + {1}, + }, + want: common.HexToHash("0xe85fd79f89ff278fc57d40aecb7947873df9f0beac531c8f71a98f630e1eab62").Bytes(), + }, + { + name: "allowedRefundees[refundee]", // Keccak256(msg.sender, 2) + args: [][]byte{ + common.FromHex("0xC1b634853Cb333D3aD8663715b08f41A3Aec47cc"), // batch poster address + {2}, + }, + want: common.HexToHash("0x7686888b19bb7b75e46bb1aa328b65150743f4899443d722f0adf8e252ccda41").Bytes(), + }, + } { + t.Run(tc.name, func(t *testing.T) { + got := slotAddress(tc.args...) + if !bytes.Equal(got, tc.want) { + t.Errorf("slotAddress(%x) = %x, want %x", tc.args, got, tc.want) + } + }) + } + +} diff --git a/cmd/chaininfo/arbitrum_chain_info.json b/cmd/chaininfo/arbitrum_chain_info.json index 051ccd03c..a21d93800 100644 --- a/cmd/chaininfo/arbitrum_chain_info.json +++ b/cmd/chaininfo/arbitrum_chain_info.json @@ -44,6 +44,7 @@ "inbox": "0x4dbd4fc535ac27206064b68ffcf827b0a60bab3f", "rollup": "0x5ef0d09d1e6204141b4d37530808ed19f60fba35", "sequencer-inbox": "0x1c479675ad559dc151f6ec7ed3fbf8cee79582b6", + "gas-refunder": "0xe64a54E2533Fd126C2E452c5fAb544d80E2E4eb5", "validator-utils": "0x9e40625f52829cf04bc4839f186d621ee33b0e67", "validator-wallet-creator": "0x960953f7c69cd2bc2322db9223a815c680ccc7ea", "deployed-at": 15411056 From 2fb5546c484b6e4ee81828629d53aab13863a455 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 5 Oct 2023 10:14:30 -0500 Subject: [PATCH 220/775] add ExecutionNode to TestClient --- system_tests/bloom_test.go | 3 +-- system_tests/common_test.go | 12 +++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/system_tests/bloom_test.go b/system_tests/bloom_test.go index bb284ad5e..9079fd35f 100644 --- a/system_tests/bloom_test.go +++ b/system_tests/bloom_test.go @@ -81,9 +81,8 @@ func TestBloom(t *testing.T) { t.Log("counts: ", i, "/", countsNum) } } - execNode := getExecNode(t, builder.L2.Node) for { - sectionSize, sectionNum := execNode.Backend.APIBackend().BloomStatus() + sectionSize, sectionNum := builder.L2.ExecNode.Backend.APIBackend().BloomStatus() if sectionSize != 256 { Fatal(t, "unexpected section size: ", sectionSize) } diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 01e44dc80..80537b7d0 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -69,11 +69,12 @@ type SecondNodeParams struct { } type TestClient struct { - ctx context.Context - Client *ethclient.Client - Backend *eth.Ethereum - Stack *node.Node - Node *arbnode.Node + ctx context.Context + Client *ethclient.Client + Backend *eth.Ethereum + Stack *node.Node + Node *arbnode.Node + ExecNode *gethexec.ExecutionNode // having cleanup() field makes cleanup customizable from default cleanup methods after calling build cleanup func() @@ -174,6 +175,7 @@ func (b *NodeBuilder) Build(t *testing.T) func() { CreateTestL2WithConfig(t, b.ctx, b.L2Info, b.nodeConfig, b.execConfig, b.takeOwnership) b.L2 = l2 } + b.L2.ExecNode = getExecNode(t, b.L2.Node) b.L2.cleanup = func() { b.L2.Node.StopAndWait() } return func() { b.L2.cleanup() From 129417b650f07b9b72fe93a809acda2033fee8a1 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Fri, 6 Oct 2023 17:22:18 +0200 Subject: [PATCH 221/775] Generate dynamic slots, add tests --- arbnode/batch_poster.go | 47 +++++++++++++------- arbutil/hash.go | 4 +- arbutil/hash_test.go | 8 ++-- system_tests/seqinbox_test.go | 84 +++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 23 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index d03ad3b17..d0f7fdb0e 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -267,7 +267,12 @@ func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader * Config: dataPosterConfigFetcher, MetadataRetriever: b.getBatchPosterPosition, RedisKey: "data-poster.queue", - AccessList: b.accessList(), + AccessList: AccessList(&AccessListOpts{ + SequencerInboxAddr: deployInfo.SequencerInbox, + DataPosterAddr: transactOpts.From, // Same as batchposter address. + BridgeAddr: deployInfo.Bridge, + GasRefunderAddr: config().gasRefunder, + }), }, ) if err != nil { @@ -276,11 +281,18 @@ func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader * return b, nil } -func (b *BatchPoster) accessList() types.AccessList { +type AccessListOpts struct { + SequencerInboxAddr common.Address + BridgeAddr common.Address + DataPosterAddr common.Address + GasRefunderAddr common.Address +} + +// AccessList returns access list (contracts, storage slots) for batchposter. +func AccessList(opts *AccessListOpts) types.AccessList { l := types.AccessList{ types.AccessTuple{ - // Bridge contract address. - Address: b.seqInboxAddr, + Address: opts.SequencerInboxAddr, StorageKeys: []common.Hash{ common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), // totalDelayedMessagesRead common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"), // bridge @@ -294,16 +306,17 @@ func (b *BatchPoster) accessList() types.AccessList { // IMPLEMENTATION_SLOT from OpenZeppelin, keccak-256 hash // of "eip1967.proxy.implementation" subtracted by 1. common.HexToHash("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"), - common.HexToHash("0xa10aa54071443520884ed767b0684edf43acec528b7da83ab38ce60126562660"), // isBatchPoster[batchPosterAddr] + // isBatchPoster[batchPosterAddr]; for mainnnet it's: "0xa10aa54071443520884ed767b0684edf43acec528b7da83ab38ce60126562660". + common.Hash(arbutil.StorageSlotAddress(opts.DataPosterAddr.Bytes(), []byte{3})), }, }, types.AccessTuple{ - Address: b.bridgeAddr, + Address: opts.BridgeAddr, StorageKeys: []common.Hash{ - common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000000a"), // sequencerReportedSubMessageCount - common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000007"), // sequencerInboxAccs.length common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000006"), // delayedInboxAccs.length + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000007"), // sequencerInboxAccs.length common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000009"), // sequencerInbox + common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000000a"), // sequencerReportedSubMessageCount // ADMIN_SLOT from OpenZeppelin, keccak-256 hash of // "eip1967.proxy.admin" subtracted by 1. common.HexToHash("0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"), @@ -314,22 +327,22 @@ func (b *BatchPoster) accessList() types.AccessList { // - sequencerInboxAccs[sequencerInboxAccs.length - 1]; // - sequencerInboxAccs.push(...); // - delayedInboxAccs[afterDelayedMessagesRead - 1]; - // May change when transaction is actually executed: + // These below may change when transaction is actually executed: // - delayedInboxAccs[delayedInboxAccs.length - 1] // - delayedInboxAccs.push(...); }, }, } - if (b.gasRefunderAddr != common.Address{}) { + if (opts.GasRefunderAddr != common.Address{}) { l = append(l, types.AccessTuple{ - Address: b.gasRefunderAddr, + Address: opts.GasRefunderAddr, StorageKeys: []common.Hash{ - // CommonParameters.{maxRefundeeBalance, extraGasMargin, calldataCost, maxGasTip} - common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000004"), - // CommonParameters.{maxGasCost, maxSingleGasUsage} - common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000005"), - common.HexToHash("0xe85fd79f89ff278fc57d40aecb7947873df9f0beac531c8f71a98f630e1eab62"), // allowedRefundees[refundee] - common.HexToHash("0x7686888b19bb7b75e46bb1aa328b65150743f4899443d722f0adf8e252ccda41"), // allowedContracts[msg.sender] + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000004"), // CommonParameters.{maxRefundeeBalance, extraGasMargin, calldataCost, maxGasTip} + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000005"), // CommonParameters.{maxGasCost, maxSingleGasUsage} + // allowedContracts[msg.sender]; for mainnet it's: "0x7686888b19bb7b75e46bb1aa328b65150743f4899443d722f0adf8e252ccda41". + common.Hash(arbutil.StorageSlotAddress(opts.SequencerInboxAddr.Bytes(), []byte{1})), + // allowedRefundees[refundee]; for mainnet it's: "0xe85fd79f89ff278fc57d40aecb7947873df9f0beac531c8f71a98f630e1eab62". + common.Hash(arbutil.StorageSlotAddress(opts.DataPosterAddr.Bytes(), []byte{2})), }, }) } diff --git a/arbutil/hash.go b/arbutil/hash.go index 4ab93b61e..0893898f7 100644 --- a/arbutil/hash.go +++ b/arbutil/hash.go @@ -5,9 +5,9 @@ import ( "golang.org/x/crypto/sha3" ) -// slotAddress pads each argument to 32 bytes, concatenates and returns +// StorageSlotAddress pads each argument to 32 bytes, concatenates and returns // keccak256 hashe of the result. -func slotAddress(args ...[]byte) []byte { +func StorageSlotAddress(args ...[]byte) []byte { hash := sha3.NewLegacyKeccak256() for _, arg := range args { // fmt.Printf("%x\n", common.BytesToHash(arg).Bytes()) diff --git a/arbutil/hash_test.go b/arbutil/hash_test.go index bc25fb21a..639274653 100644 --- a/arbutil/hash_test.go +++ b/arbutil/hash_test.go @@ -16,7 +16,7 @@ func TestSlotAddress(t *testing.T) { { name: "isBatchPoster[batchPosterAddr]", // Keccak256(addr, 3) args: [][]byte{ - common.FromHex("0xC1b634853Cb333D3aD8663715b08f41A3Aec47cc"), // batch poster address + common.FromHex("0xC1b634853Cb333D3aD8663715b08f41A3Aec47cc"), // mainnet batch poster address {3}, }, want: common.HexToHash("0xa10aa54071443520884ed767b0684edf43acec528b7da83ab38ce60126562660").Bytes(), @@ -24,7 +24,7 @@ func TestSlotAddress(t *testing.T) { { name: "allowedContracts[msg.sender]", // Keccak256(msg.sender, 1) args: [][]byte{ - common.FromHex("0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6"), // sequencer address + common.FromHex("0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6"), // mainnet sequencer address {1}, }, want: common.HexToHash("0xe85fd79f89ff278fc57d40aecb7947873df9f0beac531c8f71a98f630e1eab62").Bytes(), @@ -32,14 +32,14 @@ func TestSlotAddress(t *testing.T) { { name: "allowedRefundees[refundee]", // Keccak256(msg.sender, 2) args: [][]byte{ - common.FromHex("0xC1b634853Cb333D3aD8663715b08f41A3Aec47cc"), // batch poster address + common.FromHex("0xC1b634853Cb333D3aD8663715b08f41A3Aec47cc"), // mainnet batch poster address {2}, }, want: common.HexToHash("0x7686888b19bb7b75e46bb1aa328b65150743f4899443d722f0adf8e252ccda41").Bytes(), }, } { t.Run(tc.name, func(t *testing.T) { - got := slotAddress(tc.args...) + got := StorageSlotAddress(tc.args...) if !bytes.Equal(got, tc.want) { t.Errorf("slotAddress(%x) = %x, want %x", tc.args, got, tc.want) } diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index 6c01ae65a..309c174b2 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -6,16 +6,20 @@ package arbtest import ( "bytes" "context" + "errors" "fmt" "math/big" "math/rand" "testing" "time" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/ethclient/gethclient" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" @@ -39,6 +43,54 @@ type blockTestState struct { const seqInboxTestIters = 40 +func encodeAddBatch(seqABI *abi.ABI, seqNum *big.Int, message []byte, afterDelayedMsgRead *big.Int, gasRefunder common.Address) ([]byte, error) { + method, ok := seqABI.Methods["addSequencerL2BatchFromOrigin0"] + if !ok { + return nil, errors.New("failed to find add addSequencerL2BatchFromOrigin0 method") + } + inputData, err := method.Inputs.Pack( + seqNum, + message, + afterDelayedMsgRead, + gasRefunder, + new(big.Int).SetUint64(uint64(1)), + new(big.Int).SetUint64(uint64(1)), + ) + if err != nil { + return nil, err + } + fullData := append([]byte{}, method.ID...) + fullData = append(fullData, inputData...) + return fullData, nil +} +func diffAccessList(accessed, al types.AccessList) string { + m := make(map[common.Address]map[common.Hash]bool) + for i := 0; i < len(al); i++ { + if _, ok := m[al[i].Address]; !ok { + m[al[i].Address] = make(map[common.Hash]bool) + } + for _, slot := range al[i].StorageKeys { + m[al[i].Address][slot] = true + } + } + + diff := "" + for i := 0; i < len(accessed); i++ { + addr := accessed[i].Address + if _, ok := m[addr]; !ok { + diff += fmt.Sprintf("contract address: %q wasn't accessed\n", addr) + continue + } + for j := 0; j < len(accessed[i].StorageKeys); j++ { + slot := accessed[i].StorageKeys[j] + if _, ok := m[addr][slot]; !ok { + diff += fmt.Sprintf("storage slot: %q for contract: %v wasn't accessed", slot, addr) + } + } + } + return diff +} + func deployGasRefunder(ctx context.Context, t *testing.T, info *BlockchainTestInfo, client *ethclient.Client) common.Address { t.Helper() abi, err := bridgegen.GasRefunderMetaData.GetAbi() @@ -99,6 +151,12 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { l1BlockChain := l1backend.BlockChain() + rpcC, err := l1stack.Attach() + if err != nil { + t.Fatalf("Error connecting to l1 node: %v", err) + } + gethClient := gethclient.New(rpcC) + seqInbox, err := bridgegen.NewSequencerInbox(l1Info.GetAddress("SequencerInbox"), l1Client) Require(t, err) seqOpts := l1Info.GetDefaultTransactOpts("Sequencer", ctx) @@ -267,6 +325,32 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", seqOpts.From, err) } + seqABI, err := bridgegen.SequencerInboxMetaData.GetAbi() + if err != nil { + t.Fatalf("Error getting sequencer inbox abi: %v", err) + } + data, err := encodeAddBatch(seqABI, big.NewInt(int64(len(blockStates))), batchData, big.NewInt(1), gasRefunderAddr) + if err != nil { + t.Fatalf("Error encoding batch data: %v", err) + } + si := l1Info.GetAddress("SequencerInbox") + wantAL, _, _, err := gethClient.CreateAccessList(ctx, ethereum.CallMsg{ + From: seqOpts.From, + To: &si, + Data: data, + }) + if err != nil { + t.Fatalf("Error creating access list: %v", err) + } + accessed := arbnode.AccessList(&arbnode.AccessListOpts{ + SequencerInboxAddr: l1Info.GetAddress("SequencerInbox"), + BridgeAddr: l1Info.GetAddress("Bridge"), + DataPosterAddr: seqOpts.From, + GasRefunderAddr: gasRefunderAddr, + }) + if diff := diffAccessList(accessed, *wantAL); diff != "" { + t.Errorf("Access list mistmatch:\n%s\n", diff) + } if i%5 == 0 { tx, err = seqInbox.AddSequencerL2Batch(&seqOpts, big.NewInt(int64(len(blockStates))), batchData, big.NewInt(1), gasRefunderAddr, big.NewInt(0), big.NewInt(0)) } else { From 5fb935ebc9da6db147ab501e2df8eb78b3d88d54 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Fri, 6 Oct 2023 17:24:47 +0200 Subject: [PATCH 222/775] drop gas-refunder from arbitrum_chain_info.json --- cmd/chaininfo/arbitrum_chain_info.json | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/chaininfo/arbitrum_chain_info.json b/cmd/chaininfo/arbitrum_chain_info.json index a21d93800..051ccd03c 100644 --- a/cmd/chaininfo/arbitrum_chain_info.json +++ b/cmd/chaininfo/arbitrum_chain_info.json @@ -44,7 +44,6 @@ "inbox": "0x4dbd4fc535ac27206064b68ffcf827b0a60bab3f", "rollup": "0x5ef0d09d1e6204141b4d37530808ed19f60fba35", "sequencer-inbox": "0x1c479675ad559dc151f6ec7ed3fbf8cee79582b6", - "gas-refunder": "0xe64a54E2533Fd126C2E452c5fAb544d80E2E4eb5", "validator-utils": "0x9e40625f52829cf04bc4839f186d621ee33b0e67", "validator-wallet-creator": "0x960953f7c69cd2bc2322db9223a815c680ccc7ea", "deployed-at": 15411056 From 9936662f9b74b22043c6144769c740c4c04bf06d Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Fri, 6 Oct 2023 17:26:02 +0200 Subject: [PATCH 223/775] Move sequencer ABI instantiation outside loop --- system_tests/seqinbox_test.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index 309c174b2..c40a51a4c 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -201,6 +201,11 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { } SendWaitTestTransactions(t, ctx, l1Client, faucetTxs) + seqABI, err := bridgegen.SequencerInboxMetaData.GetAbi() + if err != nil { + t.Fatalf("Error getting sequencer inbox abi: %v", err) + } + for i := 1; i < seqInboxTestIters; i++ { if i%10 == 0 { reorgTo := rand.Int() % len(blockStates) @@ -325,10 +330,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", seqOpts.From, err) } - seqABI, err := bridgegen.SequencerInboxMetaData.GetAbi() - if err != nil { - t.Fatalf("Error getting sequencer inbox abi: %v", err) - } + data, err := encodeAddBatch(seqABI, big.NewInt(int64(len(blockStates))), batchData, big.NewInt(1), gasRefunderAddr) if err != nil { t.Fatalf("Error encoding batch data: %v", err) From 8d50a42975be9e343012fa53c54936f1b33afe48 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Fri, 6 Oct 2023 17:27:03 +0200 Subject: [PATCH 224/775] Drop commented out line from StorageSlotAddress --- arbutil/hash.go | 1 - 1 file changed, 1 deletion(-) diff --git a/arbutil/hash.go b/arbutil/hash.go index 0893898f7..6966cc6df 100644 --- a/arbutil/hash.go +++ b/arbutil/hash.go @@ -10,7 +10,6 @@ import ( func StorageSlotAddress(args ...[]byte) []byte { hash := sha3.NewLegacyKeccak256() for _, arg := range args { - // fmt.Printf("%x\n", common.BytesToHash(arg).Bytes()) hash.Write(common.BytesToHash(arg).Bytes()) } return hash.Sum(nil) From 5fef660f0127d2bd0e559b9c7348e8c52cd76f99 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 6 Oct 2023 16:45:04 -0700 Subject: [PATCH 225/775] Fix log message for error starting metrics --- cmd/nitro-val/nitro_val.go | 2 +- cmd/nitro/nitro.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/nitro-val/nitro_val.go b/cmd/nitro-val/nitro_val.go index a461a3690..43b1c1d20 100644 --- a/cmd/nitro-val/nitro_val.go +++ b/cmd/nitro-val/nitro_val.go @@ -122,7 +122,7 @@ func mainImpl() int { } if err := startMetrics(nodeConfig); err != nil { - log.Error("Starting metrics: %v", err) + log.Error("Error starting metrics", "error", err) return 1 } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 73ab30ad3..9656f7f5e 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -399,7 +399,7 @@ func mainImpl() int { } if err := startMetrics(nodeConfig); err != nil { - log.Error("Starting metrics: %v", err) + log.Error("Error starting metrics", "error", err) return 1 } From 4278196f3b0f66b1bbce6da92f6f725bc7bf3599 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 9 Oct 2023 16:07:47 +0200 Subject: [PATCH 226/775] Add access list entries for dynamic storage slots for bridge contract --- arbnode/batch_poster.go | 79 ++++++++++++++++++++++-------- arbnode/dataposter/data_poster.go | 7 +-- arbutil/hash.go | 31 +++++++++--- arbutil/hash_test.go | 67 ++++++++++++++++++++++++- staker/validatorwallet/contract.go | 6 +-- staker/validatorwallet/eoa.go | 2 +- system_tests/seqinbox_test.go | 12 +++-- 7 files changed, 162 insertions(+), 42 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index d0f7fdb0e..af054e7a5 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -6,6 +6,7 @@ package arbnode import ( "bytes" "context" + "encoding/binary" "encoding/hex" "errors" "fmt" @@ -80,6 +81,8 @@ type BatchPoster struct { batchReverted atomic.Bool // indicates whether data poster batch was reverted nextRevertCheckBlock int64 // the last parent block scanned for reverting batches + + accessList func(SequencerInboxAccs, AfterDelayedMessagesRead int) types.AccessList } type l1BlockBound int @@ -253,6 +256,16 @@ func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader * bridgeAddr: deployInfo.Bridge, daWriter: daWriter, redisLock: redisLock, + accessList: func(SequencerInboxAccs, AfterDelayedMessagesRead int) types.AccessList { + return AccessList(&AccessListOpts{ + SequencerInboxAddr: deployInfo.SequencerInbox, + DataPosterAddr: transactOpts.From, + BridgeAddr: deployInfo.Bridge, + GasRefunderAddr: config().gasRefunder, + SequencerInboxAccs: SequencerInboxAccs, + AfterDelayedMessagesRead: AfterDelayedMessagesRead, + }) + }, } dataPosterConfigFetcher := func() *dataposter.DataPosterConfig { return &config().DataPoster @@ -267,14 +280,7 @@ func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader * Config: dataPosterConfigFetcher, MetadataRetriever: b.getBatchPosterPosition, RedisKey: "data-poster.queue", - AccessList: AccessList(&AccessListOpts{ - SequencerInboxAddr: deployInfo.SequencerInbox, - DataPosterAddr: transactOpts.From, // Same as batchposter address. - BridgeAddr: deployInfo.Bridge, - GasRefunderAddr: config().gasRefunder, - }), - }, - ) + }) if err != nil { return nil, err } @@ -282,10 +288,12 @@ func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader * } type AccessListOpts struct { - SequencerInboxAddr common.Address - BridgeAddr common.Address - DataPosterAddr common.Address - GasRefunderAddr common.Address + SequencerInboxAddr common.Address + BridgeAddr common.Address + DataPosterAddr common.Address + GasRefunderAddr common.Address + SequencerInboxAccs int + AfterDelayedMessagesRead int } // AccessList returns access list (contracts, storage slots) for batchposter. @@ -307,7 +315,7 @@ func AccessList(opts *AccessListOpts) types.AccessList { // of "eip1967.proxy.implementation" subtracted by 1. common.HexToHash("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"), // isBatchPoster[batchPosterAddr]; for mainnnet it's: "0xa10aa54071443520884ed767b0684edf43acec528b7da83ab38ce60126562660". - common.Hash(arbutil.StorageSlotAddress(opts.DataPosterAddr.Bytes(), []byte{3})), + common.Hash(arbutil.PaddedKeccak256(opts.DataPosterAddr.Bytes(), []byte{3})), }, }, types.AccessTuple{ @@ -323,16 +331,28 @@ func AccessList(opts *AccessListOpts) types.AccessList { // IMPLEMENTATION_SLOT from OpenZeppelin, keccak-256 hash // of "eip1967.proxy.implementation" subtracted by 1. common.HexToHash("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"), - // TODO: add dynamic storage slots for: - // - sequencerInboxAccs[sequencerInboxAccs.length - 1]; - // - sequencerInboxAccs.push(...); - // - delayedInboxAccs[afterDelayedMessagesRead - 1]; // These below may change when transaction is actually executed: // - delayedInboxAccs[delayedInboxAccs.length - 1] // - delayedInboxAccs.push(...); }, }, } + + for _, v := range []struct{ slotIdx, val int }{ + {7, opts.SequencerInboxAccs - 1}, // - sequencerInboxAccs[sequencerInboxAccs.length - 1]; (keccak256(7, sequencerInboxAccs.length - 1)) + {7, opts.SequencerInboxAccs}, // - sequencerInboxAccs.push(...); (keccak256(7, sequencerInboxAccs.length)) + {6, opts.AfterDelayedMessagesRead - 1}, // - delayedInboxAccs[afterDelayedMessagesRead - 1]; (keccak256(6, afterDelayedMessagesRead - 1)) + } { + + sia, err := intToBytes(v.val) + if err != nil { + log.Error("Error converting sequencer inbox accs to bytes", "err", err, "sequencerInboxAccs", opts.SequencerInboxAccs) + continue + } + sb := arbutil.SumBytes(arbutil.PaddedKeccak256([]byte{byte(v.slotIdx)}), sia) + l[1].StorageKeys = append(l[1].StorageKeys, common.Hash(sb)) + } + if (opts.GasRefunderAddr != common.Address{}) { l = append(l, types.AccessTuple{ Address: opts.GasRefunderAddr, @@ -340,15 +360,23 @@ func AccessList(opts *AccessListOpts) types.AccessList { common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000004"), // CommonParameters.{maxRefundeeBalance, extraGasMargin, calldataCost, maxGasTip} common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000005"), // CommonParameters.{maxGasCost, maxSingleGasUsage} // allowedContracts[msg.sender]; for mainnet it's: "0x7686888b19bb7b75e46bb1aa328b65150743f4899443d722f0adf8e252ccda41". - common.Hash(arbutil.StorageSlotAddress(opts.SequencerInboxAddr.Bytes(), []byte{1})), + common.Hash(arbutil.PaddedKeccak256(opts.SequencerInboxAddr.Bytes(), []byte{1})), // allowedRefundees[refundee]; for mainnet it's: "0xe85fd79f89ff278fc57d40aecb7947873df9f0beac531c8f71a98f630e1eab62". - common.Hash(arbutil.StorageSlotAddress(opts.DataPosterAddr.Bytes(), []byte{2})), + common.Hash(arbutil.PaddedKeccak256(opts.DataPosterAddr.Bytes(), []byte{2})), }, }) } return l } +func intToBytes(val int) ([]byte, error) { + buf := new(bytes.Buffer) + if err := binary.Write(buf, binary.BigEndian, int64(val)); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + // checkRevert checks blocks with number in range [from, to] whether they // contain reverted batch_poster transaction. // It returns true if it finds batch posting needs to halt, which is true if a batch reverts @@ -987,7 +1015,18 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) if err != nil { return false, err } - tx, err := b.dataPoster.PostTransaction(ctx, firstMsgTime, nonce, newMeta, b.seqInboxAddr, data, gasLimit, new(big.Int)) + tx, err := b.dataPoster.PostTransaction(ctx, + firstMsgTime, + nonce, + newMeta, + b.seqInboxAddr, + data, + gasLimit, + new(big.Int), + b.accessList( + int(batchPosition.NextSeqNum), + int(b.building.segments.delayedMsg)), + ) if err != nil { return false, err } diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index e49a2194e..91bdf39d5 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -64,7 +64,6 @@ type DataPoster struct { nonce uint64 queue QueueStorage errorCount map[uint64]int // number of consecutive intermittent errors rbf-ing or sending, per nonce - accessList types.AccessList } type AttemptLocker interface { @@ -101,7 +100,6 @@ type DataPosterOpts struct { Config ConfigFetcher MetadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error) RedisKey string // Redis storage key - AccessList types.AccessList } func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, error) { @@ -152,7 +150,6 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro queue: queue, redisLock: opts.RedisLock, errorCount: make(map[uint64]int), - accessList: opts.AccessList, }, nil } @@ -343,7 +340,7 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u return newFeeCap, newTipCap, nil } -func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Time, nonce uint64, meta []byte, to common.Address, calldata []byte, gasLimit uint64, value *big.Int) (*types.Transaction, error) { +func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Time, nonce uint64, meta []byte, to common.Address, calldata []byte, gasLimit uint64, value *big.Int, accessList types.AccessList) (*types.Transaction, error) { p.mutex.Lock() defer p.mutex.Unlock() @@ -372,7 +369,7 @@ func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Tim To: &to, Value: value, Data: calldata, - AccessList: p.accessList, + AccessList: accessList, } fullTx, err := p.signer(p.sender, types.NewTx(&inner)) if err != nil { diff --git a/arbutil/hash.go b/arbutil/hash.go index 6966cc6df..faab6c655 100644 --- a/arbutil/hash.go +++ b/arbutil/hash.go @@ -2,15 +2,32 @@ package arbutil import ( "github.com/ethereum/go-ethereum/common" - "golang.org/x/crypto/sha3" + "github.com/ethereum/go-ethereum/crypto" ) -// StorageSlotAddress pads each argument to 32 bytes, concatenates and returns -// keccak256 hashe of the result. -func StorageSlotAddress(args ...[]byte) []byte { - hash := sha3.NewLegacyKeccak256() +// PaddedKeccak256 pads each argument to 32 bytes, concatenates and returns +// keccak256 hash of the result. +func PaddedKeccak256(args ...[]byte) []byte { + var data []byte for _, arg := range args { - hash.Write(common.BytesToHash(arg).Bytes()) + data = append(data, common.BytesToHash(arg).Bytes()...) } - return hash.Sum(nil) + return crypto.Keccak256(data) +} + +// SumBytes sums two byte slices and returns the result. +// If the sum of bytes are over 32 bytes, it return last 32. +func SumBytes(a, b []byte) []byte { + // Normalize lengths to hash length. + a = common.BytesToHash(a).Bytes() + b = common.BytesToHash(b).Bytes() + + sum := make([]byte, common.HashLength) + c := 0 + for i := common.HashLength - 1; i >= 0; i-- { + tmp := int(a[i]) + int(b[i]) + c + sum[i] = byte(tmp & 0xFF) + c = tmp >> 8 + } + return sum } diff --git a/arbutil/hash_test.go b/arbutil/hash_test.go index 639274653..f32a8ad6a 100644 --- a/arbutil/hash_test.go +++ b/arbutil/hash_test.go @@ -2,9 +2,12 @@ package arbutil import ( "bytes" + "encoding/binary" + "fmt" "testing" "github.com/ethereum/go-ethereum/common" + "github.com/google/go-cmp/cmp" ) func TestSlotAddress(t *testing.T) { @@ -39,7 +42,7 @@ func TestSlotAddress(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - got := StorageSlotAddress(tc.args...) + got := PaddedKeccak256(tc.args...) if !bytes.Equal(got, tc.want) { t.Errorf("slotAddress(%x) = %x, want %x", tc.args, got, tc.want) } @@ -47,3 +50,65 @@ func TestSlotAddress(t *testing.T) { } } + +func TestSumBytes(t *testing.T) { + for _, tc := range []struct { + desc string + a, b, want []byte + }{ + { + desc: "simple case", + a: []byte{0x0a, 0x0b}, + b: []byte{0x03, 0x04}, + want: common.HexToHash("0x0d0f").Bytes(), + }, + { + desc: "carry over last byte", + a: []byte{0x0a, 0xff}, + b: []byte{0x01}, + want: common.HexToHash("0x0b00").Bytes(), + }, + { + desc: "overflow", + a: common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").Bytes(), + b: []byte{0x01}, + want: common.HexToHash("0x00").Bytes(), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + got := SumBytes(tc.a, tc.b) + if diff := cmp.Diff(got, tc.want); diff != "" { + t.Errorf("SumBytes(%x, %x) = %x want: %x", tc.a, tc.b, got, tc.want) + } + }) + } +} + +func TestBrutforce(t *testing.T) { + M := map[common.Hash]bool{ + common.HexToHash("0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688"): true, + common.HexToHash("0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40"): true, + common.HexToHash("0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f"): true, + common.HexToHash("0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689"): true, + } + + for i := 0; i < 256; i++ { + for j := 0; j < 256; j++ { + addr := SumBytes(PaddedKeccak256(intToBytes(t, i)), intToBytes(t, j)) + if M[common.BytesToHash(addr)] { + t.Errorf("anodar yes, i: %v, j: %v, \taddr: %x", i, j, addr) + } + } + + } +} + +func intToBytes(t *testing.T, val int) []byte { + t.Helper() + buf := new(bytes.Buffer) + err := binary.Write(buf, binary.BigEndian, int64(val)) + if err != nil { + fmt.Println("binary.Write failed:", err) + } + return buf.Bytes() +} diff --git a/staker/validatorwallet/contract.go b/staker/validatorwallet/contract.go index 3ade358ce..302e4fb43 100644 --- a/staker/validatorwallet/contract.go +++ b/staker/validatorwallet/contract.go @@ -177,7 +177,7 @@ func (v *Contract) executeTransaction(ctx context.Context, tx *types.Transaction if err != nil { return nil, fmt.Errorf("getting gas for tx data: %w", err) } - return v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), data, gas, auth.Value) + return v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), data, gas, auth.Value, nil) } func (v *Contract) populateWallet(ctx context.Context, createIfMissing bool) error { @@ -288,7 +288,7 @@ func (v *Contract) ExecuteTransactions(ctx context.Context, builder *txbuilder.B if err != nil { return nil, fmt.Errorf("getting gas for tx data: %w", err) } - arbTx, err := v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), txData, gas, auth.Value) + arbTx, err := v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), txData, gas, auth.Value, nil) if err != nil { return nil, err } @@ -338,7 +338,7 @@ func (v *Contract) TimeoutChallenges(ctx context.Context, challenges []uint64) ( if err != nil { return nil, fmt.Errorf("getting gas for tx data: %w", err) } - return v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), data, gas, auth.Value) + return v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), data, gas, auth.Value, nil) } // gasForTxData returns auth.GasLimit if it's nonzero, otherwise returns estimate. diff --git a/staker/validatorwallet/eoa.go b/staker/validatorwallet/eoa.go index b2c9f68b5..d86181f42 100644 --- a/staker/validatorwallet/eoa.go +++ b/staker/validatorwallet/eoa.go @@ -95,7 +95,7 @@ func (w *EOA) postTransaction(ctx context.Context, baseTx *types.Transaction) (* return nil, err } gas := baseTx.Gas() + w.getExtraGas() - newTx, err := w.dataPoster.PostTransaction(ctx, time.Now(), nonce, nil, *baseTx.To(), baseTx.Data(), gas, baseTx.Value()) + newTx, err := w.dataPoster.PostTransaction(ctx, time.Now(), nonce, nil, *baseTx.To(), baseTx.Data(), gas, baseTx.Value(), nil) if err != nil { return nil, fmt.Errorf("post transaction: %w", err) } diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index c40a51a4c..a456dc5fe 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -84,7 +84,7 @@ func diffAccessList(accessed, al types.AccessList) string { for j := 0; j < len(accessed[i].StorageKeys); j++ { slot := accessed[i].StorageKeys[j] if _, ok := m[addr][slot]; !ok { - diff += fmt.Sprintf("storage slot: %q for contract: %v wasn't accessed", slot, addr) + diff += fmt.Sprintf("storage slot: %v for contract: %v wasn't accessed\n", slot, addr) } } } @@ -345,10 +345,12 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { t.Fatalf("Error creating access list: %v", err) } accessed := arbnode.AccessList(&arbnode.AccessListOpts{ - SequencerInboxAddr: l1Info.GetAddress("SequencerInbox"), - BridgeAddr: l1Info.GetAddress("Bridge"), - DataPosterAddr: seqOpts.From, - GasRefunderAddr: gasRefunderAddr, + SequencerInboxAddr: l1Info.GetAddress("SequencerInbox"), + BridgeAddr: l1Info.GetAddress("Bridge"), + DataPosterAddr: seqOpts.From, + GasRefunderAddr: gasRefunderAddr, + SequencerInboxAccs: len(blockStates), + AfterDelayedMessagesRead: 1, }) if diff := diffAccessList(accessed, *wantAL); diff != "" { t.Errorf("Access list mistmatch:\n%s\n", diff) From e79daea2c1115cd087638ac6f525224f2a78f7f7 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 9 Oct 2023 16:10:14 +0200 Subject: [PATCH 227/775] drop remnant from debugging --- arbnode/batch_poster.go | 2 +- arbutil/hash_test.go | 31 ------------------------------- 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index af054e7a5..051bac0af 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -359,7 +359,7 @@ func AccessList(opts *AccessListOpts) types.AccessList { StorageKeys: []common.Hash{ common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000004"), // CommonParameters.{maxRefundeeBalance, extraGasMargin, calldataCost, maxGasTip} common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000005"), // CommonParameters.{maxGasCost, maxSingleGasUsage} - // allowedContracts[msg.sender]; for mainnet it's: "0x7686888b19bb7b75e46bb1aa328b65150743f4899443d722f0adf8e252ccda41". + // allowedContracts[msg.sender]; for mainnet it's: "0x7686888b19bb7b75e46bb1aa328b65150743f4899443d722f0adf8e252ccda41". common.Hash(arbutil.PaddedKeccak256(opts.SequencerInboxAddr.Bytes(), []byte{1})), // allowedRefundees[refundee]; for mainnet it's: "0xe85fd79f89ff278fc57d40aecb7947873df9f0beac531c8f71a98f630e1eab62". common.Hash(arbutil.PaddedKeccak256(opts.DataPosterAddr.Bytes(), []byte{2})), diff --git a/arbutil/hash_test.go b/arbutil/hash_test.go index f32a8ad6a..2b93353d0 100644 --- a/arbutil/hash_test.go +++ b/arbutil/hash_test.go @@ -2,8 +2,6 @@ package arbutil import ( "bytes" - "encoding/binary" - "fmt" "testing" "github.com/ethereum/go-ethereum/common" @@ -83,32 +81,3 @@ func TestSumBytes(t *testing.T) { }) } } - -func TestBrutforce(t *testing.T) { - M := map[common.Hash]bool{ - common.HexToHash("0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688"): true, - common.HexToHash("0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40"): true, - common.HexToHash("0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f"): true, - common.HexToHash("0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689"): true, - } - - for i := 0; i < 256; i++ { - for j := 0; j < 256; j++ { - addr := SumBytes(PaddedKeccak256(intToBytes(t, i)), intToBytes(t, j)) - if M[common.BytesToHash(addr)] { - t.Errorf("anodar yes, i: %v, j: %v, \taddr: %x", i, j, addr) - } - } - - } -} - -func intToBytes(t *testing.T, val int) []byte { - t.Helper() - buf := new(bytes.Buffer) - err := binary.Write(buf, binary.BigEndian, int64(val)) - if err != nil { - fmt.Println("binary.Write failed:", err) - } - return buf.Bytes() -} From a2a47e85dd729c681101a572fb5be732bc10a2e6 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 9 Oct 2023 15:35:45 -0500 Subject: [PATCH 228/775] add secondary feed to go relay --- broadcastclient/broadcastclient.go | 6 +- broadcastclients/broadcastclients.go | 135 ++++++++++++++++++++++----- 2 files changed, 116 insertions(+), 25 deletions(-) diff --git a/broadcastclient/broadcastclient.go b/broadcastclient/broadcastclient.go index 2649c8819..a7ee269a4 100644 --- a/broadcastclient/broadcastclient.go +++ b/broadcastclient/broadcastclient.go @@ -69,6 +69,7 @@ type Config struct { RequireFeedVersion bool `koanf:"require-feed-version" reload:"hot"` Timeout time.Duration `koanf:"timeout" reload:"hot"` URL []string `koanf:"url"` + SecondaryURL []string `koanf:"secondary-url"` Verify signature.VerifierConfig `koanf:"verify"` EnableCompression bool `koanf:"enable-compression" reload:"hot"` } @@ -85,7 +86,8 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { f.Bool(prefix+".require-chain-id", DefaultConfig.RequireChainId, "require chain id to be present on connect") f.Bool(prefix+".require-feed-version", DefaultConfig.RequireFeedVersion, "require feed version to be present on connect") f.Duration(prefix+".timeout", DefaultConfig.Timeout, "duration to wait before timing out connection to sequencer feed") - f.StringSlice(prefix+".url", DefaultConfig.URL, "URL of sequencer feed source") + f.StringSlice(prefix+".url", DefaultConfig.URL, "list of primary URLs of sequencer feed source") + f.StringSlice(prefix+".secondary-url", DefaultConfig.SecondaryURL, "list of secondary URLs of sequencer feed source") signature.FeedVerifierConfigAddOptions(prefix+".verify", f) f.Bool(prefix+".enable-compression", DefaultConfig.EnableCompression, "enable per message deflate compression support") } @@ -97,6 +99,7 @@ var DefaultConfig = Config{ RequireFeedVersion: false, Verify: signature.DefultFeedVerifierConfig, URL: []string{""}, + SecondaryURL: []string{}, Timeout: 20 * time.Second, EnableCompression: true, } @@ -108,6 +111,7 @@ var DefaultTestConfig = Config{ RequireFeedVersion: false, Verify: signature.DefultFeedVerifierConfig, URL: []string{""}, + SecondaryURL: []string{}, Timeout: 200 * time.Millisecond, EnableCompression: true, } diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index 74596bb08..873d6be03 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -6,16 +6,42 @@ package broadcastclients import ( "context" "sync/atomic" + "time" "github.com/ethereum/go-ethereum/log" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcastclient" + "github.com/offchainlabs/nitro/broadcaster" "github.com/offchainlabs/nitro/util/contracts" + "github.com/offchainlabs/nitro/util/stopwaiter" ) +const MAX_FEED_INACTIVE_TIME = time.Second * 6 +const ROUTER_QUEUE_SIZE = 1024 + +type Router struct { + stopwaiter.StopWaiter + messageChan chan broadcaster.BroadcastFeedMessage + confirmedSequenceNumberChan chan arbutil.MessageIndex + + forwardTxStreamer broadcastclient.TransactionStreamerInterface + forwardConfirmationChan chan arbutil.MessageIndex +} + +func (r *Router) AddBroadcastMessages(feedMessages []*broadcaster.BroadcastFeedMessage) error { + for _, feedMessage := range feedMessages { + r.messageChan <- *feedMessage + } + return nil +} + type BroadcastClients struct { - clients []*broadcastclient.BroadcastClient + primaryClients []*broadcastclient.BroadcastClient + secondaryClients []*broadcastclient.BroadcastClient + numOfStartedSecondary int + + router *Router // Use atomic access connected int32 @@ -31,34 +57,55 @@ func NewBroadcastClients( addrVerifier contracts.AddressVerifierInterface, ) (*BroadcastClients, error) { config := configFetcher() - urlCount := len(config.URL) - if urlCount <= 0 { + if len(config.URL) == 0 && len(config.SecondaryURL) == 0 { return nil, nil } - clients := BroadcastClients{} - clients.clients = make([]*broadcastclient.BroadcastClient, 0, urlCount) + clients := BroadcastClients{ + router: &Router{ + messageChan: make(chan broadcaster.BroadcastFeedMessage, ROUTER_QUEUE_SIZE), + confirmedSequenceNumberChan: make(chan arbutil.MessageIndex, ROUTER_QUEUE_SIZE), + forwardTxStreamer: txStreamer, + forwardConfirmationChan: confirmedSequenceNumberListener, + }, + } var lastClientErr error - for _, address := range config.URL { - client, err := broadcastclient.NewBroadcastClient( - configFetcher, - address, - l2ChainId, - currentMessageCount, - txStreamer, - confirmedSequenceNumberListener, - fatalErrChan, - addrVerifier, - func(delta int32) { clients.adjustCount(delta) }, - ) - if err != nil { - lastClientErr = err - log.Warn("init broadcast client failed", "address", address) + makeFeeds := func(url []string) []*broadcastclient.BroadcastClient { + feeds := make([]*broadcastclient.BroadcastClient, 0, len(url)) + for _, address := range url { + client, err := broadcastclient.NewBroadcastClient( + configFetcher, + address, + l2ChainId, + currentMessageCount, + clients.router, + clients.router.confirmedSequenceNumberChan, + fatalErrChan, + addrVerifier, + func(delta int32) { clients.adjustCount(delta) }, + ) + if err != nil { + lastClientErr = err + log.Warn("init broadcast client failed", "address", address) + continue + } + feeds = append(feeds, client) } - clients.clients = append(clients.clients, client) + return feeds } - if len(clients.clients) == 0 { + + clients.primaryClients = makeFeeds(config.URL) + clients.secondaryClients = makeFeeds(config.SecondaryURL) + + if len(clients.primaryClients) == 0 && len(clients.secondaryClients) == 0 { log.Error("no connected feed on startup, last error: %w", lastClientErr) + return nil, nil + } + + // have atleast one primary client + if len(clients.primaryClients) == 0 { + clients.primaryClients = append(clients.primaryClients, clients.secondaryClients[0]) + clients.secondaryClients = clients.secondaryClients[1:] } return &clients, nil @@ -72,12 +119,52 @@ func (bcs *BroadcastClients) adjustCount(delta int32) { } func (bcs *BroadcastClients) Start(ctx context.Context) { - for _, client := range bcs.clients { + bcs.router.StopWaiter.Start(ctx, bcs.router) + + for _, client := range bcs.primaryClients { client.Start(ctx) } + + bcs.router.LaunchThread(func(ctx context.Context) { + startNewFeedTimer := time.NewTicker(MAX_FEED_INACTIVE_TIME) + defer startNewFeedTimer.Stop() + for { + select { + case <-ctx.Done(): + return + case cs := <-bcs.router.confirmedSequenceNumberChan: + startNewFeedTimer.Stop() + bcs.router.forwardConfirmationChan <- cs + startNewFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + case msg := <-bcs.router.messageChan: + startNewFeedTimer.Stop() + if err := bcs.router.forwardTxStreamer.AddBroadcastMessages([]*broadcaster.BroadcastFeedMessage{&msg}); err != nil { + log.Error("Error routing message from Sequencer Feed", "err", err) + } + startNewFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + case <-startNewFeedTimer.C: + // failed to get messages from primary feed for ~5 seconds, start a new feed + bcs.StartSecondaryFeed(ctx) + } + } + }) } + +func (bcs *BroadcastClients) StartSecondaryFeed(ctx context.Context) { + if bcs.numOfStartedSecondary < len(bcs.secondaryClients) { + client := bcs.secondaryClients[bcs.numOfStartedSecondary] + bcs.numOfStartedSecondary += 1 + client.Start(ctx) + } else { + log.Warn("failed to start a new secondary feed all available secondary feeds were started") + } +} + func (bcs *BroadcastClients) StopAndWait() { - for _, client := range bcs.clients { + for _, client := range bcs.primaryClients { client.StopAndWait() } + for i := 0; i < bcs.numOfStartedSecondary; i++ { + bcs.secondaryClients[i].StopAndWait() + } } From a65d5b58db52441cad55ea39a63248d27614099b Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 9 Oct 2023 18:25:34 -0500 Subject: [PATCH 229/775] code refactor --- arbnode/node.go | 2 ++ broadcastclients/broadcastclients.go | 6 +++--- relay/relay.go | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index bf57b1c00..1b42880d3 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -36,6 +36,7 @@ import ( "github.com/offchainlabs/nitro/das" "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/execution/gethexec" + "github.com/offchainlabs/nitro/relay" "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/challengegen" "github.com/offchainlabs/nitro/solgen/go/ospgen" @@ -643,6 +644,7 @@ func createNodeImpl( nil, fatalErrChan, bpVerifier, + relay.ConfigDefault.Queue, ) if err != nil { return nil, err diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index 873d6be03..a92c3b736 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -18,7 +18,6 @@ import ( ) const MAX_FEED_INACTIVE_TIME = time.Second * 6 -const ROUTER_QUEUE_SIZE = 1024 type Router struct { stopwaiter.StopWaiter @@ -55,6 +54,7 @@ func NewBroadcastClients( confirmedSequenceNumberListener chan arbutil.MessageIndex, fatalErrChan chan error, addrVerifier contracts.AddressVerifierInterface, + queueCapcity int, ) (*BroadcastClients, error) { config := configFetcher() if len(config.URL) == 0 && len(config.SecondaryURL) == 0 { @@ -63,8 +63,8 @@ func NewBroadcastClients( clients := BroadcastClients{ router: &Router{ - messageChan: make(chan broadcaster.BroadcastFeedMessage, ROUTER_QUEUE_SIZE), - confirmedSequenceNumberChan: make(chan arbutil.MessageIndex, ROUTER_QUEUE_SIZE), + messageChan: make(chan broadcaster.BroadcastFeedMessage, queueCapcity), + confirmedSequenceNumberChan: make(chan arbutil.MessageIndex, queueCapcity), forwardTxStreamer: txStreamer, forwardConfirmationChan: confirmedSequenceNumberListener, }, diff --git a/relay/relay.go b/relay/relay.go index bb0725119..26894c0a3 100644 --- a/relay/relay.go +++ b/relay/relay.go @@ -58,6 +58,7 @@ func NewRelay(config *Config, feedErrChan chan error) (*Relay, error) { confirmedSequenceNumberListener, feedErrChan, nil, + config.Queue, ) if err != nil { return nil, err From 226bd1cd129fb34fbb17291327cba43b8aba3a38 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 10 Oct 2023 15:30:41 +0200 Subject: [PATCH 230/775] Align with latest RollupCretor api --- Dockerfile | 2 +- arbnode/node.go | 106 ++++++++++++++++++++++++++++++++---- cmd/chaininfo/chain_info.go | 1 + cmd/deploy/deploy.go | 5 +- 4 files changed, 101 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0698fb60e..b05cb3d4d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ RUN apt-get update && \ apt-get install -y git python3 make g++ WORKDIR /workspace COPY contracts/package.json contracts/yarn.lock contracts/ -RUN cd contracts && yarn install --ignore-optional +RUN cd contracts && yarn install COPY contracts contracts/ COPY Makefile . RUN NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-solidity diff --git a/arbnode/node.go b/arbnode/node.go index 4ee454727..9d4311236 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -64,6 +64,91 @@ func andTxSucceeded(ctx context.Context, l1Reader *headerreader.HeaderReader, tx return nil } +func deployBridgeCreator(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts, maxDataSize *big.Int) (common.Address, error) { + client := l1Reader.Client() + + /// deploy eth based templates + bridgeTemplate, tx, _, err := bridgegen.DeployBridge(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("bridge deploy error: %w", err) + } + + // maxDataSize := big.NewInt(117964) + seqInboxTemplate, tx, _, err := bridgegen.DeploySequencerInbox(auth, client, maxDataSize) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("sequencer inbox deploy error: %w", err) + } + + inboxTemplate, tx, _, err := bridgegen.DeployInbox(auth, client, maxDataSize) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("inbox deploy error: %w", err) + } + + rollupEventBridgeTemplate, tx, _, err := rollupgen.DeployRollupEventInbox(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("rollup event bridge deploy error: %w", err) + } + + outboxTemplate, tx, _, err := bridgegen.DeployOutbox(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("outbox deploy error: %w", err) + } + + ethBasedTemplates := rollupgen.BridgeCreatorBridgeContracts{ + Bridge: bridgeTemplate, + SequencerInbox: seqInboxTemplate, + Inbox: inboxTemplate, + RollupEventInbox:rollupEventBridgeTemplate, + Outbox: outboxTemplate, + } + + /// deploy ERC20 based templates + erc20BridgeTemplate, tx, _, err := bridgegen.DeployERC20Bridge(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("bridge deploy error: %w", err) + } + + erc20InboxTemplate, tx, _, err := bridgegen.DeployERC20Inbox(auth, client, maxDataSize) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("inbox deploy error: %w", err) + } + + erc20RollupEventBridgeTemplate, tx, _, err := rollupgen.DeployERC20RollupEventInbox(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("rollup event bridge deploy error: %w", err) + } + + erc20OutboxTemplate, tx, _, err := bridgegen.DeployERC20Outbox(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("outbox deploy error: %w", err) + } + + erc20BasedTemplates := rollupgen.BridgeCreatorBridgeContracts{ + Bridge: erc20BridgeTemplate, + SequencerInbox: seqInboxTemplate, + Inbox: erc20InboxTemplate, + RollupEventInbox:erc20RollupEventBridgeTemplate, + Outbox: erc20OutboxTemplate, + } + + bridgeCreatorAddr, tx, _, err := rollupgen.DeployBridgeCreator(auth, client, ethBasedTemplates, erc20BasedTemplates) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("bridge creator deploy error: %w", err) + } + + return bridgeCreatorAddr, nil +} + func deployChallengeFactory(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts) (common.Address, common.Address, error) { client := l1Reader.Client() osp0, tx, _, err := ospgen.DeployOneStepProver0(auth, client) @@ -105,11 +190,8 @@ func deployChallengeFactory(ctx context.Context, l1Reader *headerreader.HeaderRe return ospEntryAddr, challengeManagerAddr, nil } -func deployRollupCreator(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts) (*rollupgen.RollupCreator, common.Address, common.Address, common.Address, error) { - // deploying bridge creator takes ~14.2 million gas - auth.GasLimit = uint64(15000000) - bridgeCreator, tx, _, err := rollupgen.DeployBridgeCreator(auth, l1Reader.Client()) - err = andTxSucceeded(ctx, l1Reader, tx, err) +func deployRollupCreator(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts, maxDataSize *big.Int) (*rollupgen.RollupCreator, common.Address, common.Address, common.Address, error) { + bridgeCreator, err := deployBridgeCreator(ctx, l1Reader, auth, maxDataSize) if err != nil { return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("bridge creator deploy error: %w", err) } @@ -161,7 +243,6 @@ func deployRollupCreator(ctx context.Context, l1Reader *headerreader.HeaderReade return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("deploy helper creator deploy error: %w", err) } - tx, err = rollupCreator.SetTemplates( auth, bridgeCreator, @@ -209,12 +290,12 @@ func GenerateRollupConfig(prod bool, wasmModuleRoot common.Hash, rollupOwner com } } -func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReader, deployAuth *bind.TransactOpts, batchPoster common.Address, authorizeValidators uint64, config rollupgen.Config, nativeToken common.Address) (*chaininfo.RollupAddresses, error) { +func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReader, deployAuth *bind.TransactOpts, batchPoster common.Address, authorizeValidators uint64, config rollupgen.Config, nativeToken common.Address, maxDataSize *big.Int) (*chaininfo.RollupAddresses, error) { if config.WasmModuleRoot == (common.Hash{}) { return nil, errors.New("no machine specified") } - rollupCreator, _, validatorUtils, validatorWalletCreator, err := deployRollupCreator(ctx, parentChainReader, deployAuth) + rollupCreator, _, validatorUtils, validatorWalletCreator, err := deployRollupCreator(ctx, parentChainReader, deployAuth, maxDataSize) if err != nil { return nil, fmt.Errorf("error deploying rollup creator: %w", err) } @@ -224,15 +305,16 @@ func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReade validatorAddrs = append(validatorAddrs, crypto.CreateAddress(validatorWalletCreator, i)) } - // 0.1 gwei - maxFeePerGas := big.NewInt(100000000) + deployUtilityFactories := false + maxFeePerGas := big.NewInt(0) // needed when utility factories are deployed tx, err := rollupCreator.CreateRollup( deployAuth, config, batchPoster, validatorAddrs, + maxDataSize, nativeToken, - false, + deployUtilityFactories, maxFeePerGas, ) if err != nil { @@ -253,6 +335,8 @@ func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReade SequencerInbox: info.SequencerInbox, DeployedAt: receipt.BlockNumber.Uint64(), Rollup: info.RollupAddress, + NativeToken: nativeToken, + UpgradeExecutor: info.UpgradeExecutor, ValidatorUtils: validatorUtils, ValidatorWalletCreator: validatorWalletCreator, }, nil diff --git a/cmd/chaininfo/chain_info.go b/cmd/chaininfo/chain_info.go index 2902e9611..cc1332151 100644 --- a/cmd/chaininfo/chain_info.go +++ b/cmd/chaininfo/chain_info.go @@ -107,6 +107,7 @@ type RollupAddresses struct { SequencerInbox common.Address `json:"sequencer-inbox"` Rollup common.Address `json:"rollup"` NativeToken common.Address `json:"native-token"` + UpgradeExecutor common.Address `json:"upgrade-executor"` ValidatorUtils common.Address `json:"validator-utils"` ValidatorWalletCreator common.Address `json:"validator-wallet-creator"` DeployedAt uint64 `json:"deployed-at"` diff --git a/cmd/deploy/deploy.go b/cmd/deploy/deploy.go index 4da3ae765..d726ad21f 100644 --- a/cmd/deploy/deploy.go +++ b/cmd/deploy/deploy.go @@ -40,7 +40,8 @@ func main() { deployAccount := flag.String("l1DeployAccount", "", "l1 seq account to use (default is first account in keystore)") ownerAddressString := flag.String("ownerAddress", "", "the rollup owner's address") sequencerAddressString := flag.String("sequencerAddress", "", "the sequencer's address") - nativeTokenAddressString := flag.String("nativeTokenAddress", "", "address of the ERC20 token which is used as native L2 currency") + nativeTokenAddressString := flag.String("nativeTokenAddress", "0x0000000000000000000000000000000000000000", "address of the ERC20 token which is used as native L2 currency") + maxDataSizeUint := flag.Uint64("maxDataSize", 117964, "maximum size of data") loserEscrowAddressString := flag.String("loserEscrowAddress", "", "the address which half of challenge loser's funds accumulate at") wasmmoduleroot := flag.String("wasmmoduleroot", "", "WASM module root hash") wasmrootpath := flag.String("wasmrootpath", "", "path to machine folders") @@ -56,6 +57,7 @@ func main() { prod := flag.Bool("prod", false, "Whether to configure the rollup for production or testing") flag.Parse() l1ChainId := new(big.Int).SetUint64(*l1ChainIdUint) + maxDataSize := new(big.Int).SetUint64(*maxDataSizeUint) if *prod { if *wasmmoduleroot == "" { @@ -147,6 +149,7 @@ func main() { *authorizevalidators, arbnode.GenerateRollupConfig(*prod, moduleRoot, ownerAddress, &chainConfig, chainConfigJson, loserEscrowAddress), nativeToken, + maxDataSize, ) if err != nil { flag.Usage() From 6a3c33741c5224ac0d9dd9299c79f7e1216e7c0e Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 10 Oct 2023 09:52:18 -0500 Subject: [PATCH 231/775] Revert "code refactor" This reverts commit a65d5b58db52441cad55ea39a63248d27614099b. --- arbnode/node.go | 2 -- broadcastclients/broadcastclients.go | 6 +++--- relay/relay.go | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 1b42880d3..bf57b1c00 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -36,7 +36,6 @@ import ( "github.com/offchainlabs/nitro/das" "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/execution/gethexec" - "github.com/offchainlabs/nitro/relay" "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/challengegen" "github.com/offchainlabs/nitro/solgen/go/ospgen" @@ -644,7 +643,6 @@ func createNodeImpl( nil, fatalErrChan, bpVerifier, - relay.ConfigDefault.Queue, ) if err != nil { return nil, err diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index a92c3b736..873d6be03 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -18,6 +18,7 @@ import ( ) const MAX_FEED_INACTIVE_TIME = time.Second * 6 +const ROUTER_QUEUE_SIZE = 1024 type Router struct { stopwaiter.StopWaiter @@ -54,7 +55,6 @@ func NewBroadcastClients( confirmedSequenceNumberListener chan arbutil.MessageIndex, fatalErrChan chan error, addrVerifier contracts.AddressVerifierInterface, - queueCapcity int, ) (*BroadcastClients, error) { config := configFetcher() if len(config.URL) == 0 && len(config.SecondaryURL) == 0 { @@ -63,8 +63,8 @@ func NewBroadcastClients( clients := BroadcastClients{ router: &Router{ - messageChan: make(chan broadcaster.BroadcastFeedMessage, queueCapcity), - confirmedSequenceNumberChan: make(chan arbutil.MessageIndex, queueCapcity), + messageChan: make(chan broadcaster.BroadcastFeedMessage, ROUTER_QUEUE_SIZE), + confirmedSequenceNumberChan: make(chan arbutil.MessageIndex, ROUTER_QUEUE_SIZE), forwardTxStreamer: txStreamer, forwardConfirmationChan: confirmedSequenceNumberListener, }, diff --git a/relay/relay.go b/relay/relay.go index 26894c0a3..bb0725119 100644 --- a/relay/relay.go +++ b/relay/relay.go @@ -58,7 +58,6 @@ func NewRelay(config *Config, feedErrChan chan error) (*Relay, error) { confirmedSequenceNumberListener, feedErrChan, nil, - config.Queue, ) if err != nil { return nil, err From 6b2174aca1eafb13bdea77656e32dda253b87148 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Tue, 10 Oct 2023 19:36:28 +0200 Subject: [PATCH 232/775] Use big.Int for bytes sum and int to byte conversion --- arbnode/batch_poster.go | 17 +---------------- arbutil/hash.go | 17 +++++------------ 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 051bac0af..76ff8e6a5 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -6,7 +6,6 @@ package arbnode import ( "bytes" "context" - "encoding/binary" "encoding/hex" "errors" "fmt" @@ -343,13 +342,7 @@ func AccessList(opts *AccessListOpts) types.AccessList { {7, opts.SequencerInboxAccs}, // - sequencerInboxAccs.push(...); (keccak256(7, sequencerInboxAccs.length)) {6, opts.AfterDelayedMessagesRead - 1}, // - delayedInboxAccs[afterDelayedMessagesRead - 1]; (keccak256(6, afterDelayedMessagesRead - 1)) } { - - sia, err := intToBytes(v.val) - if err != nil { - log.Error("Error converting sequencer inbox accs to bytes", "err", err, "sequencerInboxAccs", opts.SequencerInboxAccs) - continue - } - sb := arbutil.SumBytes(arbutil.PaddedKeccak256([]byte{byte(v.slotIdx)}), sia) + sb := arbutil.SumBytes(arbutil.PaddedKeccak256([]byte{byte(v.slotIdx)}), big.NewInt(int64(v.val)).Bytes()) l[1].StorageKeys = append(l[1].StorageKeys, common.Hash(sb)) } @@ -369,14 +362,6 @@ func AccessList(opts *AccessListOpts) types.AccessList { return l } -func intToBytes(val int) ([]byte, error) { - buf := new(bytes.Buffer) - if err := binary.Write(buf, binary.BigEndian, int64(val)); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - // checkRevert checks blocks with number in range [from, to] whether they // contain reverted batch_poster transaction. // It returns true if it finds batch posting needs to halt, which is true if a batch reverts diff --git a/arbutil/hash.go b/arbutil/hash.go index faab6c655..c6e91c8eb 100644 --- a/arbutil/hash.go +++ b/arbutil/hash.go @@ -1,6 +1,8 @@ package arbutil import ( + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ) @@ -18,16 +20,7 @@ func PaddedKeccak256(args ...[]byte) []byte { // SumBytes sums two byte slices and returns the result. // If the sum of bytes are over 32 bytes, it return last 32. func SumBytes(a, b []byte) []byte { - // Normalize lengths to hash length. - a = common.BytesToHash(a).Bytes() - b = common.BytesToHash(b).Bytes() - - sum := make([]byte, common.HashLength) - c := 0 - for i := common.HashLength - 1; i >= 0; i-- { - tmp := int(a[i]) + int(b[i]) + c - sum[i] = byte(tmp & 0xFF) - c = tmp >> 8 - } - return sum + A := big.NewInt(0).SetBytes(a) + B := big.NewInt(0).SetBytes(b) + return common.BytesToHash((A.Add(A, B)).Bytes()).Bytes() } From 30f7d2c7d5fd73e082b9886e4fb35f530baeb7bb Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 10 Oct 2023 23:11:11 +0530 Subject: [PATCH 233/775] minor fix --- arbnode/node.go | 3 --- cmd/nitro/nitro.go | 1 + execution/gethexec/node.go | 1 + 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index f4c33f924..5d06264b6 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -361,9 +361,6 @@ var ConfigDefault = Config{ DelayedSequencer: DefaultDelayedSequencerConfig, BatchPoster: DefaultBatchPosterConfig, MessagePruner: DefaultMessagePrunerConfig, - ForwardingTarget: "", - Forwarder: execution.DefaultNodeForwarderConfig, - TxPreChecker: execution.DefaultTxPreCheckerConfig, BlockValidator: staker.DefaultBlockValidatorConfig, Feed: broadcastclient.FeedConfigDefault, Staker: staker.DefaultL1ValidatorConfig, diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 60295d366..285cc3fe8 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -591,6 +591,7 @@ type NodeConfig struct { var NodeConfigDefault = NodeConfig{ Conf: genericconf.ConfConfigDefault, Node: arbnode.ConfigDefault, + Execution: gethexec.ConfigDefault, Validation: valnode.DefaultValidationConfig, ParentChain: conf.L1ConfigDefault, Chain: conf.L2ConfigDefault, diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index b29309cdb..1068dda96 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -91,6 +91,7 @@ var ConfigDefault = Config{ TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second Caching: DefaultCachingConfig, Dangerous: DefaultDangerousConfig, + Forwarder: DefaultNodeForwarderConfig, } func ConfigDefaultNonSequencerTest() *Config { From 812bda8b3abff2f690d9ebf8495d1d1ef08d3b11 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Tue, 10 Oct 2023 15:32:18 -0700 Subject: [PATCH 234/775] Add new metrics for inbox The following metrics are added to track the state currently read from inbox: * arb_inbox_batch * arb_inbox_message --- arbnode/inbox_tracker.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arbnode/inbox_tracker.go b/arbnode/inbox_tracker.go index c82e45fbe..414a9c94a 100644 --- a/arbnode/inbox_tracker.go +++ b/arbnode/inbox_tracker.go @@ -15,7 +15,9 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" + "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbstate" "github.com/offchainlabs/nitro/arbutil" @@ -24,6 +26,11 @@ import ( "github.com/offchainlabs/nitro/util/containers" ) +var ( + inboxBatchGauge = metrics.NewRegisteredGauge("arb/inbox/batch", nil) + inboxMessageGauge = metrics.NewRegisteredGauge("arb/inbox/message", nil) +) + type InboxTracker struct { db ethdb.Database txStreamer *TransactionStreamer @@ -676,6 +683,8 @@ func (t *InboxTracker) AddSequencerBatches(ctx context.Context, client arbutil.L "l1Block", latestL1Block, "l1Timestamp", time.Unix(int64(latestTimestamp), 0), ) + inboxBatchGauge.Update(int64(pos)) + inboxMessageGauge.Update(int64(newMessageCount)) if t.validator != nil { t.validator.ReorgToBatchCount(startPos) From cef0d56a75c82ae97914a67c07d4a23d0d84370a Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 10 Oct 2023 20:14:17 -0300 Subject: [PATCH 235/775] Fix typo and let potuz have a nitro PR --- staker/block_validator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staker/block_validator.go b/staker/block_validator.go index 94bc2a080..108d6d1d4 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -750,7 +750,7 @@ func (v *BlockValidator) iterativeValidationProgress(ctx context.Context, ignore } else if reorg != nil { err := v.Reorg(ctx, *reorg) if err != nil { - log.Error("error trying to rorg validation", "pos", *reorg-1, "err", err) + log.Error("error trying to reorg validation", "pos", *reorg-1, "err", err) v.possiblyFatal(err) } } From a778d5748b857595c1b055d5b8a1b8b630b3377c Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Tue, 10 Oct 2023 16:57:30 -0700 Subject: [PATCH 236/775] Update metric names * arb_inbox_latest_batch * arb_inbox_latest_batch_message --- arbnode/inbox_tracker.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arbnode/inbox_tracker.go b/arbnode/inbox_tracker.go index 414a9c94a..72e4ba288 100644 --- a/arbnode/inbox_tracker.go +++ b/arbnode/inbox_tracker.go @@ -27,8 +27,8 @@ import ( ) var ( - inboxBatchGauge = metrics.NewRegisteredGauge("arb/inbox/batch", nil) - inboxMessageGauge = metrics.NewRegisteredGauge("arb/inbox/message", nil) + inboxLatestBatchGauge = metrics.NewRegisteredGauge("arb/inbox/latest/batch", nil) + inboxLatestBatchMessageGauge = metrics.NewRegisteredGauge("arb/inbox/latest/batch/message", nil) ) type InboxTracker struct { @@ -683,8 +683,8 @@ func (t *InboxTracker) AddSequencerBatches(ctx context.Context, client arbutil.L "l1Block", latestL1Block, "l1Timestamp", time.Unix(int64(latestTimestamp), 0), ) - inboxBatchGauge.Update(int64(pos)) - inboxMessageGauge.Update(int64(newMessageCount)) + inboxLatestBatchGauge.Update(int64(pos)) + inboxLatestBatchMessageGauge.Update(int64(newMessageCount)) if t.validator != nil { t.validator.ReorgToBatchCount(startPos) From 4579b57d1cc52d9f9a6d643d3e9f6cbce8a0cdad Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Wed, 11 Oct 2023 12:38:57 +0200 Subject: [PATCH 237/775] Use options struct for batchposter to make callsites more readable --- arbnode/batch_poster.go | 60 ++++++++++++++++++------------- arbnode/node.go | 12 ++++++- system_tests/batch_poster_test.go | 16 ++++++++- 3 files changed, 62 insertions(+), 26 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index acf655e4c..77a839b70 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -217,68 +217,80 @@ var TestBatchPosterConfig = BatchPosterConfig{ L1BlockBoundBypass: time.Hour, } -func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader *headerreader.HeaderReader, inbox *InboxTracker, streamer *TransactionStreamer, syncMonitor *SyncMonitor, config BatchPosterConfigFetcher, deployInfo *chaininfo.RollupAddresses, transactOpts *bind.TransactOpts, daWriter das.DataAvailabilityServiceWriter) (*BatchPoster, error) { - seqInbox, err := bridgegen.NewSequencerInbox(deployInfo.SequencerInbox, l1Reader.Client()) +type BatchPosterOpts struct { + DataPosterDB ethdb.Database + L1Reader *headerreader.HeaderReader + Inbox *InboxTracker + Streamer *TransactionStreamer + SyncMonitor *SyncMonitor + Config BatchPosterConfigFetcher + DeployInfo *chaininfo.RollupAddresses + TransactOpts *bind.TransactOpts + DAWriter das.DataAvailabilityServiceWriter +} + +func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, error) { + seqInbox, err := bridgegen.NewSequencerInbox(opts.DeployInfo.SequencerInbox, opts.L1Reader.Client()) if err != nil { return nil, err } - bridge, err := bridgegen.NewBridge(deployInfo.Bridge, l1Reader.Client()) + bridge, err := bridgegen.NewBridge(opts.DeployInfo.Bridge, opts.L1Reader.Client()) if err != nil { return nil, err } - if err = config().Validate(); err != nil { + if err = opts.Config().Validate(); err != nil { return nil, err } seqInboxABI, err := bridgegen.SequencerInboxMetaData.GetAbi() if err != nil { return nil, err } - redisClient, err := redisutil.RedisClientFromURL(config().RedisUrl) + redisClient, err := redisutil.RedisClientFromURL(opts.Config().RedisUrl) if err != nil { return nil, err } redisLockConfigFetcher := func() *redislock.SimpleCfg { - simpleRedisLockConfig := config().RedisLock + simpleRedisLockConfig := opts.Config().RedisLock simpleRedisLockConfig.Key = batchPosterSimpleRedisLockKey return &simpleRedisLockConfig } - redisLock, err := redislock.NewSimple(redisClient, redisLockConfigFetcher, func() bool { return syncMonitor.Synced() }) + redisLock, err := redislock.NewSimple(redisClient, redisLockConfigFetcher, func() bool { return opts.SyncMonitor.Synced() }) if err != nil { return nil, err } b := &BatchPoster{ - l1Reader: l1Reader, - inbox: inbox, - streamer: streamer, - syncMonitor: syncMonitor, - config: config, + l1Reader: opts.L1Reader, + inbox: opts.Inbox, + streamer: opts.Streamer, + syncMonitor: opts.SyncMonitor, + config: opts.Config, bridge: bridge, seqInbox: seqInbox, seqInboxABI: seqInboxABI, - seqInboxAddr: deployInfo.SequencerInbox, - gasRefunderAddr: config().gasRefunder, - bridgeAddr: deployInfo.Bridge, - daWriter: daWriter, + seqInboxAddr: opts.DeployInfo.SequencerInbox, + gasRefunderAddr: opts.Config().gasRefunder, + bridgeAddr: opts.DeployInfo.Bridge, + daWriter: opts.DAWriter, redisLock: redisLock, accessList: func(SequencerInboxAccs, AfterDelayedMessagesRead int) types.AccessList { return AccessList(&AccessListOpts{ - SequencerInboxAddr: deployInfo.SequencerInbox, - DataPosterAddr: transactOpts.From, - BridgeAddr: deployInfo.Bridge, - GasRefunderAddr: config().gasRefunder, + SequencerInboxAddr: opts.DeployInfo.SequencerInbox, + DataPosterAddr: opts.TransactOpts.From, + BridgeAddr: opts.DeployInfo.Bridge, + GasRefunderAddr: opts.Config().gasRefunder, SequencerInboxAccs: SequencerInboxAccs, AfterDelayedMessagesRead: AfterDelayedMessagesRead, }) }, } dataPosterConfigFetcher := func() *dataposter.DataPosterConfig { - return &config().DataPoster + return &(opts.Config().DataPoster) } b.dataPoster, err = dataposter.NewDataPoster(ctx, &dataposter.DataPosterOpts{ - Database: dataPosterDB, - HeaderReader: l1Reader, - Auth: transactOpts, + Database: opts.DataPosterDB, + HeaderReader: opts.L1Reader, + Auth: opts.TransactOpts, RedisClient: redisClient, RedisLock: redisLock, Config: dataPosterConfigFetcher, diff --git a/arbnode/node.go b/arbnode/node.go index 5d06264b6..4fbfaf4bb 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -842,7 +842,17 @@ func createNodeImpl( if txOptsBatchPoster == nil { return nil, errors.New("batchposter, but no TxOpts") } - batchPoster, err = NewBatchPoster(ctx, rawdb.NewTable(arbDb, storage.BatchPosterPrefix), l1Reader, inboxTracker, txStreamer, syncMonitor, func() *BatchPosterConfig { return &configFetcher.Get().BatchPoster }, deployInfo, txOptsBatchPoster, daWriter) + batchPoster, err = NewBatchPoster(ctx, &BatchPosterOpts{ + DataPosterDB: rawdb.NewTable(arbDb, storage.BatchPosterPrefix), + L1Reader: l1Reader, + Inbox: inboxTracker, + Streamer: txStreamer, + SyncMonitor: syncMonitor, + Config: func() *BatchPosterConfig { return &configFetcher.Get().BatchPoster }, + DeployInfo: deployInfo, + TransactOpts: txOptsBatchPoster, + DAWriter: daWriter, + }) if err != nil { return nil, err } diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 1d705c05a..4ea2a16c0 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -83,7 +83,19 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { for i := 0; i < parallelBatchPosters; i++ { // Make a copy of the batch poster config so NewBatchPoster calling Validate() on it doesn't race batchPosterConfig := conf.BatchPoster - batchPoster, err := arbnode.NewBatchPoster(ctx, nil, nodeA.L1Reader, nodeA.InboxTracker, nodeA.TxStreamer, nodeA.SyncMonitor, func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, nodeA.DeployInfo, &seqTxOpts, nil) + batchPoster, err := arbnode.NewBatchPoster(ctx, + &arbnode.BatchPosterOpts{ + DataPosterDB: nil, + L1Reader: nodeA.L1Reader, + Inbox: nodeA.InboxTracker, + Streamer: nodeA.TxStreamer, + SyncMonitor: nodeA.SyncMonitor, + Config: func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, + DeployInfo: nodeA.DeployInfo, + TransactOpts: &seqTxOpts, + DAWriter: nil, + }, + ) Require(t, err) batchPoster.Start(ctx) defer batchPoster.StopAndWait() @@ -104,6 +116,8 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { } } + // TODO: factor this out in separate test case and skip it or delete this + // code entirely. // I've locally confirmed that this passes when the clique period is set to 1. // However, setting the clique period to 1 slows everything else (including the L1 deployment for this test) down to a crawl. if false { From f7a09711366efd223acfd7409600abfdd4f98076 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Wed, 11 Oct 2023 14:53:07 +0200 Subject: [PATCH 238/775] Fix some tests related to SimulatedBeacon change Longer timeout was required for tx to be picked up by secondary L2 in some tests: TestTwoNodesLong, TestTwoNodesLongLocalDAS, TestDASRekey Updated geth pin to use SimulatedBeacon with fix with backported upstream fix for reorgs, fixes these tests: TestMeaninglessBatchReorg, TestSequencerInboxReader --- go-ethereum | 2 +- system_tests/common_test.go | 2 +- system_tests/das_test.go | 2 +- system_tests/twonodeslong_test.go | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/go-ethereum b/go-ethereum index 90dbc8edb..ca2d9a723 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 90dbc8edbe96aeb0c5c372cc7289373ee66d3351 +Subproject commit ca2d9a7239a932ad4f79c8bde5df4ab9cef430da diff --git a/system_tests/common_test.go b/system_tests/common_test.go index c5f92515a..6cc032c9d 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -419,7 +419,7 @@ func createTestL1BlockChainWithConfig(t *testing.T, l1info info, stackConfig *no l1backend, err := eth.New(stack, &nodeConf) Require(t, err) - simBeacon, err := catalyst.NewSimulatedBeacon(1, l1backend) + simBeacon, err := catalyst.NewSimulatedBeacon(0, l1backend) Require(t, err) catalyst.RegisterSimulatedBeaconAPIs(stack, simBeacon) stack.RegisterLifecycle(simBeacon) diff --git a/system_tests/das_test.go b/system_tests/das_test.go index 8889d2d53..7e67a155e 100644 --- a/system_tests/das_test.go +++ b/system_tests/das_test.go @@ -212,7 +212,7 @@ func checkBatchPosting(t *testing.T, ctx context.Context, l1client, l2clientA *e } for _, client := range l2ClientsToCheck { - _, err = WaitForTx(ctx, client, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, client, tx.Hash(), time.Second*25) Require(t, err) l2balance, err := client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) diff --git a/system_tests/twonodeslong_test.go b/system_tests/twonodeslong_test.go index 50af61360..8585780b5 100644 --- a/system_tests/twonodeslong_test.go +++ b/system_tests/twonodeslong_test.go @@ -156,8 +156,9 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { _, err = EnsureTxSucceededWithTimeout(ctx, l2client, delayedTxs[len(delayedTxs)-1], time.Second*10) Require(t, err, "Failed waiting for Tx on main node") - _, err = EnsureTxSucceededWithTimeout(ctx, l2clientB, delayedTxs[len(delayedTxs)-1], time.Second*10) - Require(t, err, "Failed waiting for Tx on secondary node") + _, err = EnsureTxSucceededWithTimeout(ctx, l2clientB, delayedTxs[len(delayedTxs)-1], time.Second*30) + Require(t, err, fmt.Sprintf("Failed waiting for Tx on secondary node")) + delayedBalance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("DelayedReceiver"), nil) Require(t, err) directBalance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("DirectReceiver"), nil) From cbd5ca85c793881c4dca2faa21d138f364ccc8e8 Mon Sep 17 00:00:00 2001 From: GoodDaisy <90915921+GoodDaisy@users.noreply.github.com> Date: Wed, 11 Oct 2023 21:59:27 +0800 Subject: [PATCH 239/775] fix typos --- arbitrator/prover/test-cases/go/main.go | 2 +- arbnode/dataposter/data_poster.go | 2 +- arbos/addressSet/addressSet_test.go | 2 +- arbos/l1pricing/l1pricing.go | 2 +- arbos/tx_processor.go | 2 +- arbos/util/transfer.go | 4 ++-- cmd/seq-coordinator-manager/seq-coordinator-manager.go | 2 +- precompiles/precompile.go | 2 +- system_tests/seq_coordinator_test.go | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arbitrator/prover/test-cases/go/main.go b/arbitrator/prover/test-cases/go/main.go index 79541e48b..afed870fe 100644 --- a/arbitrator/prover/test-cases/go/main.go +++ b/arbitrator/prover/test-cases/go/main.go @@ -89,7 +89,7 @@ func main() { verified, err = MerkleSample(data, -1) if err != nil { if verified { - panic("succeded to verify proof invalid") + panic("succeeded to verify proof invalid") } } diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 912c6c9af..01827881d 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -39,7 +39,7 @@ import ( // is initialized with specified sender/signer and keeps nonce of that address // as it posts transactions. // Transactions are also saved in the queue when it's being sent, and when -// persistant storage is used for the queue, after restarting the node +// persistent storage is used for the queue, after restarting the node // dataposter will pick up where it left. // DataPoster must be RLP serializable and deserializable type DataPoster struct { diff --git a/arbos/addressSet/addressSet_test.go b/arbos/addressSet/addressSet_test.go index bc3b46e80..7d06c74f0 100644 --- a/arbos/addressSet/addressSet_test.go +++ b/arbos/addressSet/addressSet_test.go @@ -270,7 +270,7 @@ func TestRectifyMapping(t *testing.T) { // Non owner's should not be able to call RectifyMapping err := aset.RectifyMapping(testhelpers.RandomAddress()) if err == nil { - Fail(t, "RectifyMapping was succesfully called by non owner") + Fail(t, "RectifyMapping was successfully called by non owner") } // Corrupt the list and verify if RectifyMapping fixes it diff --git a/arbos/l1pricing/l1pricing.go b/arbos/l1pricing/l1pricing.go index e506f7690..142efbeaf 100644 --- a/arbos/l1pricing/l1pricing.go +++ b/arbos/l1pricing/l1pricing.go @@ -75,7 +75,7 @@ const ( InitialInertia = 10 InitialPerUnitReward = 10 InitialPerBatchGasCostV6 = 100_000 - InitialPerBatchGasCostV12 = 210_000 // overriden as part of the upgrade + InitialPerBatchGasCostV12 = 210_000 // overridden as part of the upgrade ) // one minute at 100000 bytes / sec diff --git a/arbos/tx_processor.go b/arbos/tx_processor.go index 3572042a0..4eeffc679 100644 --- a/arbos/tx_processor.go +++ b/arbos/tx_processor.go @@ -483,7 +483,7 @@ func (p *TxProcessor) EndTxHook(gasLeft uint64, success bool) { err = util.TransferBalance(&refundFrom, &inner.RefundTo, toRefundAddr, p.evm, scenario, "refund") if err != nil { // Normally the network fee address should be holding any collected fees. - // However, in theory, they could've been transfered out during the redeem attempt. + // However, in theory, they could've been transferred out during the redeem attempt. // If the network fee address doesn't have the necessary balance, log an error and don't give a refund. log.Error(errLog, "err", err, "feeAddress", refundFrom) } diff --git a/arbos/util/transfer.go b/arbos/util/transfer.go index da3243fd8..3a8118120 100644 --- a/arbos/util/transfer.go +++ b/arbos/util/transfer.go @@ -15,7 +15,7 @@ import ( "github.com/offchainlabs/nitro/util/arbmath" ) -// TransferBalance represents a balance change occuring aside from a call. +// TransferBalance represents a balance change occurring aside from a call. // While most uses will be transfers, setting `from` or `to` to nil will mint or burn funds, respectively. func TransferBalance( from, to *common.Address, @@ -39,7 +39,7 @@ func TransferBalance( } if tracer := evm.Config.Tracer; tracer != nil { if evm.Depth() != 0 && scenario != TracingDuringEVM { - // A non-zero depth implies this transfer is occuring inside EVM execution + // A non-zero depth implies this transfer is occurring inside EVM execution log.Error("Tracing scenario mismatch", "scenario", scenario, "depth", evm.Depth()) return errors.New("tracing scenario mismatch") } diff --git a/cmd/seq-coordinator-manager/seq-coordinator-manager.go b/cmd/seq-coordinator-manager/seq-coordinator-manager.go index a0123a912..07bc26af2 100644 --- a/cmd/seq-coordinator-manager/seq-coordinator-manager.go +++ b/cmd/seq-coordinator-manager/seq-coordinator-manager.go @@ -27,7 +27,7 @@ var addSeqForm = tview.NewForm() var priorityForm = tview.NewForm() var nonPriorityForm = tview.NewForm() -// Sequencer coordinator managment UI data store +// Sequencer coordinator management UI data store type manager struct { redisCoordinator *rediscoordinator.RedisCoordinator prioritiesSet map[string]bool diff --git a/precompiles/precompile.go b/precompiles/precompile.go index 77102a95b..ded90ebdf 100644 --- a/precompiles/precompile.go +++ b/precompiles/precompile.go @@ -366,7 +366,7 @@ func MakePrecompile(metadata *bind.MetaData, implementer interface{}) (addr, *Pr emitCost := gascost(args) cost := emitCost[0].Interface().(uint64) //nolint:errcheck if !emitCost[1].IsNil() { - // an error occured during gascost() + // an error occurred during gascost() return []reflect.Value{emitCost[1]} } if err := callerCtx.Burn(cost); err != nil { diff --git a/system_tests/seq_coordinator_test.go b/system_tests/seq_coordinator_test.go index 881e3b265..a213c366c 100644 --- a/system_tests/seq_coordinator_test.go +++ b/system_tests/seq_coordinator_test.go @@ -197,7 +197,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { } } - // sequencing suceeds only on the leder + // sequencing succeeds only on the leder for i := arbutil.MessageIndex(0); i < messagesPerRound; i++ { if sequencer := trySequencingEverywhere(); sequencer != currentSequencer { Fatal(t, "unexpected sequencer. expected: ", currentSequencer, " got ", sequencer) From 92f6404cd77ab859d63611d6c6c17db7e9f3c568 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 11 Oct 2023 16:07:27 +0200 Subject: [PATCH 240/775] add triedb race test --- system_tests/triedb_race_test.go | 83 ++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 system_tests/triedb_race_test.go diff --git a/system_tests/triedb_race_test.go b/system_tests/triedb_race_test.go new file mode 100644 index 000000000..468997b18 --- /dev/null +++ b/system_tests/triedb_race_test.go @@ -0,0 +1,83 @@ +package arbtest + +import ( + "context" + "sync" + "testing" + "time" + + "github.com/ethereum/go-ethereum/arbitrum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/util/testhelpers" +) + +func TestTrieDBCommitRace(t *testing.T) { + _ = testhelpers.InitTestLog(t, log.LvlError) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + nodeConfig := arbnode.ConfigDefaultL1Test() + nodeConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth + nodeConfig.Sequencer.MaxBlockSpeed = 0 + nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 + nodeConfig.Caching.Archive = true + nodeConfig.Caching.BlockCount = 127 + nodeConfig.Caching.BlockAge = 0 + nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 127 + nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 + l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, nil) + cancel = func() { + defer requireClose(t, l1stack) + defer node.StopAndWait() + } + defer cancel() + l2info.GenerateAccount("User2") + bc := node.Execution.Backend.ArbInterface().BlockChain() + + var wg sync.WaitGroup + quit := make(chan struct{}) + wg.Add(1) + go func() { + defer wg.Done() + for { + select { + default: + TransferBalance(t, "Faucet", "User2", common.Big1, l2info, l2client, ctx) + case <-quit: + return + } + } + }() + api := node.Execution.Backend.APIBackend() + blockNumber := 1 + for i := 0; i < 5; i++ { + var roots []common.Hash + for len(roots) < 1024 { + select { + default: + block, err := api.BlockByNumber(ctx, rpc.BlockNumber(blockNumber)) + if err == nil && block != nil { + root := block.Root() + if statedb, err := bc.StateAt(root); err == nil { + err := statedb.Database().TrieDB().Reference(root, common.Hash{}) + Require(t, err) + roots = append(roots, root) + } + blockNumber += 1 + } + case <-quit: + return + } + } + t.Log("dereferencing...") + for _, root := range roots { + err := bc.TrieDB().Dereference(root) + Require(t, err) + time.Sleep(1) + } + } + close(quit) + wg.Wait() +} From 4800578c7de4da406adcf0dbac99d722284b84dd Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 11 Oct 2023 16:08:13 +0200 Subject: [PATCH 241/775] improve test configs in recreatestate_rpc_test --- system_tests/recreatestate_rpc_test.go | 28 ++++++++++---------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index dbf68c847..33dde0578 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -95,9 +95,8 @@ func TestRecreateStateForRPCNoDepthLimit(t *testing.T) { nodeConfig.Sequencer.MaxBlockSpeed = 0 nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 nodeConfig.Caching.Archive = true - // disable caching of states in BlockChain.stateCache + // disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there nodeConfig.Caching.TrieCleanCache = 0 - nodeConfig.Caching.TrieDirtyCache = 0 nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 _, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, 32) @@ -119,7 +118,6 @@ func TestRecreateStateForRPCNoDepthLimit(t *testing.T) { if balance.Cmp(expectedBalance) != 0 { Fatal(t, "unexpected balance result for last block, want: ", expectedBalance, " have: ", balance) } - } func TestRecreateStateForRPCBigEnoughDepthLimit(t *testing.T) { @@ -131,9 +129,8 @@ func TestRecreateStateForRPCBigEnoughDepthLimit(t *testing.T) { nodeConfig.Sequencer.MaxBlockSpeed = 0 nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 nodeConfig.Caching.Archive = true - // disable caching of states in BlockChain.stateCache + // disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there nodeConfig.Caching.TrieCleanCache = 0 - nodeConfig.Caching.TrieDirtyCache = 0 nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 _, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, 32) @@ -166,9 +163,8 @@ func TestRecreateStateForRPCDepthLimitExceeded(t *testing.T) { nodeConfig.Sequencer.MaxBlockSpeed = 0 nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 nodeConfig.Caching.Archive = true - // disable caching of states in BlockChain.stateCache + // disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there nodeConfig.Caching.TrieCleanCache = 0 - nodeConfig.Caching.TrieDirtyCache = 0 nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 _, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, 32) @@ -201,9 +197,8 @@ func TestRecreateStateForRPCMissingBlockParent(t *testing.T) { nodeConfig.Sequencer.MaxBlockSpeed = 0 nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 nodeConfig.Caching.Archive = true - // disable caching of states in BlockChain.stateCache + // disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there nodeConfig.Caching.TrieCleanCache = 0 - nodeConfig.Caching.TrieDirtyCache = 0 nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 _, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, headerCacheLimit+5) @@ -247,9 +242,8 @@ func TestRecreateStateForRPCBeyondGenesis(t *testing.T) { nodeConfig.Sequencer.MaxBlockSpeed = 0 nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 nodeConfig.Caching.Archive = true - // disable caching of states in BlockChain.stateCache + // disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there nodeConfig.Caching.TrieCleanCache = 0 - nodeConfig.Caching.TrieDirtyCache = 0 nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 _, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, 32) @@ -283,9 +277,9 @@ func TestRecreateStateForRPCBlockNotFoundWhileRecreating(t *testing.T) { nodeConfig.Sequencer.MaxBlockSpeed = 0 nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 nodeConfig.Caching.Archive = true - // disable caching of states in BlockChain.stateCache + // disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there nodeConfig.Caching.TrieCleanCache = 0 - nodeConfig.Caching.TrieDirtyCache = 0 + nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 _, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, blockCacheLimit+4) @@ -412,6 +406,9 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig } for i := genesis + 1; i <= genesis+uint64(txCount); i += i % 10 { _, err = client.BalanceAt(ctx, GetTestAddressForAccountName(t, "User2"), new(big.Int).SetUint64(i)) + if err != nil { + t.Log("skipBlocks:", skipBlocks, "skipGas:", skipGas) + } Require(t, err) } @@ -425,10 +422,7 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig func TestSkippingSavingStateAndRecreatingAfterRestart(t *testing.T) { cacheConfig := execution.DefaultCachingConfig cacheConfig.Archive = true - // disable caching of states in BlockChain.stateCache - cacheConfig.TrieCleanCache = 0 - cacheConfig.TrieDirtyCache = 0 - // test defaults + //// test defaults testSkippingSavingStateAndRecreatingAfterRestart(t, &cacheConfig, 512) cacheConfig.MaxNumberOfBlocksToSkipStateSaving = 127 From ebfd141982e5f79867a4c5a398524d0c78ecbebb Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 11 Oct 2023 16:41:53 +0200 Subject: [PATCH 242/775] fix triedb_race_test --- system_tests/triedb_race_test.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/system_tests/triedb_race_test.go b/system_tests/triedb_race_test.go index 468997b18..8174a9b6a 100644 --- a/system_tests/triedb_race_test.go +++ b/system_tests/triedb_race_test.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" - "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/testhelpers" ) @@ -18,23 +18,24 @@ func TestTrieDBCommitRace(t *testing.T) { _ = testhelpers.InitTestLog(t, log.LvlError) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - nodeConfig := arbnode.ConfigDefaultL1Test() - nodeConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth - nodeConfig.Sequencer.MaxBlockSpeed = 0 - nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 - nodeConfig.Caching.Archive = true - nodeConfig.Caching.BlockCount = 127 - nodeConfig.Caching.BlockAge = 0 - nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 127 - nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 - l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, nil) + execConfig := gethexec.ConfigDefaultTest() + execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth + execConfig.Sequencer.MaxBlockSpeed = 0 + execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 + execConfig.Caching.Archive = true + execConfig.Caching.BlockCount = 127 + execConfig.Caching.BlockAge = 0 + execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 127 + execConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 + l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, execConfig, nil, nil) cancel = func() { defer requireClose(t, l1stack) defer node.StopAndWait() } defer cancel() + execNode := getExecNode(t, node) l2info.GenerateAccount("User2") - bc := node.Execution.Backend.ArbInterface().BlockChain() + bc := execNode.Backend.ArbInterface().BlockChain() var wg sync.WaitGroup quit := make(chan struct{}) @@ -50,7 +51,7 @@ func TestTrieDBCommitRace(t *testing.T) { } } }() - api := node.Execution.Backend.APIBackend() + api := execNode.Backend.APIBackend() blockNumber := 1 for i := 0; i < 5; i++ { var roots []common.Hash From 89a44158d0cff35e2fe692f0a18dbc2fe30e0b39 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 11 Oct 2023 16:55:11 +0200 Subject: [PATCH 243/775] set ParentChainReader default config in gethexec.ConfigDefaultTest --- execution/gethexec/node.go | 1 + 1 file changed, 1 insertion(+) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 1068dda96..8b3874729 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -109,6 +109,7 @@ func ConfigDefaultTest() *Config { config := ConfigDefault config.Sequencer = TestSequencerConfig config.ForwardingTarget = "null" + config.ParentChainReader = headerreader.TestConfig _ = config.Validate() From df6d1dc4816db2c29b3c825db64381a7af075006 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 11 Oct 2023 17:03:23 +0200 Subject: [PATCH 244/775] update geth to version with triedb race fix --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index b4221631e..7c1903db7 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit b4221631e1e5eac86f01582bd74234e3c0f7f5c7 +Subproject commit 7c1903db73f835fab4cc39f963ceeda6da46d44e From ab4bf63b6030c65cccc0fbb89bc28144a20408bc Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Wed, 11 Oct 2023 17:38:30 +0200 Subject: [PATCH 245/775] Lint fix --- system_tests/twonodeslong_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system_tests/twonodeslong_test.go b/system_tests/twonodeslong_test.go index 8585780b5..12e613489 100644 --- a/system_tests/twonodeslong_test.go +++ b/system_tests/twonodeslong_test.go @@ -157,7 +157,7 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { _, err = EnsureTxSucceededWithTimeout(ctx, l2client, delayedTxs[len(delayedTxs)-1], time.Second*10) Require(t, err, "Failed waiting for Tx on main node") _, err = EnsureTxSucceededWithTimeout(ctx, l2clientB, delayedTxs[len(delayedTxs)-1], time.Second*30) - Require(t, err, fmt.Sprintf("Failed waiting for Tx on secondary node")) + Require(t, err, "Failed waiting for Tx on secondary node") delayedBalance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("DelayedReceiver"), nil) Require(t, err) From e935a24b545d1573a15d0e6714d19c0062a507a1 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 11 Oct 2023 18:58:07 +0200 Subject: [PATCH 246/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 7c1903db7..89540b144 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 7c1903db73f835fab4cc39f963ceeda6da46d44e +Subproject commit 89540b1440179a851e5e29672a700851c4237d83 From 5e75c666aaee3c10ffbdcbafa372718258824585 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 11 Oct 2023 19:09:51 +0200 Subject: [PATCH 247/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 89540b144..3573250ad 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 89540b1440179a851e5e29672a700851c4237d83 +Subproject commit 3573250adec48511a0bc45647061ed6d25c4ae35 From 98c6562b3a79306687117c1267b11e94cb7c71ce Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 11 Oct 2023 13:40:21 -0500 Subject: [PATCH 248/775] Add --dev flag to easily start up a local L2-only dev chain --- cmd/nitro/init.go | 3 ++- cmd/nitro/nitro.go | 5 ++++- cmd/util/confighelpers/configuration.go | 22 ++++++++++++++++++++++ execution/gethexec/node.go | 3 ++- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index bef0f83d1..f874b5d71 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -10,6 +10,7 @@ import ( "fmt" "math/big" "os" + "reflect" "regexp" "runtime" "strings" @@ -296,7 +297,7 @@ func findImportantRoots(ctx context.Context, chainDb ethdb.Database, stack *node return nil, err } if initConfig.Prune == "validator" { - if l1Client == nil { + if l1Client == nil || reflect.ValueOf(l1Client).IsNil() { return nil, errors.New("an L1 connection is required for validator pruning") } callOpts := bind.CallOpts{ diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 285cc3fe8..80b21e5eb 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -61,7 +61,10 @@ import ( ) func printSampleUsage(name string) { - fmt.Printf("Sample usage: %s --help \n", name) + fmt.Printf("Sample usage: %s [OPTIONS] \n\n", name) + fmt.Printf("Options:\n") + fmt.Printf(" --help\n") + fmt.Printf(" --dev: Start a default L2-only dev chain\n") } func addUnlockWallet(accountManager *accounts.Manager, walletConf *genericconf.WalletConfig) (common.Address, error) { diff --git a/cmd/util/confighelpers/configuration.go b/cmd/util/confighelpers/configuration.go index 18a2b10f2..6116a492c 100644 --- a/cmd/util/confighelpers/configuration.go +++ b/cmd/util/confighelpers/configuration.go @@ -138,10 +138,32 @@ func PrintErrorAndExit(err error, usage func(string)) { } } +func devFlagArgs() []string { + args := []string{ + "--init.dev-init", + "--init.dev-init-address", "0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0E", + "--node.dangerous.no-l1-listener", + "--node.parent-chain-reader.enable=false", + "--parent-chain.id=1337", + "--chain.id=412346", + "--persistent.chain", "/tmp/dev-test", + "--node.sequencer", + "--node.dangerous.no-sequencer-coordinator", + "--node.staker.enable=false", + "--init.empty=false", + "--http.port", "8547", + "--http.addr", "127.0.0.1", + } + return args +} + func BeginCommonParse(f *flag.FlagSet, args []string) (*koanf.Koanf, error) { for _, arg := range args { if arg == "--version" || arg == "-v" { return nil, ErrVersion + } else if arg == "--dev" { + args = devFlagArgs() + break } } if err := f.Parse(args); err != nil { diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 1068dda96..d7f7a4130 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "reflect" "sync/atomic" "testing" @@ -149,7 +150,7 @@ func CreateExecutionNode( var sequencer *Sequencer var parentChainReader *headerreader.HeaderReader - if l1client != nil { + if l1client != nil && !reflect.ValueOf(l1client).IsNil() { arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) parentChainReader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher().ParentChainReader }, arbSys) if err != nil { From 36b722ce7db3a2a7b44c78bd47dea912eba24049 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 12 Oct 2023 12:47:37 +0200 Subject: [PATCH 249/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 3573250ad..202caf5bf 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 3573250adec48511a0bc45647061ed6d25c4ae35 +Subproject commit 202caf5bf944835ef78b4d7c4ba8b48bdc54d65d From 001ae3179abb304ee87b3e36cdfc03414cefaf02 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 12 Oct 2023 22:05:10 +0200 Subject: [PATCH 250/775] address review comments --- arbos/addressSet/addressSet.go | 90 ++++++------- arbos/addressTable/addressTable.go | 2 +- arbos/arbosState/arbosstate.go | 32 ++--- arbos/arbosState/arbosstate_test.go | 2 +- arbos/blockhash/blockhash.go | 2 +- arbos/l1pricing/batchPoster.go | 8 +- arbos/l1pricing/l1pricing.go | 4 +- arbos/queue_test.go | 2 +- arbos/retryables/retryable.go | 14 +- arbos/storage/queue.go | 2 +- arbos/storage/storage.go | 200 +++++++++++++++------------- 11 files changed, 184 insertions(+), 174 deletions(-) diff --git a/arbos/addressSet/addressSet.go b/arbos/addressSet/addressSet.go index 38b07f7a1..50a43c36c 100644 --- a/arbos/addressSet/addressSet.go +++ b/arbos/addressSet/addressSet.go @@ -26,49 +26,49 @@ func Initialize(sto *storage.Storage) error { func OpenAddressSet(sto *storage.Storage) *AddressSet { return &AddressSet{ - sto.NoCacheCopy(), - sto.OpenStorageBackedUint64(0), - sto.OpenSubStorage([]byte{0}, false), + backingStorage: sto.WithoutCache(), + size: sto.OpenStorageBackedUint64(0), + byAddress: sto.OpenSubStorage([]byte{0}), } } -func (aset *AddressSet) Size() (uint64, error) { - return aset.size.Get() +func (as *AddressSet) Size() (uint64, error) { + return as.size.Get() } -func (aset *AddressSet) IsMember(addr common.Address) (bool, error) { - value, err := aset.byAddress.Get(util.AddressToHash(addr)) +func (as *AddressSet) IsMember(addr common.Address) (bool, error) { + value, err := as.byAddress.Get(util.AddressToHash(addr)) return value != (common.Hash{}), err } -func (aset *AddressSet) GetAnyMember() (*common.Address, error) { - size, err := aset.size.Get() +func (as *AddressSet) GetAnyMember() (*common.Address, error) { + size, err := as.size.Get() if err != nil || size == 0 { return nil, err } - sba := aset.backingStorage.OpenStorageBackedAddressOrNil(1) + sba := as.backingStorage.OpenStorageBackedAddressOrNil(1) addr, err := sba.Get() return addr, err } -func (aset *AddressSet) Clear() error { - size, err := aset.size.Get() +func (as *AddressSet) Clear() error { + size, err := as.size.Get() if err != nil || size == 0 { return err } for i := uint64(1); i <= size; i++ { - contents, _ := aset.backingStorage.GetByUint64(i) - _ = aset.backingStorage.ClearByUint64(i) - err = aset.byAddress.Clear(contents) + contents, _ := as.backingStorage.GetByUint64(i) + _ = as.backingStorage.ClearByUint64(i) + err = as.byAddress.Clear(contents) if err != nil { return err } } - return aset.size.Clear() + return as.size.Clear() } -func (aset *AddressSet) AllMembers(maxNumToReturn uint64) ([]common.Address, error) { - size, err := aset.size.Get() +func (as *AddressSet) AllMembers(maxNumToReturn uint64) ([]common.Address, error) { + size, err := as.size.Get() if err != nil { return nil, err } @@ -77,7 +77,7 @@ func (aset *AddressSet) AllMembers(maxNumToReturn uint64) ([]common.Address, err } ret := make([]common.Address, size) for i := range ret { - sba := aset.backingStorage.OpenStorageBackedAddress(uint64(i + 1)) + sba := as.backingStorage.OpenStorageBackedAddress(uint64(i + 1)) ret[i], err = sba.Get() if err != nil { return nil, err @@ -86,22 +86,22 @@ func (aset *AddressSet) AllMembers(maxNumToReturn uint64) ([]common.Address, err return ret, nil } -func (aset *AddressSet) ClearList() error { - size, err := aset.size.Get() +func (as *AddressSet) ClearList() error { + size, err := as.size.Get() if err != nil || size == 0 { return err } for i := uint64(1); i <= size; i++ { - err = aset.backingStorage.ClearByUint64(i) + err = as.backingStorage.ClearByUint64(i) if err != nil { return err } } - return aset.size.Clear() + return as.size.Clear() } -func (aset *AddressSet) RectifyMapping(addr common.Address) error { - isOwner, err := aset.IsMember(addr) +func (as *AddressSet) RectifyMapping(addr common.Address) error { + isOwner, err := as.IsMember(addr) if !isOwner || err != nil { return errors.New("RectifyMapping: Address is not an owner") } @@ -109,15 +109,15 @@ func (aset *AddressSet) RectifyMapping(addr common.Address) error { // If the mapping is correct, RectifyMapping shouldn't do anything // Additional safety check to avoid corruption of mapping after the initial fix addrAsHash := common.BytesToHash(addr.Bytes()) - slot, err := aset.byAddress.GetUint64(addrAsHash) + slot, err := as.byAddress.GetUint64(addrAsHash) if err != nil { return err } - atSlot, err := aset.backingStorage.GetByUint64(slot) + atSlot, err := as.backingStorage.GetByUint64(slot) if err != nil { return err } - size, err := aset.size.Get() + size, err := as.size.Get() if err != nil { return err } @@ -126,72 +126,72 @@ func (aset *AddressSet) RectifyMapping(addr common.Address) error { } // Remove the owner from map and add them as a new owner - err = aset.byAddress.Clear(addrAsHash) + err = as.byAddress.Clear(addrAsHash) if err != nil { return err } - return aset.Add(addr) + return as.Add(addr) } -func (aset *AddressSet) Add(addr common.Address) error { - present, err := aset.IsMember(addr) +func (as *AddressSet) Add(addr common.Address) error { + present, err := as.IsMember(addr) if present || err != nil { return err } - size, err := aset.size.Get() + size, err := as.size.Get() if err != nil { return err } slot := util.UintToHash(1 + size) addrAsHash := common.BytesToHash(addr.Bytes()) - err = aset.byAddress.Set(addrAsHash, slot) + err = as.byAddress.Set(addrAsHash, slot) if err != nil { return err } - sba := aset.backingStorage.OpenStorageBackedAddress(1 + size) + sba := as.backingStorage.OpenStorageBackedAddress(1 + size) err = sba.Set(addr) if err != nil { return err } - _, err = aset.size.Increment() + _, err = as.size.Increment() return err } -func (aset *AddressSet) Remove(addr common.Address, arbosVersion uint64) error { +func (as *AddressSet) Remove(addr common.Address, arbosVersion uint64) error { addrAsHash := common.BytesToHash(addr.Bytes()) - slot, err := aset.byAddress.GetUint64(addrAsHash) + slot, err := as.byAddress.GetUint64(addrAsHash) if slot == 0 || err != nil { return err } - err = aset.byAddress.Clear(addrAsHash) + err = as.byAddress.Clear(addrAsHash) if err != nil { return err } - size, err := aset.size.Get() + size, err := as.size.Get() if err != nil { return err } if slot < size { - atSize, err := aset.backingStorage.GetByUint64(size) + atSize, err := as.backingStorage.GetByUint64(size) if err != nil { return err } - err = aset.backingStorage.SetByUint64(slot, atSize) + err = as.backingStorage.SetByUint64(slot, atSize) if err != nil { return err } if arbosVersion >= 11 { - err = aset.byAddress.Set(atSize, util.UintToHash(slot)) + err = as.byAddress.Set(atSize, util.UintToHash(slot)) if err != nil { return err } } } - err = aset.backingStorage.ClearByUint64(size) + err = as.backingStorage.ClearByUint64(size) if err != nil { return err } - _, err = aset.size.Decrement() + _, err = as.size.Decrement() return err } diff --git a/arbos/addressTable/addressTable.go b/arbos/addressTable/addressTable.go index 56f04badf..f44e7f3dc 100644 --- a/arbos/addressTable/addressTable.go +++ b/arbos/addressTable/addressTable.go @@ -25,7 +25,7 @@ func Initialize(sto *storage.Storage) { func Open(sto *storage.Storage) *AddressTable { numItems := sto.OpenStorageBackedUint64(0) - return &AddressTable{sto.NoCacheCopy(), sto.OpenSubStorage([]byte{}, false), numItems} + return &AddressTable{sto.WithoutCache(), sto.OpenSubStorage([]byte{}), numItems} } func (atab *AddressTable) Register(addr common.Address) (uint64, error) { diff --git a/arbos/arbosState/arbosstate.go b/arbos/arbosState/arbosstate.go index 750c796e3..8702c62d1 100644 --- a/arbos/arbosState/arbosstate.go +++ b/arbos/arbosState/arbosstate.go @@ -73,13 +73,13 @@ func OpenArbosState(stateDB vm.StateDB, burner burn.Burner) (*ArbosState, error) backingStorage.OpenStorageBackedUint64(uint64(upgradeVersionOffset)), backingStorage.OpenStorageBackedUint64(uint64(upgradeTimestampOffset)), backingStorage.OpenStorageBackedAddress(uint64(networkFeeAccountOffset)), - l1pricing.OpenL1PricingState(backingStorage.OpenSubStorage(l1PricingSubspace, true)), - l2pricing.OpenL2PricingState(backingStorage.OpenSubStorage(l2PricingSubspace, true)), - retryables.OpenRetryableState(backingStorage.OpenSubStorage(retryablesSubspace, true), stateDB), - addressTable.Open(backingStorage.OpenSubStorage(addressTableSubspace, true)), - addressSet.OpenAddressSet(backingStorage.OpenSubStorage(chainOwnerSubspace, true)), - merkleAccumulator.OpenMerkleAccumulator(backingStorage.OpenSubStorage(sendMerkleSubspace, true)), - blockhash.OpenBlockhashes(backingStorage.OpenSubStorage(blockhashesSubspace, true)), + l1pricing.OpenL1PricingState(backingStorage.OpenCachedSubStorage(l1PricingSubspace)), + l2pricing.OpenL2PricingState(backingStorage.OpenCachedSubStorage(l2PricingSubspace)), + retryables.OpenRetryableState(backingStorage.OpenCachedSubStorage(retryablesSubspace), stateDB), + addressTable.Open(backingStorage.OpenCachedSubStorage(addressTableSubspace)), + addressSet.OpenAddressSet(backingStorage.OpenCachedSubStorage(chainOwnerSubspace)), + merkleAccumulator.OpenMerkleAccumulator(backingStorage.OpenCachedSubStorage(sendMerkleSubspace)), + blockhash.OpenBlockhashes(backingStorage.OpenCachedSubStorage(blockhashesSubspace)), backingStorage.OpenStorageBackedBigInt(uint64(chainIdOffset)), backingStorage.OpenStorageBackedBytes(chainConfigSubspace), backingStorage.OpenStorageBackedUint64(uint64(genesisBlockNumOffset)), @@ -225,14 +225,14 @@ func InitializeArbosState(stateDB vm.StateDB, burner burn.Burner, chainConfig *p if desiredArbosVersion >= 2 { initialRewardsRecipient = initialChainOwner } - _ = l1pricing.InitializeL1PricingState(sto.OpenSubStorage(l1PricingSubspace, true), initialRewardsRecipient, initMessage.InitialL1BaseFee) - _ = l2pricing.InitializeL2PricingState(sto.OpenSubStorage(l2PricingSubspace, true)) - _ = retryables.InitializeRetryableState(sto.OpenSubStorage(retryablesSubspace, true)) - addressTable.Initialize(sto.OpenSubStorage(addressTableSubspace, true)) - merkleAccumulator.InitializeMerkleAccumulator(sto.OpenSubStorage(sendMerkleSubspace, true)) - blockhash.InitializeBlockhashes(sto.OpenSubStorage(blockhashesSubspace, true)) - - ownersStorage := sto.OpenSubStorage(chainOwnerSubspace, true) + _ = l1pricing.InitializeL1PricingState(sto.OpenCachedSubStorage(l1PricingSubspace), initialRewardsRecipient, initMessage.InitialL1BaseFee) + _ = l2pricing.InitializeL2PricingState(sto.OpenCachedSubStorage(l2PricingSubspace)) + _ = retryables.InitializeRetryableState(sto.OpenCachedSubStorage(retryablesSubspace)) + addressTable.Initialize(sto.OpenCachedSubStorage(addressTableSubspace)) + merkleAccumulator.InitializeMerkleAccumulator(sto.OpenCachedSubStorage(sendMerkleSubspace)) + blockhash.InitializeBlockhashes(sto.OpenCachedSubStorage(blockhashesSubspace)) + + ownersStorage := sto.OpenCachedSubStorage(chainOwnerSubspace) _ = addressSet.Initialize(ownersStorage) _ = addressSet.OpenAddressSet(ownersStorage).Add(initialChainOwner) @@ -428,7 +428,7 @@ func (state *ArbosState) ChainOwners() *addressSet.AddressSet { func (state *ArbosState) SendMerkleAccumulator() *merkleAccumulator.MerkleAccumulator { if state.sendMerkle == nil { - state.sendMerkle = merkleAccumulator.OpenMerkleAccumulator(state.backingStorage.OpenSubStorage(sendMerkleSubspace, true)) + state.sendMerkle = merkleAccumulator.OpenMerkleAccumulator(state.backingStorage.OpenCachedSubStorage(sendMerkleSubspace)) } return state.sendMerkle } diff --git a/arbos/arbosState/arbosstate_test.go b/arbos/arbosState/arbosstate_test.go index 384fc9c72..ef63c2338 100644 --- a/arbos/arbosState/arbosstate_test.go +++ b/arbos/arbosState/arbosstate_test.go @@ -64,7 +64,7 @@ func TestStorageBackedInt64(t *testing.T) { func TestStorageSlots(t *testing.T) { state, _ := NewArbosMemoryBackedArbOSState() - sto := state.BackingStorage().OpenSubStorage([]byte{}, true) + sto := state.BackingStorage().OpenCachedSubStorage([]byte{}) println("nil address", colors.Blue, storage.NilAddressRepresentation.String(), colors.Clear) diff --git a/arbos/blockhash/blockhash.go b/arbos/blockhash/blockhash.go index 99fb3ef47..34c907207 100644 --- a/arbos/blockhash/blockhash.go +++ b/arbos/blockhash/blockhash.go @@ -21,7 +21,7 @@ func InitializeBlockhashes(backingStorage *storage.Storage) { } func OpenBlockhashes(backingStorage *storage.Storage) *Blockhashes { - return &Blockhashes{backingStorage.NoCacheCopy(), backingStorage.OpenStorageBackedUint64(0)} + return &Blockhashes{backingStorage.WithoutCache(), backingStorage.OpenStorageBackedUint64(0)} } func (bh *Blockhashes) L1BlockNumber() (uint64, error) { diff --git a/arbos/l1pricing/batchPoster.go b/arbos/l1pricing/batchPoster.go index 4ac86307e..a3428c441 100644 --- a/arbos/l1pricing/batchPoster.go +++ b/arbos/l1pricing/batchPoster.go @@ -42,13 +42,13 @@ func InitializeBatchPostersTable(storage *storage.Storage) error { if err := totalFundsDue.SetChecked(common.Big0); err != nil { return err } - return addressSet.Initialize(storage.OpenSubStorage(PosterAddrsKey, true)) + return addressSet.Initialize(storage.OpenCachedSubStorage(PosterAddrsKey)) } func OpenBatchPostersTable(storage *storage.Storage) *BatchPostersTable { return &BatchPostersTable{ - posterAddrs: addressSet.OpenAddressSet(storage.OpenSubStorage(PosterAddrsKey, true)), - posterInfo: storage.OpenSubStorage(PosterInfoKey, false), + posterAddrs: addressSet.OpenAddressSet(storage.OpenCachedSubStorage(PosterAddrsKey)), + posterInfo: storage.OpenSubStorage(PosterInfoKey), totalFundsDue: storage.OpenStorageBackedBigInt(totalFundsDueOffset), } } @@ -68,7 +68,7 @@ func (bpt *BatchPostersTable) OpenPoster(poster common.Address, createIfNotExist } func (bpt *BatchPostersTable) internalOpen(poster common.Address) *BatchPosterState { - bpStorage := bpt.posterInfo.OpenSubStorage(poster.Bytes(), false) + bpStorage := bpt.posterInfo.OpenSubStorage(poster.Bytes()) return &BatchPosterState{ fundsDue: bpStorage.OpenStorageBackedBigInt(0), payTo: bpStorage.OpenStorageBackedAddress(1), diff --git a/arbos/l1pricing/l1pricing.go b/arbos/l1pricing/l1pricing.go index 1956eab29..58c1042ab 100644 --- a/arbos/l1pricing/l1pricing.go +++ b/arbos/l1pricing/l1pricing.go @@ -83,7 +83,7 @@ var InitialEquilibrationUnitsV0 = arbmath.UintToBig(60 * params.TxDataNonZeroGas var InitialEquilibrationUnitsV6 = arbmath.UintToBig(params.TxDataNonZeroGasEIP2028 * 10000000) func InitializeL1PricingState(sto *storage.Storage, initialRewardsRecipient common.Address, initialL1BaseFee *big.Int) error { - bptStorage := sto.OpenSubStorage(BatchPosterTableKey, true) + bptStorage := sto.OpenCachedSubStorage(BatchPosterTableKey) if err := InitializeBatchPostersTable(bptStorage); err != nil { return err } @@ -118,7 +118,7 @@ func InitializeL1PricingState(sto *storage.Storage, initialRewardsRecipient comm func OpenL1PricingState(sto *storage.Storage) *L1PricingState { return &L1PricingState{ sto, - OpenBatchPostersTable(sto.OpenSubStorage(BatchPosterTableKey, true)), + OpenBatchPostersTable(sto.OpenCachedSubStorage(BatchPosterTableKey)), sto.OpenStorageBackedAddress(payRewardsToOffset), sto.OpenStorageBackedBigUint(equilibrationUnitsOffset), sto.OpenStorageBackedUint64(inertiaOffset), diff --git a/arbos/queue_test.go b/arbos/queue_test.go index abeec49a9..ff993a233 100644 --- a/arbos/queue_test.go +++ b/arbos/queue_test.go @@ -14,7 +14,7 @@ import ( func TestQueue(t *testing.T) { state, statedb := arbosState.NewArbosMemoryBackedArbOSState() - sto := state.BackingStorage().OpenSubStorage([]byte{}, true) + sto := state.BackingStorage().OpenCachedSubStorage([]byte{}) Require(t, storage.InitializeQueue(sto)) q := storage.OpenQueue(sto) diff --git a/arbos/retryables/retryable.go b/arbos/retryables/retryable.go index 032293854..1121de01f 100644 --- a/arbos/retryables/retryable.go +++ b/arbos/retryables/retryable.go @@ -31,13 +31,13 @@ var ( ) func InitializeRetryableState(sto *storage.Storage) error { - return storage.InitializeQueue(sto.OpenSubStorage(timeoutQueueKey, true)) + return storage.InitializeQueue(sto.OpenCachedSubStorage(timeoutQueueKey)) } func OpenRetryableState(sto *storage.Storage, statedb vm.StateDB) *RetryableState { return &RetryableState{ sto, - storage.OpenQueue(sto.OpenSubStorage(timeoutQueueKey, true)), + storage.OpenQueue(sto.OpenCachedSubStorage(timeoutQueueKey)), } } @@ -73,7 +73,7 @@ func (rs *RetryableState) CreateRetryable( beneficiary common.Address, calldata []byte, ) (*Retryable, error) { - sto := rs.retryables.OpenSubStorage(id.Bytes(), false) + sto := rs.retryables.OpenSubStorage(id.Bytes()) ret := &Retryable{ id, sto, @@ -100,7 +100,7 @@ func (rs *RetryableState) CreateRetryable( } func (rs *RetryableState) OpenRetryable(id common.Hash, currentTimestamp uint64) (*Retryable, error) { - sto := rs.retryables.OpenSubStorage(id.Bytes(), false) + sto := rs.retryables.OpenSubStorage(id.Bytes()) timeoutStorage := sto.OpenStorageBackedUint64(timeoutOffset) timeout, err := timeoutStorage.Get() if timeout == 0 || timeout < currentTimestamp || err != nil { @@ -134,7 +134,7 @@ func (rs *RetryableState) RetryableSizeBytes(id common.Hash, currentTime uint64) } func (rs *RetryableState) DeleteRetryable(id common.Hash, evm *vm.EVM, scenario util.TracingScenario) (bool, error) { - retStorage := rs.retryables.OpenSubStorage(id.Bytes(), false) + retStorage := rs.retryables.OpenSubStorage(id.Bytes()) timeout, err := retStorage.GetByUint64(timeoutOffset) if timeout == (common.Hash{}) || err != nil { return false, err @@ -157,7 +157,7 @@ func (rs *RetryableState) DeleteRetryable(id common.Hash, evm *vm.EVM, scenario _ = retStorage.ClearByUint64(beneficiaryOffset) _ = retStorage.ClearByUint64(timeoutOffset) _ = retStorage.ClearByUint64(timeoutWindowsLeftOffset) - err = retStorage.OpenSubStorage(calldataKey, false).ClearBytes() + err = retStorage.OpenSubStorage(calldataKey).ClearBytes() return true, err } @@ -291,7 +291,7 @@ func (rs *RetryableState) TryToReapOneRetryable(currentTimestamp uint64, evm *vm if err != nil || id == nil { return err } - retryableStorage := rs.retryables.OpenSubStorage(id.Bytes(), false) + retryableStorage := rs.retryables.OpenSubStorage(id.Bytes()) timeoutStorage := retryableStorage.OpenStorageBackedUint64(timeoutOffset) timeout, err := timeoutStorage.Get() if err != nil { diff --git a/arbos/storage/queue.go b/arbos/storage/queue.go index 032ac11aa..9c02dc1ee 100644 --- a/arbos/storage/queue.go +++ b/arbos/storage/queue.go @@ -25,7 +25,7 @@ func InitializeQueue(sto *Storage) error { func OpenQueue(sto *Storage) *Queue { return &Queue{ - sto.NoCacheCopy(), + sto.WithoutCache(), sto.OpenStorageBackedUint64(0), sto.OpenStorageBackedUint64(1), } diff --git a/arbos/storage/storage.go b/arbos/storage/storage.go index 66f3d4947..47ca66445 100644 --- a/arbos/storage/storage.go +++ b/arbos/storage/storage.go @@ -91,11 +91,11 @@ func NewMemoryBackedStateDB() vm.StateDB { // a page, to preserve contiguity within a page. This will reduce cost if/when Ethereum switches to storage // representations that reward contiguity. // Because page numbers are 248 bits, this gives us 124-bit security against collision attacks, which is good enough. -func (store *Storage) mapAddress(key common.Hash) common.Hash { +func (s *Storage) mapAddress(key common.Hash) common.Hash { keyBytes := key.Bytes() boundary := common.HashLength - 1 mapped := make([]byte, 0, common.HashLength) - mapped = append(mapped, store.cachedKeccak(store.storageKey, keyBytes[:boundary])[:boundary]...) + mapped = append(mapped, s.cachedKeccak(s.storageKey, keyBytes[:boundary])[:boundary]...) mapped = append(mapped, keyBytes[boundary]) return common.BytesToHash(mapped) } @@ -107,132 +107,139 @@ func writeCost(value common.Hash) uint64 { return StorageWriteCost } -func (store *Storage) Account() common.Address { - return store.account +func (s *Storage) Account() common.Address { + return s.account } -func (store *Storage) Get(key common.Hash) (common.Hash, error) { - err := store.burner.Burn(StorageReadCost) +func (s *Storage) Get(key common.Hash) (common.Hash, error) { + err := s.burner.Burn(StorageReadCost) if err != nil { return common.Hash{}, err } - if info := store.burner.TracingInfo(); info != nil { + if info := s.burner.TracingInfo(); info != nil { info.RecordStorageGet(key) } - return store.db.GetState(store.account, store.mapAddress(key)), nil + return s.db.GetState(s.account, s.mapAddress(key)), nil } -func (store *Storage) GetStorageSlot(key common.Hash) common.Hash { - return store.mapAddress(key) +func (s *Storage) GetStorageSlot(key common.Hash) common.Hash { + return s.mapAddress(key) } -func (store *Storage) GetUint64(key common.Hash) (uint64, error) { - value, err := store.Get(key) +func (s *Storage) GetUint64(key common.Hash) (uint64, error) { + value, err := s.Get(key) return value.Big().Uint64(), err } -func (store *Storage) GetByUint64(key uint64) (common.Hash, error) { - return store.Get(util.UintToHash(key)) +func (s *Storage) GetByUint64(key uint64) (common.Hash, error) { + return s.Get(util.UintToHash(key)) } -func (store *Storage) GetUint64ByUint64(key uint64) (uint64, error) { - return store.GetUint64(util.UintToHash(key)) +func (s *Storage) GetUint64ByUint64(key uint64) (uint64, error) { + return s.GetUint64(util.UintToHash(key)) } -func (store *Storage) Set(key common.Hash, value common.Hash) error { - if store.burner.ReadOnly() { +func (s *Storage) Set(key common.Hash, value common.Hash) error { + if s.burner.ReadOnly() { log.Error("Read-only burner attempted to mutate state", "key", key, "value", value) return vm.ErrWriteProtection } - err := store.burner.Burn(writeCost(value)) + err := s.burner.Burn(writeCost(value)) if err != nil { return err } - if info := store.burner.TracingInfo(); info != nil { + if info := s.burner.TracingInfo(); info != nil { info.RecordStorageSet(key, value) } - store.db.SetState(store.account, store.mapAddress(key), value) + s.db.SetState(s.account, s.mapAddress(key), value) return nil } -func (store *Storage) SetByUint64(key uint64, value common.Hash) error { - return store.Set(util.UintToHash(key), value) +func (s *Storage) SetByUint64(key uint64, value common.Hash) error { + return s.Set(util.UintToHash(key), value) } -func (store *Storage) SetUint64ByUint64(key uint64, value uint64) error { - return store.Set(util.UintToHash(key), util.UintToHash(value)) +func (s *Storage) SetUint64ByUint64(key uint64, value uint64) error { + return s.Set(util.UintToHash(key), util.UintToHash(value)) } -func (store *Storage) Clear(key common.Hash) error { - return store.Set(key, common.Hash{}) +func (s *Storage) Clear(key common.Hash) error { + return s.Set(key, common.Hash{}) } -func (store *Storage) ClearByUint64(key uint64) error { - return store.Set(util.UintToHash(key), common.Hash{}) +func (s *Storage) ClearByUint64(key uint64) error { + return s.Set(util.UintToHash(key), common.Hash{}) } -func (store *Storage) Swap(key common.Hash, newValue common.Hash) (common.Hash, error) { - oldValue, err := store.Get(key) +func (s *Storage) Swap(key common.Hash, newValue common.Hash) (common.Hash, error) { + oldValue, err := s.Get(key) if err != nil { return common.Hash{}, err } - return oldValue, store.Set(key, newValue) + return oldValue, s.Set(key, newValue) } -func (store *Storage) OpenSubStorage(id []byte, cacheKeys bool) *Storage { - var hashCache *containers.SafeLruCache[string, []byte] - if cacheKeys { - hashCache = storageHashCache +func (s *Storage) OpenCachedSubStorage(id []byte) *Storage { + return &Storage{ + account: s.account, + db: s.db, + storageKey: s.cachedKeccak(s.storageKey, id), + burner: s.burner, + hashCache: storageHashCache, } +} +func (s *Storage) OpenSubStorage(id []byte) *Storage { return &Storage{ - store.account, - store.db, - store.cachedKeccak(store.storageKey, id), - store.burner, - hashCache, + account: s.account, + db: s.db, + storageKey: s.cachedKeccak(s.storageKey, id), + burner: s.burner, + hashCache: nil, } } -func (store *Storage) NoCacheCopy() *Storage { +// Returns shallow copy of Storage that won't use storage key hash cache. +// The storage space represented by the returned Storage is kept the same. +func (s *Storage) WithoutCache() *Storage { return &Storage{ - store.account, - store.db, - store.storageKey, - store.burner, - nil, + account: s.account, + db: s.db, + storageKey: s.storageKey, + burner: s.burner, + hashCache: nil, } } -func (store *Storage) SetBytes(b []byte) error { - err := store.ClearBytes() +func (s *Storage) SetBytes(b []byte) error { + err := s.ClearBytes() if err != nil { return err } - err = store.SetUint64ByUint64(0, uint64(len(b))) + err = s.SetUint64ByUint64(0, uint64(len(b))) if err != nil { return err } offset := uint64(1) for len(b) >= 32 { - err = store.SetByUint64(offset, common.BytesToHash(b[:32])) + err = s.SetByUint64(offset, common.BytesToHash(b[:32])) if err != nil { return err } b = b[32:] offset++ } - return store.SetByUint64(offset, common.BytesToHash(b)) + return s.SetByUint64(offset, common.BytesToHash(b)) } -func (store *Storage) GetBytes() ([]byte, error) { - bytesLeft, err := store.GetUint64ByUint64(0) +func (s *Storage) GetBytes() ([]byte, error) { + bytesLeft, err := s.GetUint64ByUint64(0) if err != nil { return nil, err } ret := []byte{} offset := uint64(1) for bytesLeft >= 32 { - next, err := store.GetByUint64(offset) + next, err := s.GetByUint64(offset) if err != nil { return nil, err } @@ -240,7 +247,7 @@ func (store *Storage) GetBytes() ([]byte, error) { bytesLeft -= 32 offset++ } - next, err := store.GetByUint64(offset) + next, err := s.GetByUint64(offset) if err != nil { return nil, err } @@ -248,18 +255,18 @@ func (store *Storage) GetBytes() ([]byte, error) { return ret, nil } -func (store *Storage) GetBytesSize() (uint64, error) { - return store.GetUint64ByUint64(0) +func (s *Storage) GetBytesSize() (uint64, error) { + return s.GetUint64ByUint64(0) } -func (store *Storage) ClearBytes() error { - bytesLeft, err := store.GetUint64ByUint64(0) +func (s *Storage) ClearBytes() error { + bytesLeft, err := s.GetUint64ByUint64(0) if err != nil { return err } offset := uint64(1) for bytesLeft > 0 { - err := store.ClearByUint64(offset) + err := s.ClearByUint64(offset) if err != nil { return err } @@ -270,48 +277,51 @@ func (store *Storage) ClearBytes() error { bytesLeft -= 32 } } - return store.ClearByUint64(0) + return s.ClearByUint64(0) } -func (store *Storage) Burner() burn.Burner { - return store.burner // not public because these should never be changed once set +func (s *Storage) Burner() burn.Burner { + return s.burner // not public because these should never be changed once set } -func (store *Storage) Keccak(data ...[]byte) ([]byte, error) { +func (s *Storage) Keccak(data ...[]byte) ([]byte, error) { byteCount := 0 for _, part := range data { byteCount += len(part) } cost := 30 + 6*arbmath.WordsForBytes(uint64(byteCount)) - if err := store.burner.Burn(cost); err != nil { + if err := s.burner.Burn(cost); err != nil { return nil, err } return crypto.Keccak256(data...), nil } +func (s *Storage) KeccakHash(data ...[]byte) (common.Hash, error) { + bytes, err := s.Keccak(data...) + return common.BytesToHash(bytes), err +} + +// Returns crypto.Keccak256 result for the given data +// If available the result is taken from hash cache +// otherwise crypto.Keccak256 is executed and its result is added to the cache and returned +// note: the method doesn't burn gas, as it's only intended for generating storage subspace keys and mapping slot addresses // note: returned slice is not thread-safe -func (store *Storage) cachedKeccak(data ...[]byte) []byte { - if store.hashCache == nil { +func (s *Storage) cachedKeccak(data ...[]byte) []byte { + if s.hashCache == nil { return crypto.Keccak256(data...) } keyString := string(bytes.Join(data, []byte{})) - hash, wasCached := store.hashCache.Get(keyString) - if wasCached { + if hash, wasCached := s.hashCache.Get(keyString); wasCached { return hash } - hash = crypto.Keccak256(data...) - evicted := store.hashCache.Add(keyString, hash) + hash := crypto.Keccak256(data...) + evicted := s.hashCache.Add(keyString, hash) if evicted && cacheFullLogged.CompareAndSwap(false, true) { log.Warn("Hash cache full, we didn't expect that. Some non-static storage keys may fill up the cache.") } return hash } -func (store *Storage) KeccakHash(data ...[]byte) (common.Hash, error) { - bytes, err := store.Keccak(data...) - return common.BytesToHash(bytes), err -} - type StorageSlot struct { account common.Address db vm.StateDB @@ -319,8 +329,8 @@ type StorageSlot struct { burner burn.Burner } -func (store *Storage) NewSlot(offset uint64) StorageSlot { - return StorageSlot{store.account, store.db, store.mapAddress(util.UintToHash(offset)), store.burner} +func (s *Storage) NewSlot(offset uint64) StorageSlot { + return StorageSlot{s.account, s.db, s.mapAddress(util.UintToHash(offset)), s.burner} } func (ss *StorageSlot) Get() (common.Hash, error) { @@ -359,8 +369,8 @@ type StorageBackedInt64 struct { StorageSlot } -func (store *Storage) OpenStorageBackedInt64(offset uint64) StorageBackedInt64 { - return StorageBackedInt64{store.NewSlot(offset)} +func (s *Storage) OpenStorageBackedInt64(offset uint64) StorageBackedInt64 { + return StorageBackedInt64{s.NewSlot(offset)} } func (sbu *StorageBackedInt64) Get() (int64, error) { @@ -380,8 +390,8 @@ type StorageBackedBips struct { backing StorageBackedInt64 } -func (store *Storage) OpenStorageBackedBips(offset uint64) StorageBackedBips { - return StorageBackedBips{StorageBackedInt64{store.NewSlot(offset)}} +func (s *Storage) OpenStorageBackedBips(offset uint64) StorageBackedBips { + return StorageBackedBips{StorageBackedInt64{s.NewSlot(offset)}} } func (sbu *StorageBackedBips) Get() (arbmath.Bips, error) { @@ -397,8 +407,8 @@ type StorageBackedUint64 struct { StorageSlot } -func (store *Storage) OpenStorageBackedUint64(offset uint64) StorageBackedUint64 { - return StorageBackedUint64{store.NewSlot(offset)} +func (s *Storage) OpenStorageBackedUint64(offset uint64) StorageBackedUint64 { + return StorageBackedUint64{s.NewSlot(offset)} } func (sbu *StorageBackedUint64) Get() (uint64, error) { @@ -485,8 +495,8 @@ type StorageBackedBigUint struct { StorageSlot } -func (store *Storage) OpenStorageBackedBigUint(offset uint64) StorageBackedBigUint { - return StorageBackedBigUint{store.NewSlot(offset)} +func (s *Storage) OpenStorageBackedBigUint(offset uint64) StorageBackedBigUint { + return StorageBackedBigUint{s.NewSlot(offset)} } func (sbbu *StorageBackedBigUint) Get() (*big.Int, error) { @@ -524,8 +534,8 @@ type StorageBackedBigInt struct { StorageSlot } -func (store *Storage) OpenStorageBackedBigInt(offset uint64) StorageBackedBigInt { - return StorageBackedBigInt{store.NewSlot(offset)} +func (s *Storage) OpenStorageBackedBigInt(offset uint64) StorageBackedBigInt { + return StorageBackedBigInt{s.NewSlot(offset)} } func (sbbi *StorageBackedBigInt) Get() (*big.Int, error) { @@ -581,8 +591,8 @@ type StorageBackedAddress struct { StorageSlot } -func (store *Storage) OpenStorageBackedAddress(offset uint64) StorageBackedAddress { - return StorageBackedAddress{store.NewSlot(offset)} +func (s *Storage) OpenStorageBackedAddress(offset uint64) StorageBackedAddress { + return StorageBackedAddress{s.NewSlot(offset)} } func (sba *StorageBackedAddress) Get() (common.Address, error) { @@ -604,8 +614,8 @@ func init() { NilAddressRepresentation = common.BigToHash(new(big.Int).Lsh(big.NewInt(1), 255)) } -func (store *Storage) OpenStorageBackedAddressOrNil(offset uint64) StorageBackedAddressOrNil { - return StorageBackedAddressOrNil{store.NewSlot(offset)} +func (s *Storage) OpenStorageBackedAddressOrNil(offset uint64) StorageBackedAddressOrNil { + return StorageBackedAddressOrNil{s.NewSlot(offset)} } func (sba *StorageBackedAddressOrNil) Get() (*common.Address, error) { @@ -629,9 +639,9 @@ type StorageBackedBytes struct { Storage } -func (store *Storage) OpenStorageBackedBytes(id []byte) StorageBackedBytes { +func (s *Storage) OpenStorageBackedBytes(id []byte) StorageBackedBytes { return StorageBackedBytes{ - *store.OpenSubStorage(id, false), + *s.OpenSubStorage(id), } } From c234d50685f9cb967b9d91ba027f175751b38419 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 12 Oct 2023 15:08:38 -0500 Subject: [PATCH 251/775] Add a CI step to start up a dev test node --- .github/workflows/docker.yml | 8 ++++++++ .github/workflows/waitForNitro.sh | 10 ++++++++++ 2 files changed, 18 insertions(+) create mode 100755 .github/workflows/waitForNitro.sh diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 6192f65a4..fe27e6c18 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -59,6 +59,14 @@ jobs: cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + - name: Start nitro-testnode and wait for rpc to come up + shell: bash + run: | + .nitro-testnode/test-node.bash --init --dev & + jobid=$! + ${{ github.action_path }}/waitForNitro.sh + kill -s SIGKILL $jobid + - name: Print WAVM module root id: module-root run: | diff --git a/.github/workflows/waitForNitro.sh b/.github/workflows/waitForNitro.sh new file mode 100755 index 000000000..1c71298dd --- /dev/null +++ b/.github/workflows/waitForNitro.sh @@ -0,0 +1,10 @@ +# poll the nitro endpoint until we get a 0 return code +while true +do + curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":45678,"method":"eth_chainId","params":[]}' 'http://localhost:8547' + if [ "$?" -eq "0" ]; then + exit 0 + else + sleep 10 + fi +done \ No newline at end of file From 338fe2103f8241b4c00c3dcf3c512de0abd986c3 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 12 Oct 2023 14:23:15 -0600 Subject: [PATCH 252/775] Don't ignore target/machines for Docker builds --- .dockerignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.dockerignore b/.dockerignore index 05cec369d..763aeda1b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -13,6 +13,9 @@ solgen/go **/node_modules target/**/* +!target/machines +!target/machines/* +!target/machines/**/* brotli/buildfiles/**/* # these are used by environment outside the docker: From 0c4241a704448525bc94e12715d15c224cc454ed Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 12 Oct 2023 15:35:01 -0500 Subject: [PATCH 253/775] fix issue --- .github/workflows/docker.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index fe27e6c18..028790fd8 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -62,9 +62,11 @@ jobs: - name: Start nitro-testnode and wait for rpc to come up shell: bash run: | - .nitro-testnode/test-node.bash --init --dev & + cd nitro-testnode + ./test-node.bash --init --dev & jobid=$! - ${{ github.action_path }}/waitForNitro.sh + cd .. + ${{ github.workspace }}/.github/workflows/waitForNitro.sh kill -s SIGKILL $jobid - name: Print WAVM module root From 5f00974dc4997d9c84ca3700b9e9164ed7aec380 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 12 Oct 2023 16:02:33 -0500 Subject: [PATCH 254/775] use run-nitro-test-node action impl --- .github/workflows/docker.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 028790fd8..d4062cdd4 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -59,16 +59,17 @@ jobs: cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - - name: Start nitro-testnode and wait for rpc to come up + - name: Start background nitro-testnode and wait for rpc to come up shell: bash run: | cd nitro-testnode ./test-node.bash --init --dev & - jobid=$! - cd .. + + - name: Wait for rpc to come up + shell: bash + run: | ${{ github.workspace }}/.github/workflows/waitForNitro.sh - kill -s SIGKILL $jobid - + - name: Print WAVM module root id: module-root run: | From eeb327c3b7d3e81ff057f58e0fb366739610dee7 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 12 Oct 2023 23:45:59 +0200 Subject: [PATCH 255/775] replace SafeLruCache with lru.Cache from geth --- arbos/storage/storage.go | 6 +-- util/containers/safe_lru.go | 82 ------------------------------------- 2 files changed, 3 insertions(+), 85 deletions(-) delete mode 100644 util/containers/safe_lru.go diff --git a/arbos/storage/storage.go b/arbos/storage/storage.go index 47ca66445..63987b91f 100644 --- a/arbos/storage/storage.go +++ b/arbos/storage/storage.go @@ -10,6 +10,7 @@ import ( "sync/atomic" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/lru" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" @@ -19,7 +20,6 @@ import ( "github.com/offchainlabs/nitro/arbos/burn" "github.com/offchainlabs/nitro/arbos/util" "github.com/offchainlabs/nitro/util/arbmath" - "github.com/offchainlabs/nitro/util/containers" ) // Storage allows ArbOS to store data persistently in the Ethereum-compatible stateDB. This is represented in @@ -46,7 +46,7 @@ type Storage struct { db vm.StateDB storageKey []byte burner burn.Burner - hashCache *containers.SafeLruCache[string, []byte] + hashCache *lru.Cache[string, []byte] } const StorageReadCost = params.SloadGasEIP2200 @@ -55,7 +55,7 @@ const StorageWriteZeroCost = params.SstoreResetGasEIP2200 const storageKeyCacheSize = 1024 -var storageHashCache = containers.NewSafeLruCache[string, []byte](storageKeyCacheSize) +var storageHashCache = lru.NewCache[string, []byte](storageKeyCacheSize) var cacheFullLogged atomic.Bool // NewGeth uses a Geth database to create an evm key-value store diff --git a/util/containers/safe_lru.go b/util/containers/safe_lru.go deleted file mode 100644 index 40e7d993e..000000000 --- a/util/containers/safe_lru.go +++ /dev/null @@ -1,82 +0,0 @@ -package containers - -import ( - "sync" -) - -// thread safe version of containers.LruCache -type SafeLruCache[K comparable, V any] struct { - inner *LruCache[K, V] - mutex sync.RWMutex -} - -func NewSafeLruCache[K comparable, V any](size int) *SafeLruCache[K, V] { - return NewSafeLruCacheWithOnEvict[K, V](size, nil) -} - -func NewSafeLruCacheWithOnEvict[K comparable, V any](size int, onEvict func(K, V)) *SafeLruCache[K, V] { - return &SafeLruCache[K, V]{ - inner: NewLruCacheWithOnEvict(size, onEvict), - } -} - -// Returns true if an item was evicted -func (c *SafeLruCache[K, V]) Add(key K, value V) bool { - c.mutex.Lock() - defer c.mutex.Unlock() - return c.inner.Add(key, value) -} - -func (c *SafeLruCache[K, V]) Get(key K) (V, bool) { - c.mutex.Lock() - defer c.mutex.Unlock() - return c.inner.Get(key) -} - -func (c *SafeLruCache[K, V]) Contains(key K) bool { - c.mutex.RLock() - defer c.mutex.RUnlock() - return c.inner.Contains(key) -} - -func (c *SafeLruCache[K, V]) Remove(key K) { - c.mutex.Lock() - defer c.mutex.Unlock() - c.inner.Remove(key) -} - -func (c *SafeLruCache[K, V]) GetOldest() (K, V, bool) { - c.mutex.RLock() - defer c.mutex.RUnlock() - return c.inner.GetOldest() -} - -func (c *SafeLruCache[K, V]) RemoveOldest() { - c.mutex.Lock() - defer c.mutex.Unlock() - c.inner.RemoveOldest() -} - -func (c *SafeLruCache[K, V]) Len() int { - c.mutex.RLock() - defer c.mutex.RUnlock() - return c.inner.Len() -} - -func (c *SafeLruCache[K, V]) Size() int { - c.mutex.RLock() - defer c.mutex.RUnlock() - return c.inner.Size() -} - -func (c *SafeLruCache[K, V]) Clear() { - c.mutex.Lock() - defer c.mutex.Unlock() - c.inner.Clear() -} - -func (c *SafeLruCache[K, V]) Resize(newSize int) { - c.mutex.Lock() - defer c.mutex.Unlock() - c.inner.Resize(newSize) -} From 7c717797b225c7685790167e183437bad1c95dd9 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 12 Oct 2023 16:57:03 -0500 Subject: [PATCH 256/775] change image name --- .github/workflows/docker.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d4062cdd4..8e439633d 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -45,7 +45,7 @@ jobs: target: nitro-node push: true context: . - tags: localhost:5000/nitro-node:latest + tags: nitro-node:latest cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max @@ -55,11 +55,11 @@ jobs: target: nitro-node-dev push: true context: . - tags: localhost:5000/nitro-node-dev:latest + tags: nitro-node-dev:latest cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - - name: Start background nitro-testnode and wait for rpc to come up + - name: Start background nitro-testnode shell: bash run: | cd nitro-testnode @@ -75,7 +75,7 @@ jobs: run: | # Unfortunately, `docker cp` seems to always result in a "permission denied" # We work around this by piping a tarball through stdout - docker run --rm --entrypoint tar localhost:5000/nitro-node-dev:latest -cf - target/machines/latest | tar xf - + docker run --rm --entrypoint tar nitro-node-dev:latest -cf - target/machines/latest | tar xf - module_root="$(cat "target/machines/latest/module-root.txt")" echo "name=module-root=$module_root" >> $GITHUB_STATE echo -e "\x1b[1;34mWAVM module root:\x1b[0m $module_root" From 6f1c79fca98a5a2eec1c9302f4bb751c2599064f Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 13 Oct 2023 00:20:15 +0200 Subject: [PATCH 257/775] add todos for renaming packages --- arbos/addressSet/addressSet.go | 2 ++ arbos/addressTable/addressTable.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arbos/addressSet/addressSet.go b/arbos/addressSet/addressSet.go index 50a43c36c..6d2db2694 100644 --- a/arbos/addressSet/addressSet.go +++ b/arbos/addressSet/addressSet.go @@ -3,6 +3,8 @@ package addressSet +// TODO rename this package to lowercase + import ( "errors" diff --git a/arbos/addressTable/addressTable.go b/arbos/addressTable/addressTable.go index f44e7f3dc..bfc526d39 100644 --- a/arbos/addressTable/addressTable.go +++ b/arbos/addressTable/addressTable.go @@ -3,6 +3,8 @@ package addressTable +// TODO rename this package to lowercase + import ( "bytes" "errors" From 9ec92bc55121f2c54571268b567a9249d5680060 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 13 Oct 2023 00:22:01 +0200 Subject: [PATCH 258/775] rephrase todos --- arbos/addressSet/addressSet.go | 2 +- arbos/addressTable/addressTable.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arbos/addressSet/addressSet.go b/arbos/addressSet/addressSet.go index 6d2db2694..1f09ff144 100644 --- a/arbos/addressSet/addressSet.go +++ b/arbos/addressSet/addressSet.go @@ -3,7 +3,7 @@ package addressSet -// TODO rename this package to lowercase +// TODO lowercase this package name import ( "errors" diff --git a/arbos/addressTable/addressTable.go b/arbos/addressTable/addressTable.go index bfc526d39..3fbb7b378 100644 --- a/arbos/addressTable/addressTable.go +++ b/arbos/addressTable/addressTable.go @@ -3,7 +3,7 @@ package addressTable -// TODO rename this package to lowercase +// TODO lowercase this package name import ( "bytes" From c9c731ee008685157532f46c277b6a683b1ebab4 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 12 Oct 2023 17:52:00 -0500 Subject: [PATCH 259/775] update nitro-testnode pin --- .github/workflows/docker.yml | 7 ++++--- nitro-testnode | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 8e439633d..a6f9c4b9a 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -45,7 +45,7 @@ jobs: target: nitro-node push: true context: . - tags: nitro-node:latest + tags: localhost:5000/nitro-node:latest cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max @@ -55,13 +55,14 @@ jobs: target: nitro-node-dev push: true context: . - tags: nitro-node-dev:latest + tags: localhost:5000/nitro-node-dev:latest cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - name: Start background nitro-testnode shell: bash run: | + docker tag localhost:5000/nitro-node-dev:latest nitro-node-dev-testnode:latest cd nitro-testnode ./test-node.bash --init --dev & @@ -75,7 +76,7 @@ jobs: run: | # Unfortunately, `docker cp` seems to always result in a "permission denied" # We work around this by piping a tarball through stdout - docker run --rm --entrypoint tar nitro-node-dev:latest -cf - target/machines/latest | tar xf - + docker run --rm --entrypoint tar localhost:5000/nitro-node-dev:latest -cf - target/machines/latest | tar xf - module_root="$(cat "target/machines/latest/module-root.txt")" echo "name=module-root=$module_root" >> $GITHUB_STATE echo -e "\x1b[1;34mWAVM module root:\x1b[0m $module_root" diff --git a/nitro-testnode b/nitro-testnode index 7ad12c0f1..86fc5f627 160000 --- a/nitro-testnode +++ b/nitro-testnode @@ -1 +1 @@ -Subproject commit 7ad12c0f1be75a72c7360d5258e0090f8225594e +Subproject commit 86fc5f6275c0269b5a5105bf78c1627d03b0ef9e From e7f1155548699efef9c4c0f8282336355aac9521 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 13 Oct 2023 10:38:09 +0200 Subject: [PATCH 260/775] Use develop branch --- .gitmodules | 2 +- contracts | 2 +- nitro-testnode | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 75e66a648..977f7a477 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,7 +13,7 @@ [submodule "contracts"] path = contracts url = https://github.com/OffchainLabs/nitro-contracts.git - branch = feature-orbit-bridge + branch = develop [submodule "arbitrator/wasm-testsuite/testsuite"] path = arbitrator/wasm-testsuite/testsuite url = https://github.com/WebAssembly/testsuite.git diff --git a/contracts b/contracts index 7dc1aa438..46d1767ce 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 7dc1aa43829d9f4afe7251ad28d96a5d0e1d48c7 +Subproject commit 46d1767ce2181c501f6b1f8651d6f1ace3da1c41 diff --git a/nitro-testnode b/nitro-testnode index 441166624..82a072dde 160000 --- a/nitro-testnode +++ b/nitro-testnode @@ -1 +1 @@ -Subproject commit 441166624c54857a11c0a880f12e19d7dbeebc69 +Subproject commit 82a072dde9f82ac57bd9ff4306dae7c36c980dba From 61afda47e78d76b74d1c0f2df2d397a459b77864 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 13 Oct 2023 13:19:37 +0200 Subject: [PATCH 261/775] Fix ChallengeManager tests How latest confirmed/finalized block is calculated is changed for SimulatedBeacon so this test needs more filler transactions to get the needed blocks to be finalized. --- system_tests/full_challenge_impl_test.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index b64a655c3..a49cfa308 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -181,7 +181,10 @@ func makeBatch(t *testing.T, l2Node *arbnode.Node, l2Info *BlockchainTestInfo, b } func confirmLatestBlock(ctx context.Context, t *testing.T, l1Info *BlockchainTestInfo, backend arbutil.L1Interface) { - for i := 0; i < 12; i++ { + // With SimulatedBeacon running in on-demand block production mode, the + // finalized block is considered to be be the nearest multiple of 32 less + // than or equal to the block number. + for i := 0; i < 32; i++ { SendWaitTestTransactions(t, ctx, backend, []*types.Transaction{ l1Info.PrepareTx("Faucet", "Faucet", 30000, big.NewInt(1e12), nil), }) @@ -403,6 +406,8 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall Fatal(t, err) } + confirmLatestBlock(ctx, t, l1Info, l1Backend) + for i := 0; i < 100; i++ { var tx *types.Transaction var currentCorrect bool From 1539963fd93443ed37397397818ccd3c46ebe59b Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 13 Oct 2023 15:13:26 +0200 Subject: [PATCH 262/775] Fix maxDataSize leftovers --- arbnode/node.go | 20 ++++++++++---------- system_tests/common_test.go | 1 + system_tests/full_challenge_impl_test.go | 1 + 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index ea09aab25..675aca336 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -98,11 +98,11 @@ func deployBridgeCreator(ctx context.Context, l1Reader *headerreader.HeaderReade } ethBasedTemplates := rollupgen.BridgeCreatorBridgeContracts{ - Bridge: bridgeTemplate, - SequencerInbox: seqInboxTemplate, - Inbox: inboxTemplate, - RollupEventInbox:rollupEventBridgeTemplate, - Outbox: outboxTemplate, + Bridge: bridgeTemplate, + SequencerInbox: seqInboxTemplate, + Inbox: inboxTemplate, + RollupEventInbox: rollupEventBridgeTemplate, + Outbox: outboxTemplate, } /// deploy ERC20 based templates @@ -131,11 +131,11 @@ func deployBridgeCreator(ctx context.Context, l1Reader *headerreader.HeaderReade } erc20BasedTemplates := rollupgen.BridgeCreatorBridgeContracts{ - Bridge: erc20BridgeTemplate, - SequencerInbox: seqInboxTemplate, - Inbox: erc20InboxTemplate, - RollupEventInbox:erc20RollupEventBridgeTemplate, - Outbox: erc20OutboxTemplate, + Bridge: erc20BridgeTemplate, + SequencerInbox: seqInboxTemplate, + Inbox: erc20InboxTemplate, + RollupEventInbox: erc20RollupEventBridgeTemplate, + Outbox: erc20OutboxTemplate, } bridgeCreatorAddr, tx, _, err := rollupgen.DeployBridgeCreator(auth, client, ethBasedTemplates, erc20BasedTemplates) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index b3965c5c8..525dada68 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -490,6 +490,7 @@ func DeployOnTestL1( 0, arbnode.GenerateRollupConfig(false, locator.LatestWasmModuleRoot(), l1info.GetAddress("RollupOwner"), chainConfig, serializedChainConfig, common.Address{}), common.Address{}, + big.NewInt(117964), ) Require(t, err) l1info.SetContract("Bridge", addresses.Bridge) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index 99064d191..f22960c39 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -207,6 +207,7 @@ func setupSequencerInboxStub(ctx context.Context, t *testing.T, l1Info *Blockcha bridgeAddr, l1Info.GetAddress("sequencer"), timeBounds, + big.NewInt(117964), ) Require(t, err) _, err = EnsureTxSucceeded(ctx, l1Client, tx) From a809568398360015c35f2c8eb2a0676251c27a88 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 13 Oct 2023 09:33:48 -0500 Subject: [PATCH 263/775] init only --- .github/workflows/docker.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a6f9c4b9a..ce92be513 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -62,9 +62,8 @@ jobs: - name: Start background nitro-testnode shell: bash run: | - docker tag localhost:5000/nitro-node-dev:latest nitro-node-dev-testnode:latest cd nitro-testnode - ./test-node.bash --init --dev & + ./test-node.bash --init & - name: Wait for rpc to come up shell: bash From a619d43bbd811870a5c08156959d1689343c1f6f Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Fri, 13 Oct 2023 16:55:09 +0200 Subject: [PATCH 264/775] Implement external signer for dataposter --- arbnode/batch_poster.go | 9 +- arbnode/dataposter/data_poster.go | 153 +++++++++++++------ arbnode/dataposter/dataposter_test.go | 210 ++++++++++++++++++++++++++ arbnode/maintenance.go | 1 + arbnode/node.go | 1 + arbnode/redislock/redis.go | 2 +- broadcastclient/broadcastclient.go | 2 +- cmd/genericconf/config.go | 2 +- cmd/genericconf/server.go | 6 +- cmd/nitro/config_test.go | 19 +++ cmd/nitro/nitro.go | 7 + cmd/rpcsvr/main.go | 134 ++++++++++++++++ das/das.go | 1 + execution/gethexec/node.go | 1 + staker/block_validator.go | 2 +- staker/staker.go | 2 +- util/headerreader/header_reader.go | 1 + util/signature/sign_verify.go | 6 + util/signature/sign_verify_test.go | 6 +- util/signature/verifier.go | 2 +- 20 files changed, 507 insertions(+), 60 deletions(-) create mode 100644 cmd/rpcsvr/main.go diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 76ff8e6a5..acf655e4c 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" + "github.com/offchainlabs/nitro/arbnode/dataposter" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbnode/redislock" @@ -47,6 +48,7 @@ import ( var ( batchPosterWalletBalance = metrics.NewRegisteredGaugeFloat64("arb/batchposter/wallet/balanceether", nil) batchPosterGasRefunderBalance = metrics.NewRegisteredGaugeFloat64("arb/batchposter/gasrefunder/balanceether", nil) + batchPosterSimpleRedisLockKey = "node.batch-poster.redis-lock.simple-lock-key" ) type batchPosterPosition struct { @@ -166,7 +168,7 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".l1-block-bound", DefaultBatchPosterConfig.L1BlockBound, "only post messages to batches when they're within the max future block/timestamp as of this L1 block tag (\"safe\", \"finalized\", \"latest\", or \"ignore\" to ignore this check)") f.Duration(prefix+".l1-block-bound-bypass", DefaultBatchPosterConfig.L1BlockBoundBypass, "post batches even if not within the layer 1 future bounds if we're within this margin of the max delay") redislock.AddConfigOptions(prefix+".redis-lock", f) - dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f) + dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f, dataposter.DefaultDataPosterConfig) genericconf.WalletConfigAddOptions(prefix+".parent-chain-wallet", f, DefaultBatchPosterConfig.ParentChainWallet.Pathname) } @@ -187,6 +189,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ ParentChainWallet: DefaultBatchPosterL1WalletConfig, L1BlockBound: "", L1BlockBoundBypass: time.Hour, + RedisLock: redislock.DefaultCfg, } var DefaultBatchPosterL1WalletConfig = genericconf.WalletConfig{ @@ -235,7 +238,9 @@ func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader * return nil, err } redisLockConfigFetcher := func() *redislock.SimpleCfg { - return &config().RedisLock + simpleRedisLockConfig := config().RedisLock + simpleRedisLockConfig.Key = batchPosterSimpleRedisLockKey + return &simpleRedisLockConfig } redisLock, err := redislock.NewSimple(redisClient, redisLockConfigFetcher, func() bool { return syncMonitor.Synced() }) if err != nil { diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 91bdf39d5..c8a673ec9 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" @@ -47,7 +48,7 @@ type DataPoster struct { headerReader *headerreader.HeaderReader client arbutil.L1Interface sender common.Address - signer bind.SignerFn + signer signerFn redisLock AttemptLocker config ConfigFetcher replacementTimes []time.Duration @@ -66,6 +67,11 @@ type DataPoster struct { errorCount map[uint64]int // number of consecutive intermittent errors rbf-ing or sending, per nonce } +// signerFn is a signer function callback when a contract requires a method to +// sign the transaction before submission. +// This can be local or external, hence the context parameter. +type signerFn func(context.Context, common.Address, *types.Transaction) (*types.Transaction, error) + type AttemptLocker interface { AttemptLock(context.Context) bool } @@ -103,13 +109,13 @@ type DataPosterOpts struct { } func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, error) { - initConfig := opts.Config() - replacementTimes, err := parseReplacementTimes(initConfig.ReplacementTimes) + cfg := opts.Config() + replacementTimes, err := parseReplacementTimes(cfg.ReplacementTimes) if err != nil { return nil, err } - if opts.HeaderReader.IsParentChainArbitrum() && !initConfig.UseNoOpStorage { - initConfig.UseNoOpStorage = true + if opts.HeaderReader.IsParentChainArbitrum() && !cfg.UseNoOpStorage { + cfg.UseNoOpStorage = true log.Info("Disabling data poster storage, as parent chain appears to be an Arbitrum chain without a mempool") } encF := func() storage.EncoderDecoderInterface { @@ -120,17 +126,17 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro } var queue QueueStorage switch { - case initConfig.UseNoOpStorage: + case cfg.UseNoOpStorage: queue = &noop.Storage{} case opts.RedisClient != nil: var err error - queue, err = redisstorage.NewStorage(opts.RedisClient, opts.RedisKey, &initConfig.RedisSigner, encF) + queue, err = redisstorage.NewStorage(opts.RedisClient, opts.RedisKey, &cfg.RedisSigner, encF) if err != nil { return nil, err } - case initConfig.UseDBStorage: + case cfg.UseDBStorage: storage := dbstorage.New(opts.Database, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) - if initConfig.Dangerous.ClearDBStorage { + if cfg.Dangerous.ClearDBStorage { if err := storage.PruneAll(ctx); err != nil { return nil, err } @@ -139,18 +145,53 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro default: queue = slice.NewStorage(func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) } - return &DataPoster{ - headerReader: opts.HeaderReader, - client: opts.HeaderReader.Client(), - sender: opts.Auth.From, - signer: opts.Auth.Signer, + dp := &DataPoster{ + headerReader: opts.HeaderReader, + client: opts.HeaderReader.Client(), + sender: opts.Auth.From, + signer: func(_ context.Context, addr common.Address, tx *types.Transaction) (*types.Transaction, error) { + return opts.Auth.Signer(addr, tx) + }, config: opts.Config, replacementTimes: replacementTimes, metadataRetriever: opts.MetadataRetriever, queue: queue, redisLock: opts.RedisLock, errorCount: make(map[uint64]int), - }, nil + } + if cfg.ExternalSigner.Enabled { + signer, sender, err := externalSigner(ctx, cfg.ExternalSigner.Address, cfg.ExternalSigner.URL) + if err != nil { + return nil, err + } + dp.signer, dp.sender = signer, sender + } + return dp, nil +} + +// externalSigner returns signer function and ethereum address of the signer. +// Returns an error if address isn't specified or if it can't connect to the +// signer RPC server. +func externalSigner(ctx context.Context, addr string, rpcURL string) (signerFn, common.Address, error) { + if addr == "" { + return nil, common.Address{}, errors.New("external signer (From) address specified") + } + sender := common.HexToAddress(addr) + client, err := rpc.DialContext(ctx, rpcURL) + if err != nil { + return nil, common.Address{}, fmt.Errorf("error connecting external signer: %w", err) + } + return func(ctx context.Context, addr common.Address, tx *types.Transaction) (*types.Transaction, error) { + data, err := tx.MarshalBinary() + if err != nil { + return nil, err + } + var signedTx *types.Transaction + if err := client.CallContext(ctx, &signedTx, "eth_signTransaction", hexutil.Encode(data)); err != nil { + return nil, fmt.Errorf("error calling with context: %w", err) + } + return signedTx, nil + }, sender, nil } func (p *DataPoster) Sender() common.Address { @@ -371,7 +412,7 @@ func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Tim Data: calldata, AccessList: accessList, } - fullTx, err := p.signer(p.sender, types.NewTx(&inner)) + fullTx, err := p.signer(ctx, p.sender, types.NewTx(&inner)) if err != nil { return nil, fmt.Errorf("signing transaction: %w", err) } @@ -450,7 +491,7 @@ func (p *DataPoster) replaceTx(ctx context.Context, prevTx *storage.QueuedTransa newTx.Sent = false newTx.Data.GasFeeCap = newFeeCap newTx.Data.GasTipCap = newTipCap - newTx.FullTx, err = p.signer(p.sender, types.NewTx(&newTx.Data)) + newTx.FullTx, err = p.signer(ctx, p.sender, types.NewTx(&newTx.Data)) if err != nil { return err } @@ -636,20 +677,31 @@ type DataPosterConfig struct { ReplacementTimes string `koanf:"replacement-times"` // This is forcibly disabled if the parent chain is an Arbitrum chain, // so you should probably use DataPoster's waitForL1Finality method instead of reading this field directly. - WaitForL1Finality bool `koanf:"wait-for-l1-finality" reload:"hot"` - MaxMempoolTransactions uint64 `koanf:"max-mempool-transactions" reload:"hot"` - MaxQueuedTransactions int `koanf:"max-queued-transactions" reload:"hot"` - TargetPriceGwei float64 `koanf:"target-price-gwei" reload:"hot"` - UrgencyGwei float64 `koanf:"urgency-gwei" reload:"hot"` - MinFeeCapGwei float64 `koanf:"min-fee-cap-gwei" reload:"hot"` - MinTipCapGwei float64 `koanf:"min-tip-cap-gwei" reload:"hot"` - MaxTipCapGwei float64 `koanf:"max-tip-cap-gwei" reload:"hot"` - NonceRbfSoftConfs uint64 `koanf:"nonce-rbf-soft-confs" reload:"hot"` - AllocateMempoolBalance bool `koanf:"allocate-mempool-balance" reload:"hot"` - UseDBStorage bool `koanf:"use-db-storage"` - UseNoOpStorage bool `koanf:"use-noop-storage"` - LegacyStorageEncoding bool `koanf:"legacy-storage-encoding" reload:"hot"` - Dangerous DangerousConfig `koanf:"dangerous"` + WaitForL1Finality bool `koanf:"wait-for-l1-finality" reload:"hot"` + MaxMempoolTransactions uint64 `koanf:"max-mempool-transactions" reload:"hot"` + MaxQueuedTransactions int `koanf:"max-queued-transactions" reload:"hot"` + TargetPriceGwei float64 `koanf:"target-price-gwei" reload:"hot"` + UrgencyGwei float64 `koanf:"urgency-gwei" reload:"hot"` + MinFeeCapGwei float64 `koanf:"min-fee-cap-gwei" reload:"hot"` + MinTipCapGwei float64 `koanf:"min-tip-cap-gwei" reload:"hot"` + MaxTipCapGwei float64 `koanf:"max-tip-cap-gwei" reload:"hot"` + NonceRbfSoftConfs uint64 `koanf:"nonce-rbf-soft-confs" reload:"hot"` + AllocateMempoolBalance bool `koanf:"allocate-mempool-balance" reload:"hot"` + UseDBStorage bool `koanf:"use-db-storage"` + UseNoOpStorage bool `koanf:"use-noop-storage"` + LegacyStorageEncoding bool `koanf:"legacy-storage-encoding" reload:"hot"` + Dangerous DangerousConfig `koanf:"dangerous"` + ExternalSigner ExternalSignerCfg `koanf:"external-signer"` +} + +type ExternalSignerCfg struct { + // If enabled, this overrides transaction options and uses external signer + // for signing transactions. + Enabled bool `koanf:"enabled"` + // URL of the external signer rpc server. + URL string `koanf:"url"` + // Hex encoded ethereum address of the external signer. + Address string `koanf:"address"` } type DangerousConfig struct { @@ -662,30 +714,37 @@ type DangerousConfig struct { // that flags can be reloaded dynamically. type ConfigFetcher func() *DataPosterConfig -func DataPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { - f.String(prefix+".replacement-times", DefaultDataPosterConfig.ReplacementTimes, "comma-separated list of durations since first posting to attempt a replace-by-fee") - f.Bool(prefix+".wait-for-l1-finality", DefaultDataPosterConfig.WaitForL1Finality, "only treat a transaction as confirmed after L1 finality has been achieved (recommended)") - f.Uint64(prefix+".max-mempool-transactions", DefaultDataPosterConfig.MaxMempoolTransactions, "the maximum number of transactions to have queued in the mempool at once (0 = unlimited)") - f.Int(prefix+".max-queued-transactions", DefaultDataPosterConfig.MaxQueuedTransactions, "the maximum number of unconfirmed transactions to track at once (0 = unlimited)") - f.Float64(prefix+".target-price-gwei", DefaultDataPosterConfig.TargetPriceGwei, "the target price to use for maximum fee cap calculation") - f.Float64(prefix+".urgency-gwei", DefaultDataPosterConfig.UrgencyGwei, "the urgency to use for maximum fee cap calculation") - f.Float64(prefix+".min-fee-cap-gwei", DefaultDataPosterConfig.MinFeeCapGwei, "the minimum fee cap to post transactions at") - f.Float64(prefix+".min-tip-cap-gwei", DefaultDataPosterConfig.MinTipCapGwei, "the minimum tip cap to post transactions at") - f.Float64(prefix+".max-tip-cap-gwei", DefaultDataPosterConfig.MaxTipCapGwei, "the maximum tip cap to post transactions at") - f.Uint64(prefix+".nonce-rbf-soft-confs", DefaultDataPosterConfig.NonceRbfSoftConfs, "the maximum probable reorg depth, used to determine when a transaction will no longer likely need replaced-by-fee") - f.Bool(prefix+".allocate-mempool-balance", DefaultDataPosterConfig.AllocateMempoolBalance, "if true, don't put transactions in the mempool that spend a total greater than the batch poster's balance") - f.Bool(prefix+".use-db-storage", DefaultDataPosterConfig.UseDBStorage, "uses database storage when enabled") - f.Bool(prefix+".use-noop-storage", DefaultDataPosterConfig.UseNoOpStorage, "uses noop storage, it doesn't store anything") - f.Bool(prefix+".legacy-storage-encoding", DefaultDataPosterConfig.LegacyStorageEncoding, "encodes items in a legacy way (as it was before dropping generics)") +func DataPosterConfigAddOptions(prefix string, f *pflag.FlagSet, defaultDataPosterConfig DataPosterConfig) { + f.String(prefix+".replacement-times", defaultDataPosterConfig.ReplacementTimes, "comma-separated list of durations since first posting to attempt a replace-by-fee") + f.Bool(prefix+".wait-for-l1-finality", defaultDataPosterConfig.WaitForL1Finality, "only treat a transaction as confirmed after L1 finality has been achieved (recommended)") + f.Uint64(prefix+".max-mempool-transactions", defaultDataPosterConfig.MaxMempoolTransactions, "the maximum number of transactions to have queued in the mempool at once (0 = unlimited)") + f.Int(prefix+".max-queued-transactions", defaultDataPosterConfig.MaxQueuedTransactions, "the maximum number of unconfirmed transactions to track at once (0 = unlimited)") + f.Float64(prefix+".target-price-gwei", defaultDataPosterConfig.TargetPriceGwei, "the target price to use for maximum fee cap calculation") + f.Float64(prefix+".urgency-gwei", defaultDataPosterConfig.UrgencyGwei, "the urgency to use for maximum fee cap calculation") + f.Float64(prefix+".min-fee-cap-gwei", defaultDataPosterConfig.MinFeeCapGwei, "the minimum fee cap to post transactions at") + f.Float64(prefix+".min-tip-cap-gwei", defaultDataPosterConfig.MinTipCapGwei, "the minimum tip cap to post transactions at") + f.Float64(prefix+".max-tip-cap-gwei", defaultDataPosterConfig.MaxTipCapGwei, "the maximum tip cap to post transactions at") + f.Uint64(prefix+".nonce-rbf-soft-confs", defaultDataPosterConfig.NonceRbfSoftConfs, "the maximum probable reorg depth, used to determine when a transaction will no longer likely need replaced-by-fee") + f.Bool(prefix+".allocate-mempool-balance", defaultDataPosterConfig.AllocateMempoolBalance, "if true, don't put transactions in the mempool that spend a total greater than the batch poster's balance") + f.Bool(prefix+".use-db-storage", defaultDataPosterConfig.UseDBStorage, "uses database storage when enabled") + f.Bool(prefix+".use-noop-storage", defaultDataPosterConfig.UseNoOpStorage, "uses noop storage, it doesn't store anything") + f.Bool(prefix+".legacy-storage-encoding", defaultDataPosterConfig.LegacyStorageEncoding, "encodes items in a legacy way (as it was before dropping generics)") signature.SimpleHmacConfigAddOptions(prefix+".redis-signer", f) addDangerousOptions(prefix+".dangerous", f) + addExternalSignerOptions(prefix+".external-signer", f) } func addDangerousOptions(prefix string, f *pflag.FlagSet) { f.Bool(prefix+".clear-dbstorage", DefaultDataPosterConfig.Dangerous.ClearDBStorage, "clear database storage") } +func addExternalSignerOptions(prefix string, f *pflag.FlagSet) { + f.Bool(prefix+".enabled", DefaultDataPosterConfig.ExternalSigner.Enabled, "enable external signer") + f.String(prefix+".url", DefaultDataPosterConfig.ExternalSigner.URL, "external signer url") + f.String(prefix+".address", DefaultDataPosterConfig.ExternalSigner.Address, "external signer address") +} + var DefaultDataPosterConfig = DataPosterConfig{ ReplacementTimes: "5m,10m,20m,30m,1h,2h,4h,6h,8h,12h,16h,18h,20h,22h", WaitForL1Finality: true, @@ -700,6 +759,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ UseNoOpStorage: false, LegacyStorageEncoding: true, Dangerous: DangerousConfig{ClearDBStorage: false}, + ExternalSigner: ExternalSignerCfg{Enabled: false}, } var DefaultDataPosterConfigForValidator = func() DataPosterConfig { @@ -721,6 +781,7 @@ var TestDataPosterConfig = DataPosterConfig{ AllocateMempoolBalance: true, UseDBStorage: false, UseNoOpStorage: false, + ExternalSigner: ExternalSignerCfg{Enabled: false}, } var TestDataPosterConfigForValidator = func() DataPosterConfig { diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index b8a9c3e49..c4c131c79 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -1,9 +1,21 @@ package dataposter import ( + "context" + "encoding/json" + "fmt" + "io" + "log" + "math/big" + "net/http" "testing" "time" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" "github.com/google/go-cmp/cmp" ) @@ -41,3 +53,201 @@ func TestParseReplacementTimes(t *testing.T) { }) } } + +type Args struct { + Name string +} + +func TestRPC(t *testing.T) { + srv, err := newServer() + if err != nil { + fmt.Printf("Erorr creating server: %v", err) + return + } + http.HandleFunc("/", srv.mux) + go func() { + fmt.Println("Server is listening on port 1234...") + t.Errorf("error listening: %v", http.ListenAndServe(":1234", nil)) + }() + + if err != nil { + t.Fatalf("Error creating a server: %v", err) + } + ctx := context.Background() + signer, addr, err := externalSigner(ctx, srv.address.Hex(), "http://127.0.0.1:1234") + if err != nil { + t.Fatalf("Error getting external signer: %v", err) + } + tx := types.NewTransaction(0, common.HexToAddress("0x01"), big.NewInt(0), 3000000, big.NewInt(30000), nil) + signedTx, err := signer(ctx, addr, tx) + if err != nil { + t.Errorf("Error signing transaction: %v", err) + } + if diff := cmp.Diff(signedTx, tx); diff != "" { + t.Errorf("diff: %v\n", diff) + } + +} + +// func setupServer(t *testing.T) { +// t.Skip() +// t.Helper() +// srv, err := newServer() +// if err != nil { +// fmt.Printf("Erorr creating server: %v", err) +// return +// } +// http.HandleFunc("/", srv.mux) +// fmt.Println("Server is listening on port 1234...") +// t.Fatal(http.ListenAndServe(":1234", nil)) +// } + +type SigningService struct{} + +func (h *SigningService) SignTx(r *http.Request, args *Args, reply *string) error { + *reply = "Hello, " + args.Name + "!" + return nil +} + +type server struct { + handlers map[string]func(*json.RawMessage) (string, error) + signerFn bind.SignerFn + address common.Address +} + +type request struct { + ID *json.RawMessage `json:"id"` + Method string `json:"method"` + Params *json.RawMessage `json:"params"` +} + +type response struct { + ID *json.RawMessage `json:"id"` + Result string `json:"result"` +} + +func newServer() (*server, error) { + signer, address, err := setupAccount("/tmp/keystore") + if err != nil { + return nil, err + } + s := &server{ + signerFn: signer, + address: address, + } + s.handlers = map[string]func(*json.RawMessage) (string, error){ + "eth_signTransaction": s.signTransaction, + } + return s, nil +} + +func setupAccount(dir string) (bind.SignerFn, common.Address, error) { + ks := keystore.NewKeyStore( + dir, + keystore.StandardScryptN, + keystore.StandardScryptP, + ) + a, err := ks.NewAccount("password") + if err != nil { + return nil, common.Address{}, fmt.Errorf("creating account account: %w", err) + } + if err := ks.Unlock(a, "password"); err != nil { + return nil, common.Address{}, fmt.Errorf("unlocking account: %w", err) + } + log.Printf("Created account: %s", a.Address.Hex()) + txOpts, err := bind.NewKeyStoreTransactorWithChainID(ks, a, big.NewInt(1)) + if err != nil { + return nil, common.Address{}, fmt.Errorf("creating transactor: %w", err) + } + return txOpts.Signer, a.Address, nil +} + +// UnmarshallFirst unmarshalls slice of params and returns the first one. +// Parameters in Go ethereum RPC calls are marashalled as slices. E.g. +// eth_sendRawTransaction or eth_signTransaction, marshall transaction as a +// slice of transactions in a message: +// https://github.com/ethereum/go-ethereum/blob/0004c6b229b787281760b14fb9460ffd9c2496f1/rpc/client.go#L548 +func unmarshallFirst(params []byte) (any, error) { + var arr []any + if err := json.Unmarshal(params, &arr); err != nil { + return "", fmt.Errorf("unmarshaling first param: %w", err) + } + return arr[0], nil +} + +// func unmarshallTx(params *json.RawMessage) (*types.Transaction, error) { + +// } + +func encodeTx(tx *types.Transaction) (string, error) { + data, err := tx.MarshalBinary() + if err != nil { + return "", err + } + return hexutil.Encode(data), nil +} + +func (s *server) signTransaction(params *json.RawMessage) (string, error) { + param, err := unmarshallFirst(*params) + if err != nil { + return "", err + } + + fmt.Printf("anodar first parameter: %q\n", param) + data, err := hexutil.Decode("0xe280827530832dc6c09400000000000000000000000000000000000000018080808080") + if err != nil { + return "", fmt.Errorf("decoding hex: %w", err) + } + fmt.Printf("decoded data: %v\n", data) + var tx types.Transaction + if err := tx.UnmarshalBinary(data); err != nil { + return "", fmt.Errorf("unmarshaling tx: %w", err) + } + fmt.Printf("tx: %v\n", tx) + return encodeTx(&tx) + // var txs []*types.Transaction + // for _, arg := range args { + // signedTx, err := s.signerFn(s.address, arg) + // if err != nil { + // return "", fmt.Errorf("signing transaction: %w", err) + // } + // txs = append(txs, signedTx) + // } + // enc, err := rlp.EncodeToBytes(txs) + // if err != nil { + // return "", fmt.Errorf("encoding transactions to bytes: %w", err) + // } + // return hexutil.Encode(enc), nil +} + +func (s *server) mux(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "can't read body", http.StatusBadRequest) + return + } + var req request + if err := json.Unmarshal(body, &req); err != nil { + http.Error(w, "can't unmarshal JSON request", http.StatusBadRequest) + return + } + method, ok := s.handlers[req.Method] + if !ok { + http.Error(w, "method not found", http.StatusNotFound) + return + } + result, err := method(req.Params) + if err != nil { + fmt.Printf("error calling method: %v\n", err) + http.Error(w, "error calling method", http.StatusInternalServerError) + return + } + resp := response{ID: req.ID, Result: result} + respBytes, err := json.Marshal(resp) + if err != nil { + http.Error(w, "error encoding response", http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + w.Write(respBytes) +} diff --git a/arbnode/maintenance.go b/arbnode/maintenance.go index f5b937cd0..53d038a0f 100644 --- a/arbnode/maintenance.go +++ b/arbnode/maintenance.go @@ -78,6 +78,7 @@ func MaintenanceConfigAddOptions(prefix string, f *flag.FlagSet) { var DefaultMaintenanceConfig = MaintenanceConfig{ TimeOfDay: "", + Lock: redislock.DefaultCfg, minutesAfterMidnight: 0, } diff --git a/arbnode/node.go b/arbnode/node.go index bf57b1c00..5d06264b6 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -370,6 +370,7 @@ var ConfigDefault = Config{ Dangerous: DefaultDangerousConfig, TransactionStreamer: DefaultTransactionStreamerConfig, ResourceMgmt: resourcemanager.DefaultConfig, + Maintenance: DefaultMaintenanceConfig, } func ConfigDefaultL1Test() *Config { diff --git a/arbnode/redislock/redis.go b/arbnode/redislock/redis.go index c02476f04..c8252e059 100644 --- a/arbnode/redislock/redis.go +++ b/arbnode/redislock/redis.go @@ -42,7 +42,7 @@ func AddConfigOptions(prefix string, f *flag.FlagSet) { f.String(prefix+".my-id", "", "this node's id prefix when acquiring the lock (optional)") f.Duration(prefix+".lockout-duration", DefaultCfg.LockoutDuration, "how long lock is held") f.Duration(prefix+".refresh-duration", DefaultCfg.RefreshDuration, "how long between consecutive calls to redis") - f.String(prefix+".key", prefix+".simple-lock-key", "key for lock") + f.String(prefix+".key", DefaultCfg.Key, "key for lock") f.Bool(prefix+".background-lock", DefaultCfg.BackgroundLock, "should node always try grabing lock in background") } diff --git a/broadcastclient/broadcastclient.go b/broadcastclient/broadcastclient.go index 2649c8819..483b0b3b7 100644 --- a/broadcastclient/broadcastclient.go +++ b/broadcastclient/broadcastclient.go @@ -96,7 +96,7 @@ var DefaultConfig = Config{ RequireChainId: false, RequireFeedVersion: false, Verify: signature.DefultFeedVerifierConfig, - URL: []string{""}, + URL: []string{}, Timeout: 20 * time.Second, EnableCompression: true, } diff --git a/cmd/genericconf/config.go b/cmd/genericconf/config.go index 8e75b6177..c3282fe1a 100644 --- a/cmd/genericconf/config.go +++ b/cmd/genericconf/config.go @@ -33,7 +33,7 @@ func ConfConfigAddOptions(prefix string, f *flag.FlagSet) { var ConfConfigDefault = ConfConfig{ Dump: false, EnvPrefix: "", - File: nil, + File: []string{}, S3: DefaultS3Config, String: "", ReloadInterval: 0, diff --git a/cmd/genericconf/server.go b/cmd/genericconf/server.go index 53560dfdb..3da027ab2 100644 --- a/cmd/genericconf/server.go +++ b/cmd/genericconf/server.go @@ -26,7 +26,7 @@ var HTTPConfigDefault = HTTPConfig{ Port: 8547, API: append(node.DefaultConfig.HTTPModules, "eth", "arb"), RPCPrefix: node.DefaultConfig.HTTPPathPrefix, - CORSDomain: node.DefaultConfig.HTTPCors, + CORSDomain: []string{}, VHosts: node.DefaultConfig.HTTPVirtualHosts, ServerTimeouts: HTTPServerTimeoutConfigDefault, } @@ -91,7 +91,7 @@ var WSConfigDefault = WSConfig{ Port: 8548, API: append(node.DefaultConfig.WSModules, "eth", "arb"), RPCPrefix: node.DefaultConfig.WSPathPrefix, - Origins: node.DefaultConfig.WSOrigins, + Origins: []string{}, ExposeAll: node.DefaultConfig.WSExposeAll, } @@ -137,7 +137,7 @@ type GraphQLConfig struct { var GraphQLConfigDefault = GraphQLConfig{ Enable: false, - CORSDomain: node.DefaultConfig.GraphQLCors, + CORSDomain: []string{}, VHosts: node.DefaultConfig.GraphQLVirtualHosts, } diff --git a/cmd/nitro/config_test.go b/cmd/nitro/config_test.go index 417b25611..ea04d4eb1 100644 --- a/cmd/nitro/config_test.go +++ b/cmd/nitro/config_test.go @@ -15,10 +15,29 @@ import ( "time" "github.com/offchainlabs/nitro/cmd/genericconf" + "github.com/offchainlabs/nitro/cmd/util/confighelpers" "github.com/offchainlabs/nitro/util/colors" "github.com/offchainlabs/nitro/util/testhelpers" + + "github.com/r3labs/diff/v3" + flag "github.com/spf13/pflag" ) +func TestEmptyCliConfig(t *testing.T) { + f := flag.NewFlagSet("", flag.ContinueOnError) + NodeConfigAddOptions(f) + k, err := confighelpers.BeginCommonParse(f, []string{}) + Require(t, err) + var emptyCliNodeConfig NodeConfig + err = confighelpers.EndCommonParse(k, &emptyCliNodeConfig) + Require(t, err) + if !reflect.DeepEqual(emptyCliNodeConfig, NodeConfigDefault) { + changelog, err := diff.Diff(emptyCliNodeConfig, NodeConfigDefault) + Require(t, err) + Fail(t, "empty cli config differs from expected default", changelog) + } +} + func TestSeqConfig(t *testing.T) { args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.parent-chain-reader.enable=false --parent-chain.id 5 --chain.id 421613 --parent-chain.wallet.pathname /l1keystore --parent-chain.wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.sequencer --execution.sequencer.enable --node.feed.output.enable --node.feed.output.port 9642", " ") _, _, _, err := ParseNode(context.Background(), args) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 9656f7f5e..285cc3fe8 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -591,16 +591,23 @@ type NodeConfig struct { var NodeConfigDefault = NodeConfig{ Conf: genericconf.ConfConfigDefault, Node: arbnode.ConfigDefault, + Execution: gethexec.ConfigDefault, + Validation: valnode.DefaultValidationConfig, ParentChain: conf.L1ConfigDefault, Chain: conf.L2ConfigDefault, LogLevel: int(log.LvlInfo), LogType: "plaintext", + FileLogging: genericconf.DefaultFileLoggingConfig, Persistent: conf.PersistentConfigDefault, HTTP: genericconf.HTTPConfigDefault, WS: genericconf.WSConfigDefault, IPC: genericconf.IPCConfigDefault, + Auth: genericconf.AuthRPCConfigDefault, + GraphQL: genericconf.GraphQLConfigDefault, Metrics: false, MetricsServer: genericconf.MetricsServerConfigDefault, + Init: InitConfigDefault, + Rpc: genericconf.DefaultRpcConfig, PProf: false, PprofCfg: genericconf.PProfDefault, } diff --git a/cmd/rpcsvr/main.go b/cmd/rpcsvr/main.go new file mode 100644 index 000000000..5fc0b7fc4 --- /dev/null +++ b/cmd/rpcsvr/main.go @@ -0,0 +1,134 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "log" + "math/big" + "net/http" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/signer/core/apitypes" +) + +type server struct { + handlers map[string]func(*json.RawMessage) (string, error) + signerFn bind.SignerFn + address common.Address +} + +type request struct { + ID *json.RawMessage `json:"id"` + Method string `json:"method"` + Params *json.RawMessage `json:"params"` +} + +type response struct { + ID *json.RawMessage `json:"id"` + Result string `json:"result"` +} + +func new() (*server, error) { + signer, address, err := setupAccount("/tmp/keystore") + if err != nil { + return nil, err + } + s := &server{ + signerFn: signer, + address: address, + } + s.handlers = map[string]func(*json.RawMessage) (string, error){ + "eth_signTransaction": s.signTransaction, + } + return s, nil +} + +func setupAccount(dir string) (bind.SignerFn, common.Address, error) { + ks := keystore.NewKeyStore( + dir, + keystore.StandardScryptN, + keystore.StandardScryptP, + ) + a, err := ks.NewAccount("password") + if err != nil { + return nil, common.Address{}, fmt.Errorf("creating account account: %w", err) + } + if err := ks.Unlock(a, "password"); err != nil { + return nil, common.Address{}, fmt.Errorf("unlocking account: %w", err) + } + log.Printf("Created account: %s", a.Address.Hex()) + txOpts, err := bind.NewKeyStoreTransactorWithChainID(ks, a, big.NewInt(1)) + if err != nil { + return nil, common.Address{}, fmt.Errorf("creating transactor: %w", err) + } + return txOpts.Signer, a.Address, nil +} + +func (s *server) signTransaction(params *json.RawMessage) (string, error) { + var args []apitypes.SendTxArgs + if err := json.Unmarshal(*params, &args); err != nil { + return "", fmt.Errorf("unmarshaling params: %w", err) + } + var txs []*types.Transaction + for _, arg := range args { + signedTx, err := s.signerFn(s.address, arg.ToTransaction()) + if err != nil { + return "", fmt.Errorf("signing transaction: %w", err) + } + txs = append(txs, signedTx) + } + enc, err := rlp.EncodeToBytes(txs) + if err != nil { + return "", fmt.Errorf("encoding transactions to bytes: %w", err) + } + return hexutil.Encode(enc), nil +} + +func (s *server) mux(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "can't read body", http.StatusBadRequest) + return + } + var req request + if err := json.Unmarshal(body, &req); err != nil { + http.Error(w, "can't unmarshal JSON request", http.StatusBadRequest) + return + } + method, ok := s.handlers[req.Method] + if !ok { + http.Error(w, "method not found", http.StatusNotFound) + return + } + result, err := method(req.Params) + if err != nil { + fmt.Printf("error calling method: %v\n", err) + http.Error(w, "error calling method", http.StatusInternalServerError) + return + } + resp := response{ID: req.ID, Result: result} + respBytes, err := json.Marshal(resp) + if err != nil { + http.Error(w, "error encoding response", http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + w.Write(respBytes) +} + +func main() { + srv, err := new() + if err != nil { + fmt.Printf("Erorr creating server: %w", err) + return + } + http.HandleFunc("/", srv.mux) + fmt.Println("Server is listening on port 1234...") + log.Fatal(http.ListenAndServe(":1234", nil)) +} diff --git a/das/das.go b/das/das.go index 208a12cc8..9133b73ea 100644 --- a/das/das.go +++ b/das/das.go @@ -69,6 +69,7 @@ var DefaultDataAvailabilityConfig = DataAvailabilityConfig{ RestAggregator: DefaultRestfulClientAggregatorConfig, ParentChainConnectionAttempts: 15, PanicOnError: false, + IpfsStorage: DefaultIpfsStorageServiceConfig, } func OptionalAddressFromString(s string) (*common.Address, error) { diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index b29309cdb..1068dda96 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -91,6 +91,7 @@ var ConfigDefault = Config{ TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second Caching: DefaultCachingConfig, Dangerous: DefaultDangerousConfig, + Forwarder: DefaultNodeForwarderConfig, } func ConfigDefaultNonSequencerTest() *Config { diff --git a/staker/block_validator.go b/staker/block_validator.go index 94bc2a080..108d6d1d4 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -750,7 +750,7 @@ func (v *BlockValidator) iterativeValidationProgress(ctx context.Context, ignore } else if reorg != nil { err := v.Reorg(ctx, *reorg) if err != nil { - log.Error("error trying to rorg validation", "pos", *reorg-1, "err", err) + log.Error("error trying to reorg validation", "pos", *reorg-1, "err", err) v.possiblyFatal(err) } } diff --git a/staker/staker.go b/staker/staker.go index d52d1adc7..4148d0a20 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -203,7 +203,7 @@ func L1ValidatorConfigAddOptions(prefix string, f *flag.FlagSet) { f.String(prefix+".gas-refunder-address", DefaultL1ValidatorConfig.GasRefunderAddress, "The gas refunder contract address (optional)") f.String(prefix+".redis-url", DefaultL1ValidatorConfig.RedisUrl, "redis url for L1 validator") f.Uint64(prefix+".extra-gas", DefaultL1ValidatorConfig.ExtraGas, "use this much more gas than estimation says is necessary to post transactions") - dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f) + dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f, dataposter.DefaultDataPosterConfigForValidator) redislock.AddConfigOptions(prefix+".redis-lock", f) DangerousConfigAddOptions(prefix+".dangerous", f) genericconf.WalletConfigAddOptions(prefix+".parent-chain-wallet", f, DefaultL1ValidatorConfig.ParentChainWallet.Pathname) diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index ab61f8a2e..ff3b420a1 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -81,6 +81,7 @@ func AddOptions(prefix string, f *flag.FlagSet) { f.Bool(prefix+".poll-only", DefaultConfig.PollOnly, "do not attempt to subscribe to header events") f.Bool(prefix+".use-finality-data", DefaultConfig.UseFinalityData, "use l1 data about finalized/safe blocks") f.Duration(prefix+".poll-interval", DefaultConfig.PollInterval, "interval when polling endpoint") + f.Duration(prefix+".subscribe-err-interval", DefaultConfig.SubscribeErrInterval, "interval for subscribe error") f.Duration(prefix+".tx-timeout", DefaultConfig.TxTimeout, "timeout when waiting for a transaction") f.Duration(prefix+".old-header-timeout", DefaultConfig.OldHeaderTimeout, "warns if the latest l1 block is at least this old") } diff --git a/util/signature/sign_verify.go b/util/signature/sign_verify.go index 291191297..5ed852bfb 100644 --- a/util/signature/sign_verify.go +++ b/util/signature/sign_verify.go @@ -31,6 +31,12 @@ func SignVerifyConfigAddOptions(prefix string, f *flag.FlagSet) { } var DefaultSignVerifyConfig = SignVerifyConfig{ + ECDSA: DefultFeedVerifierConfig, + SymmetricFallback: false, + SymmetricSign: false, + Symmetric: EmptySimpleHmacConfig, +} +var TestSignVerifyConfig = SignVerifyConfig{ ECDSA: VerifierConfig{ AcceptSequencer: true, }, diff --git a/util/signature/sign_verify_test.go b/util/signature/sign_verify_test.go index 8ecb6e5cc..916fc03a2 100644 --- a/util/signature/sign_verify_test.go +++ b/util/signature/sign_verify_test.go @@ -17,7 +17,7 @@ func TestSignVerifyModes(t *testing.T) { signingAddr := crypto.PubkeyToAddress(privateKey.PublicKey) dataSigner := DataSignerFromPrivateKey(privateKey) - config := DefaultSignVerifyConfig + config := TestSignVerifyConfig config.SymmetricFallback = false config.SymmetricSign = false config.ECDSA.AcceptSequencer = false @@ -25,14 +25,14 @@ func TestSignVerifyModes(t *testing.T) { signVerifyECDSA, err := NewSignVerify(&config, dataSigner, nil) Require(t, err) - configSymmetric := DefaultSignVerifyConfig + configSymmetric := TestSignVerifyConfig configSymmetric.SymmetricFallback = true configSymmetric.SymmetricSign = true configSymmetric.ECDSA.AcceptSequencer = false signVerifySymmetric, err := NewSignVerify(&configSymmetric, nil, nil) Require(t, err) - configFallback := DefaultSignVerifyConfig + configFallback := TestSignVerifyConfig configFallback.SymmetricFallback = true configFallback.SymmetricSign = false configFallback.ECDSA.AllowedAddresses = []string{signingAddr.Hex()} diff --git a/util/signature/verifier.go b/util/signature/verifier.go index 2bf5b854e..c2f6529ec 100644 --- a/util/signature/verifier.go +++ b/util/signature/verifier.go @@ -37,7 +37,7 @@ var ErrMissingSignature = fmt.Errorf("%w: signature not found", ErrSignatureNotV var ErrSignerNotApproved = fmt.Errorf("%w: signer not approved", ErrSignatureNotVerified) func FeedVerifierConfigAddOptions(prefix string, f *flag.FlagSet) { - f.StringArray(prefix+".allowed-addresses", DefultFeedVerifierConfig.AllowedAddresses, "a list of allowed addresses") + f.StringSlice(prefix+".allowed-addresses", DefultFeedVerifierConfig.AllowedAddresses, "a list of allowed addresses") f.Bool(prefix+".accept-sequencer", DefultFeedVerifierConfig.AcceptSequencer, "accept verified message from sequencer") DangerousFeedVerifierConfigAddOptions(prefix+".dangerous", f) } From 42694708bd45b336f3ea88c2490b6bf49a0ebf79 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Fri, 13 Oct 2023 16:56:11 +0200 Subject: [PATCH 265/775] merge master --- arbnode/dataposter/data_poster.go | 20 ++-- arbnode/dataposter/dataposter_test.go | 144 +++++++++----------------- 2 files changed, 63 insertions(+), 101 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index c8a673ec9..76787e8c4 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -20,6 +20,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" "github.com/go-redis/redis/v8" "github.com/offchainlabs/nitro/arbnode/dataposter/dbstorage" @@ -182,15 +183,20 @@ func externalSigner(ctx context.Context, addr string, rpcURL string) (signerFn, return nil, common.Address{}, fmt.Errorf("error connecting external signer: %w", err) } return func(ctx context.Context, addr common.Address, tx *types.Transaction) (*types.Transaction, error) { - data, err := tx.MarshalBinary() - if err != nil { - return nil, err + // According to the "eth_signTransaction" API definition, this shoul be + // RLP encoded transaction object. + // https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction + var rlpEncTxStr string + if err := client.CallContext(ctx, &rlpEncTxStr, "eth_signTransaction", tx); err != nil { + return nil, fmt.Errorf("signing transaction: %w", err) } - var signedTx *types.Transaction - if err := client.CallContext(ctx, &signedTx, "eth_signTransaction", hexutil.Encode(data)); err != nil { - return nil, fmt.Errorf("error calling with context: %w", err) + data, err := hexutil.Decode(rlpEncTxStr) + if err != nil { + return nil, fmt.Errorf("error decoding hex: %w", err) } - return signedTx, nil + var signedTx types.Transaction + rlp.DecodeBytes(data, &signedTx) + return &signedTx, nil }, sender, nil } diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index c4c131c79..6334d2917 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -5,9 +5,9 @@ import ( "encoding/json" "fmt" "io" - "log" "math/big" "net/http" + "os" "testing" "time" @@ -16,6 +16,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/google/go-cmp/cmp" ) @@ -54,59 +56,32 @@ func TestParseReplacementTimes(t *testing.T) { } } -type Args struct { - Name string -} - -func TestRPC(t *testing.T) { - srv, err := newServer() - if err != nil { - fmt.Printf("Erorr creating server: %v", err) - return - } - http.HandleFunc("/", srv.mux) +func TestExternalSigner(t *testing.T) { + ctx := context.Background() + httpSrv, srv := newServer(ctx, t) + t.Cleanup(func() { httpSrv.Shutdown(ctx) }) go func() { fmt.Println("Server is listening on port 1234...") - t.Errorf("error listening: %v", http.ListenAndServe(":1234", nil)) + if err := httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed { + fmt.Printf("error listening: %v", http.ListenAndServe(":1234", nil)) + } }() - - if err != nil { - t.Fatalf("Error creating a server: %v", err) - } - ctx := context.Background() signer, addr, err := externalSigner(ctx, srv.address.Hex(), "http://127.0.0.1:1234") if err != nil { t.Fatalf("Error getting external signer: %v", err) } - tx := types.NewTransaction(0, common.HexToAddress("0x01"), big.NewInt(0), 3000000, big.NewInt(30000), nil) - signedTx, err := signer(ctx, addr, tx) + tx := types.NewTransaction(13, common.HexToAddress("0x01"), big.NewInt(1), 2, big.NewInt(3), []byte{0x01, 0x02, 0x03}) + got, err := signer(ctx, addr, tx) if err != nil { - t.Errorf("Error signing transaction: %v", err) + t.Fatalf("Error signing transaction with external signer: %v", err) } - if diff := cmp.Diff(signedTx, tx); diff != "" { - t.Errorf("diff: %v\n", diff) + want, err := srv.signerFn(addr, tx) + if err != nil { + t.Fatalf("Error signing transaction: %v", err) + } + if diff := cmp.Diff(want.Hash(), got.Hash()); diff != "" { + t.Errorf("Signing transaction: unexpected diff: %v\n", diff) } - -} - -// func setupServer(t *testing.T) { -// t.Skip() -// t.Helper() -// srv, err := newServer() -// if err != nil { -// fmt.Printf("Erorr creating server: %v", err) -// return -// } -// http.HandleFunc("/", srv.mux) -// fmt.Println("Server is listening on port 1234...") -// t.Fatal(http.ListenAndServe(":1234", nil)) -// } - -type SigningService struct{} - -func (h *SigningService) SignTx(r *http.Request, args *Args, reply *string) error { - *reply = "Hello, " + args.Name + "!" - return nil } type server struct { @@ -123,24 +98,32 @@ type request struct { type response struct { ID *json.RawMessage `json:"id"` - Result string `json:"result"` + Result string `json:"result,omitempty"` } -func newServer() (*server, error) { +// newServer returns http server and server struct that implements RPC methods. +// It sets up an account in temporary directory and cleans up after test is +// done. +func newServer(ctx context.Context, t *testing.T) (*http.Server, *server) { + t.Helper() signer, address, err := setupAccount("/tmp/keystore") if err != nil { - return nil, err - } - s := &server{ - signerFn: signer, - address: address, + t.Fatalf("Error setting up account: %v", err) } + t.Cleanup(func() { os.RemoveAll("/tmp/keystore") }) + + s := &server{signerFn: signer, address: address} s.handlers = map[string]func(*json.RawMessage) (string, error){ "eth_signTransaction": s.signTransaction, } - return s, nil + m := http.NewServeMux() + httpSrv := &http.Server{Addr: ":1234", Handler: m} + m.HandleFunc("/", s.mux) + return httpSrv, s } +// setupAccount creates a new account in a given directory, unlocks it, creates +// signer with that account and returns it along with account address. func setupAccount(dir string) (bind.SignerFn, common.Address, error) { ks := keystore.NewKeyStore( dir, @@ -154,7 +137,6 @@ func setupAccount(dir string) (bind.SignerFn, common.Address, error) { if err := ks.Unlock(a, "password"); err != nil { return nil, common.Address{}, fmt.Errorf("unlocking account: %w", err) } - log.Printf("Created account: %s", a.Address.Hex()) txOpts, err := bind.NewKeyStoreTransactorWithChainID(ks, a, big.NewInt(1)) if err != nil { return nil, common.Address{}, fmt.Errorf("creating transactor: %w", err) @@ -167,57 +149,31 @@ func setupAccount(dir string) (bind.SignerFn, common.Address, error) { // eth_sendRawTransaction or eth_signTransaction, marshall transaction as a // slice of transactions in a message: // https://github.com/ethereum/go-ethereum/blob/0004c6b229b787281760b14fb9460ffd9c2496f1/rpc/client.go#L548 -func unmarshallFirst(params []byte) (any, error) { - var arr []any +func unmarshallFirst(params []byte) (*types.Transaction, error) { + var arr []apitypes.SendTxArgs if err := json.Unmarshal(params, &arr); err != nil { - return "", fmt.Errorf("unmarshaling first param: %w", err) + return nil, fmt.Errorf("unmarshaling first param: %w", err) } - return arr[0], nil -} - -// func unmarshallTx(params *json.RawMessage) (*types.Transaction, error) { - -// } - -func encodeTx(tx *types.Transaction) (string, error) { - data, err := tx.MarshalBinary() - if err != nil { - return "", err + if len(arr) != 1 { + return nil, fmt.Errorf("argument should be a single transaction, but got: %d", len(arr)) } - return hexutil.Encode(data), nil + return arr[0].ToTransaction(), nil } func (s *server) signTransaction(params *json.RawMessage) (string, error) { - param, err := unmarshallFirst(*params) + tx, err := unmarshallFirst(*params) if err != nil { return "", err } - - fmt.Printf("anodar first parameter: %q\n", param) - data, err := hexutil.Decode("0xe280827530832dc6c09400000000000000000000000000000000000000018080808080") + signedTx, err := s.signerFn(s.address, tx) if err != nil { - return "", fmt.Errorf("decoding hex: %w", err) - } - fmt.Printf("decoded data: %v\n", data) - var tx types.Transaction - if err := tx.UnmarshalBinary(data); err != nil { - return "", fmt.Errorf("unmarshaling tx: %w", err) - } - fmt.Printf("tx: %v\n", tx) - return encodeTx(&tx) - // var txs []*types.Transaction - // for _, arg := range args { - // signedTx, err := s.signerFn(s.address, arg) - // if err != nil { - // return "", fmt.Errorf("signing transaction: %w", err) - // } - // txs = append(txs, signedTx) - // } - // enc, err := rlp.EncodeToBytes(txs) - // if err != nil { - // return "", fmt.Errorf("encoding transactions to bytes: %w", err) - // } - // return hexutil.Encode(enc), nil + return "", fmt.Errorf("signing transaction: %w", err) + } + data, err := rlp.EncodeToBytes(signedTx) + if err != nil { + return "", fmt.Errorf("rlp encoding transaction: %w", err) + } + return hexutil.Encode(data), nil } func (s *server) mux(w http.ResponseWriter, r *http.Request) { From c3ed563a94c74dc5025170a57418fca08ee25935 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Fri, 13 Oct 2023 16:58:55 +0200 Subject: [PATCH 266/775] Drop accidentally added server binary for manual testing --- cmd/rpcsvr/main.go | 134 --------------------------------------------- 1 file changed, 134 deletions(-) delete mode 100644 cmd/rpcsvr/main.go diff --git a/cmd/rpcsvr/main.go b/cmd/rpcsvr/main.go deleted file mode 100644 index 5fc0b7fc4..000000000 --- a/cmd/rpcsvr/main.go +++ /dev/null @@ -1,134 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "io" - "log" - "math/big" - "net/http" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/signer/core/apitypes" -) - -type server struct { - handlers map[string]func(*json.RawMessage) (string, error) - signerFn bind.SignerFn - address common.Address -} - -type request struct { - ID *json.RawMessage `json:"id"` - Method string `json:"method"` - Params *json.RawMessage `json:"params"` -} - -type response struct { - ID *json.RawMessage `json:"id"` - Result string `json:"result"` -} - -func new() (*server, error) { - signer, address, err := setupAccount("/tmp/keystore") - if err != nil { - return nil, err - } - s := &server{ - signerFn: signer, - address: address, - } - s.handlers = map[string]func(*json.RawMessage) (string, error){ - "eth_signTransaction": s.signTransaction, - } - return s, nil -} - -func setupAccount(dir string) (bind.SignerFn, common.Address, error) { - ks := keystore.NewKeyStore( - dir, - keystore.StandardScryptN, - keystore.StandardScryptP, - ) - a, err := ks.NewAccount("password") - if err != nil { - return nil, common.Address{}, fmt.Errorf("creating account account: %w", err) - } - if err := ks.Unlock(a, "password"); err != nil { - return nil, common.Address{}, fmt.Errorf("unlocking account: %w", err) - } - log.Printf("Created account: %s", a.Address.Hex()) - txOpts, err := bind.NewKeyStoreTransactorWithChainID(ks, a, big.NewInt(1)) - if err != nil { - return nil, common.Address{}, fmt.Errorf("creating transactor: %w", err) - } - return txOpts.Signer, a.Address, nil -} - -func (s *server) signTransaction(params *json.RawMessage) (string, error) { - var args []apitypes.SendTxArgs - if err := json.Unmarshal(*params, &args); err != nil { - return "", fmt.Errorf("unmarshaling params: %w", err) - } - var txs []*types.Transaction - for _, arg := range args { - signedTx, err := s.signerFn(s.address, arg.ToTransaction()) - if err != nil { - return "", fmt.Errorf("signing transaction: %w", err) - } - txs = append(txs, signedTx) - } - enc, err := rlp.EncodeToBytes(txs) - if err != nil { - return "", fmt.Errorf("encoding transactions to bytes: %w", err) - } - return hexutil.Encode(enc), nil -} - -func (s *server) mux(w http.ResponseWriter, r *http.Request) { - body, err := io.ReadAll(r.Body) - if err != nil { - http.Error(w, "can't read body", http.StatusBadRequest) - return - } - var req request - if err := json.Unmarshal(body, &req); err != nil { - http.Error(w, "can't unmarshal JSON request", http.StatusBadRequest) - return - } - method, ok := s.handlers[req.Method] - if !ok { - http.Error(w, "method not found", http.StatusNotFound) - return - } - result, err := method(req.Params) - if err != nil { - fmt.Printf("error calling method: %v\n", err) - http.Error(w, "error calling method", http.StatusInternalServerError) - return - } - resp := response{ID: req.ID, Result: result} - respBytes, err := json.Marshal(resp) - if err != nil { - http.Error(w, "error encoding response", http.StatusInternalServerError) - return - } - w.Header().Set("Content-Type", "application/json") - w.Write(respBytes) -} - -func main() { - srv, err := new() - if err != nil { - fmt.Printf("Erorr creating server: %w", err) - return - } - http.HandleFunc("/", srv.mux) - fmt.Println("Server is listening on port 1234...") - log.Fatal(http.ListenAndServe(":1234", nil)) -} From c177f025513f5a17fbaca04c742f01290efb0cc5 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Fri, 13 Oct 2023 17:05:35 +0200 Subject: [PATCH 267/775] Fix linter errors --- arbnode/dataposter/data_poster.go | 4 +++- arbnode/dataposter/dataposter_test.go | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 76787e8c4..15044cc4e 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -195,7 +195,9 @@ func externalSigner(ctx context.Context, addr string, rpcURL string) (signerFn, return nil, fmt.Errorf("error decoding hex: %w", err) } var signedTx types.Transaction - rlp.DecodeBytes(data, &signedTx) + if err := rlp.DecodeBytes(data, &signedTx); err != nil { + return nil, fmt.Errorf("error decoding signed transaction: %w", err) + } return &signedTx, nil }, sender, nil } diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index 6334d2917..c190337a0 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -59,11 +59,16 @@ func TestParseReplacementTimes(t *testing.T) { func TestExternalSigner(t *testing.T) { ctx := context.Background() httpSrv, srv := newServer(ctx, t) - t.Cleanup(func() { httpSrv.Shutdown(ctx) }) + t.Cleanup(func() { + if err := httpSrv.Shutdown(ctx); err != nil { + t.Fatalf("Error shutting down http server: %v", err) + } + }) go func() { fmt.Println("Server is listening on port 1234...") if err := httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed { - fmt.Printf("error listening: %v", http.ListenAndServe(":1234", nil)) + t.Errorf("ListenAndServe() unexpected error: %v", err) + return } }() signer, addr, err := externalSigner(ctx, srv.address.Hex(), "http://127.0.0.1:1234") @@ -117,7 +122,7 @@ func newServer(ctx context.Context, t *testing.T) (*http.Server, *server) { "eth_signTransaction": s.signTransaction, } m := http.NewServeMux() - httpSrv := &http.Server{Addr: ":1234", Handler: m} + httpSrv := &http.Server{Addr: ":1234", Handler: m, ReadTimeout: 5 * time.Second} m.HandleFunc("/", s.mux) return httpSrv, s } @@ -201,9 +206,11 @@ func (s *server) mux(w http.ResponseWriter, r *http.Request) { resp := response{ID: req.ID, Result: result} respBytes, err := json.Marshal(resp) if err != nil { - http.Error(w, "error encoding response", http.StatusInternalServerError) + http.Error(w, fmt.Sprintf("error encoding response: %v", err), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") - w.Write(respBytes) + if _, err := w.Write(respBytes); err != nil { + fmt.Printf("error writing response: %v\n", err) + } } From a0fcf8ed97b1ec9d398e7e084c80db6c6b7db308 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 13 Oct 2023 10:36:22 -0500 Subject: [PATCH 268/775] run int dev in foreground --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ce92be513..f8d36b780 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -63,7 +63,7 @@ jobs: shell: bash run: | cd nitro-testnode - ./test-node.bash --init & + ./test-node.bash --init --dev - name: Wait for rpc to come up shell: bash From 2f7b86750db92c16b09e1114ab661fde9a06eb80 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Fri, 13 Oct 2023 17:36:52 +0200 Subject: [PATCH 269/775] Make signing method configurable to allow both eth_signTransaction and account_signTransaction --- arbnode/dataposter/data_poster.go | 17 ++++++++++------- arbnode/dataposter/dataposter_test.go | 7 ++++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 15044cc4e..11b7a954e 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -161,7 +161,7 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro errorCount: make(map[uint64]int), } if cfg.ExternalSigner.Enabled { - signer, sender, err := externalSigner(ctx, cfg.ExternalSigner.Address, cfg.ExternalSigner.URL) + signer, sender, err := externalSigner(ctx, &cfg.ExternalSigner) if err != nil { return nil, err } @@ -173,12 +173,12 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro // externalSigner returns signer function and ethereum address of the signer. // Returns an error if address isn't specified or if it can't connect to the // signer RPC server. -func externalSigner(ctx context.Context, addr string, rpcURL string) (signerFn, common.Address, error) { - if addr == "" { +func externalSigner(ctx context.Context, opts *ExternalSignerCfg) (signerFn, common.Address, error) { + if opts.Address == "" { return nil, common.Address{}, errors.New("external signer (From) address specified") } - sender := common.HexToAddress(addr) - client, err := rpc.DialContext(ctx, rpcURL) + sender := common.HexToAddress(opts.Address) + client, err := rpc.DialContext(ctx, opts.URL) if err != nil { return nil, common.Address{}, fmt.Errorf("error connecting external signer: %w", err) } @@ -710,6 +710,8 @@ type ExternalSignerCfg struct { URL string `koanf:"url"` // Hex encoded ethereum address of the external signer. Address string `koanf:"address"` + // API method name (e.g. eth_signTransaction). + Method string `koanf:"method"` } type DangerousConfig struct { @@ -751,6 +753,7 @@ func addExternalSignerOptions(prefix string, f *pflag.FlagSet) { f.Bool(prefix+".enabled", DefaultDataPosterConfig.ExternalSigner.Enabled, "enable external signer") f.String(prefix+".url", DefaultDataPosterConfig.ExternalSigner.URL, "external signer url") f.String(prefix+".address", DefaultDataPosterConfig.ExternalSigner.Address, "external signer address") + f.String(prefix+".method", DefaultDataPosterConfig.ExternalSigner.Method, "external signer method") } var DefaultDataPosterConfig = DataPosterConfig{ @@ -767,7 +770,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ UseNoOpStorage: false, LegacyStorageEncoding: true, Dangerous: DangerousConfig{ClearDBStorage: false}, - ExternalSigner: ExternalSignerCfg{Enabled: false}, + ExternalSigner: ExternalSignerCfg{Enabled: false, Method: "eth_signTransaction"}, } var DefaultDataPosterConfigForValidator = func() DataPosterConfig { @@ -789,7 +792,7 @@ var TestDataPosterConfig = DataPosterConfig{ AllocateMempoolBalance: true, UseDBStorage: false, UseNoOpStorage: false, - ExternalSigner: ExternalSignerCfg{Enabled: false}, + ExternalSigner: ExternalSignerCfg{Enabled: false, Method: "eth_signTransaction"}, } var TestDataPosterConfigForValidator = func() DataPosterConfig { diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index c190337a0..186c85ec9 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -71,7 +71,12 @@ func TestExternalSigner(t *testing.T) { return } }() - signer, addr, err := externalSigner(ctx, srv.address.Hex(), "http://127.0.0.1:1234") + signer, addr, err := externalSigner(ctx, + &ExternalSignerCfg{ + Address: srv.address.Hex(), + URL: "http://127.0.0.1:1234", + Method: "eth_signTransaction", + }) if err != nil { t.Fatalf("Error getting external signer: %v", err) } From 41b9517ec40c1a72e130dbe53940952910a14283 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 13 Oct 2023 18:21:29 +0200 Subject: [PATCH 270/775] add comment to skipped error checks --- arbos/retryables/retryable.go | 1 + 1 file changed, 1 insertion(+) diff --git a/arbos/retryables/retryable.go b/arbos/retryables/retryable.go index 1121de01f..6984e4190 100644 --- a/arbos/retryables/retryable.go +++ b/arbos/retryables/retryable.go @@ -150,6 +150,7 @@ func (rs *RetryableState) DeleteRetryable(id common.Hash, evm *vm.EVM, scenario return false, err } + // we ignore returned error as we expect that if one ClearByUint64 fails, than all consecutive calls to ClearByUint64 will fail with the same error (not modifying state), and then ClearBytes will also fail with the same error (also not modifying state) - and this one we check and return _ = retStorage.ClearByUint64(numTriesOffset) _ = retStorage.ClearByUint64(fromOffset) _ = retStorage.ClearByUint64(toOffset) From 62ea1bc582eecfcf12426d997b1b98a426ae75cd Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 13 Oct 2023 14:07:29 -0500 Subject: [PATCH 271/775] update testnode-pin, fix bugs, test run nitro-testnode on foreground --- execution/gethexec/node.go | 4 ++++ nitro-testnode | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 1068dda96..972974b42 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -73,6 +73,7 @@ func (c *Config) Validate() error { func ConfigAddOptions(prefix string, f *flag.FlagSet) { arbitrum.ConfigAddOptions(prefix+".rpc", f) SequencerConfigAddOptions(prefix+".sequencer", f) + headerreader.AddOptions(prefix+".parent-chain-reader", f) arbitrum.RecordingDatabaseConfigAddOptions(prefix+".recording-database", f) f.String(prefix+".forwarding-target", ConfigDefault.ForwardingTarget, "transaction forwarding target URL, or \"null\" to disable forwarding (iff not sequencer)") AddOptionsForNodeForwarderConfig(prefix+".forwarder", f) @@ -85,6 +86,7 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { var ConfigDefault = Config{ RPC: arbitrum.DefaultConfig, Sequencer: DefaultSequencerConfig, + ParentChainReader: headerreader.DefaultConfig, RecordingDatabase: arbitrum.DefaultRecordingDatabaseConfig, ForwardingTarget: "", TxPreChecker: DefaultTxPreCheckerConfig, @@ -96,6 +98,7 @@ var ConfigDefault = Config{ func ConfigDefaultNonSequencerTest() *Config { config := ConfigDefault + config.ParentChainReader = headerreader.Config{} config.Sequencer.Enable = false config.Forwarder = DefaultTestForwarderConfig config.ForwardingTarget = "null" @@ -107,6 +110,7 @@ func ConfigDefaultNonSequencerTest() *Config { func ConfigDefaultTest() *Config { config := ConfigDefault + config.ParentChainReader = headerreader.Config{} config.Sequencer = TestSequencerConfig config.ForwardingTarget = "null" diff --git a/nitro-testnode b/nitro-testnode index 86fc5f627..aee6ceff9 160000 --- a/nitro-testnode +++ b/nitro-testnode @@ -1 +1 @@ -Subproject commit 86fc5f6275c0269b5a5105bf78c1627d03b0ef9e +Subproject commit aee6ceff9c9d3fb2749da55a7d7842f23d1bfc8e From 66bec8ef23e694bf5e01b55d5158bfcd99dc4109 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 13 Oct 2023 14:36:58 -0500 Subject: [PATCH 272/775] run testnode in background --- .github/workflows/docker.yml | 2 +- .github/workflows/waitForNitro.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index f8d36b780..33049d439 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -63,7 +63,7 @@ jobs: shell: bash run: | cd nitro-testnode - ./test-node.bash --init --dev + ./test-node.bash --init --dev & - name: Wait for rpc to come up shell: bash diff --git a/.github/workflows/waitForNitro.sh b/.github/workflows/waitForNitro.sh index 1c71298dd..e196b38d8 100755 --- a/.github/workflows/waitForNitro.sh +++ b/.github/workflows/waitForNitro.sh @@ -5,6 +5,6 @@ do if [ "$?" -eq "0" ]; then exit 0 else - sleep 10 + sleep 20 fi done \ No newline at end of file From e2b9d7717f8677d3f63c3b76a6728c6320e5aaea Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Fri, 13 Oct 2023 13:35:21 -0700 Subject: [PATCH 273/775] Change L1 to parent chain in DAS help strings --- das/das.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/das/das.go b/das/das.go index 9133b73ea..910e51108 100644 --- a/das/das.go +++ b/das/das.go @@ -133,9 +133,9 @@ func dataAvailabilityConfigAddOptions(prefix string, f *flag.FlagSet, r role) { IpfsStorageServiceConfigAddOptions(prefix+".ipfs-storage", f) RestfulClientAggregatorConfigAddOptions(prefix+".rest-aggregator", f) - f.String(prefix+".parent-chain-node-url", DefaultDataAvailabilityConfig.ParentChainNodeURL, "URL for L1 node, only used in standalone daserver; when running as part of a node that node's L1 configuration is used") - f.Int(prefix+".parent-chain-connection-attempts", DefaultDataAvailabilityConfig.ParentChainConnectionAttempts, "layer 1 RPC connection attempts (spaced out at least 1 second per attempt, 0 to retry infinitely), only used in standalone daserver; when running as part of a node that node's L1 configuration is used") - f.String(prefix+".sequencer-inbox-address", DefaultDataAvailabilityConfig.SequencerInboxAddress, "L1 address of SequencerInbox contract") + f.String(prefix+".parent-chain-node-url", DefaultDataAvailabilityConfig.ParentChainNodeURL, "URL for parent chain node, only used in standalone daserver; when running as part of a node that node's L1 configuration is used") + f.Int(prefix+".parent-chain-connection-attempts", DefaultDataAvailabilityConfig.ParentChainConnectionAttempts, "parent chain RPC connection attempts (spaced out at least 1 second per attempt, 0 to retry infinitely), only used in standalone daserver; when running as part of a node that node's parent chain configuration is used") + f.String(prefix+".sequencer-inbox-address", DefaultDataAvailabilityConfig.SequencerInboxAddress, "parent chain address of SequencerInbox contract") } func Serialize(c *arbstate.DataAvailabilityCertificate) []byte { From 10717541ba8753997304c9eb8b81684ede1b8b4d Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Fri, 13 Oct 2023 14:33:23 -0700 Subject: [PATCH 274/775] Make clippy happy --- arbitrator/prover/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbitrator/prover/src/main.rs b/arbitrator/prover/src/main.rs index f820b03f4..0a2000fc3 100644 --- a/arbitrator/prover/src/main.rs +++ b/arbitrator/prover/src/main.rs @@ -385,7 +385,7 @@ fn main() -> Result<()> { sum.count += profile.count; let entry = func_profile .entry((module, func)) - .or_insert_with(SimpleProfile::default); + .or_default(); entry.count += sum.count; entry.total_cycles += sum.total_cycles; entry.local_cycles += profile.local_cycles; From 552283aaa9cf7da501b5aab6e22cdf5ab8a18c2e Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Fri, 13 Oct 2023 15:08:56 -0700 Subject: [PATCH 275/775] Make cargo fmt happy --- arbitrator/prover/src/main.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arbitrator/prover/src/main.rs b/arbitrator/prover/src/main.rs index 0a2000fc3..2c72d0b57 100644 --- a/arbitrator/prover/src/main.rs +++ b/arbitrator/prover/src/main.rs @@ -383,9 +383,7 @@ fn main() -> Result<()> { while let Some((module, func, profile)) = func_stack.pop() { sum.total_cycles += profile.total_cycles; sum.count += profile.count; - let entry = func_profile - .entry((module, func)) - .or_default(); + let entry = func_profile.entry((module, func)).or_default(); entry.count += sum.count; entry.total_cycles += sum.total_cycles; entry.local_cycles += profile.local_cycles; From c27cb4b736814df79d6f5d18ee60ca2ba6a35a5f Mon Sep 17 00:00:00 2001 From: Nodar Date: Mon, 16 Oct 2023 13:18:47 +0200 Subject: [PATCH 276/775] Update arbnode/dataposter/data_poster.go Co-authored-by: Joshua Colvin --- arbnode/dataposter/data_poster.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 11b7a954e..a54b05c34 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -183,7 +183,7 @@ func externalSigner(ctx context.Context, opts *ExternalSignerCfg) (signerFn, com return nil, common.Address{}, fmt.Errorf("error connecting external signer: %w", err) } return func(ctx context.Context, addr common.Address, tx *types.Transaction) (*types.Transaction, error) { - // According to the "eth_signTransaction" API definition, this shoul be + // According to the "eth_signTransaction" API definition, this should be // RLP encoded transaction object. // https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction var rlpEncTxStr string From 46618880e1883f24228746f6b301af44f2dedc26 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 16 Oct 2023 14:57:06 +0200 Subject: [PATCH 277/775] Check that signed transaction is the one sent for signing --- arbnode/dataposter/data_poster.go | 30 ++++++++++++++------------- arbnode/dataposter/dataposter_test.go | 4 ++-- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 11b7a954e..476920978 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -92,7 +92,7 @@ func parseReplacementTimes(val string) ([]time.Duration, error) { lastReplacementTime = t } if len(res) == 0 { - log.Warn("disabling replace-by-fee for data poster") + log.Warn("Disabling replace-by-fee for data poster") } // To avoid special casing "don't replace again", replace in 10 years. return append(res, time.Hour*24*365*10), nil @@ -160,7 +160,7 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro redisLock: opts.RedisLock, errorCount: make(map[uint64]int), } - if cfg.ExternalSigner.Enabled { + if cfg.ExternalSigner.URL != "" { signer, sender, err := externalSigner(ctx, &cfg.ExternalSigner) if err != nil { return nil, err @@ -182,22 +182,26 @@ func externalSigner(ctx context.Context, opts *ExternalSignerCfg) (signerFn, com if err != nil { return nil, common.Address{}, fmt.Errorf("error connecting external signer: %w", err) } + + var hasher types.Signer return func(ctx context.Context, addr common.Address, tx *types.Transaction) (*types.Transaction, error) { // According to the "eth_signTransaction" API definition, this shoul be // RLP encoded transaction object. // https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction - var rlpEncTxStr string - if err := client.CallContext(ctx, &rlpEncTxStr, "eth_signTransaction", tx); err != nil { + var data hexutil.Bytes + if err := client.CallContext(ctx, &data, opts.Method, tx); err != nil { return nil, fmt.Errorf("signing transaction: %w", err) } - data, err := hexutil.Decode(rlpEncTxStr) - if err != nil { - return nil, fmt.Errorf("error decoding hex: %w", err) - } var signedTx types.Transaction if err := rlp.DecodeBytes(data, &signedTx); err != nil { return nil, fmt.Errorf("error decoding signed transaction: %w", err) } + if hasher == nil { + hasher = types.LatestSignerForChainID(tx.ChainId()) + } + if hasher.Hash(tx) != hasher.Hash(&signedTx) { + return nil, fmt.Errorf("transaction: %x from external signer differs from request: %x", hasher.Hash(tx), hasher.Hash(&signedTx)) + } return &signedTx, nil }, sender, nil } @@ -703,10 +707,9 @@ type DataPosterConfig struct { } type ExternalSignerCfg struct { - // If enabled, this overrides transaction options and uses external signer + // URL of the external signer rpc server, if set this overrides transaction + // options and uses external signer // for signing transactions. - Enabled bool `koanf:"enabled"` - // URL of the external signer rpc server. URL string `koanf:"url"` // Hex encoded ethereum address of the external signer. Address string `koanf:"address"` @@ -750,7 +753,6 @@ func addDangerousOptions(prefix string, f *pflag.FlagSet) { } func addExternalSignerOptions(prefix string, f *pflag.FlagSet) { - f.Bool(prefix+".enabled", DefaultDataPosterConfig.ExternalSigner.Enabled, "enable external signer") f.String(prefix+".url", DefaultDataPosterConfig.ExternalSigner.URL, "external signer url") f.String(prefix+".address", DefaultDataPosterConfig.ExternalSigner.Address, "external signer address") f.String(prefix+".method", DefaultDataPosterConfig.ExternalSigner.Method, "external signer method") @@ -770,7 +772,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ UseNoOpStorage: false, LegacyStorageEncoding: true, Dangerous: DangerousConfig{ClearDBStorage: false}, - ExternalSigner: ExternalSignerCfg{Enabled: false, Method: "eth_signTransaction"}, + ExternalSigner: ExternalSignerCfg{}, } var DefaultDataPosterConfigForValidator = func() DataPosterConfig { @@ -792,7 +794,7 @@ var TestDataPosterConfig = DataPosterConfig{ AllocateMempoolBalance: true, UseDBStorage: false, UseNoOpStorage: false, - ExternalSigner: ExternalSignerCfg{Enabled: false, Method: "eth_signTransaction"}, + ExternalSigner: ExternalSignerCfg{}, } var TestDataPosterConfigForValidator = func() DataPosterConfig { diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index 186c85ec9..4b4768e0b 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -75,7 +75,7 @@ func TestExternalSigner(t *testing.T) { &ExternalSignerCfg{ Address: srv.address.Hex(), URL: "http://127.0.0.1:1234", - Method: "eth_signTransaction", + Method: "test_signTransaction", }) if err != nil { t.Fatalf("Error getting external signer: %v", err) @@ -124,7 +124,7 @@ func newServer(ctx context.Context, t *testing.T) (*http.Server, *server) { s := &server{signerFn: signer, address: address} s.handlers = map[string]func(*json.RawMessage) (string, error){ - "eth_signTransaction": s.signTransaction, + "test_signTransaction": s.signTransaction, } m := http.NewServeMux() httpSrv := &http.Server{Addr: ":1234", Handler: m, ReadTimeout: 5 * time.Second} From c551ff5595d4d9a56fd31a7b658d756db6f07499 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 16 Oct 2023 15:00:14 +0200 Subject: [PATCH 278/775] List transactions in correct order in the log line --- arbnode/dataposter/data_poster.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index ff1751014..fa7dfec48 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -200,7 +200,7 @@ func externalSigner(ctx context.Context, opts *ExternalSignerCfg) (signerFn, com hasher = types.LatestSignerForChainID(tx.ChainId()) } if hasher.Hash(tx) != hasher.Hash(&signedTx) { - return nil, fmt.Errorf("transaction: %x from external signer differs from request: %x", hasher.Hash(tx), hasher.Hash(&signedTx)) + return nil, fmt.Errorf("transaction: %x from external signer differs from request: %x", hasher.Hash(&signedTx), hasher.Hash(tx)) } return &signedTx, nil }, sender, nil From df6f73e1b9c34a2fe5b272a4259ddbe63020c34a Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 16 Oct 2023 09:38:51 -0500 Subject: [PATCH 279/775] test failure --- .github/workflows/waitForNitro.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/waitForNitro.sh b/.github/workflows/waitForNitro.sh index e196b38d8..422083e38 100755 --- a/.github/workflows/waitForNitro.sh +++ b/.github/workflows/waitForNitro.sh @@ -1,10 +1,14 @@ -# poll the nitro endpoint until we get a 0 return code -while true -do +# poll the nitro endpoint until we get a 0 return code or 30mins have passed, in that case exit 1 +start_time=$(date +%s) +timeout=20 + +while (( $(date +%s) - start_time <= timeout )); do curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":45678,"method":"eth_chainId","params":[]}' 'http://localhost:8547' if [ "$?" -eq "0" ]; then exit 0 else sleep 20 fi -done \ No newline at end of file +done + +exit 1 \ No newline at end of file From 3374afae18b43d4be49c45586185440d65c7a073 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 16 Oct 2023 16:48:22 +0200 Subject: [PATCH 280/775] Add TLS to the server side, expose optional root certificate path on client side --- arbnode/dataposter/data_poster.go | 35 ++++++++++++++- arbnode/dataposter/dataposter_test.go | 10 +++-- arbnode/dataposter/testdata/localhost.cnf | 52 +++++++++++++++++++++++ arbnode/dataposter/testdata/localhost.crt | 28 ++++++++++++ arbnode/dataposter/testdata/localhost.key | 28 ++++++++++++ 5 files changed, 147 insertions(+), 6 deletions(-) create mode 100644 arbnode/dataposter/testdata/localhost.cnf create mode 100644 arbnode/dataposter/testdata/localhost.crt create mode 100644 arbnode/dataposter/testdata/localhost.key diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index fa7dfec48..56e87e3b2 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -6,9 +6,13 @@ package dataposter import ( "context" + "crypto/tls" + "crypto/x509" "errors" "fmt" "math/big" + "net/http" + "os" "strings" "sync" "time" @@ -170,6 +174,28 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro return dp, nil } +func rpcClient(ctx context.Context, opts *ExternalSignerCfg) (*rpc.Client, error) { + rootCrt, err := os.ReadFile(opts.RootCA) + if err != nil { + return nil, fmt.Errorf("error reading external signer root CA: %w", err) + } + pool := x509.NewCertPool() + pool.AppendCertsFromPEM(rootCrt) + return rpc.DialOptions( + ctx, + opts.URL, + rpc.WithHTTPClient( + &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: pool, + }, + }, + }, + ), + ) +} + // externalSigner returns signer function and ethereum address of the signer. // Returns an error if address isn't specified or if it can't connect to the // signer RPC server. @@ -177,11 +203,12 @@ func externalSigner(ctx context.Context, opts *ExternalSignerCfg) (signerFn, com if opts.Address == "" { return nil, common.Address{}, errors.New("external signer (From) address specified") } - sender := common.HexToAddress(opts.Address) - client, err := rpc.DialContext(ctx, opts.URL) + + client, err := rpcClient(ctx, opts) if err != nil { return nil, common.Address{}, fmt.Errorf("error connecting external signer: %w", err) } + sender := common.HexToAddress(opts.Address) var hasher types.Signer return func(ctx context.Context, addr common.Address, tx *types.Transaction) (*types.Transaction, error) { @@ -715,6 +742,9 @@ type ExternalSignerCfg struct { Address string `koanf:"address"` // API method name (e.g. eth_signTransaction). Method string `koanf:"method"` + // Path to the external signer root CA certificate. + // This allows us to use self-signed certificats on the external signer. + RootCA string `koanf:"root-ca"` } type DangerousConfig struct { @@ -756,6 +786,7 @@ func addExternalSignerOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".url", DefaultDataPosterConfig.ExternalSigner.URL, "external signer url") f.String(prefix+".address", DefaultDataPosterConfig.ExternalSigner.Address, "external signer address") f.String(prefix+".method", DefaultDataPosterConfig.ExternalSigner.Method, "external signer method") + f.String(prefix+".root-ca", DefaultDataPosterConfig.ExternalSigner.RootCA, "external signer root CA") } var DefaultDataPosterConfig = DataPosterConfig{ diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index 4b4768e0b..0b3b8cba5 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -64,18 +64,20 @@ func TestExternalSigner(t *testing.T) { t.Fatalf("Error shutting down http server: %v", err) } }) + cert, key := "./testdata/localhost.crt", "./testdata/localhost.key" go func() { - fmt.Println("Server is listening on port 1234...") - if err := httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed { - t.Errorf("ListenAndServe() unexpected error: %v", err) + fmt.Println("Server is listening on port 443...") + if err := httpSrv.ListenAndServeTLS(cert, key); err != nil && err != http.ErrServerClosed { + t.Errorf("ListenAndServeTLS() unexpected error: %v", err) return } }() signer, addr, err := externalSigner(ctx, &ExternalSignerCfg{ Address: srv.address.Hex(), - URL: "http://127.0.0.1:1234", + URL: "https://localhost:1234", Method: "test_signTransaction", + RootCA: cert, }) if err != nil { t.Fatalf("Error getting external signer: %v", err) diff --git a/arbnode/dataposter/testdata/localhost.cnf b/arbnode/dataposter/testdata/localhost.cnf new file mode 100644 index 000000000..41647cc42 --- /dev/null +++ b/arbnode/dataposter/testdata/localhost.cnf @@ -0,0 +1,52 @@ +[req] +default_bits = 2048 +default_keyfile = server-key.pem +distinguished_name = subject +req_extensions = req_ext +x509_extensions = x509_ext +string_mask = utf8only + +[subject] +countryName = CH +countryName_default = CH + +stateOrProvinceName = Zurich +stateOrProvinceName_default = ZH + +localityName = city +localityName_default = Zurich + +organizationName = Offchain Labs +organizationName_default = Offchain Labs + +commonName = offchainlabs.ch +commonName_default = localhost + +emailAddress = Email Address +emailAddress_default = bigdeal@offchainlabs.ch + +[x509_ext] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer + +basicConstraints = CA:FALSE +keyUsage = digitalSignature, keyEncipherment +subjectAltName = @alternate_names +nsComment = "OpenSSL Generated Certificate" + +[req_ext] +subjectKeyIdentifier = hash + +basicConstraints = CA:FALSE +keyUsage = digitalSignature, keyEncipherment +subjectAltName = @alternate_names +nsComment = "OpenSSL Generated Certificate" + +[alternate_names] +DNS.1 = localhost +DNS.2 = 127.0.0.1 + +[alternate_names] +DNS.1 = localhost +DNS.2 = 127.0.0.1 + diff --git a/arbnode/dataposter/testdata/localhost.crt b/arbnode/dataposter/testdata/localhost.crt new file mode 100644 index 000000000..ca33dfc8c --- /dev/null +++ b/arbnode/dataposter/testdata/localhost.crt @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEwzCCA6ugAwIBAgIUHx3SdpCP5jXZE7USUqX5uRNFKPIwDQYJKoZIhvcNAQEL +BQAwfzELMAkGA1UEBhMCQ0gxCzAJBgNVBAgMAlpIMQ8wDQYDVQQHDAZadXJpY2gx +FjAUBgNVBAoMDU9mZmNoYWluIExhYnMxEjAQBgNVBAMMCWxvY2FsaG9zdDEmMCQG +CSqGSIb3DQEJARYXYmlnZGVhbEBvZmZjaGFpbmxhYnMuY2gwHhcNMjMxMDE2MTQ0 +MDA1WhcNMjQxMDE1MTQ0MDA1WjB/MQswCQYDVQQGEwJDSDELMAkGA1UECAwCWkgx +DzANBgNVBAcMBlp1cmljaDEWMBQGA1UECgwNT2ZmY2hhaW4gTGFiczESMBAGA1UE +AwwJbG9jYWxob3N0MSYwJAYJKoZIhvcNAQkBFhdiaWdkZWFsQG9mZmNoYWlubGFi +cy5jaDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALg7XwaIh4l2Fp8a +MfNMdTQSMPMR0zpnicVTn/eiozWsqlAKaxmQM3PxJ0oVWW3iJ89p4rv5m+UjK6Dr +vsUQOzl8isgyGCTMnkLtxFlyallDNRDawRcuTPuNI9NkdJm+Zz7HooLzFeBDeS13 +iRPEXr1T/4af9MjOxqFvbw5xBY9k4tc2hPp6q00948gPWKIB9Mz4thoB2Hl2rQBY +X/WhjSnre9o9qoyBO0XAsG0mssBs1vPa9/aEp7C5cDY0HCuM1RIjhXnRpb8lC9VQ +aC+FozDffmm23EGVpLmyPs590UOtVJdTUd6Q0TAT6d7fjCRUJ12DendQf2uMFV90 +u6Yj0zUCAwEAAaOCATUwggExMB0GA1UdDgQWBBT2B3FTGFQ49JyBgDGLoZREOIGD +DTCBqAYDVR0jBIGgMIGdoYGEpIGBMH8xCzAJBgNVBAYTAkNIMQswCQYDVQQIDAJa +SDEPMA0GA1UEBwwGWnVyaWNoMRYwFAYDVQQKDA1PZmZjaGFpbiBMYWJzMRIwEAYD +VQQDDAlsb2NhbGhvc3QxJjAkBgkqhkiG9w0BCQEWF2JpZ2RlYWxAb2ZmY2hhaW5s +YWJzLmNoghQfHdJ2kI/mNdkTtRJSpfm5E0Uo8jAJBgNVHRMEAjAAMAsGA1UdDwQE +AwIFoDAfBgNVHREEGDAWgglsb2NhbGhvc3SCCTEyNy4wLjAuMTAsBglghkgBhvhC +AQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwDQYJKoZIhvcNAQEL +BQADggEBAIkhBcnLeeNwUwb+sSG4Qm8JdeplHPMeViNfFIflUfIIYS00JA2q9w8W ++6Nh8s6Dn20lQETUnesYj97BdqzLjFuJYAlblhE+zP8g/3Mkpu+wZAGvQjUIRyGT +C17BEtQQgAnv5pD22jr9hpLl2KowN6Oo1gzilCA+AtMkNZFIGDOxzuIv2u8rSD89 +R/V6UEDMCgusFJnZ/GzKkUNbsrAfNUezNUal+KzMhHGHBwg4jfCNhnAAB43eRtJA +0pSRMMLcUEQnVotXDXYC3DhJmkYp1uXOH/tWs6z9xForOkWFxNMVj+zUWBi7n3Jw +N2BXlb64D96uor13U0dmvQJ72ooJc+A= +-----END CERTIFICATE----- diff --git a/arbnode/dataposter/testdata/localhost.key b/arbnode/dataposter/testdata/localhost.key new file mode 100644 index 000000000..aad9b40b3 --- /dev/null +++ b/arbnode/dataposter/testdata/localhost.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4O18GiIeJdhaf +GjHzTHU0EjDzEdM6Z4nFU5/3oqM1rKpQCmsZkDNz8SdKFVlt4ifPaeK7+ZvlIyug +677FEDs5fIrIMhgkzJ5C7cRZcmpZQzUQ2sEXLkz7jSPTZHSZvmc+x6KC8xXgQ3kt +d4kTxF69U/+Gn/TIzsahb28OcQWPZOLXNoT6eqtNPePID1iiAfTM+LYaAdh5dq0A +WF/1oY0p63vaPaqMgTtFwLBtJrLAbNbz2vf2hKewuXA2NBwrjNUSI4V50aW/JQvV +UGgvhaMw335pttxBlaS5sj7OfdFDrVSXU1HekNEwE+ne34wkVCddg3p3UH9rjBVf +dLumI9M1AgMBAAECggEAHuc8oyKrQ5xmooUZHGP2pAeqJNfYXAtqoYpLwtUJ9hKy +1e7NdNIKw3fP/J4UrHk7btAm65us8hSCeMGatEErAhNZT0gR4zhcksMCBPQLkVIT ++HINYjdOzAJqoEbRRUnaVT5VDQy8HmyLCtyqhoGR18XbjshNnhKLYKCJ2z0Lrvf2 +3rU7bbt7/rvLitVhxVL8SIe2jWSfIgcEmEAZMigB9WAnUyQ/tAfbPy1I764LLfzD +nLXn7E2OH7GrxkLjOsH9kfERlur7V7IhC9NE/wI0q+rnILRa7Q3+ifRu8qla3bo1 +iyHl1ZmsYJ8Jnzbu9exzZaQmk42OoFPcMFm0mRe+2QKBgQDvRv0Q5JhBuVurkU98 +lzATwEO0uYmeWDMnHzrFSWAKr/x4LNQ9ytSCfe1aLxgOkZq6dQ3TyZiCYzpmwGz9 +K7/gghxmsVDKeCqiGVZOgFAWy7AhQyF6zM60oqqwSvJHhmGTsA/B5LPUiYe9lITW +ZSLVYkOzha7Coa++U8vPzI5VaQKBgQDFG4reFT79j8RKEm9jie6PdRdYMzOSDWty +Gjj5N9Jnlp1k/6RzCxjmp7w7yIorq/7fWZsQtt0UqgayOn25+I8dZeGC0BradUSB +tZbGElxPsF8Jg00ZvvK3G5mpZYDrJCud8Q05EaUZPXv9GuZhozEsTQgylVecVzsN +wyEK8VuZ7QKBgQChx9adUGIdtgzkILiknbh08j8U94mz1SCo5/WdpLHaKAlE29KZ +AQXUQP51Rng2iX4bab9yndCPADZheON3/debHX3EdUkRzFPPC+CN7TW5Y/jvVGtT +kxyDh6Ru1A2iDJr290iAKXjpUB/GL5/tMa5upiTuQYnasOWZgyC/nCf0WQKBgEwn +pRLDMLA1IMjhsInL3BEvU1KvjahLaQ0P1p1rlO6TAcLpBrewPPG5MwACLmhLLtFK +xJ/Dl02Jl8a61KLKxzi7iVLKZuWq00ouR8/FfkcHxOBfC6X74bkff9I0NogjVHrU +jKBVEe3blJEpGIP20mPka1tn2g68oUNi9dxNfm/NAoGAWj/Q0pgnNq0MQ8Lj6m99 +1baaXSo8biks3E3A3cqhHQm/j3SRnkf0lueQW8+r9yR9IWdYFXz5Waq13qK+lopE +KDmww0xr8dyMUYTP1vde7np2XKa/OX3iejDzbI3RcZN/DEV+dCBY8pqHHfaAaESu +fwBWvfD8wtwCZzB3lOZEi80= +-----END PRIVATE KEY----- From 82663481ad99b6ea6eef6440aed735e3cdedd243 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 16 Oct 2023 09:58:24 -0500 Subject: [PATCH 281/775] test success --- .github/workflows/waitForNitro.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/waitForNitro.sh b/.github/workflows/waitForNitro.sh index 422083e38..a1b7f2ad0 100755 --- a/.github/workflows/waitForNitro.sh +++ b/.github/workflows/waitForNitro.sh @@ -1,6 +1,6 @@ # poll the nitro endpoint until we get a 0 return code or 30mins have passed, in that case exit 1 start_time=$(date +%s) -timeout=20 +timeout=1800 while (( $(date +%s) - start_time <= timeout )); do curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":45678,"method":"eth_chainId","params":[]}' 'http://localhost:8547' From 0bb425a4de6139d17c55ba0824770f3ae350ccc3 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 16 Oct 2023 17:20:37 +0200 Subject: [PATCH 282/775] Add client certificate, require to verify client cert --- arbnode/dataposter/data_poster.go | 33 ++++++++++++---- arbnode/dataposter/dataposter_test.go | 31 ++++++++++++--- arbnode/dataposter/testdata/client.cnf | 52 ++++++++++++++++++++++++++ arbnode/dataposter/testdata/client.crt | 28 ++++++++++++++ arbnode/dataposter/testdata/client.key | 28 ++++++++++++++ 5 files changed, 159 insertions(+), 13 deletions(-) create mode 100644 arbnode/dataposter/testdata/client.cnf create mode 100644 arbnode/dataposter/testdata/client.crt create mode 100644 arbnode/dataposter/testdata/client.key diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 56e87e3b2..02a354866 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -175,21 +175,32 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro } func rpcClient(ctx context.Context, opts *ExternalSignerCfg) (*rpc.Client, error) { - rootCrt, err := os.ReadFile(opts.RootCA) + clientCert, err := tls.LoadX509KeyPair(opts.ClientCert, opts.ClientPrivateKey) if err != nil { - return nil, fmt.Errorf("error reading external signer root CA: %w", err) + return nil, fmt.Errorf("error loading client certificate and private key: %w", err) } - pool := x509.NewCertPool() - pool.AppendCertsFromPEM(rootCrt) + + tlsCfg := &tls.Config{ + MinVersion: tls.VersionTLS12, + Certificates: []tls.Certificate{clientCert}, + } + if opts.RootCA != "" { + rootCrt, err := os.ReadFile(opts.RootCA) + if err != nil { + return nil, fmt.Errorf("error reading external signer root CA: %w", err) + } + rootCertPool := x509.NewCertPool() + rootCertPool.AppendCertsFromPEM(rootCrt) + tlsCfg.RootCAs = rootCertPool + } + return rpc.DialOptions( ctx, opts.URL, rpc.WithHTTPClient( &http.Client{ Transport: &http.Transport{ - TLSClientConfig: &tls.Config{ - RootCAs: pool, - }, + TLSClientConfig: tlsCfg, }, }, ), @@ -742,9 +753,13 @@ type ExternalSignerCfg struct { Address string `koanf:"address"` // API method name (e.g. eth_signTransaction). Method string `koanf:"method"` - // Path to the external signer root CA certificate. + // (Optional) Path to the external signer root CA certificate. // This allows us to use self-signed certificats on the external signer. RootCA string `koanf:"root-ca"` + // Client certificate for mtls. + ClientCert string `koanf:"client-cert"` + // Client certificate key for mtls. + ClientPrivateKey string `koanf:"client-private-key"` } type DangerousConfig struct { @@ -787,6 +802,8 @@ func addExternalSignerOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".address", DefaultDataPosterConfig.ExternalSigner.Address, "external signer address") f.String(prefix+".method", DefaultDataPosterConfig.ExternalSigner.Method, "external signer method") f.String(prefix+".root-ca", DefaultDataPosterConfig.ExternalSigner.RootCA, "external signer root CA") + f.String(prefix+".client-cert", DefaultDataPosterConfig.ExternalSigner.ClientCert, "rpc client cert") + f.String(prefix+".client-private-key", DefaultDataPosterConfig.ExternalSigner.ClientPrivateKey, "rpc client private key") } var DefaultDataPosterConfig = DataPosterConfig{ diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index 0b3b8cba5..d21390bcc 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -2,6 +2,8 @@ package dataposter import ( "context" + "crypto/tls" + "crypto/x509" "encoding/json" "fmt" "io" @@ -74,10 +76,12 @@ func TestExternalSigner(t *testing.T) { }() signer, addr, err := externalSigner(ctx, &ExternalSignerCfg{ - Address: srv.address.Hex(), - URL: "https://localhost:1234", - Method: "test_signTransaction", - RootCA: cert, + Address: srv.address.Hex(), + URL: "https://localhost:1234", + Method: "test_signTransaction", + RootCA: cert, + ClientCert: "./testdata/client.crt", + ClientPrivateKey: "./testdata/client.key", }) if err != nil { t.Fatalf("Error getting external signer: %v", err) @@ -129,7 +133,24 @@ func newServer(ctx context.Context, t *testing.T) (*http.Server, *server) { "test_signTransaction": s.signTransaction, } m := http.NewServeMux() - httpSrv := &http.Server{Addr: ":1234", Handler: m, ReadTimeout: 5 * time.Second} + + clientCert, err := os.ReadFile("./testdata/client.crt") + if err != nil { + panic(err) + } + pool := x509.NewCertPool() + pool.AppendCertsFromPEM(clientCert) + + httpSrv := &http.Server{ + Addr: ":1234", + Handler: m, + ReadTimeout: 5 * time.Second, + TLSConfig: &tls.Config{ + MinVersion: tls.VersionTLS12, + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: pool, + }, + } m.HandleFunc("/", s.mux) return httpSrv, s } diff --git a/arbnode/dataposter/testdata/client.cnf b/arbnode/dataposter/testdata/client.cnf new file mode 100644 index 000000000..8c15cc3db --- /dev/null +++ b/arbnode/dataposter/testdata/client.cnf @@ -0,0 +1,52 @@ +[req] +default_bits = 2048 +default_keyfile = server-key.pem +distinguished_name = subject +req_extensions = req_ext +x509_extensions = x509_ext +string_mask = utf8only + +[subject] +countryName = CH +countryName_default = CH + +stateOrProvinceName = Zurich +stateOrProvinceName_default = ZH + +localityName = city +localityName_default = Zurich + +organizationName = Offchain Labs +organizationName_default = Offchain Labs + +commonName = offchainlabs.ch +commonName_default = localhost + +emailAddress = Email Address +emailAddress_default = notabigdeal@offchainlabs.ch + +[x509_ext] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer + +basicConstraints = CA:FALSE +keyUsage = digitalSignature, keyEncipherment +subjectAltName = @alternate_names +nsComment = "OpenSSL Generated Certificate" + +[req_ext] +subjectKeyIdentifier = hash + +basicConstraints = CA:FALSE +keyUsage = digitalSignature, keyEncipherment +subjectAltName = @alternate_names +nsComment = "OpenSSL Generated Certificate" + +[alternate_names] +DNS.1 = localhost +DNS.2 = 127.0.0.1 + +[alternate_names] +DNS.1 = localhost +DNS.2 = 127.0.0.1 + diff --git a/arbnode/dataposter/testdata/client.crt b/arbnode/dataposter/testdata/client.crt new file mode 100644 index 000000000..3d494be82 --- /dev/null +++ b/arbnode/dataposter/testdata/client.crt @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIE0jCCA7qgAwIBAgIUPaBB3/hHMpZfGB3VOw1+mHG4LnUwDQYJKoZIhvcNAQEL +BQAwgYMxCzAJBgNVBAYTAkNIMQswCQYDVQQIDAJaSDEPMA0GA1UEBwwGWnVyaWNo +MRYwFAYDVQQKDA1PZmZjaGFpbiBMYWJzMRIwEAYDVQQDDAlsb2NhbGhvc3QxKjAo +BgkqhkiG9w0BCQEWG25vdGFiaWdkZWFsQG9mZmNoYWlubGFicy5jaDAeFw0yMzEw +MTYxNDU2MjhaFw0yNDEwMTUxNDU2MjhaMIGDMQswCQYDVQQGEwJDSDELMAkGA1UE +CAwCWkgxDzANBgNVBAcMBlp1cmljaDEWMBQGA1UECgwNT2ZmY2hhaW4gTGFiczES +MBAGA1UEAwwJbG9jYWxob3N0MSowKAYJKoZIhvcNAQkBFhtub3RhYmlnZGVhbEBv +ZmZjaGFpbmxhYnMuY2gwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1 +1asfUzv07QTVwlM4o3g51ilIFEApPkpdQej/GIItLEVRQW+GI9jYuEM07wdwMhSH +JPFNbZB3dmBuqDLx13hY03ufyeY+nab0/sO6x13kXChvIqgPRyJtkEAoYkMM3W0D +S6HeL/6DFoTQ2xAlZb/7i/9deuUwDL3MNVSjPCm9PjFzSOFgAQQud2uUT7aENGuG +Whw3oXz9gU/8gv3keLzcIa2PHyEW5M7jeGSYMjfW3wr0d+Z5mSNRc/U6kncKi06c +QrMKrgFfF7a5kHgxUL7bRCGgCMemXe7VfrW6oKT11JcLWDKhe+uo6bNXUptek55H +HfQi6x8cbM46/h3riZA3AgMBAAGjggE6MIIBNjAdBgNVHQ4EFgQUQD2BOems0+JQ +br234cW5noMmXRIwga0GA1UdIwSBpTCBoqGBiaSBhjCBgzELMAkGA1UEBhMCQ0gx +CzAJBgNVBAgMAlpIMQ8wDQYDVQQHDAZadXJpY2gxFjAUBgNVBAoMDU9mZmNoYWlu +IExhYnMxEjAQBgNVBAMMCWxvY2FsaG9zdDEqMCgGCSqGSIb3DQEJARYbbm90YWJp +Z2RlYWxAb2ZmY2hhaW5sYWJzLmNoghQ9oEHf+Ecyll8YHdU7DX6YcbgudTAJBgNV +HRMEAjAAMAsGA1UdDwQEAwIFoDAfBgNVHREEGDAWgglsb2NhbGhvc3SCCTEyNy4w +LjAuMTAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNh +dGUwDQYJKoZIhvcNAQELBQADggEBAF4EVkOZZeMIvv0JViP7NsmIl2ke/935x6Hd +hQiLUw13XHYXzMa5/8Y5fnKjttBODpFoQlwjgI18vzuYzItYMBc2cabQJcpfG+Wq +M3m/wl1TC2XOuHj1E4RA/nU3tslntahtXG+vkks9RN+f9irHUhDRR6AGSnSB2Gi/ +B2OGmXn7S4Qge8+fGHAjN+tlu+tOoEWP6R3if/a9UIe5EGM8QTe4zw6lr+iPrOhC +M94pK5IEWn5IIGhr3zJIYkm/Dp+rFqhV1sqPOjjFLVCA7KJ3jVVVHlcm4Xa/+fyk +CIm7/VAmnbeUNlMbkXNOfQMeku8Iwsu80pvf3kjhU/PgO/5oojk= +-----END CERTIFICATE----- diff --git a/arbnode/dataposter/testdata/client.key b/arbnode/dataposter/testdata/client.key new file mode 100644 index 000000000..b14941dd9 --- /dev/null +++ b/arbnode/dataposter/testdata/client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC11asfUzv07QTV +wlM4o3g51ilIFEApPkpdQej/GIItLEVRQW+GI9jYuEM07wdwMhSHJPFNbZB3dmBu +qDLx13hY03ufyeY+nab0/sO6x13kXChvIqgPRyJtkEAoYkMM3W0DS6HeL/6DFoTQ +2xAlZb/7i/9deuUwDL3MNVSjPCm9PjFzSOFgAQQud2uUT7aENGuGWhw3oXz9gU/8 +gv3keLzcIa2PHyEW5M7jeGSYMjfW3wr0d+Z5mSNRc/U6kncKi06cQrMKrgFfF7a5 +kHgxUL7bRCGgCMemXe7VfrW6oKT11JcLWDKhe+uo6bNXUptek55HHfQi6x8cbM46 +/h3riZA3AgMBAAECggEADUboCYMCpm+LqIhzNCtqswQD6QsiSwCmqs8nuKZGk9ue ++hmZj5IpgMJZLrgvWY4s+PGfgiRR/28QCBrVXkETiZ5zirQFN4tvLlKcSK4xZf29 +FBRUCiPxck36NhiqrBNOi1Mn8BKedl4cESkvSu1cvcmeOh100HPcHfLDVqHx3qsl +D/5yMkT2+zdhtLa+X3nkAa+3aibOvgtyfkV679e20CG6h89N9GBKkTXO8ioLZZVm +84ksnd4FcpTo7ebJJxElEB+ZA4akPHbF6ArUmcpqtGso5GtwqqO2ZlguSn2XQT0d +jqvOG4DwfSXk6SpE/dpWvU92fmxWAxZvGrZNgDyJ2QKBgQDyQ8NN4b80Yza/YXar +LWx8A6B0eMc1dXgt9m3UUI+titt45jEcaXhCX01FRFTznWGmWFtJmcWBoaQVPVel +IcDYQSxEuBUrCeI75ocv/IQtENaiX3TK7Nlz5RHfpQpfDVJq45lpiD38CGkYkAif +9pSzC8aup4W3WR0JJZ1AOHUZaQKBgQDAJNJnaSNzB+eDWTKCIN5V9X3QMkmjsuir +Nf2lBXHYARnlYWAbtYFG12wLJQMTNX5ewVQQrWtsdPkGPpCnPLelUTxMssrsXjej +JlLzYUfzRBqEXMI3AA9bVdiauxId2RTcp2F81SM1keCMcuHYxrzVkBSOC9u3wCnb +Whb6+feInwKBgQCbzgC5AcoaQwReqKvNAvWV/C8hONvFAbs8tBOGTBlbHsZvRnun +Lh1tciUbuwp3cmvuszxiZUakS/RexIitZrvDWIbD2y+h8kVRCL1Am0HWSdH/syxF +pXVkF5obHuVApCyxGZb8S+axRCdy6I7jcY3IaHZqtMpGVEVcMJilSKnmoQKBgQCC +tEmgaMfhhx34nqOaG4vDA4T7LEolnh1h4g9RwztnCZC5FZ1QHA79xqrLhfjqhzgY +cwChe6aYl5WSptq1uLrgLTuMnQ8m7QyB4h8JSkKse8ZiBctjqJnJssLutpSjUzk6 +xG2vgjk6RqpuP/PcB40K5cDlw7FJ9OFEQqthPMsi1wKBgQC0/vv5bY3DQ+wV6gUy +nFoSa/XNHaa8y7jmmlCnWJqs6DAAQQ3VW0tPX03GYL/NDcI+PwzYDHDkSB6Qa/o8 +VzVGK1/kr/+bveNvqmi0vNb54fMFLveGgsY4Cu1cffiw8m6nYJ/V4eCsHfpF1B5L +5HDnt5rFKt1Mi9WsUSRtxipxBA== +-----END PRIVATE KEY----- From 70ab85f039739015e645ab33512f7b051a9cf404 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 16 Oct 2023 17:22:01 +0200 Subject: [PATCH 283/775] Set min tls verion --- arbnode/dataposter/data_poster.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 56e87e3b2..eb4cde509 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -188,7 +188,8 @@ func rpcClient(ctx context.Context, opts *ExternalSignerCfg) (*rpc.Client, error &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ - RootCAs: pool, + MinVersion: tls.VersionTLS12, + RootCAs: pool, }, }, }, From f99cfe673e5799404186a60ce254a37d48935397 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 16 Oct 2023 10:31:24 -0500 Subject: [PATCH 284/775] refactor --- .github/workflows/waitForNitro.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/waitForNitro.sh b/.github/workflows/waitForNitro.sh index a1b7f2ad0..add83e24b 100755 --- a/.github/workflows/waitForNitro.sh +++ b/.github/workflows/waitForNitro.sh @@ -1,8 +1,7 @@ # poll the nitro endpoint until we get a 0 return code or 30mins have passed, in that case exit 1 -start_time=$(date +%s) -timeout=1800 +timeout_time=$(($(date +%s) + 1800)) -while (( $(date +%s) - start_time <= timeout )); do +while (( $(date +%s) <= timeout_time )); do curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":45678,"method":"eth_chainId","params":[]}' 'http://localhost:8547' if [ "$?" -eq "0" ]; then exit 0 From e69e47725fd87db68c5073ee0604732ed40bbc7b Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Mon, 16 Oct 2023 17:40:19 +0200 Subject: [PATCH 285/775] Add --log-type option for daserver This adds the ability to have json logs. --- cmd/daserver/daserver.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/cmd/daserver/daserver.go b/cmd/daserver/daserver.go index 335aba6a1..b2f8728a7 100644 --- a/cmd/daserver/daserver.go +++ b/cmd/daserver/daserver.go @@ -44,6 +44,7 @@ type DAServerConfig struct { Conf genericconf.ConfConfig `koanf:"conf"` LogLevel int `koanf:"log-level"` + LogType string `koanf:"log-type"` Metrics bool `koanf:"metrics"` MetricsServer genericconf.MetricsServerConfig `koanf:"metrics-server"` @@ -62,11 +63,12 @@ var DefaultDAServerConfig = DAServerConfig{ RESTServerTimeouts: genericconf.HTTPServerTimeoutConfigDefault, DataAvailability: das.DefaultDataAvailabilityConfig, Conf: genericconf.ConfConfigDefault, + LogLevel: int(log.LvlInfo), + LogType: "plaintext", Metrics: false, MetricsServer: genericconf.MetricsServerConfigDefault, PProf: false, PprofCfg: genericconf.PProfDefault, - LogLevel: 3, } func main() { @@ -99,6 +101,8 @@ func parseDAServer(args []string) (*DAServerConfig, error) { genericconf.PProfAddOptions("pprof-cfg", f) f.Int("log-level", int(log.LvlInfo), "log level; 1: ERROR, 2: WARN, 3: INFO, 4: DEBUG, 5: TRACE") + f.String("log-type", DefaultDAServerConfig.LogType, "log type (plaintext or json)") + das.DataAvailabilityConfigAddDaserverOptions("data-availability", f) genericconf.ConfConfigAddOptions("conf", f) @@ -178,7 +182,12 @@ func startup() error { confighelpers.PrintErrorAndExit(errors.New("please specify at least one of --enable-rest or --enable-rpc"), printSampleUsage) } - glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) + logFormat, err := genericconf.ParseLogType(serverConfig.LogType) + if err != nil { + flag.Usage() + panic(fmt.Sprintf("Error parsing log type: %v", err)) + } + glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, logFormat)) glogger.Verbosity(log.Lvl(serverConfig.LogLevel)) log.Root().SetHandler(glogger) From f5593692885c7401195a6907339ea1d03df95c35 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 16 Oct 2023 10:46:04 -0500 Subject: [PATCH 286/775] refactor --- .github/workflows/waitForNitro.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/waitForNitro.sh b/.github/workflows/waitForNitro.sh index add83e24b..cf3f6484f 100755 --- a/.github/workflows/waitForNitro.sh +++ b/.github/workflows/waitForNitro.sh @@ -1,9 +1,9 @@ +#!/bin/bash # poll the nitro endpoint until we get a 0 return code or 30mins have passed, in that case exit 1 timeout_time=$(($(date +%s) + 1800)) while (( $(date +%s) <= timeout_time )); do - curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":45678,"method":"eth_chainId","params":[]}' 'http://localhost:8547' - if [ "$?" -eq "0" ]; then + if curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":45678,"method":"eth_chainId","params":[]}' 'http://localhost:8547'; then exit 0 else sleep 20 From 754d9be19aacb8cca479701099930e45b8e1d8e5 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 16 Oct 2023 17:58:32 +0200 Subject: [PATCH 287/775] add simple storage key caching tests --- arbos/storage/storage_test.go | 75 +++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/arbos/storage/storage_test.go b/arbos/storage/storage_test.go index 35e6b7c4b..a8d424d14 100644 --- a/arbos/storage/storage_test.go +++ b/arbos/storage/storage_test.go @@ -1,11 +1,16 @@ package storage import ( + "bytes" + "fmt" "math/big" + "math/rand" + "sync" "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/crypto" "github.com/offchainlabs/nitro/arbos/burn" "github.com/offchainlabs/nitro/util/arbmath" ) @@ -91,3 +96,73 @@ func TestStorageBackedBigInt(t *testing.T) { }) } } + +func TestOpenCachedSubStorage(t *testing.T) { + s := NewMemoryBacked(burn.NewSystemBurner(nil, false)) + var subSpaceIDs [][]byte + for i := 0; i < 20; i++ { + subSpaceIDs = append(subSpaceIDs, []byte{byte(rand.Intn(0xff))}) + } + var expectedKeys [][]byte + for _, subSpaceID := range subSpaceIDs { + expectedKeys = append(expectedKeys, crypto.Keccak256(s.storageKey, subSpaceID)) + } + n := len(subSpaceIDs) * 50 + start := make(chan struct{}) + errs := make(chan error, n) + var wg sync.WaitGroup + for i := 0; i < n; i++ { + j := i % len(subSpaceIDs) + subSpaceID, expectedKey := subSpaceIDs[j], expectedKeys[j] + wg.Add(1) + go func() { + defer wg.Done() + <-start + ss := s.OpenCachedSubStorage(subSpaceID) + if !bytes.Equal(ss.storageKey, expectedKey) { + errs <- fmt.Errorf("unexpected storage key, want: %v, have: %v", expectedKey, ss.storageKey) + } + }() + } + close(start) + wg.Wait() + select { + case err := <-errs: + t.Fatal(err) + default: + } +} + +func TestMapAddressCache(t *testing.T) { + s := NewMemoryBacked(burn.NewSystemBurner(nil, false)) + var keys []common.Hash + for i := 0; i < 20; i++ { + keys = append(keys, common.BytesToHash([]byte{byte(rand.Intn(0xff))})) + } + var expectedMapped []common.Hash + for _, key := range keys { + expectedMapped = append(expectedMapped, s.mapAddress(key)) + } + n := len(keys) * 50 + start := make(chan struct{}) + errs := make(chan error, n) + var wg sync.WaitGroup + for i := 0; i < n; i++ { + j := i % len(keys) + key, expected := keys[j], expectedMapped[j] + wg.Add(1) + go func() { + defer wg.Done() + <-start + mapped := s.mapAddress(key) + if !bytes.Equal(mapped.Bytes(), expected.Bytes()) { + errs <- fmt.Errorf("unexpected storage key, want: %v, have: %v", expected, mapped) + } + }() + } + close(start) + wg.Wait() + if len(errs) > 0 { + t.Fatal(<-errs) + } +} From 6462f7651f538300b4b43e056fec1020ebf6e4c2 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Mon, 16 Oct 2023 19:20:35 +0200 Subject: [PATCH 288/775] Fix TestSequencerPrice* tests for SimulatedBeacon --- system_tests/fees_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system_tests/fees_test.go b/system_tests/fees_test.go index bdd998357..15ea15623 100644 --- a/system_tests/fees_test.go +++ b/system_tests/fees_test.go @@ -135,6 +135,11 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { conf := arbnode.ConfigDefaultL1Test() conf.DelayedSequencer.FinalizeDistance = 1 + // SimulatedBeacon running in OnDemand block production mode + // produces blocks in the future so we need this to avoid the batch poster + // not posting because the txs appear to be in the future. + conf.BatchPoster.MaxDelay = -time.Hour + l2info, node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, chainConfig, nil) defer requireClose(t, l1stack) defer node.StopAndWait() From 927a760942846eed49658147adbe62a9427b449a Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 16 Oct 2023 15:43:49 -0500 Subject: [PATCH 289/775] =?UTF-8?q?Add=20metrics=20to=20time=20each=20part?= =?UTF-8?q?=20of=20WSBroadcastServer=E2=80=99s=20StartWithHeader?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wsbroadcastserver/wsbroadcastserver.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/wsbroadcastserver/wsbroadcastserver.go b/wsbroadcastserver/wsbroadcastserver.go index cd277387a..f3e693d5d 100644 --- a/wsbroadcastserver/wsbroadcastserver.go +++ b/wsbroadcastserver/wsbroadcastserver.go @@ -23,6 +23,7 @@ import ( flag "github.com/spf13/pflag" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" "github.com/offchainlabs/nitro/arbutil" ) @@ -32,6 +33,8 @@ var ( HTTPHeaderFeedClientVersion = textproto.CanonicalMIMEHeaderKey("Arbitrum-Feed-Client-Version") HTTPHeaderRequestedSequenceNumber = textproto.CanonicalMIMEHeaderKey("Arbitrum-Requested-Sequence-Number") HTTPHeaderChainId = textproto.CanonicalMIMEHeaderKey("Arbitrum-Chain-Id") + UpgradeToWSTimer = metrics.NewRegisteredTimer("arb/wsbroadcastserver/wsupgrade/duration", nil) + StartWithHeaderTimer = metrics.NewRegisteredTimer("arb/wsbroadcastserver/startwithheader/duration", nil) ) const ( @@ -205,6 +208,7 @@ func (s *WSBroadcastServer) Start(ctx context.Context) error { } func (s *WSBroadcastServer) StartWithHeader(ctx context.Context, header ws.HandshakeHeader) error { + startTimeMain := time.Now() s.startMutex.Lock() defer s.startMutex.Unlock() if s.started { @@ -316,7 +320,10 @@ func (s *WSBroadcastServer) StartWithHeader(ctx context.Context, header ws.Hands } // Zero-copy upgrade to WebSocket connection. + startTime := time.Now() _, err = upgrader.Upgrade(conn) + elapsed := time.Since(startTime) + UpgradeToWSTimer.Update(elapsed) if err != nil { if err.Error() != "" { @@ -483,6 +490,9 @@ func (s *WSBroadcastServer) StartWithHeader(ctx context.Context, header ws.Hands s.started = true + elapsedMain := time.Since(startTimeMain) + StartWithHeaderTimer.Update(elapsedMain) + return nil } From b49e10369bae00f3b3ef8946355edf2e03fb1209 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 16 Oct 2023 15:52:27 -0500 Subject: [PATCH 290/775] refactor --- wsbroadcastserver/wsbroadcastserver.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wsbroadcastserver/wsbroadcastserver.go b/wsbroadcastserver/wsbroadcastserver.go index f3e693d5d..43ac27593 100644 --- a/wsbroadcastserver/wsbroadcastserver.go +++ b/wsbroadcastserver/wsbroadcastserver.go @@ -33,8 +33,8 @@ var ( HTTPHeaderFeedClientVersion = textproto.CanonicalMIMEHeaderKey("Arbitrum-Feed-Client-Version") HTTPHeaderRequestedSequenceNumber = textproto.CanonicalMIMEHeaderKey("Arbitrum-Requested-Sequence-Number") HTTPHeaderChainId = textproto.CanonicalMIMEHeaderKey("Arbitrum-Chain-Id") - UpgradeToWSTimer = metrics.NewRegisteredTimer("arb/wsbroadcastserver/wsupgrade/duration", nil) - StartWithHeaderTimer = metrics.NewRegisteredTimer("arb/wsbroadcastserver/startwithheader/duration", nil) + upgradeToWSTimer = metrics.NewRegisteredTimer("arb/wsbroadcastserver/wsupgrade/duration", nil) + startWithHeaderTimer = metrics.NewRegisteredTimer("arb/wsbroadcastserver/startwithheader/duration", nil) ) const ( @@ -323,7 +323,7 @@ func (s *WSBroadcastServer) StartWithHeader(ctx context.Context, header ws.Hands startTime := time.Now() _, err = upgrader.Upgrade(conn) elapsed := time.Since(startTime) - UpgradeToWSTimer.Update(elapsed) + upgradeToWSTimer.Update(elapsed) if err != nil { if err.Error() != "" { @@ -491,7 +491,7 @@ func (s *WSBroadcastServer) StartWithHeader(ctx context.Context, header ws.Hands s.started = true elapsedMain := time.Since(startTimeMain) - StartWithHeaderTimer.Update(elapsedMain) + startWithHeaderTimer.Update(elapsedMain) return nil } From c77006ac01ccacabb62a6da9ccf1e2681b93555d Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 16 Oct 2023 22:55:14 -0600 Subject: [PATCH 291/775] Change default sequencer MaxBlockSpeed to 250ms --- execution/gethexec/sequencer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 77442f65e..61792ed9b 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -85,7 +85,7 @@ type SequencerConfigFetcher func() *SequencerConfig var DefaultSequencerConfig = SequencerConfig{ Enable: false, - MaxBlockSpeed: time.Millisecond * 100, + MaxBlockSpeed: time.Millisecond * 250, MaxRevertGasReject: params.TxGas + 10000, MaxAcceptableTimestampDelta: time.Hour, Forwarder: DefaultSequencerForwarderConfig, From 487f6eeba172805c8be6ce2a0bb8914e55c30e5d Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 16 Oct 2023 23:07:06 -0600 Subject: [PATCH 292/775] Fix retryable gas estimation when overriding gas price to zero --- arbos/tx_processor.go | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/arbos/tx_processor.go b/arbos/tx_processor.go index 4eeffc679..436998dfb 100644 --- a/arbos/tx_processor.go +++ b/arbos/tx_processor.go @@ -245,16 +245,17 @@ func (p *TxProcessor) StartTxHook() (endTxNow bool, gasUsed uint64, err error, r } balance := statedb.GetBalance(tx.From) - basefee := evm.Context.BaseFee + effectiveBaseFee := evm.Context.BaseFee usergas := p.msg.GasLimit - maxGasCost := arbmath.BigMulByUint(tx.GasFeeCap, usergas) - maxFeePerGasTooLow := arbmath.BigLessThan(tx.GasFeeCap, basefee) - if p.msg.TxRunMode == core.MessageGasEstimationMode && tx.GasFeeCap.BitLen() == 0 { - // In gas estimation mode, we permit a zero gas fee cap. - // This matches behavior with normal tx gas estimation. - maxFeePerGasTooLow = false + if p.msg.TxRunMode != core.MessageCommitMode && tx.GasFeeCap.BitLen() == 0 { + // In gas estimation or eth_call mode, we permit a zero gas fee cap. + // This matches behavior with normal tx gas estimation and eth_call. + effectiveBaseFee = common.Big0 } + + maxGasCost := arbmath.BigMulByUint(tx.GasFeeCap, usergas) + maxFeePerGasTooLow := arbmath.BigLessThan(tx.GasFeeCap, effectiveBaseFee) if arbmath.BigLessThan(balance, maxGasCost) || usergas < params.TxGas || maxFeePerGasTooLow { // User either specified too low of a gas fee cap, didn't have enough balance to pay for gas, // or the specified gas limit is below the minimum transaction gas cost. @@ -268,7 +269,7 @@ func (p *TxProcessor) StartTxHook() (endTxNow bool, gasUsed uint64, err error, r } // pay for the retryable's gas and update the pools - gascost := arbmath.BigMulByUint(basefee, usergas) + gascost := arbmath.BigMulByUint(effectiveBaseFee, usergas) networkCost := gascost if p.state.ArbOSVersion() >= 11 { infraFeeAccount, err := p.state.InfraFeeAccount() @@ -276,7 +277,7 @@ func (p *TxProcessor) StartTxHook() (endTxNow bool, gasUsed uint64, err error, r if infraFeeAccount != (common.Address{}) { minBaseFee, err := p.state.L2PricingState().MinBaseFeeWei() p.state.Restrict(err) - infraFee := arbmath.BigMin(minBaseFee, basefee) + infraFee := arbmath.BigMin(minBaseFee, effectiveBaseFee) infraCost := arbmath.BigMulByUint(infraFee, usergas) infraCost = takeFunds(networkCost, infraCost) if err := transfer(&tx.From, &infraFeeAccount, infraCost); err != nil { @@ -294,7 +295,7 @@ func (p *TxProcessor) StartTxHook() (endTxNow bool, gasUsed uint64, err error, r } withheldGasFunds := takeFunds(availableRefund, gascost) // gascost is conceptually charged before the gas price refund - gasPriceRefund := arbmath.BigMulByUint(arbmath.BigSub(tx.GasFeeCap, basefee), tx.Gas) + gasPriceRefund := arbmath.BigMulByUint(arbmath.BigSub(tx.GasFeeCap, effectiveBaseFee), tx.Gas) if gasPriceRefund.Sign() < 0 { // This should only be possible during gas estimation mode gasPriceRefund.SetInt64(0) @@ -310,7 +311,7 @@ func (p *TxProcessor) StartTxHook() (endTxNow bool, gasUsed uint64, err error, r retryTxInner, err := retryable.MakeTx( underlyingTx.ChainId(), 0, - basefee, + effectiveBaseFee, usergas, ticketId, tx.FeeRefundAddr, From 2497ad4f019e3dd6d7d1f3d50db7005da48c3e26 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Tue, 17 Oct 2023 15:59:12 +0200 Subject: [PATCH 293/775] Fix TestBlockValidator for SimulatedBeacon --- system_tests/block_validator_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index fa3d902b1..e28287827 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -154,7 +154,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops }) } - _, err := WaitForTx(ctx, l2clientB, delayedTx.Hash(), time.Second*5) + _, err := WaitForTx(ctx, l2clientB, delayedTx.Hash(), time.Second*25) Require(t, err) } From fd11626f41a97b270f4d6a7beae7dd4445b6e379 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Tue, 17 Oct 2023 16:43:00 +0200 Subject: [PATCH 294/775] Fix TestDelayInboxLong for SimulatedBeacon --- system_tests/delayedinboxlong_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/system_tests/delayedinboxlong_test.go b/system_tests/delayedinboxlong_test.go index 994fbdd68..45abe2fe5 100644 --- a/system_tests/delayedinboxlong_test.go +++ b/system_tests/delayedinboxlong_test.go @@ -62,6 +62,7 @@ func TestDelayInboxLong(t *testing.T) { Require(t, err) } // Checking every tx is expensive, so we just check the last, assuming that the others succeeded too + confirmLatestBlock(ctx, t, l1info, l1client) _, err := EnsureTxSucceeded(ctx, l1client, l1Txs[len(l1Txs)-1]) Require(t, err) } From 127dda7363de655722381e0d9f5e8ec7bab68fe0 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Tue, 17 Oct 2023 17:29:35 +0200 Subject: [PATCH 295/775] Fix TestSendRawTransactionConditionalBasic --- system_tests/conditionaltx_test.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index 760ec2735..5848391b5 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -240,7 +240,17 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { block, err := l1client.BlockByNumber(ctx, nil) Require(t, err) blockNumber := block.NumberU64() - blockTime := block.Time() + fixBlockTime := func(blockTime uint64) uint64 { + since := time.Now().Unix() - int64(blockTime) + if int64(since) < 0 { + // If using SimulatedBeacon then the block time will be ahead of + // the actual time since it generates a new block for each tx in + // on demand mode, and assigns them to sequentially increasing timestamps. + return uint64(time.Now().Unix()) + } + return blockTime + } + blockTime := fixBlockTime(block.Time()) optionsA := getOptions(contractAddress1, currentRootHash1, currentSlotValueMap1) optionsB := getOptions(contractAddress2, currentRootHash2, currentSlotValueMap2) @@ -277,7 +287,7 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { block, err = l1client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() - blockTime = block.Time() + blockTime = fixBlockTime(block.Time()) optionsC := getOptions(contractAddress1, currentRootHash1, currentSlotValueMap1) optionsD := getOptions(contractAddress2, currentRootHash2, currentSlotValueMap2) @@ -293,7 +303,7 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { block, err = l1client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() - blockTime = block.Time() + blockTime = fixBlockTime(block.Time()) options3 := optionsDedupProduct(t, options2, getUnfulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options3 { testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) From 34fe2d041d966f6cbbc425b736c5231db0f3a7b0 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Tue, 17 Oct 2023 19:03:08 +0200 Subject: [PATCH 296/775] Add default method for external signer --- arbnode/dataposter/data_poster.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index fa7dfec48..cf4aab9e3 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -772,7 +772,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ UseNoOpStorage: false, LegacyStorageEncoding: true, Dangerous: DangerousConfig{ClearDBStorage: false}, - ExternalSigner: ExternalSignerCfg{}, + ExternalSigner: ExternalSignerCfg{Method: "eth_signTransaction"}, } var DefaultDataPosterConfigForValidator = func() DataPosterConfig { @@ -794,7 +794,7 @@ var TestDataPosterConfig = DataPosterConfig{ AllocateMempoolBalance: true, UseDBStorage: false, UseNoOpStorage: false, - ExternalSigner: ExternalSignerCfg{}, + ExternalSigner: ExternalSignerCfg{Method: "eth_signTransaction"}, } var TestDataPosterConfigForValidator = func() DataPosterConfig { From f285d2e6e93741c2ee76e36a1aa2f90f915556ea Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Tue, 17 Oct 2023 19:09:49 +0200 Subject: [PATCH 297/775] Change port 443 back to 1234 --- arbnode/dataposter/dataposter_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index 0b3b8cba5..519f5f49a 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -66,7 +66,7 @@ func TestExternalSigner(t *testing.T) { }) cert, key := "./testdata/localhost.crt", "./testdata/localhost.key" go func() { - fmt.Println("Server is listening on port 443...") + fmt.Println("Server is listening on port 1234...") if err := httpSrv.ListenAndServeTLS(cert, key); err != nil && err != http.ErrServerClosed { t.Errorf("ListenAndServeTLS() unexpected error: %v", err) return From 059a45e804657901d62a3ab908d1886a76ad0f22 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 19 Oct 2023 10:40:51 +0200 Subject: [PATCH 298/775] revert testnode pin --- nitro-testnode | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nitro-testnode b/nitro-testnode index 7ad12c0f1..aee6ceff9 160000 --- a/nitro-testnode +++ b/nitro-testnode @@ -1 +1 @@ -Subproject commit 7ad12c0f1be75a72c7360d5258e0090f8225594e +Subproject commit aee6ceff9c9d3fb2749da55a7d7842f23d1bfc8e From b015ab8f06f8fc72c827af4388428949cec8a5c6 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 19 Oct 2023 10:46:31 +0200 Subject: [PATCH 299/775] Make client certificate optional --- arbnode/dataposter/data_poster.go | 19 +++++++++++-------- arbnode/dataposter/dataposter_test.go | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 39fda3f2a..687b26ba2 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -175,15 +175,18 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro } func rpcClient(ctx context.Context, opts *ExternalSignerCfg) (*rpc.Client, error) { - clientCert, err := tls.LoadX509KeyPair(opts.ClientCert, opts.ClientPrivateKey) - if err != nil { - return nil, fmt.Errorf("error loading client certificate and private key: %w", err) + tlsCfg := &tls.Config{ + MinVersion: tls.VersionTLS12, } - tlsCfg := &tls.Config{ - MinVersion: tls.VersionTLS12, - Certificates: []tls.Certificate{clientCert}, + if opts.ClientCert == "" || opts.ClientPrivateKey == "" { + clientCert, err := tls.LoadX509KeyPair(opts.ClientCert, opts.ClientPrivateKey) + if err != nil { + return nil, fmt.Errorf("error loading client certificate and private key: %w", err) + } + tlsCfg.Certificates = []tls.Certificate{clientCert} } + if opts.RootCA != "" { rootCrt, err := os.ReadFile(opts.RootCA) if err != nil { @@ -756,9 +759,9 @@ type ExternalSignerCfg struct { // (Optional) Path to the external signer root CA certificate. // This allows us to use self-signed certificats on the external signer. RootCA string `koanf:"root-ca"` - // Client certificate for mtls. + // (Optional) Client certificate for mtls. ClientCert string `koanf:"client-cert"` - // Client certificate key for mtls. + // (Optional) Client certificate key for mtls. ClientPrivateKey string `koanf:"client-private-key"` } diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index 4734295ae..d4d72bbbf 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -136,7 +136,7 @@ func newServer(ctx context.Context, t *testing.T) (*http.Server, *server) { clientCert, err := os.ReadFile("./testdata/client.crt") if err != nil { - panic(err) + t.Fatalf("Error reading client certificate: %v", err) } pool := x509.NewCertPool() pool.AppendCertsFromPEM(clientCert) From 1d524078dc2c41fed4f2bc3efd401e18f911047f Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 19 Oct 2023 10:55:46 +0200 Subject: [PATCH 300/775] Log when certificate is enabled, fix enabling --- arbnode/dataposter/data_poster.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 687b26ba2..1a202171e 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -179,7 +179,8 @@ func rpcClient(ctx context.Context, opts *ExternalSignerCfg) (*rpc.Client, error MinVersion: tls.VersionTLS12, } - if opts.ClientCert == "" || opts.ClientPrivateKey == "" { + if opts.ClientCert != "" && opts.ClientPrivateKey != "" { + log.Info("Client certificate for external signer is enabled") clientCert, err := tls.LoadX509KeyPair(opts.ClientCert, opts.ClientPrivateKey) if err != nil { return nil, fmt.Errorf("error loading client certificate and private key: %w", err) @@ -762,6 +763,7 @@ type ExternalSignerCfg struct { // (Optional) Client certificate for mtls. ClientCert string `koanf:"client-cert"` // (Optional) Client certificate key for mtls. + // This is required when client-cert is set. ClientPrivateKey string `koanf:"client-private-key"` } From 89f837284486917a911aabb7ef426cf87f76b9bc Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 19 Oct 2023 11:19:19 +0200 Subject: [PATCH 301/775] Use latest version of nitro-contracts and testnode --- arbnode/node.go | 20 +++++++++++--------- contracts | 2 +- nitro-testnode | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 675aca336..132a9f28d 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -303,17 +303,19 @@ func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReade validatorAddrs = append(validatorAddrs, crypto.CreateAddress(validatorWalletCreator, i)) } - deployUtilityFactories := false - maxFeePerGas := big.NewInt(0) // needed when utility factories are deployed + deployParams := rollupgen.RollupCreatorRollupDeploymentParams{ + Config:config, + BatchPoster: batchPoster, + Validators: validatorAddrs, + MaxDataSize: maxDataSize, + NativeToken: nativeToken, + DeployFactoriesToL2: false, + MaxFeePerGasForRetryables: big.NewInt(0), // needed when utility factories are deployed + } + tx, err := rollupCreator.CreateRollup( deployAuth, - config, - batchPoster, - validatorAddrs, - maxDataSize, - nativeToken, - deployUtilityFactories, - maxFeePerGas, + deployParams, ) if err != nil { return nil, fmt.Errorf("error submitting create rollup tx: %w", err) diff --git a/contracts b/contracts index 46d1767ce..b22f93c7a 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 46d1767ce2181c501f6b1f8651d6f1ace3da1c41 +Subproject commit b22f93c7a1322fb8063ad71d58acb37416d71146 diff --git a/nitro-testnode b/nitro-testnode index 9f2bd4b07..0bd1ef2c6 160000 --- a/nitro-testnode +++ b/nitro-testnode @@ -1 +1 @@ -Subproject commit 9f2bd4b0743ad111a050371b4c5233744f0e4622 +Subproject commit 0bd1ef2c6b33500f9144192edadd6491ec1e6bc7 From 1df214fa7fbae995204c0568fc1d1d43c14dad4e Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 19 Oct 2023 11:54:32 +0200 Subject: [PATCH 302/775] Lint --- arbnode/node.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 132a9f28d..4b3381e78 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -304,13 +304,13 @@ func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReade } deployParams := rollupgen.RollupCreatorRollupDeploymentParams{ - Config:config, - BatchPoster: batchPoster, - Validators: validatorAddrs, - MaxDataSize: maxDataSize, - NativeToken: nativeToken, - DeployFactoriesToL2: false, - MaxFeePerGasForRetryables: big.NewInt(0), // needed when utility factories are deployed + Config: config, + BatchPoster: batchPoster, + Validators: validatorAddrs, + MaxDataSize: maxDataSize, + NativeToken: nativeToken, + DeployFactoriesToL2: false, + MaxFeePerGasForRetryables: big.NewInt(0), // needed when utility factories are deployed } tx, err := rollupCreator.CreateRollup( From 7fa50bcdc586e7a69cdff02de344b24c78b7bee4 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 19 Oct 2023 19:15:01 +0200 Subject: [PATCH 303/775] Fix TestStakersCooperative for SimulatedBeacon Make batch poster and staker work with block times in the future produced by SimualtedBeacon. --- arbnode/batch_poster.go | 2 +- staker/staker.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 4f50831e6..f9990460c 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -198,7 +198,7 @@ var TestBatchPosterConfig = BatchPosterConfig{ MaxSize: 100000, PollInterval: time.Millisecond * 10, ErrorDelay: time.Millisecond * 10, - MaxDelay: 0, + MaxDelay: -time.Hour * 1000, WaitForMaxDelay: false, CompressionLevel: 2, DASRetentionPeriod: time.Hour * 24 * 15, diff --git a/staker/staker.go b/staker/staker.go index d52d1adc7..422b5c605 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -163,7 +163,7 @@ var TestL1ValidatorConfig = L1ValidatorConfig{ Enable: true, Strategy: "Watchtower", StakerInterval: time.Millisecond * 10, - MakeAssertionInterval: 0, + MakeAssertionInterval: -time.Hour * 1000, PostingStrategy: L1PostingStrategy{}, DisableChallenge: false, ConfirmationBlocks: 0, From 0a3e0d8bbcedad1ccae5a987928875c588d38835 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 19 Oct 2023 12:10:34 -0600 Subject: [PATCH 304/775] Fix basefee in EndTxHook --- arbos/tx_processor.go | 31 ++++++++++++++++++++++++------- go-ethereum | 2 +- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/arbos/tx_processor.go b/arbos/tx_processor.go index 436998dfb..569edb7c6 100644 --- a/arbos/tx_processor.go +++ b/arbos/tx_processor.go @@ -248,7 +248,7 @@ func (p *TxProcessor) StartTxHook() (endTxNow bool, gasUsed uint64, err error, r effectiveBaseFee := evm.Context.BaseFee usergas := p.msg.GasLimit - if p.msg.TxRunMode != core.MessageCommitMode && tx.GasFeeCap.BitLen() == 0 { + if p.msg.TxRunMode != core.MessageCommitMode && p.msg.GasFeeCap.BitLen() == 0 { // In gas estimation or eth_call mode, we permit a zero gas fee cap. // This matches behavior with normal tx gas estimation and eth_call. effectiveBaseFee = common.Big0 @@ -457,7 +457,6 @@ func (p *TxProcessor) EndTxHook(gasLeft uint64, success bool) { underlyingTx := p.msg.Tx networkFeeAccount, _ := p.state.NetworkFeeAccount() - basefee := p.evm.Context.BaseFee scenario := util.TracingAfterEVM if gasLeft > p.msg.GasLimit { @@ -467,9 +466,20 @@ func (p *TxProcessor) EndTxHook(gasLeft uint64, success bool) { if underlyingTx != nil && underlyingTx.Type() == types.ArbitrumRetryTxType { inner, _ := underlyingTx.GetInner().(*types.ArbitrumRetryTx) + effectiveBaseFee := inner.GasFeeCap + if p.msg.TxRunMode == core.MessageCommitMode && !arbmath.BigEquals(effectiveBaseFee, p.evm.Context.BaseFee) { + log.Error( + "ArbitrumRetryTx GasFeeCap doesn't match basefee in commit mode", + "txHash", underlyingTx.Hash(), + "gasFeeCap", inner.GasFeeCap, + "baseFee", p.evm.Context.BaseFee, + ) + // revert to the old behavior to avoid diverging from older nodes + effectiveBaseFee = p.evm.Context.BaseFee + } // undo Geth's refund to the From address - gasRefund := arbmath.BigMulByUint(basefee, gasLeft) + gasRefund := arbmath.BigMulByUint(effectiveBaseFee, gasLeft) err := util.BurnBalance(&inner.From, gasRefund, p.evm, scenario, "undoRefund") if err != nil { log.Error("Uh oh, Geth didn't refund the user", inner.From, gasRefund) @@ -504,7 +514,7 @@ func (p *TxProcessor) EndTxHook(gasLeft uint64, success bool) { takeFunds(maxRefund, inner.SubmissionFeeRefund) } // Conceptually, the gas charge is taken from the L1 deposit pool if possible. - takeFunds(maxRefund, arbmath.BigMulByUint(basefee, gasUsed)) + takeFunds(maxRefund, arbmath.BigMulByUint(effectiveBaseFee, gasUsed)) // Refund any unused gas, without overdrafting the L1 deposit. networkRefund := gasRefund if p.state.ArbOSVersion() >= 11 { @@ -514,7 +524,7 @@ func (p *TxProcessor) EndTxHook(gasLeft uint64, success bool) { minBaseFee, err := p.state.L2PricingState().MinBaseFeeWei() p.state.Restrict(err) // TODO MinBaseFeeWei change during RetryTx execution may cause incorrect calculation of the part of the refund that should be taken from infraFeeAccount. Unless the balances of network and infra fee accounts are too low, the amount transferred to refund address should remain correct. - infraFee := arbmath.BigMin(minBaseFee, basefee) + infraFee := arbmath.BigMin(minBaseFee, effectiveBaseFee) infraRefund := arbmath.BigMulByUint(infraFee, gasLeft) infraRefund = takeFunds(networkRefund, infraRefund) refund(infraFeeAccount, infraRefund) @@ -542,6 +552,7 @@ func (p *TxProcessor) EndTxHook(gasLeft uint64, success bool) { return } + basefee := p.evm.Context.BaseFee totalCost := arbmath.BigMul(basefee, arbmath.UintToBig(gasUsed)) // total cost = price of gas * gas burnt computeCost := arbmath.BigSub(totalCost, p.PosterFee) // total cost = network's compute + poster's L1 costs if computeCost.Sign() < 0 { @@ -603,9 +614,15 @@ func (p *TxProcessor) EndTxHook(gasLeft uint64, success bool) { func (p *TxProcessor) ScheduledTxes() types.Transactions { scheduled := types.Transactions{} time := p.evm.Context.Time - basefee := p.evm.Context.BaseFee + effectiveBaseFee := p.evm.Context.BaseFee chainID := p.evm.ChainConfig().ChainID + if p.msg.TxRunMode != core.MessageCommitMode && p.msg.GasFeeCap.BitLen() == 0 { + // In gas estimation or eth_call mode, we permit a zero gas fee cap. + // This matches behavior with normal tx gas estimation and eth_call. + effectiveBaseFee = common.Big0 + } + logs := p.evm.StateDB.GetCurrentTxLogs() for _, log := range logs { if log.Address != ArbRetryableTxAddress || log.Topics[0] != RedeemScheduledEventID { @@ -624,7 +641,7 @@ func (p *TxProcessor) ScheduledTxes() types.Transactions { redeem, _ := retryable.MakeTx( chainID, event.SequenceNum, - basefee, + effectiveBaseFee, event.DonatedGas, event.TicketId, event.GasDonor, diff --git a/go-ethereum b/go-ethereum index b4221631e..e8c8827c0 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit b4221631e1e5eac86f01582bd74234e3c0f7f5c7 +Subproject commit e8c8827c0b9e22e60829da1945cba9c451cda85a From 295b465b0d9652e5943c042175c6d3555516a14e Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Thu, 19 Oct 2023 14:00:47 -0700 Subject: [PATCH 305/775] Stop using actions-rs --- .github/workflows/arbitrator-ci.yml | 36 ++++++++------------------- .github/workflows/ci.yml | 23 +++-------------- .github/workflows/codeql-analysis.yml | 9 ++----- .github/workflows/docker.yml | 2 +- 4 files changed, 17 insertions(+), 53 deletions(-) diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index f2b141fb4..8c491a421 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-8 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: recursive @@ -49,23 +49,18 @@ jobs: cache-dependency-path: '**/yarn.lock' - name: Install rust stable - uses: actions-rs/toolchain@v1 - id: install-rust + uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: "stable" - override: true components: 'llvm-tools-preview, rustfmt, clippy' + targets: 'wasm32-wasi, wasm32-unknown-unknown' - name: Install grcov - uses: actions-rs/install@v0.1 + uses: jaxxstorm/action-install-gh-release@v1.10.0 with: - crate: grcov - version: latest - use-tool-cache: true - - - name: Install rust wasm targets - run: rustup target add wasm32-wasi wasm32-unknown-unknown + repo: mozilla/grcov + tag: v0.8.18 + extension: "\\.bz2" + cache: enable - name: Cache Rust intermediate build products uses: actions/cache@v3 @@ -148,22 +143,13 @@ jobs: echo RUSTDOCFLAGS="-Cpanic=abort" >> $GITHUB_ENV - name: Clippy check - uses: actions-rs/cargo@v1 - with: - command: clippy - args: --all --manifest-path arbitrator/Cargo.toml -- -D warnings + run: cargo clippy --all --manifest-path arbitrator/Cargo.toml -- -D warnings - name: Run rust tests - uses: actions-rs/cargo@v1 - with: - command: test - args: --all --manifest-path arbitrator/Cargo.toml + run: cargo test --all --manifest-path arbitrator/Cargo.toml - name: Rustfmt - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all --manifest-path arbitrator/Cargo.toml -- --check + run: cargo fmt --all --manifest-path arbitrator/Cargo.toml -- --check - name: Make proofs from test cases run: make -j test-gen-proofs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0734aecfd..022c26d2f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true @@ -53,27 +53,10 @@ jobs: sudo apt-get update && sudo apt-get install -y lld-14 sudo ln -s /usr/bin/wasm-ld-14 /usr/local/bin/wasm-ld - - name: Install rust wasm32-unknown-unknown - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: "stable" - target: wasm32-unknown-unknown - - - name: Install rust wasm32-wasi - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: "stable" - target: wasm32-wasi - - name: Install rust stable - uses: actions-rs/toolchain@v1 - id: install-rust + uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: "stable" - override: true + targets: 'wasm32-unknown-unknown, wasm32-wasi' - name: Cache Build Products uses: actions/cache@v3 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index cfb5b6eda..8b2a765f6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -44,7 +44,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true @@ -74,12 +74,7 @@ jobs: go-version: 1.20.x - name: Install rust stable - uses: actions-rs/toolchain@v1 - id: install-rust - with: - profile: minimal - toolchain: "stable" - override: true + uses: dtolnay/rust-toolchain@stable - name: Cache Rust Build Products uses: actions/cache@v3 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 33049d439..dcc76465a 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: recursive From cca0c53c64616044b9e2e5e52bfa457cc0cfc75a Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Thu, 19 Oct 2023 15:00:12 -0700 Subject: [PATCH 306/775] Use latest docker and golangci actions Old versions of docker and golangci actions used deprecated github actions methods `The CODEQL_EXTRACTOR_GO_BUILD_TRACING environment variable has no effect on workflows with manual build steps, so we recommend that you remove it from your workflow.` --- .github/workflows/ci.yml | 2 +- .github/workflows/codeql-analysis.yml | 1 - .github/workflows/docker.yml | 6 +++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 022c26d2f..de2a580c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -108,7 +108,7 @@ jobs: run: make -j build-node-deps - name: Lint - uses: golangci/golangci-lint-action@v2 + uses: golangci/golangci-lint-action@v3 with: version: latest skip-go-installation: true diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8b2a765f6..8fb9d80c2 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -32,7 +32,6 @@ jobs: contents: read security-events: write env: - CODEQL_EXTRACTOR_GO_BUILD_TRACING: 'on' WABT_VERSION: 1.0.32 strategy: diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index dcc76465a..30ad88d91 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -28,7 +28,7 @@ jobs: submodules: recursive - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 with: driver-opts: network=host @@ -40,7 +40,7 @@ jobs: restore-keys: ${{ runner.os }}-buildx- - name: Build nitro-node docker - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v5 with: target: nitro-node push: true @@ -50,7 +50,7 @@ jobs: cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - name: Build nitro-node-dev docker - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v5 with: target: nitro-node-dev push: true From 1e1a378dc52a36cc26ad8ef6a528e7c1ef749890 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Thu, 19 Oct 2023 15:51:03 -0700 Subject: [PATCH 307/775] Don't use removed lint option `skip-go-installation` is no longer an option for `golangci/golangci-lint-action` --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de2a580c9..f2c4fac84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,7 +111,6 @@ jobs: uses: golangci/golangci-lint-action@v3 with: version: latest - skip-go-installation: true skip-pkg-cache: true - name: Custom Lint run: | From bf92b1bb542f78eff80147e22008a99f4779dd93 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 20 Oct 2023 15:32:10 +0200 Subject: [PATCH 308/775] Fix TestSendRawTransactionConditional tests Set the BatchPosterConfig.MaxDelay to negative only for the tests that need it for now. --- arbnode/batch_poster.go | 2 +- system_tests/conditionaltx_test.go | 2 +- system_tests/staker_test.go | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index f9990460c..4f50831e6 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -198,7 +198,7 @@ var TestBatchPosterConfig = BatchPosterConfig{ MaxSize: 100000, PollInterval: time.Millisecond * 10, ErrorDelay: time.Millisecond * 10, - MaxDelay: -time.Hour * 1000, + MaxDelay: 0, WaitForMaxDelay: false, CompressionLevel: 2, DASRetentionPeriod: time.Hour * 24 * 15, diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index 5848391b5..04d962e7f 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -242,7 +242,7 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { blockNumber := block.NumberU64() fixBlockTime := func(blockTime uint64) uint64 { since := time.Now().Unix() - int64(blockTime) - if int64(since) < 0 { + if since < 0 { // If using SimulatedBeacon then the block time will be ahead of // the actual time since it generates a new block for each tx in // on demand mode, and assigns them to sequentially increasing timestamps. diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 36b112d03..ff2e618da 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -65,7 +65,9 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) types.NewArbitrumSigner(types.NewLondonSigner(l2chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), transferGas, ) - _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, l2chainConfig, nil, l2info) + nodeConfig := arbnode.ConfigDefaultL1Test() + nodeConfig.BatchPoster.MaxDelay = -1000 * time.Hour + _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, l2chainConfig, nil, l2info) defer requireClose(t, l1stack) defer l2nodeA.StopAndWait() From 598c7f9eb69012afc1c02c1652afc76a1737f460 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 20 Oct 2023 16:34:50 +0200 Subject: [PATCH 309/775] Fix build of tests broken by merge of master --- system_tests/seqinbox_test.go | 5 +---- system_tests/staker_test.go | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index a456dc5fe..d7e888ed9 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -151,10 +151,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { l1BlockChain := l1backend.BlockChain() - rpcC, err := l1stack.Attach() - if err != nil { - t.Fatalf("Error connecting to l1 node: %v", err) - } + rpcC := l1stack.Attach() gethClient := gethclient.New(rpcC) seqInbox, err := bridgegen.NewSequencerInbox(l1Info.GetAddress("SequencerInbox"), l1Client) diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 98aef4adb..790aeea75 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -68,7 +68,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) ) nodeConfig := arbnode.ConfigDefaultL1Test() nodeConfig.BatchPoster.MaxDelay = -1000 * time.Hour - _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nodeCOnfig, l2chainConfig, nil, l2info) + _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nodeConfig, nil, l2chainConfig, nil, l2info) defer requireClose(t, l1stack) defer l2nodeA.StopAndWait() execNodeA := getExecNode(t, l2nodeA) @@ -76,9 +76,9 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) if faultyStaker { l2info.GenerateGenesisAccount("FaultyAddr", common.Big1) } - config := arbnode.ConfigDefaultL1Test() execConfig := gethexec.ConfigDefaultTest() execConfig.Sequencer.Enable = false + config := arbnode.ConfigDefaultL1Test() config.Sequencer = false config.DelayedSequencer.Enable = false config.BatchPoster.Enable = false From 0fe1550abf69c32c09869961c8812f0949965af4 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 20 Oct 2023 16:46:52 +0200 Subject: [PATCH 310/775] Remove testnode custom branch --- .gitmodules | 1 - nitro-testnode | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 977f7a477..7c78791c7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,4 +20,3 @@ [submodule "nitro-testnode"] path = nitro-testnode url = https://github.com/OffchainLabs/nitro-testnode.git - branch = fee-token-support diff --git a/nitro-testnode b/nitro-testnode index 0bd1ef2c6..11170fe36 160000 --- a/nitro-testnode +++ b/nitro-testnode @@ -1 +1 @@ -Subproject commit 0bd1ef2c6b33500f9144192edadd6491ec1e6bc7 +Subproject commit 11170fe36318991973bea632d9f348816a64a974 From c94302f8faf3060acc24af671787d28774d6b5e1 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 20 Oct 2023 16:49:29 +0200 Subject: [PATCH 311/775] Disallow Nitro accepting Blob transactions --- arbos/parse_l2.go | 4 ++-- execution/gethexec/sequencer.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arbos/parse_l2.go b/arbos/parse_l2.go index 88018fdfc..8f5c86f9c 100644 --- a/arbos/parse_l2.go +++ b/arbos/parse_l2.go @@ -166,8 +166,8 @@ func parseL2Message(rd io.Reader, poster common.Address, timestamp uint64, reque if err := newTx.UnmarshalBinary(readBytes); err != nil { return nil, err } - if newTx.Type() >= types.ArbitrumDepositTxType { - // Should be unreachable due to UnmarshalBinary not accepting Arbitrum internal txs + if newTx.Type() >= types.ArbitrumDepositTxType || newTx.Type() == types.BlobTxType { + // Should be unreachable for Arbitrum types due to UnmarshalBinary not accepting Arbitrum internal txs return nil, types.ErrTxTypeNotSupported } return types.Transactions{newTx}, nil diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 61792ed9b..52cf714d8 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -385,8 +385,8 @@ func (s *Sequencer) PublishTransaction(parentCtx context.Context, tx *types.Tran return errors.New("transaction sender is not on the whitelist") } } - if tx.Type() >= types.ArbitrumDepositTxType { - // Should be unreachable due to UnmarshalBinary not accepting Arbitrum internal txs + if tx.Type() >= types.ArbitrumDepositTxType || tx.Type() == types.BlobTxType { + // Should be unreachable for Arbitrum types due to UnmarshalBinary not accepting Arbitrum internal txs return types.ErrTxTypeNotSupported } From c45e1dbe21ca44418b3e6129e9edcece752b320b Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 20 Oct 2023 17:47:46 +0200 Subject: [PATCH 312/775] Fix lint G114 annotation --- cmd/genericconf/pprof.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/genericconf/pprof.go b/cmd/genericconf/pprof.go index e55bfddd3..9fd3a6f2a 100644 --- a/cmd/genericconf/pprof.go +++ b/cmd/genericconf/pprof.go @@ -17,8 +17,7 @@ func StartPprof(address string) { log.Info("Starting metrics server with pprof", "addr", fmt.Sprintf("http://%s/debug/metrics", address)) log.Info("Pprof endpoint", "addr", fmt.Sprintf("http://%s/debug/pprof", address)) go func() { - // #nosec G114 - if err := http.ListenAndServe(address, http.DefaultServeMux); err != nil { + if err := http.ListenAndServe(address, http.DefaultServeMux); /* #nosec G114 */ err != nil { log.Error("Failure in running pprof server", "err", err) } }() From 878ec4ae5df30be16422d20ce30c937c4a03488c Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 20 Oct 2023 11:26:38 -0500 Subject: [PATCH 313/775] address PR comments, refactor code to use two router design --- broadcastclients/broadcastclients.go | 106 +++++++++++++++++++-------- 1 file changed, 76 insertions(+), 30 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index 48f644b7f..f50840479 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -21,6 +21,7 @@ const ROUTER_QUEUE_SIZE = 1024 const RECENT_FEED_INITIAL_MAP_SIZE = 1024 const RECENT_FEED_ITEM_TTL = time.Second * 10 const MAX_FEED_INACTIVE_TIME = time.Second * 5 +const PRIMARY_FEED_UPTIME = time.Minute * 10 type Router struct { stopwaiter.StopWaiter @@ -43,7 +44,8 @@ type BroadcastClients struct { secondaryClients []*broadcastclient.BroadcastClient numOfStartedSecondary int - router *Router + primaryRouter *Router + secondaryRouter *Router // Use atomic access connected int32 @@ -62,17 +64,20 @@ func NewBroadcastClients( if len(config.URL) == 0 && len(config.SecondaryURL) == 0 { return nil, nil } - - clients := BroadcastClients{ - router: &Router{ + newStandardRouter := func() *Router { + return &Router{ messageChan: make(chan broadcaster.BroadcastFeedMessage, ROUTER_QUEUE_SIZE), confirmedSequenceNumberChan: make(chan arbutil.MessageIndex, ROUTER_QUEUE_SIZE), forwardTxStreamer: txStreamer, forwardConfirmationChan: confirmedSequenceNumberListener, - }, + } + } + clients := BroadcastClients{ + primaryRouter: newStandardRouter(), + secondaryRouter: newStandardRouter(), } var lastClientErr error - makeFeeds := func(url []string) []*broadcastclient.BroadcastClient { + makeFeeds := func(url []string, router *Router) []*broadcastclient.BroadcastClient { feeds := make([]*broadcastclient.BroadcastClient, 0, len(url)) for _, address := range url { client, err := broadcastclient.NewBroadcastClient( @@ -80,8 +85,8 @@ func NewBroadcastClients( address, l2ChainId, currentMessageCount, - clients.router, - clients.router.confirmedSequenceNumberChan, + router, + router.confirmedSequenceNumberChan, fatalErrChan, addrVerifier, func(delta int32) { clients.adjustCount(delta) }, @@ -96,8 +101,8 @@ func NewBroadcastClients( return feeds } - clients.primaryClients = makeFeeds(config.URL) - clients.secondaryClients = makeFeeds(config.SecondaryURL) + clients.primaryClients = makeFeeds(config.URL, clients.primaryRouter) + clients.secondaryClients = makeFeeds(config.SecondaryURL, clients.secondaryRouter) if len(clients.primaryClients) == 0 && len(clients.secondaryClients) == 0 { log.Error("no connected feed on startup, last error: %w", lastClientErr) @@ -121,7 +126,8 @@ func (bcs *BroadcastClients) adjustCount(delta int32) { } func (bcs *BroadcastClients) Start(ctx context.Context) { - bcs.router.StopWaiter.Start(ctx, bcs.router) + bcs.primaryRouter.StopWaiter.Start(ctx, bcs.primaryRouter) + bcs.secondaryRouter.StopWaiter.Start(ctx, bcs.secondaryRouter) for _, client := range bcs.primaryClients { client.Start(ctx) @@ -130,17 +136,24 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { var lastConfirmed arbutil.MessageIndex recentFeedItemsNew := make(map[arbutil.MessageIndex]time.Time, RECENT_FEED_INITIAL_MAP_SIZE) recentFeedItemsOld := make(map[arbutil.MessageIndex]time.Time, RECENT_FEED_INITIAL_MAP_SIZE) - bcs.router.LaunchThread(func(ctx context.Context) { + bcs.primaryRouter.LaunchThread(func(ctx context.Context) { recentFeedItemsCleanup := time.NewTicker(RECENT_FEED_ITEM_TTL) - startNewFeedTimer := time.NewTicker(MAX_FEED_INACTIVE_TIME) + startSecondaryFeedTimer := time.NewTicker(MAX_FEED_INACTIVE_TIME) + stopSecondaryFeedTimer := time.NewTicker(PRIMARY_FEED_UPTIME) + primaryFeedIsDownTimer := time.NewTicker(MAX_FEED_INACTIVE_TIME) defer recentFeedItemsCleanup.Stop() - defer startNewFeedTimer.Stop() + defer startSecondaryFeedTimer.Stop() + defer stopSecondaryFeedTimer.Stop() + defer primaryFeedIsDownTimer.Stop() for { select { case <-ctx.Done(): return - case msg := <-bcs.router.messageChan: - startNewFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + + // Primary feeds + case msg := <-bcs.primaryRouter.messageChan: + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) if _, ok := recentFeedItemsNew[msg.SequenceNumber]; ok { continue } @@ -148,29 +161,55 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { continue } recentFeedItemsNew[msg.SequenceNumber] = time.Now() - // need to stop the timer because forwardTxStreamer might be blocked when traffic is high - // and that shouldn't create race condition between channels timer.C and messageChan - startNewFeedTimer.Stop() - if err := bcs.router.forwardTxStreamer.AddBroadcastMessages([]*broadcaster.BroadcastFeedMessage{&msg}); err != nil { - log.Error("Error routing message from Sequencer Feed", "err", err) + if err := bcs.primaryRouter.forwardTxStreamer.AddBroadcastMessages([]*broadcaster.BroadcastFeedMessage{&msg}); err != nil { + log.Error("Error routing message from Primary Sequencer Feeds", "err", err) } - startNewFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) - case cs := <-bcs.router.confirmedSequenceNumberChan: - startNewFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + case cs := <-bcs.primaryRouter.confirmedSequenceNumberChan: + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) if cs == lastConfirmed { continue } lastConfirmed = cs - startNewFeedTimer.Stop() - bcs.router.forwardConfirmationChan <- cs - startNewFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + bcs.primaryRouter.forwardConfirmationChan <- cs + + // Secondary Feeds + case msg := <-bcs.secondaryRouter.messageChan: + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + if _, ok := recentFeedItemsNew[msg.SequenceNumber]; ok { + continue + } + if _, ok := recentFeedItemsOld[msg.SequenceNumber]; ok { + continue + } + recentFeedItemsNew[msg.SequenceNumber] = time.Now() + if err := bcs.secondaryRouter.forwardTxStreamer.AddBroadcastMessages([]*broadcaster.BroadcastFeedMessage{&msg}); err != nil { + log.Error("Error routing message from Secondary Sequencer Feeds", "err", err) + } + case cs := <-bcs.secondaryRouter.confirmedSequenceNumberChan: + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + if cs == lastConfirmed { + continue + } + lastConfirmed = cs + bcs.secondaryRouter.forwardConfirmationChan <- cs + + // Cycle buckets to get rid of old entries case <-recentFeedItemsCleanup.C: - // Cycle buckets to get rid of old entries recentFeedItemsOld = recentFeedItemsNew recentFeedItemsNew = make(map[arbutil.MessageIndex]time.Time, RECENT_FEED_INITIAL_MAP_SIZE) - case <-startNewFeedTimer.C: - // failed to get messages from primary feed for ~5 seconds, start a new feed + + // failed to get messages from both primary and secondary feeds for ~5 seconds, start a new secondary feed + case <-startSecondaryFeedTimer.C: bcs.StartSecondaryFeed(ctx) + + // failed to get messages from primary feed for ~5 seconds, reset the timer responsible for stopping a secondary + case <-primaryFeedIsDownTimer.C: + stopSecondaryFeedTimer.Reset(PRIMARY_FEED_UPTIME) + + // primary feeds have been up and running for PRIMARY_FEED_UPTIME=10 mins without a failure, stop the recently started secondary feed + case <-stopSecondaryFeedTimer.C: + bcs.StopSecondaryFeed(ctx) } } }) @@ -185,6 +224,13 @@ func (bcs *BroadcastClients) StartSecondaryFeed(ctx context.Context) { log.Warn("failed to start a new secondary feed all available secondary feeds were started") } } +func (bcs *BroadcastClients) StopSecondaryFeed(ctx context.Context) { + if bcs.numOfStartedSecondary > 0 { + bcs.numOfStartedSecondary -= 1 + client := bcs.secondaryClients[bcs.numOfStartedSecondary] + client.StopAndWait() + } +} func (bcs *BroadcastClients) StopAndWait() { for _, client := range bcs.primaryClients { From 058db5408a5cfda478332d5b8eb4061cb1279a8b Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 23 Oct 2023 13:23:31 +0200 Subject: [PATCH 314/775] Suppress golangci-lint error --- cmd/genericconf/pprof.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/genericconf/pprof.go b/cmd/genericconf/pprof.go index e55bfddd3..9fd3a6f2a 100644 --- a/cmd/genericconf/pprof.go +++ b/cmd/genericconf/pprof.go @@ -17,8 +17,7 @@ func StartPprof(address string) { log.Info("Starting metrics server with pprof", "addr", fmt.Sprintf("http://%s/debug/metrics", address)) log.Info("Pprof endpoint", "addr", fmt.Sprintf("http://%s/debug/pprof", address)) go func() { - // #nosec G114 - if err := http.ListenAndServe(address, http.DefaultServeMux); err != nil { + if err := http.ListenAndServe(address, http.DefaultServeMux); /* #nosec G114 */ err != nil { log.Error("Failure in running pprof server", "err", err) } }() From 2ec0a4412828c6adcc9345a139d3ba9e558648df Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 23 Oct 2023 22:23:54 -0500 Subject: [PATCH 315/775] Refactor System Tests --- system_tests/arbtrace_test.go | 33 +++--- system_tests/common_test.go | 5 + system_tests/conditionaltx_test.go | 143 ++++++++++++------------- system_tests/debugapi_test.go | 19 ++-- system_tests/fees_test.go | 80 +++++++------- system_tests/forwarder_test.go | 141 ++++++++++-------------- system_tests/ipc_test.go | 14 +-- system_tests/meaningless_reorg_test.go | 40 ++++--- system_tests/seq_coordinator_test.go | 68 ++++++------ system_tests/seqfeed_test.go | 114 +++++++++++--------- system_tests/seqinbox_test.go | 81 +++++++------- system_tests/staker_test.go | 80 +++++++------- 12 files changed, 398 insertions(+), 420 deletions(-) diff --git a/system_tests/arbtrace_test.go b/system_tests/arbtrace_test.go index a4995e397..36e4cc940 100644 --- a/system_tests/arbtrace_test.go +++ b/system_tests/arbtrace_test.go @@ -10,8 +10,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" - "github.com/offchainlabs/nitro/execution/gethexec" - "github.com/offchainlabs/nitro/util/testhelpers" ) type callTxArgs struct { @@ -140,18 +138,17 @@ func TestArbTraceForwarding(t *testing.T) { Public: false, }) listener, srv, err := rpc.StartIPCEndpoint(ipcPath, apis) - testhelpers.RequireImpl(t, err) + Require(t, err) defer srv.Stop() defer listener.Close() - execConfig := gethexec.ConfigDefaultTest() - execConfig.RPC.ClassicRedirect = ipcPath - execConfig.RPC.ClassicRedirectTimeout = time.Second - _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, execConfig, nil, nil, nil) - defer requireClose(t, l1stack) - defer requireClose(t, l2stack) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.execConfig.RPC.ClassicRedirect = ipcPath + builder.execConfig.RPC.ClassicRedirectTimeout = time.Second + cleanup := builder.Build(t) + defer cleanup() - l2rpc, _ := l2stack.Attach() + l2rpc, _ := builder.L2.Stack.Attach() txArgs := callTxArgs{} traceTypes := []string{"trace"} blockNum := rpc.BlockNumberOrHash{} @@ -162,22 +159,22 @@ func TestArbTraceForwarding(t *testing.T) { filter := filterRequest{} var result traceResult err = l2rpc.CallContext(ctx, &result, "arbtrace_call", txArgs, traceTypes, blockNum) - testhelpers.RequireImpl(t, err) + Require(t, err) var results []*traceResult err = l2rpc.CallContext(ctx, &results, "arbtrace_callMany", traceRequests, blockNum) - testhelpers.RequireImpl(t, err) + Require(t, err) err = l2rpc.CallContext(ctx, &results, "arbtrace_replayBlockTransactions", blockNum, traceTypes) - testhelpers.RequireImpl(t, err) + Require(t, err) err = l2rpc.CallContext(ctx, &result, "arbtrace_replayTransaction", txHash, traceTypes) - testhelpers.RequireImpl(t, err) + Require(t, err) var frames []traceFrame err = l2rpc.CallContext(ctx, &frames, "arbtrace_transaction", txHash) - testhelpers.RequireImpl(t, err) + Require(t, err) var frame traceFrame err = l2rpc.CallContext(ctx, &frame, "arbtrace_get", txHash, path) - testhelpers.RequireImpl(t, err) + Require(t, err) err = l2rpc.CallContext(ctx, &frames, "arbtrace_block", blockNum) - testhelpers.RequireImpl(t, err) + Require(t, err) err = l2rpc.CallContext(ctx, &frames, "arbtrace_filter", filter) - testhelpers.RequireImpl(t, err) + Require(t, err) } diff --git a/system_tests/common_test.go b/system_tests/common_test.go index d233631d4..41a3fd141 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -115,6 +115,10 @@ func (tc *TestClient) DeploySimple(t *testing.T, auth bind.TransactOpts) (common return deploySimple(t, tc.ctx, auth, tc.Client) } +func (tc *TestClient) EnsureTxSucceeded(transaction *types.Transaction) (*types.Receipt, error) { + return EnsureTxSucceeded(tc.ctx, tc.Client, transaction) +} + type NodeBuilder struct { // NodeBuilder configuration ctx context.Context @@ -212,6 +216,7 @@ func (b *NodeBuilder) Build2ndNode(t *testing.T, params *SecondNodeParams) (*Tes l2 := NewTestClient(b.ctx) l2.Client, l2.ConsensusNode = Create2ndNodeWithConfig(t, b.ctx, b.L2.ConsensusNode, b.L1.Stack, b.L1Info, params.initData, params.nodeConfig, params.execConfig, params.stackConfig) + l2.ExecNode = getExecNode(t, l2.ConsensusNode) l2.cleanup = func() { l2.ConsensusNode.StopAndWait() } return l2, func() { l2.cleanup() } } diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index 211908a88..d75dd2725 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -202,43 +202,42 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, l2client, _, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - execNode := getExecNode(t, node) - auth := l2info.GetDefaultTransactOpts("Owner", ctx) - contractAddress1, simple1 := deploySimple(t, ctx, auth, l2client) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + contractAddress1, simple1 := builder.L2.DeploySimple(t, auth) tx, err := simple1.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - contractAddress2, simple2 := deploySimple(t, ctx, auth, l2client) + contractAddress2, simple2 := builder.L2.DeploySimple(t, auth) tx, err = simple2.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) tx, err = simple2.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - currentRootHash1 := getStorageRootHash(t, execNode, contractAddress1) - currentSlotValueMap1 := getStorageSlotValue(t, execNode, contractAddress1) - currentRootHash2 := getStorageRootHash(t, execNode, contractAddress2) - currentSlotValueMap2 := getStorageSlotValue(t, execNode, contractAddress2) + currentRootHash1 := getStorageRootHash(t, builder.L2.ExecNode, contractAddress1) + currentSlotValueMap1 := getStorageSlotValue(t, builder.L2.ExecNode, contractAddress1) + currentRootHash2 := getStorageRootHash(t, builder.L2.ExecNode, contractAddress2) + currentSlotValueMap2 := getStorageSlotValue(t, builder.L2.ExecNode, contractAddress2) - rpcClient, err := node.Stack.Attach() + rpcClient, err := builder.L2.ConsensusNode.Stack.Attach() Require(t, err) - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - testConditionalTxThatShouldSucceed(t, ctx, -1, l2info, rpcClient, nil) + testConditionalTxThatShouldSucceed(t, ctx, -1, builder.L2Info, rpcClient, nil) for i, options := range getEmptyOptions(contractAddress1) { - testConditionalTxThatShouldSucceed(t, ctx, i, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, i, builder.L2Info, rpcClient, options) } - block, err := l1client.BlockByNumber(ctx, nil) + block, err := builder.L1.Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber := block.NumberU64() blockTime := block.Time() @@ -249,33 +248,33 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { options1 := dedupOptions(t, append(append(optionsAB, optionsA...), optionsB...)) options1 = optionsDedupProduct(t, options1, getFulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options1 { - testConditionalTxThatShouldSucceed(t, ctx, i, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, i, builder.L2Info, rpcClient, options) } tx, err = simple1.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) tx, err = simple2.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) previousStorageRootHash1 := currentRootHash1 - currentRootHash1 = getStorageRootHash(t, execNode, contractAddress1) + currentRootHash1 = getStorageRootHash(t, builder.L2.ExecNode, contractAddress1) if bytes.Equal(previousStorageRootHash1.Bytes(), currentRootHash1.Bytes()) { Fatal(t, "storage root hash didn't change as expected") } - currentSlotValueMap1 = getStorageSlotValue(t, execNode, contractAddress1) + currentSlotValueMap1 = getStorageSlotValue(t, builder.L2.ExecNode, contractAddress1) previousStorageRootHash2 := currentRootHash2 - currentRootHash2 = getStorageRootHash(t, execNode, contractAddress2) + currentRootHash2 = getStorageRootHash(t, builder.L2.ExecNode, contractAddress2) if bytes.Equal(previousStorageRootHash2.Bytes(), currentRootHash2.Bytes()) { Fatal(t, "storage root hash didn't change as expected") } - currentSlotValueMap2 = getStorageSlotValue(t, execNode, contractAddress2) + currentSlotValueMap2 = getStorageSlotValue(t, builder.L2.ExecNode, contractAddress2) - block, err = l1client.BlockByNumber(ctx, nil) + block, err = builder.L1.Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() blockTime = block.Time() @@ -286,35 +285,38 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { options2 := dedupOptions(t, append(append(optionsCD, optionsC...), optionsD...)) options2 = optionsDedupProduct(t, options2, getFulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options2 { - testConditionalTxThatShouldSucceed(t, ctx, i, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, i, builder.L2Info, rpcClient, options) } for i, options := range options1 { - testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, i, builder.L2Info, rpcClient, options, -32003) } - block, err = l1client.BlockByNumber(ctx, nil) + block, err = builder.L1.Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() blockTime = block.Time() options3 := optionsDedupProduct(t, options2, getUnfulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options3 { - testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, i, builder.L2Info, rpcClient, options, -32003) } options4 := optionsDedupProduct(t, options2, options1) for i, options := range options4 { - testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, i, builder.L2Info, rpcClient, options, -32003) } } func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() - rpcClient, err := node.Stack.Attach() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() + + rpcClient, err := builder.L2.ConsensusNode.Stack.Attach() Require(t, err) - auth := l2info.GetDefaultTransactOpts("Owner", ctx) - contractAddress, simple := deploySimple(t, ctx, auth, client) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + contractAddress, simple := builder.L2.DeploySimple(t, auth) simpleContract, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) Require(t, err) @@ -325,11 +327,11 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { var options []*arbitrum_types.ConditionalOptions for i := 0; i < numTxes; i++ { account := fmt.Sprintf("User%v", i) - l2info.GenerateAccount(account) - tx := l2info.PrepareTx("Owner", account, l2info.TransferGas, big.NewInt(1e16), nil) - err := client.SendTransaction(ctx, tx) + builder.L2Info.GenerateAccount(account) + tx := builder.L2Info.PrepareTx("Owner", account, builder.L2Info.TransferGas, big.NewInt(1e16), nil) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) } for i := numTxes - 1; i >= 0; i-- { @@ -337,7 +339,7 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { data, err := simpleContract.Pack("logAndIncrement", big.NewInt(int64(expected))) Require(t, err) account := fmt.Sprintf("User%v", i) - txes = append(txes, l2info.PrepareTxTo(account, &contractAddress, l2info.TransferGas, big.NewInt(0), data)) + txes = append(txes, builder.L2Info.PrepareTxTo(account, &contractAddress, builder.L2Info.TransferGas, big.NewInt(0), data)) options = append(options, &arbitrum_types.ConditionalOptions{KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{contractAddress: {SlotValue: map[common.Hash]common.Hash{{0}: common.BigToHash(big.NewInt(int64(expected)))}}}}) } ctxWithTimeout, cancelCtxWithTimeout := context.WithTimeout(ctx, 5*time.Second) @@ -367,8 +369,7 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { } cancelCtxWithTimeout() wg.Wait() - execNode := getExecNode(t, node) - bc := execNode.Backend.ArbInterface().BlockChain() + bc := builder.L2.ExecNode.Backend.ArbInterface().BlockChain() genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum var receipts types.Receipts @@ -404,41 +405,39 @@ func TestSendRawTransactionConditionalPreCheck(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - execConfig := gethexec.ConfigDefaultTest() - execConfig.Sequencer.MaxBlockSpeed = 0 - execConfig.TxPreChecker.Strictness = gethexec.TxPreCheckerStrictnessLikelyCompatible - execConfig.TxPreChecker.RequiredStateAge = 1 - execConfig.TxPreChecker.RequiredStateMaxBlocks = 2 + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.execConfig.Sequencer.MaxBlockSpeed = 0 + builder.execConfig.TxPreChecker.Strictness = gethexec.TxPreCheckerStrictnessLikelyCompatible + builder.execConfig.TxPreChecker.RequiredStateAge = 1 + builder.execConfig.TxPreChecker.RequiredStateMaxBlocks = 2 + cleanup := builder.Build(t) + defer cleanup() - l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, execConfig, nil, nil) - defer requireClose(t, l1stack) - defer node.StopAndWait() - rpcClient, err := node.Stack.Attach() + rpcClient, err := builder.L2.ConsensusNode.Stack.Attach() Require(t, err) - execNode := getExecNode(t, node) - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) start := time.Now().Unix() - contractAddress, simple := deploySimple(t, ctx, auth, l2client) + contractAddress, simple := builder.L2.DeploySimple(t, auth) if time.Since(time.Unix(start, 0)) > 200*time.Millisecond { start++ time.Sleep(time.Until(time.Unix(start, 0))) } tx, err := simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - currentRootHash := getStorageRootHash(t, execNode, contractAddress) + currentRootHash := getStorageRootHash(t, builder.L2.ExecNode, contractAddress) options := &arbitrum_types.ConditionalOptions{ KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{ contractAddress: {RootHash: ¤tRootHash}, }, } - testConditionalTxThatShouldFail(t, ctx, 0, l2info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, 0, builder.L2Info, rpcClient, options, -32003) time.Sleep(time.Until(time.Unix(start+1, 0))) - testConditionalTxThatShouldSucceed(t, ctx, 1, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, 1, builder.L2Info, rpcClient, options) start = time.Now().Unix() if time.Since(time.Unix(start, 0)) > 200*time.Millisecond { @@ -447,23 +446,23 @@ func TestSendRawTransactionConditionalPreCheck(t *testing.T) { } tx, err = simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - currentRootHash = getStorageRootHash(t, execNode, contractAddress) + currentRootHash = getStorageRootHash(t, builder.L2.ExecNode, contractAddress) options = &arbitrum_types.ConditionalOptions{ KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{ contractAddress: {RootHash: ¤tRootHash}, }, } - testConditionalTxThatShouldFail(t, ctx, 2, l2info, rpcClient, options, -32003) - tx = l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) - Require(t, l2client.SendTransaction(ctx, tx)) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + testConditionalTxThatShouldFail(t, ctx, 2, builder.L2Info, rpcClient, options, -32003) + tx = builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) + Require(t, builder.L2.Client.SendTransaction(ctx, tx)) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - testConditionalTxThatShouldFail(t, ctx, 3, l2info, rpcClient, options, -32003) - tx = l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) - Require(t, l2client.SendTransaction(ctx, tx)) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + testConditionalTxThatShouldFail(t, ctx, 3, builder.L2Info, rpcClient, options, -32003) + tx = builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) + Require(t, builder.L2.Client.SendTransaction(ctx, tx)) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - testConditionalTxThatShouldSucceed(t, ctx, 4, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, 4, builder.L2Info, rpcClient, options) } diff --git a/system_tests/debugapi_test.go b/system_tests/debugapi_test.go index ff28e2350..b8fbffcfe 100644 --- a/system_tests/debugapi_test.go +++ b/system_tests/debugapi_test.go @@ -8,32 +8,31 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/rpc" - "github.com/offchainlabs/nitro/util/testhelpers" ) func TestDebugAPI(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, nil, nil, nil) - defer requireClose(t, l1stack) - defer requireClose(t, l2stack) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - l2rpc, _ := l2stack.Attach() + l2rpc, _ := builder.L2.Stack.Attach() var dump state.Dump err := l2rpc.CallContext(ctx, &dump, "debug_dumpBlock", rpc.LatestBlockNumber) - testhelpers.RequireImpl(t, err) + Require(t, err) err = l2rpc.CallContext(ctx, &dump, "debug_dumpBlock", rpc.PendingBlockNumber) - testhelpers.RequireImpl(t, err) + Require(t, err) var badBlocks []eth.BadBlockArgs err = l2rpc.CallContext(ctx, &badBlocks, "debug_getBadBlocks") - testhelpers.RequireImpl(t, err) + Require(t, err) var dumpIt state.IteratorDump err = l2rpc.CallContext(ctx, &dumpIt, "debug_accountRange", rpc.LatestBlockNumber, hexutil.Bytes{}, 10, true, true, false) - testhelpers.RequireImpl(t, err) + Require(t, err) err = l2rpc.CallContext(ctx, &dumpIt, "debug_accountRange", rpc.PendingBlockNumber, hexutil.Bytes{}, 10, true, true, false) - testhelpers.RequireImpl(t, err) + Require(t, err) } diff --git a/system_tests/fees_test.go b/system_tests/fees_test.go index 750293622..17ab7b69c 100644 --- a/system_tests/fees_test.go +++ b/system_tests/fees_test.go @@ -20,7 +20,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbcompress" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/l1pricing" "github.com/ethereum/go-ethereum/common" @@ -33,20 +32,20 @@ func TestSequencerFeePaid(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, l2client, _, _, _, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() - execNode := getExecNode(t, l2node) - version := execNode.ArbInterface.BlockChain().Config().ArbitrumChainParams.InitialArbOSVersion - callOpts := l2info.GetDefaultCallOpts("Owner", ctx) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() + + version := builder.L2.ExecNode.ArbInterface.BlockChain().Config().ArbitrumChainParams.InitialArbOSVersion + callOpts := builder.L2Info.GetDefaultCallOpts("Owner", ctx) // get the network fee account - arbOwnerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("0x6b"), l2client) + arbOwnerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("0x6b"), builder.L2.Client) Require(t, err, "failed to deploy contract") - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), builder.L2.Client) Require(t, err, "failed to deploy contract") - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), builder.L2.Client) Require(t, err, "failed to deploy contract") networkFeeAccount, err := arbOwnerPublic.GetNetworkFeeAccount(callOpts) Require(t, err, "could not get the network fee account") @@ -54,24 +53,24 @@ func TestSequencerFeePaid(t *testing.T) { l1Estimate, err := arbGasInfo.GetL1BaseFeeEstimate(callOpts) Require(t, err) - baseFee := GetBaseFee(t, l2client, ctx) - l2info.GasPrice = baseFee + baseFee := GetBaseFee(t, builder.L2.Client, ctx) + builder.L2Info.GasPrice = baseFee testFees := func(tip uint64) (*big.Int, *big.Int) { tipCap := arbmath.BigMulByUint(baseFee, tip) - txOpts := l2info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) txOpts.GasTipCap = tipCap gasPrice := arbmath.BigAdd(baseFee, tipCap) - networkBefore := GetBalance(t, ctx, l2client, networkFeeAccount) + networkBefore := builder.L2.GetBalance(t, networkFeeAccount) tx, err := arbDebug.Events(&txOpts, true, [32]byte{}) Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, l2client, tx) + receipt, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) - networkAfter := GetBalance(t, ctx, l2client, networkFeeAccount) - l1Charge := arbmath.BigMulByUint(l2info.GasPrice, receipt.GasUsedForL1) + networkAfter := builder.L2.GetBalance(t, networkFeeAccount) + l1Charge := arbmath.BigMulByUint(builder.L2Info.GasPrice, receipt.GasUsedForL1) // the network should receive // 1. compute costs @@ -93,7 +92,7 @@ func TestSequencerFeePaid(t *testing.T) { l1GasBought := arbmath.BigDiv(l1Charge, l1Estimate).Uint64() l1ChargeExpected := arbmath.BigMulByUint(l1Estimate, txSize*params.TxDataNonZeroGasEIP2028) // L1 gas can only be charged in terms of L2 gas, so subtract off any rounding error from the expected value - l1ChargeExpected.Sub(l1ChargeExpected, new(big.Int).Mod(l1ChargeExpected, l2info.GasPrice)) + l1ChargeExpected.Sub(l1ChargeExpected, new(big.Int).Mod(l1ChargeExpected, builder.L2Info.GasPrice)) colors.PrintBlue("bytes ", l1GasBought/params.TxDataNonZeroGasEIP2028, txSize) @@ -132,42 +131,39 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - chainConfig := params.ArbitrumDevTestChainConfig() - conf := arbnode.ConfigDefaultL1Test() - conf.DelayedSequencer.FinalizeDistance = 1 - - l2info, node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, chainConfig, nil) - defer requireClose(t, l1stack) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig.DelayedSequencer.FinalizeDistance = 1 + cleanup := builder.Build(t) + defer cleanup() - ownerAuth := l2info.GetDefaultTransactOpts("Owner", ctx) + ownerAuth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) // make ownerAuth a chain owner - arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) + arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), builder.L2.Client) Require(t, err) tx, err := arbdebug.BecomeChainOwner(&ownerAuth) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) // use ownerAuth to set the L1 price per unit Require(t, err) - arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), l2client) + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), builder.L2.Client) Require(t, err) tx, err = arbOwner.SetL1PricePerUnit(&ownerAuth, arbmath.UintToBig(initialEstimate)) Require(t, err) - _, err = WaitForTx(ctx, l2client, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, builder.L2.Client, tx.Hash(), time.Second*5) Require(t, err) - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), builder.L2.Client) Require(t, err) lastEstimate, err := arbGasInfo.GetL1BaseFeeEstimate(&bind.CallOpts{Context: ctx}) Require(t, err) - lastBatchCount, err := node.InboxTracker.GetBatchCount() + lastBatchCount, err := builder.L2.ConsensusNode.InboxTracker.GetBatchCount() Require(t, err) - l1Header, err := l1client.HeaderByNumber(ctx, nil) + l1Header, err := builder.L1.Client.HeaderByNumber(ctx, nil) Require(t, err) - rewardRecipientBalanceBefore := GetBalance(t, ctx, l2client, l1pricing.BatchPosterAddress) + rewardRecipientBalanceBefore := builder.L2.GetBalance(t, l1pricing.BatchPosterAddress) timesPriceAdjusted := 0 colors.PrintBlue("Initial values") @@ -176,17 +172,17 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { numRetrogradeMoves := 0 for i := 0; i < 256; i++ { - tx, receipt := TransferBalance(t, "Owner", "Owner", common.Big1, l2info, l2client, ctx) - header, err := l2client.HeaderByHash(ctx, receipt.BlockHash) + tx, receipt := builder.L2.TransferBalance(t, "Owner", "Owner", common.Big1, builder.L2Info) + header, err := builder.L2.Client.HeaderByHash(ctx, receipt.BlockHash) Require(t, err) - TransferBalance(t, "Faucet", "Faucet", common.Big1, l1info, l1client, ctx) // generate l1 traffic + builder.L1.TransferBalance(t, "Faucet", "Faucet", common.Big1, builder.L1Info) // generate l1 traffic units := compressedTxSize(t, tx) * params.TxDataNonZeroGasEIP2028 estimatedL1FeePerUnit := arbmath.BigDivByUint(arbmath.BigMulByUint(header.BaseFee, receipt.GasUsedForL1), units) if !arbmath.BigEquals(lastEstimate, estimatedL1FeePerUnit) { - l1Header, err = l1client.HeaderByNumber(ctx, nil) + l1Header, err = builder.L1.Client.HeaderByNumber(ctx, nil) Require(t, err) callOpts := &bind.CallOpts{Context: ctx, BlockNumber: receipt.BlockNumber} @@ -235,7 +231,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { // see that the inbox advances for j := 16; j > 0; j-- { - newBatchCount, err := node.InboxTracker.GetBatchCount() + newBatchCount, err := builder.L2.ConsensusNode.InboxTracker.GetBatchCount() Require(t, err) if newBatchCount > lastBatchCount { colors.PrintGrey("posted new batch ", newBatchCount) @@ -250,7 +246,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { } } - rewardRecipientBalanceAfter := GetBalance(t, ctx, l2client, chainConfig.ArbitrumChainParams.InitialChainOwner) + rewardRecipientBalanceAfter := builder.L2.GetBalance(t, builder.chainConfig.ArbitrumChainParams.InitialChainOwner) colors.PrintMint("reward recipient balance ", rewardRecipientBalanceBefore, " ➤ ", rewardRecipientBalanceAfter) colors.PrintMint("price changes ", timesPriceAdjusted) @@ -261,7 +257,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { Fatal(t, "reward recipient didn't get paid") } - arbAggregator, err := precompilesgen.NewArbAggregator(common.HexToAddress("0x6d"), l2client) + arbAggregator, err := precompilesgen.NewArbAggregator(common.HexToAddress("0x6d"), builder.L2.Client) Require(t, err) batchPosterAddresses, err := arbAggregator.GetBatchPosters(&bind.CallOpts{Context: ctx}) Require(t, err) @@ -269,7 +265,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { for _, bpAddr := range batchPosterAddresses { if bpAddr != l1pricing.BatchPosterAddress && bpAddr != l1pricing.L1PricerFundsPoolAddress { numReimbursed++ - bal, err := l1client.BalanceAt(ctx, bpAddr, nil) + bal, err := builder.L1.Client.BalanceAt(ctx, bpAddr, nil) Require(t, err) if bal.Sign() == 0 { Fatal(t, "Batch poster balance is zero for", bpAddr) diff --git a/system_tests/forwarder_test.go b/system_tests/forwarder_test.go index fc7eb4cc2..d29e82c12 100644 --- a/system_tests/forwarder_test.go +++ b/system_tests/forwarder_test.go @@ -15,13 +15,9 @@ import ( "time" "github.com/alicebob/miniredis/v2" - "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/node" "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/execution/gethexec" - "github.com/offchainlabs/nitro/statetransfer" "github.com/offchainlabs/nitro/util/redisutil" ) @@ -33,16 +29,14 @@ func TestStaticForwarder(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ipcPath := tmpPath(t, "test.ipc") - ipcConfig := genericconf.IPCConfigDefault - ipcConfig.Path = ipcPath - stackConfig := createStackConfigForTest(t.TempDir()) - ipcConfig.Apply(stackConfig) - nodeConfigA := arbnode.ConfigDefaultL1Test() - nodeConfigA.BatchPoster.Enable = false - l2info, nodeA, clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfigA, nil, nil, stackConfig) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig.BatchPoster.Enable = false + builder.l2StackConfig.IPCPath = ipcPath + cleanupA := builder.Build(t) + defer cleanupA() + + clientA := builder.L2.Client nodeConfigB := arbnode.ConfigDefaultL1Test() execConfigB := gethexec.ConfigDefaultTest() @@ -53,18 +47,22 @@ func TestStaticForwarder(t *testing.T) { execConfigB.ForwardingTarget = ipcPath nodeConfigB.BatchPoster.Enable = false - clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, nodeConfigB, execConfigB, nil) - defer nodeB.StopAndWait() + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{ + nodeConfig: nodeConfigB, + execConfig: execConfigB, + }) + defer cleanupB() + clientB := testClientB.Client - l2info.GenerateAccount("User2") - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, transferAmount, nil) + builder.L2Info.GenerateAccount("User2") + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, transferAmount, nil) err := clientB.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, clientA, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - l2balance, err := clientA.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := clientA.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(transferAmount) != 0 { @@ -95,36 +93,18 @@ type fallbackSequencerOpts struct { enableSecCoordinator bool } -func fallbackSequencer( - ctx context.Context, t *testing.T, opts *fallbackSequencerOpts, -) (l2info info, currentNode *arbnode.Node, l2client *ethclient.Client, - l1info info, l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node) { - stackConfig := createStackConfigForTest(t.TempDir()) - ipcConfig := genericconf.IPCConfigDefault - ipcConfig.Path = opts.ipcPath - ipcConfig.Apply(stackConfig) - nodeConfig := arbnode.ConfigDefaultL1Test() - nodeConfig.SeqCoordinator.Enable = opts.enableSecCoordinator - nodeConfig.SeqCoordinator.RedisUrl = opts.redisUrl - nodeConfig.SeqCoordinator.MyUrl = opts.ipcPath - return createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, nil, stackConfig) +func fallbackSequencer(ctx context.Context, t *testing.T, opts *fallbackSequencerOpts) *NodeBuilder { + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.l2StackConfig.IPCPath = opts.ipcPath + builder.nodeConfig.SeqCoordinator.Enable = opts.enableSecCoordinator + builder.nodeConfig.SeqCoordinator.RedisUrl = opts.redisUrl + builder.nodeConfig.SeqCoordinator.MyUrl = opts.ipcPath + return builder } -func createForwardingNode( - ctx context.Context, t *testing.T, - first *arbnode.Node, - l1stack *node.Node, - l1info *BlockchainTestInfo, - l2InitData *statetransfer.ArbosInitializationInfo, - ipcPath string, - redisUrl string, - fallbackPath string, -) (*ethclient.Client, *arbnode.Node) { - stackConfig := createStackConfigForTest(t.TempDir()) +func createForwardingNode(t *testing.T, builder *NodeBuilder, ipcPath string, redisUrl string, fallbackPath string) (*TestClient, func()) { if ipcPath != "" { - ipcConfig := genericconf.IPCConfigDefault - ipcConfig.Path = ipcPath - ipcConfig.Apply(stackConfig) + builder.l2StackConfig.IPCPath = ipcPath } nodeConfig := arbnode.ConfigDefaultL1Test() nodeConfig.Sequencer = false @@ -136,29 +116,18 @@ func createForwardingNode( execConfig.ForwardingTarget = fallbackPath // nodeConfig.Feed.Output.Enable = false - return Create2ndNodeWithConfig(t, ctx, first, l1stack, l1info, l2InitData, nodeConfig, execConfig, stackConfig) + return builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: nodeConfig, execConfig: execConfig}) } -func createSequencer( - ctx context.Context, t *testing.T, - first *arbnode.Node, - l1stack *node.Node, - l1info *BlockchainTestInfo, - l2InitData *statetransfer.ArbosInitializationInfo, - ipcPath string, - redisUrl string, -) (*ethclient.Client, *arbnode.Node) { - stackConfig := createStackConfigForTest(t.TempDir()) - ipcConfig := genericconf.IPCConfigDefault - ipcConfig.Path = ipcPath - ipcConfig.Apply(stackConfig) +func createSequencer(t *testing.T, builder *NodeBuilder, ipcPath string, redisUrl string) (*TestClient, func()) { + builder.l2StackConfig.IPCPath = ipcPath nodeConfig := arbnode.ConfigDefaultL1Test() nodeConfig.BatchPoster.Enable = false nodeConfig.SeqCoordinator.Enable = true nodeConfig.SeqCoordinator.RedisUrl = redisUrl nodeConfig.SeqCoordinator.MyUrl = ipcPath - return Create2ndNodeWithConfig(t, ctx, first, l1stack, l1info, l2InitData, nodeConfig, gethexec.ConfigDefaultTest(), stackConfig) + return builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: nodeConfig}) } // tmpPath returns file path with specified filename from temporary directory of the test. @@ -252,34 +221,36 @@ func TestRedisForwarder(t *testing.T) { redisServer, redisUrl := initRedis(ctx, t, append(nodePaths, fbNodePath)) defer redisServer.Close() - l2info, fallbackNode, fallbackClient, l1info, _, _, l1stack := fallbackSequencer(ctx, t, + builder := fallbackSequencer(ctx, t, &fallbackSequencerOpts{ ipcPath: fbNodePath, redisUrl: redisUrl, enableSecCoordinator: true, }) - defer requireClose(t, l1stack) - defer fallbackNode.StopAndWait() + cleanup := builder.Build(t) + defer cleanup() + fallbackNode, fallbackClient := builder.L2.ConsensusNode, builder.L2.Client - forwardingClient, forwardingNode := createForwardingNode(ctx, t, fallbackNode, l1stack, l1info, &l2info.ArbInitData, "", redisUrl, fbNodePath) - defer forwardingNode.StopAndWait() + TestClientForwarding, cleanupForwarding := createForwardingNode(t, builder, "", redisUrl, fbNodePath) + defer cleanupForwarding() + forwardingClient := TestClientForwarding.Client var seqNodes []*arbnode.Node var seqClients []*ethclient.Client for _, path := range nodePaths { - client, node := createSequencer(ctx, t, fallbackNode, l1stack, l1info, &l2info.ArbInitData, path, redisUrl) - seqNodes = append(seqNodes, node) - seqClients = append(seqClients, client) + testClientSeq, _ := createSequencer(t, builder, path, redisUrl) + seqNodes = append(seqNodes, testClientSeq.ConsensusNode) + seqClients = append(seqClients, testClientSeq.Client) } defer stopNodes(seqNodes) for i := range seqClients { userA := user("A", i) - l2info.GenerateAccount(userA) - tx := l2info.PrepareTx("Owner", userA, l2info.TransferGas, big.NewInt(1e12+int64(l2info.TransferGas)*l2info.GasPrice.Int64()), nil) + builder.L2Info.GenerateAccount(userA) + tx := builder.L2Info.PrepareTx("Owner", userA, builder.L2Info.TransferGas, big.NewInt(1e12+int64(builder.L2Info.TransferGas)*builder.L2Info.GasPrice.Int64()), nil) err := fallbackClient.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, fallbackClient, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) } @@ -289,8 +260,8 @@ func TestRedisForwarder(t *testing.T) { } userA := user("A", i) userB := user("B", i) - l2info.GenerateAccount(userB) - tx := l2info.PrepareTx(userA, userB, l2info.TransferGas, transferAmount, nil) + builder.L2Info.GenerateAccount(userB) + tx := builder.L2Info.PrepareTx(userA, userB, builder.L2Info.TransferGas, transferAmount, nil) sendFunc := func() error { return forwardingClient.SendTransaction(ctx, tx) } if err := tryWithTimeout(ctx, sendFunc, gethexec.DefaultTestForwarderConfig.UpdateInterval*10); err != nil { @@ -299,7 +270,7 @@ func TestRedisForwarder(t *testing.T) { _, err := EnsureTxSucceeded(ctx, seqClients[i], tx) Require(t, err) - l2balance, err := seqClients[i].BalanceAt(ctx, l2info.GetAddress(userB), nil) + l2balance, err := seqClients[i].BalanceAt(ctx, builder.L2Info.GetAddress(userB), nil) Require(t, err) if l2balance.Cmp(transferAmount) != 0 { @@ -320,29 +291,31 @@ func TestRedisForwarderFallbackNoRedis(t *testing.T) { redisServer, redisUrl := initRedis(ctx, t, nodePaths) redisServer.Close() - l2info, fallbackNode, fallbackClient, l1info, _, _, l1stack := fallbackSequencer(ctx, t, + builder := fallbackSequencer(ctx, t, &fallbackSequencerOpts{ ipcPath: fallbackIpcPath, redisUrl: redisUrl, enableSecCoordinator: false, }) - defer requireClose(t, l1stack) - defer fallbackNode.StopAndWait() + cleanup := builder.Build(t) + defer cleanup() + fallbackClient := builder.L2.Client - forwardingClient, forwardingNode := createForwardingNode(ctx, t, fallbackNode, l1stack, l1info, &l2info.ArbInitData, "", redisUrl, fallbackIpcPath) - defer forwardingNode.StopAndWait() + TestClientForwarding, cleanupForwarding := createForwardingNode(t, builder, "", redisUrl, fallbackIpcPath) + defer cleanupForwarding() + forwardingClient := TestClientForwarding.Client user := "User2" - l2info.GenerateAccount(user) - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, transferAmount, nil) + builder.L2Info.GenerateAccount(user) + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, transferAmount, nil) sendFunc := func() error { return forwardingClient.SendTransaction(ctx, tx) } err := tryWithTimeout(ctx, sendFunc, gethexec.DefaultTestForwarderConfig.UpdateInterval*10) Require(t, err) - _, err = EnsureTxSucceeded(ctx, fallbackClient, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - l2balance, err := fallbackClient.BalanceAt(ctx, l2info.GetAddress(user), nil) + l2balance, err := fallbackClient.BalanceAt(ctx, builder.L2Info.GetAddress(user), nil) Require(t, err) if l2balance.Cmp(transferAmount) != 0 { diff --git a/system_tests/ipc_test.go b/system_tests/ipc_test.go index dc73825a1..511a608e6 100644 --- a/system_tests/ipc_test.go +++ b/system_tests/ipc_test.go @@ -9,24 +9,18 @@ import ( "testing" "github.com/ethereum/go-ethereum/ethclient" - "github.com/offchainlabs/nitro/cmd/genericconf" ) func TestIpcRpc(t *testing.T) { ipcPath := filepath.Join(t.TempDir(), "test.ipc") - ipcConfig := genericconf.IPCConfigDefault - ipcConfig.Path = ipcPath - - stackConf := createStackConfigForTest(t.TempDir()) - ipcConfig.Apply(stackConf) - ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, l2node, _, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, nil, nil, stackConf) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.l2StackConfig.IPCPath = ipcPath + cleanup := builder.Build(t) + defer cleanup() _, err := ethclient.Dial(ipcPath) Require(t, err) diff --git a/system_tests/meaningless_reorg_test.go b/system_tests/meaningless_reorg_test.go index 7fb6934e8..f09f68041 100644 --- a/system_tests/meaningless_reorg_test.go +++ b/system_tests/meaningless_reorg_test.go @@ -10,7 +10,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/solgen/go/bridgegen" ) @@ -18,27 +17,26 @@ func TestMeaninglessBatchReorg(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - conf := arbnode.ConfigDefaultL1Test() - conf.BatchPoster.Enable = false - l2Info, arbNode, l2Client, l1Info, l1Backend, l1Client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil, nil) - defer requireClose(t, l1stack) - defer arbNode.StopAndWait() - seqInbox, err := bridgegen.NewSequencerInbox(l1Info.GetAddress("SequencerInbox"), l1Client) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig.BatchPoster.Enable = false + cleanup := builder.Build(t) + defer cleanup() + + seqInbox, err := bridgegen.NewSequencerInbox(builder.L1Info.GetAddress("SequencerInbox"), builder.L1.Client) Require(t, err) - seqOpts := l1Info.GetDefaultTransactOpts("Sequencer", ctx) + seqOpts := builder.L1Info.GetDefaultTransactOpts("Sequencer", ctx) tx, err := seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(1), nil, big.NewInt(1), common.Address{}) Require(t, err) - batchReceipt, err := EnsureTxSucceeded(ctx, l1Client, tx) + batchReceipt, err := builder.L1.EnsureTxSucceeded(tx) Require(t, err) - execNode := getExecNode(t, arbNode) for i := 0; ; i++ { if i >= 500 { Fatal(t, "Failed to read batch from L1") } - msgNum, err := execNode.ExecEngine.HeadMessageNumber() + msgNum, err := builder.L2.ExecNode.ExecEngine.HeadMessageNumber() Require(t, err) if msgNum == 1 { break @@ -47,33 +45,33 @@ func TestMeaninglessBatchReorg(t *testing.T) { } time.Sleep(10 * time.Millisecond) } - metadata, err := arbNode.InboxTracker.GetBatchMetadata(1) + metadata, err := builder.L2.ConsensusNode.InboxTracker.GetBatchMetadata(1) Require(t, err) originalBatchBlock := batchReceipt.BlockNumber.Uint64() if metadata.ParentChainBlock != originalBatchBlock { Fatal(t, "Posted batch in block", originalBatchBlock, "but metadata says L1 block was", metadata.ParentChainBlock) } - _, l2Receipt := TransferBalance(t, "Owner", "Owner", common.Big1, l2Info, l2Client, ctx) + _, l2Receipt := builder.L2.TransferBalance(t, "Owner", "Owner", common.Big1, builder.L2Info) // Make the reorg larger to force the miner to discard transactions. // The miner usually collects transactions from deleted blocks and puts them in the mempool. // However, this code doesn't run on reorgs larger than 64 blocks for performance reasons. // Therefore, we make a bunch of small blocks to prevent the code from running. for j := uint64(0); j < 70; j++ { - TransferBalance(t, "Faucet", "Faucet", common.Big1, l1Info, l1Client, ctx) + builder.L1.TransferBalance(t, "Faucet", "Faucet", common.Big1, builder.L1Info) } - parentBlock := l1Backend.BlockChain().GetBlockByNumber(batchReceipt.BlockNumber.Uint64() - 1) - err = l1Backend.BlockChain().ReorgToOldBlock(parentBlock) + parentBlock := builder.L1.L1Backend.BlockChain().GetBlockByNumber(batchReceipt.BlockNumber.Uint64() - 1) + err = builder.L1.L1Backend.BlockChain().ReorgToOldBlock(parentBlock) Require(t, err) // Produce a new l1Block so that the batch ends up in a different l1Block than before - TransferBalance(t, "User", "User", common.Big1, l1Info, l1Client, ctx) + builder.L1.TransferBalance(t, "User", "User", common.Big1, builder.L1Info) tx, err = seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(1), nil, big.NewInt(1), common.Address{}) Require(t, err) - newBatchReceipt, err := EnsureTxSucceeded(ctx, l1Client, tx) + newBatchReceipt, err := builder.L1.EnsureTxSucceeded(tx) Require(t, err) newBatchBlock := newBatchReceipt.BlockNumber.Uint64() @@ -87,7 +85,7 @@ func TestMeaninglessBatchReorg(t *testing.T) { if i >= 500 { Fatal(t, "Failed to read batch reorg from L1") } - metadata, err = arbNode.InboxTracker.GetBatchMetadata(1) + metadata, err = builder.L2.ConsensusNode.InboxTracker.GetBatchMetadata(1) Require(t, err) if metadata.ParentChainBlock == newBatchBlock { break @@ -97,10 +95,10 @@ func TestMeaninglessBatchReorg(t *testing.T) { time.Sleep(10 * time.Millisecond) } - _, err = arbNode.InboxReader.GetSequencerMessageBytes(ctx, 1) + _, err = builder.L2.ConsensusNode.InboxReader.GetSequencerMessageBytes(ctx, 1) Require(t, err) - l2Header, err := l2Client.HeaderByNumber(ctx, l2Receipt.BlockNumber) + l2Header, err := builder.L2.Client.HeaderByNumber(ctx, l2Receipt.BlockNumber) Require(t, err) if l2Header.Hash() != l2Receipt.BlockHash { diff --git a/system_tests/seq_coordinator_test.go b/system_tests/seq_coordinator_test.go index a213c366c..ac3167a60 100644 --- a/system_tests/seq_coordinator_test.go +++ b/system_tests/seq_coordinator_test.go @@ -14,7 +14,6 @@ import ( "github.com/go-redis/redis/v8" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/arbostypes" @@ -47,11 +46,12 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - nodeConfig := arbnode.ConfigDefaultL2Test() - nodeConfig.SeqCoordinator.Enable = true - nodeConfig.SeqCoordinator.RedisUrl = redisutil.CreateTestRedis(ctx, t) + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.takeOwnership = false + builder.nodeConfig.SeqCoordinator.Enable = true + builder.nodeConfig.SeqCoordinator.RedisUrl = redisutil.CreateTestRedis(ctx, t) - l2Info := NewArbTestInfo(t, params.ArbitrumDevTestChainConfig().ChainID) + l2Info := builder.L2Info // stdio protocol makes sure forwarder initialization doesn't fail nodeNames := []string{"stdio://A", "stdio://B", "stdio://C", "stdio://D", "stdio://E"} @@ -59,12 +59,13 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { nodes := make([]*arbnode.Node, len(nodeNames)) // init DB to known state - initRedisForTest(t, ctx, nodeConfig.SeqCoordinator.RedisUrl, nodeNames) + initRedisForTest(t, ctx, builder.nodeConfig.SeqCoordinator.RedisUrl, nodeNames) createStartNode := func(nodeNum int) { - nodeConfig.SeqCoordinator.MyUrl = nodeNames[nodeNum] - _, node, _ := CreateTestL2WithConfig(t, ctx, l2Info, nodeConfig, nil, false) - nodes[nodeNum] = node + builder.nodeConfig.SeqCoordinator.MyUrl = nodeNames[nodeNum] + builder.L2Info = l2Info + builder.Build(t) + nodes[nodeNum] = builder.L2.ConsensusNode } trySequencing := func(nodeNum int) bool { @@ -128,7 +129,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { if attempts > 10 { Fatal(t, "timeout waiting for msg ", msgNum, " debug: ", currentNode.SeqCoordinator.DebugPrint()) } - <-time.After(nodeConfig.SeqCoordinator.UpdateInterval / 3) + <-time.After(builder.nodeConfig.SeqCoordinator.UpdateInterval / 3) } } } @@ -232,7 +233,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { } if sequencer == -1 || (addNodes && (sequencer == currentSequencer+1)) { - time.Sleep(nodeConfig.SeqCoordinator.LockoutDuration / 5) + time.Sleep(builder.nodeConfig.SeqCoordinator.LockoutDuration / 5) continue } if sequencer == currentSequencer { @@ -270,21 +271,20 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - nodeConfig := arbnode.ConfigDefaultL1Test() - nodeConfig.SeqCoordinator.Enable = true - nodeConfig.SeqCoordinator.RedisUrl = redisutil.CreateTestRedis(ctx, t) - nodeConfig.BatchPoster.Enable = false + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig.SeqCoordinator.Enable = true + builder.nodeConfig.SeqCoordinator.RedisUrl = redisutil.CreateTestRedis(ctx, t) + builder.nodeConfig.BatchPoster.Enable = false nodeNames := []string{"stdio://A", "stdio://B"} + initRedisForTest(t, ctx, builder.nodeConfig.SeqCoordinator.RedisUrl, nodeNames) + builder.nodeConfig.SeqCoordinator.MyUrl = nodeNames[0] - initRedisForTest(t, ctx, nodeConfig.SeqCoordinator.RedisUrl, nodeNames) + cleanup := builder.Build(t) + defer cleanup() + clientA := builder.L2.Client - nodeConfig.SeqCoordinator.MyUrl = nodeNames[0] - l2Info, nodeA, clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, params.ArbitrumDevTestChainConfig(), nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() - - redisClient, err := redisutil.RedisClientFromURL(nodeConfig.SeqCoordinator.RedisUrl) + redisClient, err := redisutil.RedisClientFromURL(builder.nodeConfig.SeqCoordinator.RedisUrl) Require(t, err) defer redisClient.Close() @@ -292,27 +292,29 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { for { err := redisClient.Get(ctx, redisutil.CHOSENSEQ_KEY).Err() if errors.Is(err, redis.Nil) { - time.Sleep(nodeConfig.SeqCoordinator.UpdateInterval) + time.Sleep(builder.nodeConfig.SeqCoordinator.UpdateInterval) continue } Require(t, err) break } - l2Info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - nodeConfigDup := *nodeConfig - nodeConfig = &nodeConfigDup + nodeConfigDup := *builder.nodeConfig + builder.nodeConfig = &nodeConfigDup - nodeConfig.SeqCoordinator.MyUrl = nodeNames[1] + builder.nodeConfig.SeqCoordinator.MyUrl = nodeNames[1] if !successCase { - nodeConfig.SeqCoordinator.Signer.ECDSA.AcceptSequencer = false - nodeConfig.SeqCoordinator.Signer.ECDSA.AllowedAddresses = []string{l2Info.GetAddress("User2").Hex()} + builder.nodeConfig.SeqCoordinator.Signer.ECDSA.AcceptSequencer = false + builder.nodeConfig.SeqCoordinator.Signer.ECDSA.AllowedAddresses = []string{builder.L2Info.GetAddress("User2").Hex()} } - clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2Info.ArbInitData, nodeConfig, nil, nil) - defer nodeB.StopAndWait() - tx := l2Info.PrepareTx("Owner", "User2", l2Info.TransferGas, big.NewInt(1e12), nil) + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: builder.nodeConfig}) + defer cleanupB() + clientB := testClientB.Client + + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) err = clientA.SendTransaction(ctx, tx) Require(t, err) @@ -323,7 +325,7 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { if successCase { _, err = WaitForTx(ctx, clientB, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := clientB.BalanceAt(ctx, l2Info.GetAddress("User2"), nil) + l2balance, err := clientB.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index d0d05d569..749a91e3b 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -13,7 +13,6 @@ import ( "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/broadcastclient" - "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/relay" "github.com/offchainlabs/nitro/util/signature" "github.com/offchainlabs/nitro/wsbroadcastserver" @@ -43,30 +42,33 @@ func TestSequencerFeed(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - seqNodeConfig := arbnode.ConfigDefaultL2Test() - seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true) - defer nodeA.StopAndWait() - clientNodeConfig := arbnode.ConfigDefaultL2Test() - port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port - clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) + builderSeq := NewNodeBuilder(ctx).DefaultConfig(t, false) + builderSeq.nodeConfig.Feed.Output = *newBroadcasterConfigTest() + cleanupSeq := builderSeq.Build(t) + defer cleanupSeq() + seqInfo, seqNode, seqClient := builderSeq.L2Info, builderSeq.L2.ConsensusNode, builderSeq.L2.Client - _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false) - defer nodeB.StopAndWait() + port := seqNode.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.nodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) + builder.takeOwnership = false + cleanup := builder.Build(t) + defer cleanup() + client := builder.L2.Client - l2info1.GenerateAccount("User2") + seqInfo.GenerateAccount("User2") - tx := l2info1.PrepareTx("Owner", "User2", l2info1.TransferGas, big.NewInt(1e12), nil) + tx := seqInfo.PrepareTx("Owner", "User2", seqInfo.TransferGas, big.NewInt(1e12), nil) - err := client1.SendTransaction(ctx, tx) + err := seqClient.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client1, tx) + _, err = builderSeq.L2.EnsureTxSucceeded(tx) Require(t, err) - _, err = WaitForTx(ctx, client2, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, client, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := client2.BalanceAt(ctx, l2info1.GetAddress("User2"), nil) + l2balance, err := client.BalanceAt(ctx, seqInfo.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) @@ -78,16 +80,17 @@ func TestRelayedSequencerFeed(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - seqNodeConfig := arbnode.ConfigDefaultL2Test() - seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true) - defer nodeA.StopAndWait() + builderSeq := NewNodeBuilder(ctx).DefaultConfig(t, false) + builderSeq.nodeConfig.Feed.Output = *newBroadcasterConfigTest() + cleanupSeq := builderSeq.Build(t) + defer cleanupSeq() + seqInfo, seqNode, seqClient := builderSeq.L2Info, builderSeq.L2.ConsensusNode, builderSeq.L2.Client - bigChainId, err := client1.ChainID(ctx) + bigChainId, err := seqClient.ChainID(ctx) Require(t, err) config := relay.ConfigDefault - port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + port := seqNode.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port config.Node.Feed.Input = *newBroadcastClientConfigTest(port) config.Node.Feed.Output = *newBroadcasterConfigTest() config.Chain.ID = bigChainId.Uint64() @@ -99,26 +102,28 @@ func TestRelayedSequencerFeed(t *testing.T) { Require(t, err) defer currentRelay.StopAndWait() - clientNodeConfig := arbnode.ConfigDefaultL2Test() port = currentRelay.GetListenerAddr().(*net.TCPAddr).Port - clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeC, client3 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false) - defer nodeC.StopAndWait() - StartWatchChanErr(t, ctx, feedErrChan, nodeC) + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.nodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) + builder.takeOwnership = false + cleanup := builder.Build(t) + defer cleanup() + node, client := builder.L2.ConsensusNode, builder.L2.Client + StartWatchChanErr(t, ctx, feedErrChan, node) - l2info1.GenerateAccount("User2") + seqInfo.GenerateAccount("User2") - tx := l2info1.PrepareTx("Owner", "User2", l2info1.TransferGas, big.NewInt(1e12), nil) + tx := seqInfo.PrepareTx("Owner", "User2", seqInfo.TransferGas, big.NewInt(1e12), nil) - err = client1.SendTransaction(ctx, tx) + err = seqClient.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client1, tx) + _, err = builderSeq.L2.EnsureTxSucceeded(tx) Require(t, err) - _, err = WaitForTx(ctx, client3, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, client, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := client3.BalanceAt(ctx, l2info1.GetAddress("User2"), nil) + l2balance, err := client.BalanceAt(ctx, seqInfo.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) @@ -136,11 +141,16 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigA.BatchPoster.Enable = true nodeConfigA.Feed.Output.Enable = false - l2infoA, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfigA, nil, chainConfig, nil) - defer requireClose(t, l1stack, "unable to close l1stack") - defer nodeA.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig = nodeConfigA + builder.chainConfig = chainConfig + builder.L2Info = nil + cleanup := builder.Build(t) + defer cleanup() - authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) + l2clientA := builder.L2.Client + + authorizeDASKeyset(t, ctx, dasSignerKey, builder.L1Info, builder.L1.Client) // The lying sequencer nodeConfigC := arbnode.ConfigDefaultL1Test() @@ -148,8 +158,9 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigC.DataAvailability = nodeConfigA.DataAvailability nodeConfigC.DataAvailability.RPCAggregator.Enable = false nodeConfigC.Feed.Output = *newBroadcasterConfigTest() - l2clientC, nodeC := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2infoA.ArbInitData, nodeConfigC, gethexec.ConfigDefaultTest(), nil) - defer nodeC.StopAndWait() + testClientC, cleanupC := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: nodeConfigC}) + defer cleanupC() + l2clientC, nodeC := testClientC.Client, testClientC.ConsensusNode port := nodeC.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port @@ -159,15 +170,16 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigB.Feed.Input = *newBroadcastClientConfigTest(port) nodeConfigB.DataAvailability = nodeConfigA.DataAvailability nodeConfigB.DataAvailability.RPCAggregator.Enable = false - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2infoA.ArbInitData, nodeConfigB, nil, nil) - defer nodeB.StopAndWait() + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: nodeConfigB}) + defer cleanupB() + l2clientB := testClientB.Client - l2infoA.GenerateAccount("FraudUser") - l2infoA.GenerateAccount("RealUser") + builder.L2Info.GenerateAccount("FraudUser") + builder.L2Info.GenerateAccount("RealUser") - fraudTx := l2infoA.PrepareTx("Owner", "FraudUser", l2infoA.TransferGas, big.NewInt(1e12), nil) - l2infoA.GetInfoWithPrivKey("Owner").Nonce -= 1 // Use same l2info object for different l2s - realTx := l2infoA.PrepareTx("Owner", "RealUser", l2infoA.TransferGas, big.NewInt(1e12), nil) + fraudTx := builder.L2Info.PrepareTx("Owner", "FraudUser", builder.L2Info.TransferGas, big.NewInt(1e12), nil) + builder.L2Info.GetInfoWithPrivKey("Owner").Nonce -= 1 // Use same l2info object for different l2s + realTx := builder.L2Info.PrepareTx("Owner", "RealUser", builder.L2Info.TransferGas, big.NewInt(1e12), nil) for i := 0; i < 10; i++ { err := l2clientC.SendTransaction(ctx, fraudTx) @@ -180,7 +192,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { } } - _, err := EnsureTxSucceeded(ctx, l2clientC, fraudTx) + _, err := testClientC.EnsureTxSucceeded(fraudTx) if err != nil { t.Fatal("error ensuring fraud transaction succeeded:", err) } @@ -190,7 +202,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { if err != nil { t.Fatal("error waiting for tx:", err) } - l2balance, err := l2clientB.BalanceAt(ctx, l2infoA.GetAddress("FraudUser"), nil) + l2balance, err := l2clientB.BalanceAt(ctx, builder.L2Info.GetAddress("FraudUser"), nil) if err != nil { t.Fatal("error getting balance:", err) } @@ -204,7 +216,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { t.Fatal("error sending real transaction:", err) } - _, err = EnsureTxSucceeded(ctx, l2clientA, realTx) + _, err = builder.L2.EnsureTxSucceeded(realTx) if err != nil { t.Fatal("error ensuring real transaction succeeded:", err) } @@ -214,7 +226,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { if err != nil { t.Fatal("error waiting for transaction to get to node b:", err) } - l2balanceFraudAcct, err := l2clientB.BalanceAt(ctx, l2infoA.GetAddress("FraudUser"), nil) + l2balanceFraudAcct, err := l2clientB.BalanceAt(ctx, builder.L2Info.GetAddress("FraudUser"), nil) if err != nil { t.Fatal("error getting fraud balance:", err) } @@ -222,7 +234,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { t.Fatal("Unexpected balance (fraud acct should be empty) was:", l2balanceFraudAcct) } - l2balanceRealAcct, err := l2clientB.BalanceAt(ctx, l2infoA.GetAddress("RealUser"), nil) + l2balanceRealAcct, err := l2clientB.BalanceAt(ctx, builder.L2Info.GetAddress("RealUser"), nil) if err != nil { t.Fatal("error getting real balance:", err) } diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index a456dc5fe..c90617455 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -138,32 +138,33 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - conf := arbnode.ConfigDefaultL1Test() - conf.InboxReader.HardReorg = true + + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig.InboxReader.HardReorg = true if validator { - conf.BlockValidator.Enable = true + builder.nodeConfig.BlockValidator.Enable = true } - l2Info, arbNode, _, l1Info, l1backend, l1Client, l1stack := createTestNodeOnL1WithConfig(t, ctx, false, conf, nil, nil, nil) - execNode := getExecNode(t, arbNode) - l2Backend := execNode.Backend - defer requireClose(t, l1stack) - defer arbNode.StopAndWait() + builder.isSequencer = false + cleanup := builder.Build(t) + defer cleanup() + + l2Backend := builder.L2.ExecNode.Backend - l1BlockChain := l1backend.BlockChain() + l1BlockChain := builder.L1.L1Backend.BlockChain() - rpcC, err := l1stack.Attach() + rpcC, err := builder.L1.Stack.Attach() if err != nil { t.Fatalf("Error connecting to l1 node: %v", err) } gethClient := gethclient.New(rpcC) - seqInbox, err := bridgegen.NewSequencerInbox(l1Info.GetAddress("SequencerInbox"), l1Client) + seqInbox, err := bridgegen.NewSequencerInbox(builder.L1Info.GetAddress("SequencerInbox"), builder.L1.Client) Require(t, err) - seqOpts := l1Info.GetDefaultTransactOpts("Sequencer", ctx) + seqOpts := builder.L1Info.GetDefaultTransactOpts("Sequencer", ctx) - gasRefunderAddr := deployGasRefunder(ctx, t, l1Info, l1Client) + gasRefunderAddr := deployGasRefunder(ctx, t, builder.L1Info, builder.L1.Client) - ownerAddress := l2Info.GetAddress("Owner") + ownerAddress := builder.L2Info.GetAddress("Owner") var startL2BlockNumber uint64 = 0 startState, _, err := l2Backend.APIBackend().StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) @@ -196,10 +197,10 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { } var faucetTxs []*types.Transaction for _, acct := range accounts { - l1Info.GenerateAccount(acct) - faucetTxs = append(faucetTxs, l1Info.PrepareTx("Faucet", acct, 30000, big.NewInt(1e16), nil)) + builder.L1Info.GenerateAccount(acct) + faucetTxs = append(faucetTxs, builder.L1Info.PrepareTx("Faucet", acct, 30000, big.NewInt(1e16), nil)) } - SendWaitTestTransactions(t, ctx, l1Client, faucetTxs) + SendWaitTestTransactions(t, ctx, builder.L1.Client, faucetTxs) seqABI, err := bridgegen.SequencerInboxMetaData.GetAbi() if err != nil { @@ -216,7 +217,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { // The miner usually collects transactions from deleted blocks and puts them in the mempool. // However, this code doesn't run on reorgs larger than 64 blocks for performance reasons. // Therefore, we make a bunch of small blocks to prevent the code from running. - padAddr := l1Info.GetAddress("ReorgPadding") + padAddr := builder.L1Info.GetAddress("ReorgPadding") for j := uint64(0); j < 70; j++ { rawTx := &types.DynamicFeeTx{ To: &padAddr, @@ -225,12 +226,12 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { Value: new(big.Int), Nonce: j, } - tx := l1Info.SignTxAs("ReorgPadding", rawTx) - Require(t, l1Client.SendTransaction(ctx, tx)) - _, _ = EnsureTxSucceeded(ctx, l1Client, tx) + tx := builder.L1Info.SignTxAs("ReorgPadding", rawTx) + Require(t, builder.L1.Client.SendTransaction(ctx, tx)) + _, _ = builder.L1.EnsureTxSucceeded(tx) } reorgTargetNumber := blockStates[reorgTo].l1BlockNumber - currentHeader, err := l1Client.HeaderByNumber(ctx, nil) + currentHeader, err := builder.L1.Client.HeaderByNumber(ctx, nil) Require(t, err) if currentHeader.Number.Int64()-int64(reorgTargetNumber) < 65 { Fatal(t, "Less than 65 blocks of difference between current block", currentHeader.Number, "and target", reorgTargetNumber) @@ -245,10 +246,10 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { // Sometimes, this causes it to drop the next tx. // To work around this, we create a sacrificial tx, which may or may not succeed. // Whichever happens, by the end of this block, the miner will have processed the reorg. - tx := l1Info.PrepareTx(fmt.Sprintf("ReorgSacrifice%v", i/10), "Faucet", 30000, big.NewInt(0), nil) - err = l1Client.SendTransaction(ctx, tx) + tx := builder.L1Info.PrepareTx(fmt.Sprintf("ReorgSacrifice%v", i/10), "Faucet", 30000, big.NewInt(0), nil) + err = builder.L1.Client.SendTransaction(ctx, tx) Require(t, err) - _, _ = WaitForTx(ctx, l1Client, tx.Hash(), time.Second) + _, _ = WaitForTx(ctx, builder.L1.Client, tx.Hash(), time.Second) } else { state := blockStates[len(blockStates)-1] newBalances := make(map[common.Address]*big.Int) @@ -276,10 +277,10 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { var dest common.Address if j == 0 && amount.Cmp(reserveAmount) >= 0 { name := accountName(len(state.accounts)) - if !l2Info.HasAccount(name) { - l2Info.GenerateAccount(name) + if !builder.L2Info.HasAccount(name) { + builder.L2Info.GenerateAccount(name) } - dest = l2Info.GetAddress(name) + dest = builder.L2Info.GetAddress(name) state.accounts = append(state.accounts, dest) state.balances[dest] = big.NewInt(0) } else { @@ -294,7 +295,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { Nonce: state.nonces[source], } state.nonces[source]++ - tx := l2Info.SignTxAs(accountName(sourceNum), rawTx) + tx := builder.L2Info.SignTxAs(accountName(sourceNum), rawTx) txData, err := tx.MarshalBinary() Require(t, err) var segment []byte @@ -314,7 +315,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { seqNonce := len(blockStates) - 1 for j := 0; ; j++ { - haveNonce, err := l1Client.PendingNonceAt(ctx, seqOpts.From) + haveNonce, err := builder.L1.Client.PendingNonceAt(ctx, seqOpts.From) Require(t, err) if haveNonce == uint64(seqNonce) { break @@ -326,7 +327,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { } seqOpts.Nonce = big.NewInt(int64(seqNonce)) var tx *types.Transaction - before, err := l1Client.BalanceAt(ctx, seqOpts.From, nil) + before, err := builder.L1.Client.BalanceAt(ctx, seqOpts.From, nil) if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", seqOpts.From, err) } @@ -335,7 +336,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { if err != nil { t.Fatalf("Error encoding batch data: %v", err) } - si := l1Info.GetAddress("SequencerInbox") + si := builder.L1Info.GetAddress("SequencerInbox") wantAL, _, _, err := gethClient.CreateAccessList(ctx, ethereum.CallMsg{ From: seqOpts.From, To: &si, @@ -345,8 +346,8 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { t.Fatalf("Error creating access list: %v", err) } accessed := arbnode.AccessList(&arbnode.AccessListOpts{ - SequencerInboxAddr: l1Info.GetAddress("SequencerInbox"), - BridgeAddr: l1Info.GetAddress("Bridge"), + SequencerInboxAddr: builder.L1Info.GetAddress("SequencerInbox"), + BridgeAddr: builder.L1Info.GetAddress("Bridge"), DataPosterAddr: seqOpts.From, GasRefunderAddr: gasRefunderAddr, SequencerInboxAccs: len(blockStates), @@ -361,18 +362,18 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { tx, err = seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(int64(len(blockStates))), batchData, big.NewInt(1), gasRefunderAddr) } Require(t, err) - txRes, err := EnsureTxSucceeded(ctx, l1Client, tx) + txRes, err := builder.L1.EnsureTxSucceeded(tx) if err != nil { // Geth's clique miner is finicky. // Unfortunately this is so rare that I haven't had an opportunity to test this workaround. // Specifically, I suspect there's a race where it thinks there's no txs to put in the new block, // if a new tx arrives at the same time as it tries to create a block. // Resubmit the transaction in an attempt to get the miner going again. - _ = l1Client.SendTransaction(ctx, tx) - txRes, err = EnsureTxSucceeded(ctx, l1Client, tx) + _ = builder.L1.Client.SendTransaction(ctx, tx) + txRes, err = builder.L1.EnsureTxSucceeded(tx) Require(t, err) } - after, err := l1Client.BalanceAt(ctx, seqOpts.From, nil) + after, err := builder.L1.Client.BalanceAt(ctx, seqOpts.From, nil) if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", seqOpts.From, err) } @@ -414,9 +415,9 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { if validator && i%15 == 0 { for i := 0; ; i++ { - expectedPos, err := execNode.ExecEngine.BlockNumberToMessageIndex(expectedBlockNumber) + expectedPos, err := builder.L2.ExecNode.ExecEngine.BlockNumberToMessageIndex(expectedBlockNumber) Require(t, err) - lastValidated := arbNode.BlockValidator.Validated(t) + lastValidated := builder.L2.ConsensusNode.BlockValidator.Validated(t) if lastValidated == expectedPos+1 { break } else if i >= 1000 { diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 6267abe0c..023949142 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -28,7 +28,6 @@ import ( "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbutil" - "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/staker" @@ -60,29 +59,32 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) ctx, cancelCtx := context.WithCancel(context.Background()) defer cancelCtx() var transferGas = util.NormalizeL2GasForL1GasInitial(800_000, params.GWei) // include room for aggregator L1 costs - l2chainConfig := params.ArbitrumDevTestChainConfig() - l2info := NewBlockChainTestInfo( + + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.L2Info = NewBlockChainTestInfo( t, - types.NewArbitrumSigner(types.NewLondonSigner(l2chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), + types.NewArbitrumSigner(types.NewLondonSigner(builder.chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), transferGas, ) - _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, l2chainConfig, nil, l2info) - defer requireClose(t, l1stack) - defer l2nodeA.StopAndWait() - execNodeA := getExecNode(t, l2nodeA) + cleanupA := builder.Build(t) + defer cleanupA() + + l2nodeA := builder.L2.ConsensusNode + execNodeA := builder.L2.ExecNode if faultyStaker { - l2info.GenerateGenesisAccount("FaultyAddr", common.Big1) + builder.L2Info.GenerateGenesisAccount("FaultyAddr", common.Big1) } config := arbnode.ConfigDefaultL1Test() - execConfig := gethexec.ConfigDefaultTest() - execConfig.Sequencer.Enable = false config.Sequencer = false config.DelayedSequencer.Enable = false config.BatchPoster.Enable = false - _, l2nodeB := Create2ndNodeWithConfig(t, ctx, l2nodeA, l1stack, l1info, &l2info.ArbInitData, config, execConfig, nil) - defer l2nodeB.StopAndWait() - execNodeB := getExecNode(t, l2nodeB) + builder.execConfig.Sequencer.Enable = false + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: config}) + defer cleanupB() + + l2nodeB := testClientB.ConsensusNode + execNodeB := testClientB.ExecNode nodeAGenesis := execNodeA.Backend.APIBackend().CurrentHeader().Hash() nodeBGenesis := execNodeB.Backend.APIBackend().CurrentHeader().Hash() @@ -96,19 +98,19 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } } - BridgeBalance(t, "Faucet", big.NewInt(1).Mul(big.NewInt(params.Ether), big.NewInt(10000)), l1info, l2info, l1client, l2clientA, ctx) + builder.BridgeBalance(t, "Faucet", big.NewInt(1).Mul(big.NewInt(params.Ether), big.NewInt(10000))) - deployAuth := l1info.GetDefaultTransactOpts("RollupOwner", ctx) + deployAuth := builder.L1Info.GetDefaultTransactOpts("RollupOwner", ctx) balance := big.NewInt(params.Ether) balance.Mul(balance, big.NewInt(100)) - l1info.GenerateAccount("ValidatorA") - TransferBalance(t, "Faucet", "ValidatorA", balance, l1info, l1client, ctx) - l1authA := l1info.GetDefaultTransactOpts("ValidatorA", ctx) + builder.L1Info.GenerateAccount("ValidatorA") + builder.L1.TransferBalance(t, "Faucet", "ValidatorA", balance, builder.L1Info) + l1authA := builder.L1Info.GetDefaultTransactOpts("ValidatorA", ctx) - l1info.GenerateAccount("ValidatorB") - TransferBalance(t, "Faucet", "ValidatorB", balance, l1info, l1client, ctx) - l1authB := l1info.GetDefaultTransactOpts("ValidatorB", ctx) + builder.L1Info.GenerateAccount("ValidatorB") + builder.L1.TransferBalance(t, "Faucet", "ValidatorB", balance, builder.L1Info) + l1authB := builder.L1Info.GetDefaultTransactOpts("ValidatorB", ctx) valWalletAddrAPtr, err := validatorwallet.GetValidatorWalletContract(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader, true) Require(t, err) @@ -119,19 +121,19 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err, "didn't cache validator wallet address", valWalletAddrA.String(), "vs", valWalletAddrCheck.String()) } - rollup, err := rollupgen.NewRollupAdminLogic(l2nodeA.DeployInfo.Rollup, l1client) + rollup, err := rollupgen.NewRollupAdminLogic(l2nodeA.DeployInfo.Rollup, builder.L1.Client) Require(t, err) tx, err := rollup.SetValidator(&deployAuth, []common.Address{valWalletAddrA, l1authB.From}, []bool{true, true}) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = builder.L1.EnsureTxSucceeded(tx) Require(t, err) tx, err = rollup.SetMinimumAssertionPeriod(&deployAuth, big.NewInt(1)) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = builder.L1.EnsureTxSucceeded(tx) Require(t, err) - validatorUtils, err := rollupgen.NewValidatorUtils(l2nodeA.DeployInfo.ValidatorUtils, l1client) + validatorUtils, err := rollupgen.NewValidatorUtils(l2nodeA.DeployInfo.ValidatorUtils, builder.L1.Client) Require(t, err) valConfig := staker.TestL1ValidatorConfig @@ -223,7 +225,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) err = valWalletB.Initialize(ctx) Require(t, err) } - valWalletC := validatorwallet.NewNoOp(l1client, l2nodeA.DeployInfo.Rollup) + valWalletC := validatorwallet.NewNoOp(builder.L1.Client, l2nodeA.DeployInfo.Rollup) valConfig.Strategy = "Watchtower" stakerC, err := staker.NewStaker( l2nodeA.L1Reader, @@ -245,11 +247,11 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) err = stakerC.Initialize(ctx) Require(t, err) - l2info.GenerateAccount("BackgroundUser") - tx = l2info.PrepareTx("Faucet", "BackgroundUser", l2info.TransferGas, balance, nil) - err = l2clientA.SendTransaction(ctx, tx) + builder.L2Info.GenerateAccount("BackgroundUser") + tx = builder.L2Info.PrepareTx("Faucet", "BackgroundUser", builder.L2Info.TransferGas, balance, nil) + err = builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2clientA, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) // Continually make L2 transactions in a background thread @@ -261,7 +263,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) })() go (func() { defer close(backgroundTxsShutdownChan) - err := makeBackgroundTxs(backgroundTxsCtx, l2info, l2clientA) + err := makeBackgroundTxs(backgroundTxsCtx, builder.L2Info, builder.L2.Client) if !errors.Is(err, context.Canceled) { log.Warn("error making background txs", "err", err) } @@ -304,26 +306,26 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) if !challengeMangerTimedOut { // Upgrade the ChallengeManager contract to an implementation which says challenges are always timed out - mockImpl, tx, _, err := mocksgen.DeployTimedOutChallengeManager(&deployAuth, l1client) + mockImpl, tx, _, err := mocksgen.DeployTimedOutChallengeManager(&deployAuth, builder.L1.Client) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = builder.L1.EnsureTxSucceeded(tx) Require(t, err) managerAddr := valWalletA.ChallengeManagerAddress() // 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 proxyAdminSlot := common.BigToHash(arbmath.BigSub(crypto.Keccak256Hash([]byte("eip1967.proxy.admin")).Big(), common.Big1)) - proxyAdminBytes, err := l1client.StorageAt(ctx, managerAddr, proxyAdminSlot, nil) + proxyAdminBytes, err := builder.L1.Client.StorageAt(ctx, managerAddr, proxyAdminSlot, nil) Require(t, err) proxyAdminAddr := common.BytesToAddress(proxyAdminBytes) if proxyAdminAddr == (common.Address{}) { Fatal(t, "failed to get challenge manager proxy admin") } - proxyAdmin, err := mocksgen.NewProxyAdminForBinding(proxyAdminAddr, l1client) + proxyAdmin, err := mocksgen.NewProxyAdminForBinding(proxyAdminAddr, builder.L1.Client) Require(t, err) tx, err = proxyAdmin.Upgrade(&deployAuth, managerAddr, mockImpl) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = builder.L1.EnsureTxSucceeded(tx) Require(t, err) challengeMangerTimedOut = true @@ -343,7 +345,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } Require(t, err, "Staker", stakerName, "failed to act") if tx != nil { - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = builder.L1.EnsureTxSucceeded(tx) Require(t, err, "EnsureTxSucceeded failed for staker", stakerName, "tx") } if faultyStaker { @@ -379,7 +381,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err) } for j := 0; j < 5; j++ { - TransferBalance(t, "Faucet", "Faucet", common.Big0, l1info, l1client, ctx) + builder.L1.TransferBalance(t, "Faucet", "Faucet", common.Big0, builder.L1Info) } } From a430014a20e58db025d8612b0e324fcab1fe936e Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 24 Oct 2023 18:00:46 -0500 Subject: [PATCH 316/775] code refactor --- wsbroadcastserver/wsbroadcastserver.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wsbroadcastserver/wsbroadcastserver.go b/wsbroadcastserver/wsbroadcastserver.go index 43ac27593..9a7037a71 100644 --- a/wsbroadcastserver/wsbroadcastserver.go +++ b/wsbroadcastserver/wsbroadcastserver.go @@ -33,8 +33,8 @@ var ( HTTPHeaderFeedClientVersion = textproto.CanonicalMIMEHeaderKey("Arbitrum-Feed-Client-Version") HTTPHeaderRequestedSequenceNumber = textproto.CanonicalMIMEHeaderKey("Arbitrum-Requested-Sequence-Number") HTTPHeaderChainId = textproto.CanonicalMIMEHeaderKey("Arbitrum-Chain-Id") - upgradeToWSTimer = metrics.NewRegisteredTimer("arb/wsbroadcastserver/wsupgrade/duration", nil) - startWithHeaderTimer = metrics.NewRegisteredTimer("arb/wsbroadcastserver/startwithheader/duration", nil) + upgradeToWSTimer = metrics.NewRegisteredTimer("arb/feed/clients/wsupgrade/duration", nil) + startWithHeaderTimer = metrics.NewRegisteredTimer("arb/feed/clients/start/duration", nil) ) const ( From 25e42335f2ca90e61ed263ea9b1a2e31d1a8c759 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 25 Oct 2023 12:42:29 +0200 Subject: [PATCH 317/775] Perform admin actions through upg executor in system tests --- arbnode/node.go | 1 - system_tests/common_test.go | 24 +++++++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 4b3381e78..0782e8ecb 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -72,7 +72,6 @@ func deployBridgeCreator(ctx context.Context, l1Reader *headerreader.HeaderReade return common.Address{}, fmt.Errorf("bridge deploy error: %w", err) } - // maxDataSize := big.NewInt(117964) seqInboxTemplate, tx, _, err := bridgegen.DeploySequencerInbox(auth, client, maxDataSize) err = andTxSucceeded(ctx, l1Reader, tx, err) if err != nil { diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 31401945f..b985d02fd 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -12,6 +12,7 @@ import ( "net" "os" "strconv" + "strings" "testing" "time" @@ -30,6 +31,7 @@ import ( "github.com/offchainlabs/nitro/validator/server_common" "github.com/offchainlabs/nitro/validator/valnode" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" @@ -52,6 +54,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" + "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" "github.com/offchainlabs/nitro/statetransfer" "github.com/offchainlabs/nitro/util/testhelpers" ) @@ -628,6 +631,8 @@ func DeployOnTestL1( l1Reader.Start(ctx) defer l1Reader.StopAndWait() + nativeToken := common.Address{} + maxDataSize := big.NewInt(117964) addresses, err := arbnode.DeployOnL1( ctx, l1Reader, @@ -635,13 +640,14 @@ func DeployOnTestL1( l1info.GetAddress("Sequencer"), 0, arbnode.GenerateRollupConfig(false, locator.LatestWasmModuleRoot(), l1info.GetAddress("RollupOwner"), chainConfig, serializedChainConfig, common.Address{}), - common.Address{}, - big.NewInt(117964), + nativeToken, + maxDataSize, ) Require(t, err) l1info.SetContract("Bridge", addresses.Bridge) l1info.SetContract("SequencerInbox", addresses.SequencerInbox) l1info.SetContract("Inbox", addresses.Inbox) + l1info.SetContract("UpgradeExecutor", addresses.UpgradeExecutor) initMessage := getInitMessage(ctx, t, l1client, addresses) return addresses, initMessage } @@ -990,11 +996,19 @@ func authorizeDASKeyset( err := keyset.Serialize(wr) Require(t, err, "unable to serialize DAS keyset") keysetBytes := wr.Bytes() - sequencerInbox, err := bridgegen.NewSequencerInbox(l1info.Accounts["SequencerInbox"].Address, l1client) - Require(t, err, "unable to create sequencer inbox") + + sequencerInboxABI, err := abi.JSON(strings.NewReader(bridgegen.SequencerInboxABI)) + Require(t, err, "unable to parse sequencer inbox ABI") + setKeysetCalldata, err := sequencerInboxABI.Pack("setValidKeyset", keysetBytes) + Require(t, err, "unable to generate calldata") + + upgradeExecutor, err := upgrade_executorgen.NewUpgradeExecutor(l1info.Accounts["UpgradeExecutor"].Address, l1client) + Require(t, err, "unable to bind upgrade executor") + trOps := l1info.GetDefaultTransactOpts("RollupOwner", ctx) - tx, err := sequencerInbox.SetValidKeyset(&trOps, keysetBytes) + tx, err := upgradeExecutor.ExecuteCall(&trOps, l1info.Accounts["SequencerInbox"].Address, setKeysetCalldata) Require(t, err, "unable to set valid keyset") + _, err = EnsureTxSucceeded(ctx, l1client, tx) Require(t, err, "unable to ensure transaction success for setting valid keyset") } From 967d924e2f5e28fcc8647f84c533c46375754963 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 25 Oct 2023 12:47:08 +0200 Subject: [PATCH 318/775] Perform admin action through upg executor in staker test --- system_tests/staker_test.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 6267abe0c..7870c7b84 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -16,6 +16,7 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" @@ -31,6 +32,7 @@ import ( "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" + "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/staker/validatorwallet" "github.com/offchainlabs/nitro/util" @@ -120,16 +122,20 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } rollup, err := rollupgen.NewRollupAdminLogic(l2nodeA.DeployInfo.Rollup, l1client) - Require(t, err) - tx, err := rollup.SetValidator(&deployAuth, []common.Address{valWalletAddrA, l1authB.From}, []bool{true, true}) - Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) - Require(t, err) - - tx, err = rollup.SetMinimumAssertionPeriod(&deployAuth, big.NewInt(1)) - Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) - Require(t, err) + upgradeExecutor, err := upgrade_executorgen.NewUpgradeExecutor(l2nodeA.DeployInfo.UpgradeExecutor, l1client) + Require(t, err, "unable to bind upgrade executor") + rollupABI, err := abi.JSON(strings.NewReader(rollupgen.RollupAdminLogicABI)) + Require(t, err, "unable to parse rollup ABI") + + setValidatorCalldata, err := rollupABI.Pack("setValidator", []common.Address{valWalletAddrA, l1authB.From}, []bool{true, true}) + Require(t, err, "unable to generate setValidator calldata") + tx, err := upgradeExecutor.ExecuteCall(&deployAuth, l2nodeA.DeployInfo.Rollup, setValidatorCalldata) + Require(t, err, "unable to set validators") + + setMinAssertPeriodCalldata, err := rollupABI.Pack("setMinimumAssertionPeriod", big.NewInt(1)) + Require(t, err, "unable to generate setMinimumAssertionPeriod calldata") + tx, err = upgradeExecutor.ExecuteCall(&deployAuth, l2nodeA.DeployInfo.Rollup, setMinAssertPeriodCalldata) + Require(t, err, "unable to set minimum assertion period") validatorUtils, err := rollupgen.NewValidatorUtils(l2nodeA.DeployInfo.ValidatorUtils, l1client) Require(t, err) From 1b76e9e7188dd9653a1fa45432a00388511d42f4 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 25 Oct 2023 16:39:29 +0530 Subject: [PATCH 319/775] Changes based on PR comments --- contracts | 2 +- system_tests/block_validator_test.go | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/contracts b/contracts index b16bf0b73..c3031ba6c 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit b16bf0b737468382854dac28346fec8b65b55989 +Subproject commit c3031ba6cc39c70aad7ac8165b4a89f81ebae98c diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index 816f0bd73..f2fd888dc 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -127,6 +127,10 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops _, _, simple, err = mocksgen.DeploySimple(&auth, l2client) Require(t, err, "could not deploy contract") + tx, err := simple.StoreDifficulty(&auth) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, l2client, tx) + Require(t, err) difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) Require(t, err) if !arbmath.BigEquals(difficulty, common.Big1) { @@ -135,7 +139,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops // make auth a chain owner arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) Require(t, err) - tx, err := arbDebug.BecomeChainOwner(&auth) + tx, err = arbDebug.BecomeChainOwner(&auth) Require(t, err) _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) @@ -146,6 +150,10 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops _, err = EnsureTxSucceeded(ctx, l2client, tx) Require(t, err) + tx, err = simple.StoreDifficulty(&auth) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, l2client, tx) + Require(t, err) difficulty, err = simple.GetBlockDifficulty(&bind.CallOpts{}) Require(t, err) if !arbmath.BigEquals(difficulty, common.Big1) { @@ -187,13 +195,6 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops Fatal(t, "Unexpected balance:", l2balance) } } - if workload == upgradeArbOs { - difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) - Require(t, err) - if !arbmath.BigEquals(difficulty, common.Big1) { - Fatal(t, "Expected difficulty to be 1 but got:", difficulty) - } - } lastBlock, err := l2clientB.BlockByNumber(ctx, nil) Require(t, err) From b0c0db9be5be43d429f155a99bee63a8fb66608d Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 25 Oct 2023 17:03:31 +0530 Subject: [PATCH 320/775] update contract --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index c3031ba6c..e9b869d42 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit c3031ba6cc39c70aad7ac8165b4a89f81ebae98c +Subproject commit e9b869d42f1551a43f1aae540463e8b2cd05b0b1 From 9067c64d0bbb08f2f6fcb8cf33996e7e8ff852a0 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 25 Oct 2023 17:23:46 +0530 Subject: [PATCH 321/775] minor fix --- system_tests/estimation_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index 00803d204..6f741901d 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -154,7 +154,7 @@ func TestDifficultyForArbOSTen(t *testing.T) { chainConfig := params.ArbitrumDevTestChainConfig() chainConfig.ArbitrumChainParams.InitialArbOSVersion = 10 - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, arbnode.ConfigDefaultL2Test(), true, chainConfig) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, arbnode.ConfigDefaultL2Test(), nil, true, chainConfig) defer node.StopAndWait() auth := l2info.GetDefaultTransactOpts("Owner", ctx) From 35b4bcf8eaf63356361a9bdc00013c829e072c72 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 25 Oct 2023 17:27:26 +0530 Subject: [PATCH 322/775] update contract --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index e9b869d42..c3d98acd2 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit e9b869d42f1551a43f1aae540463e8b2cd05b0b1 +Subproject commit c3d98acd24279d88ca51367fe9ba77fb2b1cd074 From 17ce3cc9bfa771963a61d220a3f0a19d85a486f5 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 25 Oct 2023 17:32:02 +0530 Subject: [PATCH 323/775] update contract --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index c3d98acd2..e9b869d42 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit c3d98acd24279d88ca51367fe9ba77fb2b1cd074 +Subproject commit e9b869d42f1551a43f1aae540463e8b2cd05b0b1 From d603cba1d0f1599132b4f311790aa4d1969eebd3 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 25 Oct 2023 14:12:06 +0200 Subject: [PATCH 324/775] Add missing checks --- system_tests/staker_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 7870c7b84..968d7c8e0 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -122,6 +122,8 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } rollup, err := rollupgen.NewRollupAdminLogic(l2nodeA.DeployInfo.Rollup, l1client) + Require(t, err) + upgradeExecutor, err := upgrade_executorgen.NewUpgradeExecutor(l2nodeA.DeployInfo.UpgradeExecutor, l1client) Require(t, err, "unable to bind upgrade executor") rollupABI, err := abi.JSON(strings.NewReader(rollupgen.RollupAdminLogicABI)) @@ -131,11 +133,15 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err, "unable to generate setValidator calldata") tx, err := upgradeExecutor.ExecuteCall(&deployAuth, l2nodeA.DeployInfo.Rollup, setValidatorCalldata) Require(t, err, "unable to set validators") + _, err = EnsureTxSucceeded(ctx, l1client, tx) + Require(t, err) setMinAssertPeriodCalldata, err := rollupABI.Pack("setMinimumAssertionPeriod", big.NewInt(1)) Require(t, err, "unable to generate setMinimumAssertionPeriod calldata") tx, err = upgradeExecutor.ExecuteCall(&deployAuth, l2nodeA.DeployInfo.Rollup, setMinAssertPeriodCalldata) Require(t, err, "unable to set minimum assertion period") + _, err = EnsureTxSucceeded(ctx, l1client, tx) + Require(t, err) validatorUtils, err := rollupgen.NewValidatorUtils(l2nodeA.DeployInfo.ValidatorUtils, l1client) Require(t, err) From 1c8f496d4f5046ff254296131f4bff6acaca1585 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 25 Oct 2023 14:38:31 +0200 Subject: [PATCH 325/775] Upgrade through upg executor --- system_tests/staker_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 968d7c8e0..01243608d 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -331,9 +331,11 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Fatal(t, "failed to get challenge manager proxy admin") } - proxyAdmin, err := mocksgen.NewProxyAdminForBinding(proxyAdminAddr, l1client) + proxyAdminABI, err := abi.JSON(strings.NewReader(mocksgen.ProxyAdminForBindingABI)) Require(t, err) - tx, err = proxyAdmin.Upgrade(&deployAuth, managerAddr, mockImpl) + upgradeCalldata, err := proxyAdminABI.Pack("upgrade", managerAddr, mockImpl) + Require(t, err) + tx, err = upgradeExecutor.ExecuteCall(&deployAuth, proxyAdminAddr, upgradeCalldata) Require(t, err) _, err = EnsureTxSucceeded(ctx, l1client, tx) Require(t, err) From 46287a1be3d942c53204800e7c981a856c8cf53b Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 25 Oct 2023 19:05:46 +0530 Subject: [PATCH 326/775] minor fix --- system_tests/estimation_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index 6f741901d..441c99bca 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -141,6 +141,10 @@ func TestDifficultyForLatestArbOS(t *testing.T) { _, _, simple, err := mocksgen.DeploySimple(&auth, client) Require(t, err, "could not deploy contract") + tx, err := simple.StoreDifficulty(&auth) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, client, tx) + Require(t, err) difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) Require(t, err) if !arbmath.BigEquals(difficulty, common.Big1) { @@ -163,6 +167,10 @@ func TestDifficultyForArbOSTen(t *testing.T) { _, _, simple, err := mocksgen.DeploySimple(&auth, client) Require(t, err, "could not deploy contract") + tx, err := simple.StoreDifficulty(&auth) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, client, tx) + Require(t, err) difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) Require(t, err) if !arbmath.BigEquals(difficulty, common.Big1) { From 0e9445dbf9ea1efe29408fef7f1d5be5b85362e6 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Wed, 25 Oct 2023 09:35:58 -0500 Subject: [PATCH 327/775] Update wsbroadcastserver/wsbroadcastserver.go Co-authored-by: Joshua Colvin --- wsbroadcastserver/wsbroadcastserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsbroadcastserver/wsbroadcastserver.go b/wsbroadcastserver/wsbroadcastserver.go index 9a7037a71..fed548963 100644 --- a/wsbroadcastserver/wsbroadcastserver.go +++ b/wsbroadcastserver/wsbroadcastserver.go @@ -33,7 +33,7 @@ var ( HTTPHeaderFeedClientVersion = textproto.CanonicalMIMEHeaderKey("Arbitrum-Feed-Client-Version") HTTPHeaderRequestedSequenceNumber = textproto.CanonicalMIMEHeaderKey("Arbitrum-Requested-Sequence-Number") HTTPHeaderChainId = textproto.CanonicalMIMEHeaderKey("Arbitrum-Chain-Id") - upgradeToWSTimer = metrics.NewRegisteredTimer("arb/feed/clients/wsupgrade/duration", nil) + upgradeToWSTimer = metrics.NewRegisteredTimer("arb/feed/clients/upgrade/duration", nil) startWithHeaderTimer = metrics.NewRegisteredTimer("arb/feed/clients/start/duration", nil) ) From 70df6d6a225cf0b88d5178971c5c55cb56a4ef84 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 25 Oct 2023 09:57:01 -0500 Subject: [PATCH 328/775] code refactor --- wsbroadcastserver/wsbroadcastserver.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/wsbroadcastserver/wsbroadcastserver.go b/wsbroadcastserver/wsbroadcastserver.go index fed548963..c26a91014 100644 --- a/wsbroadcastserver/wsbroadcastserver.go +++ b/wsbroadcastserver/wsbroadcastserver.go @@ -204,11 +204,18 @@ func (s *WSBroadcastServer) Start(ctx context.Context) error { HTTPHeaderChainId: []string{strconv.FormatUint(s.chainId, 10)}, }) - return s.StartWithHeader(ctx, header) + startTime := time.Now() + err := s.StartWithHeader(ctx, header) + elapsed := time.Since(startTime) + startWithHeaderTimer.Update(elapsed) + + if err != nil { + return err + } + return nil } func (s *WSBroadcastServer) StartWithHeader(ctx context.Context, header ws.HandshakeHeader) error { - startTimeMain := time.Now() s.startMutex.Lock() defer s.startMutex.Unlock() if s.started { @@ -490,9 +497,6 @@ func (s *WSBroadcastServer) StartWithHeader(ctx context.Context, header ws.Hands s.started = true - elapsedMain := time.Since(startTimeMain) - startWithHeaderTimer.Update(elapsedMain) - return nil } From 7315e8ac0fe1d9a161a12f88a15a7b2c1a2c35d1 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 25 Oct 2023 11:18:13 -0500 Subject: [PATCH 329/775] add more functions to TestClient, refactor all tests --- system_tests/aliasing_test.go | 26 +- system_tests/batch_poster_test.go | 54 ++--- system_tests/block_hash_test.go | 10 +- system_tests/block_validator_test.go | 73 +++--- system_tests/bloom_test.go | 6 +- system_tests/common_test.go | 67 +----- system_tests/contract_tx_test.go | 18 +- system_tests/delayedinbox_test.go | 15 +- system_tests/delayedinboxlong_test.go | 26 +- system_tests/estimation_test.go | 79 ++++--- system_tests/fees_test.go | 2 +- system_tests/infra_fee_test.go | 29 +-- system_tests/initialization_test.go | 8 +- system_tests/log_subscription_test.go | 15 +- system_tests/nodeinterface_test.go | 14 +- system_tests/outbox_test.go | 17 +- system_tests/precompile_test.go | 32 +-- system_tests/recreatestate_rpc_test.go | 19 +- system_tests/reorg_resequencing_test.go | 45 ++-- system_tests/retryable_test.go | 302 ++++++++++++------------ system_tests/seq_coordinator_test.go | 44 ++-- system_tests/seq_nonce_test.go | 54 +++-- system_tests/seq_pause_test.go | 22 +- system_tests/seq_reject_test.go | 57 +++-- system_tests/seq_whitelist_test.go | 23 +- system_tests/seqcompensation_test.go | 28 +-- system_tests/seqinbox_test.go | 29 ++- system_tests/staker_test.go | 13 +- system_tests/transfer_test.go | 17 +- system_tests/triedb_race_test.go | 38 ++- system_tests/twonodes_test.go | 33 +-- system_tests/twonodeslong_test.go | 82 ++++--- 32 files changed, 634 insertions(+), 663 deletions(-) diff --git a/system_tests/aliasing_test.go b/system_tests/aliasing_test.go index 5e4e65a2c..60a89468a 100644 --- a/system_tests/aliasing_test.go +++ b/system_tests/aliasing_test.go @@ -22,20 +22,20 @@ func TestAliasing(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) - user := l1info.GetDefaultTransactOpts("User", ctx) - TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), l2info, l2client, ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + user := builder.L1Info.GetDefaultTransactOpts("User", ctx) + builder.L2.TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), builder.L2Info) - simpleAddr, simple := deploySimple(t, ctx, auth, l2client) + simpleAddr, simple := builder.L2.DeploySimple(t, auth) simpleContract, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) Require(t, err) // Test direct calls - arbsys, err := precompilesgen.NewArbSys(types.ArbSysAddress, l2client) + arbsys, err := precompilesgen.NewArbSys(types.ArbSysAddress, builder.L2.Client) Require(t, err) top, err := arbsys.IsTopLevelCall(nil) Require(t, err) @@ -56,14 +56,14 @@ func TestAliasing(t *testing.T) { // check via L2 tx, err := simple.CheckCalls(&auth, top, direct, static, delegate, callcode, call) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) // check signed txes via L1 data, err := simpleContract.Pack("checkCalls", top, direct, static, delegate, callcode, call) Require(t, err) - tx = l2info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) - SendSignedTxViaL1(t, ctx, l1info, l1client, l2client, tx) + tx = builder.L2Info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) + builder.L1.SendSignedTx(t, builder.L2.Client, tx, builder.L1Info) } testUnsigned := func(top, direct, static, delegate, callcode, call bool) { @@ -72,8 +72,8 @@ func TestAliasing(t *testing.T) { // check unsigned txes via L1 data, err := simpleContract.Pack("checkCalls", top, direct, static, delegate, callcode, call) Require(t, err) - tx := l2info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) - SendUnsignedTxViaL1(t, ctx, l1info, l1client, l2client, tx) + tx := builder.L2Info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) + builder.L1.SendUnsignedTx(t, builder.L2.Client, tx, builder.L1Info) } testL2Signed(true, true, false, false, false, false) diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 8c0de8c6d..8561e3ffc 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -50,10 +50,9 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { builder.nodeConfig.BatchPoster.RedisUrl = redisUrl cleanup := builder.Build(t) defer cleanup() - l1A, l2A := builder.L1, builder.L2 - l2B, cleanup2nd := builder.Build2ndNode(t, &SecondNodeParams{}) - defer cleanup2nd() + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{}) + defer cleanupB() builder.L2Info.GenerateAccount("User2") @@ -63,12 +62,12 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) txs = append(txs, tx) - err := l2A.Client.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) } for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, l2A.Client, tx) + _, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) } @@ -77,7 +76,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { seqTxOpts := builder.L1Info.GetDefaultTransactOpts("Sequencer", ctx) builder.nodeConfig.BatchPoster.Enable = true builder.nodeConfig.BatchPoster.MaxSize = len(firstTxData) * 2 - startL1Block, err := l1A.Client.BlockNumber(ctx) + startL1Block, err := builder.L1.Client.BlockNumber(ctx) Require(t, err) for i := 0; i < parallelBatchPosters; i++ { // Make a copy of the batch poster config so NewBatchPoster calling Validate() on it doesn't race @@ -85,12 +84,12 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { batchPoster, err := arbnode.NewBatchPoster(ctx, &arbnode.BatchPosterOpts{ DataPosterDB: nil, - L1Reader: l2A.ConsensusNode.L1Reader, - Inbox: l2A.ConsensusNode.InboxTracker, - Streamer: l2A.ConsensusNode.TxStreamer, - SyncMonitor: l2A.ConsensusNode.SyncMonitor, + L1Reader: builder.L2.ConsensusNode.L1Reader, + Inbox: builder.L2.ConsensusNode.InboxTracker, + Streamer: builder.L2.ConsensusNode.TxStreamer, + SyncMonitor: builder.L2.ConsensusNode.SyncMonitor, Config: func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, - DeployInfo: l2A.ConsensusNode.DeployInfo, + DeployInfo: builder.L2.ConsensusNode.DeployInfo, TransactOpts: &seqTxOpts, DAWriter: nil, }, @@ -102,11 +101,11 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { lastTxHash := txs[len(txs)-1].Hash() for i := 90; i > 0; i-- { - SendWaitTestTransactions(t, ctx, l1A.Client, []*types.Transaction{ + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) time.Sleep(500 * time.Millisecond) - _, err := l2B.Client.TransactionReceipt(ctx, lastTxHash) + _, err := testClientB.Client.TransactionReceipt(ctx, lastTxHash) if err == nil { break } @@ -121,9 +120,9 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { // However, setting the clique period to 1 slows everything else (including the L1 deployment for this test) down to a crawl. if false { // Make sure the batch poster is able to post multiple batches in one block - endL1Block, err := l1A.Client.BlockNumber(ctx) + endL1Block, err := builder.L1.Client.BlockNumber(ctx) Require(t, err) - seqInbox, err := arbnode.NewSequencerInbox(l1A.Client, l2A.ConsensusNode.DeployInfo.SequencerInbox, 0) + seqInbox, err := arbnode.NewSequencerInbox(builder.L1.Client, builder.L2.ConsensusNode.DeployInfo.SequencerInbox, 0) Require(t, err) batches, err := seqInbox.LookupBatchesInRange(ctx, new(big.Int).SetUint64(startL1Block), new(big.Int).SetUint64(endL1Block)) Require(t, err) @@ -143,7 +142,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { } } - l2balance, err := l2B.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) + l2balance, err := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Sign() == 0 { @@ -160,10 +159,9 @@ func TestBatchPosterLargeTx(t *testing.T) { builder.execConfig.Sequencer.MaxTxDataSize = 110000 cleanup := builder.Build(t) defer cleanup() - l2A := builder.L2 - l2B, cleanup2nd := builder.Build2ndNode(t, &SecondNodeParams{}) - defer cleanup2nd() + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{}) + defer cleanupB() data := make([]byte, 100000) _, err := rand.Read(data) @@ -171,11 +169,11 @@ func TestBatchPosterLargeTx(t *testing.T) { faucetAddr := builder.L2Info.GetAddress("Faucet") gas := builder.L2Info.TransferGas + 20000*uint64(len(data)) tx := builder.L2Info.PrepareTxTo("Faucet", &faucetAddr, gas, common.Big0, data) - err = l2A.Client.SendTransaction(ctx, tx) + err = builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - receiptA, err := EnsureTxSucceeded(ctx, l2A.Client, tx) + receiptA, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) - receiptB, err := EnsureTxSucceededWithTimeout(ctx, l2B.Client, tx, time.Second*30) + receiptB, err := testClientB.EnsureTxSucceededWithTimeout(tx, time.Second*30) Require(t, err) if receiptA.BlockHash != receiptB.BlockHash { Fatal(t, "receipt A block hash", receiptA.BlockHash, "does not equal receipt B block hash", receiptB.BlockHash) @@ -193,7 +191,7 @@ func TestBatchPosterKeepsUp(t *testing.T) { builder.execConfig.RPC.RPCTxFeeCap = 1000. cleanup := builder.Build(t) defer cleanup() - l2A := builder.L2 + builder.L2Info.GasPrice = big.NewInt(100e9) go func() { @@ -203,9 +201,9 @@ func TestBatchPosterKeepsUp(t *testing.T) { for { gas := builder.L2Info.TransferGas + 20000*uint64(len(data)) tx := builder.L2Info.PrepareTx("Faucet", "Faucet", gas, common.Big0, data) - err = l2A.Client.SendTransaction(ctx, tx) + err = builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err := EnsureTxSucceeded(ctx, l2A.Client, tx) + _, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) } }() @@ -213,11 +211,11 @@ func TestBatchPosterKeepsUp(t *testing.T) { start := time.Now() for { time.Sleep(time.Second) - batches, err := l2A.ConsensusNode.InboxTracker.GetBatchCount() + batches, err := builder.L2.ConsensusNode.InboxTracker.GetBatchCount() Require(t, err) - postedMessages, err := l2A.ConsensusNode.InboxTracker.GetBatchMessageCount(batches - 1) + postedMessages, err := builder.L2.ConsensusNode.InboxTracker.GetBatchMessageCount(batches - 1) Require(t, err) - haveMessages, err := l2A.ConsensusNode.TxStreamer.GetMessageCount() + haveMessages, err := builder.L2.ConsensusNode.TxStreamer.GetMessageCount() Require(t, err) duration := time.Since(start) fmt.Printf("batches posted: %v over %v (%.2f batches/second)\n", batches, duration, float64(batches)/(float64(duration)/float64(time.Second))) diff --git a/system_tests/block_hash_test.go b/system_tests/block_hash_test.go index 2b8051242..b437f3dad 100644 --- a/system_tests/block_hash_test.go +++ b/system_tests/block_hash_test.go @@ -16,13 +16,13 @@ func TestBlockHash(t *testing.T) { defer cancel() // Even though we don't use the L1, we need to create this node on L1 to get accurate L1 block numbers - l2info, l2node, l2client, _, _, _, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Faucet", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) - _, _, simple, err := mocksgen.DeploySimple(&auth, l2client) + _, _, simple, err := mocksgen.DeploySimple(&auth, builder.L2.Client) Require(t, err) _, err = simple.CheckBlockHashes(&bind.CallOpts{Context: ctx}) diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index 1699346b1..d0409f867 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -51,20 +51,23 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops delayEvery = workloadLoops / 3 } - l2info, nodeA, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, nil, chainConfig, nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig = l1NodeConfigA + builder.chainConfig = chainConfig + builder.L2Info = nil + cleanup := builder.Build(t) + defer cleanup() - authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) + authorizeDASKeyset(t, ctx, dasSignerKey, builder.L1Info, builder.L1.Client) validatorConfig := arbnode.ConfigDefaultL1NonSequencerTest() validatorConfig.BlockValidator.Enable = true validatorConfig.DataAvailability = l1NodeConfigA.DataAvailability validatorConfig.DataAvailability.RPCAggregator.Enable = false AddDefaultValNode(t, ctx, validatorConfig, !arbitrator) - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, validatorConfig, nil, nil) - defer nodeB.StopAndWait() - l2info.GenerateAccount("User2") + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: validatorConfig}) + defer cleanupB() + builder.L2Info.GenerateAccount("User2") perTransfer := big.NewInt(1e12) @@ -73,7 +76,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops var tx *types.Transaction if workload == ethSend { - tx = l2info.PrepareTx("Owner", "User2", l2info.TransferGas, perTransfer, nil) + tx = builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, perTransfer, nil) } else { var contractCode []byte var gas uint64 @@ -87,10 +90,10 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops contractCode = append(contractCode, byte(vm.CODECOPY)) contractCode = append(contractCode, byte(vm.PUSH0)) contractCode = append(contractCode, byte(vm.RETURN)) - basefee := GetBaseFee(t, l2client, ctx) + basefee := builder.L2.GetBaseFee(t) var err error - gas, err = l2client.EstimateGas(ctx, ethereum.CallMsg{ - From: l2info.GetAddress("Owner"), + gas, err = builder.L2.Client.EstimateGas(ctx, ethereum.CallMsg{ + From: builder.L2Info.GetAddress("Owner"), GasPrice: basefee, Value: big.NewInt(0), Data: contractCode, @@ -102,14 +105,14 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops contractCode = append(contractCode, 0x60, 0x00, 0x60, 0x00, 0x52) // PUSH1 0 MSTORE } contractCode = append(contractCode, 0x60, 0x00, 0x56) // JUMP - gas = l2info.TransferGas*2 + l2pricing.InitialPerBlockGasLimitV6 + gas = builder.L2Info.TransferGas*2 + l2pricing.InitialPerBlockGasLimitV6 } - tx = l2info.PrepareTxTo("Owner", nil, gas, common.Big0, contractCode) + tx = builder.L2Info.PrepareTxTo("Owner", nil, gas, common.Big0, contractCode) } - err := l2client.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceededWithTimeout(ctx, l2client, tx, time.Second*5) + _, err = builder.L2.EnsureTxSucceeded(tx) if workload != depleteGas { Require(t, err) } @@ -118,49 +121,49 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops } } } else { - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) // make auth a chain owner - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), builder.L2.Client) Require(t, err) tx, err := arbDebug.BecomeChainOwner(&auth) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), l2client) + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), builder.L2.Client) Require(t, err) tx, err = arbOwner.ScheduleArbOSUpgrade(&auth, 11, 0) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - tx = l2info.PrepareTxTo("Owner", nil, l2info.TransferGas, perTransfer, []byte{byte(vm.PUSH0)}) - err = l2client.SendTransaction(ctx, tx) + tx = builder.L2Info.PrepareTxTo("Owner", nil, builder.L2Info.TransferGas, perTransfer, []byte{byte(vm.PUSH0)}) + err = builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceededWithTimeout(ctx, l2client, tx, time.Second*5) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) } if workload != depleteGas { - delayedTx := l2info.PrepareTx("Owner", "User2", 30002, perTransfer, nil) - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - WrapL2ForDelayed(t, delayedTx, l1info, "User", 100000), + delayedTx := builder.L2Info.PrepareTx("Owner", "User2", 30002, perTransfer, nil) + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + WrapL2ForDelayed(t, delayedTx, builder.L1Info, "User", 100000), }) // give the inbox reader a bit of time to pick up the delayed message time.Sleep(time.Millisecond * 500) // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } - _, err := WaitForTx(ctx, l2clientB, delayedTx.Hash(), time.Second*5) + _, err := WaitForTx(ctx, testClientB.Client, delayedTx.Hash(), time.Second*5) Require(t, err) } if workload == ethSend { - l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) expectedBalance := new(big.Int).Mul(perTransfer, big.NewInt(int64(workloadLoops+1))) @@ -169,7 +172,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops } } - lastBlock, err := l2clientB.BlockByNumber(ctx, nil) + lastBlock, err := testClientB.Client.BlockByNumber(ctx, nil) Require(t, err) for { usefulBlock := false @@ -182,22 +185,22 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops if usefulBlock { break } - lastBlock, err = l2clientB.BlockByHash(ctx, lastBlock.ParentHash()) + lastBlock, err = testClientB.Client.BlockByHash(ctx, lastBlock.ParentHash()) Require(t, err) } t.Log("waiting for block: ", lastBlock.NumberU64()) timeout := getDeadlineTimeout(t, time.Minute*10) // messageindex is same as block number here - if !nodeB.BlockValidator.WaitForPos(t, ctx, arbutil.MessageIndex(lastBlock.NumberU64()), timeout) { + if !testClientB.ConsensusNode.BlockValidator.WaitForPos(t, ctx, arbutil.MessageIndex(lastBlock.NumberU64()), timeout) { Fatal(t, "did not validate all blocks") } - gethExec, ok := nodeB.Execution.(*gethexec.ExecutionNode) + gethExec, ok := testClientB.ConsensusNode.Execution.(*gethexec.ExecutionNode) if !ok { t.Fail() } gethExec.Recorder.TrimAllPrepared(t) finalRefCount := gethExec.Recorder.RecordingDBReferenceCount() - lastBlockNow, err := l2clientB.BlockByNumber(ctx, nil) + lastBlockNow, err := testClientB.Client.BlockByNumber(ctx, nil) Require(t, err) // up to 3 extra references: awaiting validation, recently valid, lastValidatedHeader largestRefCount := lastBlockNow.NumberU64() - lastBlock.NumberU64() + 3 diff --git a/system_tests/bloom_test.go b/system_tests/bloom_test.go index 9079fd35f..a3cab748e 100644 --- a/system_tests/bloom_test.go +++ b/system_tests/bloom_test.go @@ -36,7 +36,7 @@ func TestBloom(t *testing.T) { ownerTxOpts := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) ownerTxOpts.Context = ctx - _, simple := deploySimple(t, ctx, ownerTxOpts, builder.L2.Client) + _, simple := builder.L2.DeploySimple(t, ownerTxOpts) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) @@ -64,7 +64,7 @@ func TestBloom(t *testing.T) { if sendNullEvent { tx, err = simple.EmitNullEvent(&ownerTxOpts) Require(t, err) - _, err = EnsureTxSucceeded(ctx, builder.L2.Client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) } @@ -75,7 +75,7 @@ func TestBloom(t *testing.T) { tx, err = simple.Increment(&ownerTxOpts) } Require(t, err) - _, err = EnsureTxSucceeded(ctx, builder.L2.Client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) if i%100 == 0 { t.Log("counts: ", i, "/", countsNum) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 41a3fd141..0d7cd2dfa 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -103,6 +103,10 @@ func (tc *TestClient) GetBalance(t *testing.T, account common.Address) *big.Int return GetBalance(t, tc.ctx, tc.Client, account) } +func (tc *TestClient) GetBaseFee(t *testing.T) *big.Int { + return GetBaseFee(t, tc.Client, tc.ctx) +} + func (tc *TestClient) GetBaseFeeAt(t *testing.T, blockNum *big.Int) *big.Int { return GetBaseFeeAt(t, tc.Client, tc.ctx, blockNum) } @@ -116,7 +120,11 @@ func (tc *TestClient) DeploySimple(t *testing.T, auth bind.TransactOpts) (common } func (tc *TestClient) EnsureTxSucceeded(transaction *types.Transaction) (*types.Receipt, error) { - return EnsureTxSucceeded(tc.ctx, tc.Client, transaction) + return tc.EnsureTxSucceededWithTimeout(transaction, time.Second*5) +} + +func (tc *TestClient) EnsureTxSucceededWithTimeout(transaction *types.Transaction, timeout time.Duration) (*types.Receipt, error) { + return EnsureTxSucceededWithTimeout(tc.ctx, tc.Client, transaction, timeout) } type NodeBuilder struct { @@ -169,13 +177,13 @@ func (b *NodeBuilder) Build(t *testing.T) func() { if b.withL1 { l1, l2 := NewTestClient(b.ctx), NewTestClient(b.ctx) b.L2Info, l2.ConsensusNode, l2.Client, l2.Stack, b.L1Info, l1.L1Backend, l1.Client, l1.Stack = - createTestNodeOnL1WithConfigImpl(t, b.ctx, b.isSequencer, b.nodeConfig, b.execConfig, b.chainConfig, b.l2StackConfig, b.L2Info) + createTestNodeWithL1(t, b.ctx, b.isSequencer, b.nodeConfig, b.execConfig, b.chainConfig, b.l2StackConfig, b.L2Info) b.L1, b.L2 = l1, l2 b.L1.cleanup = func() { requireClose(t, b.L1.Stack) } } else { l2 := NewTestClient(b.ctx) b.L2Info, l2.ConsensusNode, l2.Client = - CreateTestL2WithConfig(t, b.ctx, b.L2Info, b.nodeConfig, b.execConfig, b.takeOwnership) + createTestNode(t, b.ctx, b.L2Info, b.nodeConfig, b.execConfig, b.takeOwnership) b.L2 = l2 } b.L2.ExecNode = getExecNode(t, b.L2.ConsensusNode) @@ -702,34 +710,7 @@ func ClientForStack(t *testing.T, backend *node.Node) *ethclient.Client { } // Create and deploy L1 and arbnode for L2 -func createTestNodeOnL1( - t *testing.T, - ctx context.Context, - isSequencer bool, -) ( - l2info info, node *arbnode.Node, l2client *ethclient.Client, l1info info, - l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node, -) { - return createTestNodeOnL1WithConfig(t, ctx, isSequencer, nil, nil, nil, nil) -} - -func createTestNodeOnL1WithConfig( - t *testing.T, - ctx context.Context, - isSequencer bool, - nodeConfig *arbnode.Config, - execConfig *gethexec.Config, - chainConfig *params.ChainConfig, - stackConfig *node.Config, -) ( - l2info info, currentNode *arbnode.Node, l2client *ethclient.Client, l1info info, - l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node, -) { - l2info, currentNode, l2client, _, l1info, l1backend, l1client, l1stack = createTestNodeOnL1WithConfigImpl(t, ctx, isSequencer, nodeConfig, execConfig, chainConfig, stackConfig, nil) - return -} - -func createTestNodeOnL1WithConfigImpl( +func createTestNodeWithL1( t *testing.T, ctx context.Context, isSequencer bool, @@ -801,11 +782,7 @@ func createTestNodeOnL1WithConfigImpl( // L2 -Only. Enough for tests that needs no interface to L1 // Requires precompiles.AllowDebugPrecompiles = true -func CreateTestL2(t *testing.T, ctx context.Context) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { - return CreateTestL2WithConfig(t, ctx, nil, nil, nil, true) -} - -func CreateTestL2WithConfig( +func createTestNode( t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, execConfig *gethexec.Config, takeOwnership bool, ) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { if nodeConfig == nil { @@ -879,24 +856,6 @@ func Fatal(t *testing.T, printables ...interface{}) { testhelpers.FailImpl(t, printables...) } -func Create2ndNode( - t *testing.T, - ctx context.Context, - first *arbnode.Node, - l1stack *node.Node, - l1info *BlockchainTestInfo, - l2InitData *statetransfer.ArbosInitializationInfo, - dasConfig *das.DataAvailabilityConfig, -) (*ethclient.Client, *arbnode.Node) { - nodeConf := arbnode.ConfigDefaultL1NonSequencerTest() - if dasConfig == nil { - nodeConf.DataAvailability.Enable = false - } else { - nodeConf.DataAvailability = *dasConfig - } - return Create2ndNodeWithConfig(t, ctx, first, l1stack, l1info, l2InitData, nodeConf, nil, nil) -} - func Create2ndNodeWithConfig( t *testing.T, ctx context.Context, diff --git a/system_tests/contract_tx_test.go b/system_tests/contract_tx_test.go index d6c2eb5f3..56d79b36d 100644 --- a/system_tests/contract_tx_test.go +++ b/system_tests/contract_tx_test.go @@ -25,18 +25,20 @@ func TestContractTxDeploy(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, nil, false) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.takeOwnership = false + cleanup := builder.Build(t) + defer cleanup() from := common.HexToAddress("0x123412341234") - TransferBalanceTo(t, "Faucet", from, big.NewInt(1e18), l2info, client, ctx) + builder.L2.TransferBalanceTo(t, "Faucet", from, big.NewInt(1e18), builder.L2Info) for stateNonce := uint64(0); stateNonce < 2; stateNonce++ { - pos, err := node.TxStreamer.GetMessageCount() + pos, err := builder.L2.ConsensusNode.TxStreamer.GetMessageCount() Require(t, err) var delayedMessagesRead uint64 if pos > 0 { - lastMessage, err := node.TxStreamer.GetMessage(pos - 1) + lastMessage, err := builder.L2.ConsensusNode.TxStreamer.GetMessage(pos - 1) Require(t, err) delayedMessagesRead = lastMessage.DelayedMessagesRead } @@ -68,7 +70,7 @@ func TestContractTxDeploy(t *testing.T) { l2Msg = append(l2Msg, math.U256Bytes(contractTx.Value)...) l2Msg = append(l2Msg, contractTx.Data...) - err = node.TxStreamer.AddMessages(pos, true, []arbostypes.MessageWithMetadata{ + err = builder.L2.ConsensusNode.TxStreamer.AddMessages(pos, true, []arbostypes.MessageWithMetadata{ { Message: &arbostypes.L1IncomingMessage{ Header: &arbostypes.L1IncomingMessageHeader{ @@ -89,7 +91,7 @@ func TestContractTxDeploy(t *testing.T) { txHash := types.NewTx(contractTx).Hash() t.Log("made contract tx", contractTx, "with hash", txHash) - receipt, err := WaitForTx(ctx, client, txHash, time.Second*10) + receipt, err := WaitForTx(ctx, builder.L2.Client, txHash, time.Second*10) Require(t, err) if receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "Receipt has non-successful status", receipt.Status) @@ -102,7 +104,7 @@ func TestContractTxDeploy(t *testing.T) { t.Log("deployed contract", receipt.ContractAddress, "from address", from, "with nonce", stateNonce) stateNonce++ - code, err := client.CodeAt(ctx, receipt.ContractAddress, nil) + code, err := builder.L2.Client.CodeAt(ctx, receipt.ContractAddress, nil) Require(t, err) if !bytes.Equal(code, []byte{0xFE}) { Fatal(t, "expected contract", receipt.ContractAddress, "code of 0xFE but got", hex.EncodeToString(code)) diff --git a/system_tests/delayedinbox_test.go b/system_tests/delayedinbox_test.go index e48cb3702..ca3e7b599 100644 --- a/system_tests/delayedinbox_test.go +++ b/system_tests/delayedinbox_test.go @@ -38,16 +38,17 @@ func TestDelayInboxSimple(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() - l2info.GenerateAccount("User2") + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - delayedTx := l2info.PrepareTx("Owner", "User2", 50001, big.NewInt(1e6), nil) - SendSignedTxViaL1(t, ctx, l1info, l1client, l2client, delayedTx) + builder.L2Info.GenerateAccount("User2") - l2balance, err := l2client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + delayedTx := builder.L2Info.PrepareTx("Owner", "User2", 50001, big.NewInt(1e6), nil) + builder.L1.SendSignedTx(t, builder.L2.Client, delayedTx, builder.L1Info) + + l2balance, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e6)) != 0 { Fatal(t, "Unexpected balance:", l2balance) diff --git a/system_tests/delayedinboxlong_test.go b/system_tests/delayedinboxlong_test.go index b1c8ea361..7c57771f5 100644 --- a/system_tests/delayedinboxlong_test.go +++ b/system_tests/delayedinboxlong_test.go @@ -25,11 +25,11 @@ func TestDelayInboxLong(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, l2client, l1info, l1backend, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") fundsPerDelayed := int64(1000000) delayedMessages := int64(0) @@ -42,22 +42,22 @@ func TestDelayInboxLong(t *testing.T) { randNum := rand.Int() % messagesPerDelayed var l1tx *types.Transaction if randNum == 0 { - delayedTx := l2info.PrepareTx("Owner", "User2", 50001, big.NewInt(fundsPerDelayed), nil) - l1tx = WrapL2ForDelayed(t, delayedTx, l1info, "User", 100000) + delayedTx := builder.L2Info.PrepareTx("Owner", "User2", 50001, big.NewInt(fundsPerDelayed), nil) + l1tx = WrapL2ForDelayed(t, delayedTx, builder.L1Info, "User", 100000) lastDelayedMessage = delayedTx delayedMessages++ } else { - l1tx = l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) + l1tx = builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) } l1Txs = append(l1Txs, l1tx) } // adding multiple messages in the same AddLocal to get them in the same L1 block - errs := l1backend.TxPool().AddLocals(l1Txs) + errs := builder.L1.L1Backend.TxPool().AddLocals(l1Txs) for _, err := range errs { Require(t, err) } // Checking every tx is expensive, so we just check the last, assuming that the others succeeded too - _, err := EnsureTxSucceeded(ctx, l1client, l1Txs[len(l1Txs)-1]) + _, err := builder.L1.EnsureTxSucceeded(l1Txs[len(l1Txs)-1]) Require(t, err) } @@ -68,14 +68,14 @@ func TestDelayInboxLong(t *testing.T) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 100; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } - _, err := WaitForTx(ctx, l2client, lastDelayedMessage.Hash(), time.Second*5) + _, err := WaitForTx(ctx, builder.L2.Client, lastDelayedMessage.Hash(), time.Second*5) Require(t, err) - l2balance, err := l2client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(fundsPerDelayed*delayedMessages)) != 0 { Fatal(t, "Unexpected balance:", "balance", l2balance, "expected", fundsPerDelayed*delayedMessages) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index 9f2db62da..691b02a12 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -26,17 +26,18 @@ func TestDeploy(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) auth.GasMargin = 0 // don't adjust, we want to see if the estimate alone is sufficient - _, simple := deploySimple(t, ctx, auth, client) + _, simple := builder.L2.DeploySimple(t, auth) tx, err := simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) counter, err := simple.Counter(&bind.CallOpts{}) @@ -51,24 +52,25 @@ func TestEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) auth.GasMargin = 0 // don't adjust, we want to see if the estimate alone is sufficient gasPrice := big.NewInt(params.GWei / 10) // set the gas price - arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), client) + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), builder.L2.Client) Require(t, err, "could not deploy ArbOwner contract") tx, err := arbOwner.SetMinimumL2BaseFee(&auth, gasPrice) Require(t, err, "could not set L2 gas price") - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) // connect to arbGasInfo precompile - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), builder.L2.Client) Require(t, err, "could not deploy contract") // wait for price to come to equilibrium @@ -76,8 +78,8 @@ func TestEstimate(t *testing.T) { numTriesLeft := 20 for !equilibrated && numTriesLeft > 0 { // make an empty block to let the gas price update - l2info.GasPrice = new(big.Int).Mul(l2info.GasPrice, big.NewInt(2)) - TransferBalance(t, "Owner", "Owner", common.Big0, l2info, client, ctx) + builder.L2Info.GasPrice = new(big.Int).Mul(builder.L2Info.GasPrice, big.NewInt(2)) + builder.L2.TransferBalance(t, "Owner", "Owner", common.Big0, builder.L2Info) // check if the price has equilibrated _, _, _, _, _, setPrice, err := arbGasInfo.GetPricesInWei(&bind.CallOpts{}) @@ -91,22 +93,22 @@ func TestEstimate(t *testing.T) { Fatal(t, "L2 gas price did not converge", gasPrice) } - initialBalance, err := client.BalanceAt(ctx, auth.From, nil) + initialBalance, err := builder.L2.Client.BalanceAt(ctx, auth.From, nil) Require(t, err, "could not get balance") // deploy a test contract - _, tx, simple, err := mocksgen.DeploySimple(&auth, client) + _, tx, simple, err := mocksgen.DeploySimple(&auth, builder.L2.Client) Require(t, err, "could not deploy contract") - receipt, err := EnsureTxSucceeded(ctx, client, tx) + receipt, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) - header, err := client.HeaderByNumber(ctx, receipt.BlockNumber) + header, err := builder.L2.Client.HeaderByNumber(ctx, receipt.BlockNumber) Require(t, err, "could not get header") if header.BaseFee.Cmp(gasPrice) != 0 { Fatal(t, "Header has wrong basefee", header.BaseFee, gasPrice) } - balance, err := client.BalanceAt(ctx, auth.From, nil) + balance, err := builder.L2.Client.BalanceAt(ctx, auth.From, nil) Require(t, err, "could not get balance") expectedCost := receipt.GasUsed * gasPrice.Uint64() observedCost := initialBalance.Uint64() - balance.Uint64() @@ -116,7 +118,7 @@ func TestEstimate(t *testing.T) { tx, err = simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) counter, err := simple.Counter(&bind.CallOpts{}) @@ -131,11 +133,12 @@ func TestComponentEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() l1BaseFee := new(big.Int).Set(arbostypes.DefaultInitialL1BaseFee) - l2BaseFee := GetBaseFee(t, client, ctx) + l2BaseFee := builder.L2.GetBaseFee(t) colors.PrintGrey("l1 basefee ", l1BaseFee) colors.PrintGrey("l2 basefee ", l2BaseFee) @@ -144,10 +147,10 @@ func TestComponentEstimate(t *testing.T) { maxPriorityFeePerGas := big.NewInt(0) maxFeePerGas := arbmath.BigMulByUfrac(l2BaseFee, 3, 2) - l2info.GenerateAccount("User") - TransferBalance(t, "Owner", "User", userBalance, l2info, client, ctx) + builder.L2Info.GenerateAccount("User") + builder.L2.TransferBalance(t, "Owner", "User", userBalance, builder.L2Info) - from := l2info.GetAddress("User") + from := builder.L2Info.GetAddress("User") to := testhelpers.RandomAddress() gas := uint64(100000000) calldata := []byte{0x00, 0x12} @@ -171,7 +174,7 @@ func TestComponentEstimate(t *testing.T) { Value: value, Data: estimateCalldata, } - returnData, err := client.CallContract(ctx, msg, nil) + returnData, err := builder.L2.Client.CallContract(ctx, msg, nil) Require(t, err) outputs, err := nodeMethod.Outputs.Unpack(returnData) @@ -185,9 +188,8 @@ func TestComponentEstimate(t *testing.T) { baseFee, _ := outputs[2].(*big.Int) l1BaseFeeEstimate, _ := outputs[3].(*big.Int) - execNode := getExecNode(t, node) - tx := l2info.SignTxAs("User", &types.DynamicFeeTx{ - ChainID: execNode.ArbInterface.BlockChain().Config().ChainID, + tx := builder.L2Info.SignTxAs("User", &types.DynamicFeeTx{ + ChainID: builder.L2.ExecNode.ArbInterface.BlockChain().Config().ChainID, Nonce: 0, GasTipCap: maxPriorityFeePerGas, GasFeeCap: maxFeePerGas, @@ -208,8 +210,8 @@ func TestComponentEstimate(t *testing.T) { Fatal(t, baseFee, l2BaseFee.Uint64()) } - Require(t, client.SendTransaction(ctx, tx)) - receipt, err := EnsureTxSucceeded(ctx, client, tx) + Require(t, builder.L2.Client.SendTransaction(ctx, tx)) + receipt, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) l2Used := receipt.GasUsed - receipt.GasUsedForL1 @@ -224,14 +226,15 @@ func TestDisableL1Charging(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() addr := common.HexToAddress("0x12345678") - gasWithL1Charging, err := client.EstimateGas(ctx, ethereum.CallMsg{To: &addr}) + gasWithL1Charging, err := builder.L2.Client.EstimateGas(ctx, ethereum.CallMsg{To: &addr}) Require(t, err) - gasWithoutL1Charging, err := client.EstimateGas(ctx, ethereum.CallMsg{To: &addr, SkipL1Charging: true}) + gasWithoutL1Charging, err := builder.L2.Client.EstimateGas(ctx, ethereum.CallMsg{To: &addr, SkipL1Charging: true}) Require(t, err) if gasWithL1Charging <= gasWithoutL1Charging { @@ -241,14 +244,14 @@ func TestDisableL1Charging(t *testing.T) { Fatal(t, "Incorrect gas estimate with disabled L1 charging") } - _, err = client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithL1Charging}, nil) + _, err = builder.L2.Client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithL1Charging}, nil) Require(t, err) - _, err = client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging}, nil) + _, err = builder.L2.Client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging}, nil) if err == nil { Fatal(t, "CallContract passed with insufficient gas") } - _, err = client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging, SkipL1Charging: true}, nil) + _, err = builder.L2.Client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging, SkipL1Charging: true}, nil) Require(t, err) } diff --git a/system_tests/fees_test.go b/system_tests/fees_test.go index 17ab7b69c..3ac5b29b0 100644 --- a/system_tests/fees_test.go +++ b/system_tests/fees_test.go @@ -53,7 +53,7 @@ func TestSequencerFeePaid(t *testing.T) { l1Estimate, err := arbGasInfo.GetL1BaseFeeEstimate(callOpts) Require(t, err) - baseFee := GetBaseFee(t, builder.L2.Client, ctx) + baseFee := builder.L2.GetBaseFee(t) builder.L2Info.GasPrice = baseFee testFees := func(tip uint64) (*big.Int, *big.Int) { diff --git a/system_tests/infra_fee_test.go b/system_tests/infra_fee_test.go index a56e05456..9366fc204 100644 --- a/system_tests/infra_fee_test.go +++ b/system_tests/infra_fee_test.go @@ -23,45 +23,46 @@ func TestInfraFee(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, nil, true) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) + ownerTxOpts := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) ownerTxOpts.Context = ctx - ownerCallOpts := l2info.GetDefaultCallOpts("Owner", ctx) + ownerCallOpts := builder.L2Info.GetDefaultCallOpts("Owner", ctx) - arbowner, err := precompilesgen.NewArbOwner(common.HexToAddress("70"), client) + arbowner, err := precompilesgen.NewArbOwner(common.HexToAddress("70"), builder.L2.Client) Require(t, err) - arbownerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("6b"), client) + arbownerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("6b"), builder.L2.Client) Require(t, err) networkFeeAddr, err := arbownerPublic.GetNetworkFeeAccount(ownerCallOpts) Require(t, err) infraFeeAddr := common.BytesToAddress(crypto.Keccak256([]byte{3, 2, 6})) tx, err := arbowner.SetInfraFeeAccount(&ownerTxOpts, infraFeeAddr) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - _, simple := deploySimple(t, ctx, ownerTxOpts, client) + _, simple := builder.L2.DeploySimple(t, ownerTxOpts) - netFeeBalanceBefore, err := client.BalanceAt(ctx, networkFeeAddr, nil) + netFeeBalanceBefore, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - infraFeeBalanceBefore, err := client.BalanceAt(ctx, infraFeeAddr, nil) + infraFeeBalanceBefore, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) tx, err = simple.Increment(&ownerTxOpts) Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, client, tx) + receipt, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) l2GasUsed := receipt.GasUsed - receipt.GasUsedForL1 expectedFunds := arbmath.BigMulByUint(arbmath.UintToBig(l2pricing.InitialBaseFeeWei), l2GasUsed) expectedBalanceAfter := arbmath.BigAdd(infraFeeBalanceBefore, expectedFunds) - netFeeBalanceAfter, err := client.BalanceAt(ctx, networkFeeAddr, nil) + netFeeBalanceAfter, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - infraFeeBalanceAfter, err := client.BalanceAt(ctx, infraFeeAddr, nil) + infraFeeBalanceAfter, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) if !arbmath.BigEquals(netFeeBalanceBefore, netFeeBalanceAfter) { diff --git a/system_tests/initialization_test.go b/system_tests/initialization_test.go index 0e055adc5..6707df1c6 100644 --- a/system_tests/initialization_test.go +++ b/system_tests/initialization_test.go @@ -62,14 +62,16 @@ func TestInitContract(t *testing.T) { l2info.ArbInitData.Accounts = append(l2info.ArbInitData.Accounts, accountInfo) expectedSums[accountAddress] = sum } - _, node, client := CreateTestL2WithConfig(t, ctx, l2info, nil, nil, true) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.L2Info = l2info + cleanup := builder.Build(t) + defer cleanup() for accountAddress, sum := range expectedSums { msg := ethereum.CallMsg{ To: &accountAddress, } - res, err := client.CallContract(ctx, msg, big.NewInt(0)) + res, err := builder.L2.Client.CallContract(ctx, msg, big.NewInt(0)) Require(t, err) resBig := new(big.Int).SetBytes(res) if resBig.Cmp(sum) != 0 { diff --git a/system_tests/log_subscription_test.go b/system_tests/log_subscription_test.go index 5ee1732fb..e4402533a 100644 --- a/system_tests/log_subscription_test.go +++ b/system_tests/log_subscription_test.go @@ -19,21 +19,22 @@ func TestLogSubscription(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) - arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, client) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, builder.L2.Client) Require(t, err) logChan := make(chan types.Log, 128) - subscription, err := client.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, logChan) + subscription, err := builder.L2.Client.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, logChan) Require(t, err) defer subscription.Unsubscribe() tx, err := arbSys.WithdrawEth(&auth, common.Address{}) Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, client, tx) + receipt, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) if len(receipt.Logs) != 1 { @@ -52,6 +53,6 @@ func TestLogSubscription(t *testing.T) { if !reflect.DeepEqual(receiptLog, subscriptionLog) { Fatal(t, "Receipt log", receiptLog, "is different than subscription log", subscriptionLog) } - _, err = client.BlockByHash(ctx, subscriptionLog.BlockHash) + _, err = builder.L2.Client.BlockByHash(ctx, subscriptionLog.BlockHash) Require(t, err) } diff --git a/system_tests/nodeinterface_test.go b/system_tests/nodeinterface_test.go index 167f2204c..40953a449 100644 --- a/system_tests/nodeinterface_test.go +++ b/system_tests/nodeinterface_test.go @@ -19,23 +19,23 @@ func TestL2BlockRangeForL1(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, l2client, l1info, _, _, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer node.StopAndWait() - user := l1info.GetDefaultTransactOpts("User", ctx) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() + user := builder.L1Info.GetDefaultTransactOpts("User", ctx) numTransactions := 200 for i := 0; i < numTransactions; i++ { - TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), l2info, l2client, ctx) + builder.L2.TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), builder.L2Info) } - nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, builder.L2.Client) if err != nil { t.Fatalf("Error creating node interface: %v", err) } l1BlockNums := map[uint64]*[2]uint64{} - latestL2, err := l2client.BlockNumber(ctx) + latestL2, err := builder.L2.Client.BlockNumber(ctx) if err != nil { t.Fatalf("Error querying most recent l2 block: %v", err) } diff --git a/system_tests/outbox_test.go b/system_tests/outbox_test.go index 6b43cc83b..d0ca0ccda 100644 --- a/system_tests/outbox_test.go +++ b/system_tests/outbox_test.go @@ -35,14 +35,15 @@ func TestOutboxProofs(t *testing.T) { withdrawTopic := arbSysAbi.Events["L2ToL1Tx"].ID merkleTopic := arbSysAbi.Events["SendMerkleUpdate"].ID - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) - arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, client) + arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, builder.L2.Client) Require(t, err) - nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, client) + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, builder.L2.Client) Require(t, err) txnCount := int64(1 + rand.Intn(16)) @@ -71,7 +72,7 @@ func TestOutboxProofs(t *testing.T) { txns = append(txns, tx.Hash()) time.Sleep(4 * time.Millisecond) // Geth takes a few ms for the receipt to show up - _, err = client.TransactionReceipt(ctx, tx.Hash()) + _, err = builder.L2.Client.TransactionReceipt(ctx, tx.Hash()) if err == nil { merkleState, err := arbSys.SendMerkleTreeState(&bind.CallOpts{}) Require(t, err, "could not get merkle root") @@ -86,7 +87,7 @@ func TestOutboxProofs(t *testing.T) { for _, tx := range txns { var receipt *types.Receipt - receipt, err = client.TransactionReceipt(ctx, tx) + receipt, err = builder.L2.Client.TransactionReceipt(ctx, tx) Require(t, err, "No receipt for txn") if receipt.Status != types.ReceiptStatusSuccessful { @@ -187,7 +188,7 @@ func TestOutboxProofs(t *testing.T) { // in one lookup, query geth for all the data we need to construct a proof var logs []types.Log if len(query) > 0 { - logs, err = client.FilterLogs(ctx, ethereum.FilterQuery{ + logs, err = builder.L2.Client.FilterLogs(ctx, ethereum.FilterQuery{ Addresses: []common.Address{ types.ArbSysAddress, }, diff --git a/system_tests/precompile_test.go b/system_tests/precompile_test.go index ad08ff747..10db09275 100644 --- a/system_tests/precompile_test.go +++ b/system_tests/precompile_test.go @@ -21,10 +21,11 @@ func TestPurePrecompileMethodCalls(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - arbSys, err := precompilesgen.NewArbSys(common.HexToAddress("0x64"), client) + arbSys, err := precompilesgen.NewArbSys(common.HexToAddress("0x64"), builder.L2.Client) Require(t, err, "could not deploy ArbSys contract") chainId, err := arbSys.ArbChainID(&bind.CallOpts{}) Require(t, err, "failed to get the ChainID") @@ -37,10 +38,11 @@ func TestViewLogReverts(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), builder.L2.Client) Require(t, err, "could not deploy ArbSys contract") err = arbDebug.EventsView(nil) @@ -53,11 +55,12 @@ func TestCustomSolidityErrors(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() callOpts := &bind.CallOpts{Context: ctx} - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), builder.L2.Client) Require(t, err, "could not bind ArbDebug contract") customError := arbDebug.CustomRevert(callOpts, 1024) if customError == nil { @@ -69,7 +72,7 @@ func TestCustomSolidityErrors(t *testing.T) { Fatal(t, observedMessage) } - arbSys, err := precompilesgen.NewArbSys(arbos.ArbSysAddress, client) + arbSys, err := precompilesgen.NewArbSys(arbos.ArbSysAddress, builder.L2.Client) Require(t, err, "could not bind ArbSys contract") _, customError = arbSys.ArbBlockHash(callOpts, big.NewInt(1e9)) if customError == nil { @@ -86,11 +89,12 @@ func TestPrecompileErrorGasLeft(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - auth := info.GetDefaultTransactOpts("Faucet", ctx) - _, _, simple, err := mocksgen.DeploySimple(&auth, client) + auth := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) + _, _, simple, err := mocksgen.DeploySimple(&auth, builder.L2.Client) Require(t, err) assertNotAllGasConsumed := func(to common.Address, input []byte) { diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index 285548dcd..9429155d7 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -23,26 +23,23 @@ import ( func prepareNodeWithHistory(t *testing.T, ctx context.Context, execConfig *gethexec.Config, txCount uint64) (node *arbnode.Node, executionNode *gethexec.ExecutionNode, l2client *ethclient.Client, cancel func()) { t.Helper() - l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, execConfig, nil, nil) - cancel = func() { - defer requireClose(t, l1stack) - defer node.StopAndWait() - } - l2info.GenerateAccount("User2") + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.execConfig = execConfig + cleanup := builder.Build(t) + builder.L2Info.GenerateAccount("User2") var txs []*types.Transaction for i := uint64(0); i < txCount; i++ { - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, common.Big1, nil) + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) txs = append(txs, tx) - err := l2client.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) } for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, l2client, tx) + _, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) } - exec := getExecNode(t, node) - return node, exec, l2client, cancel + return builder.L2.ConsensusNode, builder.L2.ExecNode, builder.L2.Client, cleanup } func fillHeaderCache(t *testing.T, bc *core.BlockChain, from, to uint64) { diff --git a/system_tests/reorg_resequencing_test.go b/system_tests/reorg_resequencing_test.go index bdd4c4af4..fcc6603ae 100644 --- a/system_tests/reorg_resequencing_test.go +++ b/system_tests/reorg_resequencing_test.go @@ -19,29 +19,28 @@ func TestReorgResequencing(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - execNode := getExecNode(t, node) - - startMsgCount, err := node.TxStreamer.GetMessageCount() + startMsgCount, err := builder.L2.ConsensusNode.TxStreamer.GetMessageCount() Require(t, err) - l2info.GenerateAccount("Intermediate") - l2info.GenerateAccount("User1") - l2info.GenerateAccount("User2") - l2info.GenerateAccount("User3") - l2info.GenerateAccount("User4") - TransferBalance(t, "Owner", "User1", big.NewInt(params.Ether), l2info, client, ctx) - TransferBalance(t, "Owner", "Intermediate", big.NewInt(params.Ether*3), l2info, client, ctx) - TransferBalance(t, "Intermediate", "User2", big.NewInt(params.Ether), l2info, client, ctx) - TransferBalance(t, "Intermediate", "User3", big.NewInt(params.Ether), l2info, client, ctx) + builder.L2Info.GenerateAccount("Intermediate") + builder.L2Info.GenerateAccount("User1") + builder.L2Info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User3") + builder.L2Info.GenerateAccount("User4") + builder.L2.TransferBalance(t, "Owner", "User1", big.NewInt(params.Ether), builder.L2Info) + builder.L2.TransferBalance(t, "Owner", "Intermediate", big.NewInt(params.Ether*3), builder.L2Info) + builder.L2.TransferBalance(t, "Intermediate", "User2", big.NewInt(params.Ether), builder.L2Info) + builder.L2.TransferBalance(t, "Intermediate", "User3", big.NewInt(params.Ether), builder.L2Info) // Intermediate does not have exactly 1 ether because of fees accountsWithBalance := []string{"User1", "User2", "User3"} verifyBalances := func(scenario string) { for _, account := range accountsWithBalance { - balance, err := client.BalanceAt(ctx, l2info.GetAddress(account), nil) + balance, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress(account), nil) Require(t, err) if balance.Int64() != params.Ether { Fatal(t, "expected account", account, "to have a balance of 1 ether but instead it has", balance, "wei "+scenario) @@ -50,15 +49,15 @@ func TestReorgResequencing(t *testing.T) { } verifyBalances("before reorg") - err = node.TxStreamer.ReorgTo(startMsgCount) + err = builder.L2.ConsensusNode.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = execNode.ExecEngine.HeadMessageNumberSync(t) + _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t) Require(t, err) verifyBalances("after empty reorg") - prevMessage, err := node.TxStreamer.GetMessage(startMsgCount - 1) + prevMessage, err := builder.L2.ConsensusNode.TxStreamer.GetMessage(startMsgCount - 1) Require(t, err) delayedIndexHash := common.BigToHash(big.NewInt(int64(prevMessage.DelayedMessagesRead))) newMessage := &arbostypes.L1IncomingMessage{ @@ -70,24 +69,24 @@ func TestReorgResequencing(t *testing.T) { RequestId: &delayedIndexHash, L1BaseFee: common.Big0, }, - L2msg: append(l2info.GetAddress("User4").Bytes(), math.U256Bytes(big.NewInt(params.Ether))...), + L2msg: append(builder.L2Info.GetAddress("User4").Bytes(), math.U256Bytes(big.NewInt(params.Ether))...), } - err = node.TxStreamer.AddMessages(startMsgCount, true, []arbostypes.MessageWithMetadata{{ + err = builder.L2.ConsensusNode.TxStreamer.AddMessages(startMsgCount, true, []arbostypes.MessageWithMetadata{{ Message: newMessage, DelayedMessagesRead: prevMessage.DelayedMessagesRead + 1, }}) Require(t, err) - _, err = execNode.ExecEngine.HeadMessageNumberSync(t) + _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t) Require(t, err) accountsWithBalance = append(accountsWithBalance, "User4") verifyBalances("after reorg with new deposit") - err = node.TxStreamer.ReorgTo(startMsgCount) + err = builder.L2.ConsensusNode.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = execNode.ExecEngine.HeadMessageNumberSync(t) + _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t) Require(t, err) verifyBalances("after second empty reorg") diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 0fc6d24ed..3400af335 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -14,16 +14,15 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/arbos/arbostypes" + "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbos/retryables" "github.com/offchainlabs/nitro/arbos/util" "github.com/offchainlabs/nitro/execution/gethexec" - "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/node_interfacegen" @@ -33,25 +32,23 @@ import ( ) func retryableSetup(t *testing.T) ( - *BlockchainTestInfo, - *BlockchainTestInfo, - *ethclient.Client, - *ethclient.Client, + *NodeBuilder, *bridgegen.Inbox, func(*types.Receipt) *types.Transaction, context.Context, func(), ) { ctx, cancel := context.WithCancel(context.Background()) - l2info, l2node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.Build(t) - l2info.GenerateAccount("User2") - l2info.GenerateAccount("Beneficiary") - l2info.GenerateAccount("Burn") + builder.L2Info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("Beneficiary") + builder.L2Info.GenerateAccount("Burn") - delayedInbox, err := bridgegen.NewInbox(l1info.GetAddress("Inbox"), l1client) + delayedInbox, err := bridgegen.NewInbox(builder.L1Info.GetAddress("Inbox"), builder.L1.Client) Require(t, err) - delayedBridge, err := arbnode.NewDelayedBridge(l1client, l1info.GetAddress("Bridge"), 0) + delayedBridge, err := arbnode.NewDelayedBridge(builder.L1.Client, builder.L1Info.GetAddress("Bridge"), 0) Require(t, err) lookupL2Tx := func(l1Receipt *types.Receipt) *types.Transaction { @@ -91,15 +88,15 @@ func retryableSetup(t *testing.T) ( // burn some gas so that the faucet's Callvalue + Balance never exceeds a uint256 discard := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - TransferBalance(t, "Faucet", "Burn", discard, l2info, l2client, ctx) + builder.L2.TransferBalance(t, "Faucet", "Burn", discard, builder.L2Info) teardown := func() { // check the integrity of the RPC - blockNum, err := l2client.BlockNumber(ctx) + blockNum, err := builder.L2.Client.BlockNumber(ctx) Require(t, err, "failed to get L2 block number") for number := uint64(0); number < blockNum; number++ { - block, err := l2client.BlockByNumber(ctx, arbmath.UintToBig(number)) + block, err := builder.L2.Client.BlockByNumber(ctx, arbmath.UintToBig(number)) Require(t, err, "failed to get L2 block", number, "of", blockNum) if block.Number().Uint64() != number { Fatal(t, "block number mismatch", number, block.Number().Uint64()) @@ -108,19 +105,20 @@ func retryableSetup(t *testing.T) ( cancel() - l2node.StopAndWait() - requireClose(t, l1stack) + builder.L2.ConsensusNode.StopAndWait() + requireClose(t, builder.L1.Stack) } - return l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown + return builder, delayedInbox, lookupL2Tx, ctx, teardown } func TestRetryableNoExist(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, l2client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) + arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), builder.L2.Client) Require(t, err) _, err = arbRetryableTx.GetTimeout(&bind.CallOpts{}, common.Hash{}) if err.Error() != "execution reverted: error NoTicketWithID()" { @@ -130,20 +128,20 @@ func TestRetryableNoExist(t *testing.T) { func TestSubmitRetryableImmediateSuccess(t *testing.T) { t.Parallel() - l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - user2Address := l2info.GetAddress("User2") - beneficiaryAddress := l2info.GetAddress("Beneficiary") + user2Address := builder.L2Info.GetAddress("User2") + beneficiaryAddress := builder.L2Info.GetAddress("Beneficiary") deposit := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) callValue := big.NewInt(1e6) - nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, builder.L2.Client) Require(t, err, "failed to deploy NodeInterface") // estimate the gas needed to auto redeem the retryable - usertxoptsL2 := l2info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL2 := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL2.NoSend = true usertxoptsL2.GasMargin = 0 tx, err := nodeInterface.EstimateRetryableTicket( @@ -161,7 +159,7 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { colors.PrintBlue("estimate: ", estimate) // submit & auto redeem the retryable using the gas estimate - usertxoptsL1 := l1info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL1 := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL1.Value = deposit l1tx, err := delayedInbox.CreateRetryableTicket( &usertxoptsL1, @@ -176,21 +174,21 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := builder.L1.EnsureTxSucceeded(l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, builder) - receipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) + receipt, err := builder.L2.EnsureTxSucceeded(lookupL2Tx(l1Receipt)) Require(t, err) if receipt.Status != types.ReceiptStatusSuccessful { Fatal(t) } - l2balance, err := l2client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if !arbmath.BigEquals(l2balance, big.NewInt(1e6)) { @@ -200,18 +198,18 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { func TestSubmitRetryableFailThenRetry(t *testing.T) { t.Parallel() - l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) - usertxopts := l1info.GetDefaultTransactOpts("Faucet", ctx) + ownerTxOpts := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + usertxopts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxopts.Value = arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - simpleAddr, simple := deploySimple(t, ctx, ownerTxOpts, l2client) + simpleAddr, simple := builder.L2.DeploySimple(t, ownerTxOpts) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) - beneficiaryAddress := l2info.GetAddress("Beneficiary") + beneficiaryAddress := builder.L2Info.GetAddress("Beneficiary") l1tx, err := delayedInbox.CreateRetryableTicket( &usertxopts, simpleAddr, @@ -226,15 +224,15 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := builder.L1.EnsureTxSucceeded(l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, builder) - receipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) + receipt, err := builder.L2.EnsureTxSucceeded(lookupL2Tx(l1Receipt)) Require(t, err) if len(receipt.Logs) != 2 { Fatal(t, len(receipt.Logs)) @@ -243,23 +241,23 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { firstRetryTxId := receipt.Logs[1].Topics[2] // get receipt for the auto redeem, make sure it failed - receipt, err = WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) + receipt, err = WaitForTx(ctx, builder.L2.Client, firstRetryTxId, time.Second*5) Require(t, err) if receipt.Status != types.ReceiptStatusFailed { Fatal(t, receipt.GasUsed) } - arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) + arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), builder.L2.Client) Require(t, err) tx, err := arbRetryableTx.Redeem(&ownerTxOpts, ticketId) Require(t, err) - receipt, err = EnsureTxSucceeded(ctx, l2client, tx) + receipt, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) retryTxId := receipt.Logs[0].Topics[2] // check the receipt for the retry - receipt, err = WaitForTx(ctx, l2client, retryTxId, time.Second*1) + receipt, err = WaitForTx(ctx, builder.L2.Client, retryTxId, time.Second*1) Require(t, err) if receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, receipt.Status) @@ -289,32 +287,32 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { func TestSubmissionGasCosts(t *testing.T) { t.Parallel() - l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, l2client, l2info) - elevateL2Basefee(t, ctx, l2client, l2info) + infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, builder) + elevateL2Basefee(t, ctx, builder) - usertxopts := l1info.GetDefaultTransactOpts("Faucet", ctx) + usertxopts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxopts.Value = arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - l2info.GenerateAccount("Refund") - l2info.GenerateAccount("Receive") - faucetAddress := util.RemapL1Address(l1info.GetAddress("Faucet")) - beneficiaryAddress := l2info.GetAddress("Beneficiary") - feeRefundAddress := l2info.GetAddress("Refund") - receiveAddress := l2info.GetAddress("Receive") + builder.L2Info.GenerateAccount("Refund") + builder.L2Info.GenerateAccount("Receive") + faucetAddress := util.RemapL1Address(builder.L1Info.GetAddress("Faucet")) + beneficiaryAddress := builder.L2Info.GetAddress("Beneficiary") + feeRefundAddress := builder.L2Info.GetAddress("Refund") + receiveAddress := builder.L2Info.GetAddress("Receive") colors.PrintBlue("Faucet ", faucetAddress) colors.PrintBlue("Receive ", receiveAddress) colors.PrintBlue("Beneficiary ", beneficiaryAddress) colors.PrintBlue("Fee Refund ", feeRefundAddress) - fundsBeforeSubmit, err := l2client.BalanceAt(ctx, faucetAddress, nil) + fundsBeforeSubmit, err := builder.L2.Client.BalanceAt(ctx, faucetAddress, nil) Require(t, err) - infraBalanceBefore, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceBefore, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceBefore, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceBefore, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) usefulGas := params.TxGas @@ -338,28 +336,28 @@ func TestSubmissionGasCosts(t *testing.T) { ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := builder.L1.EnsureTxSucceeded(l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, builder) submissionTxOuter := lookupL2Tx(l1Receipt) - submissionReceipt, err := EnsureTxSucceeded(ctx, l2client, submissionTxOuter) + submissionReceipt, err := builder.L2.EnsureTxSucceeded(submissionTxOuter) Require(t, err) if len(submissionReceipt.Logs) != 2 { Fatal(t, "Unexpected number of logs:", len(submissionReceipt.Logs)) } firstRetryTxId := submissionReceipt.Logs[1].Topics[2] // get receipt for the auto redeem - redeemReceipt, err := WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) + redeemReceipt, err := WaitForTx(ctx, builder.L2.Client, firstRetryTxId, time.Second*5) Require(t, err) if redeemReceipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "first retry tx failed") } - redeemBlock, err := l2client.HeaderByNumber(ctx, redeemReceipt.BlockNumber) + redeemBlock, err := builder.L2.Client.HeaderByNumber(ctx, redeemReceipt.BlockNumber) Require(t, err) l2BaseFee := redeemBlock.BaseFee @@ -367,18 +365,18 @@ func TestSubmissionGasCosts(t *testing.T) { excessWei := arbmath.BigMulByUint(l2BaseFee, excessGasLimit) excessWei.Add(excessWei, arbmath.BigMul(excessGasPrice, retryableGas)) - fundsAfterSubmit, err := l2client.BalanceAt(ctx, faucetAddress, nil) + fundsAfterSubmit, err := builder.L2.Client.BalanceAt(ctx, faucetAddress, nil) Require(t, err) - beneficiaryFunds, err := l2client.BalanceAt(ctx, beneficiaryAddress, nil) + beneficiaryFunds, err := builder.L2.Client.BalanceAt(ctx, beneficiaryAddress, nil) Require(t, err) - refundFunds, err := l2client.BalanceAt(ctx, feeRefundAddress, nil) + refundFunds, err := builder.L2.Client.BalanceAt(ctx, feeRefundAddress, nil) Require(t, err) - receiveFunds, err := l2client.BalanceAt(ctx, receiveAddress, nil) + receiveFunds, err := builder.L2.Client.BalanceAt(ctx, receiveAddress, nil) Require(t, err) - infraBalanceAfter, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceAfter, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceAfter, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceAfter, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) colors.PrintBlue("CallGas ", retryableGas) @@ -425,7 +423,7 @@ func TestSubmissionGasCosts(t *testing.T) { Fatal(t, "Supplied gas was improperly deducted\n", fundsBeforeSubmit, "\n", fundsAfterSubmit) } - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), builder.L2.Client) Require(t, err) minimumBaseFee, err := arbGasInfo.GetMinimumGasPrice(&bind.CallOpts{Context: ctx}) Require(t, err) @@ -450,28 +448,28 @@ func TestSubmissionGasCosts(t *testing.T) { } } -func waitForL1DelayBlocks(t *testing.T, ctx context.Context, l1client *ethclient.Client, l1info *BlockchainTestInfo) { +func waitForL1DelayBlocks(t *testing.T, ctx context.Context, builder *NodeBuilder) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } } func TestDepositETH(t *testing.T) { t.Parallel() - _, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - faucetAddr := l1info.GetAddress("Faucet") + faucetAddr := builder.L1Info.GetAddress("Faucet") - oldBalance, err := l2client.BalanceAt(ctx, faucetAddr, nil) + oldBalance, err := builder.L2.Client.BalanceAt(ctx, faucetAddr, nil) if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", faucetAddr, err) } - txOpts := l1info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) txOpts.Value = big.NewInt(13) l1tx, err := delayedInbox.DepositEth0(&txOpts) @@ -479,20 +477,20 @@ func TestDepositETH(t *testing.T) { t.Fatalf("DepositEth0() unexected error: %v", err) } - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := builder.L1.EnsureTxSucceeded(l1tx) if err != nil { t.Fatalf("EnsureTxSucceeded() unexpected error: %v", err) } if l1Receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("Got transaction status: %v, want: %v", l1Receipt.Status, types.ReceiptStatusSuccessful) } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, builder) - l2Receipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) + l2Receipt, err := builder.L2.EnsureTxSucceeded(lookupL2Tx(l1Receipt)) if err != nil { t.Fatalf("EnsureTxSucceeded unexpected error: %v", err) } - newBalance, err := l2client.BalanceAt(ctx, faucetAddr, l2Receipt.BlockNumber) + newBalance, err := builder.L2.Client.BalanceAt(ctx, faucetAddr, l2Receipt.BlockNumber) if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", faucetAddr, err) } @@ -502,13 +500,13 @@ func TestDepositETH(t *testing.T) { } func TestArbitrumContractTx(t *testing.T) { - l2Info, l1Info, l2Client, l1Client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - faucetL2Addr := util.RemapL1Address(l1Info.GetAddress("Faucet")) - TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), l2Info, l2Client, ctx) + faucetL2Addr := util.RemapL1Address(builder.L1Info.GetAddress("Faucet")) + builder.L2.TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), builder.L2Info) - l2TxOpts := l2Info.GetDefaultTransactOpts("Faucet", ctx) - l2ContractAddr, _ := deploySimple(t, ctx, l2TxOpts, l2Client) + l2TxOpts := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) + l2ContractAddr, _ := builder.L2.DeploySimple(t, l2TxOpts) l2ContractABI, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) if err != nil { t.Fatalf("Error parsing contract ABI: %v", err) @@ -518,15 +516,15 @@ func TestArbitrumContractTx(t *testing.T) { t.Fatalf("Error packing method's call data: %v", err) } unsignedTx := types.NewTx(&types.ArbitrumContractTx{ - ChainId: l2Info.Signer.ChainID(), + ChainId: builder.L2Info.Signer.ChainID(), From: faucetL2Addr, - GasFeeCap: l2Info.GasPrice.Mul(l2Info.GasPrice, big.NewInt(2)), + GasFeeCap: builder.L2Info.GasPrice.Mul(builder.L2Info.GasPrice, big.NewInt(2)), Gas: 1e6, To: &l2ContractAddr, Value: common.Big0, Data: data, }) - txOpts := l1Info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) l1tx, err := delayedInbox.SendContractTransaction( &txOpts, arbmath.UintToBig(unsignedTx.Gas()), @@ -538,15 +536,15 @@ func TestArbitrumContractTx(t *testing.T) { if err != nil { t.Fatalf("Error sending unsigned transaction: %v", err) } - receipt, err := EnsureTxSucceeded(ctx, l1Client, l1tx) + receipt, err := builder.L1.EnsureTxSucceeded(l1tx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", l1tx.Hash(), err) } if receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("L1 transaction: %v has failed", l1tx.Hash()) } - waitForL1DelayBlocks(t, ctx, l1Client, l1Info) - receipt, err = EnsureTxSucceeded(ctx, l2Client, lookupL2Tx(receipt)) + waitForL1DelayBlocks(t, ctx, builder) + _, err = builder.L2.EnsureTxSucceeded(lookupL2Tx(receipt)) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", unsignedTx.Hash(), err) } @@ -555,17 +553,17 @@ func TestArbitrumContractTx(t *testing.T) { func TestL1FundedUnsignedTransaction(t *testing.T) { t.Parallel() ctx := context.Background() - l2Info, node, l2Client, l1Info, _, l1Client, l1Stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1Stack) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - faucetL2Addr := util.RemapL1Address(l1Info.GetAddress("Faucet")) + faucetL2Addr := util.RemapL1Address(builder.L1Info.GetAddress("Faucet")) // Transfer balance to Faucet's corresponding L2 address, so that there is // enough balance on its' account for executing L2 transaction. - TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), l2Info, l2Client, ctx) + builder.L2.TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), builder.L2Info) - l2TxOpts := l2Info.GetDefaultTransactOpts("Faucet", ctx) - contractAddr, _ := deploySimple(t, ctx, l2TxOpts, l2Client) + l2TxOpts := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) + contractAddr, _ := builder.L2.DeploySimple(t, l2TxOpts) contractABI, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) if err != nil { t.Fatalf("Error parsing contract ABI: %v", err) @@ -574,27 +572,27 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { if err != nil { t.Fatalf("Error packing method's call data: %v", err) } - nonce, err := l2Client.NonceAt(ctx, faucetL2Addr, nil) + nonce, err := builder.L2.Client.NonceAt(ctx, faucetL2Addr, nil) if err != nil { t.Fatalf("Error getting nonce at address: %v, error: %v", faucetL2Addr, err) } unsignedTx := types.NewTx(&types.ArbitrumUnsignedTx{ - ChainId: l2Info.Signer.ChainID(), + ChainId: builder.L2Info.Signer.ChainID(), From: faucetL2Addr, Nonce: nonce, - GasFeeCap: l2Info.GasPrice, + GasFeeCap: builder.L2Info.GasPrice, Gas: 1e6, To: &contractAddr, Value: common.Big0, Data: data, }) - delayedInbox, err := bridgegen.NewInbox(l1Info.GetAddress("Inbox"), l1Client) + delayedInbox, err := bridgegen.NewInbox(builder.L1Info.GetAddress("Inbox"), builder.L1.Client) if err != nil { t.Fatalf("Error getting Go binding of L1 Inbox contract: %v", err) } - txOpts := l1Info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) l1tx, err := delayedInbox.SendUnsignedTransaction( &txOpts, arbmath.UintToBig(unsignedTx.Gas()), @@ -607,15 +605,15 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { if err != nil { t.Fatalf("Error sending unsigned transaction: %v", err) } - receipt, err := EnsureTxSucceeded(ctx, l1Client, l1tx) + receipt, err := builder.L1.EnsureTxSucceeded(l1tx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", l1tx.Hash(), err) } if receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("L1 transaction: %v has failed", l1tx.Hash()) } - waitForL1DelayBlocks(t, ctx, l1Client, l1Info) - receipt, err = EnsureTxSucceeded(ctx, l2Client, unsignedTx) + waitForL1DelayBlocks(t, ctx, builder) + receipt, err = builder.L2.EnsureTxSucceeded(unsignedTx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", unsignedTx.Hash(), err) } @@ -625,28 +623,28 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { } func TestRetryableSubmissionAndRedeemFees(t *testing.T) { - l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, l2client, l2info) + infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, builder) - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) - simpleAddr, simple := deploySimple(t, ctx, ownerTxOpts, l2client) + ownerTxOpts := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + simpleAddr, simple := builder.L2.DeploySimple(t, ownerTxOpts) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) - elevateL2Basefee(t, ctx, l2client, l2info) + elevateL2Basefee(t, ctx, builder) - infraBalanceBefore, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceBefore, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceBefore, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceBefore, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - beneficiaryAddress := l2info.GetAddress("Beneficiary") + beneficiaryAddress := builder.L2Info.GetAddress("Beneficiary") deposit := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) callValue := common.Big0 - usertxoptsL1 := l1info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL1 := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL1.Value = deposit - baseFee := GetBaseFee(t, l2client, ctx) + baseFee := builder.L2.GetBaseFee(t) l1tx, err := delayedInbox.CreateRetryableTicket( &usertxoptsL1, simpleAddr, @@ -660,16 +658,16 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { simpleABI.Methods["incrementRedeem"].ID, ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := builder.L1.EnsureTxSucceeded(l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, builder) submissionTxOuter := lookupL2Tx(l1Receipt) - submissionReceipt, err := EnsureTxSucceeded(ctx, l2client, submissionTxOuter) + submissionReceipt, err := builder.L2.EnsureTxSucceeded(submissionTxOuter) Require(t, err) if len(submissionReceipt.Logs) != 2 { Fatal(t, len(submissionReceipt.Logs)) @@ -677,36 +675,36 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { ticketId := submissionReceipt.Logs[0].Topics[1] firstRetryTxId := submissionReceipt.Logs[1].Topics[2] // get receipt for the auto redeem, make sure it failed - autoRedeemReceipt, err := WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) + autoRedeemReceipt, err := WaitForTx(ctx, builder.L2.Client, firstRetryTxId, time.Second*5) Require(t, err) if autoRedeemReceipt.Status != types.ReceiptStatusFailed { Fatal(t, "first retry tx shouldn't have succeeded") } - infraBalanceAfterSubmission, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceAfterSubmission, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceAfterSubmission, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceAfterSubmission, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - usertxoptsL2 := l2info.GetDefaultTransactOpts("Faucet", ctx) - arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) + usertxoptsL2 := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) + arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), builder.L2.Client) Require(t, err) tx, err := arbRetryableTx.Redeem(&usertxoptsL2, ticketId) Require(t, err) - redeemReceipt, err := EnsureTxSucceeded(ctx, l2client, tx) + redeemReceipt, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) retryTxId := redeemReceipt.Logs[0].Topics[2] // check the receipt for the retry - retryReceipt, err := WaitForTx(ctx, l2client, retryTxId, time.Second*1) + retryReceipt, err := WaitForTx(ctx, builder.L2.Client, retryTxId, time.Second*1) Require(t, err) if retryReceipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "retry failed") } - infraBalanceAfterRedeem, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceAfterRedeem, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceAfterRedeem, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceAfterRedeem, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) // verify that the increment happened, so we know the retry succeeded @@ -735,11 +733,11 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { infraRedeemFee := arbmath.BigSub(infraBalanceAfterRedeem, infraBalanceAfterSubmission) networkRedeemFee := arbmath.BigSub(networkBalanceAfterRedeem, networkBalanceAfterSubmission) - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), builder.L2.Client) Require(t, err) minimumBaseFee, err := arbGasInfo.GetMinimumGasPrice(&bind.CallOpts{Context: ctx}) Require(t, err) - submissionBaseFee := GetBaseFeeAt(t, l2client, ctx, submissionReceipt.BlockNumber) + submissionBaseFee := builder.L2.GetBaseFeeAt(t, submissionReceipt.BlockNumber) submissionTx, ok := submissionTxOuter.GetInner().(*types.ArbitrumSubmitRetryableTx) if !ok { Fatal(t, "inner tx isn't ArbitrumSubmitRetryableTx") @@ -753,13 +751,13 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { retryableSubmissionFee, ) - retryTxOuter, _, err := l2client.TransactionByHash(ctx, retryTxId) + retryTxOuter, _, err := builder.L2.Client.TransactionByHash(ctx, retryTxId) Require(t, err) retryTx, ok := retryTxOuter.GetInner().(*types.ArbitrumRetryTx) if !ok { Fatal(t, "inner tx isn't ArbitrumRetryTx") } - redeemBaseFee := GetBaseFeeAt(t, l2client, ctx, redeemReceipt.BlockNumber) + redeemBaseFee := builder.L2.GetBaseFeeAt(t, redeemReceipt.BlockNumber) t.Log("redeem base fee:", redeemBaseFee) // redeem & retry expected fees @@ -795,59 +793,59 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { } // elevateL2Basefee by burning gas exceeding speed limit -func elevateL2Basefee(t *testing.T, ctx context.Context, l2client *ethclient.Client, l2info *BlockchainTestInfo) { - baseFeeBefore := GetBaseFee(t, l2client, ctx) +func elevateL2Basefee(t *testing.T, ctx context.Context, builder *NodeBuilder) { + baseFeeBefore := builder.L2.GetBaseFee(t) colors.PrintBlue("Elevating base fee...") arbostestabi, err := precompilesgen.ArbosTestMetaData.GetAbi() Require(t, err) - _, err = precompilesgen.NewArbosTest(common.HexToAddress("0x69"), l2client) + _, err = precompilesgen.NewArbosTest(common.HexToAddress("0x69"), builder.L2.Client) Require(t, err, "failed to deploy ArbosTest") burnAmount := gethexec.ConfigDefaultTest().RPC.RPCGasCap burnTarget := uint64(5 * l2pricing.InitialSpeedLimitPerSecondV6 * l2pricing.InitialBacklogTolerance) for i := uint64(0); i < (burnTarget+burnAmount)/burnAmount; i++ { burnArbGas := arbostestabi.Methods["burnArbGas"] - data, err := burnArbGas.Inputs.Pack(arbmath.UintToBig(burnAmount - l2info.TransferGas)) + data, err := burnArbGas.Inputs.Pack(arbmath.UintToBig(burnAmount - builder.L2Info.TransferGas)) Require(t, err) input := append([]byte{}, burnArbGas.ID...) input = append(input, data...) to := common.HexToAddress("0x69") - tx := l2info.PrepareTxTo("Faucet", &to, burnAmount, big.NewInt(0), input) - Require(t, l2client.SendTransaction(ctx, tx)) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + tx := builder.L2Info.PrepareTxTo("Faucet", &to, burnAmount, big.NewInt(0), input) + Require(t, builder.L2.Client.SendTransaction(ctx, tx)) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) } - baseFee := GetBaseFee(t, l2client, ctx) + baseFee := builder.L2.GetBaseFee(t) colors.PrintBlue("New base fee: ", baseFee, " diff:", baseFee.Uint64()-baseFeeBefore.Uint64()) } -func setupFeeAddresses(t *testing.T, ctx context.Context, l2client *ethclient.Client, l2info *BlockchainTestInfo) (common.Address, common.Address) { - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) - ownerCallOpts := l2info.GetDefaultCallOpts("Owner", ctx) +func setupFeeAddresses(t *testing.T, ctx context.Context, builder *NodeBuilder) (common.Address, common.Address) { + ownerTxOpts := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + ownerCallOpts := builder.L2Info.GetDefaultCallOpts("Owner", ctx) // make "Owner" a chain owner - arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) + arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), builder.L2.Client) Require(t, err, "failed to deploy ArbDebug") tx, err := arbdebug.BecomeChainOwner(&ownerTxOpts) Require(t, err, "failed to deploy ArbDebug") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - arbowner, err := precompilesgen.NewArbOwner(common.HexToAddress("70"), l2client) + arbowner, err := precompilesgen.NewArbOwner(common.HexToAddress("70"), builder.L2.Client) Require(t, err) - arbownerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("6b"), l2client) + arbownerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("6b"), builder.L2.Client) Require(t, err) - l2info.GenerateAccount("InfraFee") - l2info.GenerateAccount("NetworkFee") - networkFeeAddr := l2info.GetAddress("NetworkFee") - infraFeeAddr := l2info.GetAddress("InfraFee") + builder.L2Info.GenerateAccount("InfraFee") + builder.L2Info.GenerateAccount("NetworkFee") + networkFeeAddr := builder.L2Info.GetAddress("NetworkFee") + infraFeeAddr := builder.L2Info.GetAddress("InfraFee") tx, err = arbowner.SetNetworkFeeAccount(&ownerTxOpts, networkFeeAddr) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) networkFeeAccount, err := arbownerPublic.GetNetworkFeeAccount(ownerCallOpts) Require(t, err) tx, err = arbowner.SetInfraFeeAccount(&ownerTxOpts, infraFeeAddr) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) infraFeeAccount, err := arbownerPublic.GetInfraFeeAccount(ownerCallOpts) Require(t, err) diff --git a/system_tests/seq_coordinator_test.go b/system_tests/seq_coordinator_test.go index ac3167a60..886a0528c 100644 --- a/system_tests/seq_coordinator_test.go +++ b/system_tests/seq_coordinator_test.go @@ -56,7 +56,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { // stdio protocol makes sure forwarder initialization doesn't fail nodeNames := []string{"stdio://A", "stdio://B", "stdio://C", "stdio://D", "stdio://E"} - nodes := make([]*arbnode.Node, len(nodeNames)) + testNodes := make([]*TestClient, len(nodeNames)) // init DB to known state initRedisForTest(t, ctx, builder.nodeConfig.SeqCoordinator.RedisUrl, nodeNames) @@ -65,11 +65,11 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { builder.nodeConfig.SeqCoordinator.MyUrl = nodeNames[nodeNum] builder.L2Info = l2Info builder.Build(t) - nodes[nodeNum] = builder.L2.ConsensusNode + testNodes[nodeNum] = builder.L2 } trySequencing := func(nodeNum int) bool { - node := nodes[nodeNum] + node := testNodes[nodeNum].ConsensusNode curMsgs, err := node.TxStreamer.GetMessageCountSync(t) Require(t, err) emptyMessage := arbostypes.MessageWithMetadata{ @@ -98,14 +98,15 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { // node(n) has higher prio than node(n+1), so should be impossible for more than one to succeed trySequencingEverywhere := func() int { succeeded := -1 - for nodeNum, node := range nodes { + for nodeNum, testNode := range testNodes { + node := testNode.ConsensusNode if node == nil { continue } if trySequencing(nodeNum) { if succeeded >= 0 { t.Fatal("sequnced succeeded in parallel", - "index1:", succeeded, "debug", nodes[succeeded].SeqCoordinator.DebugPrint(), + "index1:", succeeded, "debug", testNodes[succeeded].ConsensusNode.SeqCoordinator.DebugPrint(), "index2:", nodeNum, "debug", node.SeqCoordinator.DebugPrint(), "now", time.Now().UnixMilli()) } @@ -116,7 +117,8 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { } waitForMsgEverywhere := func(msgNum arbutil.MessageIndex) { - for _, currentNode := range nodes { + for _, testNode := range testNodes { + currentNode := testNode.ConsensusNode if currentNode == nil { continue } @@ -137,16 +139,16 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { var needsStop []*arbnode.Node killNode := func(nodeNum int) { if nodeNum%3 == 0 { - nodes[nodeNum].SeqCoordinator.PrepareForShutdown() - needsStop = append(needsStop, nodes[nodeNum]) + testNodes[nodeNum].ConsensusNode.SeqCoordinator.PrepareForShutdown() + needsStop = append(needsStop, testNodes[nodeNum].ConsensusNode) } else { - nodes[nodeNum].StopAndWait() + testNodes[nodeNum].ConsensusNode.StopAndWait() } - nodes[nodeNum] = nil + testNodes[nodeNum].ConsensusNode = nil } nodeForwardTarget := func(nodeNum int) int { - execNode := getExecNode(t, nodes[nodeNum]) + execNode := testNodes[nodeNum].ExecNode fwTarget := execNode.TxPublisher.(*gethexec.TxPreChecker).TransactionPublisher.(*gethexec.Sequencer).ForwardTarget() if fwTarget == "" { return -1 @@ -178,7 +180,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { t.Log("Starting other nodes") - for i := 1; i < len(nodes); i++ { + for i := 1; i < len(testNodes); i++ { createStartNode(i) } @@ -189,7 +191,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { for { // all remaining nodes know which is the chosen one - for i := currentSequencer + 1; i < len(nodes); i++ { + for i := currentSequencer + 1; i < len(testNodes); i++ { for attempts := 1; nodeForwardTarget(i) != currentSequencer; attempts++ { if attempts > 10 { t.Fatal("initial forward target not set") @@ -206,7 +208,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { sequencedMesssages++ } - if currentSequencer == len(nodes)-1 { + if currentSequencer == len(testNodes)-1 { addNodes = true } if addNodes { @@ -258,7 +260,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { waitForMsgEverywhere(sequencedMesssages) } - for nodeNum := range nodes { + for nodeNum := range testNodes { killNode(nodeNum) } for _, node := range needsStop { @@ -282,7 +284,6 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { cleanup := builder.Build(t) defer cleanup() - clientA := builder.L2.Client redisClient, err := redisutil.RedisClientFromURL(builder.nodeConfig.SeqCoordinator.RedisUrl) Require(t, err) @@ -312,26 +313,25 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: builder.nodeConfig}) defer cleanupB() - clientB := testClientB.Client tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) - err = clientA.SendTransaction(ctx, tx) + err = builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, clientA, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) if successCase { - _, err = WaitForTx(ctx, clientB, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, testClientB.Client, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := clientB.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) + l2balance, err := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) } } else { - _, err = WaitForTx(ctx, clientB, tx.Hash(), time.Second) + _, err = WaitForTx(ctx, testClientB.Client, tx.Hash(), time.Second) if err == nil { Fatal(t, "tx received by node with different seq coordinator signing key") } diff --git a/system_tests/seq_nonce_test.go b/system_tests/seq_nonce_test.go index d70f47a14..f0e3dcffd 100644 --- a/system_tests/seq_nonce_test.go +++ b/system_tests/seq_nonce_test.go @@ -15,7 +15,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/arbmath" ) @@ -24,12 +23,13 @@ func TestSequencerParallelNonces(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - config := gethexec.ConfigDefaultTest() - config.Sequencer.NonceFailureCacheExpiry = time.Minute - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.takeOwnership = false + builder.execConfig.Sequencer.NonceFailureCacheExpiry = time.Minute + cleanup := builder.Build(t) + defer cleanup() - l2info.GenerateAccount("Destination") + builder.L2Info.GenerateAccount("Destination") wg := sync.WaitGroup{} for thread := 0; thread < 10; thread++ { @@ -37,11 +37,11 @@ func TestSequencerParallelNonces(t *testing.T) { go func() { defer wg.Done() for i := 0; i < 10; i++ { - tx := l2info.PrepareTx("Owner", "Destination", l2info.TransferGas, common.Big1, nil) + tx := builder.L2Info.PrepareTx("Owner", "Destination", builder.L2Info.TransferGas, common.Big1, nil) // Sleep a random amount of time up to 20 milliseconds time.Sleep(time.Millisecond * time.Duration(rand.Intn(20))) t.Log("Submitting transaction with nonce", tx.Nonce()) - err := client.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) t.Log("Got response for transaction with nonce", tx.Nonce()) } @@ -49,8 +49,8 @@ func TestSequencerParallelNonces(t *testing.T) { } wg.Wait() - addr := l2info.GetAddress("Destination") - balance, err := client.BalanceAt(ctx, addr, nil) + addr := builder.L2Info.GetAddress("Destination") + balance, err := builder.L2.Client.BalanceAt(ctx, addr, nil) Require(t, err) if !arbmath.BigEquals(balance, big.NewInt(100)) { Fatal(t, "Unexpected user balance", balance) @@ -62,15 +62,16 @@ func TestSequencerNonceTooHigh(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - config := gethexec.ConfigDefaultTest() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.takeOwnership = false + cleanup := builder.Build(t) + defer cleanup() - l2info.GetInfoWithPrivKey("Owner").Nonce++ + builder.L2Info.GetInfoWithPrivKey("Owner").Nonce++ before := time.Now() - tx := l2info.PrepareTx("Owner", "Owner", l2info.TransferGas, common.Big0, nil) - err := client.SendTransaction(ctx, tx) + tx := builder.L2Info.PrepareTx("Owner", "Owner", builder.L2Info.TransferGas, common.Big0, nil) + err := builder.L2.Client.SendTransaction(ctx, tx) if err == nil { Fatal(t, "No error when nonce was too high") } @@ -78,7 +79,7 @@ func TestSequencerNonceTooHigh(t *testing.T) { Fatal(t, "Unexpected transaction error", err) } elapsed := time.Since(before) - if elapsed > 2*config.Sequencer.NonceFailureCacheExpiry { + if elapsed > 2*builder.execConfig.Sequencer.NonceFailureCacheExpiry { Fatal(t, "Sequencer took too long to respond with nonce too high") } } @@ -88,19 +89,20 @@ func TestSequencerNonceTooHighQueueFull(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - config := gethexec.ConfigDefaultTest() - config.Sequencer.NonceFailureCacheSize = 5 - config.Sequencer.NonceFailureCacheExpiry = time.Minute - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.takeOwnership = false + builder.execConfig.Sequencer.NonceFailureCacheSize = 5 + builder.execConfig.Sequencer.NonceFailureCacheExpiry = time.Minute + cleanup := builder.Build(t) + defer cleanup() count := 15 var completed uint64 for i := 0; i < count; i++ { - l2info.GetInfoWithPrivKey("Owner").Nonce++ - tx := l2info.PrepareTx("Owner", "Owner", l2info.TransferGas, common.Big0, nil) + builder.L2Info.GetInfoWithPrivKey("Owner").Nonce++ + tx := builder.L2Info.PrepareTx("Owner", "Owner", builder.L2Info.TransferGas, common.Big0, nil) go func() { - err := client.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) if err == nil { Fatal(t, "No error when nonce was too high") } @@ -110,7 +112,7 @@ func TestSequencerNonceTooHighQueueFull(t *testing.T) { for wait := 9; wait >= 0; wait-- { got := int(atomic.LoadUint64(&completed)) - expected := count - config.Sequencer.NonceFailureCacheSize + expected := count - builder.execConfig.Sequencer.NonceFailureCacheSize if got == expected { break } diff --git a/system_tests/seq_pause_test.go b/system_tests/seq_pause_test.go index 381776851..6ce464d8d 100644 --- a/system_tests/seq_pause_test.go +++ b/system_tests/seq_pause_test.go @@ -16,13 +16,13 @@ func TestSequencerPause(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info1, nodeA, client := CreateTestL2(t, ctx) - defer nodeA.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() const numUsers = 100 - execA := getExecNode(t, nodeA) - prechecker, ok := execA.TxPublisher.(*gethexec.TxPreChecker) + prechecker, ok := builder.L2.ExecNode.TxPublisher.(*gethexec.TxPreChecker) if !ok { t.Error("prechecker not found on node") } @@ -35,15 +35,15 @@ func TestSequencerPause(t *testing.T) { for num := 0; num < numUsers; num++ { userName := fmt.Sprintf("My_User_%d", num) - l2info1.GenerateAccount(userName) + builder.L2Info.GenerateAccount(userName) users = append(users, userName) } for _, userName := range users { - tx := l2info1.PrepareTx("Owner", userName, l2info1.TransferGas, big.NewInt(1e16), nil) - err := client.SendTransaction(ctx, tx) + tx := builder.L2Info.PrepareTx("Owner", userName, builder.L2Info.TransferGas, big.NewInt(1e16), nil) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) } @@ -52,7 +52,7 @@ func TestSequencerPause(t *testing.T) { var txs types.Transactions for _, userName := range users { - tx := l2info1.PrepareTx(userName, "Owner", l2info1.TransferGas, big.NewInt(2), nil) + tx := builder.L2Info.PrepareTx(userName, "Owner", builder.L2Info.TransferGas, big.NewInt(2), nil) txs = append(txs, tx) } @@ -63,7 +63,7 @@ func TestSequencerPause(t *testing.T) { }(tx) } - _, err := EnsureTxSucceededWithTimeout(ctx, client, txs[0], time.Second) + _, err := builder.L2.EnsureTxSucceededWithTimeout(txs[0], time.Second) if err == nil { t.Error("tx passed while sequencer paused") } @@ -71,7 +71,7 @@ func TestSequencerPause(t *testing.T) { sequencer.Activate() for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, client, tx) + _, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) } } diff --git a/system_tests/seq_reject_test.go b/system_tests/seq_reject_test.go index 34a14c660..76bdfc261 100644 --- a/system_tests/seq_reject_test.go +++ b/system_tests/seq_reject_test.go @@ -17,7 +17,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/colors" @@ -28,21 +27,21 @@ func TestSequencerRejection(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - seqNodeConfig := arbnode.ConfigDefaultL2Test() - seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() feedErrChan := make(chan error, 10) - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true) - defer nodeA.StopAndWait() - - clientNodeConfig := arbnode.ConfigDefaultL2Test() - port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port - clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - - _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false) - defer nodeB.StopAndWait() - - auth := l2info1.GetDefaultTransactOpts("Owner", ctx) - simpleAddr, _ := deploySimple(t, ctx, auth, client1) + builderSeq := NewNodeBuilder(ctx).DefaultConfig(t, false) + builderSeq.nodeConfig.Feed.Output = *newBroadcasterConfigTest() + cleanupSeq := builderSeq.Build(t) + defer cleanupSeq() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.takeOwnership = false + port := builderSeq.L2.ConsensusNode.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + builder.nodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) + cleanup := builder.Build(t) + defer cleanup() + + auth := builderSeq.L2Info.GetDefaultTransactOpts("Owner", ctx) + simpleAddr, _ := builderSeq.L2.DeploySimple(t, auth) simpleAbi, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) noopId := simpleAbi.Methods["noop"].ID @@ -51,7 +50,7 @@ func TestSequencerRejection(t *testing.T) { // Generate the accounts before hand to avoid races for user := 0; user < 9; user++ { name := fmt.Sprintf("User%v", user) - l2info1.GenerateAccount(name) + builderSeq.L2Info.GenerateAccount(name) } wg := sync.WaitGroup{} @@ -59,24 +58,24 @@ func TestSequencerRejection(t *testing.T) { for user := 0; user < 9; user++ { user := user name := fmt.Sprintf("User%v", user) - tx := l2info1.PrepareTx("Owner", name, l2info1.TransferGas, big.NewInt(params.Ether), nil) + tx := builderSeq.L2Info.PrepareTx("Owner", name, builderSeq.L2Info.TransferGas, big.NewInt(params.Ether), nil) - err := client1.SendTransaction(ctx, tx) + err := builderSeq.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client1, tx) + _, err = builderSeq.L2.EnsureTxSucceeded(tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client2, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) wg.Add(1) go func() { defer wg.Done() - info := l2info1.GetInfoWithPrivKey(name) + info := builderSeq.L2Info.GetInfoWithPrivKey(name) txData := &types.DynamicFeeTx{ To: &simpleAddr, - Gas: l2info1.TransferGas + 10000, - GasFeeCap: arbmath.BigMulByUint(l2info1.GasPrice, 100), + Gas: builderSeq.L2Info.TransferGas + 10000, + GasFeeCap: arbmath.BigMulByUint(builderSeq.L2Info.GasPrice, 100), Value: common.Big0, } for atomic.LoadInt32(&stopBackground) == 0 { @@ -92,8 +91,8 @@ func TestSequencerRejection(t *testing.T) { txData.Nonce = 1 << 32 expectedErr = "nonce too high" } - tx = l2info1.SignTxAs(name, txData) - err = client1.SendTransaction(ctx, tx) + tx = builderSeq.L2Info.SignTxAs(name, txData) + err = builderSeq.L2.Client.SendTransaction(ctx, tx) if err != nil && (expectedErr == "" || !strings.Contains(err.Error(), expectedErr)) { Require(t, err, "failed to send tx for user", user) } @@ -102,7 +101,7 @@ func TestSequencerRejection(t *testing.T) { } for i := 100; i >= 0; i-- { - block, err := client1.BlockNumber(ctx) + block, err := builderSeq.L2.Client.BlockNumber(ctx) Require(t, err) if block >= 200 { break @@ -120,11 +119,11 @@ func TestSequencerRejection(t *testing.T) { atomic.StoreInt32(&stopBackground, 1) wg.Wait() - header1, err := client1.HeaderByNumber(ctx, nil) + header1, err := builderSeq.L2.Client.HeaderByNumber(ctx, nil) Require(t, err) for i := 100; i >= 0; i-- { - header2, err := client2.HeaderByNumber(ctx, header1.Number) + header2, err := builder.L2.Client.HeaderByNumber(ctx, header1.Number) if err != nil { select { case err := <-feedErrChan: @@ -132,7 +131,7 @@ func TestSequencerRejection(t *testing.T) { case <-time.After(time.Millisecond * 100): } if i == 0 { - client2Block, _ := client2.BlockNumber(ctx) + client2Block, _ := builder.L2.Client.BlockNumber(ctx) Fatal(t, "client2 failed to reach client1 block ", header1.Number, ", only reached block", client2Block) } continue diff --git a/system_tests/seq_whitelist_test.go b/system_tests/seq_whitelist_test.go index 36e309a5d..efa30171a 100644 --- a/system_tests/seq_whitelist_test.go +++ b/system_tests/seq_whitelist_test.go @@ -9,31 +9,30 @@ import ( "testing" "github.com/ethereum/go-ethereum/params" - "github.com/offchainlabs/nitro/execution/gethexec" ) func TestSequencerWhitelist(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - config := gethexec.ConfigDefaultTest() - config.Sequencer.SenderWhitelist = GetTestAddressForAccountName(t, "Owner").String() + "," + GetTestAddressForAccountName(t, "User").String() - l2info, l2node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, true) - defer l2node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.execConfig.Sequencer.SenderWhitelist = GetTestAddressForAccountName(t, "Owner").String() + "," + GetTestAddressForAccountName(t, "User").String() + cleanup := builder.Build(t) + defer cleanup() - l2info.GenerateAccount("User") - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User") + builder.L2Info.GenerateAccount("User2") // Owner is on the whitelist - TransferBalance(t, "Owner", "User", big.NewInt(params.Ether), l2info, client, ctx) - TransferBalance(t, "Owner", "User2", big.NewInt(params.Ether), l2info, client, ctx) + builder.L2.TransferBalance(t, "Owner", "User", big.NewInt(params.Ether), builder.L2Info) + builder.L2.TransferBalance(t, "Owner", "User2", big.NewInt(params.Ether), builder.L2Info) // User is on the whitelist - TransferBalance(t, "User", "User2", big.NewInt(params.Ether/10), l2info, client, ctx) + builder.L2.TransferBalance(t, "User", "User2", big.NewInt(params.Ether/10), builder.L2Info) // User2 is *not* on the whitelist, therefore this should fail - tx := l2info.PrepareTx("User2", "User", l2info.TransferGas, big.NewInt(params.Ether/10), nil) - err := client.SendTransaction(ctx, tx) + tx := builder.L2Info.PrepareTx("User2", "User", builder.L2Info.TransferGas, big.NewInt(params.Ether/10), nil) + err := builder.L2.Client.SendTransaction(ctx, tx) if err == nil { Fatal(t, "transaction from user not on whitelist accepted") } diff --git a/system_tests/seqcompensation_test.go b/system_tests/seqcompensation_test.go index 362acf6a3..156ced6bf 100644 --- a/system_tests/seqcompensation_test.go +++ b/system_tests/seqcompensation_test.go @@ -18,19 +18,19 @@ func TestSequencerCompensation(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, nil) - defer nodeB.StopAndWait() + TestClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{}) + defer cleanupB() - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) - err := l2clientA.SendTransaction(ctx, tx) + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2clientA, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) // give the inbox reader a bit of time to pick up the delayed message @@ -38,22 +38,22 @@ func TestSequencerCompensation(t *testing.T) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } - _, err = WaitForTx(ctx, l2clientB, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, TestClientB.Client, tx.Hash(), time.Second*5) Require(t, err) // clientB sees balance means sequencer message was sent - l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := TestClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { Fatal(t, "Unexpected balance:", l2balance) } - initialSeqBalance, err := l2clientB.BalanceAt(ctx, l1pricing.BatchPosterAddress, big.NewInt(0)) + initialSeqBalance, err := TestClientB.Client.BalanceAt(ctx, l1pricing.BatchPosterAddress, big.NewInt(0)) Require(t, err) if initialSeqBalance.Sign() != 0 { Fatal(t, "Unexpected initial sequencer balance:", initialSeqBalance) diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index c90617455..69aeab0c8 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -18,7 +18,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient/gethclient" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" @@ -91,44 +90,44 @@ func diffAccessList(accessed, al types.AccessList) string { return diff } -func deployGasRefunder(ctx context.Context, t *testing.T, info *BlockchainTestInfo, client *ethclient.Client) common.Address { +func deployGasRefunder(ctx context.Context, t *testing.T, builder *NodeBuilder) common.Address { t.Helper() abi, err := bridgegen.GasRefunderMetaData.GetAbi() if err != nil { t.Fatalf("Error getting gas refunder abi: %v", err) } - fauOpts := info.GetDefaultTransactOpts("Faucet", ctx) - addr, tx, _, err := bind.DeployContract(&fauOpts, *abi, common.FromHex(bridgegen.GasRefunderBin), client) + fauOpts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) + addr, tx, _, err := bind.DeployContract(&fauOpts, *abi, common.FromHex(bridgegen.GasRefunderBin), builder.L1.Client) if err != nil { t.Fatalf("Error getting gas refunder contract deployment transaction: %v", err) } - if _, err := EnsureTxSucceeded(ctx, client, tx); err != nil { + if _, err := builder.L1.EnsureTxSucceeded(tx); err != nil { t.Fatalf("Error deploying gas refunder contract: %v", err) } - tx = info.PrepareTxTo("Faucet", &addr, 30000, big.NewInt(9223372036854775807), nil) - if err := client.SendTransaction(ctx, tx); err != nil { + tx = builder.L1Info.PrepareTxTo("Faucet", &addr, 30000, big.NewInt(9223372036854775807), nil) + if err := builder.L1.Client.SendTransaction(ctx, tx); err != nil { t.Fatalf("Error sending gas refunder funding transaction") } - if _, err := EnsureTxSucceeded(ctx, client, tx); err != nil { + if _, err := builder.L1.EnsureTxSucceeded(tx); err != nil { t.Fatalf("Error funding gas refunder") } - contract, err := bridgegen.NewGasRefunder(addr, client) + contract, err := bridgegen.NewGasRefunder(addr, builder.L1.Client) if err != nil { t.Fatalf("Error getting gas refunder contract binding: %v", err) } - tx, err = contract.AllowContracts(&fauOpts, []common.Address{info.GetAddress("SequencerInbox")}) + tx, err = contract.AllowContracts(&fauOpts, []common.Address{builder.L1Info.GetAddress("SequencerInbox")}) if err != nil { t.Fatalf("Error creating transaction for altering allowlist in refunder: %v", err) } - if _, err := EnsureTxSucceeded(ctx, client, tx); err != nil { + if _, err := builder.L1.EnsureTxSucceeded(tx); err != nil { t.Fatalf("Error addting sequencer inbox in gas refunder allowlist: %v", err) } - tx, err = contract.AllowRefundees(&fauOpts, []common.Address{info.GetAddress("Sequencer")}) + tx, err = contract.AllowRefundees(&fauOpts, []common.Address{builder.L1Info.GetAddress("Sequencer")}) if err != nil { t.Fatalf("Error creating transaction for altering allowlist in refunder: %v", err) } - if _, err := EnsureTxSucceeded(ctx, client, tx); err != nil { + if _, err := builder.L1.EnsureTxSucceeded(tx); err != nil { t.Fatalf("Error addting sequencer in gas refunder allowlist: %v", err) } return addr @@ -162,7 +161,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { Require(t, err) seqOpts := builder.L1Info.GetDefaultTransactOpts("Sequencer", ctx) - gasRefunderAddr := deployGasRefunder(ctx, t, builder.L1Info, builder.L1.Client) + gasRefunderAddr := deployGasRefunder(ctx, t, builder) ownerAddress := builder.L2Info.GetAddress("Owner") var startL2BlockNumber uint64 = 0 @@ -200,7 +199,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { builder.L1Info.GenerateAccount(acct) faucetTxs = append(faucetTxs, builder.L1Info.PrepareTx("Faucet", acct, 30000, big.NewInt(1e16), nil)) } - SendWaitTestTransactions(t, ctx, builder.L1.Client, faucetTxs) + builder.L1.SendWaitTestTransactions(t, faucetTxs) seqABI, err := bridgegen.SequencerInboxMetaData.GetAbi() if err != nil { diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 023949142..e9eb884c9 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -27,7 +27,6 @@ import ( "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbos/l2pricing" - "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/staker" @@ -38,15 +37,15 @@ import ( "github.com/offchainlabs/nitro/validator/valnode" ) -func makeBackgroundTxs(ctx context.Context, l2info *BlockchainTestInfo, l2clientA arbutil.L1Interface) error { +func makeBackgroundTxs(ctx context.Context, builder *NodeBuilder) error { for i := uint64(0); ctx.Err() == nil; i++ { - l2info.Accounts["BackgroundUser"].Nonce = i - tx := l2info.PrepareTx("BackgroundUser", "BackgroundUser", l2info.TransferGas, common.Big0, nil) - err := l2clientA.SendTransaction(ctx, tx) + builder.L2Info.Accounts["BackgroundUser"].Nonce = i + tx := builder.L2Info.PrepareTx("BackgroundUser", "BackgroundUser", builder.L2Info.TransferGas, common.Big0, nil) + err := builder.L2.Client.SendTransaction(ctx, tx) if err != nil { return err } - _, err = EnsureTxSucceeded(ctx, l2clientA, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) if err != nil { return err } @@ -263,7 +262,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) })() go (func() { defer close(backgroundTxsShutdownChan) - err := makeBackgroundTxs(backgroundTxsCtx, builder.L2Info, builder.L2.Client) + err := makeBackgroundTxs(backgroundTxsCtx, builder) if !errors.Is(err, context.Canceled) { log.Warn("error making background txs", "err", err) } diff --git a/system_tests/transfer_test.go b/system_tests/transfer_test.go index 2e3317907..a270cca76 100644 --- a/system_tests/transfer_test.go +++ b/system_tests/transfer_test.go @@ -13,23 +13,24 @@ import ( func TestTransfer(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, client := CreateTestL2(t, ctx) - defer l2node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) - err := client.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - bal, err := client.BalanceAt(ctx, l2info.GetAddress("Owner"), nil) + bal, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("Owner"), nil) Require(t, err) fmt.Println("Owner balance is: ", bal) - bal2, err := client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + bal2, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if bal2.Cmp(big.NewInt(1e12)) != 0 { Fatal(t, "Unexpected recipient balance: ", bal2) diff --git a/system_tests/triedb_race_test.go b/system_tests/triedb_race_test.go index 8174a9b6a..6d9415df8 100644 --- a/system_tests/triedb_race_test.go +++ b/system_tests/triedb_race_test.go @@ -10,7 +10,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" - "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/testhelpers" ) @@ -18,24 +17,21 @@ func TestTrieDBCommitRace(t *testing.T) { _ = testhelpers.InitTestLog(t, log.LvlError) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - execConfig := gethexec.ConfigDefaultTest() - execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth - execConfig.Sequencer.MaxBlockSpeed = 0 - execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 - execConfig.Caching.Archive = true - execConfig.Caching.BlockCount = 127 - execConfig.Caching.BlockAge = 0 - execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 127 - execConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 - l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, execConfig, nil, nil) - cancel = func() { - defer requireClose(t, l1stack) - defer node.StopAndWait() - } - defer cancel() - execNode := getExecNode(t, node) - l2info.GenerateAccount("User2") - bc := execNode.Backend.ArbInterface().BlockChain() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth + builder.execConfig.Sequencer.MaxBlockSpeed = 0 + builder.execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 + builder.execConfig.Caching.Archive = true + builder.execConfig.Caching.BlockCount = 127 + builder.execConfig.Caching.BlockAge = 0 + builder.execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 127 + builder.execConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 + cleanup := builder.Build(t) + defer cleanup() + + builder.L2Info.GenerateAccount("User2") + bc := builder.L2.ExecNode.Backend.ArbInterface().BlockChain() var wg sync.WaitGroup quit := make(chan struct{}) @@ -45,13 +41,13 @@ func TestTrieDBCommitRace(t *testing.T) { for { select { default: - TransferBalance(t, "Faucet", "User2", common.Big1, l2info, l2client, ctx) + builder.L2.TransferBalance(t, "Faucet", "User2", common.Big1, builder.L2Info) case <-quit: return } } }() - api := execNode.Backend.APIBackend() + api := builder.L2.ExecNode.Backend.APIBackend() blockNumber := 1 for i := 0; i < 5; i++ { var roots []common.Hash diff --git a/system_tests/twonodes_test.go b/system_tests/twonodes_test.go index 6280a4a57..c8e348cff 100644 --- a/system_tests/twonodes_test.go +++ b/system_tests/twonodes_test.go @@ -20,24 +20,27 @@ func testTwoNodesSimple(t *testing.T, dasModeStr string) { chainConfig, l1NodeConfigA, lifecycleManager, _, dasSignerKey := setupConfigWithDAS(t, ctx, dasModeStr) defer lifecycleManager.StopAndWaitUntil(time.Second) - l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, nil, chainConfig, nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() - - authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig = l1NodeConfigA + builder.chainConfig = chainConfig + builder.L2Info = nil + cleanup := builder.Build(t) + defer cleanup() + + authorizeDASKeyset(t, ctx, dasSignerKey, builder.L1Info, builder.L1.Client) l1NodeConfigBDataAvailability := l1NodeConfigA.DataAvailability l1NodeConfigBDataAvailability.RPCAggregator.Enable = false - l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, &l1NodeConfigBDataAvailability) - defer nodeB.StopAndWait() + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{dasConfig: &l1NodeConfigBDataAvailability}) + defer cleanupB() - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) - err := l2clientA.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2clientA, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) // give the inbox reader a bit of time to pick up the delayed message @@ -45,15 +48,15 @@ func testTwoNodesSimple(t *testing.T, dasModeStr string) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } - _, err = WaitForTx(ctx, l2clientB, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, testClientB.Client, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { diff --git a/system_tests/twonodeslong_test.go b/system_tests/twonodeslong_test.go index 16c369df4..09203e3bc 100644 --- a/system_tests/twonodeslong_test.go +++ b/system_tests/twonodeslong_test.go @@ -42,32 +42,36 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { chainConfig, l1NodeConfigA, lifecycleManager, _, dasSignerKey := setupConfigWithDAS(t, ctx, dasModeStr) defer lifecycleManager.StopAndWaitUntil(time.Second) - l2info, nodeA, l2client, l1info, l1backend, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, nil, chainConfig, nil) - defer requireClose(t, l1stack) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig = l1NodeConfigA + builder.chainConfig = chainConfig + builder.L2Info = nil + builder.Build(t) + defer requireClose(t, builder.L1.Stack) - authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) + authorizeDASKeyset(t, ctx, dasSignerKey, builder.L1Info, builder.L1.Client) l1NodeConfigBDataAvailability := l1NodeConfigA.DataAvailability l1NodeConfigBDataAvailability.RPCAggregator.Enable = false - l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, &l1NodeConfigBDataAvailability) - defer nodeB.StopAndWait() + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{dasConfig: &l1NodeConfigBDataAvailability}) + defer cleanupB() - l2info.GenerateAccount("DelayedFaucet") - l2info.GenerateAccount("DelayedReceiver") - l2info.GenerateAccount("DirectReceiver") + builder.L2Info.GenerateAccount("DelayedFaucet") + builder.L2Info.GenerateAccount("DelayedReceiver") + builder.L2Info.GenerateAccount("DirectReceiver") - l2info.GenerateAccount("ErrorTxSender") + builder.L2Info.GenerateAccount("ErrorTxSender") - SendWaitTestTransactions(t, ctx, l2client, []*types.Transaction{ - l2info.PrepareTx("Faucet", "ErrorTxSender", l2info.TransferGas, big.NewInt(l2pricing.InitialBaseFeeWei*int64(l2info.TransferGas)), nil), + builder.L2.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L2Info.PrepareTx("Faucet", "ErrorTxSender", builder.L2Info.TransferGas, big.NewInt(l2pricing.InitialBaseFeeWei*int64(builder.L2Info.TransferGas)), nil), }) delayedMsgsToSendMax := big.NewInt(int64(largeLoops * avgDelayedMessagesPerLoop * 10)) delayedFaucetNeeds := new(big.Int).Mul(new(big.Int).Add(fundsPerDelayed, new(big.Int).SetUint64(l2pricing.InitialBaseFeeWei*100000)), delayedMsgsToSendMax) - SendWaitTestTransactions(t, ctx, l2client, []*types.Transaction{ - l2info.PrepareTx("Faucet", "DelayedFaucet", l2info.TransferGas, delayedFaucetNeeds, nil), + builder.L2.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L2Info.PrepareTx("Faucet", "DelayedFaucet", builder.L2Info.TransferGas, delayedFaucetNeeds, nil), }) - delayedFaucetBalance, err := l2client.BalanceAt(ctx, l2info.GetAddress("DelayedFaucet"), nil) + delayedFaucetBalance, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("DelayedFaucet"), nil) Require(t, err) if delayedFaucetBalance.Cmp(delayedFaucetNeeds) != 0 { @@ -85,17 +89,17 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { randNum := rand.Int() % avgTotalL1MessagesPerLoop var l1tx *types.Transaction if randNum < avgDelayedMessagesPerLoop { - delayedTx := l2info.PrepareTx("DelayedFaucet", "DelayedReceiver", 30001, fundsPerDelayed, nil) - l1tx = WrapL2ForDelayed(t, delayedTx, l1info, "User", 100000) + delayedTx := builder.L2Info.PrepareTx("DelayedFaucet", "DelayedReceiver", 30001, fundsPerDelayed, nil) + l1tx = WrapL2ForDelayed(t, delayedTx, builder.L1Info, "User", 100000) delayedTxs = append(delayedTxs, delayedTx) delayedTransfers++ } else { - l1tx = l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) + l1tx = builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) } l1Txs = append(l1Txs, l1tx) } // adding multiple messages in the same AddLocal to get them in the same L1 block - errs := l1backend.TxPool().AddLocals(l1Txs) + errs := builder.L1.L1Backend.TxPool().AddLocals(l1Txs) for _, err := range errs { if err != nil { Fatal(t, err) @@ -104,26 +108,26 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { l2TxsThisTime := rand.Int() % (avgL2MsgsPerLoop * 2) l2Txs := make([]*types.Transaction, 0, l2TxsThisTime) for len(l2Txs) < l2TxsThisTime { - l2Txs = append(l2Txs, l2info.PrepareTx("Faucet", "DirectReceiver", l2info.TransferGas, fundsPerDirect, nil)) + l2Txs = append(l2Txs, builder.L2Info.PrepareTx("Faucet", "DirectReceiver", builder.L2Info.TransferGas, fundsPerDirect, nil)) } - SendWaitTestTransactions(t, ctx, l2client, l2Txs) + builder.L2.SendWaitTestTransactions(t, l2Txs) directTransfers += int64(l2TxsThisTime) if len(l1Txs) > 0 { - _, err := EnsureTxSucceeded(ctx, l1client, l1Txs[len(l1Txs)-1]) + _, err := builder.L1.EnsureTxSucceeded(l1Txs[len(l1Txs)-1]) if err != nil { Fatal(t, err) } } // create bad tx on delayed inbox - l2info.GetInfoWithPrivKey("ErrorTxSender").Nonce = 10 - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - WrapL2ForDelayed(t, l2info.PrepareTx("ErrorTxSender", "DelayedReceiver", 30002, delayedFaucetNeeds, nil), l1info, "User", 100000), + builder.L2Info.GetInfoWithPrivKey("ErrorTxSender").Nonce = 10 + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + WrapL2ForDelayed(t, builder.L2Info.PrepareTx("ErrorTxSender", "DelayedReceiver", 30002, delayedFaucetNeeds, nil), builder.L1Info, "User", 100000), }) extrBlocksThisTime := rand.Int() % (avgExtraBlocksPerLoop * 2) for i := 0; i < extrBlocksThisTime; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } } @@ -137,45 +141,45 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { for i := 0; i < finalPropagateLoops; i++ { var tx *types.Transaction for j := 0; j < 30; j++ { - tx = l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) - err := l1client.SendTransaction(ctx, tx) + tx = builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) + err := builder.L1.Client.SendTransaction(ctx, tx) if err != nil { Fatal(t, err) } - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = builder.L1.EnsureTxSucceeded(tx) if err != nil { Fatal(t, err) } } } - _, err = EnsureTxSucceededWithTimeout(ctx, l2client, delayedTxs[len(delayedTxs)-1], time.Second*10) + _, err = builder.L2.EnsureTxSucceededWithTimeout(delayedTxs[len(delayedTxs)-1], time.Second*10) Require(t, err, "Failed waiting for Tx on main node") - _, err = EnsureTxSucceededWithTimeout(ctx, l2clientB, delayedTxs[len(delayedTxs)-1], time.Second*10) + _, err = testClientB.EnsureTxSucceededWithTimeout(delayedTxs[len(delayedTxs)-1], time.Second*10) Require(t, err, "Failed waiting for Tx on secondary node") - delayedBalance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("DelayedReceiver"), nil) + delayedBalance, err := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("DelayedReceiver"), nil) Require(t, err) - directBalance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("DirectReceiver"), nil) + directBalance, err := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("DirectReceiver"), nil) Require(t, err) delayedExpectd := new(big.Int).Mul(fundsPerDelayed, big.NewInt(delayedTransfers)) directExpectd := new(big.Int).Mul(fundsPerDirect, big.NewInt(directTransfers)) if (delayedBalance.Cmp(delayedExpectd) != 0) || (directBalance.Cmp(directExpectd) != 0) { t.Error("delayed balance", delayedBalance, "expected", delayedExpectd, "transfers", delayedTransfers) t.Error("direct balance", directBalance, "expected", directExpectd, "transfers", directTransfers) - ownerBalance, _ := l2clientB.BalanceAt(ctx, l2info.GetAddress("Owner"), nil) - delayedFaucetBalance, _ := l2clientB.BalanceAt(ctx, l2info.GetAddress("DelayedFaucet"), nil) + ownerBalance, _ := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("Owner"), nil) + delayedFaucetBalance, _ := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("DelayedFaucet"), nil) t.Error("owner balance", ownerBalance, "delayed faucet", delayedFaucetBalance) Fatal(t, "Unexpected balance") } - nodeA.StopAndWait() + builder.L2.ConsensusNode.StopAndWait() - if nodeB.BlockValidator != nil { - lastBlockHeader, err := l2clientB.HeaderByNumber(ctx, nil) + if testClientB.ConsensusNode.BlockValidator != nil { + lastBlockHeader, err := testClientB.Client.HeaderByNumber(ctx, nil) Require(t, err) timeout := getDeadlineTimeout(t, time.Minute*30) // messageindex is same as block number here - if !nodeB.BlockValidator.WaitForPos(t, ctx, arbutil.MessageIndex(lastBlockHeader.Number.Uint64()), timeout) { + if !testClientB.ConsensusNode.BlockValidator.WaitForPos(t, ctx, arbutil.MessageIndex(lastBlockHeader.Number.Uint64()), timeout) { Fatal(t, "did not validate all blocks") } } From e8f06193fa3c0641258ea2e961eaaa30852823b0 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Wed, 25 Oct 2023 19:21:18 -0700 Subject: [PATCH 330/775] Prevent double `v` in reported version https://github.com/OffchainLabs/nitro/issues/1935 Ensure that `web3_clientVersion` does not have extra `v` included --- cmd/nitro-val/nitro_val.go | 4 ++++ cmd/nitro/nitro.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/cmd/nitro-val/nitro_val.go b/cmd/nitro-val/nitro_val.go index 43b1c1d20..6bcb55f05 100644 --- a/cmd/nitro-val/nitro_val.go +++ b/cmd/nitro-val/nitro_val.go @@ -75,6 +75,10 @@ func mainImpl() int { stackConf.P2P.NoDiscovery = true vcsRevision, vcsTime := confighelpers.GetVersion() stackConf.Version = vcsRevision + if stackConf.Version[0] == 'v' { + // Skip leading "v" in version string + stackConf.Version = stackConf.Version[1:] + } pathResolver := func(workdir string) func(string) string { if workdir == "" { diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 80b21e5eb..426f514c1 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -179,6 +179,10 @@ func mainImpl() int { stackConf.P2P.NoDiscovery = true vcsRevision, vcsTime := confighelpers.GetVersion() stackConf.Version = vcsRevision + if stackConf.Version[0] == 'v' { + // Skip leading "v" in version string + stackConf.Version = stackConf.Version[1:] + } pathResolver := func(workdir string) func(string) string { if workdir == "" { From ed5694bea32a8159b6551bebc1f5856af8cd041a Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Wed, 25 Oct 2023 20:41:37 -0700 Subject: [PATCH 331/775] Fix issue attempting to access empty string Also remove code duplication --- cmd/daserver/daserver.go | 2 +- cmd/genericconf/getversion18.go | 9 +++++++-- cmd/nitro-val/nitro_val.go | 8 ++------ cmd/nitro/nitro.go | 8 ++------ cmd/relay/relay.go | 2 +- cmd/util/confighelpers/configuration.go | 4 ++-- 6 files changed, 15 insertions(+), 18 deletions(-) diff --git a/cmd/daserver/daserver.go b/cmd/daserver/daserver.go index b2f8728a7..07481651b 100644 --- a/cmd/daserver/daserver.go +++ b/cmd/daserver/daserver.go @@ -239,7 +239,7 @@ func startup() error { dasLifecycleManager.Register(&L1ReaderCloser{l1Reader}) } - vcsRevision, vcsTime := confighelpers.GetVersion() + vcsRevision, _, vcsTime := confighelpers.GetVersion() var rpcServer *http.Server if serverConfig.EnableRPC { log.Info("Starting HTTP-RPC server", "addr", serverConfig.RPCAddr, "port", serverConfig.RPCPort, "revision", vcsRevision, "vcs.time", vcsTime) diff --git a/cmd/genericconf/getversion18.go b/cmd/genericconf/getversion18.go index 2c183f687..4aabae91e 100644 --- a/cmd/genericconf/getversion18.go +++ b/cmd/genericconf/getversion18.go @@ -7,7 +7,7 @@ package genericconf import "runtime/debug" -func GetVersion(definedVersion string, definedTime string, definedModified string) (string, string) { +func GetVersion(definedVersion string, definedTime string, definedModified string) (string, string, string) { vcsVersion := "development" vcsTime := "development" vcsModified := "false" @@ -43,5 +43,10 @@ func GetVersion(definedVersion string, definedTime string, definedModified strin vcsVersion = vcsVersion + "-modified" } - return vcsVersion, vcsTime + strippedVersion := vcsVersion + if len(strippedVersion) > 0 && strippedVersion[0] == 'v' { + strippedVersion = strippedVersion[1:] + } + + return vcsVersion, strippedVersion, vcsTime } diff --git a/cmd/nitro-val/nitro_val.go b/cmd/nitro-val/nitro_val.go index 6bcb55f05..20b8b2362 100644 --- a/cmd/nitro-val/nitro_val.go +++ b/cmd/nitro-val/nitro_val.go @@ -73,12 +73,8 @@ func mainImpl() int { stackConf.P2P.ListenAddr = "" stackConf.P2P.NoDial = true stackConf.P2P.NoDiscovery = true - vcsRevision, vcsTime := confighelpers.GetVersion() - stackConf.Version = vcsRevision - if stackConf.Version[0] == 'v' { - // Skip leading "v" in version string - stackConf.Version = stackConf.Version[1:] - } + vcsRevision, strippedRevision, vcsTime := confighelpers.GetVersion() + stackConf.Version = strippedRevision pathResolver := func(workdir string) func(string) string { if workdir == "" { diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 426f514c1..72668c60e 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -177,12 +177,8 @@ func mainImpl() int { stackConf.P2P.ListenAddr = "" stackConf.P2P.NoDial = true stackConf.P2P.NoDiscovery = true - vcsRevision, vcsTime := confighelpers.GetVersion() - stackConf.Version = vcsRevision - if stackConf.Version[0] == 'v' { - // Skip leading "v" in version string - stackConf.Version = stackConf.Version[1:] - } + vcsRevision, strippedRevision, vcsTime := confighelpers.GetVersion() + stackConf.Version = strippedRevision pathResolver := func(workdir string) func(string) string { if workdir == "" { diff --git a/cmd/relay/relay.go b/cmd/relay/relay.go index 552838308..b25aadf57 100644 --- a/cmd/relay/relay.go +++ b/cmd/relay/relay.go @@ -76,7 +76,7 @@ func startup() error { glogger.Verbosity(log.Lvl(relayConfig.LogLevel)) log.Root().SetHandler(glogger) - vcsRevision, vcsTime := confighelpers.GetVersion() + vcsRevision, _, vcsTime := confighelpers.GetVersion() log.Info("Running Arbitrum nitro relay", "revision", vcsRevision, "vcs.time", vcsTime) defer log.Info("Cleanly shutting down relay") diff --git a/cmd/util/confighelpers/configuration.go b/cmd/util/confighelpers/configuration.go index 6116a492c..85a8f4ade 100644 --- a/cmd/util/confighelpers/configuration.go +++ b/cmd/util/confighelpers/configuration.go @@ -118,12 +118,12 @@ func loadS3Variables(k *koanf.Koanf) error { var ErrVersion = errors.New("configuration: version requested") -func GetVersion() (string, string) { +func GetVersion() (string, string, string) { return genericconf.GetVersion(version, datetime, modified) } func PrintErrorAndExit(err error, usage func(string)) { - vcsRevision, vcsTime := GetVersion() + vcsRevision, _, vcsTime := GetVersion() fmt.Printf("Version: %v, time: %v\n", vcsRevision, vcsTime) if err != nil && errors.Is(err, ErrVersion) { // Already printed version, just exit From daea49bdf4d0f46ea66611bf0abf6025554f2a98 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Wed, 25 Oct 2023 22:02:02 -0700 Subject: [PATCH 332/775] Update geth pin Update geth pin to include the following changes: OffchainLabs/go-ethereum#255 OffchainLabs/go-ethereum#262 OffchainLabs/go-ethereum#263 --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index e8c8827c0..859182f2f 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit e8c8827c0b9e22e60829da1945cba9c451cda85a +Subproject commit 859182f2fa2d33c03fba5e29e1e750d3f49525fe From b5383bd6c8945da431fc71e4cd934e34e2b98f1b Mon Sep 17 00:00:00 2001 From: amsanghi Date: Thu, 26 Oct 2023 19:29:54 +0530 Subject: [PATCH 333/775] changes based on pr comments --- execution/gethexec/node.go | 3 ++- system_tests/common_test.go | 13 ++++++------- system_tests/contract_tx_test.go | 2 +- system_tests/estimation_test.go | 26 +++++++++++++------------- system_tests/infra_fee_test.go | 2 +- system_tests/initialization_test.go | 2 +- system_tests/seq_coordinator_test.go | 2 +- system_tests/seq_nonce_test.go | 6 +++--- system_tests/seq_reject_test.go | 4 ++-- system_tests/seq_whitelist_test.go | 2 +- system_tests/seqfeed_test.go | 8 ++++---- 11 files changed, 35 insertions(+), 35 deletions(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 5a99d59c5..7eb9b1314 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -7,6 +7,7 @@ import ( "reflect" "sync/atomic" "testing" + "time" "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" @@ -99,7 +100,7 @@ var ConfigDefault = Config{ func ConfigDefaultNonSequencerTest() *Config { config := ConfigDefault - config.ParentChainReader = headerreader.Config{} + config.ParentChainReader = headerreader.Config{OldHeaderTimeout: 5 * time.Minute} config.Sequencer.Enable = false config.Forwarder = DefaultTestForwarderConfig config.ForwardingTarget = "null" diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 21b8aa896..d233631d4 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -171,7 +171,7 @@ func (b *NodeBuilder) Build(t *testing.T) func() { } else { l2 := NewTestClient(b.ctx) b.L2Info, l2.ConsensusNode, l2.Client = - CreateTestL2WithConfig(t, b.ctx, b.L2Info, b.nodeConfig, b.execConfig, b.takeOwnership, b.chainConfig) + CreateTestL2WithConfig(t, b.ctx, b.L2Info, b.nodeConfig, b.execConfig, b.takeOwnership) b.L2 = l2 } b.L2.ExecNode = getExecNode(t, b.L2.ConsensusNode) @@ -797,11 +797,11 @@ func createTestNodeOnL1WithConfigImpl( // L2 -Only. Enough for tests that needs no interface to L1 // Requires precompiles.AllowDebugPrecompiles = true func CreateTestL2(t *testing.T, ctx context.Context) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { - return CreateTestL2WithConfig(t, ctx, nil, nil, nil, true, nil) + return CreateTestL2WithConfig(t, ctx, nil, nil, nil, true) } func CreateTestL2WithConfig( - t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, execConfig *gethexec.Config, takeOwnership bool, chainConfig *params.ChainConfig, + t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, execConfig *gethexec.Config, takeOwnership bool, ) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { if nodeConfig == nil { nodeConfig = arbnode.ConfigDefaultL2Test() @@ -809,14 +809,12 @@ func CreateTestL2WithConfig( if execConfig == nil { execConfig = gethexec.ConfigDefaultTest() } - if chainConfig == nil { - chainConfig = params.ArbitrumDevTestChainConfig() - } + feedErrChan := make(chan error, 10) AddDefaultValNode(t, ctx, nodeConfig, true) - l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, l2Info, "", chainConfig, &execConfig.Caching) + l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, l2Info, "", params.ArbitrumDevTestChainConfig(), &execConfig.Caching) Require(t, execConfig.Validate()) execConfigFetcher := func() *gethexec.Config { return execConfig } @@ -825,6 +823,7 @@ func CreateTestL2WithConfig( currentNode, err := arbnode.CreateNode(ctx, stack, execNode, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), nil, nil, nil, nil, nil, feedErrChan) Require(t, err) + // Give the node an init message err = currentNode.TxStreamer.AddFakeInitMessage() Require(t, err) diff --git a/system_tests/contract_tx_test.go b/system_tests/contract_tx_test.go index b35be3614..d6c2eb5f3 100644 --- a/system_tests/contract_tx_test.go +++ b/system_tests/contract_tx_test.go @@ -25,7 +25,7 @@ func TestContractTxDeploy(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, nil, false, nil) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, nil, false) defer node.StopAndWait() from := common.HexToAddress("0x123412341234") diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index 441c99bca..13f4e1f93 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -5,7 +5,6 @@ package arbtest import ( "context" - "github.com/offchainlabs/nitro/arbnode" "math/big" "testing" @@ -132,18 +131,19 @@ func TestDifficultyForLatestArbOS(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) // deploy a test contract - _, _, simple, err := mocksgen.DeploySimple(&auth, client) + _, _, simple, err := mocksgen.DeploySimple(&auth, builder.L2.Client) Require(t, err, "could not deploy contract") tx, err := simple.StoreDifficulty(&auth) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, builder.L2.Client, tx) Require(t, err) difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) Require(t, err) @@ -156,20 +156,20 @@ func TestDifficultyForArbOSTen(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - chainConfig := params.ArbitrumDevTestChainConfig() - chainConfig.ArbitrumChainParams.InitialArbOSVersion = 10 - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, arbnode.ConfigDefaultL2Test(), nil, true, chainConfig) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.chainConfig.ArbitrumChainParams.InitialArbOSVersion = 10 + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) // deploy a test contract - _, _, simple, err := mocksgen.DeploySimple(&auth, client) + _, _, simple, err := mocksgen.DeploySimple(&auth, builder.L2.Client) Require(t, err, "could not deploy contract") tx, err := simple.StoreDifficulty(&auth) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = EnsureTxSucceeded(ctx, builder.L2.Client, tx) Require(t, err) difficulty, err := simple.GetBlockDifficulty(&bind.CallOpts{}) Require(t, err) diff --git a/system_tests/infra_fee_test.go b/system_tests/infra_fee_test.go index ee9671914..a56e05456 100644 --- a/system_tests/infra_fee_test.go +++ b/system_tests/infra_fee_test.go @@ -23,7 +23,7 @@ func TestInfraFee(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, nil, true, nil) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, nil, true) defer node.StopAndWait() l2info.GenerateAccount("User2") diff --git a/system_tests/initialization_test.go b/system_tests/initialization_test.go index dc01aeba4..0e055adc5 100644 --- a/system_tests/initialization_test.go +++ b/system_tests/initialization_test.go @@ -62,7 +62,7 @@ func TestInitContract(t *testing.T) { l2info.ArbInitData.Accounts = append(l2info.ArbInitData.Accounts, accountInfo) expectedSums[accountAddress] = sum } - _, node, client := CreateTestL2WithConfig(t, ctx, l2info, nil, nil, true, nil) + _, node, client := CreateTestL2WithConfig(t, ctx, l2info, nil, nil, true) defer node.StopAndWait() for accountAddress, sum := range expectedSums { diff --git a/system_tests/seq_coordinator_test.go b/system_tests/seq_coordinator_test.go index 37905fc18..a213c366c 100644 --- a/system_tests/seq_coordinator_test.go +++ b/system_tests/seq_coordinator_test.go @@ -63,7 +63,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { createStartNode := func(nodeNum int) { nodeConfig.SeqCoordinator.MyUrl = nodeNames[nodeNum] - _, node, _ := CreateTestL2WithConfig(t, ctx, l2Info, nodeConfig, nil, false, nil) + _, node, _ := CreateTestL2WithConfig(t, ctx, l2Info, nodeConfig, nil, false) nodes[nodeNum] = node } diff --git a/system_tests/seq_nonce_test.go b/system_tests/seq_nonce_test.go index 2856e2946..d70f47a14 100644 --- a/system_tests/seq_nonce_test.go +++ b/system_tests/seq_nonce_test.go @@ -26,7 +26,7 @@ func TestSequencerParallelNonces(t *testing.T) { config := gethexec.ConfigDefaultTest() config.Sequencer.NonceFailureCacheExpiry = time.Minute - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false, nil) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false) defer node.StopAndWait() l2info.GenerateAccount("Destination") @@ -63,7 +63,7 @@ func TestSequencerNonceTooHigh(t *testing.T) { defer cancel() config := gethexec.ConfigDefaultTest() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false, nil) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false) defer node.StopAndWait() l2info.GetInfoWithPrivKey("Owner").Nonce++ @@ -91,7 +91,7 @@ func TestSequencerNonceTooHighQueueFull(t *testing.T) { config := gethexec.ConfigDefaultTest() config.Sequencer.NonceFailureCacheSize = 5 config.Sequencer.NonceFailureCacheExpiry = time.Minute - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false, nil) + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false) defer node.StopAndWait() count := 15 diff --git a/system_tests/seq_reject_test.go b/system_tests/seq_reject_test.go index c067a66bc..34a14c660 100644 --- a/system_tests/seq_reject_test.go +++ b/system_tests/seq_reject_test.go @@ -31,14 +31,14 @@ func TestSequencerRejection(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() feedErrChan := make(chan error, 10) - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true, nil) + l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true) defer nodeA.StopAndWait() clientNodeConfig := arbnode.ConfigDefaultL2Test() port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false, nil) + _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false) defer nodeB.StopAndWait() auth := l2info1.GetDefaultTransactOpts("Owner", ctx) diff --git a/system_tests/seq_whitelist_test.go b/system_tests/seq_whitelist_test.go index b7d85c63c..36e309a5d 100644 --- a/system_tests/seq_whitelist_test.go +++ b/system_tests/seq_whitelist_test.go @@ -18,7 +18,7 @@ func TestSequencerWhitelist(t *testing.T) { config := gethexec.ConfigDefaultTest() config.Sequencer.SenderWhitelist = GetTestAddressForAccountName(t, "Owner").String() + "," + GetTestAddressForAccountName(t, "User").String() - l2info, l2node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, true, nil) + l2info, l2node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, true) defer l2node.StopAndWait() l2info.GenerateAccount("User") diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index 2a53cd858..d0d05d569 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -45,13 +45,13 @@ func TestSequencerFeed(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true, nil) + l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true) defer nodeA.StopAndWait() clientNodeConfig := arbnode.ConfigDefaultL2Test() port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false, nil) + _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false) defer nodeB.StopAndWait() l2info1.GenerateAccount("User2") @@ -80,7 +80,7 @@ func TestRelayedSequencerFeed(t *testing.T) { seqNodeConfig := arbnode.ConfigDefaultL2Test() seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true, nil) + l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true) defer nodeA.StopAndWait() bigChainId, err := client1.ChainID(ctx) @@ -102,7 +102,7 @@ func TestRelayedSequencerFeed(t *testing.T) { clientNodeConfig := arbnode.ConfigDefaultL2Test() port = currentRelay.GetListenerAddr().(*net.TCPAddr).Port clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeC, client3 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false, nil) + _, nodeC, client3 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false) defer nodeC.StopAndWait() StartWatchChanErr(t, ctx, feedErrChan, nodeC) From ba0de156d74168800ccfde059802bd2f2a8e35cb Mon Sep 17 00:00:00 2001 From: amsanghi Date: Thu, 26 Oct 2023 20:05:19 +0530 Subject: [PATCH 334/775] update block validator test --- system_tests/block_validator_test.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index 61a2738b9..0be794edf 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -54,10 +54,13 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops delayEvery = workloadLoops / 3 } - l2info, nodeA, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, nil, chainConfig, nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() - + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.chainConfig = chainConfig + builder.nodeConfig = l1NodeConfigA + builder.L2Info = NewArbTestInfo(t, chainConfig.ChainID) + cleanup := builder.Build(t) + defer cleanup() + l2info, l2client, l1info, l1client := builder.L2Info, builder.L2.Client, builder.L1Info, builder.L1.Client authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) validatorConfig := arbnode.ConfigDefaultL1NonSequencerTest() @@ -65,8 +68,9 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops validatorConfig.DataAvailability = l1NodeConfigA.DataAvailability validatorConfig.DataAvailability.RPCAggregator.Enable = false AddDefaultValNode(t, ctx, validatorConfig, !arbitrator) - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, validatorConfig, nil, nil) - defer nodeB.StopAndWait() + l2B, cleanup2nd := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: validatorConfig}) + defer cleanup2nd() + l2clientB, nodeB := l2B.Client, l2B.ConsensusNode l2info.GenerateAccount("User2") perTransfer := big.NewInt(1e12) From e88f53e12a99e8c8ef553945779f10d0f3e56ba6 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Thu, 26 Oct 2023 09:40:19 -0500 Subject: [PATCH 335/775] Update wsbroadcastserver.go --- wsbroadcastserver/wsbroadcastserver.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/wsbroadcastserver/wsbroadcastserver.go b/wsbroadcastserver/wsbroadcastserver.go index c26a91014..d51b36840 100644 --- a/wsbroadcastserver/wsbroadcastserver.go +++ b/wsbroadcastserver/wsbroadcastserver.go @@ -208,11 +208,7 @@ func (s *WSBroadcastServer) Start(ctx context.Context) error { err := s.StartWithHeader(ctx, header) elapsed := time.Since(startTime) startWithHeaderTimer.Update(elapsed) - - if err != nil { - return err - } - return nil + return err } func (s *WSBroadcastServer) StartWithHeader(ctx context.Context, header ws.HandshakeHeader) error { From 756ef6ff323c6e133882e04cf48f5abecaa0cb50 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 26 Oct 2023 10:43:52 -0500 Subject: [PATCH 336/775] code refactor --- broadcastclients/broadcastclients.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index f50840479..acfcf8045 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -201,7 +201,7 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { // failed to get messages from both primary and secondary feeds for ~5 seconds, start a new secondary feed case <-startSecondaryFeedTimer.C: - bcs.StartSecondaryFeed(ctx) + bcs.startSecondaryFeed(ctx) // failed to get messages from primary feed for ~5 seconds, reset the timer responsible for stopping a secondary case <-primaryFeedIsDownTimer.C: @@ -209,13 +209,13 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { // primary feeds have been up and running for PRIMARY_FEED_UPTIME=10 mins without a failure, stop the recently started secondary feed case <-stopSecondaryFeedTimer.C: - bcs.StopSecondaryFeed(ctx) + bcs.stopSecondaryFeed(ctx) } } }) } -func (bcs *BroadcastClients) StartSecondaryFeed(ctx context.Context) { +func (bcs *BroadcastClients) startSecondaryFeed(ctx context.Context) { if bcs.numOfStartedSecondary < len(bcs.secondaryClients) { client := bcs.secondaryClients[bcs.numOfStartedSecondary] bcs.numOfStartedSecondary += 1 @@ -224,7 +224,7 @@ func (bcs *BroadcastClients) StartSecondaryFeed(ctx context.Context) { log.Warn("failed to start a new secondary feed all available secondary feeds were started") } } -func (bcs *BroadcastClients) StopSecondaryFeed(ctx context.Context) { +func (bcs *BroadcastClients) stopSecondaryFeed(ctx context.Context) { if bcs.numOfStartedSecondary > 0 { bcs.numOfStartedSecondary -= 1 client := bcs.secondaryClients[bcs.numOfStartedSecondary] From cf82b27fe65a2b7ac043a42ff4b9896686b3f412 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 26 Oct 2023 18:59:44 +0200 Subject: [PATCH 337/775] Update nitro-contracts to v1.1.0 --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index b22f93c7a..1a94dabd8 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit b22f93c7a1322fb8063ad71d58acb37416d71146 +Subproject commit 1a94dabd805673e4c85e4071662814a142b20893 From 1969387881cf637f4495d32c4c1c978daa468c06 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 27 Oct 2023 09:09:13 +0200 Subject: [PATCH 338/775] Update maxDataSize param description --- cmd/deploy/deploy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/deploy/deploy.go b/cmd/deploy/deploy.go index d726ad21f..0b7203890 100644 --- a/cmd/deploy/deploy.go +++ b/cmd/deploy/deploy.go @@ -41,7 +41,7 @@ func main() { ownerAddressString := flag.String("ownerAddress", "", "the rollup owner's address") sequencerAddressString := flag.String("sequencerAddress", "", "the sequencer's address") nativeTokenAddressString := flag.String("nativeTokenAddress", "0x0000000000000000000000000000000000000000", "address of the ERC20 token which is used as native L2 currency") - maxDataSizeUint := flag.Uint64("maxDataSize", 117964, "maximum size of data") + maxDataSizeUint := flag.Uint64("maxDataSize", 117964, "maximum data size of a batch or a cross-chain message (default = 90% of Geth's 128KB tx size limit)") loserEscrowAddressString := flag.String("loserEscrowAddress", "", "the address which half of challenge loser's funds accumulate at") wasmmoduleroot := flag.String("wasmmoduleroot", "", "WASM module root hash") wasmrootpath := flag.String("wasmrootpath", "", "path to machine folders") From 1e5a97b2139a6df1793af90143b180c326929ef8 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 27 Oct 2023 13:46:38 +0200 Subject: [PATCH 339/775] Turn on feature to deploy the L2 utility factories as part of rollup creation process --- arbnode/node.go | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 0782e8ecb..b026284ef 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -41,6 +41,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/ospgen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" + "github.com/offchainlabs/nitro/solgen/go/test_helpersgen" "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/staker/validatorwallet" @@ -292,7 +293,7 @@ func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReade return nil, errors.New("no machine specified") } - rollupCreator, _, validatorUtils, validatorWalletCreator, err := deployRollupCreator(ctx, parentChainReader, deployAuth, maxDataSize) + rollupCreator, rollupCreatorAddress, validatorUtils, validatorWalletCreator, err := deployRollupCreator(ctx, parentChainReader, deployAuth, maxDataSize) if err != nil { return nil, fmt.Errorf("error deploying rollup creator: %w", err) } @@ -302,14 +303,32 @@ func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReade validatorAddrs = append(validatorAddrs, crypto.CreateAddress(validatorWalletCreator, i)) } + // 0.13 ETH is enough to deploy L2 factories via retryables. Excess is refunded + feeCost := big.NewInt(130000000000000000) + // if there is a fee token, approve the rollup creator to spend it + if (nativeToken != common.Address{}) { + // use ERC20 binding to approve + nativeTokenContract, err := test_helpersgen.NewTestToken(nativeToken, parentChainReader.Client()) + if err != nil { + return nil, fmt.Errorf("error binding native token: %w", err) + } + tx, err := nativeTokenContract.Approve(deployAuth, rollupCreatorAddress, feeCost) + err = andTxSucceeded(ctx, parentChainReader, tx, err) + if err != nil { + return nil, fmt.Errorf("error calling approve: %w", err) + } + feeCost = big.NewInt(0) + } + + deployAuth.Value = feeCost deployParams := rollupgen.RollupCreatorRollupDeploymentParams{ Config: config, BatchPoster: batchPoster, Validators: validatorAddrs, MaxDataSize: maxDataSize, NativeToken: nativeToken, - DeployFactoriesToL2: false, - MaxFeePerGasForRetryables: big.NewInt(0), // needed when utility factories are deployed + DeployFactoriesToL2: true, + MaxFeePerGasForRetryables: big.NewInt(100000000), // 0.1 gwei } tx, err := rollupCreator.CreateRollup( From e1eb6b520557fd603ea4b6948a0886f826bc0cff Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 27 Oct 2023 14:31:00 +0200 Subject: [PATCH 340/775] Revert "Turn on feature to deploy the L2 utility factories as part of rollup creation process" This reverts commit 1e5a97b2139a6df1793af90143b180c326929ef8. --- arbnode/node.go | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index b026284ef..0782e8ecb 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -41,7 +41,6 @@ import ( "github.com/offchainlabs/nitro/solgen/go/ospgen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" - "github.com/offchainlabs/nitro/solgen/go/test_helpersgen" "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/staker/validatorwallet" @@ -293,7 +292,7 @@ func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReade return nil, errors.New("no machine specified") } - rollupCreator, rollupCreatorAddress, validatorUtils, validatorWalletCreator, err := deployRollupCreator(ctx, parentChainReader, deployAuth, maxDataSize) + rollupCreator, _, validatorUtils, validatorWalletCreator, err := deployRollupCreator(ctx, parentChainReader, deployAuth, maxDataSize) if err != nil { return nil, fmt.Errorf("error deploying rollup creator: %w", err) } @@ -303,32 +302,14 @@ func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReade validatorAddrs = append(validatorAddrs, crypto.CreateAddress(validatorWalletCreator, i)) } - // 0.13 ETH is enough to deploy L2 factories via retryables. Excess is refunded - feeCost := big.NewInt(130000000000000000) - // if there is a fee token, approve the rollup creator to spend it - if (nativeToken != common.Address{}) { - // use ERC20 binding to approve - nativeTokenContract, err := test_helpersgen.NewTestToken(nativeToken, parentChainReader.Client()) - if err != nil { - return nil, fmt.Errorf("error binding native token: %w", err) - } - tx, err := nativeTokenContract.Approve(deployAuth, rollupCreatorAddress, feeCost) - err = andTxSucceeded(ctx, parentChainReader, tx, err) - if err != nil { - return nil, fmt.Errorf("error calling approve: %w", err) - } - feeCost = big.NewInt(0) - } - - deployAuth.Value = feeCost deployParams := rollupgen.RollupCreatorRollupDeploymentParams{ Config: config, BatchPoster: batchPoster, Validators: validatorAddrs, MaxDataSize: maxDataSize, NativeToken: nativeToken, - DeployFactoriesToL2: true, - MaxFeePerGasForRetryables: big.NewInt(100000000), // 0.1 gwei + DeployFactoriesToL2: false, + MaxFeePerGasForRetryables: big.NewInt(0), // needed when utility factories are deployed } tx, err := rollupCreator.CreateRollup( From ba6ca95ce1fe1ef9cd5b1bd79acfa6aba2442282 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 27 Oct 2023 16:54:46 +0200 Subject: [PATCH 341/775] Fix TestChallengeManagerFullAsserter tests Use newer version of geth with statedb use after Commit issue fixed. --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 2a53ab681..627e5f3c0 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 2a53ab6818d2f3641c17f5adc11de99394184374 +Subproject commit 627e5f3c0464cec6b8cf42c4d6eaa5b095e45f88 From 0871ed186db11cbda2e62842335bb33c82db63bd Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 27 Oct 2023 11:17:04 -0500 Subject: [PATCH 342/775] Add pause to stopwaiter to enable restart after stopping --- broadcastclients/broadcastclients.go | 5 +++-- util/stopwaiter/stopwaiter.go | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index acfcf8045..52346ecbb 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -220,7 +220,7 @@ func (bcs *BroadcastClients) startSecondaryFeed(ctx context.Context) { client := bcs.secondaryClients[bcs.numOfStartedSecondary] bcs.numOfStartedSecondary += 1 client.Start(ctx) - } else { + } else if len(bcs.secondaryClients) > 0 { log.Warn("failed to start a new secondary feed all available secondary feeds were started") } } @@ -228,7 +228,8 @@ func (bcs *BroadcastClients) stopSecondaryFeed(ctx context.Context) { if bcs.numOfStartedSecondary > 0 { bcs.numOfStartedSecondary -= 1 client := bcs.secondaryClients[bcs.numOfStartedSecondary] - client.StopAndWait() + client.Pause() + log.Info("disconnected secondary feed") } } diff --git a/util/stopwaiter/stopwaiter.go b/util/stopwaiter/stopwaiter.go index 1e70e328e..e279e333a 100644 --- a/util/stopwaiter/stopwaiter.go +++ b/util/stopwaiter/stopwaiter.go @@ -116,6 +116,20 @@ func (s *StopWaiterSafe) StopAndWait() error { return s.stopAndWaitImpl(stopDelayWarningTimeout) } +// Pause calls StopAndWait but updates started and stopped booleans to default. Only call if you want to restart the stopwaiter +func (s *StopWaiterSafe) Pause() error { + if err := s.stopAndWaitImpl(stopDelayWarningTimeout); err != nil { + return err + } + + s.mutex.Lock() + defer s.mutex.Unlock() + s.started = false + s.stopped = false + + return nil +} + func getAllStackTraces() string { buf := make([]byte, 64*1024*1024) size := runtime.Stack(buf, true) @@ -326,6 +340,12 @@ func (s *StopWaiter) StopAndWait() { } } +func (s *StopWaiter) Pause() { + if err := s.StopWaiterSafe.Pause(); err != nil { + panic(err) + } +} + // If stop was already called, thread might silently not be launched func (s *StopWaiter) LaunchThread(foo func(context.Context)) { if err := s.StopWaiterSafe.LaunchThreadSafe(foo); err != nil { From 5441b43832ddbb6b905d6cddcbaec12b800cf82b Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 27 Oct 2023 11:47:15 -0500 Subject: [PATCH 343/775] Retain new feed messages when cache is cleared --- arbnode/transaction_streamer.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index bcc389dc0..2ee1526ee 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -696,6 +696,7 @@ func (s *TransactionStreamer) addMessagesAndEndBatchImpl(messageStartPos arbutil var oldMsg *arbostypes.MessageWithMetadata var lastDelayedRead uint64 var hasNewConfirmedMessages bool + var cacheClearLen int messagesAfterPos := messageStartPos + arbutil.MessageIndex(len(messages)) broadcastStartPos := arbutil.MessageIndex(atomic.LoadUint64(&s.broadcasterQueuedMessagesPos)) @@ -724,10 +725,13 @@ func (s *TransactionStreamer) addMessagesAndEndBatchImpl(messageStartPos arbutil // Or no active broadcast reorg and broadcast messages start before or immediately after last L1 message if messagesAfterPos >= broadcastStartPos { broadcastSliceIndex := int(messagesAfterPos - broadcastStartPos) + messagesOldLen := len(messages) if broadcastSliceIndex < len(s.broadcasterQueuedMessages) { // Some cached feed messages can be used messages = append(messages, s.broadcasterQueuedMessages[broadcastSliceIndex:]...) } + // This calculation gives the exact length of cache which was appended to messages + cacheClearLen = broadcastSliceIndex + len(messages) - messagesOldLen } // L1 used or replaced broadcast cache items @@ -800,8 +804,14 @@ func (s *TransactionStreamer) addMessagesAndEndBatchImpl(messageStartPos arbutil } if clearQueueOnSuccess { - s.broadcasterQueuedMessages = s.broadcasterQueuedMessages[:0] - atomic.StoreUint64(&s.broadcasterQueuedMessagesPos, 0) + // Check if new messages were added at the end of cache, if they were, then dont remove those particular messages + if len(s.broadcasterQueuedMessages) > cacheClearLen { + s.broadcasterQueuedMessages = s.broadcasterQueuedMessages[cacheClearLen:] + atomic.StoreUint64(&s.broadcasterQueuedMessagesPos, uint64(broadcastStartPos)+uint64(cacheClearLen)) + } else { + s.broadcasterQueuedMessages = s.broadcasterQueuedMessages[:0] + atomic.StoreUint64(&s.broadcasterQueuedMessagesPos, 0) + } s.broadcasterQueuedMessagesActiveReorg = false } From dd8a25655bffcf25d9493ad29248308f32d66ea4 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 27 Oct 2023 15:34:12 -0500 Subject: [PATCH 344/775] remove pause implementation and code refactor --- broadcastclients/broadcastclients.go | 88 +++++++++++++++------------- util/stopwaiter/stopwaiter.go | 20 ------- 2 files changed, 46 insertions(+), 62 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index 52346ecbb..7fef07be7 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -42,6 +42,7 @@ func (r *Router) AddBroadcastMessages(feedMessages []*broadcaster.BroadcastFeedM type BroadcastClients struct { primaryClients []*broadcastclient.BroadcastClient secondaryClients []*broadcastclient.BroadcastClient + secondaryURL []string numOfStartedSecondary int primaryRouter *Router @@ -51,6 +52,8 @@ type BroadcastClients struct { connected int32 } +var makeClient func(string, *Router) (*broadcastclient.BroadcastClient, error) + func NewBroadcastClients( configFetcher broadcastclient.ConfigFetcher, l2ChainId uint64, @@ -75,44 +78,36 @@ func NewBroadcastClients( clients := BroadcastClients{ primaryRouter: newStandardRouter(), secondaryRouter: newStandardRouter(), + secondaryURL: config.SecondaryURL, } var lastClientErr error - makeFeeds := func(url []string, router *Router) []*broadcastclient.BroadcastClient { - feeds := make([]*broadcastclient.BroadcastClient, 0, len(url)) - for _, address := range url { - client, err := broadcastclient.NewBroadcastClient( - configFetcher, - address, - l2ChainId, - currentMessageCount, - router, - router.confirmedSequenceNumberChan, - fatalErrChan, - addrVerifier, - func(delta int32) { clients.adjustCount(delta) }, - ) - if err != nil { - lastClientErr = err - log.Warn("init broadcast client failed", "address", address) - continue - } - feeds = append(feeds, client) - } - return feeds + makeClient = func(url string, router *Router) (*broadcastclient.BroadcastClient, error) { + return broadcastclient.NewBroadcastClient( + configFetcher, + url, + l2ChainId, + currentMessageCount, + router, + router.confirmedSequenceNumberChan, + fatalErrChan, + addrVerifier, + func(delta int32) { clients.adjustCount(delta) }, + ) } - clients.primaryClients = makeFeeds(config.URL, clients.primaryRouter) - clients.secondaryClients = makeFeeds(config.SecondaryURL, clients.secondaryRouter) - - if len(clients.primaryClients) == 0 && len(clients.secondaryClients) == 0 { - log.Error("no connected feed on startup, last error: %w", lastClientErr) - return nil, nil + clients.primaryClients = make([]*broadcastclient.BroadcastClient, 0, len(config.URL)) + for _, address := range config.URL { + client, err := makeClient(address, clients.primaryRouter) + if err != nil { + lastClientErr = err + log.Warn("init broadcast client failed", "address", address) + continue + } + clients.primaryClients = append(clients.primaryClients, client) } - - // have atleast one primary client if len(clients.primaryClients) == 0 { - clients.primaryClients = append(clients.primaryClients, clients.secondaryClients[0]) - clients.secondaryClients = clients.secondaryClients[1:] + log.Error("no connected feed on startup, last error: %w", lastClientErr) + return nil, nil } return &clients, nil @@ -209,27 +204,36 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { // primary feeds have been up and running for PRIMARY_FEED_UPTIME=10 mins without a failure, stop the recently started secondary feed case <-stopSecondaryFeedTimer.C: - bcs.stopSecondaryFeed(ctx) + bcs.stopSecondaryFeed() } } }) } func (bcs *BroadcastClients) startSecondaryFeed(ctx context.Context) { - if bcs.numOfStartedSecondary < len(bcs.secondaryClients) { - client := bcs.secondaryClients[bcs.numOfStartedSecondary] + if bcs.numOfStartedSecondary < len(bcs.secondaryURL) { + pos := bcs.numOfStartedSecondary + url := bcs.secondaryURL[pos] + client, err := makeClient(url, bcs.secondaryRouter) + if err != nil { + log.Warn("init broadcast secondary client failed", "address", url) + bcs.secondaryURL = append(bcs.secondaryURL[:pos], bcs.secondaryURL[pos+1:]...) + return + } bcs.numOfStartedSecondary += 1 + bcs.secondaryClients = append(bcs.secondaryClients, client) client.Start(ctx) - } else if len(bcs.secondaryClients) > 0 { + log.Info("secondary feed started", "url", url) + } else if len(bcs.secondaryURL) > 0 { log.Warn("failed to start a new secondary feed all available secondary feeds were started") } } -func (bcs *BroadcastClients) stopSecondaryFeed(ctx context.Context) { + +func (bcs *BroadcastClients) stopSecondaryFeed() { if bcs.numOfStartedSecondary > 0 { bcs.numOfStartedSecondary -= 1 - client := bcs.secondaryClients[bcs.numOfStartedSecondary] - client.Pause() - log.Info("disconnected secondary feed") + bcs.secondaryClients[bcs.numOfStartedSecondary].StopAndWait() + log.Info("disconnected secondary feed", "url", bcs.secondaryURL[bcs.numOfStartedSecondary]) } } @@ -237,7 +241,7 @@ func (bcs *BroadcastClients) StopAndWait() { for _, client := range bcs.primaryClients { client.StopAndWait() } - for i := 0; i < bcs.numOfStartedSecondary; i++ { - bcs.secondaryClients[i].StopAndWait() + for _, client := range bcs.secondaryClients { + client.StopAndWait() } } diff --git a/util/stopwaiter/stopwaiter.go b/util/stopwaiter/stopwaiter.go index e279e333a..1e70e328e 100644 --- a/util/stopwaiter/stopwaiter.go +++ b/util/stopwaiter/stopwaiter.go @@ -116,20 +116,6 @@ func (s *StopWaiterSafe) StopAndWait() error { return s.stopAndWaitImpl(stopDelayWarningTimeout) } -// Pause calls StopAndWait but updates started and stopped booleans to default. Only call if you want to restart the stopwaiter -func (s *StopWaiterSafe) Pause() error { - if err := s.stopAndWaitImpl(stopDelayWarningTimeout); err != nil { - return err - } - - s.mutex.Lock() - defer s.mutex.Unlock() - s.started = false - s.stopped = false - - return nil -} - func getAllStackTraces() string { buf := make([]byte, 64*1024*1024) size := runtime.Stack(buf, true) @@ -340,12 +326,6 @@ func (s *StopWaiter) StopAndWait() { } } -func (s *StopWaiter) Pause() { - if err := s.StopWaiterSafe.Pause(); err != nil { - panic(err) - } -} - // If stop was already called, thread might silently not be launched func (s *StopWaiter) LaunchThread(foo func(context.Context)) { if err := s.StopWaiterSafe.LaunchThreadSafe(foo); err != nil { From 1f0ac34e128bb048882f22b10b8753b96d5e31c3 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 27 Oct 2023 15:59:33 -0500 Subject: [PATCH 345/775] code refactor --- broadcastclients/broadcastclients.go | 33 ++++++++++++++-------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index 7fef07be7..551dcdb46 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -40,10 +40,9 @@ func (r *Router) AddBroadcastMessages(feedMessages []*broadcaster.BroadcastFeedM } type BroadcastClients struct { - primaryClients []*broadcastclient.BroadcastClient - secondaryClients []*broadcastclient.BroadcastClient - secondaryURL []string - numOfStartedSecondary int + primaryClients []*broadcastclient.BroadcastClient + secondaryClients []*broadcastclient.BroadcastClient + secondaryURL []string primaryRouter *Router secondaryRouter *Router @@ -76,11 +75,12 @@ func NewBroadcastClients( } } clients := BroadcastClients{ - primaryRouter: newStandardRouter(), - secondaryRouter: newStandardRouter(), - secondaryURL: config.SecondaryURL, + primaryRouter: newStandardRouter(), + secondaryRouter: newStandardRouter(), + primaryClients: make([]*broadcastclient.BroadcastClient, 0, len(config.URL)), + secondaryClients: make([]*broadcastclient.BroadcastClient, 0, len(config.SecondaryURL)), + secondaryURL: config.SecondaryURL, } - var lastClientErr error makeClient = func(url string, router *Router) (*broadcastclient.BroadcastClient, error) { return broadcastclient.NewBroadcastClient( configFetcher, @@ -95,7 +95,7 @@ func NewBroadcastClients( ) } - clients.primaryClients = make([]*broadcastclient.BroadcastClient, 0, len(config.URL)) + var lastClientErr error for _, address := range config.URL { client, err := makeClient(address, clients.primaryRouter) if err != nil { @@ -211,8 +211,8 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { } func (bcs *BroadcastClients) startSecondaryFeed(ctx context.Context) { - if bcs.numOfStartedSecondary < len(bcs.secondaryURL) { - pos := bcs.numOfStartedSecondary + pos := len(bcs.secondaryClients) + if pos < len(bcs.secondaryURL) { url := bcs.secondaryURL[pos] client, err := makeClient(url, bcs.secondaryRouter) if err != nil { @@ -220,7 +220,6 @@ func (bcs *BroadcastClients) startSecondaryFeed(ctx context.Context) { bcs.secondaryURL = append(bcs.secondaryURL[:pos], bcs.secondaryURL[pos+1:]...) return } - bcs.numOfStartedSecondary += 1 bcs.secondaryClients = append(bcs.secondaryClients, client) client.Start(ctx) log.Info("secondary feed started", "url", url) @@ -230,10 +229,12 @@ func (bcs *BroadcastClients) startSecondaryFeed(ctx context.Context) { } func (bcs *BroadcastClients) stopSecondaryFeed() { - if bcs.numOfStartedSecondary > 0 { - bcs.numOfStartedSecondary -= 1 - bcs.secondaryClients[bcs.numOfStartedSecondary].StopAndWait() - log.Info("disconnected secondary feed", "url", bcs.secondaryURL[bcs.numOfStartedSecondary]) + pos := len(bcs.secondaryClients) + if pos > 0 { + pos -= 1 + bcs.secondaryClients[pos].StopAndWait() + bcs.secondaryClients = bcs.secondaryClients[:pos] + log.Info("disconnected secondary feed", "url", bcs.secondaryURL[pos]) } } From be17feabe83895f8abff4a110c84d705e9f67ba4 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 30 Oct 2023 12:51:49 +0100 Subject: [PATCH 346/775] Update nitro-contracts ref to include sha256 preimage support --- contracts | 2 +- nitro-testnode | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts b/contracts index 1a94dabd8..695750067 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 1a94dabd805673e4c85e4071662814a142b20893 +Subproject commit 695750067b2b7658556bdf61ec8cf16132d83dd0 diff --git a/nitro-testnode b/nitro-testnode index 11170fe36..3a7b2cee2 160000 --- a/nitro-testnode +++ b/nitro-testnode @@ -1 +1 @@ -Subproject commit 11170fe36318991973bea632d9f348816a64a974 +Subproject commit 3a7b2cee29cf591cc4c3f6c5ddc00bf5be367bd9 From 5da8bfb6d60fb4a46957065e88b0156706e9fbc6 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Mon, 30 Oct 2023 17:26:16 -0700 Subject: [PATCH 347/775] Update geth pin for merge-v1.12.1 --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 627e5f3c0..93b7de9a2 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 627e5f3c0464cec6b8cf42c4d6eaa5b095e45f88 +Subproject commit 93b7de9a246a428aa338670536e4e9ce7c8901fe From 3f275eece332005f88142c7ef674fa987e2e577e Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 31 Oct 2023 13:17:32 -0600 Subject: [PATCH 348/775] testnode: update --- nitro-testnode | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nitro-testnode b/nitro-testnode index 3a7b2cee2..bb3f094f4 160000 --- a/nitro-testnode +++ b/nitro-testnode @@ -1 +1 @@ -Subproject commit 3a7b2cee29cf591cc4c3f6c5ddc00bf5be367bd9 +Subproject commit bb3f094f4359780c2a9aba28e15bb845be9b35a3 From c5b9eebdcd68ebe53b2d6b2d77490a86c484024c Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Tue, 31 Oct 2023 12:38:00 -0700 Subject: [PATCH 349/775] Update dependencies for dependabot --- go.mod | 26 ++++++++++++++------------ go.sum | 47 ++++++++++++++++++++++++++--------------------- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/go.mod b/go.mod index cdfae4df1..5ab2eda5c 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.10 github.com/aws/aws-sdk-go-v2/service/s3 v1.26.9 github.com/cavaliergopher/grab/v3 v3.0.1 + github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 github.com/codeclysm/extract/v3 v3.0.2 github.com/dgraph-io/badger/v3 v3.2103.2 github.com/enescakir/emoji v1.0.0 @@ -36,7 +37,7 @@ require ( github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 github.com/spf13/pflag v1.0.5 github.com/wealdtech/go-merkletree v1.0.0 - golang.org/x/term v0.6.0 + golang.org/x/term v0.13.0 golang.org/x/tools v0.7.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) @@ -74,7 +75,6 @@ require ( github.com/cespare/xxhash v1.1.0 // indirect github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 // indirect github.com/cockroachdb/redact v1.1.3 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect @@ -106,7 +106,7 @@ require ( github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.3.0 // indirect - github.com/golang/glog v1.0.0 // indirect + github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect @@ -268,9 +268,11 @@ require ( golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect golang.org/x/mod v0.10.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect - google.golang.org/grpc v1.53.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/grpc v1.59.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect lukechampine.com/blake3 v1.1.7 // indirect nhooyr.io/websocket v1.8.7 // indirect @@ -296,7 +298,7 @@ require ( github.com/go-redis/redis/v8 v8.11.4 github.com/go-stack/stack v1.8.1 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.3.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect @@ -317,11 +319,11 @@ require ( github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect - golang.org/x/crypto v0.7.0 - golang.org/x/net v0.8.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.7.0 - golang.org/x/text v0.8.0 // indirect + golang.org/x/crypto v0.14.0 + golang.org/x/net v0.17.0 // indirect + golang.org/x/sync v0.3.0 // indirect + golang.org/x/sys v0.13.0 + golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect ) diff --git a/go.sum b/go.sum index db81b3a07..424e3508c 100644 --- a/go.sum +++ b/go.sum @@ -441,8 +441,9 @@ github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzq github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -527,8 +528,8 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -1761,8 +1762,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1860,8 +1861,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1883,8 +1884,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1981,14 +1982,14 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1999,8 +2000,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2143,8 +2144,12 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= +google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a h1:myvhA4is3vrit1a6NZCWBIwN0kNEnX21DJOJX/NvIfI= +google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= @@ -2176,8 +2181,8 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -2192,8 +2197,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 7972e29a2d58d881abde02ab2a3623df84c68dda Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 1 Nov 2023 09:39:01 -0600 Subject: [PATCH 350/775] sequence delayed initially when starting without coordinator --- arbnode/node.go | 21 +++++++++++++++------ arbnode/seq_coordinator.go | 3 --- execution/gethexec/sequencer.go | 1 + 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 0782e8ecb..93e7894fe 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -1053,8 +1053,23 @@ func (n *Node) Start(ctx context.Context) error { return fmt.Errorf("error starting inbox reader: %w", err) } } + // must init broadcast server before trying to sequence anything + if n.BroadcastServer != nil { + err = n.BroadcastServer.Start(ctx) + if err != nil { + return fmt.Errorf("error starting feed broadcast server: %w", err) + } + } if n.SeqCoordinator != nil { n.SeqCoordinator.Start(ctx) + } else { + if n.DelayedSequencer != nil { + err := n.DelayedSequencer.ForceSequenceDelayed(ctx) + if err != nil { + return fmt.Errorf("error initially sequencing delayed instructions: %w", err) + } + } + n.Execution.Activate() } if n.MaintenanceRunner != nil { n.MaintenanceRunner.Start(ctx) @@ -1101,12 +1116,6 @@ func (n *Node) Start(ctx context.Context) error { if n.L1Reader != nil { n.L1Reader.Start(ctx) } - if n.BroadcastServer != nil { - err = n.BroadcastServer.Start(ctx) - if err != nil { - return fmt.Errorf("error starting feed broadcast server: %w", err) - } - } if n.BroadcastClients != nil { go func() { if n.InboxReader != nil { diff --git a/arbnode/seq_coordinator.go b/arbnode/seq_coordinator.go index 1e8405e01..cb6f4fe50 100644 --- a/arbnode/seq_coordinator.go +++ b/arbnode/seq_coordinator.go @@ -156,9 +156,6 @@ func NewSeqCoordinator( config: config, signer: signer, } - if sequencer != nil { - sequencer.Pause() - } streamer.SetSeqCoordinator(coordinator) return coordinator, nil } diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 61792ed9b..782ab8753 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -322,6 +322,7 @@ func NewSequencer(execEngine *ExecutionEngine, l1Reader *headerreader.HeaderRead containers.NewLruCacheWithOnEvict(config.NonceCacheSize, s.onNonceFailureEvict), func() time.Duration { return configFetcher().NonceFailureCacheExpiry }, } + s.Pause() execEngine.EnableReorgSequencing() return s, nil } From 1356435881cde93fc94debe024ecc983425df2bf Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Wed, 1 Nov 2023 13:28:34 -0700 Subject: [PATCH 351/775] Update merge-v1.12.1 geth pin --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 93b7de9a2..4b278324b 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 93b7de9a246a428aa338670536e4e9ce7c8901fe +Subproject commit 4b278324b5efe7d6f66cd5421a9d8de66a0a636a From ff5a53066612bdf4e2b0749da76138d797022de4 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 1 Nov 2023 23:22:09 -0600 Subject: [PATCH 352/775] Use new DataPoster storage encoding by default --- arbnode/dataposter/data_poster.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 1a202171e..b5be06af5 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -823,7 +823,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ AllocateMempoolBalance: true, UseDBStorage: true, UseNoOpStorage: false, - LegacyStorageEncoding: true, + LegacyStorageEncoding: false, Dangerous: DangerousConfig{ClearDBStorage: false}, ExternalSigner: ExternalSignerCfg{Method: "eth_signTransaction"}, } @@ -847,6 +847,7 @@ var TestDataPosterConfig = DataPosterConfig{ AllocateMempoolBalance: true, UseDBStorage: false, UseNoOpStorage: false, + LegacyStorageEncoding: false, ExternalSigner: ExternalSignerCfg{Method: "eth_signTransaction"}, } From cc73d70009e54b403ecec75ba9a15546106c705f Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 1 Nov 2023 23:35:09 -0600 Subject: [PATCH 353/775] Match against "execution reverted" case insensitive --- staker/execution_reverted_test.go | 26 ++++++++++++++++++++++++++ staker/rollup_watcher.go | 7 +++++-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 staker/execution_reverted_test.go diff --git a/staker/execution_reverted_test.go b/staker/execution_reverted_test.go new file mode 100644 index 000000000..98a3bdfd6 --- /dev/null +++ b/staker/execution_reverted_test.go @@ -0,0 +1,26 @@ +package staker + +import ( + "io" + "testing" +) + +func TestExecutionRevertedRegexp(t *testing.T) { + executionRevertedErrors := []string{ + // go-ethereum and most other execution clients return "execution reverted" + "execution reverted", + // execution clients may decode the EVM revert data as a string and include it in the error + "execution reverted: FOO", + // besu returns "Execution reverted" + "Execution reverted", + } + for _, errString := range executionRevertedErrors { + if !executionRevertedRegexp.MatchString(errString) { + t.Fatalf("execution reverted regexp didn't match %q", errString) + } + } + // This regexp should not match random IO errors + if executionRevertedRegexp.MatchString(io.ErrUnexpectedEOF.Error()) { + t.Fatal("execution reverted regexp matched unexpected EOF") + } +} diff --git a/staker/rollup_watcher.go b/staker/rollup_watcher.go index 2fa3f888e..59a23d891 100644 --- a/staker/rollup_watcher.go +++ b/staker/rollup_watcher.go @@ -9,7 +9,7 @@ import ( "errors" "fmt" "math/big" - "strings" + "regexp" "sync/atomic" "github.com/ethereum/go-ethereum/common" @@ -72,6 +72,9 @@ func (r *RollupWatcher) getCallOpts(ctx context.Context) *bind.CallOpts { return &opts } +// A regexp matching "execution reverted" errors returned from the parent chain RPC. +var executionRevertedRegexp = regexp.MustCompile("(?i)execution reverted") + func (r *RollupWatcher) getNodeCreationBlock(ctx context.Context, nodeNum uint64) (*big.Int, error) { callOpts := r.getCallOpts(ctx) if !r.unSupportedL3Method.Load() { @@ -80,7 +83,7 @@ func (r *RollupWatcher) getNodeCreationBlock(ctx context.Context, nodeNum uint64 return createdAtBlock, nil } log.Trace("failed to call getNodeCreationBlockForLogLookup, falling back on node CreatedAtBlock field", "err", err) - if strings.Contains(err.Error(), "execution reverted") { + if executionRevertedRegexp.MatchString(err.Error()) { r.unSupportedL3Method.Store(true) } else { return nil, err From bac419077a8778a4cf8f29ecaa24156b2ffaa79f Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 2 Nov 2023 13:00:43 -0700 Subject: [PATCH 354/775] Fix cond tx test, base bounds on l2 block time --- system_tests/conditionaltx_test.go | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index 3bac22ed0..d2284eb5b 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -102,7 +102,7 @@ func getOptions(address common.Address, rootHash common.Hash, slotValueMap map[c } func getFulfillableBlockTimeLimits(t *testing.T, blockNumber uint64, timestamp uint64) []*arbitrum_types.ConditionalOptions { - future := math.HexOrDecimal64(timestamp + 30) + future := math.HexOrDecimal64(timestamp + 40) past := math.HexOrDecimal64(timestamp - 1) futureBlockNumber := math.HexOrDecimal64(blockNumber + 1000) currentBlockNumber := math.HexOrDecimal64(blockNumber) @@ -238,23 +238,18 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { block, err := builder.L1.Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber := block.NumberU64() - fixBlockTime := func(blockTime uint64) uint64 { - since := time.Now().Unix() - int64(blockTime) - if since < 0 { - // If using SimulatedBeacon then the block time will be ahead of - // the actual time since it generates a new block for each tx in - // on demand mode, and assigns them to sequentially increasing timestamps. - return uint64(time.Now().Unix()) - } - return blockTime + + l2BlockTime := func() uint64 { + l2Block, err := builder.L2.Client.BlockByNumber(ctx, nil) + Require(t, err) + return l2Block.Time() } - blockTime := fixBlockTime(block.Time()) optionsA := getOptions(contractAddress1, currentRootHash1, currentSlotValueMap1) optionsB := getOptions(contractAddress2, currentRootHash2, currentSlotValueMap2) optionsAB := optionsProduct(optionsA, optionsB) options1 := dedupOptions(t, append(append(optionsAB, optionsA...), optionsB...)) - options1 = optionsDedupProduct(t, options1, getFulfillableBlockTimeLimits(t, blockNumber, blockTime)) + options1 = optionsDedupProduct(t, options1, getFulfillableBlockTimeLimits(t, blockNumber, l2BlockTime())) for i, options := range options1 { testConditionalTxThatShouldSucceed(t, ctx, i, builder.L2Info, rpcClient, options) } @@ -285,13 +280,12 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { block, err = builder.L1.Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() - blockTime = fixBlockTime(block.Time()) optionsC := getOptions(contractAddress1, currentRootHash1, currentSlotValueMap1) optionsD := getOptions(contractAddress2, currentRootHash2, currentSlotValueMap2) optionsCD := optionsProduct(optionsC, optionsD) options2 := dedupOptions(t, append(append(optionsCD, optionsC...), optionsD...)) - options2 = optionsDedupProduct(t, options2, getFulfillableBlockTimeLimits(t, blockNumber, blockTime)) + options2 = optionsDedupProduct(t, options2, getFulfillableBlockTimeLimits(t, blockNumber, l2BlockTime())) for i, options := range options2 { testConditionalTxThatShouldSucceed(t, ctx, i, builder.L2Info, rpcClient, options) } @@ -301,8 +295,7 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { block, err = builder.L1.Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() - blockTime = fixBlockTime(block.Time()) - options3 := optionsDedupProduct(t, options2, getUnfulfillableBlockTimeLimits(t, blockNumber, blockTime)) + options3 := optionsDedupProduct(t, options2, getUnfulfillableBlockTimeLimits(t, blockNumber, l2BlockTime())) for i, options := range options3 { testConditionalTxThatShouldFail(t, ctx, i, builder.L2Info, rpcClient, options, -32003) } From 02b096e82af7423354478f6c006f9b3759d604bc Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 2 Nov 2023 16:07:16 -0700 Subject: [PATCH 355/775] Update geth pin for merge-v1.12.1 --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 4b278324b..890cbcac4 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 4b278324b5efe7d6f66cd5421a9d8de66a0a636a +Subproject commit 890cbcac4ec591088761a3cf2cdec9bf29183cbb From d4b9f31b7053bb3ca049256ee1a4c9a48d44cca5 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 3 Nov 2023 10:38:40 -0500 Subject: [PATCH 356/775] Allow orbit chains to add additional transaction validity checks --- arbos/block_processor.go | 5 +++++ arbos/extra_transaction_checks.go | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 arbos/extra_transaction_checks.go diff --git a/arbos/block_processor.go b/arbos/block_processor.go index 6f87864b6..928928627 100644 --- a/arbos/block_processor.go +++ b/arbos/block_processor.go @@ -327,6 +327,11 @@ func ProduceBlockAdvanced( return nil, nil, err } + // Additional transaction validity check + if err = extraTxFilter(chainConfig, header, statedb, state, tx, options, sender, l1Info, result); err != nil { + return nil, nil, err + } + return receipt, result, nil })() diff --git a/arbos/extra_transaction_checks.go b/arbos/extra_transaction_checks.go new file mode 100644 index 000000000..758442c96 --- /dev/null +++ b/arbos/extra_transaction_checks.go @@ -0,0 +1,27 @@ +package arbos + +import ( + "github.com/ethereum/go-ethereum/arbitrum_types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" + "github.com/offchainlabs/nitro/arbos/arbosState" +) + +// extraTxFilter should be modified by chain operators to enforce additional transaction validity rules +func extraTxFilter( + chainConfig *params.ChainConfig, + currentBlockHeader *types.Header, + statedb *state.StateDB, + state *arbosState.ArbosState, + tx *types.Transaction, + options *arbitrum_types.ConditionalOptions, + sender common.Address, + l1Info *L1Info, + result *core.ExecutionResult, +) error { + // TODO: implement additional checks + return nil +} From 6562f23dad30a03d891ecf6edecdf97541363ee6 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 3 Nov 2023 09:54:35 -0700 Subject: [PATCH 357/775] Disable race condition test for pebbledb --- system_tests/batch_poster_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 8561e3ffc..34eefdd3c 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -1,6 +1,10 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE +// TODO There is a race condition in the currently used version of pebbledb, remove when upgraded. +//go:build !race +// +build !race + package arbtest import ( From e4f8ceb93979fd1f91729882fa938d2a18369e46 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 3 Nov 2023 11:00:28 -0700 Subject: [PATCH 358/775] Revert "Disable race condition test for pebbledb" This reverts commit 6562f23dad30a03d891ecf6edecdf97541363ee6. --- system_tests/batch_poster_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 34eefdd3c..8561e3ffc 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -1,10 +1,6 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -// TODO There is a race condition in the currently used version of pebbledb, remove when upgraded. -//go:build !race -// +build !race - package arbtest import ( From d93a6940770bbdf3acab147af2ca838dfae7ebd0 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 3 Nov 2023 11:05:44 -0700 Subject: [PATCH 359/775] Use leveldb for tests til race cond issues fixed --- system_tests/common_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index c0864886d..327ce94e0 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -480,6 +480,7 @@ func createStackConfigForTest(dataDir string) *node.Config { stackConf.P2P.NoDial = true stackConf.P2P.ListenAddr = "" stackConf.P2P.NAT = nil + stackConf.DBEngine = "leveldb" // TODO Try pebble again in future once iterator race condition issues are fixed return &stackConf } @@ -492,6 +493,7 @@ func createTestValidationNode(t *testing.T, ctx context.Context, config *valnode stackConf.WSModules = []string{server_api.Namespace} stackConf.P2P.NoDiscovery = true stackConf.P2P.ListenAddr = "" + stackConf.DBEngine = "leveldb" // TODO Try pebble again in future once iterator race condition issues are fixed valnode.EnsureValidationExposedViaAuthRPC(&stackConf) From 870570724521fe25c0401e27bc1ca9fd8f28bb30 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 3 Nov 2023 10:48:00 -0600 Subject: [PATCH 360/775] rpcclient: add retrydelay --- util/rpcclient/rpcclient.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/util/rpcclient/rpcclient.go b/util/rpcclient/rpcclient.go index 0a0945907..61c125eae 100644 --- a/util/rpcclient/rpcclient.go +++ b/util/rpcclient/rpcclient.go @@ -28,6 +28,7 @@ type ClientConfig struct { ConnectionWait time.Duration `koanf:"connection-wait"` ArgLogLimit uint `koanf:"arg-log-limit" reload:"hot"` RetryErrors string `koanf:"retry-errors" reload:"hot"` + RetryDelay time.Duration `koanf:"retry-delay"` retryErrors *regexp.Regexp } @@ -63,6 +64,7 @@ func RPCClientAddOptions(prefix string, f *flag.FlagSet, defaultConfig *ClientCo f.Uint(prefix+".arg-log-limit", defaultConfig.ArgLogLimit, "limit size of arguments in log entries") f.Uint(prefix+".retries", defaultConfig.Retries, "number of retries in case of failure(0 mean one attempt)") f.String(prefix+".retry-errors", defaultConfig.RetryErrors, "Errors matching this regular expression are automatically retried") + f.Duration(prefix+".retry-delay", defaultConfig.RetryDelay, "delay between retries") } type RpcClient struct { @@ -131,6 +133,14 @@ func (c *RpcClient) CallContext(ctx_in context.Context, result interface{}, meth log.Trace("sending RPC request", "method", method, "logId", logId, "args", limitedArgumentsMarshal{int(c.config().ArgLogLimit), args}) var err error for i := 0; i < int(c.config().Retries)+1; i++ { + retryDelay := c.config().RetryDelay + if i > 0 && retryDelay > 0 { + select { + case <-ctx_in.Done(): + return ctx_in.Err() + case <-time.After(retryDelay): + } + } if ctx_in.Err() != nil { return ctx_in.Err() } From a6fddc1e6361a61107b91088cc5ac8f94d023961 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 3 Nov 2023 11:00:48 -0600 Subject: [PATCH 361/775] rpcclient: initiaql toxiproxy test --- go.mod | 1 + go.sum | 8 ++ util/rpcclient/rpcclient_test.go | 5 + util/rpcclient/rpcclient_toxiproxy_test.go | 112 +++++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 util/rpcclient/rpcclient_toxiproxy_test.go diff --git a/go.mod b/go.mod index 5ab2eda5c..131d88a0b 100644 --- a/go.mod +++ b/go.mod @@ -48,6 +48,7 @@ require ( bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc // indirect github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect github.com/DataDog/zstd v1.5.2 // indirect + github.com/Shopify/toxiproxy v2.1.4+incompatible // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect diff --git a/go.sum b/go.sum index 424e3508c..07852c74f 100644 --- a/go.sum +++ b/go.sum @@ -59,6 +59,7 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fTKCulPVs= +github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= @@ -227,6 +228,7 @@ github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoG github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codeclysm/extract/v3 v3.0.2 h1:sB4LcE3Php7LkhZwN0n2p8GCwZe92PEQutdbGURf5xc= github.com/codeclysm/extract/v3 v3.0.2/go.mod h1:NKsw+hqua9H+Rlwy/w/3Qgt9jDonYEgB6wJu+25eOKw= @@ -265,6 +267,7 @@ github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6Uh github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= @@ -380,6 +383,7 @@ github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -871,6 +875,7 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -1245,6 +1250,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= @@ -1386,6 +1392,7 @@ github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAv github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk= +github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -1620,6 +1627,7 @@ github.com/wealdtech/go-merkletree v1.0.0/go.mod h1:cdil512d/8ZC7Kx3bfrDvGMQXB25 github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4= github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= +github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa h1:EyA027ZAkuaCLoxVX4r1TZMPy1d31fM6hbfQ4OU4I5o= github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= diff --git a/util/rpcclient/rpcclient_test.go b/util/rpcclient/rpcclient_test.go index c9d813ab0..b885770f6 100644 --- a/util/rpcclient/rpcclient_test.go +++ b/util/rpcclient/rpcclient_test.go @@ -88,6 +88,11 @@ func (t *testAPI) FailAtFirst(ctx context.Context) error { return errors.New("error") } +func (t *testAPI) Delay(ctx context.Context, msec int64) error { + <-time.After(time.Millisecond * time.Duration(msec)) + return nil +} + func TestRpcClientRetry(t *testing.T) { t.Parallel() ctx, cancel := context.WithTimeout(context.Background(), time.Minute*2) diff --git a/util/rpcclient/rpcclient_toxiproxy_test.go b/util/rpcclient/rpcclient_toxiproxy_test.go new file mode 100644 index 000000000..31385d50d --- /dev/null +++ b/util/rpcclient/rpcclient_toxiproxy_test.go @@ -0,0 +1,112 @@ +//go:build toxiproxy +// +build toxiproxy + +package rpcclient + +import ( + "context" + "testing" + "time" + + toxiproxy "github.com/Shopify/toxiproxy/client" +) + +func TestToxiRpcClient(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute*2) + defer cancel() + + server1 := createTestNode(t, ctx, 0) + + toxiprox := toxiproxy.NewClient("localhost:8474") + proxy, err := toxiprox.CreateProxy("testRpc", "", server1.WSEndpoint()[5:]) + Require(t, err) + defer proxy.Delete() + + config := &ClientConfig{ + URL: "ws://" + proxy.Listen, + Timeout: time.Second * 5, + Retries: 3, + RetryErrors: "websocket: close.*|.* i/o timeout|.*connection reset by peer|dial tcp .*", + RetryDelay: time.Millisecond * 500, + } + Require(t, config.Validate()) + configFetcher := func() *ClientConfig { return config } + + client := NewRpcClient(configFetcher, server1) + + err = client.Start(ctx) + Require(t, err) + + err = client.CallContext(ctx, nil, "test_delay", 500) + Require(t, err) + + errChan := make(chan error) + proxyErrChan := make(chan error) + callDealy := func() { + callCtx, cancel := context.WithTimeout(ctx, 10*time.Second) + errChan <- client.CallContext(callCtx, nil, "test_delay", 3000) + cancel() + } + proxyDisable := func() { + <-time.After(time.Millisecond * 30) + err = proxy.Disable() + if err != nil { + proxyErrChan <- err + return + } + <-time.After(time.Millisecond * 500) + err = proxy.Enable() + proxyErrChan <- err + } + proxyReset := func() { + <-time.After(time.Millisecond * 20) + _, err = proxy.AddToxic("reset_all", "reset_peer", "downstream", 1.0, toxiproxy.Attributes{"timeout": 5}) + if err != nil { + proxyErrChan <- err + return + } + <-time.After(time.Millisecond * 3000) + err = proxy.RemoveToxic("reset_all") + proxyErrChan <- err + } + + config.Retries = 0 + go callDealy() + go proxyDisable() + err = <-proxyErrChan + Require(t, err) + err = <-errChan + if err == nil { + Fail(t, "call during proxyDisable succeeded without retries") + } + + config.Retries = 3 + go callDealy() + go proxyDisable() + err = <-proxyErrChan + Require(t, err) + err = <-errChan + if err != nil { + Fail(t, "call during proxyDisable failed with retries:", err) + } + + config.Retries = 0 + go callDealy() + go proxyReset() + err = <-proxyErrChan + Require(t, err) + err = <-errChan + if err == nil { + Fail(t, "call during proxyReset succeeded without retries") + } + + config.Retries = 3 + go callDealy() + go proxyReset() + err = <-proxyErrChan + Require(t, err) + err = <-errChan + if err != nil { + Fail(t, "call during proxyReset failed with retries:", err) + } +} From a41fe839601ddd5184a62278d0966c2320261f98 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 3 Nov 2023 15:23:19 -0500 Subject: [PATCH 362/775] Add backup feed URLs to chain information --- cmd/chaininfo/arbitrum_chain_info.json | 69 +++++++++----------------- cmd/chaininfo/chain_info.go | 13 ++--- cmd/nitro/nitro.go | 3 ++ 3 files changed, 34 insertions(+), 51 deletions(-) diff --git a/cmd/chaininfo/arbitrum_chain_info.json b/cmd/chaininfo/arbitrum_chain_info.json index 051ccd03c..0fa2db57f 100644 --- a/cmd/chaininfo/arbitrum_chain_info.json +++ b/cmd/chaininfo/arbitrum_chain_info.json @@ -5,9 +5,9 @@ "parent-chain-is-arbitrum": false, "sequencer-url": "https://arb1-sequencer.arbitrum.io/rpc", "feed-url": "wss://arb1-feed.arbitrum.io/feed", + "secondary-feed-url": "wss://arb1-delayed-feed.arbitrum.io/feed", "has-genesis-state": true, - "chain-config": - { + "chain-config": { "chainId": 42161, "homesteadBlock": 0, "daoForkBlock": null, @@ -23,13 +23,11 @@ "muirGlacierBlock": 0, "berlinBlock": 0, "londonBlock": 0, - "clique": - { + "clique": { "period": 0, "epoch": 0 }, - "arbitrum": - { + "arbitrum": { "EnableArbOS": true, "AllowDebugPrecompiles": false, "DataAvailabilityCommittee": false, @@ -38,8 +36,7 @@ "GenesisBlockNum": 0 } }, - "rollup": - { + "rollup": { "bridge": "0x8315177ab297ba92a06054ce80a67ed4dbd7ed3a", "inbox": "0x4dbd4fc535ac27206064b68ffcf827b0a60bab3f", "rollup": "0x5ef0d09d1e6204141b4d37530808ed19f60fba35", @@ -56,8 +53,7 @@ "sequencer-url": "https://nova.arbitrum.io/rpc", "feed-url": "wss://nova-feed.arbitrum.io/feed", "das-index-url": "https://nova.arbitrum.io/das-servers", - "chain-config": - { + "chain-config": { "chainId": 42170, "homesteadBlock": 0, "daoForkBlock": null, @@ -73,13 +69,11 @@ "muirGlacierBlock": 0, "berlinBlock": 0, "londonBlock": 0, - "clique": - { + "clique": { "period": 0, "epoch": 0 }, - "arbitrum": - { + "arbitrum": { "EnableArbOS": true, "AllowDebugPrecompiles": false, "DataAvailabilityCommittee": true, @@ -88,8 +82,7 @@ "GenesisBlockNum": 0 } }, - "rollup": - { + "rollup": { "bridge": "0xc1ebd02f738644983b6c4b2d440b8e77dde276bd", "inbox": "0xc4448b71118c9071bcb9734a0eac55d18a153949", "rollup": "0xfb209827c58283535b744575e11953dcc4bead88", @@ -105,8 +98,7 @@ "parent-chain-is-arbitrum": false, "sequencer-url": "https://goerli-rollup.arbitrum.io/rpc", "feed-url": "wss://goerli-rollup.arbitrum.io/feed", - "chain-config": - { + "chain-config": { "chainId": 421613, "homesteadBlock": 0, "daoForkBlock": null, @@ -122,13 +114,11 @@ "muirGlacierBlock": 0, "berlinBlock": 0, "londonBlock": 0, - "clique": - { + "clique": { "period": 0, "epoch": 0 }, - "arbitrum": - { + "arbitrum": { "EnableArbOS": true, "AllowDebugPrecompiles": false, "DataAvailabilityCommittee": false, @@ -137,8 +127,7 @@ "GenesisBlockNum": 0 } }, - "rollup": - { + "rollup": { "bridge": "0xaf4159a80b6cc41ed517db1c453d1ef5c2e4db72", "inbox": "0x6bebc4925716945d46f0ec336d5c2564f419682c", "rollup": "0x45e5caea8768f42b385a366d3551ad1e0cbfab17", @@ -150,8 +139,7 @@ }, { "chain-name": "arb-dev-test", - "chain-config": - { + "chain-config": { "chainId": 412346, "homesteadBlock": 0, "daoForkBlock": null, @@ -167,13 +155,11 @@ "muirGlacierBlock": 0, "berlinBlock": 0, "londonBlock": 0, - "clique": - { + "clique": { "period": 0, "epoch": 0 }, - "arbitrum": - { + "arbitrum": { "EnableArbOS": true, "AllowDebugPrecompiles": true, "DataAvailabilityCommittee": false, @@ -185,8 +171,7 @@ }, { "chain-name": "anytrust-dev-test", - "chain-config": - { + "chain-config": { "chainId": 412347, "homesteadBlock": 0, "daoForkBlock": null, @@ -202,13 +187,11 @@ "muirGlacierBlock": 0, "berlinBlock": 0, "londonBlock": 0, - "clique": - { + "clique": { "period": 0, "epoch": 0 }, - "arbitrum": - { + "arbitrum": { "EnableArbOS": true, "AllowDebugPrecompiles": true, "DataAvailabilityCommittee": true, @@ -225,8 +208,7 @@ "chain-name": "sepolia-rollup", "sequencer-url": "https://sepolia-rollup-sequencer.arbitrum.io/rpc", "feed-url": "wss://sepolia-rollup.arbitrum.io/feed", - "chain-config": - { + "chain-config": { "chainId": 421614, "homesteadBlock": 0, "daoForkBlock": null, @@ -242,13 +224,11 @@ "muirGlacierBlock": 0, "berlinBlock": 0, "londonBlock": 0, - "clique": - { + "clique": { "period": 0, "epoch": 0 }, - "arbitrum": - { + "arbitrum": { "EnableArbOS": true, "AllowDebugPrecompiles": false, "DataAvailabilityCommittee": false, @@ -257,8 +237,7 @@ "GenesisBlockNum": 0 } }, - "rollup": - { + "rollup": { "bridge": "0x38f918D0E9F1b721EDaA41302E399fa1B79333a9", "inbox": "0xaAe29B0366299461418F5324a79Afc425BE5ae21", "sequencer-inbox": "0x6c97864CE4bEf387dE0b3310A44230f7E3F1be0D", @@ -268,4 +247,4 @@ "deployed-at": 4139226 } } -] +] \ No newline at end of file diff --git a/cmd/chaininfo/chain_info.go b/cmd/chaininfo/chain_info.go index cc1332151..fe499442d 100644 --- a/cmd/chaininfo/chain_info.go +++ b/cmd/chaininfo/chain_info.go @@ -22,12 +22,13 @@ type ChainInfo struct { ParentChainId uint64 `json:"parent-chain-id"` ParentChainIsArbitrum *bool `json:"parent-chain-is-arbitrum"` // This is the forwarding target to submit transactions to, called the sequencer URL for clarity - SequencerUrl string `json:"sequencer-url"` - FeedUrl string `json:"feed-url"` - DasIndexUrl string `json:"das-index-url"` - HasGenesisState bool `json:"has-genesis-state"` - ChainConfig *params.ChainConfig `json:"chain-config"` - RollupAddresses *RollupAddresses `json:"rollup"` + SequencerUrl string `json:"sequencer-url"` + FeedUrl string `json:"feed-url"` + SecondaryFeedUrl string `json:"secondary-feed-url"` + DasIndexUrl string `json:"das-index-url"` + HasGenesisState bool `json:"has-genesis-state"` + ChainConfig *params.ChainConfig `json:"chain-config"` + RollupAddresses *RollupAddresses `json:"rollup"` } func GetChainConfig(chainId *big.Int, chainName string, genesisBlockNum uint64, l2ChainInfoFiles []string, l2ChainInfoJson string) (*params.ChainConfig, error) { diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 72668c60e..0154606af 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -817,6 +817,9 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c if chainInfo.FeedUrl != "" { chainDefaults["node.feed.input.url"] = chainInfo.FeedUrl } + if chainInfo.SecondaryFeedUrl != "" { + chainDefaults["node.feed.input.secondary-url"] = chainInfo.SecondaryFeedUrl + } if chainInfo.DasIndexUrl != "" { chainDefaults["node.data-availability.enable"] = true chainDefaults["node.data-availability.rest-aggregator.enable"] = true From b07d69129eb6d5efeaa66a97971dd89e0a05d6c2 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 13 Nov 2023 17:10:47 +0100 Subject: [PATCH 363/775] Drop initializing conf field that doesn't exist anymore --- cmd/datool/datool.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmd/datool/datool.go b/cmd/datool/datool.go index d20a5b52c..d78d975fd 100644 --- a/cmd/datool/datool.go +++ b/cmd/datool/datool.go @@ -102,7 +102,6 @@ func parseClientStoreConfig(args []string) (*ClientStoreConfig, error) { f.String("signing-wallet", "", "wallet containing ecdsa key to sign the message with") f.String("signing-wallet-password", genericconf.PASSWORD_NOT_SET, "password to unlock the wallet, if not specified the user is prompted for the password") f.Duration("das-retention-period", 24*time.Hour, "The period which DASes are requested to retain the stored batches.") - genericconf.ConfConfigAddOptions("conf", f) k, err := confighelpers.BeginCommonParse(f, args) if err != nil { @@ -204,8 +203,6 @@ func parseRESTClientGetByHashConfig(args []string) (*RESTClientGetByHashConfig, f.String("url", "http://localhost:9877", "URL of DAS server to connect to.") f.String("data-hash", "", "hash of the message to retrieve, if starts with '0x' it's treated as hex encoded, otherwise base64 encoded") - genericconf.ConfConfigAddOptions("conf", f) - k, err := confighelpers.BeginCommonParse(f, args) if err != nil { return nil, err @@ -267,7 +264,6 @@ func parseKeyGenConfig(args []string) (*KeyGenConfig, error) { f.String("dir", "", "the directory to generate the keys in") f.Bool("ecdsa", false, "generate an ECDSA keypair instead of BLS") f.Bool("wallet", false, "generate the ECDSA keypair in a wallet file") - genericconf.ConfConfigAddOptions("conf", f) k, err := confighelpers.BeginCommonParse(f, args) if err != nil { From f41c60c3444a2d4bc9b96c51681671cabf3521d7 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Mon, 13 Nov 2023 12:28:22 -0800 Subject: [PATCH 364/775] Update against latest go-ethereum merge-v1.12.1 --- go-ethereum | 2 +- nodeInterface/NodeInterface.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/go-ethereum b/go-ethereum index 890cbcac4..be1fd29a2 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 890cbcac4ec591088761a3cf2cdec9bf29183cbb +Subproject commit be1fd29a26173eae9008c33280b2942a86a4b0fc diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index 6e2e5650c..3b377bc5a 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -499,7 +499,7 @@ func (n NodeInterface) GasEstimateComponents( block := rpc.BlockNumberOrHashWithHash(n.header.Hash(), false) args := n.messageArgs(evm, value, to, contractCreation, data) - totalRaw, err := arbitrum.EstimateGas(context, backend, args, block, gasCap) + totalRaw, err := arbitrum.EstimateGas(context, backend, args, block, nil, gasCap) if err != nil { return 0, 0, nil, nil, err } From 43b12ef791ed6f72a8b0854770e1f2d3f28a0c70 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 11 Oct 2023 10:09:46 +1300 Subject: [PATCH 365/775] Move Broadcast message objects to separate library --- arbnode/inbox_tracker.go | 3 +- arbnode/transaction_streamer.go | 3 +- broadcastclient/broadcastclient.go | 8 +-- broadcastclient/broadcastclient_test.go | 7 +-- broadcaster/broadcaster.go | 53 ++++--------------- broadcaster/message/message.go | 42 +++++++++++++++ .../message_serialization_test.go} | 2 +- broadcaster/message/message_test_utils.go | 29 ++++++++++ broadcaster/sequencenumbercatchupbuffer.go | 11 ++-- .../sequencenumbercatchupbuffer_test.go | 42 +++++---------- relay/relay.go | 9 ++-- 11 files changed, 117 insertions(+), 92 deletions(-) create mode 100644 broadcaster/message/message.go rename broadcaster/{broadcaster_serialization_test.go => message/message_serialization_test.go} (98%) create mode 100644 broadcaster/message/message_test_utils.go diff --git a/arbnode/inbox_tracker.go b/arbnode/inbox_tracker.go index 72e4ba288..51f74cbeb 100644 --- a/arbnode/inbox_tracker.go +++ b/arbnode/inbox_tracker.go @@ -22,6 +22,7 @@ import ( "github.com/offchainlabs/nitro/arbstate" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcaster" + m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/containers" ) @@ -240,7 +241,7 @@ func (t *InboxTracker) PopulateFeedBacklog(broadcastServer *broadcaster.Broadcas if err != nil { return fmt.Errorf("error getting tx streamer message count: %w", err) } - var feedMessages []*broadcaster.BroadcastFeedMessage + var feedMessages []*m.BroadcastFeedMessage for seqNum := startMessage; seqNum < messageCount; seqNum++ { message, err := t.txStreamer.GetMessage(seqNum) if err != nil { diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 2ee1526ee..1761b59a2 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -33,6 +33,7 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcaster" + m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/sharedmetrics" @@ -426,7 +427,7 @@ func (s *TransactionStreamer) AddMessages(pos arbutil.MessageIndex, messagesAreC return s.AddMessagesAndEndBatch(pos, messagesAreConfirmed, messages, nil) } -func (s *TransactionStreamer) AddBroadcastMessages(feedMessages []*broadcaster.BroadcastFeedMessage) error { +func (s *TransactionStreamer) AddBroadcastMessages(feedMessages []*m.BroadcastFeedMessage) error { if len(feedMessages) == 0 { return nil } diff --git a/broadcastclient/broadcastclient.go b/broadcastclient/broadcastclient.go index e94daa463..f27fc28fa 100644 --- a/broadcastclient/broadcastclient.go +++ b/broadcastclient/broadcastclient.go @@ -27,7 +27,7 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/offchainlabs/nitro/arbutil" - "github.com/offchainlabs/nitro/broadcaster" + m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/util/contracts" "github.com/offchainlabs/nitro/util/signature" "github.com/offchainlabs/nitro/util/stopwaiter" @@ -117,7 +117,7 @@ var DefaultTestConfig = Config{ } type TransactionStreamerInterface interface { - AddBroadcastMessages(feedMessages []*broadcaster.BroadcastFeedMessage) error + AddBroadcastMessages(feedMessages []*m.BroadcastFeedMessage) error } type BroadcastClient struct { @@ -381,7 +381,7 @@ func (bc *BroadcastClient) startBackgroundReader(earlyFrameData io.Reader) { backoffDuration = bc.config().ReconnectInitialBackoff if msg != nil { - res := broadcaster.BroadcastMessage{} + res := m.BroadcastMessage{} err = json.Unmarshal(msg, &res) if err != nil { log.Error("error unmarshalling message", "msg", msg, "err", err) @@ -483,7 +483,7 @@ func (bc *BroadcastClient) StopAndWait() { } } -func (bc *BroadcastClient) isValidSignature(ctx context.Context, message *broadcaster.BroadcastFeedMessage) error { +func (bc *BroadcastClient) isValidSignature(ctx context.Context, message *m.BroadcastFeedMessage) error { if bc.config().Verify.Dangerous.AcceptMissing && bc.sigVerifier == nil { // Verifier disabled return nil diff --git a/broadcastclient/broadcastclient_test.go b/broadcastclient/broadcastclient_test.go index fa743d422..b75bc44c1 100644 --- a/broadcastclient/broadcastclient_test.go +++ b/broadcastclient/broadcastclient_test.go @@ -23,6 +23,7 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcaster" + m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/util/contracts" "github.com/offchainlabs/nitro/util/signature" "github.com/offchainlabs/nitro/util/testhelpers" @@ -178,20 +179,20 @@ func TestInvalidSignature(t *testing.T) { } type dummyTransactionStreamer struct { - messageReceiver chan broadcaster.BroadcastFeedMessage + messageReceiver chan m.BroadcastFeedMessage chainId uint64 sequencerAddr *common.Address } func NewDummyTransactionStreamer(chainId uint64, sequencerAddr *common.Address) *dummyTransactionStreamer { return &dummyTransactionStreamer{ - messageReceiver: make(chan broadcaster.BroadcastFeedMessage), + messageReceiver: make(chan m.BroadcastFeedMessage), chainId: chainId, sequencerAddr: sequencerAddr, } } -func (ts *dummyTransactionStreamer) AddBroadcastMessages(feedMessages []*broadcaster.BroadcastFeedMessage) error { +func (ts *dummyTransactionStreamer) AddBroadcastMessages(feedMessages []*m.BroadcastFeedMessage) error { for _, feedMessage := range feedMessages { ts.messageReceiver <- *feedMessage } diff --git a/broadcaster/broadcaster.go b/broadcaster/broadcaster.go index c3f4c62ce..bd7a38289 100644 --- a/broadcaster/broadcaster.go +++ b/broadcaster/broadcaster.go @@ -9,11 +9,11 @@ import ( "github.com/gobwas/ws" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" + m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/util/signature" "github.com/offchainlabs/nitro/wsbroadcastserver" ) @@ -25,41 +25,6 @@ type Broadcaster struct { dataSigner signature.DataSignerFunc } -// BroadcastMessage is the base message type for messages to send over the network. -// -// Acts as a variant holding the message types. The type of the message is -// indicated by whichever of the fields is non-empty. The fields holding the message -// types are annotated with omitempty so only the populated message is sent as -// json. The message fields should be pointers or slices and end with -// "Messages" or "Message". -// -// The format is forwards compatible, ie if a json BroadcastMessage is received that -// has fields that are not in the Go struct then deserialization will succeed -// skip the unknown field [1] -// -// References: -// [1] https://pkg.go.dev/encoding/json#Unmarshal -type BroadcastMessage struct { - Version int `json:"version"` - // TODO better name than messages since there are different types of messages - Messages []*BroadcastFeedMessage `json:"messages,omitempty"` - ConfirmedSequenceNumberMessage *ConfirmedSequenceNumberMessage `json:"confirmedSequenceNumberMessage,omitempty"` -} - -type BroadcastFeedMessage struct { - SequenceNumber arbutil.MessageIndex `json:"sequenceNumber"` - Message arbostypes.MessageWithMetadata `json:"message"` - Signature []byte `json:"signature"` -} - -func (m *BroadcastFeedMessage) Hash(chainId uint64) (common.Hash, error) { - return m.Message.Hash(m.SequenceNumber, chainId) -} - -type ConfirmedSequenceNumberMessage struct { - SequenceNumber arbutil.MessageIndex `json:"sequenceNumber"` -} - func NewBroadcaster(config wsbroadcastserver.BroadcasterConfigFetcher, chainId uint64, feedErrChan chan error, dataSigner signature.DataSignerFunc) *Broadcaster { catchupBuffer := NewSequenceNumberCatchupBuffer(func() bool { return config().LimitCatchup }, func() int { return config().MaxCatchup }) return &Broadcaster{ @@ -70,7 +35,7 @@ func NewBroadcaster(config wsbroadcastserver.BroadcasterConfigFetcher, chainId u } } -func (b *Broadcaster) NewBroadcastFeedMessage(message arbostypes.MessageWithMetadata, sequenceNumber arbutil.MessageIndex) (*BroadcastFeedMessage, error) { +func (b *Broadcaster) NewBroadcastFeedMessage(message arbostypes.MessageWithMetadata, sequenceNumber arbutil.MessageIndex) (*m.BroadcastFeedMessage, error) { var messageSignature []byte if b.dataSigner != nil { hash, err := message.Hash(sequenceNumber, b.chainId) @@ -83,7 +48,7 @@ func (b *Broadcaster) NewBroadcastFeedMessage(message arbostypes.MessageWithMeta } } - return &BroadcastFeedMessage{ + return &m.BroadcastFeedMessage{ SequenceNumber: sequenceNumber, Message: message, Signature: messageSignature, @@ -105,17 +70,17 @@ func (b *Broadcaster) BroadcastSingle(msg arbostypes.MessageWithMetadata, seq ar return nil } -func (b *Broadcaster) BroadcastSingleFeedMessage(bfm *BroadcastFeedMessage) { - broadcastFeedMessages := make([]*BroadcastFeedMessage, 0, 1) +func (b *Broadcaster) BroadcastSingleFeedMessage(bfm *m.BroadcastFeedMessage) { + broadcastFeedMessages := make([]*m.BroadcastFeedMessage, 0, 1) broadcastFeedMessages = append(broadcastFeedMessages, bfm) b.BroadcastFeedMessages(broadcastFeedMessages) } -func (b *Broadcaster) BroadcastFeedMessages(messages []*BroadcastFeedMessage) { +func (b *Broadcaster) BroadcastFeedMessages(messages []*m.BroadcastFeedMessage) { - bm := BroadcastMessage{ + bm := m.BroadcastMessage{ Version: 1, Messages: messages, } @@ -125,9 +90,9 @@ func (b *Broadcaster) BroadcastFeedMessages(messages []*BroadcastFeedMessage) { func (b *Broadcaster) Confirm(seq arbutil.MessageIndex) { log.Debug("confirming sequence number", "sequenceNumber", seq) - b.server.Broadcast(BroadcastMessage{ + b.server.Broadcast(m.BroadcastMessage{ Version: 1, - ConfirmedSequenceNumberMessage: &ConfirmedSequenceNumberMessage{seq}}) + ConfirmedSequenceNumberMessage: &m.ConfirmedSequenceNumberMessage{seq}}) } func (b *Broadcaster) ClientCount() int32 { diff --git a/broadcaster/message/message.go b/broadcaster/message/message.go new file mode 100644 index 000000000..d42e0c8b6 --- /dev/null +++ b/broadcaster/message/message.go @@ -0,0 +1,42 @@ +package message + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/offchainlabs/nitro/arbos/arbostypes" + "github.com/offchainlabs/nitro/arbutil" +) + +// BroadcastMessage is the base message type for messages to send over the network. +// +// Acts as a variant holding the message types. The type of the message is +// indicated by whichever of the fields is non-empty. The fields holding the message +// types are annotated with omitempty so only the populated message is sent as +// json. The message fields should be pointers or slices and end with +// "Messages" or "Message". +// +// The format is forwards compatible, ie if a json BroadcastMessage is received that +// has fields that are not in the Go struct then deserialization will succeed +// skip the unknown field [1] +// +// References: +// [1] https://pkg.go.dev/encoding/json#Unmarshal +type BroadcastMessage struct { + Version int `json:"version"` + // TODO better name than messages since there are different types of messages + Messages []*BroadcastFeedMessage `json:"messages,omitempty"` + ConfirmedSequenceNumberMessage *ConfirmedSequenceNumberMessage `json:"confirmedSequenceNumberMessage,omitempty"` +} + +type BroadcastFeedMessage struct { + SequenceNumber arbutil.MessageIndex `json:"sequenceNumber"` + Message arbostypes.MessageWithMetadata `json:"message"` + Signature []byte `json:"signature"` +} + +func (m *BroadcastFeedMessage) Hash(chainId uint64) (common.Hash, error) { + return m.Message.Hash(m.SequenceNumber, chainId) +} + +type ConfirmedSequenceNumberMessage struct { + SequenceNumber arbutil.MessageIndex `json:"sequenceNumber"` +} diff --git a/broadcaster/broadcaster_serialization_test.go b/broadcaster/message/message_serialization_test.go similarity index 98% rename from broadcaster/broadcaster_serialization_test.go rename to broadcaster/message/message_serialization_test.go index 64adb4912..c3e14a86a 100644 --- a/broadcaster/broadcaster_serialization_test.go +++ b/broadcaster/message/message_serialization_test.go @@ -1,7 +1,7 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE -package broadcaster +package message import ( "bytes" diff --git a/broadcaster/message/message_test_utils.go b/broadcaster/message/message_test_utils.go new file mode 100644 index 000000000..0943b49c6 --- /dev/null +++ b/broadcaster/message/message_test_utils.go @@ -0,0 +1,29 @@ +package message + +import ( + "github.com/offchainlabs/nitro/arbos/arbostypes" + "github.com/offchainlabs/nitro/arbutil" +) + +func CreateDummyBroadcastMessage(seqNums []arbutil.MessageIndex) *BroadcastMessage { + return &BroadcastMessage{ + Messages: CreateDummyBroadcastMessages(seqNums), + } +} + +func CreateDummyBroadcastMessages(seqNums []arbutil.MessageIndex) []*BroadcastFeedMessage { + return CreateDummyBroadcastMessagesImpl(seqNums, len(seqNums)) +} + +func CreateDummyBroadcastMessagesImpl(seqNums []arbutil.MessageIndex, length int) []*BroadcastFeedMessage { + broadcastMessages := make([]*BroadcastFeedMessage, 0, length) + for _, seqNum := range seqNums { + broadcastMessage := &BroadcastFeedMessage{ + SequenceNumber: seqNum, + Message: arbostypes.EmptyTestMessageWithMetadata, + } + broadcastMessages = append(broadcastMessages, broadcastMessage) + } + + return broadcastMessages +} diff --git a/broadcaster/sequencenumbercatchupbuffer.go b/broadcaster/sequencenumbercatchupbuffer.go index bdd3e60c5..fb51a3cea 100644 --- a/broadcaster/sequencenumbercatchupbuffer.go +++ b/broadcaster/sequencenumbercatchupbuffer.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/offchainlabs/nitro/arbutil" + m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/wsbroadcastserver" ) @@ -26,7 +27,7 @@ var ( ) type SequenceNumberCatchupBuffer struct { - messages []*BroadcastFeedMessage + messages []*m.BroadcastFeedMessage messageCount int32 limitCatchup func() bool maxCatchup func() int @@ -39,7 +40,7 @@ func NewSequenceNumberCatchupBuffer(limitCatchup func() bool, maxCatchup func() } } -func (b *SequenceNumberCatchupBuffer) getCacheMessages(requestedSeqNum arbutil.MessageIndex) *BroadcastMessage { +func (b *SequenceNumberCatchupBuffer) getCacheMessages(requestedSeqNum arbutil.MessageIndex) *m.BroadcastMessage { if len(b.messages) == 0 { return nil } @@ -68,7 +69,7 @@ func (b *SequenceNumberCatchupBuffer) getCacheMessages(requestedSeqNum arbutil.M messagesToSend := b.messages[startingIndex:] if len(messagesToSend) > 0 { - bm := BroadcastMessage{ + bm := m.BroadcastMessage{ Version: 1, Messages: messagesToSend, } @@ -105,7 +106,7 @@ func (b *SequenceNumberCatchupBuffer) pruneBufferToIndex(idx int) { b.messages = b.messages[idx:] if len(b.messages) > 10 && cap(b.messages) > len(b.messages)*10 { // Too much spare capacity, copy to fresh slice to reset memory usage - b.messages = append([]*BroadcastFeedMessage(nil), b.messages[:len(b.messages)]...) + b.messages = append([]*m.BroadcastFeedMessage(nil), b.messages[:len(b.messages)]...) } } @@ -141,7 +142,7 @@ func (b *SequenceNumberCatchupBuffer) deleteConfirmed(confirmedSequenceNumber ar } func (b *SequenceNumberCatchupBuffer) OnDoBroadcast(bmi interface{}) error { - broadcastMessage, ok := bmi.(BroadcastMessage) + broadcastMessage, ok := bmi.(m.BroadcastMessage) if !ok { msg := "requested to broadcast message of unknown type" log.Error(msg) diff --git a/broadcaster/sequencenumbercatchupbuffer_test.go b/broadcaster/sequencenumbercatchupbuffer_test.go index fc6655057..80e1efe5c 100644 --- a/broadcaster/sequencenumbercatchupbuffer_test.go +++ b/broadcaster/sequencenumbercatchupbuffer_test.go @@ -20,8 +20,8 @@ import ( "strings" "testing" - "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" + m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/util/arbmath" ) @@ -40,26 +40,10 @@ func TestGetEmptyCacheMessages(t *testing.T) { } } -func createDummyBroadcastMessages(seqNums []arbutil.MessageIndex) []*BroadcastFeedMessage { - return createDummyBroadcastMessagesImpl(seqNums, len(seqNums)) -} -func createDummyBroadcastMessagesImpl(seqNums []arbutil.MessageIndex, length int) []*BroadcastFeedMessage { - broadcastMessages := make([]*BroadcastFeedMessage, 0, length) - for _, seqNum := range seqNums { - broadcastMessage := &BroadcastFeedMessage{ - SequenceNumber: seqNum, - Message: arbostypes.EmptyTestMessageWithMetadata, - } - broadcastMessages = append(broadcastMessages, broadcastMessage) - } - - return broadcastMessages -} - func TestGetCacheMessages(t *testing.T) { indexes := []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46} buffer := SequenceNumberCatchupBuffer{ - messages: createDummyBroadcastMessages(indexes), + messages: m.CreateDummyBroadcastMessages(indexes), messageCount: int32(len(indexes)), limitCatchup: func() bool { return false }, maxCatchup: func() int { return -1 }, @@ -125,7 +109,7 @@ func TestDeleteConfirmedNil(t *testing.T) { func TestDeleteConfirmInvalidOrder(t *testing.T) { indexes := []arbutil.MessageIndex{40, 42} buffer := SequenceNumberCatchupBuffer{ - messages: createDummyBroadcastMessages(indexes), + messages: m.CreateDummyBroadcastMessages(indexes), messageCount: int32(len(indexes)), limitCatchup: func() bool { return false }, maxCatchup: func() int { return -1 }, @@ -141,7 +125,7 @@ func TestDeleteConfirmInvalidOrder(t *testing.T) { func TestDeleteConfirmed(t *testing.T) { indexes := []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46} buffer := SequenceNumberCatchupBuffer{ - messages: createDummyBroadcastMessages(indexes), + messages: m.CreateDummyBroadcastMessages(indexes), messageCount: int32(len(indexes)), limitCatchup: func() bool { return false }, maxCatchup: func() int { return -1 }, @@ -157,7 +141,7 @@ func TestDeleteConfirmed(t *testing.T) { func TestDeleteFreeMem(t *testing.T) { indexes := []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51} buffer := SequenceNumberCatchupBuffer{ - messages: createDummyBroadcastMessagesImpl(indexes, len(indexes)*10+1), + messages: m.CreateDummyBroadcastMessagesImpl(indexes, len(indexes)*10+1), messageCount: int32(len(indexes)), limitCatchup: func() bool { return false }, maxCatchup: func() int { return -1 }, @@ -192,14 +176,14 @@ func TestBroadcastBadMessage(t *testing.T) { func TestBroadcastPastSeqNum(t *testing.T) { indexes := []arbutil.MessageIndex{40} buffer := SequenceNumberCatchupBuffer{ - messages: createDummyBroadcastMessagesImpl(indexes, len(indexes)*10+1), + messages: m.CreateDummyBroadcastMessagesImpl(indexes, len(indexes)*10+1), messageCount: int32(len(indexes)), limitCatchup: func() bool { return false }, maxCatchup: func() int { return -1 }, } - bm := BroadcastMessage{ - Messages: []*BroadcastFeedMessage{ + bm := m.BroadcastMessage{ + Messages: []*m.BroadcastFeedMessage{ { SequenceNumber: 39, }, @@ -215,14 +199,14 @@ func TestBroadcastPastSeqNum(t *testing.T) { func TestBroadcastFutureSeqNum(t *testing.T) { indexes := []arbutil.MessageIndex{40} buffer := SequenceNumberCatchupBuffer{ - messages: createDummyBroadcastMessagesImpl(indexes, len(indexes)*10+1), + messages: m.CreateDummyBroadcastMessagesImpl(indexes, len(indexes)*10+1), messageCount: int32(len(indexes)), limitCatchup: func() bool { return false }, maxCatchup: func() int { return -1 }, } - bm := BroadcastMessage{ - Messages: []*BroadcastFeedMessage{ + bm := m.BroadcastMessage{ + Messages: []*m.BroadcastFeedMessage{ { SequenceNumber: 42, }, @@ -246,8 +230,8 @@ func TestMaxCatchupBufferSize(t *testing.T) { firstMessage := 10 for i := firstMessage; i <= 20; i += 2 { - bm := BroadcastMessage{ - Messages: []*BroadcastFeedMessage{ + bm := m.BroadcastMessage{ + Messages: []*m.BroadcastFeedMessage{ { SequenceNumber: arbutil.MessageIndex(i), }, diff --git a/relay/relay.go b/relay/relay.go index 428890286..8e2997138 100644 --- a/relay/relay.go +++ b/relay/relay.go @@ -16,6 +16,7 @@ import ( "github.com/offchainlabs/nitro/broadcastclient" "github.com/offchainlabs/nitro/broadcastclients" "github.com/offchainlabs/nitro/broadcaster" + m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/cmd/util/confighelpers" "github.com/offchainlabs/nitro/util/sharedmetrics" @@ -28,14 +29,14 @@ type Relay struct { broadcastClients *broadcastclients.BroadcastClients broadcaster *broadcaster.Broadcaster confirmedSequenceNumberChan chan arbutil.MessageIndex - messageChan chan broadcaster.BroadcastFeedMessage + messageChan chan m.BroadcastFeedMessage } type MessageQueue struct { - queue chan broadcaster.BroadcastFeedMessage + queue chan m.BroadcastFeedMessage } -func (q *MessageQueue) AddBroadcastMessages(feedMessages []*broadcaster.BroadcastFeedMessage) error { +func (q *MessageQueue) AddBroadcastMessages(feedMessages []*m.BroadcastFeedMessage) error { for _, feedMessage := range feedMessages { q.queue <- *feedMessage } @@ -45,7 +46,7 @@ func (q *MessageQueue) AddBroadcastMessages(feedMessages []*broadcaster.Broadcas func NewRelay(config *Config, feedErrChan chan error) (*Relay, error) { - q := MessageQueue{make(chan broadcaster.BroadcastFeedMessage, config.Queue)} + q := MessageQueue{make(chan m.BroadcastFeedMessage, config.Queue)} confirmedSequenceNumberListener := make(chan arbutil.MessageIndex, config.Queue) From 3f119a49474f1bc1f4696737ebac2e81dc00506c Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 11 Oct 2023 11:25:19 +1300 Subject: [PATCH 366/775] Create backlog library --- broadcaster/backlog/backlog.go | 288 ++++++++++++++++++++++ broadcaster/backlog/backlog_test.go | 367 ++++++++++++++++++++++++++++ broadcaster/backlog/config.go | 24 ++ 3 files changed, 679 insertions(+) create mode 100644 broadcaster/backlog/backlog.go create mode 100644 broadcaster/backlog/backlog_test.go create mode 100644 broadcaster/backlog/config.go diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go new file mode 100644 index 000000000..499d0a5fa --- /dev/null +++ b/broadcaster/backlog/backlog.go @@ -0,0 +1,288 @@ +package backlog + +import ( + "errors" + "fmt" + "sync/atomic" + + "github.com/ethereum/go-ethereum/log" + "github.com/offchainlabs/nitro/arbutil" + m "github.com/offchainlabs/nitro/broadcaster/message" + "github.com/offchainlabs/nitro/util/arbmath" +) + +var ( + errDropSegments = errors.New("remove previous segments from backlog") + errSequenceNumberSeen = errors.New("sequence number already present in backlog") + errOutOfBounds = errors.New("message not found in backlog") +) + +type Backlog interface { + Append(bm *m.BroadcastMessage) error + Get(start, end arbutil.MessageIndex) (*m.BroadcastMessage, error) + MessageCount() int +} + +type backlog struct { + head atomic.Pointer[backlogSegment] + tail atomic.Pointer[backlogSegment] + lookupByIndex map[arbutil.MessageIndex]*atomic.Pointer[backlogSegment] + config ConfigFetcher + messageCount atomic.Uint64 +} + +func NewBacklog(c ConfigFetcher) Backlog { + lookup := make(map[arbutil.MessageIndex]*atomic.Pointer[backlogSegment]) + return &backlog{ + lookupByIndex: lookup, + config: c, + } +} + +// Append will add the given messages to the backlogSegment at head until +// that segment reaches its limit. If messages remain to be added a new segment +// will be created. +func (b *backlog) Append(bm *m.BroadcastMessage) error { + + if bm.ConfirmedSequenceNumberMessage != nil { + b.delete(bm.ConfirmedSequenceNumberMessage.SequenceNumber) + // add to metric? + } + + for _, msg := range bm.Messages { + s := b.tail.Load() + if s == nil { + s = &backlogSegment{} + b.head.Store(s) + b.tail.Store(s) + } + + prevMsgIdx := s.end + if s.MessageCount() >= b.config().SegmentLimit { + nextS := &backlogSegment{} + s.nextSegment.Store(nextS) + prevMsgIdx = s.end + nextS.previousSegment.Store(s) + s = nextS + b.tail.Store(s) + } + + err := s.append(prevMsgIdx, msg) + if errors.Is(err, errDropSegments) { + head := b.head.Load() + b.removeFromLookup(head.start, msg.SequenceNumber) + b.head.Store(s) + b.tail.Store(s) + b.messageCount.Store(0) + log.Warn(err.Error()) + } else if errors.Is(err, errSequenceNumberSeen) { + log.Info("ignoring message sequence number (%s), already in backlog", msg.SequenceNumber) + continue + } else if err != nil { + return err + } + p := &atomic.Pointer[backlogSegment]{} + p.Store(s) + b.lookupByIndex[msg.SequenceNumber] = p + b.messageCount.Add(1) + } + + return nil +} + +// Get reads messages from the given start to end MessageIndex +func (b *backlog) Get(start, end arbutil.MessageIndex) (*m.BroadcastMessage, error) { + head := b.head.Load() + tail := b.tail.Load() + if head == nil && tail == nil { + return nil, errOutOfBounds + } + + if start < head.start { + start = head.start + } + + if end > tail.end { + return nil, errOutOfBounds + } + + s, err := b.lookup(start) + if err != nil { + return nil, err + } + + bm := &m.BroadcastMessage{Version: 1} + required := int(end-start) + 1 + for { + segMsgs, err := s.get(arbmath.MaxInt(start, s.start), arbmath.MinInt(end, s.end)) + if err != nil { + return nil, err + } + + bm.Messages = append(bm.Messages, segMsgs...) + s = s.nextSegment.Load() + if len(bm.Messages) == required { + break + } else if s == nil { + return nil, errOutOfBounds + } + } + return bm, nil +} + +// delete removes segments before the confirmed sequence number given. It will +// not remove the segment containing the confirmed sequence number. +func (b *backlog) delete(confirmed arbutil.MessageIndex) { + head := b.head.Load() + tail := b.tail.Load() + if head == nil && tail == nil { + return + } + + if confirmed < head.start { + return + } + + if confirmed > tail.end { + log.Error("confirmed sequence number is past the end of stored messages", "confirmed sequence number", confirmed, "last stored sequence number", tail.end) + b.reset() + // should this be returning an error? The other buffer does not and just continues + return + } + + // find the segment containing the confirmed message + s, err := b.lookup(confirmed) + if err != nil { + log.Error(fmt.Sprintf("%s: clearing backlog", err.Error())) + b.reset() + // should this be returning an error? The other buffer does not and just continues + return + } + + // check the segment actually contains that message + if found := s.contains(confirmed); !found { + log.Error("error message not found in backlog segment, clearing backlog", "confirmed sequence number", confirmed) + b.reset() + // should this be returning an error? The other buffer does not and just continues + return + } + + // remove all previous segments + previous := s.previousSegment.Load() + if previous == nil { + return + } + b.removeFromLookup(head.start, previous.end) + b.head.Store(s) + count := b.messageCount.Load() - uint64(previous.end-head.start) - uint64(1) + b.messageCount.Store(count) +} + +// removeFromLookup removes all entries from the head segment's start index to +// the given confirmed index +func (b *backlog) removeFromLookup(start arbutil.MessageIndex, end arbutil.MessageIndex) { + for i := start; i == end; i++ { + delete(b.lookupByIndex, i) + } +} + +func (b *backlog) lookup(i arbutil.MessageIndex) (*backlogSegment, error) { + pointer, ok := b.lookupByIndex[i] + if !ok { + return nil, fmt.Errorf("error finding backlog segment containing message with SequenceNumber %d", i) + } + + s := pointer.Load() + if s == nil { + return nil, fmt.Errorf("error loading backlog segment containing message with SequenceNumber %d", i) + } + + return s, nil +} + +func (s *backlog) MessageCount() int { + return int(s.messageCount.Load()) +} + +// reset removes all segments from the backlog +func (b *backlog) reset() { + b.head = atomic.Pointer[backlogSegment]{} + b.tail = atomic.Pointer[backlogSegment]{} + b.lookupByIndex = map[arbutil.MessageIndex]*atomic.Pointer[backlogSegment]{} + b.messageCount.Store(0) +} + +type backlogSegment struct { + start arbutil.MessageIndex + end arbutil.MessageIndex + messages []*m.BroadcastFeedMessage + messageCount atomic.Uint64 + nextSegment atomic.Pointer[backlogSegment] + previousSegment atomic.Pointer[backlogSegment] +} + +// get reads messages from the given start to end MessageIndex +func (s *backlogSegment) get(start, end arbutil.MessageIndex) ([]*m.BroadcastFeedMessage, error) { + noMsgs := []*m.BroadcastFeedMessage{} + if start < s.start { + return noMsgs, errOutOfBounds + } + + if end > s.end { + return noMsgs, errOutOfBounds + } + + startIndex := int(start - s.start) + endIndex := int(end-s.start) + 1 + return s.messages[startIndex:endIndex], nil +} + +// append appends the given BroadcastFeedMessage to messages if it is the first +// message in the sequence or the next in the sequence. If segment's end +// message is ahead of the given message append will do nothing. If the given +// message is ahead of the segment's end message append will return +// errDropSegments to ensure any messages before the given message are dropped. +func (s *backlogSegment) append(prevMsgIdx arbutil.MessageIndex, msg *m.BroadcastFeedMessage) error { + seen := false + defer s.updateSegment(&seen) + + if expSeqNum := prevMsgIdx + 1; prevMsgIdx == 0 || msg.SequenceNumber == expSeqNum { + s.messages = append(s.messages, msg) + } else if msg.SequenceNumber > expSeqNum { + s.messages = nil + s.messages = append(s.messages, msg) + return fmt.Errorf("new message sequence number (%d) is greater than the expected sequence number (%d): %w", msg.SequenceNumber, expSeqNum, errDropSegments) + } else { + seen = true + return errSequenceNumberSeen + } + return nil +} + +// contains confirms whether the segment contains a message with the given sequence number +func (s *backlogSegment) contains(i arbutil.MessageIndex) bool { + if i < s.start || i > s.end { + return false + } + + msgIndex := uint64(i - s.start) + msg := s.messages[msgIndex] + return msg.SequenceNumber == i +} + +// updateSegment updates the messageCount, start and end indices of the segment +// this should be called using defer whenever a method updates the messages. It +// will do nothing if the message has already been seen by the backlog. +func (s *backlogSegment) updateSegment(seen *bool) { + if !*seen { + c := len(s.messages) + s.messageCount.Store(uint64(c)) + s.start = s.messages[0].SequenceNumber + s.end = s.messages[c-1].SequenceNumber + } +} + +// MessageCount returns the number of messages stored in the backlog +func (s *backlogSegment) MessageCount() int { + return int(s.messageCount.Load()) +} diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go new file mode 100644 index 000000000..346d825d3 --- /dev/null +++ b/broadcaster/backlog/backlog_test.go @@ -0,0 +1,367 @@ +package backlog + +import ( + "errors" + "sync/atomic" + "testing" + + "github.com/offchainlabs/nitro/arbutil" + m "github.com/offchainlabs/nitro/broadcaster/message" + "github.com/offchainlabs/nitro/util/arbmath" +) + +func validateBacklog(t *testing.T, b *backlog, count int, start, end arbutil.MessageIndex, lookupKeys []arbutil.MessageIndex) { + if b.MessageCount() != count { + t.Errorf("backlog message count (%d) does not equal expected message count (%d)", b.MessageCount(), count) + } + + head := b.head.Load() + if start != 0 && head.start != start { + t.Errorf("head of backlog (%d) does not equal expected head (%d)", head.start, start) + } + + tail := b.tail.Load() + if end != 0 && tail.end != end { + t.Errorf("tail of backlog (%d) does not equal expected tail (%d)", tail.end, end) + } + + for _, k := range lookupKeys { + if _, ok := b.lookupByIndex[k]; !ok { + t.Errorf("failed to find message (%d) in lookup", k) + } + } +} + +func createDummyBacklog(indexes []arbutil.MessageIndex) (*backlog, error) { + b := &backlog{ + lookupByIndex: map[arbutil.MessageIndex]*atomic.Pointer[backlogSegment]{}, + config: func() *Config { return &DefaultTestConfig }, + } + bm := &m.BroadcastMessage{Messages: m.CreateDummyBroadcastMessages(indexes)} + err := b.Append(bm) + return b, err +} + +func TestAppend(t *testing.T) { + testcases := []struct { + name string + backlogIndexes []arbutil.MessageIndex + newIndexes []arbutil.MessageIndex + expectedCount int + expectedStart arbutil.MessageIndex + expectedEnd arbutil.MessageIndex + expectedLookupKeys []arbutil.MessageIndex + }{ + { + "EmptyBacklog", + []arbutil.MessageIndex{}, + []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + 7, + 40, + 46, + []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + }, + { + "NonEmptyBacklog", + []arbutil.MessageIndex{40, 41}, + []arbutil.MessageIndex{42, 43, 44, 45, 46}, + 7, + 40, + 46, + []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + }, + { + "NonSequential", + []arbutil.MessageIndex{40, 41}, + []arbutil.MessageIndex{42, 43, 45, 46}, + 2, // Message 45 is non sequential, the previous messages will be dropped from the backlog + 45, + 46, + []arbutil.MessageIndex{45, 46}, + }, + { + "MessageSeen", + []arbutil.MessageIndex{40, 41}, + []arbutil.MessageIndex{42, 43, 44, 45, 46, 41}, + 7, // Message 41 is already present in the backlog, it will be ignored + 40, + 46, + []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + }, + { + "NonSequentialFirstSegmentMessage", + []arbutil.MessageIndex{40, 41}, + []arbutil.MessageIndex{42, 44, 45, 46}, + 3, // Message 44 is non sequential and the first message in a new segment, the previous messages will be dropped from the backlog + 44, + 46, + []arbutil.MessageIndex{45, 46}, + }, + { + "MessageSeenFirstSegmentMessage", + []arbutil.MessageIndex{40, 41}, + []arbutil.MessageIndex{42, 43, 44, 45, 41, 46}, + 7, // Message 41 is already present in the backlog and the first message in a new segment, it will be ignored + 40, + 46, + []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + // The segment limit is 3, the above test cases have been created + // to include testing certain actions on the first message of a + // new segment. + b, err := createDummyBacklog(tc.backlogIndexes) + if err != nil { + t.Fatalf("error creating dummy backlog: %s", err) + } + + bm := &m.BroadcastMessage{Messages: m.CreateDummyBroadcastMessages(tc.newIndexes)} + err = b.Append(bm) + if err != nil { + t.Fatalf("error appending BroadcastMessage: %s", err) + } + + validateBacklog(t, b, tc.expectedCount, tc.expectedStart, tc.expectedEnd, tc.expectedLookupKeys) + }) + } +} + +func TestDeleteInvalidBacklog(t *testing.T) { + // Create a backlog with an invalid sequence + s := &backlogSegment{ + start: 40, + end: 42, + messages: m.CreateDummyBroadcastMessages([]arbutil.MessageIndex{40, 42}), + } + s.messageCount.Store(2) + + p := &atomic.Pointer[backlogSegment]{} + p.Store(s) + lookup := make(map[arbutil.MessageIndex]*atomic.Pointer[backlogSegment]) + lookup[40] = p + b := &backlog{ + lookupByIndex: lookup, + config: func() *Config { return &DefaultTestConfig }, + } + b.messageCount.Store(2) + b.head.Store(s) + b.tail.Store(s) + + bm := &m.BroadcastMessage{ + Messages: nil, + ConfirmedSequenceNumberMessage: &m.ConfirmedSequenceNumberMessage{ + SequenceNumber: 41, + }, + } + + err := b.Append(bm) + if err != nil { + t.Fatalf("error appending BroadcastMessage: %s", err) + } + + validateBacklog(t, b, 0, 0, 0, []arbutil.MessageIndex{}) +} + +func TestDelete(t *testing.T) { + testcases := []struct { + name string + backlogIndexes []arbutil.MessageIndex + confirmed arbutil.MessageIndex + expectedCount int + expectedStart arbutil.MessageIndex + expectedEnd arbutil.MessageIndex + expectedLookupKeys []arbutil.MessageIndex + }{ + { + "EmptyBacklog", + []arbutil.MessageIndex{}, + 0, // no segements in backlog so nothing to delete + 0, + 0, + 0, + []arbutil.MessageIndex{}, + }, + { + "MsgBeforeBacklog", + []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + 39, // no segments will be deleted + 7, + 40, + 46, + []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + }, + { + "MsgInBacklog", + []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + 43, // only the first segment will be deleted + 4, + 43, + 46, + []arbutil.MessageIndex{43, 44, 45, 46}, + }, + { + "MsgInFirstSegmentInBacklog", + []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + 42, // first segment will not be deleted as confirmed message is there + 7, + 40, + 46, + []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + }, + { + "MsgAfterBacklog", + []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + 47, // all segments will be deleted + 0, + 0, + 0, + []arbutil.MessageIndex{}, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + b, err := createDummyBacklog(tc.backlogIndexes) + if err != nil { + t.Fatalf("error creating dummy backlog: %s", err) + } + + bm := &m.BroadcastMessage{ + Messages: nil, + ConfirmedSequenceNumberMessage: &m.ConfirmedSequenceNumberMessage{ + SequenceNumber: tc.confirmed, + }, + } + + err = b.Append(bm) + if err != nil { + t.Fatalf("error appending BroadcastMessage: %s", err) + } + + validateBacklog(t, b, tc.expectedCount, tc.expectedStart, tc.expectedEnd, tc.expectedLookupKeys) + }) + } +} + +// make sure that an append, then delete, then append ends up with the correct messageCounts + +func TestGetEmptyBacklog(t *testing.T) { + b, err := createDummyBacklog([]arbutil.MessageIndex{}) + if err != nil { + t.Fatalf("error creating dummy backlog: %s", err) + } + + _, err = b.Get(1, 2) + if !errors.Is(err, errOutOfBounds) { + t.Fatalf("unexpected error: %s", err) + } +} + +func TestGet(t *testing.T) { + indexes := []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46} + b, err := createDummyBacklog(indexes) + if err != nil { + t.Fatalf("error creating dummy backlog: %s", err) + } + + testcases := []struct { + name string + start arbutil.MessageIndex + end arbutil.MessageIndex + expectedErr error + expectedCount int + }{ + { + "LowerBoundFar", + 0, + 43, + nil, + 4, + }, + { + "LowerBoundClose", + 39, + 43, + nil, + 4, + }, + { + "UpperBoundFar", + 43, + 18446744073709551615, + errOutOfBounds, + 0, + }, + { + "UpperBoundClose", + 0, + 47, + errOutOfBounds, + 0, + }, + { + "AllMessages", + 40, + 46, + nil, + 7, + }, + { + "SomeMessages", + 42, + 44, + nil, + 3, + }, + { + "FirstMessage", + 40, + 40, + nil, + 1, + }, + { + "LastMessage", + 46, + 46, + nil, + 1, + }, + { + "SingleMessage", + 43, + 43, + nil, + 1, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + bm, err := b.Get(tc.start, tc.end) + if !errors.Is(err, tc.expectedErr) { + t.Fatalf("unexpected error: %s", err) + } + + // Some of the tests are checking the correct error is returned + // Do not check bm if an error should be returned + if err == nil { + actualCount := len(bm.Messages) + if actualCount != tc.expectedCount { + t.Fatalf("number of messages returned (%d) does not equal the expected number of messages (%d)", actualCount, tc.expectedCount) + } + + start := arbmath.MaxInt(tc.start, 40) + for i := start; i <= tc.end; i++ { + msg := bm.Messages[i-start] + if msg.SequenceNumber != i { + t.Fatalf("unexpected sequence number (%d) in %d returned message", i, i-tc.start) + } + } + } + }) + } +} diff --git a/broadcaster/backlog/config.go b/broadcaster/backlog/config.go new file mode 100644 index 000000000..0e760cd0c --- /dev/null +++ b/broadcaster/backlog/config.go @@ -0,0 +1,24 @@ +package backlog + +import ( + flag "github.com/spf13/pflag" +) + +type ConfigFetcher func() *Config + +type Config struct { + SegmentLimit int `koanf:"segment-limit" reload:"hot"` +} + +func AddOptions(prefix string, f *flag.FlagSet) { + f.Int(prefix+".segment-limit", DefaultConfig.SegmentLimit, "the maximum number of messages each segment within the backlog can contain") +} + +var ( + DefaultConfig = Config{ + SegmentLimit: 240, + } + DefaultTestConfig = Config{ + SegmentLimit: 3, + } +) From 342e3c9e29d374c0674e19c2fb4148d6490e096a Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 11 Oct 2023 16:29:17 +1300 Subject: [PATCH 367/775] create a race condition test for backlog library --- broadcaster/backlog/backlog_test.go | 79 ++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 13 deletions(-) diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go index 346d825d3..d22f42202 100644 --- a/broadcaster/backlog/backlog_test.go +++ b/broadcaster/backlog/backlog_test.go @@ -2,8 +2,10 @@ package backlog import ( "errors" + "sync" "sync/atomic" "testing" + "time" "github.com/offchainlabs/nitro/arbutil" m "github.com/offchainlabs/nitro/broadcaster/message" @@ -32,6 +34,21 @@ func validateBacklog(t *testing.T, b *backlog, count int, start, end arbutil.Mes } } +func validateBroadcastMessage(t *testing.T, bm *m.BroadcastMessage, expectedCount int, start, end arbutil.MessageIndex) { + actualCount := len(bm.Messages) + if actualCount != expectedCount { + t.Errorf("number of messages returned (%d) does not equal the expected number of messages (%d)", actualCount, expectedCount) + } + + s := arbmath.MaxInt(start, 40) + for i := s; i <= end; i++ { + msg := bm.Messages[i-s] + if msg.SequenceNumber != i { + t.Errorf("unexpected sequence number (%d) in %d returned message", i, i-s) + } + } +} + func createDummyBacklog(indexes []arbutil.MessageIndex) (*backlog, error) { b := &backlog{ lookupByIndex: map[arbutil.MessageIndex]*atomic.Pointer[backlogSegment]{}, @@ -348,20 +365,56 @@ func TestGet(t *testing.T) { // Some of the tests are checking the correct error is returned // Do not check bm if an error should be returned - if err == nil { - actualCount := len(bm.Messages) - if actualCount != tc.expectedCount { - t.Fatalf("number of messages returned (%d) does not equal the expected number of messages (%d)", actualCount, tc.expectedCount) - } - - start := arbmath.MaxInt(tc.start, 40) - for i := start; i <= tc.end; i++ { - msg := bm.Messages[i-start] - if msg.SequenceNumber != i { - t.Fatalf("unexpected sequence number (%d) in %d returned message", i, i-tc.start) - } - } + if tc.expectedErr == nil { + validateBroadcastMessage(t, bm, tc.expectedCount, tc.start, tc.end) } }) } } + +// TestBacklogRaceCondition performs read & write operations in separate +// goroutines to ensure that the backlog does not have race conditions. The +// `go test -race` command can be used to test this. +func TestBacklogRaceCondition(t *testing.T) { + indexes := []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46} + b, err := createDummyBacklog(indexes) + if err != nil { + t.Fatalf("error creating dummy backlog: %s", err) + } + + wg := sync.WaitGroup{} + newIndexes := []arbutil.MessageIndex{47, 48, 49, 50, 51, 52, 53, 54, 55} + + // Write to backlog in goroutine + wg.Add(1) + go func(t *testing.T, b *backlog) { + defer wg.Done() + for _, i := range newIndexes { + bm := m.CreateDummyBroadcastMessage([]arbutil.MessageIndex{i}) + err := b.Append(bm) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + time.Sleep(time.Millisecond) + } + }(t, b) + + // Read from backlog in goroutine + wg.Add(1) + go func(t *testing.T, b *backlog) { + defer wg.Done() + for _, i := range []arbutil.MessageIndex{42, 43, 44, 45, 46, 47} { + bm, err := b.Get(i, i+1) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } else { + validateBroadcastMessage(t, bm, 2, i, i+1) + } + time.Sleep(2 * time.Millisecond) + } + }(t, b) + + // Wait for both goroutines to finish + wg.Wait() + validateBacklog(t, b, 16, 40, 55, append(indexes, newIndexes...)) +} From b55d38ee2bf537ae1c52af96652f098f765c1f05 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 12 Oct 2023 09:30:28 +1300 Subject: [PATCH 368/775] fix backlog race conditions --- broadcaster/backlog/backlog.go | 87 ++++++++++++++++------------- broadcaster/backlog/backlog_test.go | 38 ++++++------- 2 files changed, 67 insertions(+), 58 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 499d0a5fa..6feb7576f 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -3,10 +3,10 @@ package backlog import ( "errors" "fmt" + "sync" "sync/atomic" "github.com/ethereum/go-ethereum/log" - "github.com/offchainlabs/nitro/arbutil" m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/util/arbmath" ) @@ -19,20 +19,21 @@ var ( type Backlog interface { Append(bm *m.BroadcastMessage) error - Get(start, end arbutil.MessageIndex) (*m.BroadcastMessage, error) + Get(start, end uint64) (*m.BroadcastMessage, error) MessageCount() int } type backlog struct { head atomic.Pointer[backlogSegment] tail atomic.Pointer[backlogSegment] - lookupByIndex map[arbutil.MessageIndex]*atomic.Pointer[backlogSegment] + lookupLock sync.RWMutex + lookupByIndex map[uint64]*atomic.Pointer[backlogSegment] config ConfigFetcher messageCount atomic.Uint64 } func NewBacklog(c ConfigFetcher) Backlog { - lookup := make(map[arbutil.MessageIndex]*atomic.Pointer[backlogSegment]) + lookup := make(map[uint64]*atomic.Pointer[backlogSegment]) return &backlog{ lookupByIndex: lookup, config: c, @@ -45,7 +46,7 @@ func NewBacklog(c ConfigFetcher) Backlog { func (b *backlog) Append(bm *m.BroadcastMessage) error { if bm.ConfirmedSequenceNumberMessage != nil { - b.delete(bm.ConfirmedSequenceNumberMessage.SequenceNumber) + b.delete(uint64(bm.ConfirmedSequenceNumberMessage.SequenceNumber)) // add to metric? } @@ -57,11 +58,11 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { b.tail.Store(s) } - prevMsgIdx := s.end + prevMsgIdx := s.end.Load() if s.MessageCount() >= b.config().SegmentLimit { nextS := &backlogSegment{} s.nextSegment.Store(nextS) - prevMsgIdx = s.end + prevMsgIdx = s.end.Load() nextS.previousSegment.Store(s) s = nextS b.tail.Store(s) @@ -70,7 +71,7 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { err := s.append(prevMsgIdx, msg) if errors.Is(err, errDropSegments) { head := b.head.Load() - b.removeFromLookup(head.start, msg.SequenceNumber) + b.removeFromLookup(head.start.Load(), uint64(msg.SequenceNumber)) b.head.Store(s) b.tail.Store(s) b.messageCount.Store(0) @@ -83,7 +84,9 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { } p := &atomic.Pointer[backlogSegment]{} p.Store(s) - b.lookupByIndex[msg.SequenceNumber] = p + b.lookupLock.Lock() + b.lookupByIndex[uint64(msg.SequenceNumber)] = p + b.lookupLock.Unlock() b.messageCount.Add(1) } @@ -91,18 +94,18 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { } // Get reads messages from the given start to end MessageIndex -func (b *backlog) Get(start, end arbutil.MessageIndex) (*m.BroadcastMessage, error) { +func (b *backlog) Get(start, end uint64) (*m.BroadcastMessage, error) { head := b.head.Load() tail := b.tail.Load() if head == nil && tail == nil { return nil, errOutOfBounds } - if start < head.start { - start = head.start + if start < head.start.Load() { + start = head.start.Load() } - if end > tail.end { + if end > tail.end.Load() { return nil, errOutOfBounds } @@ -114,7 +117,7 @@ func (b *backlog) Get(start, end arbutil.MessageIndex) (*m.BroadcastMessage, err bm := &m.BroadcastMessage{Version: 1} required := int(end-start) + 1 for { - segMsgs, err := s.get(arbmath.MaxInt(start, s.start), arbmath.MinInt(end, s.end)) + segMsgs, err := s.get(arbmath.MaxInt(start, s.start.Load()), arbmath.MinInt(end, s.end.Load())) if err != nil { return nil, err } @@ -132,19 +135,19 @@ func (b *backlog) Get(start, end arbutil.MessageIndex) (*m.BroadcastMessage, err // delete removes segments before the confirmed sequence number given. It will // not remove the segment containing the confirmed sequence number. -func (b *backlog) delete(confirmed arbutil.MessageIndex) { +func (b *backlog) delete(confirmed uint64) { head := b.head.Load() tail := b.tail.Load() if head == nil && tail == nil { return } - if confirmed < head.start { + if confirmed < head.start.Load() { return } - if confirmed > tail.end { - log.Error("confirmed sequence number is past the end of stored messages", "confirmed sequence number", confirmed, "last stored sequence number", tail.end) + if confirmed > tail.end.Load() { + log.Error("confirmed sequence number is past the end of stored messages", "confirmed sequence number", confirmed, "last stored sequence number", tail.end.Load()) b.reset() // should this be returning an error? The other buffer does not and just continues return @@ -172,22 +175,26 @@ func (b *backlog) delete(confirmed arbutil.MessageIndex) { if previous == nil { return } - b.removeFromLookup(head.start, previous.end) + b.removeFromLookup(head.start.Load(), previous.end.Load()) b.head.Store(s) - count := b.messageCount.Load() - uint64(previous.end-head.start) - uint64(1) + count := b.messageCount.Load() + head.start.Load() - previous.end.Load() - uint64(1) b.messageCount.Store(count) } // removeFromLookup removes all entries from the head segment's start index to // the given confirmed index -func (b *backlog) removeFromLookup(start arbutil.MessageIndex, end arbutil.MessageIndex) { +func (b *backlog) removeFromLookup(start, end uint64) { + b.lookupLock.Lock() + defer b.lookupLock.Unlock() for i := start; i == end; i++ { delete(b.lookupByIndex, i) } } -func (b *backlog) lookup(i arbutil.MessageIndex) (*backlogSegment, error) { +func (b *backlog) lookup(i uint64) (*backlogSegment, error) { + b.lookupLock.RLock() pointer, ok := b.lookupByIndex[i] + b.lookupLock.RUnlock() if !ok { return nil, fmt.Errorf("error finding backlog segment containing message with SequenceNumber %d", i) } @@ -206,15 +213,17 @@ func (s *backlog) MessageCount() int { // reset removes all segments from the backlog func (b *backlog) reset() { + b.lookupLock.Lock() + defer b.lookupLock.Unlock() b.head = atomic.Pointer[backlogSegment]{} b.tail = atomic.Pointer[backlogSegment]{} - b.lookupByIndex = map[arbutil.MessageIndex]*atomic.Pointer[backlogSegment]{} + b.lookupByIndex = map[uint64]*atomic.Pointer[backlogSegment]{} b.messageCount.Store(0) } type backlogSegment struct { - start arbutil.MessageIndex - end arbutil.MessageIndex + start atomic.Uint64 + end atomic.Uint64 messages []*m.BroadcastFeedMessage messageCount atomic.Uint64 nextSegment atomic.Pointer[backlogSegment] @@ -222,18 +231,18 @@ type backlogSegment struct { } // get reads messages from the given start to end MessageIndex -func (s *backlogSegment) get(start, end arbutil.MessageIndex) ([]*m.BroadcastFeedMessage, error) { +func (s *backlogSegment) get(start, end uint64) ([]*m.BroadcastFeedMessage, error) { noMsgs := []*m.BroadcastFeedMessage{} - if start < s.start { + if start < s.start.Load() { return noMsgs, errOutOfBounds } - if end > s.end { + if end > s.end.Load() { return noMsgs, errOutOfBounds } - startIndex := int(start - s.start) - endIndex := int(end-s.start) + 1 + startIndex := start - s.start.Load() + endIndex := end - s.start.Load() + 1 return s.messages[startIndex:endIndex], nil } @@ -242,13 +251,13 @@ func (s *backlogSegment) get(start, end arbutil.MessageIndex) ([]*m.BroadcastFee // message is ahead of the given message append will do nothing. If the given // message is ahead of the segment's end message append will return // errDropSegments to ensure any messages before the given message are dropped. -func (s *backlogSegment) append(prevMsgIdx arbutil.MessageIndex, msg *m.BroadcastFeedMessage) error { +func (s *backlogSegment) append(prevMsgIdx uint64, msg *m.BroadcastFeedMessage) error { seen := false defer s.updateSegment(&seen) - if expSeqNum := prevMsgIdx + 1; prevMsgIdx == 0 || msg.SequenceNumber == expSeqNum { + if expSeqNum := prevMsgIdx + 1; prevMsgIdx == 0 || uint64(msg.SequenceNumber) == expSeqNum { s.messages = append(s.messages, msg) - } else if msg.SequenceNumber > expSeqNum { + } else if uint64(msg.SequenceNumber) > expSeqNum { s.messages = nil s.messages = append(s.messages, msg) return fmt.Errorf("new message sequence number (%d) is greater than the expected sequence number (%d): %w", msg.SequenceNumber, expSeqNum, errDropSegments) @@ -260,14 +269,14 @@ func (s *backlogSegment) append(prevMsgIdx arbutil.MessageIndex, msg *m.Broadcas } // contains confirms whether the segment contains a message with the given sequence number -func (s *backlogSegment) contains(i arbutil.MessageIndex) bool { - if i < s.start || i > s.end { +func (s *backlogSegment) contains(i uint64) bool { + if i < s.start.Load() || i > s.end.Load() { return false } - msgIndex := uint64(i - s.start) + msgIndex := i - s.start.Load() msg := s.messages[msgIndex] - return msg.SequenceNumber == i + return uint64(msg.SequenceNumber) == i } // updateSegment updates the messageCount, start and end indices of the segment @@ -277,8 +286,8 @@ func (s *backlogSegment) updateSegment(seen *bool) { if !*seen { c := len(s.messages) s.messageCount.Store(uint64(c)) - s.start = s.messages[0].SequenceNumber - s.end = s.messages[c-1].SequenceNumber + s.start.Store(uint64(s.messages[0].SequenceNumber)) + s.end.Store(uint64(s.messages[c-1].SequenceNumber)) } } diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go index d22f42202..fe062aee1 100644 --- a/broadcaster/backlog/backlog_test.go +++ b/broadcaster/backlog/backlog_test.go @@ -12,29 +12,29 @@ import ( "github.com/offchainlabs/nitro/util/arbmath" ) -func validateBacklog(t *testing.T, b *backlog, count int, start, end arbutil.MessageIndex, lookupKeys []arbutil.MessageIndex) { +func validateBacklog(t *testing.T, b *backlog, count int, start, end uint64, lookupKeys []arbutil.MessageIndex) { if b.MessageCount() != count { t.Errorf("backlog message count (%d) does not equal expected message count (%d)", b.MessageCount(), count) } head := b.head.Load() - if start != 0 && head.start != start { - t.Errorf("head of backlog (%d) does not equal expected head (%d)", head.start, start) + if start != 0 && head.start.Load() != start { + t.Errorf("head of backlog (%d) does not equal expected head (%d)", head.start.Load(), start) } tail := b.tail.Load() - if end != 0 && tail.end != end { - t.Errorf("tail of backlog (%d) does not equal expected tail (%d)", tail.end, end) + if end != 0 && tail.end.Load() != end { + t.Errorf("tail of backlog (%d) does not equal expected tail (%d)", tail.end.Load(), end) } for _, k := range lookupKeys { - if _, ok := b.lookupByIndex[k]; !ok { + if _, err := b.lookup(uint64(k)); err != nil { t.Errorf("failed to find message (%d) in lookup", k) } } } -func validateBroadcastMessage(t *testing.T, bm *m.BroadcastMessage, expectedCount int, start, end arbutil.MessageIndex) { +func validateBroadcastMessage(t *testing.T, bm *m.BroadcastMessage, expectedCount int, start, end uint64) { actualCount := len(bm.Messages) if actualCount != expectedCount { t.Errorf("number of messages returned (%d) does not equal the expected number of messages (%d)", actualCount, expectedCount) @@ -43,7 +43,7 @@ func validateBroadcastMessage(t *testing.T, bm *m.BroadcastMessage, expectedCoun s := arbmath.MaxInt(start, 40) for i := s; i <= end; i++ { msg := bm.Messages[i-s] - if msg.SequenceNumber != i { + if uint64(msg.SequenceNumber) != i { t.Errorf("unexpected sequence number (%d) in %d returned message", i, i-s) } } @@ -51,7 +51,7 @@ func validateBroadcastMessage(t *testing.T, bm *m.BroadcastMessage, expectedCoun func createDummyBacklog(indexes []arbutil.MessageIndex) (*backlog, error) { b := &backlog{ - lookupByIndex: map[arbutil.MessageIndex]*atomic.Pointer[backlogSegment]{}, + lookupByIndex: map[uint64]*atomic.Pointer[backlogSegment]{}, config: func() *Config { return &DefaultTestConfig }, } bm := &m.BroadcastMessage{Messages: m.CreateDummyBroadcastMessages(indexes)} @@ -65,8 +65,8 @@ func TestAppend(t *testing.T) { backlogIndexes []arbutil.MessageIndex newIndexes []arbutil.MessageIndex expectedCount int - expectedStart arbutil.MessageIndex - expectedEnd arbutil.MessageIndex + expectedStart uint64 + expectedEnd uint64 expectedLookupKeys []arbutil.MessageIndex }{ { @@ -149,15 +149,15 @@ func TestAppend(t *testing.T) { func TestDeleteInvalidBacklog(t *testing.T) { // Create a backlog with an invalid sequence s := &backlogSegment{ - start: 40, - end: 42, messages: m.CreateDummyBroadcastMessages([]arbutil.MessageIndex{40, 42}), } + s.start.Store(40) + s.end.Store(42) s.messageCount.Store(2) p := &atomic.Pointer[backlogSegment]{} p.Store(s) - lookup := make(map[arbutil.MessageIndex]*atomic.Pointer[backlogSegment]) + lookup := make(map[uint64]*atomic.Pointer[backlogSegment]) lookup[40] = p b := &backlog{ lookupByIndex: lookup, @@ -188,8 +188,8 @@ func TestDelete(t *testing.T) { backlogIndexes []arbutil.MessageIndex confirmed arbutil.MessageIndex expectedCount int - expectedStart arbutil.MessageIndex - expectedEnd arbutil.MessageIndex + expectedStart uint64 + expectedEnd uint64 expectedLookupKeys []arbutil.MessageIndex }{ { @@ -286,8 +286,8 @@ func TestGet(t *testing.T) { testcases := []struct { name string - start arbutil.MessageIndex - end arbutil.MessageIndex + start uint64 + end uint64 expectedErr error expectedCount int }{ @@ -403,7 +403,7 @@ func TestBacklogRaceCondition(t *testing.T) { wg.Add(1) go func(t *testing.T, b *backlog) { defer wg.Done() - for _, i := range []arbutil.MessageIndex{42, 43, 44, 45, 46, 47} { + for _, i := range []uint64{42, 43, 44, 45, 46, 47} { bm, err := b.Get(i, i+1) if err != nil { t.Fatalf("unexpected error: %s", err) From fc4db62ca4eb96a91f876da1dddc3b19c010649e Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 12 Oct 2023 10:54:25 +1300 Subject: [PATCH 369/775] add delete method to race condition test --- broadcaster/backlog/backlog_test.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go index fe062aee1..65b5d7095 100644 --- a/broadcaster/backlog/backlog_test.go +++ b/broadcaster/backlog/backlog_test.go @@ -414,7 +414,20 @@ func TestBacklogRaceCondition(t *testing.T) { } }(t, b) - // Wait for both goroutines to finish + // Delete from backlog in goroutine. This is normally done via Append with + // a confirmed sequence number, using delete method for simplicity in test. + wg.Add(1) + go func(t *testing.T, b *backlog) { + defer wg.Done() + for _, i := range []uint64{40, 43, 47} { + b.delete(i) + time.Sleep(5 * time.Millisecond) + } + }(t, b) + + // Wait for all goroutines to finish wg.Wait() - validateBacklog(t, b, 16, 40, 55, append(indexes, newIndexes...)) + // Messages up to 47 were deleted. However the segment that 47 was in is + // kept, which is why the backlog starts at 46. + validateBacklog(t, b, 10, 46, 55, append(indexes, newIndexes...)) } From d805660793812b835b43209a0ceabf49fcf60677 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 18 Oct 2023 17:18:42 +1300 Subject: [PATCH 370/775] swap catchupbuffer for backlog in wsbroadcastserver --- broadcaster/backlog/backlog.go | 30 +++++- broadcaster/broadcaster.go | 4 +- wsbroadcastserver/clientconnection.go | 123 ++++++++++++++++++++----- wsbroadcastserver/clientmanager.go | 59 ++++-------- wsbroadcastserver/wsbroadcastserver.go | 22 +++-- 5 files changed, 157 insertions(+), 81 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 6feb7576f..1ea46ee5a 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -18,9 +18,10 @@ var ( ) type Backlog interface { + Head() BacklogSegment Append(bm *m.BroadcastMessage) error Get(start, end uint64) (*m.BroadcastMessage, error) - MessageCount() int + Count() int } type backlog struct { @@ -40,6 +41,10 @@ func NewBacklog(c ConfigFetcher) Backlog { } } +func (b *backlog) Head() BacklogSegment { + return b.head.Load() +} + // Append will add the given messages to the backlogSegment at head until // that segment reaches its limit. If messages remain to be added a new segment // will be created. @@ -50,6 +55,8 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { // add to metric? } + // TODO(clamb): Do I need a max catchup config for the backlog? Similar to catchup buffer + for _, msg := range bm.Messages { s := b.tail.Load() if s == nil { @@ -59,7 +66,7 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { } prevMsgIdx := s.end.Load() - if s.MessageCount() >= b.config().SegmentLimit { + if s.count() >= b.config().SegmentLimit { nextS := &backlogSegment{} s.nextSegment.Store(nextS) prevMsgIdx = s.end.Load() @@ -207,7 +214,7 @@ func (b *backlog) lookup(i uint64) (*backlogSegment, error) { return s, nil } -func (s *backlog) MessageCount() int { +func (s *backlog) Count() int { return int(s.messageCount.Load()) } @@ -221,6 +228,11 @@ func (b *backlog) reset() { b.messageCount.Store(0) } +type BacklogSegment interface { + Next() BacklogSegment + Messages() []*m.BroadcastFeedMessage +} + type backlogSegment struct { start atomic.Uint64 end atomic.Uint64 @@ -230,6 +242,14 @@ type backlogSegment struct { previousSegment atomic.Pointer[backlogSegment] } +func (s *backlogSegment) Next() BacklogSegment { + return s.nextSegment.Load() +} + +func (s *backlogSegment) Messages() []*m.BroadcastFeedMessage { + return s.messages +} + // get reads messages from the given start to end MessageIndex func (s *backlogSegment) get(start, end uint64) ([]*m.BroadcastFeedMessage, error) { noMsgs := []*m.BroadcastFeedMessage{} @@ -291,7 +311,7 @@ func (s *backlogSegment) updateSegment(seen *bool) { } } -// MessageCount returns the number of messages stored in the backlog -func (s *backlogSegment) MessageCount() int { +// count returns the number of messages stored in the backlog segment +func (s *backlogSegment) count() int { return int(s.messageCount.Load()) } diff --git a/broadcaster/broadcaster.go b/broadcaster/broadcaster.go index bd7a38289..b96ff1606 100644 --- a/broadcaster/broadcaster.go +++ b/broadcaster/broadcaster.go @@ -80,7 +80,7 @@ func (b *Broadcaster) BroadcastSingleFeedMessage(bfm *m.BroadcastFeedMessage) { func (b *Broadcaster) BroadcastFeedMessages(messages []*m.BroadcastFeedMessage) { - bm := m.BroadcastMessage{ + bm := &m.BroadcastMessage{ Version: 1, Messages: messages, } @@ -90,7 +90,7 @@ func (b *Broadcaster) BroadcastFeedMessages(messages []*m.BroadcastFeedMessage) func (b *Broadcaster) Confirm(seq arbutil.MessageIndex) { log.Debug("confirming sequence number", "sequenceNumber", seq) - b.server.Broadcast(m.BroadcastMessage{ + b.server.Broadcast(&m.BroadcastMessage{ Version: 1, ConfirmedSequenceNumberMessage: &m.ConfirmedSequenceNumberMessage{seq}}) } diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index bdbeccfd2..fff07cf89 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -5,6 +5,7 @@ package wsbroadcastserver import ( "context" + "errors" "fmt" "math/rand" "net" @@ -12,7 +13,9 @@ import ( "sync/atomic" "time" + "github.com/ethereum/go-ethereum/log" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/broadcaster/backlog" "github.com/gobwas/ws" "github.com/gobwas/ws/wsflate" @@ -20,6 +23,8 @@ import ( "github.com/offchainlabs/nitro/util/stopwaiter" ) +var errContextDone = errors.New("context done") + // ClientConnection represents client connection. type ClientConnection struct { stopwaiter.StopWaiter @@ -36,6 +41,8 @@ type ClientConnection struct { lastHeardUnix int64 out chan []byte + backlog backlog.Backlog + registered chan bool compression bool flateReader *wsflate.Reader @@ -51,6 +58,7 @@ func NewClientConnection( connectingIP net.IP, compression bool, delay time.Duration, + bklg backlog.Backlog, ) *ClientConnection { return &ClientConnection{ conn: conn, @@ -65,6 +73,8 @@ func NewClientConnection( compression: compression, flateReader: NewFlateReader(), delay: delay, + backlog: bklg, + registered: make(chan bool, 1), } } @@ -76,33 +86,98 @@ func (cc *ClientConnection) Compression() bool { return cc.compression } +func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.BacklogSegment) (backlog.BacklogSegment, error) { + for segment != nil { + select { + case <-ctx.Done(): + return nil, errContextDone + default: + } + + bm := &m.BroadcastMessage{ + Messages: segment.Messages(), + } + notCompressed, compressed, err := serializeMessage(cc.clientManager, bm, !cc.compression, cc.compression) + if err != nil { + return nil, err + } + + data := []byte{} + if cc.compression { + data = compressed.Bytes() + } else { + data = notCompressed.Bytes() + } + err := cc.writeRaw(data) + if err != nil { + return nil, err + } + log.Debug("segment sent to client", "client", cc.Name, "sentCount", len(bm.Messages)) + + prevSegment = segment + segment = segment.Next() + } + return prevSegment, nil + +} + func (cc *ClientConnection) Start(parentCtx context.Context) { cc.StopWaiter.Start(parentCtx, cc) cc.LaunchThread(func(ctx context.Context) { + // A delay may be configured, ensures the Broadcaster delays before any + // messages are sent to the client. The ClientConnection has not been + // registered so the out channel filling is not a concern. if cc.delay != 0 { - var delayQueue [][]byte t := time.NewTimer(cc.delay) - done := false - for !done { - select { - case <-ctx.Done(): - return - case data := <-cc.out: - delayQueue = append(delayQueue, data) - case <-t.C: - for _, data := range delayQueue { - err := cc.writeRaw(data) - if err != nil { - logWarn(err, "error writing data to client") - cc.clientManager.Remove(cc) - return - } - } - done = true - } + select { + case <-ctx.Done(): + return + case <-t.C: } } + // Send the current backlog before registering the ClientConnection in + // case the backlog is very large + head := cc.backlog.Head() + segment, err := cc.writeBacklog(ctx, head) + if errors.Is(err, errContextDone) { + return + } else if err != nil { + logWarn(err, "error writing messages from backlog") + cc.clientManager.Remove(cc) + return + } + + cc.clientManager.Register(cc) + timer := time.NewTimer(5 * time.Second) + select { + case <-ctx.Done(): + return + case <-cc.registered: + log.Debug("ClientConnection registered with ClientManager", "client", cc.Name) + case <-timer.C: + log.Warn("timed out waiting for ClientConnection to register with ClientManager", "client", cc.Name) + } + + // The backlog may have had more messages added to it whilst the + // ClientConnection registers with the ClientManager, therefore the + // last segment must be sent again. This may result in duplicate + // messages being sent to the client but the client should handle any + // duplicate messages. The ClientConnection can not be registered + // before the backlog is sent as the backlog may be very large. This + // could result in the out channel running out of space. + _, err := cc.writeBacklog(ctx, head) + if errors.Is(err, errContextDone) { + return + } else if err != nil { + logWarn(err, "error writing messages from backlog") + cc.clientManager.Remove(cc) + return + } + + // TODO(clamb): does this still need to consider the requested seq number from the client? currently it just sends everything in the backlog + + // broadcast any new messages sent to the out channel for { select { case <-ctx.Done(): @@ -119,6 +194,12 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { }) } +// Registered is used by the ClientManager to indicate that ClientConnection +// has been registered with the ClientManager +func (cc *ClientConnection) Registered() { + cc.registered <- true +} + func (cc *ClientConnection) StopOnly() { // Ignore errors from conn.Close since we are just shutting down _ = cc.conn.Close() @@ -161,11 +242,11 @@ func (cc *ClientConnection) readRequest(ctx context.Context, timeout time.Durati return data, opCode, err } -func (cc *ClientConnection) Write(x interface{}) error { +func (cc *ClientConnection) Write(bm *m.BroadcastMessage) error { cc.ioMutex.Lock() defer cc.ioMutex.Unlock() - notCompressed, compressed, err := serializeMessage(cc.clientManager, x, !cc.compression, cc.compression) + notCompressed, compressed, err := serializeMessage(cc.clientManager, bm, !cc.compression, cc.compression) if err != nil { return err } diff --git a/wsbroadcastserver/clientmanager.go b/wsbroadcastserver/clientmanager.go index f140e6254..1bfd72044 100644 --- a/wsbroadcastserver/clientmanager.go +++ b/wsbroadcastserver/clientmanager.go @@ -10,7 +10,6 @@ import ( "encoding/json" "fmt" "io" - "net" "strings" "sync/atomic" "time" @@ -24,7 +23,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" - "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/broadcaster/backlog" "github.com/offchainlabs/nitro/util/stopwaiter" ) @@ -39,13 +38,6 @@ var ( clientsDurationHistogram = metrics.NewRegisteredHistogram("arb/feed/clients/duration", nil, metrics.NewBoundedHistogramSample()) ) -// CatchupBuffer is a Protocol-specific client catch-up logic can be injected using this interface -type CatchupBuffer interface { - OnRegisterClient(*ClientConnection) (error, int, time.Duration) - OnDoBroadcast(interface{}) error - GetMessageCount() int -} - // ClientManager manages client connections type ClientManager struct { stopwaiter.StopWaiter @@ -54,10 +46,10 @@ type ClientManager struct { clientCount int32 pool *gopool.Pool poller netpoll.Poller - broadcastChan chan interface{} + broadcastChan chan *m.BroadcastMessage clientAction chan ClientConnectionAction config BroadcasterConfigFetcher - catchupBuffer CatchupBuffer + backlog backlog.Backlog flateWriter *flate.Writer connectionLimiter *ConnectionLimiter @@ -68,16 +60,16 @@ type ClientConnectionAction struct { create bool } -func NewClientManager(poller netpoll.Poller, configFetcher BroadcasterConfigFetcher, catchupBuffer CatchupBuffer) *ClientManager { +func NewClientManager(poller netpoll.Poller, configFetcher BroadcasterConfigFetcher, bklg backlog.Backlog) *ClientManager { config := configFetcher() return &ClientManager{ poller: poller, pool: gopool.NewPool(config.Workers, config.Queue, 1), clientPtrMap: make(map[*ClientConnection]bool), - broadcastChan: make(chan interface{}, 1), + broadcastChan: make(chan *m.BroadcastMessage, 1), clientAction: make(chan ClientConnectionAction, 128), config: configFetcher, - catchupBuffer: catchupBuffer, + backlog: bklg, connectionLimiter: NewConnectionLimiter(func() *ConnectionLimiterConfig { return &configFetcher().ConnectionLimits }), } } @@ -89,6 +81,8 @@ func (cm *ClientManager) registerClient(ctx context.Context, clientConnection *C } }() + // TODO:(clamb) the clientsTotalFailedRegisterCounter was deleted after backlog logic moved to ClientConnection. Should this metric be reintroduced or will it be ok to just delete completely given the behaviour has changed, ask Lee + if cm.config().ConnectionLimits.Enable && !cm.connectionLimiter.Register(clientConnection.clientIp) { return fmt.Errorf("Connection limited %s", clientConnection.clientIp) } @@ -97,40 +91,18 @@ func (cm *ClientManager) registerClient(ctx context.Context, clientConnection *C clientsConnectCount.Inc(1) atomic.AddInt32(&cm.clientCount, 1) - err, sent, elapsed := cm.catchupBuffer.OnRegisterClient(clientConnection) - if err != nil { - clientsTotalFailedRegisterCounter.Inc(1) - if cm.config().ConnectionLimits.Enable { - cm.connectionLimiter.Release(clientConnection.clientIp) - } - return err - } - if cm.config().LogConnect { - log.Info("client registered", "client", clientConnection.Name, "requestedSeqNum", clientConnection.RequestedSeqNum(), "sentCount", sent, "elapsed", elapsed) - } - - clientConnection.Start(ctx) cm.clientPtrMap[clientConnection] = true clientsTotalSuccessCounter.Inc(1) return nil } -// Register registers new connection as a Client. -func (cm *ClientManager) Register( - conn net.Conn, - desc *netpoll.Desc, - requestedSeqNum arbutil.MessageIndex, - connectingIP net.IP, - compression bool, -) *ClientConnection { - createClient := ClientConnectionAction{ - NewClientConnection(conn, desc, cm, requestedSeqNum, connectingIP, compression, cm.config().ClientDelay), +// Register registers given connection as a Client. +func (cm *ClientManager) Register(clientConnection *ClientConnection) { + cm.clientAction <- ClientConnectionAction{ + clientConnection, true, } - cm.clientAction <- createClient - - return createClient.cc } // removeAll removes all clients after main ClientManager thread exits @@ -189,7 +161,7 @@ func (cm *ClientManager) ClientCount() int32 { } // Broadcast sends batch item to all clients. -func (cm *ClientManager) Broadcast(bm interface{}) { +func (cm *ClientManager) Broadcast(bm *m.BroadcastMessage) { if cm.Stopped() { // This should only occur if a reorg occurs after the broadcast server is stopped, // with the sequencer enabled but not the sequencer coordinator. @@ -199,8 +171,8 @@ func (cm *ClientManager) Broadcast(bm interface{}) { cm.broadcastChan <- bm } -func (cm *ClientManager) doBroadcast(bm interface{}) ([]*ClientConnection, error) { - if err := cm.catchupBuffer.OnDoBroadcast(bm); err != nil { +func (cm *ClientManager) doBroadcast(bm *m.BroadcastMessage) ([]*ClientConnection, error) { + if err := cm.backlog.Append(bm); err != nil { return nil, err } config := cm.config() @@ -348,6 +320,7 @@ func (cm *ClientManager) Start(parentCtx context.Context) { // Log message already output in registerClient cm.removeClientImpl(clientAction.cc) } + clientAction.cc.Registered() } else { cm.removeClient(clientAction.cc) } diff --git a/wsbroadcastserver/wsbroadcastserver.go b/wsbroadcastserver/wsbroadcastserver.go index d51b36840..02adaa370 100644 --- a/wsbroadcastserver/wsbroadcastserver.go +++ b/wsbroadcastserver/wsbroadcastserver.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/broadcaster/backlog" ) var ( @@ -163,18 +164,18 @@ type WSBroadcastServer struct { config BroadcasterConfigFetcher started bool clientManager *ClientManager - catchupBuffer CatchupBuffer + backlog backlog.Backlog chainId uint64 fatalErrChan chan error } -func NewWSBroadcastServer(config BroadcasterConfigFetcher, catchupBuffer CatchupBuffer, chainId uint64, fatalErrChan chan error) *WSBroadcastServer { +func NewWSBroadcastServer(config BroadcasterConfigFetcher, bklg backlog.Backlog, chainId uint64, fatalErrChan chan error) *WSBroadcastServer { return &WSBroadcastServer{ - config: config, - started: false, - catchupBuffer: catchupBuffer, - chainId: chainId, - fatalErrChan: fatalErrChan, + config: config, + started: false, + backlog: bklg, + chainId: chainId, + fatalErrChan: fatalErrChan, } } @@ -192,7 +193,7 @@ func (s *WSBroadcastServer) Initialize() error { // Make pool of X size, Y sized work queue and one pre-spawned // goroutine. - s.clientManager = NewClientManager(s.poller, s.config, s.catchupBuffer) + s.clientManager = NewClientManager(s.poller, s.config, s.backlog) return nil } @@ -372,7 +373,8 @@ func (s *WSBroadcastServer) StartWithHeader(ctx context.Context, header ws.Hands // Register incoming client in clientManager. safeConn := writeDeadliner{conn, config.WriteTimeout} - client := s.clientManager.Register(safeConn, desc, requestedSeqNum, connectingIP, compressionAccepted) + client := NewClientConnection(safeConn, desc, s.clientManager, requestedSeqNum, connectingIP, compressionAccepted, s.config().ClientDelay, s.backlog) + client.Start(ctx) // Subscribe to events about conn. err = s.poller.Start(desc, func(ev netpoll.Event) { @@ -528,7 +530,7 @@ func (s *WSBroadcastServer) Started() bool { } // Broadcast sends batch item to all clients. -func (s *WSBroadcastServer) Broadcast(bm interface{}) { +func (s *WSBroadcastServer) Broadcast(bm *m.BroadcastMessage) { s.clientManager.Broadcast(bm) } From 54ea210b0e73c7a724060fa1f55e7598121e0525 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 19 Oct 2023 20:48:46 +1300 Subject: [PATCH 371/775] fix go vet errors --- broadcaster/backlog/backlog_test.go | 20 ++++++++++++----- broadcaster/broadcaster.go | 28 +++++++++++++----------- broadcaster/broadcaster_test.go | 30 +++++++++++++++----------- wsbroadcastserver/clientconnection.go | 6 ++++-- wsbroadcastserver/clientmanager.go | 1 + wsbroadcastserver/wsbroadcastserver.go | 5 +++++ 6 files changed, 58 insertions(+), 32 deletions(-) diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go index 65b5d7095..3683c6108 100644 --- a/broadcaster/backlog/backlog_test.go +++ b/broadcaster/backlog/backlog_test.go @@ -13,8 +13,8 @@ import ( ) func validateBacklog(t *testing.T, b *backlog, count int, start, end uint64, lookupKeys []arbutil.MessageIndex) { - if b.MessageCount() != count { - t.Errorf("backlog message count (%d) does not equal expected message count (%d)", b.MessageCount(), count) + if b.Count() != count { + t.Errorf("backlog message count (%d) does not equal expected message count (%d)", b.Count(), count) } head := b.head.Load() @@ -387,13 +387,15 @@ func TestBacklogRaceCondition(t *testing.T) { // Write to backlog in goroutine wg.Add(1) + errs := make(chan error, 15) go func(t *testing.T, b *backlog) { defer wg.Done() for _, i := range newIndexes { bm := m.CreateDummyBroadcastMessage([]arbutil.MessageIndex{i}) err := b.Append(bm) + errs <- err if err != nil { - t.Fatalf("unexpected error: %s", err) + return } time.Sleep(time.Millisecond) } @@ -405,8 +407,9 @@ func TestBacklogRaceCondition(t *testing.T) { defer wg.Done() for _, i := range []uint64{42, 43, 44, 45, 46, 47} { bm, err := b.Get(i, i+1) + errs <- err if err != nil { - t.Fatalf("unexpected error: %s", err) + return } else { validateBroadcastMessage(t, bm, 2, i, i+1) } @@ -425,8 +428,15 @@ func TestBacklogRaceCondition(t *testing.T) { } }(t, b) - // Wait for all goroutines to finish + // Wait for all goroutines to finish or return errors wg.Wait() + close(errs) + for err = range errs { + + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + } // Messages up to 47 were deleted. However the segment that 47 was in is // kept, which is why the backlog starts at 46. validateBacklog(t, b, 10, 46, 55, append(indexes, newIndexes...)) diff --git a/broadcaster/broadcaster.go b/broadcaster/broadcaster.go index b96ff1606..270d153af 100644 --- a/broadcaster/broadcaster.go +++ b/broadcaster/broadcaster.go @@ -13,25 +13,26 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/broadcaster/backlog" m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/util/signature" "github.com/offchainlabs/nitro/wsbroadcastserver" ) type Broadcaster struct { - server *wsbroadcastserver.WSBroadcastServer - catchupBuffer *SequenceNumberCatchupBuffer - chainId uint64 - dataSigner signature.DataSignerFunc + server *wsbroadcastserver.WSBroadcastServer + backlog backlog.Backlog + chainId uint64 + dataSigner signature.DataSignerFunc } func NewBroadcaster(config wsbroadcastserver.BroadcasterConfigFetcher, chainId uint64, feedErrChan chan error, dataSigner signature.DataSignerFunc) *Broadcaster { - catchupBuffer := NewSequenceNumberCatchupBuffer(func() bool { return config().LimitCatchup }, func() int { return config().MaxCatchup }) + bklg := backlog.NewBacklog(func() *backlog.Config { return &config().Backlog }) return &Broadcaster{ - server: wsbroadcastserver.NewWSBroadcastServer(config, catchupBuffer, chainId, feedErrChan), - catchupBuffer: catchupBuffer, - chainId: chainId, - dataSigner: dataSigner, + server: wsbroadcastserver.NewWSBroadcastServer(config, bklg, chainId, feedErrChan), + backlog: bklg, + chainId: chainId, + dataSigner: dataSigner, } } @@ -91,8 +92,11 @@ func (b *Broadcaster) BroadcastFeedMessages(messages []*m.BroadcastFeedMessage) func (b *Broadcaster) Confirm(seq arbutil.MessageIndex) { log.Debug("confirming sequence number", "sequenceNumber", seq) b.server.Broadcast(&m.BroadcastMessage{ - Version: 1, - ConfirmedSequenceNumberMessage: &m.ConfirmedSequenceNumberMessage{seq}}) + Version: 1, + ConfirmedSequenceNumberMessage: &m.ConfirmedSequenceNumberMessage{ + SequenceNumber: seq, + }, + }) } func (b *Broadcaster) ClientCount() int32 { @@ -104,7 +108,7 @@ func (b *Broadcaster) ListenerAddr() net.Addr { } func (b *Broadcaster) GetCachedMessageCount() int { - return b.catchupBuffer.GetMessageCount() + return b.backlog.Count() } func (b *Broadcaster) Initialize() error { diff --git a/broadcaster/broadcaster_test.go b/broadcaster/broadcaster_test.go index a97facef3..79291e023 100644 --- a/broadcaster/broadcaster_test.go +++ b/broadcaster/broadcaster_test.go @@ -44,7 +44,7 @@ type messageCountPredicate struct { } func (p *messageCountPredicate) Test() bool { - p.was = p.b.catchupBuffer.GetMessageCount() + p.was = p.b.backlog.Count() return p.was == p.expected } @@ -78,26 +78,30 @@ func TestBroadcasterMessagesRemovedOnConfirmation(t *testing.T) { waitUntilUpdated(t, expectMessageCount(3, "after 3 messages")) Require(t, b.BroadcastSingle(arbostypes.EmptyTestMessageWithMetadata, 4)) waitUntilUpdated(t, expectMessageCount(4, "after 4 messages")) + Require(t, b.BroadcastSingle(arbostypes.EmptyTestMessageWithMetadata, 5)) + waitUntilUpdated(t, expectMessageCount(5, "after 4 messages")) + Require(t, b.BroadcastSingle(arbostypes.EmptyTestMessageWithMetadata, 6)) + waitUntilUpdated(t, expectMessageCount(6, "after 4 messages")) - b.Confirm(1) + b.Confirm(4) waitUntilUpdated(t, expectMessageCount(3, - "after 4 messages, 1 cleared by confirm")) + "after 6 messages, 4 cleared by confirm (first backlog segment)")) - b.Confirm(2) - waitUntilUpdated(t, expectMessageCount(2, - "after 4 messages, 2 cleared by confirm")) + b.Confirm(5) + waitUntilUpdated(t, expectMessageCount(3, + "after 6 messages, 5 cleared by confirm, but segment containing 5th message remains in backlog")) - b.Confirm(1) - waitUntilUpdated(t, expectMessageCount(2, + b.Confirm(4) + waitUntilUpdated(t, expectMessageCount(3, "nothing changed because confirmed sequence number before cache")) - b.Confirm(2) - Require(t, b.BroadcastSingle(arbostypes.EmptyTestMessageWithMetadata, 5)) - waitUntilUpdated(t, expectMessageCount(3, - "after 5 messages, 2 cleared by confirm")) + b.Confirm(5) + Require(t, b.BroadcastSingle(arbostypes.EmptyTestMessageWithMetadata, 7)) + waitUntilUpdated(t, expectMessageCount(4, + "after 7 messages, 4 cleared by confirm, but segment containing 5th message remains in backlog")) // Confirm not-yet-seen or already confirmed/cleared sequence numbers twice to force clearing cache - b.Confirm(6) + b.Confirm(8) waitUntilUpdated(t, expectMessageCount(0, "clear all messages after confirmed 1 beyond latest")) } diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index fff07cf89..82fd3ce6c 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcaster/backlog" + m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/gobwas/ws" "github.com/gobwas/ws/wsflate" @@ -87,6 +88,7 @@ func (cc *ClientConnection) Compression() bool { } func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.BacklogSegment) (backlog.BacklogSegment, error) { + var prevSegment backlog.BacklogSegment for segment != nil { select { case <-ctx.Done(): @@ -108,7 +110,7 @@ func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.Ba } else { data = notCompressed.Bytes() } - err := cc.writeRaw(data) + err = cc.writeRaw(data) if err != nil { return nil, err } @@ -166,7 +168,7 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { // duplicate messages. The ClientConnection can not be registered // before the backlog is sent as the backlog may be very large. This // could result in the out channel running out of space. - _, err := cc.writeBacklog(ctx, head) + _, err = cc.writeBacklog(ctx, segment) if errors.Is(err, errContextDone) { return } else if err != nil { diff --git a/wsbroadcastserver/clientmanager.go b/wsbroadcastserver/clientmanager.go index 1bfd72044..1de63a833 100644 --- a/wsbroadcastserver/clientmanager.go +++ b/wsbroadcastserver/clientmanager.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/offchainlabs/nitro/broadcaster/backlog" + m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/util/stopwaiter" ) diff --git a/wsbroadcastserver/wsbroadcastserver.go b/wsbroadcastserver/wsbroadcastserver.go index 02adaa370..3a98871fe 100644 --- a/wsbroadcastserver/wsbroadcastserver.go +++ b/wsbroadcastserver/wsbroadcastserver.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcaster/backlog" + m "github.com/offchainlabs/nitro/broadcaster/message" ) var ( @@ -67,6 +68,7 @@ type BroadcasterConfig struct { MaxCatchup int `koanf:"max-catchup" reload:"hot"` ConnectionLimits ConnectionLimiterConfig `koanf:"connection-limits" reload:"hot"` ClientDelay time.Duration `koanf:"client-delay" reload:"hot"` + Backlog backlog.Config `koanf:"backlog" reload:"hot"` } func (bc *BroadcasterConfig) Validate() error { @@ -101,6 +103,7 @@ func BroadcasterConfigAddOptions(prefix string, f *flag.FlagSet) { f.Int(prefix+".max-catchup", DefaultBroadcasterConfig.MaxCatchup, "the maximum size of the catchup buffer (-1 means unlimited)") ConnectionLimiterConfigAddOptions(prefix+".connection-limits", f) f.Duration(prefix+".client-delay", DefaultBroadcasterConfig.ClientDelay, "delay the first messages sent to each client by this amount") + backlog.AddOptions(prefix+".backlog", f) } var DefaultBroadcasterConfig = BroadcasterConfig{ @@ -126,6 +129,7 @@ var DefaultBroadcasterConfig = BroadcasterConfig{ MaxCatchup: -1, ConnectionLimits: DefaultConnectionLimiterConfig, ClientDelay: 0, + Backlog: backlog.DefaultConfig, } var DefaultTestBroadcasterConfig = BroadcasterConfig{ @@ -151,6 +155,7 @@ var DefaultTestBroadcasterConfig = BroadcasterConfig{ MaxCatchup: -1, ConnectionLimits: DefaultConnectionLimiterConfig, ClientDelay: 0, + Backlog: backlog.DefaultTestConfig, } type WSBroadcastServer struct { From 946046acd17d60ea5499501759c4a6e34f742bd0 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 1 Nov 2023 14:35:47 +1300 Subject: [PATCH 372/775] use Lookup() and requestedSeqNum instead of Head() when sending messages from the backlog --- broadcaster/backlog/backlog.go | 133 ++++++++++++++++---------- broadcaster/backlog/backlog_test.go | 15 ++- wsbroadcastserver/clientconnection.go | 13 ++- wsbroadcastserver/clientmanager.go | 2 +- 4 files changed, 97 insertions(+), 66 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 1ea46ee5a..32cf7bfd5 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -18,10 +18,9 @@ var ( ) type Backlog interface { - Head() BacklogSegment - Append(bm *m.BroadcastMessage) error - Get(start, end uint64) (*m.BroadcastMessage, error) - Count() int + Append(*m.BroadcastMessage) error + Count() uint64 + Lookup(uint64) (BacklogSegment, error) } type backlog struct { @@ -41,10 +40,6 @@ func NewBacklog(c ConfigFetcher) Backlog { } } -func (b *backlog) Head() BacklogSegment { - return b.head.Load() -} - // Append will add the given messages to the backlogSegment at head until // that segment reaches its limit. If messages remain to be added a new segment // will be created. @@ -52,35 +47,35 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { if bm.ConfirmedSequenceNumberMessage != nil { b.delete(uint64(bm.ConfirmedSequenceNumberMessage.SequenceNumber)) - // add to metric? + // TODO(clamb): add to metric? } // TODO(clamb): Do I need a max catchup config for the backlog? Similar to catchup buffer for _, msg := range bm.Messages { - s := b.tail.Load() - if s == nil { - s = &backlogSegment{} - b.head.Store(s) - b.tail.Store(s) + segment := b.tail.Load() + if segment == nil { + segment = newBacklogSegment() + b.head.Store(segment) + b.tail.Store(segment) } - prevMsgIdx := s.end.Load() - if s.count() >= b.config().SegmentLimit { - nextS := &backlogSegment{} - s.nextSegment.Store(nextS) - prevMsgIdx = s.end.Load() - nextS.previousSegment.Store(s) - s = nextS - b.tail.Store(s) + prevMsgIdx := segment.End() + if segment.count() >= b.config().SegmentLimit { + nextSegment := newBacklogSegment() + segment.nextSegment.Store(nextSegment) + prevMsgIdx = segment.End() + nextSegment.previousSegment.Store(segment) + segment = nextSegment + b.tail.Store(segment) } - err := s.append(prevMsgIdx, msg) + err := segment.append(prevMsgIdx, msg) if errors.Is(err, errDropSegments) { head := b.head.Load() - b.removeFromLookup(head.start.Load(), uint64(msg.SequenceNumber)) - b.head.Store(s) - b.tail.Store(s) + b.removeFromLookup(head.Start(), uint64(msg.SequenceNumber)) + b.head.Store(segment) + b.tail.Store(segment) b.messageCount.Store(0) log.Warn(err.Error()) } else if errors.Is(err, errSequenceNumberSeen) { @@ -90,7 +85,7 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { return err } p := &atomic.Pointer[backlogSegment]{} - p.Store(s) + p.Store(segment) b.lookupLock.Lock() b.lookupByIndex[uint64(msg.SequenceNumber)] = p b.lookupLock.Unlock() @@ -100,23 +95,24 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { return nil } -// Get reads messages from the given start to end MessageIndex -func (b *backlog) Get(start, end uint64) (*m.BroadcastMessage, error) { +// get reads messages from the given start to end MessageIndex. It was created +// for the original implementation of the backlog but currently is not used. +func (b *backlog) get(start, end uint64) (*m.BroadcastMessage, error) { head := b.head.Load() tail := b.tail.Load() if head == nil && tail == nil { return nil, errOutOfBounds } - if start < head.start.Load() { - start = head.start.Load() + if start < head.Start() { + start = head.Start() } - if end > tail.end.Load() { + if end > tail.End() { return nil, errOutOfBounds } - s, err := b.lookup(start) + segment, err := b.Lookup(start) if err != nil { return nil, err } @@ -124,16 +120,16 @@ func (b *backlog) Get(start, end uint64) (*m.BroadcastMessage, error) { bm := &m.BroadcastMessage{Version: 1} required := int(end-start) + 1 for { - segMsgs, err := s.get(arbmath.MaxInt(start, s.start.Load()), arbmath.MinInt(end, s.end.Load())) + segMsgs, err := segment.Get(arbmath.MaxInt(start, segment.Start()), arbmath.MinInt(end, segment.End())) if err != nil { return nil, err } bm.Messages = append(bm.Messages, segMsgs...) - s = s.nextSegment.Load() + segment = segment.Next() if len(bm.Messages) == required { break - } else if s == nil { + } else if segment == nil { return nil, errOutOfBounds } } @@ -149,11 +145,11 @@ func (b *backlog) delete(confirmed uint64) { return } - if confirmed < head.start.Load() { + if confirmed < head.Start() { return } - if confirmed > tail.end.Load() { + if confirmed > tail.End() { log.Error("confirmed sequence number is past the end of stored messages", "confirmed sequence number", confirmed, "last stored sequence number", tail.end.Load()) b.reset() // should this be returning an error? The other buffer does not and just continues @@ -161,7 +157,7 @@ func (b *backlog) delete(confirmed uint64) { } // find the segment containing the confirmed message - s, err := b.lookup(confirmed) + segment, err := b.Lookup(confirmed) if err != nil { log.Error(fmt.Sprintf("%s: clearing backlog", err.Error())) b.reset() @@ -170,7 +166,7 @@ func (b *backlog) delete(confirmed uint64) { } // check the segment actually contains that message - if found := s.contains(confirmed); !found { + if found := segment.Contains(confirmed); !found { log.Error("error message not found in backlog segment, clearing backlog", "confirmed sequence number", confirmed) b.reset() // should this be returning an error? The other buffer does not and just continues @@ -178,13 +174,13 @@ func (b *backlog) delete(confirmed uint64) { } // remove all previous segments - previous := s.previousSegment.Load() - if previous == nil { + previous := segment.Previous() + if IsBacklogSegmentNil(previous) { return } - b.removeFromLookup(head.start.Load(), previous.end.Load()) - b.head.Store(s) - count := b.messageCount.Load() + head.start.Load() - previous.end.Load() - uint64(1) + b.removeFromLookup(head.Start(), previous.End()) + b.head.Store(segment.(*backlogSegment)) + count := b.Count() + head.Start() - previous.End() - uint64(1) b.messageCount.Store(count) } @@ -198,7 +194,7 @@ func (b *backlog) removeFromLookup(start, end uint64) { } } -func (b *backlog) lookup(i uint64) (*backlogSegment, error) { +func (b *backlog) Lookup(i uint64) (BacklogSegment, error) { b.lookupLock.RLock() pointer, ok := b.lookupByIndex[i] b.lookupLock.RUnlock() @@ -214,8 +210,8 @@ func (b *backlog) lookup(i uint64) (*backlogSegment, error) { return s, nil } -func (s *backlog) Count() int { - return int(s.messageCount.Load()) +func (s *backlog) Count() uint64 { + return s.messageCount.Load() } // reset removes all segments from the backlog @@ -229,7 +225,12 @@ func (b *backlog) reset() { } type BacklogSegment interface { + Start() uint64 + End() uint64 + Contains(uint64) bool Next() BacklogSegment + Previous() BacklogSegment + Get(uint64, uint64) ([]*m.BroadcastFeedMessage, error) Messages() []*m.BroadcastFeedMessage } @@ -242,16 +243,44 @@ type backlogSegment struct { previousSegment atomic.Pointer[backlogSegment] } +// newBacklogSegment creates a backlogSegment object with an empty slice of +// messages. It does not return an interface as it is only used inside the +// backlog library. +func newBacklogSegment() *backlogSegment { + return &backlogSegment{ + messages: []*m.BroadcastFeedMessage{}, + } +} + +// IsBacklogSegmentNil uses the internal backlogSegment type to check if a +// variable of type BacklogSegment is nil or not. Comparing whether an +// interface is nil directly will not work. +func IsBacklogSegmentNil(segment BacklogSegment) bool { + return segment.(*backlogSegment) == nil +} + +func (s *backlogSegment) Start() uint64 { + return uint64(s.start.Load()) +} + +func (s *backlogSegment) End() uint64 { + return uint64(s.end.Load()) +} + func (s *backlogSegment) Next() BacklogSegment { return s.nextSegment.Load() } +func (s *backlogSegment) Previous() BacklogSegment { + return s.previousSegment.Load() +} + func (s *backlogSegment) Messages() []*m.BroadcastFeedMessage { return s.messages } -// get reads messages from the given start to end MessageIndex -func (s *backlogSegment) get(start, end uint64) ([]*m.BroadcastFeedMessage, error) { +// Get reads messages from the given start to end MessageIndex +func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, error) { noMsgs := []*m.BroadcastFeedMessage{} if start < s.start.Load() { return noMsgs, errOutOfBounds @@ -288,8 +317,8 @@ func (s *backlogSegment) append(prevMsgIdx uint64, msg *m.BroadcastFeedMessage) return nil } -// contains confirms whether the segment contains a message with the given sequence number -func (s *backlogSegment) contains(i uint64) bool { +// Contains confirms whether the segment contains a message with the given sequence number +func (s *backlogSegment) Contains(i uint64) bool { if i < s.start.Load() || i > s.end.Load() { return false } diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go index 3683c6108..559480bfe 100644 --- a/broadcaster/backlog/backlog_test.go +++ b/broadcaster/backlog/backlog_test.go @@ -12,7 +12,7 @@ import ( "github.com/offchainlabs/nitro/util/arbmath" ) -func validateBacklog(t *testing.T, b *backlog, count int, start, end uint64, lookupKeys []arbutil.MessageIndex) { +func validateBacklog(t *testing.T, b *backlog, count, start, end uint64, lookupKeys []arbutil.MessageIndex) { if b.Count() != count { t.Errorf("backlog message count (%d) does not equal expected message count (%d)", b.Count(), count) } @@ -28,7 +28,7 @@ func validateBacklog(t *testing.T, b *backlog, count int, start, end uint64, loo } for _, k := range lookupKeys { - if _, err := b.lookup(uint64(k)); err != nil { + if _, err := b.Lookup(uint64(k)); err != nil { t.Errorf("failed to find message (%d) in lookup", k) } } @@ -64,7 +64,7 @@ func TestAppend(t *testing.T) { name string backlogIndexes []arbutil.MessageIndex newIndexes []arbutil.MessageIndex - expectedCount int + expectedCount uint64 expectedStart uint64 expectedEnd uint64 expectedLookupKeys []arbutil.MessageIndex @@ -187,7 +187,7 @@ func TestDelete(t *testing.T) { name string backlogIndexes []arbutil.MessageIndex confirmed arbutil.MessageIndex - expectedCount int + expectedCount uint64 expectedStart uint64 expectedEnd uint64 expectedLookupKeys []arbutil.MessageIndex @@ -252,7 +252,6 @@ func TestDelete(t *testing.T) { SequenceNumber: tc.confirmed, }, } - err = b.Append(bm) if err != nil { t.Fatalf("error appending BroadcastMessage: %s", err) @@ -271,7 +270,7 @@ func TestGetEmptyBacklog(t *testing.T) { t.Fatalf("error creating dummy backlog: %s", err) } - _, err = b.Get(1, 2) + _, err = b.get(1, 2) if !errors.Is(err, errOutOfBounds) { t.Fatalf("unexpected error: %s", err) } @@ -358,7 +357,7 @@ func TestGet(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - bm, err := b.Get(tc.start, tc.end) + bm, err := b.get(tc.start, tc.end) if !errors.Is(err, tc.expectedErr) { t.Fatalf("unexpected error: %s", err) } @@ -406,7 +405,7 @@ func TestBacklogRaceCondition(t *testing.T) { go func(t *testing.T, b *backlog) { defer wg.Done() for _, i := range []uint64{42, 43, 44, 45, 46, 47} { - bm, err := b.Get(i, i+1) + bm, err := b.get(i, i+1) errs <- err if err != nil { return diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 82fd3ce6c..c7ecfbda9 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -89,7 +89,7 @@ func (cc *ClientConnection) Compression() bool { func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.BacklogSegment) (backlog.BacklogSegment, error) { var prevSegment backlog.BacklogSegment - for segment != nil { + for !backlog.IsBacklogSegmentNil(segment) { select { case <-ctx.Done(): return nil, errContextDone @@ -140,8 +140,13 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { // Send the current backlog before registering the ClientConnection in // case the backlog is very large - head := cc.backlog.Head() - segment, err := cc.writeBacklog(ctx, head) + segment, err := cc.backlog.Lookup(cc.requestedSeqNum) + if err != nil { + logWarn(err, "error finding requested sequence number in backlog") + cc.clientManager.Remove(cc) + return + } + segment, err = cc.writeBacklog(ctx, segment) if errors.Is(err, errContextDone) { return } else if err != nil { @@ -177,8 +182,6 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { return } - // TODO(clamb): does this still need to consider the requested seq number from the client? currently it just sends everything in the backlog - // broadcast any new messages sent to the out channel for { select { diff --git a/wsbroadcastserver/clientmanager.go b/wsbroadcastserver/clientmanager.go index 1de63a833..b2790f850 100644 --- a/wsbroadcastserver/clientmanager.go +++ b/wsbroadcastserver/clientmanager.go @@ -227,7 +227,7 @@ func (cm *ClientManager) doBroadcast(bm *m.BroadcastMessage) ([]*ClientConnectio return clientDeleteList, nil } -func serializeMessage(cm *ClientManager, bm interface{}, enableNonCompressedOutput, enableCompressedOutput bool) (bytes.Buffer, bytes.Buffer, error) { +func serializeMessage(cm *ClientManager, bm *m.BroadcastMessage, enableNonCompressedOutput, enableCompressedOutput bool) (bytes.Buffer, bytes.Buffer, error) { var notCompressed bytes.Buffer var compressed bytes.Buffer writers := []io.Writer{} From ff440a4ca00d043efabedc9ff1733fee85022a39 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 1 Nov 2023 14:37:32 +1300 Subject: [PATCH 373/775] change warn to error --- wsbroadcastserver/clientconnection.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index c7ecfbda9..f97516f69 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -163,7 +163,7 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { case <-cc.registered: log.Debug("ClientConnection registered with ClientManager", "client", cc.Name) case <-timer.C: - log.Warn("timed out waiting for ClientConnection to register with ClientManager", "client", cc.Name) + log.Error("timed out waiting for ClientConnection to register with ClientManager", "client", cc.Name) } // The backlog may have had more messages added to it whilst the From 5d36e6b4033b249fc71432fa3e2976ef0f9f76db Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 1 Nov 2023 17:23:47 +1300 Subject: [PATCH 374/775] change lookupByIndex map values from atomic pointer to backlogSegment to normal pointer to backlogSegment --- broadcaster/backlog/backlog.go | 19 ++++++------------- broadcaster/backlog/backlog_test.go | 9 +++------ 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 32cf7bfd5..850aff3c7 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -27,13 +27,13 @@ type backlog struct { head atomic.Pointer[backlogSegment] tail atomic.Pointer[backlogSegment] lookupLock sync.RWMutex - lookupByIndex map[uint64]*atomic.Pointer[backlogSegment] + lookupByIndex map[uint64]*backlogSegment config ConfigFetcher messageCount atomic.Uint64 } func NewBacklog(c ConfigFetcher) Backlog { - lookup := make(map[uint64]*atomic.Pointer[backlogSegment]) + lookup := make(map[uint64]*backlogSegment) return &backlog{ lookupByIndex: lookup, config: c, @@ -84,10 +84,8 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { } else if err != nil { return err } - p := &atomic.Pointer[backlogSegment]{} - p.Store(segment) b.lookupLock.Lock() - b.lookupByIndex[uint64(msg.SequenceNumber)] = p + b.lookupByIndex[uint64(msg.SequenceNumber)] = segment b.lookupLock.Unlock() b.messageCount.Add(1) } @@ -196,18 +194,13 @@ func (b *backlog) removeFromLookup(start, end uint64) { func (b *backlog) Lookup(i uint64) (BacklogSegment, error) { b.lookupLock.RLock() - pointer, ok := b.lookupByIndex[i] + segment, ok := b.lookupByIndex[i] b.lookupLock.RUnlock() if !ok { return nil, fmt.Errorf("error finding backlog segment containing message with SequenceNumber %d", i) } - s := pointer.Load() - if s == nil { - return nil, fmt.Errorf("error loading backlog segment containing message with SequenceNumber %d", i) - } - - return s, nil + return segment, nil } func (s *backlog) Count() uint64 { @@ -220,7 +213,7 @@ func (b *backlog) reset() { defer b.lookupLock.Unlock() b.head = atomic.Pointer[backlogSegment]{} b.tail = atomic.Pointer[backlogSegment]{} - b.lookupByIndex = map[uint64]*atomic.Pointer[backlogSegment]{} + b.lookupByIndex = map[uint64]*backlogSegment{} b.messageCount.Store(0) } diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go index 559480bfe..8872be841 100644 --- a/broadcaster/backlog/backlog_test.go +++ b/broadcaster/backlog/backlog_test.go @@ -3,7 +3,6 @@ package backlog import ( "errors" "sync" - "sync/atomic" "testing" "time" @@ -51,7 +50,7 @@ func validateBroadcastMessage(t *testing.T, bm *m.BroadcastMessage, expectedCoun func createDummyBacklog(indexes []arbutil.MessageIndex) (*backlog, error) { b := &backlog{ - lookupByIndex: map[uint64]*atomic.Pointer[backlogSegment]{}, + lookupByIndex: map[uint64]*backlogSegment{}, config: func() *Config { return &DefaultTestConfig }, } bm := &m.BroadcastMessage{Messages: m.CreateDummyBroadcastMessages(indexes)} @@ -155,10 +154,8 @@ func TestDeleteInvalidBacklog(t *testing.T) { s.end.Store(42) s.messageCount.Store(2) - p := &atomic.Pointer[backlogSegment]{} - p.Store(s) - lookup := make(map[uint64]*atomic.Pointer[backlogSegment]) - lookup[40] = p + lookup := make(map[uint64]*backlogSegment) + lookup[40] = s b := &backlog{ lookupByIndex: lookup, config: func() *Config { return &DefaultTestConfig }, From bff53fca1da330118b15e2205eca9a3aec8575ef Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 1 Nov 2023 17:37:14 +1300 Subject: [PATCH 375/775] remove max catchup TODO - not necessary --- broadcaster/backlog/backlog.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 850aff3c7..7cff4028c 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -50,8 +50,6 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { // TODO(clamb): add to metric? } - // TODO(clamb): Do I need a max catchup config for the backlog? Similar to catchup buffer - for _, msg := range bm.Messages { segment := b.tail.Load() if segment == nil { From 1faa39ecef1af208530abfcab666fa74b11f1a52 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 1 Nov 2023 17:44:34 +1300 Subject: [PATCH 376/775] fix broadcaster tests after Head -> Lookup change in clientconnection --- broadcaster/broadcaster.go | 2 +- broadcaster/broadcaster_test.go | 2 +- wsbroadcastserver/clientconnection.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/broadcaster/broadcaster.go b/broadcaster/broadcaster.go index 270d153af..8a70e3981 100644 --- a/broadcaster/broadcaster.go +++ b/broadcaster/broadcaster.go @@ -108,7 +108,7 @@ func (b *Broadcaster) ListenerAddr() net.Addr { } func (b *Broadcaster) GetCachedMessageCount() int { - return b.backlog.Count() + return int(b.backlog.Count()) } func (b *Broadcaster) Initialize() error { diff --git a/broadcaster/broadcaster_test.go b/broadcaster/broadcaster_test.go index 79291e023..884f1de1d 100644 --- a/broadcaster/broadcaster_test.go +++ b/broadcaster/broadcaster_test.go @@ -44,7 +44,7 @@ type messageCountPredicate struct { } func (p *messageCountPredicate) Test() bool { - p.was = p.b.backlog.Count() + p.was = p.b.GetCachedMessageCount() return p.was == p.expected } diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index f97516f69..c457d9a22 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -140,7 +140,7 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { // Send the current backlog before registering the ClientConnection in // case the backlog is very large - segment, err := cc.backlog.Lookup(cc.requestedSeqNum) + segment, err := cc.backlog.Lookup(uint64(cc.requestedSeqNum)) if err != nil { logWarn(err, "error finding requested sequence number in backlog") cc.clientManager.Remove(cc) From 06d72a8411337ea483f71505ec5aeb8fb2a5c32b Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 2 Nov 2023 15:20:14 +1300 Subject: [PATCH 377/775] fix broadcast client invalid signature test --- wsbroadcastserver/clientconnection.go | 1 + 1 file changed, 1 insertion(+) diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index c457d9a22..907108b6b 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -97,6 +97,7 @@ func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.Ba } bm := &m.BroadcastMessage{ + Version: 1, // TODO(clamb): I am unsure if it is correct to hard code the version here like this? It seems to be done in other places though Messages: segment.Messages(), } notCompressed, compressed, err := serializeMessage(cc.clientManager, bm, !cc.compression, cc.compression) From a0bf64b7bd46860664ae46db91fa6c7288d157e8 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Tue, 7 Nov 2023 16:07:06 +1300 Subject: [PATCH 378/775] fix backlog sending duplicate messages to clients --- broadcaster/backlog/backlog.go | 6 +- broadcaster/backlog/backlog_test.go | 6 +- broadcaster/sequencenumbercatchupbuffer.go | 194 ------------- .../sequencenumbercatchupbuffer_test.go | 255 ------------------ wsbroadcastserver/clientconnection.go | 124 +++++---- wsbroadcastserver/clientmanager.go | 24 +- 6 files changed, 93 insertions(+), 516 deletions(-) delete mode 100644 broadcaster/sequencenumbercatchupbuffer.go delete mode 100644 broadcaster/sequencenumbercatchupbuffer_test.go diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 7cff4028c..57b481007 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -19,6 +19,7 @@ var ( type Backlog interface { Append(*m.BroadcastMessage) error + Get(uint64, uint64) (*m.BroadcastMessage, error) Count() uint64 Lookup(uint64) (BacklogSegment, error) } @@ -91,9 +92,8 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { return nil } -// get reads messages from the given start to end MessageIndex. It was created -// for the original implementation of the backlog but currently is not used. -func (b *backlog) get(start, end uint64) (*m.BroadcastMessage, error) { +// Get reads messages from the given start to end MessageIndex. +func (b *backlog) Get(start, end uint64) (*m.BroadcastMessage, error) { head := b.head.Load() tail := b.tail.Load() if head == nil && tail == nil { diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go index 8872be841..4a31e6c57 100644 --- a/broadcaster/backlog/backlog_test.go +++ b/broadcaster/backlog/backlog_test.go @@ -267,7 +267,7 @@ func TestGetEmptyBacklog(t *testing.T) { t.Fatalf("error creating dummy backlog: %s", err) } - _, err = b.get(1, 2) + _, err = b.Get(1, 2) if !errors.Is(err, errOutOfBounds) { t.Fatalf("unexpected error: %s", err) } @@ -354,7 +354,7 @@ func TestGet(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - bm, err := b.get(tc.start, tc.end) + bm, err := b.Get(tc.start, tc.end) if !errors.Is(err, tc.expectedErr) { t.Fatalf("unexpected error: %s", err) } @@ -402,7 +402,7 @@ func TestBacklogRaceCondition(t *testing.T) { go func(t *testing.T, b *backlog) { defer wg.Done() for _, i := range []uint64{42, 43, 44, 45, 46, 47} { - bm, err := b.get(i, i+1) + bm, err := b.Get(i, i+1) errs <- err if err != nil { return diff --git a/broadcaster/sequencenumbercatchupbuffer.go b/broadcaster/sequencenumbercatchupbuffer.go deleted file mode 100644 index fb51a3cea..000000000 --- a/broadcaster/sequencenumbercatchupbuffer.go +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE - -package broadcaster - -import ( - "errors" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - - "github.com/offchainlabs/nitro/arbutil" - m "github.com/offchainlabs/nitro/broadcaster/message" - "github.com/offchainlabs/nitro/wsbroadcastserver" -) - -const ( - // Do not send cache if requested seqnum is older than last cached minus maxRequestedSeqNumOffset - maxRequestedSeqNumOffset = arbutil.MessageIndex(10_000) -) - -var ( - confirmedSequenceNumberGauge = metrics.NewRegisteredGauge("arb/sequencenumber/confirmed", nil) - cachedMessagesSentHistogram = metrics.NewRegisteredHistogram("arb/feed/clients/cache/sent", nil, metrics.NewBoundedHistogramSample()) -) - -type SequenceNumberCatchupBuffer struct { - messages []*m.BroadcastFeedMessage - messageCount int32 - limitCatchup func() bool - maxCatchup func() int -} - -func NewSequenceNumberCatchupBuffer(limitCatchup func() bool, maxCatchup func() int) *SequenceNumberCatchupBuffer { - return &SequenceNumberCatchupBuffer{ - limitCatchup: limitCatchup, - maxCatchup: maxCatchup, - } -} - -func (b *SequenceNumberCatchupBuffer) getCacheMessages(requestedSeqNum arbutil.MessageIndex) *m.BroadcastMessage { - if len(b.messages) == 0 { - return nil - } - var startingIndex int32 - // Ignore messages older than requested sequence number - firstCachedSeqNum := b.messages[0].SequenceNumber - if firstCachedSeqNum < requestedSeqNum { - lastCachedSeqNum := firstCachedSeqNum + arbutil.MessageIndex(len(b.messages)-1) - if lastCachedSeqNum < requestedSeqNum { - // Past end, nothing to return - return nil - } - startingIndex = int32(requestedSeqNum - firstCachedSeqNum) - if startingIndex >= int32(len(b.messages)) { - log.Error("unexpected startingIndex", "requestedSeqNum", requestedSeqNum, "firstCachedSeqNum", firstCachedSeqNum, "startingIndex", startingIndex, "lastCachedSeqNum", lastCachedSeqNum, "cacheLength", len(b.messages)) - return nil - } - if b.messages[startingIndex].SequenceNumber != requestedSeqNum { - log.Error("requestedSeqNum not found where expected", "requestedSeqNum", requestedSeqNum, "firstCachedSeqNum", firstCachedSeqNum, "startingIndex", startingIndex, "foundSeqNum", b.messages[startingIndex].SequenceNumber) - return nil - } - } else if b.limitCatchup() && firstCachedSeqNum > maxRequestedSeqNumOffset && requestedSeqNum < (firstCachedSeqNum-maxRequestedSeqNumOffset) { - // Requested seqnum is too old, don't send any cache - return nil - } - - messagesToSend := b.messages[startingIndex:] - if len(messagesToSend) > 0 { - bm := m.BroadcastMessage{ - Version: 1, - Messages: messagesToSend, - } - - return &bm - } - - return nil -} - -func (b *SequenceNumberCatchupBuffer) OnRegisterClient(clientConnection *wsbroadcastserver.ClientConnection) (error, int, time.Duration) { - start := time.Now() - bm := b.getCacheMessages(clientConnection.RequestedSeqNum()) - var bmCount int - if bm != nil { - bmCount = len(bm.Messages) - } - if bm != nil { - // send the newly connected client the requested messages - err := clientConnection.Write(bm) - if err != nil { - log.Error("error sending client cached messages", "error", err, "client", clientConnection.Name, "elapsed", time.Since(start)) - return err, 0, 0 - } - } - - cachedMessagesSentHistogram.Update(int64(bmCount)) - - return nil, bmCount, time.Since(start) -} - -// Takes as input an index into the messages array, not a message index -func (b *SequenceNumberCatchupBuffer) pruneBufferToIndex(idx int) { - b.messages = b.messages[idx:] - if len(b.messages) > 10 && cap(b.messages) > len(b.messages)*10 { - // Too much spare capacity, copy to fresh slice to reset memory usage - b.messages = append([]*m.BroadcastFeedMessage(nil), b.messages[:len(b.messages)]...) - } -} - -func (b *SequenceNumberCatchupBuffer) deleteConfirmed(confirmedSequenceNumber arbutil.MessageIndex) { - if len(b.messages) == 0 { - return - } - - firstSequenceNumber := b.messages[0].SequenceNumber - - if confirmedSequenceNumber < firstSequenceNumber { - // Confirmed sequence number is older than cache, so nothing to do - return - } - - confirmedIndex := uint64(confirmedSequenceNumber - firstSequenceNumber) - - if confirmedIndex >= uint64(len(b.messages)) { - log.Error("ConfirmedSequenceNumber is past the end of stored messages", "confirmedSequenceNumber", confirmedSequenceNumber, "firstSequenceNumber", firstSequenceNumber, "cacheLength", len(b.messages)) - b.messages = nil - return - } - - if b.messages[confirmedIndex].SequenceNumber != confirmedSequenceNumber { - // Log instead of returning error here so that the message will be sent to downstream - // relays to also cause them to be cleared. - log.Error("Invariant violation: confirmedSequenceNumber is not where expected, clearing buffer", "confirmedSequenceNumber", confirmedSequenceNumber, "firstSequenceNumber", firstSequenceNumber, "cacheLength", len(b.messages), "foundSequenceNumber", b.messages[confirmedIndex].SequenceNumber) - b.messages = nil - return - } - - b.pruneBufferToIndex(int(confirmedIndex) + 1) -} - -func (b *SequenceNumberCatchupBuffer) OnDoBroadcast(bmi interface{}) error { - broadcastMessage, ok := bmi.(m.BroadcastMessage) - if !ok { - msg := "requested to broadcast message of unknown type" - log.Error(msg) - return errors.New(msg) - } - defer func() { atomic.StoreInt32(&b.messageCount, int32(len(b.messages))) }() - - if confirmMsg := broadcastMessage.ConfirmedSequenceNumberMessage; confirmMsg != nil { - b.deleteConfirmed(confirmMsg.SequenceNumber) - confirmedSequenceNumberGauge.Update(int64(confirmMsg.SequenceNumber)) - } - - maxCatchup := b.maxCatchup() - if maxCatchup == 0 { - b.messages = nil - return nil - } - - for _, newMsg := range broadcastMessage.Messages { - if len(b.messages) == 0 { - // Add to empty list - b.messages = append(b.messages, newMsg) - } else if expectedSequenceNumber := b.messages[len(b.messages)-1].SequenceNumber + 1; newMsg.SequenceNumber == expectedSequenceNumber { - // Next sequence number to add to end of list - b.messages = append(b.messages, newMsg) - } else if newMsg.SequenceNumber > expectedSequenceNumber { - log.Warn( - "Message requested to be broadcast has unexpected sequence number; discarding to seqNum from catchup buffer", - "seqNum", newMsg.SequenceNumber, - "expectedSeqNum", expectedSequenceNumber, - ) - b.messages = nil - b.messages = append(b.messages, newMsg) - } else { - log.Info("Skipping already seen message", "seqNum", newMsg.SequenceNumber) - } - } - - if maxCatchup >= 0 && len(b.messages) > maxCatchup { - b.pruneBufferToIndex(len(b.messages) - maxCatchup) - } - - return nil - -} - -func (b *SequenceNumberCatchupBuffer) GetMessageCount() int { - return int(atomic.LoadInt32(&b.messageCount)) -} diff --git a/broadcaster/sequencenumbercatchupbuffer_test.go b/broadcaster/sequencenumbercatchupbuffer_test.go deleted file mode 100644 index 80e1efe5c..000000000 --- a/broadcaster/sequencenumbercatchupbuffer_test.go +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright 2020-2021, Offchain Labs, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package broadcaster - -import ( - "strings" - "testing" - - "github.com/offchainlabs/nitro/arbutil" - m "github.com/offchainlabs/nitro/broadcaster/message" - "github.com/offchainlabs/nitro/util/arbmath" -) - -func TestGetEmptyCacheMessages(t *testing.T) { - buffer := SequenceNumberCatchupBuffer{ - messages: nil, - messageCount: 0, - limitCatchup: func() bool { return false }, - maxCatchup: func() int { return -1 }, - } - - // Get everything - bm := buffer.getCacheMessages(0) - if bm != nil { - t.Error("shouldn't have returned anything") - } -} - -func TestGetCacheMessages(t *testing.T) { - indexes := []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46} - buffer := SequenceNumberCatchupBuffer{ - messages: m.CreateDummyBroadcastMessages(indexes), - messageCount: int32(len(indexes)), - limitCatchup: func() bool { return false }, - maxCatchup: func() int { return -1 }, - } - - // Get everything - bm := buffer.getCacheMessages(0) - if len(bm.Messages) != 7 { - t.Error("didn't return all messages") - } - - // Get everything - bm = buffer.getCacheMessages(1) - if len(bm.Messages) != 7 { - t.Error("didn't return all messages") - } - - // Get everything - bm = buffer.getCacheMessages(40) - if len(bm.Messages) != 7 { - t.Error("didn't return all messages") - } - - // Get nothing - bm = buffer.getCacheMessages(100) - if bm != nil { - t.Error("should not have returned anything") - } - - // Test single - bm = buffer.getCacheMessages(46) - if bm == nil { - t.Fatal("nothing returned") - } - if len(bm.Messages) != 1 { - t.Errorf("expected 1 message, got %d messages", len(bm.Messages)) - } - if bm.Messages[0].SequenceNumber != 46 { - t.Errorf("expected sequence number 46, got %d", bm.Messages[0].SequenceNumber) - } - - // Test extremes - bm = buffer.getCacheMessages(arbutil.MessageIndex(^uint64(0))) - if bm != nil { - t.Fatal("should not have returned anything") - } -} - -func TestDeleteConfirmedNil(t *testing.T) { - buffer := SequenceNumberCatchupBuffer{ - messages: nil, - messageCount: 0, - limitCatchup: func() bool { return false }, - maxCatchup: func() int { return -1 }, - } - - buffer.deleteConfirmed(0) - if len(buffer.messages) != 0 { - t.Error("nothing should be present") - } -} - -func TestDeleteConfirmInvalidOrder(t *testing.T) { - indexes := []arbutil.MessageIndex{40, 42} - buffer := SequenceNumberCatchupBuffer{ - messages: m.CreateDummyBroadcastMessages(indexes), - messageCount: int32(len(indexes)), - limitCatchup: func() bool { return false }, - maxCatchup: func() int { return -1 }, - } - - // Confirm before cache - buffer.deleteConfirmed(41) - if len(buffer.messages) != 0 { - t.Error("cache not in contiguous order should have caused everything to be deleted") - } -} - -func TestDeleteConfirmed(t *testing.T) { - indexes := []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46} - buffer := SequenceNumberCatchupBuffer{ - messages: m.CreateDummyBroadcastMessages(indexes), - messageCount: int32(len(indexes)), - limitCatchup: func() bool { return false }, - maxCatchup: func() int { return -1 }, - } - - // Confirm older than cache - buffer.deleteConfirmed(39) - if len(buffer.messages) != 7 { - t.Error("nothing should have been deleted") - } - -} -func TestDeleteFreeMem(t *testing.T) { - indexes := []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51} - buffer := SequenceNumberCatchupBuffer{ - messages: m.CreateDummyBroadcastMessagesImpl(indexes, len(indexes)*10+1), - messageCount: int32(len(indexes)), - limitCatchup: func() bool { return false }, - maxCatchup: func() int { return -1 }, - } - - // Confirm older than cache - buffer.deleteConfirmed(40) - if cap(buffer.messages) > 20 { - t.Error("extra memory was not freed, cap: ", cap(buffer.messages)) - } - -} - -func TestBroadcastBadMessage(t *testing.T) { - buffer := SequenceNumberCatchupBuffer{ - messages: nil, - messageCount: 0, - limitCatchup: func() bool { return false }, - maxCatchup: func() int { return -1 }, - } - - var foo int - err := buffer.OnDoBroadcast(foo) - if err == nil { - t.Error("expected error") - } - if !strings.Contains(err.Error(), "unknown type") { - t.Error("unexpected type") - } -} - -func TestBroadcastPastSeqNum(t *testing.T) { - indexes := []arbutil.MessageIndex{40} - buffer := SequenceNumberCatchupBuffer{ - messages: m.CreateDummyBroadcastMessagesImpl(indexes, len(indexes)*10+1), - messageCount: int32(len(indexes)), - limitCatchup: func() bool { return false }, - maxCatchup: func() int { return -1 }, - } - - bm := m.BroadcastMessage{ - Messages: []*m.BroadcastFeedMessage{ - { - SequenceNumber: 39, - }, - }, - } - err := buffer.OnDoBroadcast(bm) - if err != nil { - t.Error("expected error") - } - -} - -func TestBroadcastFutureSeqNum(t *testing.T) { - indexes := []arbutil.MessageIndex{40} - buffer := SequenceNumberCatchupBuffer{ - messages: m.CreateDummyBroadcastMessagesImpl(indexes, len(indexes)*10+1), - messageCount: int32(len(indexes)), - limitCatchup: func() bool { return false }, - maxCatchup: func() int { return -1 }, - } - - bm := m.BroadcastMessage{ - Messages: []*m.BroadcastFeedMessage{ - { - SequenceNumber: 42, - }, - }, - } - err := buffer.OnDoBroadcast(bm) - if err != nil { - t.Error("expected error") - } - -} - -func TestMaxCatchupBufferSize(t *testing.T) { - limit := 5 - buffer := SequenceNumberCatchupBuffer{ - messages: nil, - messageCount: 0, - limitCatchup: func() bool { return false }, - maxCatchup: func() int { return limit }, - } - - firstMessage := 10 - for i := firstMessage; i <= 20; i += 2 { - bm := m.BroadcastMessage{ - Messages: []*m.BroadcastFeedMessage{ - { - SequenceNumber: arbutil.MessageIndex(i), - }, - { - SequenceNumber: arbutil.MessageIndex(i + 1), - }, - }, - } - err := buffer.OnDoBroadcast(bm) - Require(t, err) - haveMessages := buffer.getCacheMessages(0) - expectedCount := arbmath.MinInt(i+len(bm.Messages)-firstMessage, limit) - if len(haveMessages.Messages) != expectedCount { - t.Errorf("after broadcasting messages %v and %v, expected to have %v messages but got %v", i, i+1, expectedCount, len(haveMessages.Messages)) - } - expectedFirstMessage := arbutil.MessageIndex(arbmath.MaxInt(firstMessage, i+len(bm.Messages)-limit)) - if haveMessages.Messages[0].SequenceNumber != expectedFirstMessage { - t.Errorf("after broadcasting messages %v and %v, expected the first message to be %v but got %v", i, i+1, expectedFirstMessage, haveMessages.Messages[0].SequenceNumber) - } - } -} diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 907108b6b..e4452f8f1 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -26,6 +26,11 @@ import ( var errContextDone = errors.New("context done") +type message struct { + data []byte + sequenceNumber arbutil.MessageIndex +} + // ClientConnection represents client connection. type ClientConnection struct { stopwaiter.StopWaiter @@ -39,11 +44,13 @@ type ClientConnection struct { Name string clientManager *ClientManager requestedSeqNum arbutil.MessageIndex + LastSentSeqNum atomic.Uint64 lastHeardUnix int64 - out chan []byte + out chan message backlog backlog.Backlog registered chan bool + backlogSent bool compression bool flateReader *wsflate.Reader @@ -70,12 +77,13 @@ func NewClientConnection( clientManager: clientManager, requestedSeqNum: requestedSeqNum, lastHeardUnix: time.Now().Unix(), - out: make(chan []byte, clientManager.config().MaxSendQueue), + out: make(chan message, clientManager.config().MaxSendQueue), compression: compression, flateReader: NewFlateReader(), delay: delay, backlog: bklg, registered: make(chan bool, 1), + backlogSent: false, } } @@ -87,41 +95,57 @@ func (cc *ClientConnection) Compression() bool { return cc.compression } -func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.BacklogSegment) (backlog.BacklogSegment, error) { +func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.BacklogSegment) error { var prevSegment backlog.BacklogSegment for !backlog.IsBacklogSegmentNil(segment) { + // must get the next segment before the messages to be sent are + // retrieved ensures another segment is not added in between calls. + prevSegment = segment + segment = segment.Next() + select { case <-ctx.Done(): - return nil, errContextDone + return errContextDone default: } + msgs := prevSegment.Messages() bm := &m.BroadcastMessage{ Version: 1, // TODO(clamb): I am unsure if it is correct to hard code the version here like this? It seems to be done in other places though - Messages: segment.Messages(), + Messages: msgs, } - notCompressed, compressed, err := serializeMessage(cc.clientManager, bm, !cc.compression, cc.compression) + err := cc.writeBroadcastMessage(bm) if err != nil { - return nil, err + return err } - data := []byte{} - if cc.compression { - data = compressed.Bytes() - } else { - data = notCompressed.Bytes() - } - err = cc.writeRaw(data) - if err != nil { - return nil, err - } - log.Debug("segment sent to client", "client", cc.Name, "sentCount", len(bm.Messages)) + // do not use prevSegment.End() method, must figure out the last + // sequence number from the messages that were actually sent in case + // more messages are added. + end := uint64(msgs[len(msgs)-1].SequenceNumber) + cc.LastSentSeqNum.Store(end) + log.Debug("segment sent to client", "client", cc.Name, "sentCount", len(bm.Messages), "lastSentSeqNum", end) + } + return nil +} - prevSegment = segment - segment = segment.Next() +func (cc *ClientConnection) writeBroadcastMessage(bm *m.BroadcastMessage) error { + notCompressed, compressed, err := serializeMessage(cc.clientManager, bm, !cc.compression, cc.compression) + if err != nil { + return err } - return prevSegment, nil + data := []byte{} + if cc.compression { + data = compressed.Bytes() + } else { + data = notCompressed.Bytes() + } + err = cc.writeRaw(data) + if err != nil { + return err + } + return nil } func (cc *ClientConnection) Start(parentCtx context.Context) { @@ -147,7 +171,7 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { cc.clientManager.Remove(cc) return } - segment, err = cc.writeBacklog(ctx, segment) + err = cc.writeBacklog(ctx, segment) if errors.Is(err, errContextDone) { return } else if err != nil { @@ -167,29 +191,32 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { log.Error("timed out waiting for ClientConnection to register with ClientManager", "client", cc.Name) } - // The backlog may have had more messages added to it whilst the - // ClientConnection registers with the ClientManager, therefore the - // last segment must be sent again. This may result in duplicate - // messages being sent to the client but the client should handle any - // duplicate messages. The ClientConnection can not be registered - // before the backlog is sent as the backlog may be very large. This - // could result in the out channel running out of space. - _, err = cc.writeBacklog(ctx, segment) - if errors.Is(err, errContextDone) { - return - } else if err != nil { - logWarn(err, "error writing messages from backlog") - cc.clientManager.Remove(cc) - return - } - // broadcast any new messages sent to the out channel for { select { case <-ctx.Done(): return - case data := <-cc.out: - err := cc.writeRaw(data) + case msg := <-cc.out: + expSeqNum := cc.LastSentSeqNum.Load() + 1 + if !cc.backlogSent && uint64(msg.sequenceNumber) > expSeqNum { + catchupSeqNum := uint64(msg.sequenceNumber) - 1 + bm, err := cc.backlog.Get(expSeqNum, catchupSeqNum) + if err != nil { + logWarn(err, fmt.Sprintf("error reading messages %d to %d from backlog", expSeqNum, catchupSeqNum)) + cc.clientManager.Remove(cc) + return + } + + err = cc.writeBroadcastMessage(bm) + if err != nil { + logWarn(err, fmt.Sprintf("error writing messages %d to %d from backlog", expSeqNum, catchupSeqNum)) + cc.clientManager.Remove(cc) + return + } + } + cc.backlogSent = true + + err := cc.writeRaw(msg.data) if err != nil { logWarn(err, "error writing data to client") cc.clientManager.Remove(cc) @@ -248,23 +275,6 @@ func (cc *ClientConnection) readRequest(ctx context.Context, timeout time.Durati return data, opCode, err } -func (cc *ClientConnection) Write(bm *m.BroadcastMessage) error { - cc.ioMutex.Lock() - defer cc.ioMutex.Unlock() - - notCompressed, compressed, err := serializeMessage(cc.clientManager, bm, !cc.compression, cc.compression) - if err != nil { - return err - } - - if cc.compression { - cc.out <- compressed.Bytes() - } else { - cc.out <- notCompressed.Bytes() - } - return nil -} - func (cc *ClientConnection) writeRaw(p []byte) error { cc.ioMutex.Lock() defer cc.ioMutex.Unlock() diff --git a/wsbroadcastserver/clientmanager.go b/wsbroadcastserver/clientmanager.go index b2790f850..589f9ca67 100644 --- a/wsbroadcastserver/clientmanager.go +++ b/wsbroadcastserver/clientmanager.go @@ -172,7 +172,11 @@ func (cm *ClientManager) Broadcast(bm *m.BroadcastMessage) { cm.broadcastChan <- bm } -func (cm *ClientManager) doBroadcast(bm *m.BroadcastMessage) ([]*ClientConnection, error) { +func (cm *ClientManager) doBroadcast(bfm *m.BroadcastFeedMessage) ([]*ClientConnection, error) { + bm := &m.BroadcastMessage{ + Version: 1, + Messages: []*m.BroadcastFeedMessage{bfm}, + } if err := cm.backlog.Append(bm); err != nil { return nil, err } @@ -207,8 +211,18 @@ func (cm *ClientManager) doBroadcast(bm *m.BroadcastMessage) ([]*ClientConnectio continue } } + + if uint64(bfm.SequenceNumber) <= client.LastSentSeqNum.Load() { + log.Warn("client has already sent message with this sequence number, skipping the message", "client", client.Name, "sequence number", bfm.SequenceNumber) + continue + } + + m := message{ + sequenceNumber: bfm.SequenceNumber, + data: data, + } select { - case client.out <- data: + case client.out <- m: default: // Queue for client too backed up, disconnect instead of blocking on channel send sendQueueTooLargeCount++ @@ -327,8 +341,10 @@ func (cm *ClientManager) Start(parentCtx context.Context) { } case bm := <-cm.broadcastChan: var err error - clientDeleteList, err = cm.doBroadcast(bm) - logError(err, "failed to do broadcast") + for _, msg := range bm.Messages { + clientDeleteList, err = cm.doBroadcast(msg) + logError(err, "failed to do broadcast") + } case <-pingTimer.C: clientDeleteList = cm.verifyClients() pingTimer.Reset(cm.config().Ping) From 1858770edb48210c729af1866e88b4c2225cb15a Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:37:25 +1300 Subject: [PATCH 379/775] fix BroadcastClient test TestBroadcastClientConfirmedMessage --- wsbroadcastserver/clientconnection.go | 6 ++--- wsbroadcastserver/clientmanager.go | 35 ++++++++++++++++++++------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index e4452f8f1..94845bde9 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -28,7 +28,7 @@ var errContextDone = errors.New("context done") type message struct { data []byte - sequenceNumber arbutil.MessageIndex + sequenceNumber *arbutil.MessageIndex } // ClientConnection represents client connection. @@ -198,8 +198,8 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { return case msg := <-cc.out: expSeqNum := cc.LastSentSeqNum.Load() + 1 - if !cc.backlogSent && uint64(msg.sequenceNumber) > expSeqNum { - catchupSeqNum := uint64(msg.sequenceNumber) - 1 + if !cc.backlogSent && msg.sequenceNumber != nil && uint64(*msg.sequenceNumber) > expSeqNum { + catchupSeqNum := uint64(*msg.sequenceNumber) - 1 bm, err := cc.backlog.Get(expSeqNum, catchupSeqNum) if err != nil { logWarn(err, fmt.Sprintf("error reading messages %d to %d from backlog", expSeqNum, catchupSeqNum)) diff --git a/wsbroadcastserver/clientmanager.go b/wsbroadcastserver/clientmanager.go index 589f9ca67..614e1ba14 100644 --- a/wsbroadcastserver/clientmanager.go +++ b/wsbroadcastserver/clientmanager.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" + "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcaster/backlog" m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/util/stopwaiter" @@ -172,11 +173,7 @@ func (cm *ClientManager) Broadcast(bm *m.BroadcastMessage) { cm.broadcastChan <- bm } -func (cm *ClientManager) doBroadcast(bfm *m.BroadcastFeedMessage) ([]*ClientConnection, error) { - bm := &m.BroadcastMessage{ - Version: 1, - Messages: []*m.BroadcastFeedMessage{bfm}, - } +func (cm *ClientManager) doBroadcast(bm *m.BroadcastMessage) ([]*ClientConnection, error) { if err := cm.backlog.Append(bm); err != nil { return nil, err } @@ -212,13 +209,23 @@ func (cm *ClientManager) doBroadcast(bfm *m.BroadcastFeedMessage) ([]*ClientConn } } - if uint64(bfm.SequenceNumber) <= client.LastSentSeqNum.Load() { - log.Warn("client has already sent message with this sequence number, skipping the message", "client", client.Name, "sequence number", bfm.SequenceNumber) + var seqNum *arbutil.MessageIndex + n := len(bm.Messages) + if n == 0 { + seqNum = nil + } else if n == 1 { + seqNum = &bm.Messages[0].SequenceNumber + } else { + return nil, fmt.Errorf("doBroadcast was sent %d BroadcastFeedMessages, it can only parse 1 BroadcastFeedMessage at a time", n) + } + + if seqNum != nil && uint64(*seqNum) <= client.LastSentSeqNum.Load() { + log.Warn("client has already sent message with this sequence number, skipping the message", "client", client.Name, "sequence number", *seqNum) continue } m := message{ - sequenceNumber: bfm.SequenceNumber, + sequenceNumber: seqNum, data: data, } select { @@ -342,7 +349,17 @@ func (cm *ClientManager) Start(parentCtx context.Context) { case bm := <-cm.broadcastChan: var err error for _, msg := range bm.Messages { - clientDeleteList, err = cm.doBroadcast(msg) + m := &m.BroadcastMessage{ + Version: bm.Version, + Messages: []*m.BroadcastFeedMessage{msg}, + ConfirmedSequenceNumberMessage: bm.ConfirmedSequenceNumberMessage, + } + clientDeleteList, err = cm.doBroadcast(m) + logError(err, "failed to do broadcast") + } + + if len(bm.Messages) == 0 { + clientDeleteList, err = cm.doBroadcast(bm) logError(err, "failed to do broadcast") } case <-pingTimer.C: From 66357cf75c976f397955f0737b002c11664f0ae7 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Fri, 10 Nov 2023 17:26:47 +1300 Subject: [PATCH 380/775] move flateWriter to serializeMessage to avoid race condition --- wsbroadcastserver/clientconnection.go | 2 +- wsbroadcastserver/clientmanager.go | 25 +++++++++++-------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 94845bde9..b29e653d8 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -130,7 +130,7 @@ func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.Ba } func (cc *ClientConnection) writeBroadcastMessage(bm *m.BroadcastMessage) error { - notCompressed, compressed, err := serializeMessage(cc.clientManager, bm, !cc.compression, cc.compression) + notCompressed, compressed, err := serializeMessage(bm, !cc.compression, cc.compression) if err != nil { return err } diff --git a/wsbroadcastserver/clientmanager.go b/wsbroadcastserver/clientmanager.go index 614e1ba14..21c4f131f 100644 --- a/wsbroadcastserver/clientmanager.go +++ b/wsbroadcastserver/clientmanager.go @@ -52,7 +52,6 @@ type ClientManager struct { clientAction chan ClientConnectionAction config BroadcasterConfigFetcher backlog backlog.Backlog - flateWriter *flate.Writer connectionLimiter *ConnectionLimiter } @@ -180,9 +179,9 @@ func (cm *ClientManager) doBroadcast(bm *m.BroadcastMessage) ([]*ClientConnectio config := cm.config() // /-> wsutil.Writer -> not compressed msg buffer // bm -> json.Encoder -> io.MultiWriter -| - // \-> cm.flateWriter -> wsutil.Writer -> compressed msg buffer + // \-> flateWriter -> wsutil.Writer -> compressed msg buffer - notCompressed, compressed, err := serializeMessage(cm, bm, !config.RequireCompression, config.EnableCompression) + notCompressed, compressed, err := serializeMessage(bm, !config.RequireCompression, config.EnableCompression) if err != nil { return nil, err } @@ -248,7 +247,12 @@ func (cm *ClientManager) doBroadcast(bm *m.BroadcastMessage) ([]*ClientConnectio return clientDeleteList, nil } -func serializeMessage(cm *ClientManager, bm *m.BroadcastMessage, enableNonCompressedOutput, enableCompressedOutput bool) (bytes.Buffer, bytes.Buffer, error) { +func serializeMessage(bm *m.BroadcastMessage, enableNonCompressedOutput, enableCompressedOutput bool) (bytes.Buffer, bytes.Buffer, error) { + flateWriter, err := flate.NewWriterDict(nil, DeflateCompressionLevel, GetStaticCompressorDictionary()) + if err != nil { + return bytes.Buffer{}, bytes.Buffer{}, fmt.Errorf("unable to create flate writer: %w", err) + } + var notCompressed bytes.Buffer var compressed bytes.Buffer writers := []io.Writer{} @@ -259,19 +263,12 @@ func serializeMessage(cm *ClientManager, bm *m.BroadcastMessage, enableNonCompre writers = append(writers, notCompressedWriter) } if enableCompressedOutput { - if cm.flateWriter == nil { - var err error - cm.flateWriter, err = flate.NewWriterDict(nil, DeflateCompressionLevel, GetStaticCompressorDictionary()) - if err != nil { - return bytes.Buffer{}, bytes.Buffer{}, fmt.Errorf("unable to create flate writer: %w", err) - } - } compressedWriter = wsutil.NewWriter(&compressed, ws.StateServerSide|ws.StateExtended, ws.OpText) var msg wsflate.MessageState msg.SetCompressed(true) compressedWriter.SetExtensions(&msg) - cm.flateWriter.Reset(compressedWriter) - writers = append(writers, cm.flateWriter) + flateWriter.Reset(compressedWriter) + writers = append(writers, flateWriter) } multiWriter := io.MultiWriter(writers...) @@ -285,7 +282,7 @@ func serializeMessage(cm *ClientManager, bm *m.BroadcastMessage, enableNonCompre } } if compressedWriter != nil { - if err := cm.flateWriter.Close(); err != nil { + if err := flateWriter.Close(); err != nil { return bytes.Buffer{}, bytes.Buffer{}, fmt.Errorf("unable to close flate writer: %w", err) } if err := compressedWriter.Flush(); err != nil { From b046b8fced847fa7490dacc82ba8e0b5eca5065b Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Tue, 14 Nov 2023 14:49:42 +1300 Subject: [PATCH 381/775] refactor ClientConnection to stop relying on ClientManager - CM will pass down the required channel to communicate with each CC --- wsbroadcastserver/clientconnection.go | 42 ++++++++++++++++++++------ wsbroadcastserver/clientmanager.go | 20 ------------ wsbroadcastserver/wsbroadcastserver.go | 6 ++-- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index b29e653d8..6b4c33b8f 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -31,6 +31,11 @@ type message struct { sequenceNumber *arbutil.MessageIndex } +type ClientConnectionAction struct { + cc *ClientConnection + create bool +} + // ClientConnection represents client connection. type ClientConnection struct { stopwaiter.StopWaiter @@ -42,7 +47,7 @@ type ClientConnection struct { desc *netpoll.Desc Name string - clientManager *ClientManager + clientAction chan ClientConnectionAction requestedSeqNum arbutil.MessageIndex LastSentSeqNum atomic.Uint64 @@ -61,10 +66,11 @@ type ClientConnection struct { func NewClientConnection( conn net.Conn, desc *netpoll.Desc, - clientManager *ClientManager, + clientAction chan ClientConnectionAction, requestedSeqNum arbutil.MessageIndex, connectingIP net.IP, compression bool, + maxSendQueue int, delay time.Duration, bklg backlog.Backlog, ) *ClientConnection { @@ -74,10 +80,10 @@ func NewClientConnection( desc: desc, creation: time.Now(), Name: fmt.Sprintf("%s@%s-%d", connectingIP, conn.RemoteAddr(), rand.Intn(10)), - clientManager: clientManager, + clientAction: clientAction, requestedSeqNum: requestedSeqNum, lastHeardUnix: time.Now().Unix(), - out: make(chan message, clientManager.config().MaxSendQueue), + out: make(chan message, maxSendQueue), compression: compression, flateReader: NewFlateReader(), delay: delay, @@ -95,6 +101,22 @@ func (cc *ClientConnection) Compression() bool { return cc.compression } +// Register sends the ClientConnection to be registered with the ClientManager. +func (cc *ClientConnection) Register() { + cc.clientAction <- ClientConnectionAction{ + cc: cc, + create: true, + } +} + +// Remove sends the ClientConnection to be removed from the ClientManager. +func (cc *ClientConnection) Remove() { + cc.clientAction <- ClientConnectionAction{ + cc: cc, + create: false, + } +} + func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.BacklogSegment) error { var prevSegment backlog.BacklogSegment for !backlog.IsBacklogSegmentNil(segment) { @@ -168,7 +190,7 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { segment, err := cc.backlog.Lookup(uint64(cc.requestedSeqNum)) if err != nil { logWarn(err, "error finding requested sequence number in backlog") - cc.clientManager.Remove(cc) + cc.Remove() return } err = cc.writeBacklog(ctx, segment) @@ -176,11 +198,11 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { return } else if err != nil { logWarn(err, "error writing messages from backlog") - cc.clientManager.Remove(cc) + cc.Remove() return } - cc.clientManager.Register(cc) + cc.Register() timer := time.NewTimer(5 * time.Second) select { case <-ctx.Done(): @@ -203,14 +225,14 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { bm, err := cc.backlog.Get(expSeqNum, catchupSeqNum) if err != nil { logWarn(err, fmt.Sprintf("error reading messages %d to %d from backlog", expSeqNum, catchupSeqNum)) - cc.clientManager.Remove(cc) + cc.Remove() return } err = cc.writeBroadcastMessage(bm) if err != nil { logWarn(err, fmt.Sprintf("error writing messages %d to %d from backlog", expSeqNum, catchupSeqNum)) - cc.clientManager.Remove(cc) + cc.Remove() return } } @@ -219,7 +241,7 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { err := cc.writeRaw(msg.data) if err != nil { logWarn(err, "error writing data to client") - cc.clientManager.Remove(cc) + cc.Remove() return } } diff --git a/wsbroadcastserver/clientmanager.go b/wsbroadcastserver/clientmanager.go index 21c4f131f..683d652c2 100644 --- a/wsbroadcastserver/clientmanager.go +++ b/wsbroadcastserver/clientmanager.go @@ -56,11 +56,6 @@ type ClientManager struct { connectionLimiter *ConnectionLimiter } -type ClientConnectionAction struct { - cc *ClientConnection - create bool -} - func NewClientManager(poller netpoll.Poller, configFetcher BroadcasterConfigFetcher, bklg backlog.Backlog) *ClientManager { config := configFetcher() return &ClientManager{ @@ -98,14 +93,6 @@ func (cm *ClientManager) registerClient(ctx context.Context, clientConnection *C return nil } -// Register registers given connection as a Client. -func (cm *ClientManager) Register(clientConnection *ClientConnection) { - cm.clientAction <- ClientConnectionAction{ - clientConnection, - true, - } -} - // removeAll removes all clients after main ClientManager thread exits func (cm *ClientManager) removeAll() { // Only called after main ClientManager thread exits, so remove client directly @@ -150,13 +137,6 @@ func (cm *ClientManager) removeClient(clientConnection *ClientConnection) { delete(cm.clientPtrMap, clientConnection) } -func (cm *ClientManager) Remove(clientConnection *ClientConnection) { - cm.clientAction <- ClientConnectionAction{ - clientConnection, - false, - } -} - func (cm *ClientManager) ClientCount() int32 { return atomic.LoadInt32(&cm.clientCount) } diff --git a/wsbroadcastserver/wsbroadcastserver.go b/wsbroadcastserver/wsbroadcastserver.go index 3a98871fe..eb47f8a63 100644 --- a/wsbroadcastserver/wsbroadcastserver.go +++ b/wsbroadcastserver/wsbroadcastserver.go @@ -378,7 +378,7 @@ func (s *WSBroadcastServer) StartWithHeader(ctx context.Context, header ws.Hands // Register incoming client in clientManager. safeConn := writeDeadliner{conn, config.WriteTimeout} - client := NewClientConnection(safeConn, desc, s.clientManager, requestedSeqNum, connectingIP, compressionAccepted, s.config().ClientDelay, s.backlog) + client := NewClientConnection(safeConn, desc, s.clientManager.clientAction, requestedSeqNum, connectingIP, compressionAccepted, s.config().MaxSendQueue, s.config().ClientDelay, s.backlog) client.Start(ctx) // Subscribe to events about conn. @@ -387,7 +387,7 @@ func (s *WSBroadcastServer) StartWithHeader(ctx context.Context, header ws.Hands // ReadHup or Hup received, means the client has close the connection // remove it from the clientManager registry. log.Debug("Hup received", "age", client.Age(), "client", client.Name) - s.clientManager.Remove(client) + client.Remove() return } @@ -399,7 +399,7 @@ func (s *WSBroadcastServer) StartWithHeader(ctx context.Context, header ws.Hands s.clientManager.pool.Schedule(func() { // Ignore any messages sent from client, close on any error if _, _, err := client.Receive(ctx, s.config().ReadTimeout); err != nil { - s.clientManager.Remove(client) + client.Remove() return } }) From 7cf1b2b4d49929d284dac975441f61f1522cbc04 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Tue, 14 Nov 2023 14:50:26 +1300 Subject: [PATCH 382/775] refactor backlog to allow deletion of all confirmed messages from segments --- broadcaster/backlog/backlog.go | 83 ++++++++++++++++++----------- broadcaster/backlog/backlog_test.go | 48 ++++++++++++----- broadcaster/broadcaster_test.go | 14 ++--- 3 files changed, 94 insertions(+), 51 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 57b481007..de786bd32 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -132,8 +132,10 @@ func (b *backlog) Get(start, end uint64) (*m.BroadcastMessage, error) { return bm, nil } -// delete removes segments before the confirmed sequence number given. It will -// not remove the segment containing the confirmed sequence number. +// delete removes segments before the confirmed sequence number given. The +// segment containing the confirmed sequence number will continue to store +// previous messages but will register that messages up to the given number +// have been deleted. func (b *backlog) delete(confirmed uint64) { head := b.head.Load() tail := b.tail.Load() @@ -148,36 +150,38 @@ func (b *backlog) delete(confirmed uint64) { if confirmed > tail.End() { log.Error("confirmed sequence number is past the end of stored messages", "confirmed sequence number", confirmed, "last stored sequence number", tail.end.Load()) b.reset() - // should this be returning an error? The other buffer does not and just continues return } // find the segment containing the confirmed message - segment, err := b.Lookup(confirmed) + found, err := b.Lookup(confirmed) if err != nil { log.Error(fmt.Sprintf("%s: clearing backlog", err.Error())) b.reset() - // should this be returning an error? The other buffer does not and just continues return } - - // check the segment actually contains that message - if found := segment.Contains(confirmed); !found { - log.Error("error message not found in backlog segment, clearing backlog", "confirmed sequence number", confirmed) - b.reset() - // should this be returning an error? The other buffer does not and just continues - return + segment := found.(*backlogSegment) + + // delete messages from the segment with the confirmed message + newHead := segment + start := head.Start() + if segment.End() == confirmed { + found = segment.Next() + newHead = found.(*backlogSegment) + } else { + err = segment.Delete(confirmed) + if err != nil { + log.Error(fmt.Sprintf("%s: clearing backlog", err.Error())) + b.reset() + return + } } - // remove all previous segments - previous := segment.Previous() - if IsBacklogSegmentNil(previous) { - return - } - b.removeFromLookup(head.Start(), previous.End()) - b.head.Store(segment.(*backlogSegment)) - count := b.Count() + head.Start() - previous.End() - uint64(1) + // tidy up lookup, count and head + b.removeFromLookup(start, confirmed) + count := b.Count() + start - confirmed - uint64(1) b.messageCount.Store(count) + b.head.Store(newHead) } // removeFromLookup removes all entries from the head segment's start index to @@ -185,7 +189,7 @@ func (b *backlog) delete(confirmed uint64) { func (b *backlog) removeFromLookup(start, end uint64) { b.lookupLock.Lock() defer b.lookupLock.Unlock() - for i := start; i == end; i++ { + for i := start; i <= end; i++ { delete(b.lookupByIndex, i) } } @@ -218,16 +222,16 @@ func (b *backlog) reset() { type BacklogSegment interface { Start() uint64 End() uint64 - Contains(uint64) bool Next() BacklogSegment - Previous() BacklogSegment Get(uint64, uint64) ([]*m.BroadcastFeedMessage, error) Messages() []*m.BroadcastFeedMessage + Delete(uint64) error } type backlogSegment struct { start atomic.Uint64 end atomic.Uint64 + messagesLock sync.RWMutex messages []*m.BroadcastFeedMessage messageCount atomic.Uint64 nextSegment atomic.Pointer[backlogSegment] @@ -262,11 +266,9 @@ func (s *backlogSegment) Next() BacklogSegment { return s.nextSegment.Load() } -func (s *backlogSegment) Previous() BacklogSegment { - return s.previousSegment.Load() -} - func (s *backlogSegment) Messages() []*m.BroadcastFeedMessage { + s.messagesLock.RLock() + defer s.messagesLock.RUnlock() return s.messages } @@ -283,6 +285,9 @@ func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, erro startIndex := start - s.start.Load() endIndex := end - s.start.Load() + 1 + + s.messagesLock.RLock() + defer s.messagesLock.RUnlock() return s.messages[startIndex:endIndex], nil } @@ -292,6 +297,8 @@ func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, erro // message is ahead of the segment's end message append will return // errDropSegments to ensure any messages before the given message are dropped. func (s *backlogSegment) append(prevMsgIdx uint64, msg *m.BroadcastFeedMessage) error { + s.messagesLock.Lock() + defer s.messagesLock.Unlock() seen := false defer s.updateSegment(&seen) @@ -309,14 +316,26 @@ func (s *backlogSegment) append(prevMsgIdx uint64, msg *m.BroadcastFeedMessage) } // Contains confirms whether the segment contains a message with the given sequence number -func (s *backlogSegment) Contains(i uint64) bool { - if i < s.start.Load() || i > s.end.Load() { - return false +func (s *backlogSegment) Delete(confirmed uint64) error { + seen := false + defer s.updateSegment(&seen) + + start := s.start.Load() + end := s.end.Load() + if confirmed < start || confirmed > end { + return fmt.Errorf("confirmed message (%d) is not in current backlog (%d-%d)", confirmed, start, end) } - msgIndex := i - s.start.Load() + msgIndex := confirmed - start + s.messagesLock.Lock() msg := s.messages[msgIndex] - return uint64(msg.SequenceNumber) == i + if uint64(msg.SequenceNumber) != confirmed { + return fmt.Errorf("confirmed message (%d) is not in expected index (%d) in current backlog (%d-%d)", confirmed, msgIndex, start, end) + } + + s.messages = s.messages[msgIndex+1:] + s.messagesLock.Unlock() + return nil } // updateSegment updates the messageCount, start and end indices of the segment diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go index 4a31e6c57..e7b4f5f63 100644 --- a/broadcaster/backlog/backlog_test.go +++ b/broadcaster/backlog/backlog_test.go @@ -31,6 +31,12 @@ func validateBacklog(t *testing.T, b *backlog, count, start, end uint64, lookupK t.Errorf("failed to find message (%d) in lookup", k) } } + + expLen := len(lookupKeys) + actualLen := len(b.lookupByIndex) + if expLen != actualLen { + t.Errorf("expected length of lookupByIndex map (%d) does not equal actual length (%d)", expLen, actualLen) + } } func validateBroadcastMessage(t *testing.T, bm *m.BroadcastMessage, expectedCount int, start, end uint64) { @@ -111,7 +117,7 @@ func TestAppend(t *testing.T) { 3, // Message 44 is non sequential and the first message in a new segment, the previous messages will be dropped from the backlog 44, 46, - []arbutil.MessageIndex{45, 46}, + []arbutil.MessageIndex{44, 45, 46}, }, { "MessageSeenFirstSegmentMessage", @@ -208,22 +214,40 @@ func TestDelete(t *testing.T) { []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, }, { - "MsgInBacklog", + "FirstMsgInBacklog", []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, - 43, // only the first segment will be deleted - 4, - 43, + 40, // this is the first message in the backlog + 6, + 41, 46, - []arbutil.MessageIndex{43, 44, 45, 46}, + []arbutil.MessageIndex{41, 42, 43, 44, 45, 46}, }, { - "MsgInFirstSegmentInBacklog", + "FirstMsgInSegment", []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, - 42, // first segment will not be deleted as confirmed message is there - 7, - 40, + 43, // this is the first message in a middle segment of the backlog + 3, + 44, + 46, + []arbutil.MessageIndex{44, 45, 46}, + }, + { + "MiddleMsgInSegment", + []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + 44, // this is a message in the middle of a middle segment of the backlog + 2, + 45, 46, + []arbutil.MessageIndex{45, 46}, + }, + { + "LastMsgInSegment", []arbutil.MessageIndex{40, 41, 42, 43, 44, 45, 46}, + 45, // this is the last message in a middle segment of the backlog, the whole segment should be deleted along with any segments before it + 1, + 46, + 46, + []arbutil.MessageIndex{46}, }, { "MsgAfterBacklog", @@ -420,7 +444,7 @@ func TestBacklogRaceCondition(t *testing.T) { defer wg.Done() for _, i := range []uint64{40, 43, 47} { b.delete(i) - time.Sleep(5 * time.Millisecond) + time.Sleep(10 * time.Millisecond) } }(t, b) @@ -435,5 +459,5 @@ func TestBacklogRaceCondition(t *testing.T) { } // Messages up to 47 were deleted. However the segment that 47 was in is // kept, which is why the backlog starts at 46. - validateBacklog(t, b, 10, 46, 55, append(indexes, newIndexes...)) + validateBacklog(t, b, 8, 48, 55, newIndexes[1:]) } diff --git a/broadcaster/broadcaster_test.go b/broadcaster/broadcaster_test.go index 884f1de1d..8ac06e970 100644 --- a/broadcaster/broadcaster_test.go +++ b/broadcaster/broadcaster_test.go @@ -84,21 +84,21 @@ func TestBroadcasterMessagesRemovedOnConfirmation(t *testing.T) { waitUntilUpdated(t, expectMessageCount(6, "after 4 messages")) b.Confirm(4) - waitUntilUpdated(t, expectMessageCount(3, - "after 6 messages, 4 cleared by confirm (first backlog segment)")) + waitUntilUpdated(t, expectMessageCount(2, + "after 6 messages, 4 cleared by confirm")) b.Confirm(5) - waitUntilUpdated(t, expectMessageCount(3, - "after 6 messages, 5 cleared by confirm, but segment containing 5th message remains in backlog")) + waitUntilUpdated(t, expectMessageCount(1, + "after 6 messages, 5 cleared by confirm")) b.Confirm(4) - waitUntilUpdated(t, expectMessageCount(3, + waitUntilUpdated(t, expectMessageCount(1, "nothing changed because confirmed sequence number before cache")) b.Confirm(5) Require(t, b.BroadcastSingle(arbostypes.EmptyTestMessageWithMetadata, 7)) - waitUntilUpdated(t, expectMessageCount(4, - "after 7 messages, 4 cleared by confirm, but segment containing 5th message remains in backlog")) + waitUntilUpdated(t, expectMessageCount(2, + "after 7 messages, 5 cleared by confirm")) // Confirm not-yet-seen or already confirmed/cleared sequence numbers twice to force clearing cache b.Confirm(8) From a265e27ac4f7483ef539233b92fb67a23f43f5eb Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:15:53 +1300 Subject: [PATCH 383/775] fix messages in broadcastclients --- broadcastclients/broadcastclients.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index 551dcdb46..5422e38a9 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -12,7 +12,7 @@ import ( "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcastclient" - "github.com/offchainlabs/nitro/broadcaster" + m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/util/contracts" "github.com/offchainlabs/nitro/util/stopwaiter" ) @@ -25,14 +25,14 @@ const PRIMARY_FEED_UPTIME = time.Minute * 10 type Router struct { stopwaiter.StopWaiter - messageChan chan broadcaster.BroadcastFeedMessage + messageChan chan m.BroadcastFeedMessage confirmedSequenceNumberChan chan arbutil.MessageIndex forwardTxStreamer broadcastclient.TransactionStreamerInterface forwardConfirmationChan chan arbutil.MessageIndex } -func (r *Router) AddBroadcastMessages(feedMessages []*broadcaster.BroadcastFeedMessage) error { +func (r *Router) AddBroadcastMessages(feedMessages []*m.BroadcastFeedMessage) error { for _, feedMessage := range feedMessages { r.messageChan <- *feedMessage } @@ -68,7 +68,7 @@ func NewBroadcastClients( } newStandardRouter := func() *Router { return &Router{ - messageChan: make(chan broadcaster.BroadcastFeedMessage, ROUTER_QUEUE_SIZE), + messageChan: make(chan m.BroadcastFeedMessage, ROUTER_QUEUE_SIZE), confirmedSequenceNumberChan: make(chan arbutil.MessageIndex, ROUTER_QUEUE_SIZE), forwardTxStreamer: txStreamer, forwardConfirmationChan: confirmedSequenceNumberListener, @@ -156,7 +156,7 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { continue } recentFeedItemsNew[msg.SequenceNumber] = time.Now() - if err := bcs.primaryRouter.forwardTxStreamer.AddBroadcastMessages([]*broadcaster.BroadcastFeedMessage{&msg}); err != nil { + if err := bcs.primaryRouter.forwardTxStreamer.AddBroadcastMessages([]*m.BroadcastFeedMessage{&msg}); err != nil { log.Error("Error routing message from Primary Sequencer Feeds", "err", err) } case cs := <-bcs.primaryRouter.confirmedSequenceNumberChan: @@ -178,7 +178,7 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { continue } recentFeedItemsNew[msg.SequenceNumber] = time.Now() - if err := bcs.secondaryRouter.forwardTxStreamer.AddBroadcastMessages([]*broadcaster.BroadcastFeedMessage{&msg}); err != nil { + if err := bcs.secondaryRouter.forwardTxStreamer.AddBroadcastMessages([]*m.BroadcastFeedMessage{&msg}); err != nil { log.Error("Error routing message from Secondary Sequencer Feeds", "err", err) } case cs := <-bcs.secondaryRouter.confirmedSequenceNumberChan: From 617c0d6e0c00fc0fbc38728072ba6fc660ecc578 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Tue, 14 Nov 2023 19:51:36 +1300 Subject: [PATCH 384/775] fix lint errors --- broadcaster/backlog/backlog.go | 14 ++++++++++++-- wsbroadcastserver/clientconnection.go | 2 +- wsbroadcastserver/clientmanager.go | 15 +++++++-------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index de786bd32..3ef731386 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -160,14 +160,24 @@ func (b *backlog) delete(confirmed uint64) { b.reset() return } - segment := found.(*backlogSegment) + segment, ok := found.(*backlogSegment) + if !ok { + log.Error("error in backlogSegment type assertion: clearing backlog") + b.reset() + return + } // delete messages from the segment with the confirmed message newHead := segment start := head.Start() if segment.End() == confirmed { found = segment.Next() - newHead = found.(*backlogSegment) + newHead, ok = found.(*backlogSegment) + if !ok { + log.Error("error in backlogSegment type assertion: clearing backlog") + b.reset() + return + } } else { err = segment.Delete(confirmed) if err != nil { diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 6b4c33b8f..02dd300b3 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -157,7 +157,7 @@ func (cc *ClientConnection) writeBroadcastMessage(bm *m.BroadcastMessage) error return err } - data := []byte{} + var data []byte if cc.compression { data = compressed.Bytes() } else { diff --git a/wsbroadcastserver/clientmanager.go b/wsbroadcastserver/clientmanager.go index 683d652c2..7dc0cdcb5 100644 --- a/wsbroadcastserver/clientmanager.go +++ b/wsbroadcastserver/clientmanager.go @@ -30,14 +30,13 @@ import ( ) var ( - clientsCurrentGauge = metrics.NewRegisteredGauge("arb/feed/clients/current", nil) - clientsConnectCount = metrics.NewRegisteredCounter("arb/feed/clients/connect", nil) - clientsDisconnectCount = metrics.NewRegisteredCounter("arb/feed/clients/disconnect", nil) - clientsTotalSuccessCounter = metrics.NewRegisteredCounter("arb/feed/clients/success", nil) - clientsTotalFailedRegisterCounter = metrics.NewRegisteredCounter("arb/feed/clients/failed/register", nil) - clientsTotalFailedUpgradeCounter = metrics.NewRegisteredCounter("arb/feed/clients/failed/upgrade", nil) - clientsTotalFailedWorkerCounter = metrics.NewRegisteredCounter("arb/feed/clients/failed/worker", nil) - clientsDurationHistogram = metrics.NewRegisteredHistogram("arb/feed/clients/duration", nil, metrics.NewBoundedHistogramSample()) + clientsCurrentGauge = metrics.NewRegisteredGauge("arb/feed/clients/current", nil) + clientsConnectCount = metrics.NewRegisteredCounter("arb/feed/clients/connect", nil) + clientsDisconnectCount = metrics.NewRegisteredCounter("arb/feed/clients/disconnect", nil) + clientsTotalSuccessCounter = metrics.NewRegisteredCounter("arb/feed/clients/success", nil) + clientsTotalFailedUpgradeCounter = metrics.NewRegisteredCounter("arb/feed/clients/failed/upgrade", nil) + clientsTotalFailedWorkerCounter = metrics.NewRegisteredCounter("arb/feed/clients/failed/worker", nil) + clientsDurationHistogram = metrics.NewRegisteredHistogram("arb/feed/clients/duration", nil, metrics.NewBoundedHistogramSample()) ) // ClientManager manages client connections From 6635e255112a5188f88ab237c299a564c1bf4233 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 14 Nov 2023 10:21:59 -0600 Subject: [PATCH 385/775] =?UTF-8?q?Make=20=E2=80=9Cerror=20posting=20batch?= =?UTF-8?q?=E2=80=9D=20error=20just=20a=20warning=20unless=20it=20happens?= =?UTF-8?q?=20continuously?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- arbnode/batch_poster.go | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 77a839b70..edfb5c35d 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -30,7 +30,6 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbnode/dataposter" - "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbnode/redislock" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbstate" @@ -1109,22 +1108,21 @@ func (b *BatchPoster) Start(ctxIn context.Context) { return b.config().PollInterval } posted, err := b.maybePostSequencerBatch(ctx) - ephemeralError := errors.Is(err, AccumulatorNotFoundErr) || errors.Is(err, storage.ErrStorageRace) - if !ephemeralError { + if err == nil { b.firstEphemeralError = time.Time{} } if err != nil { b.building = nil logLevel := log.Error - if ephemeralError { - // Likely the inbox tracker just isn't caught up. - // Let's see if this error disappears naturally. - if b.firstEphemeralError == (time.Time{}) { - b.firstEphemeralError = time.Now() - logLevel = log.Debug - } else if time.Since(b.firstEphemeralError) < time.Minute { - logLevel = log.Debug - } + // Likely the inbox tracker just isn't caught up. + // Let's see if this error disappears naturally. + if b.firstEphemeralError == (time.Time{}) { + b.firstEphemeralError = time.Now() + logLevel = log.Warn + } else if time.Since(b.firstEphemeralError) < time.Minute { + logLevel = log.Warn + } else if time.Since(b.firstEphemeralError) < time.Minute*5 && strings.Contains(err.Error(), "will exceed max mempool size") { + logLevel = log.Warn } logLevel("error posting batch", "err", err) return b.config().ErrorDelay From c4c67d4e6013ba771c54b61e36f3ee4fb7c0caa8 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Tue, 14 Nov 2023 09:39:01 -0800 Subject: [PATCH 386/775] Fix geth merge PR comments --- arbos/arbosState/initialize.go | 2 +- arbos/parse_l2.go | 1 + execution/gethexec/sequencer.go | 1 + system_tests/conditionaltx_test.go | 8 ++++---- system_tests/delayedinboxlong_test.go | 13 +++++-------- system_tests/twonodeslong_test.go | 15 ++++++--------- 6 files changed, 18 insertions(+), 22 deletions(-) diff --git a/arbos/arbosState/initialize.go b/arbos/arbosState/initialize.go index a428cad7f..56d8172ee 100644 --- a/arbos/arbosState/initialize.go +++ b/arbos/arbosState/initialize.go @@ -58,7 +58,7 @@ func InitializeArbosInDatabase(db ethdb.Database, initData statetransfer.InitDat } commit := func() (common.Hash, error) { - root, err := statedb.Commit(0, true) + root, err := statedb.Commit(chainConfig.ArbitrumChainParams.GenesisBlockNum, true) if err != nil { return common.Hash{}, err } diff --git a/arbos/parse_l2.go b/arbos/parse_l2.go index 8f5c86f9c..e76781a6f 100644 --- a/arbos/parse_l2.go +++ b/arbos/parse_l2.go @@ -168,6 +168,7 @@ func parseL2Message(rd io.Reader, poster common.Address, timestamp uint64, reque } if newTx.Type() >= types.ArbitrumDepositTxType || newTx.Type() == types.BlobTxType { // Should be unreachable for Arbitrum types due to UnmarshalBinary not accepting Arbitrum internal txs + // and we want to disallow BlobTxType since Arbitrum doesn't support EIP-4844 txs yet. return nil, types.ErrTxTypeNotSupported } return types.Transactions{newTx}, nil diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 52cf714d8..e1b55b6ce 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -387,6 +387,7 @@ func (s *Sequencer) PublishTransaction(parentCtx context.Context, tx *types.Tran } if tx.Type() >= types.ArbitrumDepositTxType || tx.Type() == types.BlobTxType { // Should be unreachable for Arbitrum types due to UnmarshalBinary not accepting Arbitrum internal txs + // and we want to disallow BlobTxType since Arbitrum doesn't support EIP-4844 txs yet. return types.ErrTxTypeNotSupported } diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index d2284eb5b..08367aa62 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -239,7 +239,7 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { Require(t, err) blockNumber := block.NumberU64() - l2BlockTime := func() uint64 { + currentL2BlockTime := func() uint64 { l2Block, err := builder.L2.Client.BlockByNumber(ctx, nil) Require(t, err) return l2Block.Time() @@ -249,7 +249,7 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { optionsB := getOptions(contractAddress2, currentRootHash2, currentSlotValueMap2) optionsAB := optionsProduct(optionsA, optionsB) options1 := dedupOptions(t, append(append(optionsAB, optionsA...), optionsB...)) - options1 = optionsDedupProduct(t, options1, getFulfillableBlockTimeLimits(t, blockNumber, l2BlockTime())) + options1 = optionsDedupProduct(t, options1, getFulfillableBlockTimeLimits(t, blockNumber, currentL2BlockTime())) for i, options := range options1 { testConditionalTxThatShouldSucceed(t, ctx, i, builder.L2Info, rpcClient, options) } @@ -285,7 +285,7 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { optionsD := getOptions(contractAddress2, currentRootHash2, currentSlotValueMap2) optionsCD := optionsProduct(optionsC, optionsD) options2 := dedupOptions(t, append(append(optionsCD, optionsC...), optionsD...)) - options2 = optionsDedupProduct(t, options2, getFulfillableBlockTimeLimits(t, blockNumber, l2BlockTime())) + options2 = optionsDedupProduct(t, options2, getFulfillableBlockTimeLimits(t, blockNumber, currentL2BlockTime())) for i, options := range options2 { testConditionalTxThatShouldSucceed(t, ctx, i, builder.L2Info, rpcClient, options) } @@ -295,7 +295,7 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { block, err = builder.L1.Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() - options3 := optionsDedupProduct(t, options2, getUnfulfillableBlockTimeLimits(t, blockNumber, l2BlockTime())) + options3 := optionsDedupProduct(t, options2, getUnfulfillableBlockTimeLimits(t, blockNumber, currentL2BlockTime())) for i, options := range options3 { testConditionalTxThatShouldFail(t, ctx, i, builder.L2Info, rpcClient, options, -32003) } diff --git a/system_tests/delayedinboxlong_test.go b/system_tests/delayedinboxlong_test.go index 99994fdcf..b5743bfb6 100644 --- a/system_tests/delayedinboxlong_test.go +++ b/system_tests/delayedinboxlong_test.go @@ -38,8 +38,8 @@ func TestDelayInboxLong(t *testing.T) { var lastDelayedMessage *types.Transaction for i := 0; i < addLocalLoops; i++ { - l1Txs := make([]*types.Transaction, 0, messagesPerAddLocal) - for len(l1Txs) < messagesPerAddLocal { + wrappedL1Txs := make([]*txpool.Transaction, 0, messagesPerAddLocal) + for len(wrappedL1Txs) < messagesPerAddLocal { randNum := rand.Int() % messagesPerDelayed var l1tx *types.Transaction if randNum == 0 { @@ -50,12 +50,9 @@ func TestDelayInboxLong(t *testing.T) { } else { l1tx = builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) } - l1Txs = append(l1Txs, l1tx) - } - wrappedL1Txs := make([]*txpool.Transaction, 0, messagesPerAddLocal) - for _, tx := range l1Txs { - wrappedL1Txs = append(wrappedL1Txs, &txpool.Transaction{Tx: tx}) + wrappedL1Txs = append(wrappedL1Txs, &txpool.Transaction{Tx: l1tx}) } + // adding multiple messages in the same Add with local=true to get them in the same L1 block errs := builder.L1.L1Backend.TxPool().Add(wrappedL1Txs, true, false) for _, err := range errs { @@ -63,7 +60,7 @@ func TestDelayInboxLong(t *testing.T) { } // Checking every tx is expensive, so we just check the last, assuming that the others succeeded too confirmLatestBlock(ctx, t, builder.L1Info, builder.L1.Client) - _, err := builder.L1.EnsureTxSucceeded(l1Txs[len(l1Txs)-1]) + _, err := builder.L1.EnsureTxSucceeded(wrappedL1Txs[len(wrappedL1Txs)-1].Tx) Require(t, err) } diff --git a/system_tests/twonodeslong_test.go b/system_tests/twonodeslong_test.go index 4e7c694bc..25110330c 100644 --- a/system_tests/twonodeslong_test.go +++ b/system_tests/twonodeslong_test.go @@ -85,8 +85,8 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { } for i := 0; i < largeLoops; i++ { l1TxsThisTime := rand.Int() % (avgTotalL1MessagesPerLoop * 2) - l1Txs := make([]*types.Transaction, 0, l1TxsThisTime) - for len(l1Txs) < l1TxsThisTime { + wrappedL1Txs := make([]*txpool.Transaction, 0, l1TxsThisTime) + for len(wrappedL1Txs) < l1TxsThisTime { randNum := rand.Int() % avgTotalL1MessagesPerLoop var l1tx *types.Transaction if randNum < avgDelayedMessagesPerLoop { @@ -97,12 +97,9 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { } else { l1tx = builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) } - l1Txs = append(l1Txs, l1tx) - } - wrappedL1Txs := make([]*txpool.Transaction, 0, l1TxsThisTime) - for _, tx := range l1Txs { - wrappedL1Txs = append(wrappedL1Txs, &txpool.Transaction{Tx: tx}) + wrappedL1Txs = append(wrappedL1Txs, &txpool.Transaction{Tx: l1tx}) } + // adding multiple messages in the same Add with local=true to get them in the same L1 block errs := builder.L1.L1Backend.TxPool().Add(wrappedL1Txs, true, false) for _, err := range errs { @@ -117,8 +114,8 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { } builder.L2.SendWaitTestTransactions(t, l2Txs) directTransfers += int64(l2TxsThisTime) - if len(l1Txs) > 0 { - _, err := builder.L1.EnsureTxSucceeded(l1Txs[len(l1Txs)-1]) + if len(wrappedL1Txs) > 0 { + _, err := builder.L1.EnsureTxSucceeded(wrappedL1Txs[len(wrappedL1Txs)-1].Tx) if err != nil { Fatal(t, err) } From 8e72df616333f39df56bf0d4f4eeb56a2829de29 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 15 Nov 2023 16:25:09 +1300 Subject: [PATCH 387/775] remove unnecessary exported functions from BacklogSegment interface and recreate the Contains method --- broadcaster/backlog/backlog.go | 46 ++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 3ef731386..3f046516f 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -108,21 +108,25 @@ func (b *backlog) Get(start, end uint64) (*m.BroadcastMessage, error) { return nil, errOutOfBounds } - segment, err := b.Lookup(start) + found, err := b.Lookup(start) if err != nil { return nil, err } + segment, ok := found.(*backlogSegment) + if !ok { + return nil, fmt.Errorf("error in backlogSegment type assertion") + } bm := &m.BroadcastMessage{Version: 1} required := int(end-start) + 1 for { - segMsgs, err := segment.Get(arbmath.MaxInt(start, segment.Start()), arbmath.MinInt(end, segment.End())) + segMsgs, err := segment.get(arbmath.MaxInt(start, segment.Start()), arbmath.MinInt(end, segment.End())) if err != nil { return nil, err } bm.Messages = append(bm.Messages, segMsgs...) - segment = segment.Next() + segment = segment.nextSegment.Load() if len(bm.Messages) == required { break } else if segment == nil { @@ -179,7 +183,7 @@ func (b *backlog) delete(confirmed uint64) { return } } else { - err = segment.Delete(confirmed) + err = segment.delete(confirmed) if err != nil { log.Error(fmt.Sprintf("%s: clearing backlog", err.Error())) b.reset() @@ -233,9 +237,8 @@ type BacklogSegment interface { Start() uint64 End() uint64 Next() BacklogSegment - Get(uint64, uint64) ([]*m.BroadcastFeedMessage, error) + Contains(uint64) bool Messages() []*m.BroadcastFeedMessage - Delete(uint64) error } type backlogSegment struct { @@ -282,8 +285,8 @@ func (s *backlogSegment) Messages() []*m.BroadcastFeedMessage { return s.messages } -// Get reads messages from the given start to end MessageIndex -func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, error) { +// get reads messages from the given start to end MessageIndex +func (s *backlogSegment) get(start, end uint64) ([]*m.BroadcastFeedMessage, error) { noMsgs := []*m.BroadcastFeedMessage{} if start < s.start.Load() { return noMsgs, errOutOfBounds @@ -326,23 +329,34 @@ func (s *backlogSegment) append(prevMsgIdx uint64, msg *m.BroadcastFeedMessage) } // Contains confirms whether the segment contains a message with the given sequence number -func (s *backlogSegment) Delete(confirmed uint64) error { +func (s *backlogSegment) Contains(i uint64) bool { + start := s.start.Load() + if i < start || i > s.end.Load() { + return false + } + + msgIndex := i - start + s.messagesLock.RLock() + msg := s.messages[msgIndex] + s.messagesLock.RUnlock() + if uint64(msg.SequenceNumber) != i { + return false + } + return true +} + +func (s *backlogSegment) delete(confirmed uint64) error { seen := false defer s.updateSegment(&seen) start := s.start.Load() end := s.end.Load() - if confirmed < start || confirmed > end { - return fmt.Errorf("confirmed message (%d) is not in current backlog (%d-%d)", confirmed, start, end) - } - msgIndex := confirmed - start - s.messagesLock.Lock() - msg := s.messages[msgIndex] - if uint64(msg.SequenceNumber) != confirmed { + if !s.Contains(confirmed) { return fmt.Errorf("confirmed message (%d) is not in expected index (%d) in current backlog (%d-%d)", confirmed, msgIndex, start, end) } + s.messagesLock.Lock() s.messages = s.messages[msgIndex+1:] s.messagesLock.Unlock() return nil From ea46fd9032fb17628ce632909a68cf7e6aad2e14 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 15 Nov 2023 16:26:17 +1300 Subject: [PATCH 388/775] ensure the ClientConnection only sends the requested messages to the client rather than the whole segment --- wsbroadcastserver/clientconnection.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 02dd300b3..1b570a36d 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -132,6 +132,10 @@ func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.Ba } msgs := prevSegment.Messages() + if prevSegment.Contains(uint64(cc.requestedSeqNum)) { + requestedIdx := int(cc.requestedSeqNum) - int(prevSegment.Start()) + msgs = msgs[requestedIdx:] + } bm := &m.BroadcastMessage{ Version: 1, // TODO(clamb): I am unsure if it is correct to hard code the version here like this? It seems to be done in other places though Messages: msgs, From 60ce3825a481bcd79690db075175b6b8a9ef7113 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 15 Nov 2023 16:42:59 +1300 Subject: [PATCH 389/775] fix backlog lint error --- broadcaster/backlog/backlog.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 3f046516f..8fe721dc3 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -339,10 +339,7 @@ func (s *backlogSegment) Contains(i uint64) bool { s.messagesLock.RLock() msg := s.messages[msgIndex] s.messagesLock.RUnlock() - if uint64(msg.SequenceNumber) != i { - return false - } - return true + return uint64(msg.SequenceNumber) == i } func (s *backlogSegment) delete(confirmed uint64) error { From 4af7991e78162afc4b611cf571b37fcdc89df048 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 15 Nov 2023 10:43:56 -0600 Subject: [PATCH 390/775] Fix the check for duplicate sequencerBatches in indox_reader --- arbnode/inbox_reader.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/inbox_reader.go b/arbnode/inbox_reader.go index 6ce9fd717..9c830e3c8 100644 --- a/arbnode/inbox_reader.go +++ b/arbnode/inbox_reader.go @@ -435,11 +435,11 @@ func (r *InboxReader) run(ctx context.Context, hadError bool) error { } else if err != nil { // Unknown error (database error?) return err - } else if haveAcc == batch.BeforeInboxAcc { + } else if haveAcc == batch.AfterInboxAcc { // Skip this batch, as we already have it in the database sequencerBatches = sequencerBatches[1:] } else { - // The first batch BeforeInboxAcc matches, but this batch doesn't, + // The first batch AfterInboxAcc matches, but this batch doesn't, // so we'll successfully reorg it when we hit the addMessages break } From 9ebb2764d1e3401e05bf7058d1908bcf030b40a5 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 15 Nov 2023 10:54:47 -0700 Subject: [PATCH 391/775] Add support for consensus v10.3 to Dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index b05cb3d4d..b966125b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -163,6 +163,7 @@ COPY ./scripts/download-machine.sh . RUN ./download-machine.sh consensus-v10 0x6b94a7fc388fd8ef3def759297828dc311761e88d8179c7ee8d3887dc554f3c3 RUN ./download-machine.sh consensus-v10.1 0xda4e3ad5e7feacb817c21c8d0220da7650fe9051ece68a3f0b1c5d38bbb27b21 RUN ./download-machine.sh consensus-v10.2 0x0754e09320c381566cc0449904c377a52bd34a6b9404432e80afd573b67f7b17 +RUN ./download-machine.sh consensus-v10.3 0xf559b6d4fa869472dabce70fe1c15221bdda837533dfd891916836975b434dec FROM golang:1.20-bullseye as node-builder WORKDIR /workspace From 3c8d3c797b343217d03d3d16cef1998e3b506d27 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 15 Nov 2023 15:35:52 -0600 Subject: [PATCH 392/775] add more backup feeds and fix assignment to chainDefaults --- cmd/chaininfo/arbitrum_chain_info.json | 2 +- cmd/nitro/nitro.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/chaininfo/arbitrum_chain_info.json b/cmd/chaininfo/arbitrum_chain_info.json index 0fa2db57f..421abea20 100644 --- a/cmd/chaininfo/arbitrum_chain_info.json +++ b/cmd/chaininfo/arbitrum_chain_info.json @@ -5,7 +5,7 @@ "parent-chain-is-arbitrum": false, "sequencer-url": "https://arb1-sequencer.arbitrum.io/rpc", "feed-url": "wss://arb1-feed.arbitrum.io/feed", - "secondary-feed-url": "wss://arb1-delayed-feed.arbitrum.io/feed", + "secondary-feed-url": "wss://arb1-delayed-feed.arbitrum.io/feed,wss://arb1-feed-fallback-1.arbitrum.io/feed,wss://arb1-feed-fallback-2.arbitrum.io/feed,wss://arb1-feed-fallback-3.arbitrum.io/feed,wss://arb1-feed-fallback-4.arbitrum.io/feed,wss://arb1-feed-fallback-5.arbitrum.io/feed", "has-genesis-state": true, "chain-config": { "chainId": 42161, diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 0154606af..49c326eb7 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -815,10 +815,10 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c chainDefaults["execution.forwarding-target"] = chainInfo.SequencerUrl } if chainInfo.FeedUrl != "" { - chainDefaults["node.feed.input.url"] = chainInfo.FeedUrl + chainDefaults["node.feed.input.url"] = strings.Split(chainInfo.FeedUrl, ",") } if chainInfo.SecondaryFeedUrl != "" { - chainDefaults["node.feed.input.secondary-url"] = chainInfo.SecondaryFeedUrl + chainDefaults["node.feed.input.secondary-url"] = strings.Split(chainInfo.SecondaryFeedUrl, ",") } if chainInfo.DasIndexUrl != "" { chainDefaults["node.data-availability.enable"] = true From 5e2f1aa1f6ac6daefa8c2bfd91e05811c71b97ef Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 16 Nov 2023 15:33:50 +1300 Subject: [PATCH 393/775] ensure WSBroadcast server sends the whole backlog when the requested seq num is lower than what is in the backlog --- broadcaster/backlog/backlog.go | 5 +++++ wsbroadcastserver/clientconnection.go | 15 +++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 8fe721dc3..1618fc5ee 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -18,6 +18,7 @@ var ( ) type Backlog interface { + Head() BacklogSegment Append(*m.BroadcastMessage) error Get(uint64, uint64) (*m.BroadcastMessage, error) Count() uint64 @@ -41,6 +42,10 @@ func NewBacklog(c ConfigFetcher) Backlog { } } +func (b *backlog) Head() BacklogSegment { + return b.head.Load() +} + // Append will add the given messages to the backlogSegment at head until // that segment reaches its limit. If messages remain to be added a new segment // will be created. diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 1b570a36d..9e82b09a6 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -191,13 +191,16 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { // Send the current backlog before registering the ClientConnection in // case the backlog is very large - segment, err := cc.backlog.Lookup(uint64(cc.requestedSeqNum)) - if err != nil { - logWarn(err, "error finding requested sequence number in backlog") - cc.Remove() - return + segment := cc.backlog.Head() + if !backlog.IsBacklogSegmentNil(segment) && segment.Start() < uint64(cc.requestedSeqNum) { + s, err := cc.backlog.Lookup(uint64(cc.requestedSeqNum)) + if err != nil { + logWarn(err, "error finding requested sequence number in backlog: sending the entire backlog instead") + } else { + segment = s + } } - err = cc.writeBacklog(ctx, segment) + err := cc.writeBacklog(ctx, segment) if errors.Is(err, errContextDone) { return } else if err != nil { From 812e7a6399e13e40330108fac65d9449819e3712 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 16 Nov 2023 16:55:31 +1300 Subject: [PATCH 394/775] add comments to backlog functions --- broadcaster/backlog/backlog.go | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 1618fc5ee..999dd3b6a 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -17,6 +17,7 @@ var ( errOutOfBounds = errors.New("message not found in backlog") ) +// Backlog defines the interface for backlog. type Backlog interface { Head() BacklogSegment Append(*m.BroadcastMessage) error @@ -25,6 +26,8 @@ type Backlog interface { Lookup(uint64) (BacklogSegment, error) } +// backlog stores backlogSegments and provides the ability to read/write +// messages. type backlog struct { head atomic.Pointer[backlogSegment] tail atomic.Pointer[backlogSegment] @@ -34,6 +37,7 @@ type backlog struct { messageCount atomic.Uint64 } +// NewBacklog creates a backlog. func NewBacklog(c ConfigFetcher) Backlog { lookup := make(map[uint64]*backlogSegment) return &backlog{ @@ -42,6 +46,7 @@ func NewBacklog(c ConfigFetcher) Backlog { } } +// Head return the head backlogSegment within the backlog. func (b *backlog) Head() BacklogSegment { return b.head.Load() } @@ -204,7 +209,7 @@ func (b *backlog) delete(confirmed uint64) { } // removeFromLookup removes all entries from the head segment's start index to -// the given confirmed index +// the given confirmed index. func (b *backlog) removeFromLookup(start, end uint64) { b.lookupLock.Lock() defer b.lookupLock.Unlock() @@ -213,6 +218,7 @@ func (b *backlog) removeFromLookup(start, end uint64) { } } +// Lookup attempts to find the backlogSegment storing the given message index. func (b *backlog) Lookup(i uint64) (BacklogSegment, error) { b.lookupLock.RLock() segment, ok := b.lookupByIndex[i] @@ -224,11 +230,12 @@ func (b *backlog) Lookup(i uint64) (BacklogSegment, error) { return segment, nil } +// Count returns the number of messages stored within the backlog. func (s *backlog) Count() uint64 { return s.messageCount.Load() } -// reset removes all segments from the backlog +// reset removes all segments from the backlog. func (b *backlog) reset() { b.lookupLock.Lock() defer b.lookupLock.Unlock() @@ -238,6 +245,7 @@ func (b *backlog) reset() { b.messageCount.Store(0) } +// BacklogSegment defines the interface for backlogSegment. type BacklogSegment interface { Start() uint64 End() uint64 @@ -246,6 +254,8 @@ type BacklogSegment interface { Messages() []*m.BroadcastFeedMessage } +// backlogSegment stores messages up to a limit defined by the backlog. It also +// points to the next backlogSegment in the list. type backlogSegment struct { start atomic.Uint64 end atomic.Uint64 @@ -272,25 +282,29 @@ func IsBacklogSegmentNil(segment BacklogSegment) bool { return segment.(*backlogSegment) == nil } +// Start returns the first message index within the backlogSegment. func (s *backlogSegment) Start() uint64 { return uint64(s.start.Load()) } +// End returns the last message index within the backlogSegment. func (s *backlogSegment) End() uint64 { return uint64(s.end.Load()) } +// Next returns the next backlogSegment. func (s *backlogSegment) Next() BacklogSegment { return s.nextSegment.Load() } +// Messages returns all of the messages stored in the backlogSegment. func (s *backlogSegment) Messages() []*m.BroadcastFeedMessage { s.messagesLock.RLock() defer s.messagesLock.RUnlock() return s.messages } -// get reads messages from the given start to end MessageIndex +// get reads messages from the given start to end message index. func (s *backlogSegment) get(start, end uint64) ([]*m.BroadcastFeedMessage, error) { noMsgs := []*m.BroadcastFeedMessage{} if start < s.start.Load() { @@ -333,7 +347,8 @@ func (s *backlogSegment) append(prevMsgIdx uint64, msg *m.BroadcastFeedMessage) return nil } -// Contains confirms whether the segment contains a message with the given sequence number +// Contains confirms whether the segment contains a message with the given +// sequence number. func (s *backlogSegment) Contains(i uint64) bool { start := s.start.Load() if i < start || i > s.end.Load() { @@ -347,6 +362,8 @@ func (s *backlogSegment) Contains(i uint64) bool { return uint64(msg.SequenceNumber) == i } +// delete removes messages from the backlogSegment up to and including the +// given confirmed message index. func (s *backlogSegment) delete(confirmed uint64) error { seen := false defer s.updateSegment(&seen) @@ -376,7 +393,7 @@ func (s *backlogSegment) updateSegment(seen *bool) { } } -// count returns the number of messages stored in the backlog segment +// count returns the number of messages stored in the backlog segment. func (s *backlogSegment) count() int { return int(s.messageCount.Load()) } From 50f211da4f0ff89f011b950a1dfaadcefc75a937 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 16 Nov 2023 14:26:22 -0600 Subject: [PATCH 395/775] Handle nil channel case inside router model --- broadcastclients/broadcastclients.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index 551dcdb46..b2824221e 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -166,7 +166,9 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { continue } lastConfirmed = cs - bcs.primaryRouter.forwardConfirmationChan <- cs + if bcs.primaryRouter.forwardConfirmationChan != nil { + bcs.primaryRouter.forwardConfirmationChan <- cs + } // Secondary Feeds case msg := <-bcs.secondaryRouter.messageChan: @@ -187,7 +189,9 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { continue } lastConfirmed = cs - bcs.secondaryRouter.forwardConfirmationChan <- cs + if bcs.secondaryRouter.forwardConfirmationChan != nil { + bcs.secondaryRouter.forwardConfirmationChan <- cs + } // Cycle buckets to get rid of old entries case <-recentFeedItemsCleanup.C: From 050bd1bcd3624c6ca640f72bdb3a8c61dbb9474d Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 16 Nov 2023 16:19:47 -0800 Subject: [PATCH 396/775] Use geth v1.12.2 branch --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index be1fd29a2..c3635af75 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit be1fd29a26173eae9008c33280b2942a86a4b0fc +Subproject commit c3635af757887bde1243a9dd83ec079b47e9aa3f From ce37f8067856989ec77d42d6bb1156d37b3fd5f8 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 16 Nov 2023 17:28:51 -0700 Subject: [PATCH 397/775] deploy: move to own package --- arbnode/node.go | 267 ---------------------------------- cmd/deploy/deploy.go | 3 +- deploy/deploy.go | 283 ++++++++++++++++++++++++++++++++++++ system_tests/common_test.go | 3 +- 4 files changed, 287 insertions(+), 269 deletions(-) create mode 100644 deploy/deploy.go diff --git a/arbnode/node.go b/arbnode/node.go index 0782e8ecb..d7b1d83ba 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -18,7 +18,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" @@ -37,11 +36,8 @@ import ( "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/solgen/go/bridgegen" - "github.com/offchainlabs/nitro/solgen/go/challengegen" - "github.com/offchainlabs/nitro/solgen/go/ospgen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" - "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/staker/validatorwallet" "github.com/offchainlabs/nitro/util/contracts" @@ -51,215 +47,6 @@ import ( "github.com/offchainlabs/nitro/wsbroadcastserver" ) -func andTxSucceeded(ctx context.Context, l1Reader *headerreader.HeaderReader, tx *types.Transaction, err error) error { - if err != nil { - return fmt.Errorf("error submitting tx: %w", err) - } - _, err = l1Reader.WaitForTxApproval(ctx, tx) - if err != nil { - return fmt.Errorf("error executing tx: %w", err) - } - return nil -} - -func deployBridgeCreator(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts, maxDataSize *big.Int) (common.Address, error) { - client := l1Reader.Client() - - /// deploy eth based templates - bridgeTemplate, tx, _, err := bridgegen.DeployBridge(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("bridge deploy error: %w", err) - } - - seqInboxTemplate, tx, _, err := bridgegen.DeploySequencerInbox(auth, client, maxDataSize) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("sequencer inbox deploy error: %w", err) - } - - inboxTemplate, tx, _, err := bridgegen.DeployInbox(auth, client, maxDataSize) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("inbox deploy error: %w", err) - } - - rollupEventBridgeTemplate, tx, _, err := rollupgen.DeployRollupEventInbox(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("rollup event bridge deploy error: %w", err) - } - - outboxTemplate, tx, _, err := bridgegen.DeployOutbox(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("outbox deploy error: %w", err) - } - - ethBasedTemplates := rollupgen.BridgeCreatorBridgeContracts{ - Bridge: bridgeTemplate, - SequencerInbox: seqInboxTemplate, - Inbox: inboxTemplate, - RollupEventInbox: rollupEventBridgeTemplate, - Outbox: outboxTemplate, - } - - /// deploy ERC20 based templates - erc20BridgeTemplate, tx, _, err := bridgegen.DeployERC20Bridge(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("bridge deploy error: %w", err) - } - - erc20InboxTemplate, tx, _, err := bridgegen.DeployERC20Inbox(auth, client, maxDataSize) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("inbox deploy error: %w", err) - } - - erc20RollupEventBridgeTemplate, tx, _, err := rollupgen.DeployERC20RollupEventInbox(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("rollup event bridge deploy error: %w", err) - } - - erc20OutboxTemplate, tx, _, err := bridgegen.DeployERC20Outbox(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("outbox deploy error: %w", err) - } - - erc20BasedTemplates := rollupgen.BridgeCreatorBridgeContracts{ - Bridge: erc20BridgeTemplate, - SequencerInbox: seqInboxTemplate, - Inbox: erc20InboxTemplate, - RollupEventInbox: erc20RollupEventBridgeTemplate, - Outbox: erc20OutboxTemplate, - } - - bridgeCreatorAddr, tx, _, err := rollupgen.DeployBridgeCreator(auth, client, ethBasedTemplates, erc20BasedTemplates) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("bridge creator deploy error: %w", err) - } - - return bridgeCreatorAddr, nil -} - -func deployChallengeFactory(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts) (common.Address, common.Address, error) { - client := l1Reader.Client() - osp0, tx, _, err := ospgen.DeployOneStepProver0(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, common.Address{}, fmt.Errorf("osp0 deploy error: %w", err) - } - - ospMem, _, _, err := ospgen.DeployOneStepProverMemory(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, common.Address{}, fmt.Errorf("ospMemory deploy error: %w", err) - } - - ospMath, _, _, err := ospgen.DeployOneStepProverMath(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, common.Address{}, fmt.Errorf("ospMath deploy error: %w", err) - } - - ospHostIo, _, _, err := ospgen.DeployOneStepProverHostIo(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, common.Address{}, fmt.Errorf("ospHostIo deploy error: %w", err) - } - - ospEntryAddr, tx, _, err := ospgen.DeployOneStepProofEntry(auth, client, osp0, ospMem, ospMath, ospHostIo) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, common.Address{}, fmt.Errorf("ospEntry deploy error: %w", err) - } - - challengeManagerAddr, tx, _, err := challengegen.DeployChallengeManager(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, common.Address{}, fmt.Errorf("ospEntry deploy error: %w", err) - } - - return ospEntryAddr, challengeManagerAddr, nil -} - -func deployRollupCreator(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts, maxDataSize *big.Int) (*rollupgen.RollupCreator, common.Address, common.Address, common.Address, error) { - bridgeCreator, err := deployBridgeCreator(ctx, l1Reader, auth, maxDataSize) - if err != nil { - return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("bridge creator deploy error: %w", err) - } - - ospEntryAddr, challengeManagerAddr, err := deployChallengeFactory(ctx, l1Reader, auth) - if err != nil { - return nil, common.Address{}, common.Address{}, common.Address{}, err - } - - rollupAdminLogic, tx, _, err := rollupgen.DeployRollupAdminLogic(auth, l1Reader.Client()) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("rollup admin logic deploy error: %w", err) - } - - rollupUserLogic, tx, _, err := rollupgen.DeployRollupUserLogic(auth, l1Reader.Client()) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("rollup user logic deploy error: %w", err) - } - - rollupCreatorAddress, tx, rollupCreator, err := rollupgen.DeployRollupCreator(auth, l1Reader.Client()) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("rollup creator deploy error: %w", err) - } - - upgradeExecutor, tx, _, err := upgrade_executorgen.DeployUpgradeExecutor(auth, l1Reader.Client()) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("upgrade executor deploy error: %w", err) - } - - validatorUtils, tx, _, err := rollupgen.DeployValidatorUtils(auth, l1Reader.Client()) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("validator utils deploy error: %w", err) - } - - validatorWalletCreator, tx, _, err := rollupgen.DeployValidatorWalletCreator(auth, l1Reader.Client()) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("validator wallet creator deploy error: %w", err) - } - - l2FactoriesDeployHelper, tx, _, err := rollupgen.DeployDeployHelper(auth, l1Reader.Client()) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("deploy helper creator deploy error: %w", err) - } - - tx, err = rollupCreator.SetTemplates( - auth, - bridgeCreator, - ospEntryAddr, - challengeManagerAddr, - rollupAdminLogic, - rollupUserLogic, - upgradeExecutor, - validatorUtils, - validatorWalletCreator, - l2FactoriesDeployHelper, - ) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("rollup set template error: %w", err) - } - - return rollupCreator, rollupCreatorAddress, validatorUtils, validatorWalletCreator, nil -} - func GenerateRollupConfig(prod bool, wasmModuleRoot common.Hash, rollupOwner common.Address, chainConfig *params.ChainConfig, serializedChainConfig []byte, loserStakeEscrow common.Address) rollupgen.Config { var confirmPeriod uint64 if prod { @@ -287,60 +74,6 @@ func GenerateRollupConfig(prod bool, wasmModuleRoot common.Hash, rollupOwner com } } -func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReader, deployAuth *bind.TransactOpts, batchPoster common.Address, authorizeValidators uint64, config rollupgen.Config, nativeToken common.Address, maxDataSize *big.Int) (*chaininfo.RollupAddresses, error) { - if config.WasmModuleRoot == (common.Hash{}) { - return nil, errors.New("no machine specified") - } - - rollupCreator, _, validatorUtils, validatorWalletCreator, err := deployRollupCreator(ctx, parentChainReader, deployAuth, maxDataSize) - if err != nil { - return nil, fmt.Errorf("error deploying rollup creator: %w", err) - } - - var validatorAddrs []common.Address - for i := uint64(1); i <= authorizeValidators; i++ { - validatorAddrs = append(validatorAddrs, crypto.CreateAddress(validatorWalletCreator, i)) - } - - deployParams := rollupgen.RollupCreatorRollupDeploymentParams{ - Config: config, - BatchPoster: batchPoster, - Validators: validatorAddrs, - MaxDataSize: maxDataSize, - NativeToken: nativeToken, - DeployFactoriesToL2: false, - MaxFeePerGasForRetryables: big.NewInt(0), // needed when utility factories are deployed - } - - tx, err := rollupCreator.CreateRollup( - deployAuth, - deployParams, - ) - if err != nil { - return nil, fmt.Errorf("error submitting create rollup tx: %w", err) - } - receipt, err := parentChainReader.WaitForTxApproval(ctx, tx) - if err != nil { - return nil, fmt.Errorf("error executing create rollup tx: %w", err) - } - info, err := rollupCreator.ParseRollupCreated(*receipt.Logs[len(receipt.Logs)-1]) - if err != nil { - return nil, fmt.Errorf("error parsing rollup created log: %w", err) - } - - return &chaininfo.RollupAddresses{ - Bridge: info.Bridge, - Inbox: info.InboxAddress, - SequencerInbox: info.SequencerInbox, - DeployedAt: receipt.BlockNumber.Uint64(), - Rollup: info.RollupAddress, - NativeToken: nativeToken, - UpgradeExecutor: info.UpgradeExecutor, - ValidatorUtils: validatorUtils, - ValidatorWalletCreator: validatorWalletCreator, - }, nil -} - type Config struct { Sequencer bool `koanf:"sequencer"` ParentChainReader headerreader.Config `koanf:"parent-chain-reader" reload:"hot"` diff --git a/cmd/deploy/deploy.go b/cmd/deploy/deploy.go index 0b7203890..afbcddec6 100644 --- a/cmd/deploy/deploy.go +++ b/cmd/deploy/deploy.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/cmd/util" + deploycode "github.com/offchainlabs/nitro/deploy" ) func main() { @@ -141,7 +142,7 @@ func main() { defer l1Reader.StopAndWait() nativeToken := common.HexToAddress(*nativeTokenAddressString) - deployedAddresses, err := arbnode.DeployOnL1( + deployedAddresses, err := deploycode.DeployOnL1( ctx, l1Reader, l1TransactionOpts, diff --git a/deploy/deploy.go b/deploy/deploy.go new file mode 100644 index 000000000..abdf4c06b --- /dev/null +++ b/deploy/deploy.go @@ -0,0 +1,283 @@ +package deploy + +import ( + "context" + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/offchainlabs/nitro/cmd/chaininfo" + "github.com/offchainlabs/nitro/solgen/go/bridgegen" + "github.com/offchainlabs/nitro/solgen/go/challengegen" + "github.com/offchainlabs/nitro/solgen/go/ospgen" + "github.com/offchainlabs/nitro/solgen/go/rollupgen" + "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" + "github.com/offchainlabs/nitro/util/headerreader" +) + +func andTxSucceeded(ctx context.Context, l1Reader *headerreader.HeaderReader, tx *types.Transaction, err error) error { + if err != nil { + return fmt.Errorf("error submitting tx: %w", err) + } + _, err = l1Reader.WaitForTxApproval(ctx, tx) + if err != nil { + return fmt.Errorf("error executing tx: %w", err) + } + return nil +} + +func deployBridgeCreator(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts, maxDataSize *big.Int) (common.Address, error) { + client := l1Reader.Client() + + /// deploy eth based templates + bridgeTemplate, tx, _, err := bridgegen.DeployBridge(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("bridge deploy error: %w", err) + } + + seqInboxTemplate, tx, _, err := bridgegen.DeploySequencerInbox(auth, client, maxDataSize) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("sequencer inbox deploy error: %w", err) + } + + inboxTemplate, tx, _, err := bridgegen.DeployInbox(auth, client, maxDataSize) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("inbox deploy error: %w", err) + } + + rollupEventBridgeTemplate, tx, _, err := rollupgen.DeployRollupEventInbox(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("rollup event bridge deploy error: %w", err) + } + + outboxTemplate, tx, _, err := bridgegen.DeployOutbox(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("outbox deploy error: %w", err) + } + + ethBasedTemplates := rollupgen.BridgeCreatorBridgeContracts{ + Bridge: bridgeTemplate, + SequencerInbox: seqInboxTemplate, + Inbox: inboxTemplate, + RollupEventInbox: rollupEventBridgeTemplate, + Outbox: outboxTemplate, + } + + /// deploy ERC20 based templates + erc20BridgeTemplate, tx, _, err := bridgegen.DeployERC20Bridge(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("bridge deploy error: %w", err) + } + + erc20InboxTemplate, tx, _, err := bridgegen.DeployERC20Inbox(auth, client, maxDataSize) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("inbox deploy error: %w", err) + } + + erc20RollupEventBridgeTemplate, tx, _, err := rollupgen.DeployERC20RollupEventInbox(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("rollup event bridge deploy error: %w", err) + } + + erc20OutboxTemplate, tx, _, err := bridgegen.DeployERC20Outbox(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("outbox deploy error: %w", err) + } + + erc20BasedTemplates := rollupgen.BridgeCreatorBridgeContracts{ + Bridge: erc20BridgeTemplate, + SequencerInbox: seqInboxTemplate, + Inbox: erc20InboxTemplate, + RollupEventInbox: erc20RollupEventBridgeTemplate, + Outbox: erc20OutboxTemplate, + } + + bridgeCreatorAddr, tx, _, err := rollupgen.DeployBridgeCreator(auth, client, ethBasedTemplates, erc20BasedTemplates) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("bridge creator deploy error: %w", err) + } + + return bridgeCreatorAddr, nil +} + +func deployChallengeFactory(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts) (common.Address, common.Address, error) { + client := l1Reader.Client() + osp0, tx, _, err := ospgen.DeployOneStepProver0(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, common.Address{}, fmt.Errorf("osp0 deploy error: %w", err) + } + + ospMem, _, _, err := ospgen.DeployOneStepProverMemory(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, common.Address{}, fmt.Errorf("ospMemory deploy error: %w", err) + } + + ospMath, _, _, err := ospgen.DeployOneStepProverMath(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, common.Address{}, fmt.Errorf("ospMath deploy error: %w", err) + } + + ospHostIo, _, _, err := ospgen.DeployOneStepProverHostIo(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, common.Address{}, fmt.Errorf("ospHostIo deploy error: %w", err) + } + + challengeManagerAddr, tx, _, err := challengegen.DeployChallengeManager(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, common.Address{}, fmt.Errorf("challenge manager deploy error: %w", err) + } + + ospEntryAddr, tx, _, err := ospgen.DeployOneStepProofEntry(auth, client, osp0, ospMem, ospMath, ospHostIo) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, common.Address{}, fmt.Errorf("ospEntry deploy error: %w", err) + } + + return ospEntryAddr, challengeManagerAddr, nil +} + +func deployRollupCreator(ctx context.Context, l1Reader *headerreader.HeaderReader, auth *bind.TransactOpts, maxDataSize *big.Int) (*rollupgen.RollupCreator, common.Address, common.Address, common.Address, error) { + bridgeCreator, err := deployBridgeCreator(ctx, l1Reader, auth, maxDataSize) + if err != nil { + return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("bridge creator deploy error: %w", err) + } + + ospEntryAddr, challengeManagerAddr, err := deployChallengeFactory(ctx, l1Reader, auth) + if err != nil { + return nil, common.Address{}, common.Address{}, common.Address{}, err + } + + rollupAdminLogic, tx, _, err := rollupgen.DeployRollupAdminLogic(auth, l1Reader.Client()) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("rollup admin logic deploy error: %w", err) + } + + rollupUserLogic, tx, _, err := rollupgen.DeployRollupUserLogic(auth, l1Reader.Client()) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("rollup user logic deploy error: %w", err) + } + + rollupCreatorAddress, tx, rollupCreator, err := rollupgen.DeployRollupCreator(auth, l1Reader.Client()) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("rollup creator deploy error: %w", err) + } + + upgradeExecutor, tx, _, err := upgrade_executorgen.DeployUpgradeExecutor(auth, l1Reader.Client()) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("upgrade executor deploy error: %w", err) + } + + validatorUtils, tx, _, err := rollupgen.DeployValidatorUtils(auth, l1Reader.Client()) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("validator utils deploy error: %w", err) + } + + validatorWalletCreator, tx, _, err := rollupgen.DeployValidatorWalletCreator(auth, l1Reader.Client()) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("validator wallet creator deploy error: %w", err) + } + + l2FactoriesDeployHelper, tx, _, err := rollupgen.DeployDeployHelper(auth, l1Reader.Client()) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("deploy helper creator deploy error: %w", err) + } + + tx, err = rollupCreator.SetTemplates( + auth, + bridgeCreator, + ospEntryAddr, + challengeManagerAddr, + rollupAdminLogic, + rollupUserLogic, + upgradeExecutor, + validatorUtils, + validatorWalletCreator, + l2FactoriesDeployHelper, + ) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return nil, common.Address{}, common.Address{}, common.Address{}, fmt.Errorf("rollup set template error: %w", err) + } + + return rollupCreator, rollupCreatorAddress, validatorUtils, validatorWalletCreator, nil +} + +func DeployOnL1(ctx context.Context, parentChainReader *headerreader.HeaderReader, deployAuth *bind.TransactOpts, batchPoster common.Address, authorizeValidators uint64, config rollupgen.Config, nativeToken common.Address, maxDataSize *big.Int) (*chaininfo.RollupAddresses, error) { + if config.WasmModuleRoot == (common.Hash{}) { + return nil, errors.New("no machine specified") + } + + rollupCreator, _, validatorUtils, validatorWalletCreator, err := deployRollupCreator(ctx, parentChainReader, deployAuth, maxDataSize) + if err != nil { + return nil, fmt.Errorf("error deploying rollup creator: %w", err) + } + + var validatorAddrs []common.Address + for i := uint64(1); i <= authorizeValidators; i++ { + validatorAddrs = append(validatorAddrs, crypto.CreateAddress(validatorWalletCreator, i)) + } + + deployParams := rollupgen.RollupCreatorRollupDeploymentParams{ + Config: config, + BatchPoster: batchPoster, + Validators: validatorAddrs, + MaxDataSize: maxDataSize, + NativeToken: nativeToken, + DeployFactoriesToL2: false, + MaxFeePerGasForRetryables: big.NewInt(0), // needed when utility factories are deployed + } + + tx, err := rollupCreator.CreateRollup( + deployAuth, + deployParams, + ) + if err != nil { + return nil, fmt.Errorf("error submitting create rollup tx: %w", err) + } + receipt, err := parentChainReader.WaitForTxApproval(ctx, tx) + if err != nil { + return nil, fmt.Errorf("error executing create rollup tx: %w", err) + } + info, err := rollupCreator.ParseRollupCreated(*receipt.Logs[len(receipt.Logs)-1]) + if err != nil { + return nil, fmt.Errorf("error parsing rollup created log: %w", err) + } + + return &chaininfo.RollupAddresses{ + Bridge: info.Bridge, + Inbox: info.InboxAddress, + SequencerInbox: info.SequencerInbox, + DeployedAt: receipt.BlockNumber.Uint64(), + Rollup: info.RollupAddress, + NativeToken: nativeToken, + UpgradeExecutor: info.UpgradeExecutor, + ValidatorUtils: validatorUtils, + ValidatorWalletCreator: validatorWalletCreator, + }, nil +} diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 327ce94e0..b0074a268 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -23,6 +23,7 @@ import ( "github.com/offchainlabs/nitro/cmd/chaininfo" "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/das" + "github.com/offchainlabs/nitro/deploy" "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/headerreader" @@ -656,7 +657,7 @@ func DeployOnTestL1( nativeToken := common.Address{} maxDataSize := big.NewInt(117964) - addresses, err := arbnode.DeployOnL1( + addresses, err := deploy.DeployOnL1( ctx, l1Reader, &l1TransactionOpts, From 5859a47c1db2c5c82b911169727febc81dd4735f Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 16 Nov 2023 16:29:57 -0800 Subject: [PATCH 398/775] Updates from go mod tidy for geth 1.12.2 --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 49f37c074..c917d0da3 100644 --- a/go.mod +++ b/go.mod @@ -99,7 +99,7 @@ require ( github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/ethereum/c-kzg-4844 v0.3.0 // indirect + github.com/ethereum/c-kzg-4844 v0.3.1 // indirect github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect @@ -248,7 +248,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/samber/lo v1.36.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/supranational/blst v0.3.11-0.20230406105308-e9dfc5ee724b // indirect + github.com/supranational/blst v0.3.11 // indirect github.com/urfave/cli/v2 v2.24.1 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect @@ -277,8 +277,8 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.24.0 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect - golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect - golang.org/x/mod v0.10.0 // indirect + golang.org/x/exp v0.0.0-20230810033253-352e893a4cad // indirect + golang.org/x/mod v0.11.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sync v0.3.0 // indirect golang.org/x/text v0.13.0 // indirect diff --git a/go.sum b/go.sum index bb8d6f77f..a8eacfefb 100644 --- a/go.sum +++ b/go.sum @@ -334,8 +334,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum/c-kzg-4844 v0.3.0 h1:3Y3hD6l5i0dEYsBL50C+Om644kve3pNqoAcvE26o9zI= -github.com/ethereum/c-kzg-4844 v0.3.0/go.mod h1:WI2Nd82DMZAAZI1wV2neKGost9EKjvbpQR9OqE5Qqa8= +github.com/ethereum/c-kzg-4844 v0.3.1 h1:sR65+68+WdnMKxseNWxSJuAv2tsUrihTpVBTfM/U5Zg= +github.com/ethereum/c-kzg-4844 v0.3.1/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= @@ -1589,8 +1589,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/supranational/blst v0.3.11-0.20230406105308-e9dfc5ee724b h1:u49mjRnygnB34h8OKbnNJFVUtWSKIKb1KukdV8bILUM= -github.com/supranational/blst v0.3.11-0.20230406105308-e9dfc5ee724b/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= @@ -1798,8 +1798,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20230810033253-352e893a4cad h1:g0bG7Z4uG+OgH2QDODnjp6ggkk1bJDsINcuWmJN1iJU= +golang.org/x/exp v0.0.0-20230810033253-352e893a4cad/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1824,8 +1824,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From 5fe74348b2f4f3d3b79f158e7ba3c30437e10049 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 16 Nov 2023 19:27:52 -0700 Subject: [PATCH 399/775] headerreader: use directly don't need interface since we separated headerreader from arbnode --- staker/staker.go | 5 +++-- staker/stateless_block_validator.go | 8 -------- staker/validatorwallet/contract.go | 9 +-------- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/staker/staker.go b/staker/staker.go index 7918e8000..4f35c1bc9 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -26,6 +26,7 @@ import ( "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/staker/txbuilder" "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/stopwaiter" "github.com/offchainlabs/nitro/validator" ) @@ -240,7 +241,7 @@ type LatestConfirmedNotifier interface { type Staker struct { *L1Validator stopwaiter.StopWaiter - l1Reader L1ReaderInterface + l1Reader *headerreader.HeaderReader stakedNotifiers []LatestStakedNotifier confirmedNotifiers []LatestConfirmedNotifier activeChallenge *ChallengeManager @@ -277,7 +278,7 @@ type ValidatorWalletInterface interface { } func NewStaker( - l1Reader L1ReaderInterface, + l1Reader *headerreader.HeaderReader, wallet ValidatorWalletInterface, callOpts bind.CallOpts, config L1ValidatorConfig, diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index c4968ca9e..acd86f862 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -19,7 +19,6 @@ import ( "github.com/offchainlabs/nitro/validator" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" @@ -71,13 +70,6 @@ type InboxReaderInterface interface { GetSequencerMessageBytes(ctx context.Context, seqNum uint64) ([]byte, error) } -type L1ReaderInterface interface { - Client() arbutil.L1Interface - Subscribe(bool) (<-chan *types.Header, func()) - WaitForTxApproval(ctx context.Context, tx *types.Transaction) (*types.Receipt, error) - UseFinalityData() bool -} - type GlobalStatePosition struct { BatchNumber uint64 PosInBatch uint64 diff --git a/staker/validatorwallet/contract.go b/staker/validatorwallet/contract.go index 302e4fb43..774e9ab40 100644 --- a/staker/validatorwallet/contract.go +++ b/staker/validatorwallet/contract.go @@ -400,19 +400,12 @@ func (b *Contract) DataPoster() *dataposter.DataPoster { return b.dataPoster } -type L1ReaderInterface interface { - Client() arbutil.L1Interface - Subscribe(bool) (<-chan *types.Header, func()) - WaitForTxApproval(ctx context.Context, tx *types.Transaction) (*types.Receipt, error) - UseFinalityData() bool -} - func GetValidatorWalletContract( ctx context.Context, validatorWalletFactoryAddr common.Address, fromBlock int64, transactAuth *bind.TransactOpts, - l1Reader L1ReaderInterface, + l1Reader *headerreader.HeaderReader, createIfMissing bool, ) (*common.Address, error) { client := l1Reader.Client() From 03725c0c370a4ee1ab6be3abc1175bdc7b234c73 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 17 Nov 2023 18:03:51 -0700 Subject: [PATCH 400/775] deploy: test all transactions --- deploy/deploy.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/deploy.go b/deploy/deploy.go index abdf4c06b..bd2f2ec32 100644 --- a/deploy/deploy.go +++ b/deploy/deploy.go @@ -122,19 +122,19 @@ func deployChallengeFactory(ctx context.Context, l1Reader *headerreader.HeaderRe return common.Address{}, common.Address{}, fmt.Errorf("osp0 deploy error: %w", err) } - ospMem, _, _, err := ospgen.DeployOneStepProverMemory(auth, client) + ospMem, tx, _, err := ospgen.DeployOneStepProverMemory(auth, client) err = andTxSucceeded(ctx, l1Reader, tx, err) if err != nil { return common.Address{}, common.Address{}, fmt.Errorf("ospMemory deploy error: %w", err) } - ospMath, _, _, err := ospgen.DeployOneStepProverMath(auth, client) + ospMath, tx, _, err := ospgen.DeployOneStepProverMath(auth, client) err = andTxSucceeded(ctx, l1Reader, tx, err) if err != nil { return common.Address{}, common.Address{}, fmt.Errorf("ospMath deploy error: %w", err) } - ospHostIo, _, _, err := ospgen.DeployOneStepProverHostIo(auth, client) + ospHostIo, tx, _, err := ospgen.DeployOneStepProverHostIo(auth, client) err = andTxSucceeded(ctx, l1Reader, tx, err) if err != nil { return common.Address{}, common.Address{}, fmt.Errorf("ospHostIo deploy error: %w", err) From ee65d7fdec958dfce67fd60ac0cc0074abd1979b Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 17 Nov 2023 18:05:03 -0700 Subject: [PATCH 401/775] gethexec: fix test headerreader configs --- execution/gethexec/node.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 5a99d59c5..a29adbdb6 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -99,7 +99,7 @@ var ConfigDefault = Config{ func ConfigDefaultNonSequencerTest() *Config { config := ConfigDefault - config.ParentChainReader = headerreader.Config{} + config.ParentChainReader = headerreader.TestConfig config.Sequencer.Enable = false config.Forwarder = DefaultTestForwarderConfig config.ForwardingTarget = "null" @@ -111,7 +111,6 @@ func ConfigDefaultNonSequencerTest() *Config { func ConfigDefaultTest() *Config { config := ConfigDefault - config.ParentChainReader = headerreader.Config{} config.Sequencer = TestSequencerConfig config.ForwardingTarget = "null" config.ParentChainReader = headerreader.TestConfig From b9c715823bb9752f62fff15fabe3044aac9f12be Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 17 Nov 2023 18:08:54 -0700 Subject: [PATCH 402/775] headerreader: in tests, wait for block to become safe In tests all blocks are marked safe as published immediately but not atomically, which creates some race conditions. Avoid race conditions by only considering blocks published if consensus saw them. --- util/headerreader/header_reader.go | 86 +++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 19 deletions(-) diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index ff3b420a1..678c3099f 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -55,13 +55,18 @@ type cachedHeader struct { } type Config struct { - Enable bool `koanf:"enable"` - PollOnly bool `koanf:"poll-only" reload:"hot"` - PollInterval time.Duration `koanf:"poll-interval" reload:"hot"` - SubscribeErrInterval time.Duration `koanf:"subscribe-err-interval" reload:"hot"` - TxTimeout time.Duration `koanf:"tx-timeout" reload:"hot"` - OldHeaderTimeout time.Duration `koanf:"old-header-timeout" reload:"hot"` - UseFinalityData bool `koanf:"use-finality-data" reload:"hot"` + Enable bool `koanf:"enable"` + PollOnly bool `koanf:"poll-only" reload:"hot"` + PollInterval time.Duration `koanf:"poll-interval" reload:"hot"` + SubscribeErrInterval time.Duration `koanf:"subscribe-err-interval" reload:"hot"` + TxTimeout time.Duration `koanf:"tx-timeout" reload:"hot"` + OldHeaderTimeout time.Duration `koanf:"old-header-timeout" reload:"hot"` + UseFinalityData bool `koanf:"use-finality-data" reload:"hot"` + Dangerous DangerousConfig `koanf:"dangerous"` +} + +type DangerousConfig struct { + WaitForTxApprovalSafePoll time.Duration `koanf:"wait-for-tx-approval-safe-poll"` } type ConfigFetcher func() *Config @@ -74,6 +79,9 @@ var DefaultConfig = Config{ TxTimeout: 5 * time.Minute, OldHeaderTimeout: 5 * time.Minute, UseFinalityData: true, + Dangerous: DangerousConfig{ + WaitForTxApprovalSafePoll: 0, + }, } func AddOptions(prefix string, f *flag.FlagSet) { @@ -84,6 +92,11 @@ func AddOptions(prefix string, f *flag.FlagSet) { f.Duration(prefix+".subscribe-err-interval", DefaultConfig.SubscribeErrInterval, "interval for subscribe error") f.Duration(prefix+".tx-timeout", DefaultConfig.TxTimeout, "timeout when waiting for a transaction") f.Duration(prefix+".old-header-timeout", DefaultConfig.OldHeaderTimeout, "warns if the latest l1 block is at least this old") + AddDangerousOptions(prefix+".dangerous", f) +} + +func AddDangerousOptions(prefix string, f *flag.FlagSet) { + f.Duration(prefix+".wait-for-tx-approval-safe-poll", DefaultConfig.Dangerous.WaitForTxApprovalSafePoll, "Dangerous! only meant to be used by system tests") } var TestConfig = Config{ @@ -93,6 +106,9 @@ var TestConfig = Config{ TxTimeout: time.Second * 5, OldHeaderTimeout: 5 * time.Minute, UseFinalityData: false, + Dangerous: DangerousConfig{ + WaitForTxApprovalSafePoll: time.Millisecond * 100, + }, } func New(ctx context.Context, client arbutil.L1Interface, config ConfigFetcher, arbSysPrecompile ArbSysInterface) (*HeaderReader, error) { @@ -120,6 +136,8 @@ func New(ctx context.Context, client arbutil.L1Interface, config ConfigFetcher, }, nil } +func (s *HeaderReader) Config() *Config { return s.config() } + // Subscribe to block header updates. // Subscribers are notified when there is a change. // Channel could be missing headers and have duplicates. @@ -328,22 +346,52 @@ func (s *HeaderReader) WaitForTxApproval(ctxIn context.Context, tx *types.Transa ctx, cancel := context.WithTimeout(ctxIn, s.config().TxTimeout) defer cancel() txHash := tx.Hash() + waitForBlock := false + waitForSafePoll := s.config().Dangerous.WaitForTxApprovalSafePoll for { - receipt, err := s.client.TransactionReceipt(ctx, txHash) - if err == nil && receipt.BlockNumber.IsUint64() { - receiptBlockNr := receipt.BlockNumber.Uint64() - callBlockNr := s.LastPendingCallBlockNr() - if callBlockNr > receiptBlockNr { - return receipt, arbutil.DetailTxError(ctx, s.client, tx, receipt) + if waitForBlock { + select { + case _, ok := <-headerchan: + if !ok { + return nil, fmt.Errorf("waiting for %v: channel closed", txHash) + } + case <-ctx.Done(): + return nil, ctx.Err() } } - select { - case _, ok := <-headerchan: - if !ok { - return nil, fmt.Errorf("waiting for %v: channel closed", txHash) + waitForBlock = true + receipt, err := s.client.TransactionReceipt(ctx, txHash) + if err != nil || receipt == nil { + continue + } + if !receipt.BlockNumber.IsUint64() { + continue + } + receiptBlockNr := receipt.BlockNumber.Uint64() + callBlockNr := s.LastPendingCallBlockNr() + if callBlockNr <= receiptBlockNr { + continue + } + if waitForSafePoll != 0 { + safeBlock, err := s.client.BlockByNumber(ctx, big.NewInt(int64(rpc.SafeBlockNumber))) + if err != nil || safeBlock == nil { + log.Warn("parent chain: failed getting safeblock", "err", err) + continue } - case <-ctx.Done(): - return nil, ctx.Err() + if safeBlock.NumberU64() < receiptBlockNr { + log.Info("parent chain: waiting for safe block (see wait-for-tx-approval-safe-poll)", "waiting", receiptBlockNr, "safe", safeBlock.NumberU64()) + select { + case <-time.After(time.Millisecond * 100): + case <-ctx.Done(): + return nil, ctx.Err() + } + waitForBlock = false + continue + } + } + block, err := s.client.BlockByHash(ctx, receipt.BlockHash) + if block != nil && err == nil { + return receipt, arbutil.DetailTxError(ctx, s.client, tx, receipt) } } } From 2f635b2cea98ce8924f457f2a1cef0aead0f0eb7 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 17 Nov 2023 18:10:31 -0700 Subject: [PATCH 403/775] system tests: EnsureWaTxSucceeds wait for safe blocks on l1 To avoid race conditions, make sure simulated consensus also saw the block. --- system_tests/wrap_transaction_test.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/system_tests/wrap_transaction_test.go b/system_tests/wrap_transaction_test.go index e4ce6a4bb..85cf01521 100644 --- a/system_tests/wrap_transaction_test.go +++ b/system_tests/wrap_transaction_test.go @@ -15,8 +15,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" + "github.com/offchainlabs/nitro/util/headerreader" ) func GetPendingBlockNumber(ctx context.Context, client arbutil.L1Interface) (*big.Int, error) { @@ -77,11 +79,27 @@ func EnsureTxSucceeded(ctx context.Context, client arbutil.L1Interface, tx *type } func EnsureTxSucceededWithTimeout(ctx context.Context, client arbutil.L1Interface, tx *types.Transaction, timeout time.Duration) (*types.Receipt, error) { - txRes, err := WaitForTx(ctx, client, tx.Hash(), timeout) + receipt, err := WaitForTx(ctx, client, tx.Hash(), timeout) if err != nil { return nil, fmt.Errorf("waitFoxTx (tx=%s) got: %w", tx.Hash().Hex(), err) } - return txRes, arbutil.DetailTxError(ctx, client, tx, txRes) + if receipt.Status == types.ReceiptStatusSuccessful && tx.ChainId().Cmp(simulatedChainID) == 0 { + for { + safeBlock, err := client.HeaderByNumber(ctx, big.NewInt(int64(rpc.SafeBlockNumber))) + if err != nil { + return receipt, err + } + if safeBlock.Number.Cmp(receipt.BlockNumber) >= 0 { + break + } + select { + case <-time.After(headerreader.TestConfig.Dangerous.WaitForTxApprovalSafePoll): + case <-ctx.Done(): + return receipt, ctx.Err() + } + } + } + return receipt, arbutil.DetailTxError(ctx, client, tx, receipt) } func headerSubscribeMainLoop(chanOut chan<- *types.Header, ctx context.Context, client ethereum.ChainReader) { From 6b42be964a7ff89f0508d6c06a2aac669b0f8a06 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 17 Nov 2023 18:11:34 -0700 Subject: [PATCH 404/775] full_challenge: use EnsureTxSuccess on the custom deployer make sure each transaction is received before moving forward. --- system_tests/full_challenge_impl_test.go | 45 ++++++++++++------------ 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index 98e776487..43ba6a056 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -42,30 +42,31 @@ import ( ) func DeployOneStepProofEntry(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) common.Address { - osp0, _, _, err := ospgen.DeployOneStepProver0(auth, client) - if err != nil { - Fatal(t, err) - } - ospMem, _, _, err := ospgen.DeployOneStepProverMemory(auth, client) - if err != nil { - Fatal(t, err) - } - ospMath, _, _, err := ospgen.DeployOneStepProverMath(auth, client) - if err != nil { - Fatal(t, err) - } - ospHostIo, _, _, err := ospgen.DeployOneStepProverHostIo(auth, client) - if err != nil { - Fatal(t, err) - } + osp0, tx, _, err := ospgen.DeployOneStepProver0(auth, client) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, client, tx) + Require(t, err) + + ospMem, tx, _, err := ospgen.DeployOneStepProverMemory(auth, client) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, client, tx) + Require(t, err) + + ospMath, tx, _, err := ospgen.DeployOneStepProverMath(auth, client) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, client, tx) + Require(t, err) + + ospHostIo, tx, _, err := ospgen.DeployOneStepProverHostIo(auth, client) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, client, tx) + Require(t, err) + ospEntry, tx, _, err := ospgen.DeployOneStepProofEntry(auth, client, osp0, ospMem, ospMath, ospHostIo) - if err != nil { - Fatal(t, err) - } + Require(t, err) _, err = EnsureTxSucceeded(ctx, client, tx) - if err != nil { - Fatal(t, err) - } + Require(t, err) + return ospEntry } From 174977e462d782cac7b7dd98d0d4714d3888cd40 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 20 Nov 2023 22:03:11 +0530 Subject: [PATCH 405/775] Add backup transaction forwarding URLs --- execution/gethexec/forwarder.go | 92 ++++++++++++++++++++++----------- execution/gethexec/node.go | 46 +++++++++-------- execution/gethexec/sequencer.go | 6 +-- 3 files changed, 90 insertions(+), 54 deletions(-) diff --git a/execution/gethexec/forwarder.go b/execution/gethexec/forwarder.go index 7dea24b41..c70342ed4 100644 --- a/execution/gethexec/forwarder.go +++ b/execution/gethexec/forwarder.go @@ -9,6 +9,7 @@ import ( "fmt" "net" "net/http" + "regexp" "sync" "sync/atomic" "time" @@ -79,19 +80,23 @@ func AddOptionsForForwarderConfigImpl(prefix string, defaultConfig *ForwarderCon } type TxForwarder struct { + ctx context.Context + enabled atomic.Bool - target string timeout time.Duration transport *http.Transport - rpcClient *rpc.Client - ethClient *ethclient.Client healthMutex sync.Mutex healthErr error healthChecked time.Time + + targets []string + rpcClients []*rpc.Client + ethClients []*ethclient.Client + tryNewForwarderErrors *regexp.Regexp } -func NewForwarder(target string, config *ForwarderConfig) *TxForwarder { +func NewForwarder(targets []string, config *ForwarderConfig) *TxForwarder { dialer := net.Dialer{ Timeout: 5 * time.Second, KeepAlive: 2 * time.Second, @@ -116,34 +121,45 @@ func NewForwarder(target string, config *ForwarderConfig) *TxForwarder { ExpectContinueTimeout: 1 * time.Second, } return &TxForwarder{ - target: target, - timeout: config.ConnectionTimeout, - transport: transport, + targets: targets, + timeout: config.ConnectionTimeout, + transport: transport, + tryNewForwarderErrors: regexp.MustCompile(`(?i)(http:|json:|.*Timeout exceeded).*`), } } -func (f *TxForwarder) ctxWithTimeout(inctx context.Context) (context.Context, context.CancelFunc) { +func (f *TxForwarder) ctxWithTimeout() (context.Context, context.CancelFunc) { if f.timeout == time.Duration(0) { - return context.WithCancel(inctx) + return context.WithCancel(f.ctx) } - return context.WithTimeout(inctx, f.timeout) + return context.WithTimeout(f.ctx, f.timeout) } func (f *TxForwarder) PublishTransaction(inctx context.Context, tx *types.Transaction, options *arbitrum_types.ConditionalOptions) error { if !f.enabled.Load() { return ErrNoSequencer } - ctx, cancelFunc := f.ctxWithTimeout(inctx) + ctx, cancelFunc := f.ctxWithTimeout() defer cancelFunc() - if options == nil { - return f.ethClient.SendTransaction(ctx, tx) + for pos, rpcClient := range f.rpcClients { + var err error + if options == nil { + err = f.ethClients[pos].SendTransaction(ctx, tx) + } else { + err = arbitrum.SendConditionalTransactionRPC(ctx, rpcClient, tx, options) + } + if err == nil || !f.tryNewForwarderErrors.MatchString(err.Error()) { + return err + } + log.Info("error forwarding transaction to a backup target", "target", f.targets[pos], "err", err) } - return arbitrum.SendConditionalTransactionRPC(ctx, f.rpcClient, tx, options) + return errors.New("failed to publish transaction to any of the forwarding targets") } const cacheUpstreamHealth = 2 * time.Second const maxHealthTimeout = 10 * time.Second +// CheckHealth returns health of the highest priority forwarding target func (f *TxForwarder) CheckHealth(inctx context.Context) error { if !f.enabled.Load() { return ErrNoSequencer @@ -157,28 +173,44 @@ func (f *TxForwarder) CheckHealth(inctx context.Context) error { } ctx, cancelFunc := context.WithTimeout(context.Background(), timeout) defer cancelFunc() - f.healthErr = f.rpcClient.CallContext(ctx, nil, "arb_checkPublisherHealth") + f.healthErr = f.rpcClients[0].CallContext(ctx, nil, "arb_checkPublisherHealth") f.healthChecked = time.Now() } return f.healthErr } func (f *TxForwarder) Initialize(inctx context.Context) error { - if f.target == "" { - f.rpcClient = nil - f.ethClient = nil - f.enabled.Store(false) - return nil + if f.ctx == nil { + f.ctx = inctx + } + + pos := 0 + for pos < len(f.targets) { + if f.targets[pos] == "" { + f.targets = append(f.targets[:pos], f.targets[pos+1:]...) + } else { + pos += 1 + } } - ctx, cancelFunc := f.ctxWithTimeout(inctx) + + ctx, cancelFunc := f.ctxWithTimeout() defer cancelFunc() - rpcClient, err := rpc.DialTransport(ctx, f.target, f.transport) - if err != nil { - return err + pos = 0 + for pos < len(f.targets) { + rpcClient, err := rpc.DialTransport(ctx, f.targets[pos], f.transport) + if err != nil { + log.Warn("error initializing a forwarding client in txForwarder", "forwarding url", f.targets[pos], "err", err) + f.targets = append(f.targets[:pos], f.targets[pos+1:]...) + continue + } + ethClient := ethclient.NewClient(rpcClient) + f.rpcClients = append(f.rpcClients, rpcClient) + f.ethClients = append(f.ethClients, ethClient) + pos += 1 + } + if len(f.rpcClients) > 0 { + f.enabled.Store(true) } - f.rpcClient = rpcClient - f.ethClient = ethclient.NewClient(rpcClient) - f.enabled.Store(true) return nil } @@ -192,8 +224,8 @@ func (f *TxForwarder) Start(ctx context.Context) error { } func (f *TxForwarder) StopAndWait() { - if f.ethClient != nil { - f.ethClient.Close() // internally closes also the rpc client + for _, ethClient := range f.ethClients { + ethClient.Close() // internally closes also the rpc client } } @@ -346,7 +378,7 @@ func (f *RedisTxForwarder) update(ctx context.Context) time.Duration { } var newForwarder *TxForwarder for { - newForwarder = NewForwarder(newSequencerUrl, f.config) + newForwarder = NewForwarder([]string{newSequencerUrl}, f.config) err := newForwarder.Initialize(ctx) if err == nil { break diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 5a99d59c5..29cb32245 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -39,16 +39,17 @@ func DangerousConfigAddOptions(prefix string, f *flag.FlagSet) { } type Config struct { - ParentChainReader headerreader.Config `koanf:"parent-chain-reader" reload:"hot"` - Sequencer SequencerConfig `koanf:"sequencer" reload:"hot"` - RecordingDatabase arbitrum.RecordingDatabaseConfig `koanf:"recording-database"` - TxPreChecker TxPreCheckerConfig `koanf:"tx-pre-checker" reload:"hot"` - Forwarder ForwarderConfig `koanf:"forwarder"` - ForwardingTarget string `koanf:"forwarding-target"` - Caching CachingConfig `koanf:"caching"` - RPC arbitrum.Config `koanf:"rpc"` - TxLookupLimit uint64 `koanf:"tx-lookup-limit"` - Dangerous DangerousConfig `koanf:"dangerous"` + ParentChainReader headerreader.Config `koanf:"parent-chain-reader" reload:"hot"` + Sequencer SequencerConfig `koanf:"sequencer" reload:"hot"` + RecordingDatabase arbitrum.RecordingDatabaseConfig `koanf:"recording-database"` + TxPreChecker TxPreCheckerConfig `koanf:"tx-pre-checker" reload:"hot"` + Forwarder ForwarderConfig `koanf:"forwarder"` + ForwardingTarget string `koanf:"forwarding-target"` + SecondaryForwardingTarget []string `koanf:"secondary-forwarding-target"` + Caching CachingConfig `koanf:"caching"` + RPC arbitrum.Config `koanf:"rpc"` + TxLookupLimit uint64 `koanf:"tx-lookup-limit"` + Dangerous DangerousConfig `koanf:"dangerous"` forwardingTarget string } @@ -77,6 +78,7 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { headerreader.AddOptions(prefix+".parent-chain-reader", f) arbitrum.RecordingDatabaseConfigAddOptions(prefix+".recording-database", f) f.String(prefix+".forwarding-target", ConfigDefault.ForwardingTarget, "transaction forwarding target URL, or \"null\" to disable forwarding (iff not sequencer)") + f.StringSlice(prefix+".secondary-forwarding-target", ConfigDefault.SecondaryForwardingTarget, "secondary transaction forwarding target URL") AddOptionsForNodeForwarderConfig(prefix+".forwarder", f) TxPreCheckerConfigAddOptions(prefix+".tx-pre-checker", f) CachingConfigAddOptions(prefix+".caching", f) @@ -85,16 +87,17 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { } var ConfigDefault = Config{ - RPC: arbitrum.DefaultConfig, - Sequencer: DefaultSequencerConfig, - ParentChainReader: headerreader.DefaultConfig, - RecordingDatabase: arbitrum.DefaultRecordingDatabaseConfig, - ForwardingTarget: "", - TxPreChecker: DefaultTxPreCheckerConfig, - TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second - Caching: DefaultCachingConfig, - Dangerous: DefaultDangerousConfig, - Forwarder: DefaultNodeForwarderConfig, + RPC: arbitrum.DefaultConfig, + Sequencer: DefaultSequencerConfig, + ParentChainReader: headerreader.DefaultConfig, + RecordingDatabase: arbitrum.DefaultRecordingDatabaseConfig, + ForwardingTarget: "", + SecondaryForwardingTarget: []string{}, + TxPreChecker: DefaultTxPreCheckerConfig, + TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second + Caching: DefaultCachingConfig, + Dangerous: DefaultDangerousConfig, + Forwarder: DefaultNodeForwarderConfig, } func ConfigDefaultNonSequencerTest() *Config { @@ -176,7 +179,8 @@ func CreateExecutionNode( } else if config.forwardingTarget == "" { txPublisher = NewTxDropper() } else { - txPublisher = NewForwarder(config.forwardingTarget, &config.Forwarder) + targets := append([]string{config.forwardingTarget}, config.SecondaryForwardingTarget...) + txPublisher = NewForwarder(targets, &config.Forwarder) } } diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index e1b55b6ce..377d5a045 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -489,20 +489,20 @@ func (s *Sequencer) ForwardTarget() string { if s.forwarder == nil { return "" } - return s.forwarder.target + return s.forwarder.targets[0] } func (s *Sequencer) ForwardTo(url string) error { s.activeMutex.Lock() defer s.activeMutex.Unlock() if s.forwarder != nil { - if s.forwarder.target == url { + if s.forwarder.targets[0] == url { log.Warn("attempted to update sequencer forward target with existing target", "url", url) return nil } s.forwarder.Disable() } - s.forwarder = NewForwarder(url, &s.config().Forwarder) + s.forwarder = NewForwarder([]string{url}, &s.config().Forwarder) err := s.forwarder.Initialize(s.GetContext()) if err != nil { log.Error("failed to set forward agent", "err", err) From fa138006f46f682ddfeaea25f18b85459860c27d Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 20 Nov 2023 17:09:06 -0700 Subject: [PATCH 406/775] Add a regression test for the empty retryable escrow account --- go-ethereum | 2 +- go.mod | 8 ++-- go.sum | 16 +++---- system_tests/retryable_test.go | 83 +++++++++++++++++++++++++++++++++- 4 files changed, 95 insertions(+), 14 deletions(-) diff --git a/go-ethereum b/go-ethereum index be1fd29a2..d8932299a 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit be1fd29a26173eae9008c33280b2942a86a4b0fc +Subproject commit d8932299a0a87e870f3a13284b87a91adca6924c diff --git a/go.mod b/go.mod index 49f37c074..c917d0da3 100644 --- a/go.mod +++ b/go.mod @@ -99,7 +99,7 @@ require ( github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/ethereum/c-kzg-4844 v0.3.0 // indirect + github.com/ethereum/c-kzg-4844 v0.3.1 // indirect github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect @@ -248,7 +248,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/samber/lo v1.36.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/supranational/blst v0.3.11-0.20230406105308-e9dfc5ee724b // indirect + github.com/supranational/blst v0.3.11 // indirect github.com/urfave/cli/v2 v2.24.1 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect @@ -277,8 +277,8 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.24.0 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect - golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect - golang.org/x/mod v0.10.0 // indirect + golang.org/x/exp v0.0.0-20230810033253-352e893a4cad // indirect + golang.org/x/mod v0.11.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sync v0.3.0 // indirect golang.org/x/text v0.13.0 // indirect diff --git a/go.sum b/go.sum index bb8d6f77f..a8eacfefb 100644 --- a/go.sum +++ b/go.sum @@ -334,8 +334,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum/c-kzg-4844 v0.3.0 h1:3Y3hD6l5i0dEYsBL50C+Om644kve3pNqoAcvE26o9zI= -github.com/ethereum/c-kzg-4844 v0.3.0/go.mod h1:WI2Nd82DMZAAZI1wV2neKGost9EKjvbpQR9OqE5Qqa8= +github.com/ethereum/c-kzg-4844 v0.3.1 h1:sR65+68+WdnMKxseNWxSJuAv2tsUrihTpVBTfM/U5Zg= +github.com/ethereum/c-kzg-4844 v0.3.1/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= @@ -1589,8 +1589,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/supranational/blst v0.3.11-0.20230406105308-e9dfc5ee724b h1:u49mjRnygnB34h8OKbnNJFVUtWSKIKb1KukdV8bILUM= -github.com/supranational/blst v0.3.11-0.20230406105308-e9dfc5ee724b/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= @@ -1798,8 +1798,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20230810033253-352e893a4cad h1:g0bG7Z4uG+OgH2QDODnjp6ggkk1bJDsINcuWmJN1iJU= +golang.org/x/exp v0.0.0-20230810033253-352e893a4cad/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1824,8 +1824,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 3400af335..461967170 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -191,11 +191,92 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { l2balance, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) - if !arbmath.BigEquals(l2balance, big.NewInt(1e6)) { + if !arbmath.BigEquals(l2balance, callValue) { Fatal(t, "Unexpected balance:", l2balance) } } +func TestSubmitRetryableEmptyEscrow(t *testing.T) { + t.Parallel() + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + defer teardown() + + user2Address := builder.L2Info.GetAddress("User2") + beneficiaryAddress := builder.L2Info.GetAddress("Beneficiary") + + deposit := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) + callValue := common.Big0 + + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, builder.L2.Client) + Require(t, err, "failed to deploy NodeInterface") + + // estimate the gas needed to auto redeem the retryable + usertxoptsL2 := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL2.NoSend = true + usertxoptsL2.GasMargin = 0 + tx, err := nodeInterface.EstimateRetryableTicket( + &usertxoptsL2, + usertxoptsL2.From, + deposit, + user2Address, + callValue, + beneficiaryAddress, + beneficiaryAddress, + []byte{0x32, 0x42, 0x32, 0x88}, // increase the cost to beyond that of params.TxGas + ) + Require(t, err, "failed to estimate retryable submission") + estimate := tx.Gas() + colors.PrintBlue("estimate: ", estimate) + + // submit & auto redeem the retryable using the gas estimate + usertxoptsL1 := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL1.Value = deposit + l1tx, err := delayedInbox.CreateRetryableTicket( + &usertxoptsL1, + user2Address, + callValue, + big.NewInt(1e16), + beneficiaryAddress, + beneficiaryAddress, + arbmath.UintToBig(estimate), + big.NewInt(l2pricing.InitialBaseFeeWei*2), + []byte{0x32, 0x42, 0x32, 0x88}, + ) + Require(t, err) + + l1Receipt, err := builder.L1.EnsureTxSucceeded(l1tx) + Require(t, err) + if l1Receipt.Status != types.ReceiptStatusSuccessful { + Fatal(t, "l1Receipt indicated failure") + } + + waitForL1DelayBlocks(t, ctx, builder) + + l2Tx := lookupL2Tx(l1Receipt) + receipt, err := builder.L2.EnsureTxSucceeded(l2Tx) + Require(t, err) + if receipt.Status != types.ReceiptStatusSuccessful { + Fatal(t) + } + + l2balance, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) + Require(t, err) + + if !arbmath.BigEquals(l2balance, callValue) { + Fatal(t, "Unexpected balance:", l2balance) + } + + escrowAccount := retryables.RetryableEscrowAddress(l2Tx.Hash()) + state, err := builder.L2.ExecNode.ArbInterface.BlockChain().State() + Require(t, err) + escrowCodeHash := state.GetCodeHash(escrowAccount) + if escrowCodeHash == (common.Hash{}) { + Fatal(t, "Escrow account deleted (or not created)") + } else if escrowCodeHash != types.EmptyCodeHash { + Fatal(t, "Escrow account has unexpected code hash", escrowCodeHash) + } +} + func TestSubmitRetryableFailThenRetry(t *testing.T) { t.Parallel() builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) From 786221872d2adfcb4ed33bf38371b5cbe7c7e8c5 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 20 Nov 2023 17:25:17 -0700 Subject: [PATCH 407/775] Bump geth pin --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index d8932299a..d8a45317f 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit d8932299a0a87e870f3a13284b87a91adca6924c +Subproject commit d8a45317fba1d2ae99cbb2da4d2f651d0666bda0 From 94867c6a15f22285fdc14a8acf58fc5c254bc670 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Mon, 20 Nov 2023 17:56:46 -0700 Subject: [PATCH 408/775] don't re-request parent block if same block as previous block `logsToDeliveredMessages` was requesting parent block for every single parsedLog even if the previous parsedLog had the same block number, causing lots of duplicate requests. --- arbnode/delayed.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/arbnode/delayed.go b/arbnode/delayed.go index f2c3d6200..51b22c58b 100644 --- a/arbnode/delayed.go +++ b/arbnode/delayed.go @@ -184,6 +184,8 @@ func (b *DelayedBridge) logsToDeliveredMessages(ctx context.Context, logs []type } messages := make([]*DelayedInboxMessage, 0, len(logs)) + var lastParentChainBlockNumber uint64 + var lastL1BlockNumber uint64 for _, parsedLog := range parsedLogs { msgKey := common.BigToHash(parsedLog.MessageIndex) data, ok := messageData[msgKey] @@ -196,9 +198,17 @@ func (b *DelayedBridge) logsToDeliveredMessages(ctx context.Context, logs []type requestId := common.BigToHash(parsedLog.MessageIndex) parentChainBlockNumber := parsedLog.Raw.BlockNumber - l1BlockNumber, err := arbutil.CorrespondingL1BlockNumber(ctx, b.client, parentChainBlockNumber) - if err != nil { - return nil, err + var l1BlockNumber uint64 + if lastParentChainBlockNumber == parentChainBlockNumber && lastParentChainBlockNumber > 0 { + l1BlockNumber = lastL1BlockNumber + } else { + var err error + l1BlockNumber, err = arbutil.CorrespondingL1BlockNumber(ctx, b.client, parentChainBlockNumber) + if err != nil { + return nil, err + } + lastParentChainBlockNumber = parentChainBlockNumber + lastL1BlockNumber = l1BlockNumber } msg := &DelayedInboxMessage{ BlockHash: parsedLog.Raw.BlockHash, @@ -216,7 +226,7 @@ func (b *DelayedBridge) logsToDeliveredMessages(ctx context.Context, logs []type }, ParentChainBlockNumber: parsedLog.Raw.BlockNumber, } - err = msg.Message.FillInBatchGasCost(batchFetcher) + err := msg.Message.FillInBatchGasCost(batchFetcher) if err != nil { return nil, err } From ba1f54d93461c11863e242eeabe02fb9b20f938a Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 21 Nov 2023 10:25:17 +0530 Subject: [PATCH 409/775] regex should include errNoSuchHost from net and i/0.* errors --- execution/gethexec/forwarder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execution/gethexec/forwarder.go b/execution/gethexec/forwarder.go index c70342ed4..39a8a96e2 100644 --- a/execution/gethexec/forwarder.go +++ b/execution/gethexec/forwarder.go @@ -124,7 +124,7 @@ func NewForwarder(targets []string, config *ForwarderConfig) *TxForwarder { targets: targets, timeout: config.ConnectionTimeout, transport: transport, - tryNewForwarderErrors: regexp.MustCompile(`(?i)(http:|json:|.*Timeout exceeded).*`), + tryNewForwarderErrors: regexp.MustCompile(`(?i)(^http:|^json:|^i/0|timeout exceeded|no such host)`), } } From cab414fe73794f1fe3709ca3e8b60acfa09d955e Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 21 Nov 2023 09:07:19 -0700 Subject: [PATCH 410/775] Bump geth submodule pin --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index d8a45317f..f5328d1ab 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit d8a45317fba1d2ae99cbb2da4d2f651d0666bda0 +Subproject commit f5328d1abc2f5e4f25cabf9a1345a57f8c10f0f6 From e5b62f3cda7b9fd8cf339ad94fd9bf3b772f91e6 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 21 Nov 2023 22:06:14 +0530 Subject: [PATCH 411/775] Prioritize reading messages from primary feeds over secondaries --- broadcastclients/broadcastclients.go | 56 +++++++++++++++------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index b2824221e..7fe6ca489 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -170,45 +170,49 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { bcs.primaryRouter.forwardConfirmationChan <- cs } - // Secondary Feeds - case msg := <-bcs.secondaryRouter.messageChan: - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) - if _, ok := recentFeedItemsNew[msg.SequenceNumber]; ok { - continue - } - if _, ok := recentFeedItemsOld[msg.SequenceNumber]; ok { - continue - } - recentFeedItemsNew[msg.SequenceNumber] = time.Now() - if err := bcs.secondaryRouter.forwardTxStreamer.AddBroadcastMessages([]*broadcaster.BroadcastFeedMessage{&msg}); err != nil { - log.Error("Error routing message from Secondary Sequencer Feeds", "err", err) - } - case cs := <-bcs.secondaryRouter.confirmedSequenceNumberChan: - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) - if cs == lastConfirmed { - continue - } - lastConfirmed = cs - if bcs.secondaryRouter.forwardConfirmationChan != nil { - bcs.secondaryRouter.forwardConfirmationChan <- cs - } - // Cycle buckets to get rid of old entries case <-recentFeedItemsCleanup.C: recentFeedItemsOld = recentFeedItemsNew recentFeedItemsNew = make(map[arbutil.MessageIndex]time.Time, RECENT_FEED_INITIAL_MAP_SIZE) - // failed to get messages from both primary and secondary feeds for ~5 seconds, start a new secondary feed + // Failed to get messages from both primary and secondary feeds for ~5 seconds, start a new secondary feed case <-startSecondaryFeedTimer.C: bcs.startSecondaryFeed(ctx) - // failed to get messages from primary feed for ~5 seconds, reset the timer responsible for stopping a secondary + // Failed to get messages from primary feed for ~5 seconds, reset the timer responsible for stopping a secondary case <-primaryFeedIsDownTimer.C: stopSecondaryFeedTimer.Reset(PRIMARY_FEED_UPTIME) - // primary feeds have been up and running for PRIMARY_FEED_UPTIME=10 mins without a failure, stop the recently started secondary feed + // Primary feeds have been up and running for PRIMARY_FEED_UPTIME=10 mins without a failure, stop the recently started secondary feed case <-stopSecondaryFeedTimer.C: bcs.stopSecondaryFeed() + + default: + select { + // Secondary Feeds + case msg := <-bcs.secondaryRouter.messageChan: + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + if _, ok := recentFeedItemsNew[msg.SequenceNumber]; ok { + continue + } + if _, ok := recentFeedItemsOld[msg.SequenceNumber]; ok { + continue + } + recentFeedItemsNew[msg.SequenceNumber] = time.Now() + if err := bcs.secondaryRouter.forwardTxStreamer.AddBroadcastMessages([]*broadcaster.BroadcastFeedMessage{&msg}); err != nil { + log.Error("Error routing message from Secondary Sequencer Feeds", "err", err) + } + case cs := <-bcs.secondaryRouter.confirmedSequenceNumberChan: + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + if cs == lastConfirmed { + continue + } + lastConfirmed = cs + if bcs.secondaryRouter.forwardConfirmationChan != nil { + bcs.secondaryRouter.forwardConfirmationChan <- cs + } + default: + } } } }) From 7846c07d11c337dd8eaed37788ab8c3674590611 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 21 Nov 2023 10:33:04 -0700 Subject: [PATCH 412/775] Add a test of contract deployment with extended contract sizes --- system_tests/common_test.go | 6 +- system_tests/deployment_test.go | 143 ++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 system_tests/deployment_test.go diff --git a/system_tests/common_test.go b/system_tests/common_test.go index b0074a268..7752fbd34 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -189,7 +189,7 @@ func (b *NodeBuilder) Build(t *testing.T) func() { } else { l2 := NewTestClient(b.ctx) b.L2Info, l2.ConsensusNode, l2.Client = - createTestNode(t, b.ctx, b.L2Info, b.nodeConfig, b.execConfig, b.takeOwnership) + createTestNode(t, b.ctx, b.L2Info, b.nodeConfig, b.execConfig, b.chainConfig, b.takeOwnership) b.L2 = l2 } b.L2.ExecNode = getExecNode(t, b.L2.ConsensusNode) @@ -801,7 +801,7 @@ func createTestNodeWithL1( // L2 -Only. Enough for tests that needs no interface to L1 // Requires precompiles.AllowDebugPrecompiles = true func createTestNode( - t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, execConfig *gethexec.Config, takeOwnership bool, + t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, execConfig *gethexec.Config, chainConfig *params.ChainConfig, takeOwnership bool, ) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { if nodeConfig == nil { nodeConfig = arbnode.ConfigDefaultL2Test() @@ -814,7 +814,7 @@ func createTestNode( AddDefaultValNode(t, ctx, nodeConfig, true) - l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, l2Info, "", params.ArbitrumDevTestChainConfig(), &execConfig.Caching) + l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, l2Info, "", chainConfig, &execConfig.Caching) Require(t, execConfig.Validate()) execConfigFetcher := func() *gethexec.Config { return execConfig } diff --git a/system_tests/deployment_test.go b/system_tests/deployment_test.go new file mode 100644 index 000000000..a689abaa1 --- /dev/null +++ b/system_tests/deployment_test.go @@ -0,0 +1,143 @@ +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package arbtest + +import ( + "bytes" + "context" + "math/big" + "strings" + "testing" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/params" +) + +func testContractDeployment(t *testing.T, ctx context.Context, client *ethclient.Client, contractCode []byte, accountInfo *AccountInfo, expectedEstimateGasError error) { + // First, we need to make the "deploy code" which returns the contractCode to be deployed + deployCode := []byte{ + 0x7F, // PUSH32 + } + // len(contractCode) + deployCode = append(deployCode, math.U256Bytes(big.NewInt(int64(len(contractCode))))...) + var codeOffset byte = 42 + deployCode = append(deployCode, []byte{ + 0x80, // DUP + 0x60, codeOffset, // PUSH1 [codeOffset] + 0x60, 0x00, // PUSH1 0 + 0x39, // CODECOPY + 0x60, 0x00, // PUSH1 0 + 0xF3, // RETURN + }...) + if len(deployCode) != int(codeOffset) { + Fatal(t, "computed codeOffset", codeOffset, "incorrectly, should be", len(deployCode)) + } + deployCode = append(deployCode, contractCode...) + + deploymentGas, err := client.EstimateGas(ctx, ethereum.CallMsg{ + Data: deployCode, + }) + if expectedEstimateGasError != nil { + if err == nil { + Fatal(t, "missing expected contract deployment error", expectedEstimateGasError) + } else if strings.Contains(err.Error(), expectedEstimateGasError.Error()) { + // success + return + } + // else, fall through to Require, as this error is unexpected + } + Require(t, err) + + chainId, err := client.ChainID(ctx) + Require(t, err) + latestHeader, err := client.HeaderByNumber(ctx, nil) + Require(t, err) + nonce, err := client.PendingNonceAt(ctx, accountInfo.Address) + Require(t, err) + + tx := types.NewTx(&types.DynamicFeeTx{ + ChainID: chainId, + Nonce: nonce, + GasTipCap: common.Big0, + GasFeeCap: latestHeader.BaseFee, + Gas: deploymentGas, + To: nil, + Value: common.Big0, + Data: deployCode, + }) + tx, err = types.SignTx(tx, types.LatestSignerForChainID(chainId), accountInfo.PrivateKey) + Require(t, err) + + err = client.SendTransaction(ctx, tx) + Require(t, err) + receipt, err := EnsureTxSucceeded(ctx, client, tx) + Require(t, err) + + deployedCode, err := client.CodeAt(ctx, receipt.ContractAddress, receipt.BlockNumber) + Require(t, err) + if !bytes.Equal(deployedCode, contractCode) { + Fatal(t, "expected to deploy code of length", len(contractCode), "but got code of length", len(deployedCode)) + } + + callResult, err := client.CallContract(ctx, ethereum.CallMsg{To: &receipt.ContractAddress}, nil) + Require(t, err) + if len(callResult) > 0 { + Fatal(t, "somehow got a non-empty result from contract of", callResult) + } +} + +// Makes a contract which does nothing but takes up a given length +func makeContractOfLength(length int) []byte { + ret := make([]byte, length) + for i := 0; i < length; i++ { + if i%2 == 0 { + ret[i] = 0x58 // PC + } else { + ret[i] = 0x50 // POP + } + } + return ret +} + +func TestContractDeployment(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() + + account := builder.L2Info.GetInfoWithPrivKey("Faucet") + for _, size := range []int{0, 1, 1000, 20000, params.MaxCodeSize} { + testContractDeployment(t, ctx, builder.L2.Client, makeContractOfLength(size), account, nil) + } + + testContractDeployment(t, ctx, builder.L2.Client, makeContractOfLength(40000), account, vm.ErrMaxCodeSizeExceeded) + testContractDeployment(t, ctx, builder.L2.Client, makeContractOfLength(60000), account, core.ErrMaxInitCodeSizeExceeded) +} + +func TestExtendedContractDeployment(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.chainConfig.ArbitrumChainParams.MaxCodeSize = params.MaxCodeSize * 3 + builder.chainConfig.ArbitrumChainParams.MaxInitCodeSize = params.MaxInitCodeSize * 3 + cleanup := builder.Build(t) + defer cleanup() + + account := builder.L2Info.GetInfoWithPrivKey("Faucet") + for _, size := range []int{0, 1, 1000, 20000, 30000, 40000, 60000, params.MaxCodeSize * 3} { + testContractDeployment(t, ctx, builder.L2.Client, makeContractOfLength(size), account, nil) + } + + testContractDeployment(t, ctx, builder.L2.Client, makeContractOfLength(100000), account, vm.ErrMaxCodeSizeExceeded) + testContractDeployment(t, ctx, builder.L2.Client, makeContractOfLength(200000), account, core.ErrMaxInitCodeSizeExceeded) +} From 86445c5e4c62558f47c69757b712174bfaa0fee7 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 21 Nov 2023 11:09:40 -0700 Subject: [PATCH 413/775] Minimal fix to the unrelated U256Bytes race causing CI to fail --- arbnode/transaction_streamer.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 2ee1526ee..31e7751e5 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -531,7 +531,9 @@ func (s *TransactionStreamer) AddFakeInitMessage() error { if err != nil { return fmt.Errorf("failed to serialize chain config: %w", err) } - msg := append(append(math.U256Bytes(s.chainConfig.ChainID), 0), chainConfigJson...) + // TODO: once we have a safe U256Bytes that does a copy internally, use that instead of doing an explicit copy here + chainIdBytes := math.U256Bytes(new(big.Int).Set(s.chainConfig.ChainID)) + msg := append(append(chainIdBytes, 0), chainConfigJson...) return s.AddMessages(0, false, []arbostypes.MessageWithMetadata{{ Message: &arbostypes.L1IncomingMessage{ Header: &arbostypes.L1IncomingMessageHeader{ From 5fec2e618ebe758958dcd69f56986e1bb2f13dff Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 21 Nov 2023 15:21:26 -0700 Subject: [PATCH 414/775] Fix retryable scheduling gas usage --- arbos/arbostypes/incomingmessage.go | 2 ++ arbos/block_processor.go | 13 +++++++++++++ go-ethereum | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/arbos/arbostypes/incomingmessage.go b/arbos/arbostypes/incomingmessage.go index e9a5466d4..7810258d3 100644 --- a/arbos/arbostypes/incomingmessage.go +++ b/arbos/arbostypes/incomingmessage.go @@ -34,6 +34,8 @@ const ( const MaxL2MessageSize = 256 * 1024 +const ArbosVersion_FixRedeemGas = uint64(11) + type L1IncomingMessageHeader struct { Kind uint8 `json:"kind"` Poster common.Address `json:"sender"` diff --git a/arbos/block_processor.go b/arbos/block_processor.go index fbb4b58c0..5f8bf37c8 100644 --- a/arbos/block_processor.go +++ b/arbos/block_processor.go @@ -362,6 +362,19 @@ func ProduceBlockAdvanced( } txGasUsed := header.GasUsed - preTxHeaderGasUsed + arbosVer := types.DeserializeHeaderExtraInformation(header).ArbOSFormatVersion + if arbosVer >= arbostypes.ArbosVersion_FixRedeemGas { + // subtract gas burned for future use + for _, scheduledTx := range result.ScheduledTxes { + switch inner := scheduledTx.GetInner().(type) { + case *types.ArbitrumRetryTx: + txGasUsed = arbmath.SaturatingUSub(txGasUsed, inner.Gas) + default: + log.Warn("Unexpected type of scheduled tx", "type", scheduledTx.Type()) + } + } + } + // Update expectedTotalBalanceDelta (also done in logs loop) switch txInner := tx.GetInner().(type) { case *types.ArbitrumDepositTx: diff --git a/go-ethereum b/go-ethereum index 0461acc49..abe584818 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 0461acc49eae88ec137760f1d033f2dd2b4371f1 +Subproject commit abe584818e104dd5b4fdb8f60381a14eede896de From df93361a1293574903f28fbbbe0469a3ea5c644d Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 21 Nov 2023 21:37:53 -0700 Subject: [PATCH 415/775] Finalize ArbOS 11 --- arbos/arbosState/arbosstate.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arbos/arbosState/arbosstate.go b/arbos/arbosState/arbosstate.go index 48e29e121..b6913c34a 100644 --- a/arbos/arbosState/arbosstate.go +++ b/arbos/arbosState/arbosstate.go @@ -295,14 +295,6 @@ func (state *ArbosState) UpgradeArbosVersion( l1pricing.L1PricerFundsPoolAddress, ))) case 10: - if !chainConfig.DebugMode() { - // This upgrade isn't finalized so we only want to support it for testing - return fmt.Errorf( - "the chain is upgrading to unsupported ArbOS version %v, %w", - state.arbosVersion+1, - ErrFatalNodeOutOfDate, - ) - } // Update the PerBatchGasCost to a more accurate value compared to the old v6 default. ensure(state.l1PricingState.SetPerBatchGasCost(l1pricing.InitialPerBatchGasCostV12)) From de96b9a7d7fbd8697c58d32e949f5c3fb9aa8f0f Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 22 Nov 2023 11:57:51 +0530 Subject: [PATCH 416/775] address PR comments --- arbos/block_processor.go | 10 ++++++++-- arbos/extra_transaction_checks.go | 21 ++++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/arbos/block_processor.go b/arbos/block_processor.go index 928928627..7a6e9d8e6 100644 --- a/arbos/block_processor.go +++ b/arbos/block_processor.go @@ -269,6 +269,11 @@ func ProduceBlockAdvanced( return nil, nil, err } + // Additional pre-transaction validity check + if err = extraPreTxFilter(chainConfig, header, statedb, state, tx, options, sender, l1Info); err != nil { + return nil, nil, err + } + if basefee.Sign() > 0 { dataGas = math.MaxUint64 brotliCompressionLevel, err := state.BrotliCompressionLevel() @@ -327,8 +332,9 @@ func ProduceBlockAdvanced( return nil, nil, err } - // Additional transaction validity check - if err = extraTxFilter(chainConfig, header, statedb, state, tx, options, sender, l1Info, result); err != nil { + // Additional post-transaction validity check + if err = extraPostTxFilter(chainConfig, header, statedb, state, tx, options, sender, l1Info, result); err != nil { + statedb.RevertToSnapshot(snap) return nil, nil, err } diff --git a/arbos/extra_transaction_checks.go b/arbos/extra_transaction_checks.go index 758442c96..0f970c992 100644 --- a/arbos/extra_transaction_checks.go +++ b/arbos/extra_transaction_checks.go @@ -10,8 +10,23 @@ import ( "github.com/offchainlabs/nitro/arbos/arbosState" ) -// extraTxFilter should be modified by chain operators to enforce additional transaction validity rules -func extraTxFilter( +// extraPreTxFilter should be modified by chain operators to enforce additional pre-transaction validity rules +func extraPreTxFilter( + chainConfig *params.ChainConfig, + currentBlockHeader *types.Header, + statedb *state.StateDB, + state *arbosState.ArbosState, + tx *types.Transaction, + options *arbitrum_types.ConditionalOptions, + sender common.Address, + l1Info *L1Info, +) error { + // TODO: implement additional pre-transaction checks + return nil +} + +// extraPostTxFilter should be modified by chain operators to enforce additional post-transaction validity rules +func extraPostTxFilter( chainConfig *params.ChainConfig, currentBlockHeader *types.Header, statedb *state.StateDB, @@ -22,6 +37,6 @@ func extraTxFilter( l1Info *L1Info, result *core.ExecutionResult, ) error { - // TODO: implement additional checks + // TODO: implement additional post-transaction checks return nil } From e4121658a7751eed8b4636862099306acaa967d1 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 22 Nov 2023 19:30:03 +0530 Subject: [PATCH 417/775] Use U256Bytes from arbmath --- arbnode/delayed.go | 2 +- arbnode/inbox_test.go | 7 +++---- arbnode/transaction_streamer.go | 5 ++--- arbos/parse_l2.go | 7 +++---- precompiles/ArbSys.go | 7 +++---- staker/assertion.go | 7 ++++--- system_tests/contract_tx_test.go | 7 +++---- system_tests/deployment_test.go | 6 +++--- system_tests/reorg_resequencing_test.go | 5 +++-- util/arbmath/math.go | 12 ++++++++++++ 10 files changed, 37 insertions(+), 28 deletions(-) diff --git a/arbnode/delayed.go b/arbnode/delayed.go index 51b22c58b..498aa0475 100644 --- a/arbnode/delayed.go +++ b/arbnode/delayed.go @@ -117,7 +117,7 @@ func (m *DelayedInboxMessage) AfterInboxAcc() common.Hash { arbmath.UintToBytes(m.Message.Header.BlockNumber), arbmath.UintToBytes(m.Message.Header.Timestamp), m.Message.Header.RequestId.Bytes(), - math.U256Bytes(m.Message.Header.L1BaseFee), + arbmath.U256Bytes(m.Message.Header.L1BaseFee), crypto.Keccak256(m.Message.L2msg), ) return crypto.Keccak256Hash(m.BeforeInboxAcc[:], hash) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 3060ae2ae..92d216f76 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -21,7 +21,6 @@ import ( "github.com/offchainlabs/nitro/util/testhelpers" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" @@ -148,10 +147,10 @@ func TestTransactionStreamer(t *testing.T) { var gas uint64 = 100000 var l2Message []byte l2Message = append(l2Message, arbos.L2MessageKind_ContractTx) - l2Message = append(l2Message, math.U256Bytes(new(big.Int).SetUint64(gas))...) - l2Message = append(l2Message, math.U256Bytes(big.NewInt(l2pricing.InitialBaseFeeWei))...) + l2Message = append(l2Message, arbmath.Uint64ToU256Bytes(gas)...) + l2Message = append(l2Message, arbmath.Uint64ToU256Bytes(l2pricing.InitialBaseFeeWei)...) l2Message = append(l2Message, dest.Hash().Bytes()...) - l2Message = append(l2Message, math.U256Bytes(value)...) + l2Message = append(l2Message, arbmath.U256Bytes(value)...) var requestId common.Hash binary.BigEndian.PutUint64(requestId.Bytes()[:8], uint64(i)) messages = append(messages, arbostypes.MessageWithMetadata{ diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 31e7751e5..3cbad93c9 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -24,7 +24,6 @@ import ( "github.com/syndtr/goleveldb/leveldb" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -35,6 +34,7 @@ import ( "github.com/offchainlabs/nitro/broadcaster" "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/staker" + "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/sharedmetrics" "github.com/offchainlabs/nitro/util/stopwaiter" ) @@ -531,8 +531,7 @@ func (s *TransactionStreamer) AddFakeInitMessage() error { if err != nil { return fmt.Errorf("failed to serialize chain config: %w", err) } - // TODO: once we have a safe U256Bytes that does a copy internally, use that instead of doing an explicit copy here - chainIdBytes := math.U256Bytes(new(big.Int).Set(s.chainConfig.ChainID)) + chainIdBytes := arbmath.U256Bytes(s.chainConfig.ChainID) msg := append(append(chainIdBytes, 0), chainConfigJson...) return s.AddMessages(0, false, []arbostypes.MessageWithMetadata{{ Message: &arbostypes.L1IncomingMessage{ diff --git a/arbos/parse_l2.go b/arbos/parse_l2.go index e76781a6f..d2df3bdf8 100644 --- a/arbos/parse_l2.go +++ b/arbos/parse_l2.go @@ -9,7 +9,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" @@ -40,8 +39,8 @@ func ParseL2Transactions(msg *arbostypes.L1IncomingMessage, chainId *big.Int, ba return nil, errors.New("cannot issue L2 funded by L1 tx without L1 request id") } kind := msg.L2msg[0] - depositRequestId := crypto.Keccak256Hash(msg.Header.RequestId[:], math.U256Bytes(common.Big0)) - unsignedRequestId := crypto.Keccak256Hash(msg.Header.RequestId[:], math.U256Bytes(common.Big1)) + depositRequestId := crypto.Keccak256Hash(msg.Header.RequestId[:], arbmath.U256Bytes(common.Big0)) + unsignedRequestId := crypto.Keccak256Hash(msg.Header.RequestId[:], arbmath.U256Bytes(common.Big1)) tx, err := parseUnsignedTx(bytes.NewReader(msg.L2msg[1:]), msg.Header.Poster, &unsignedRequestId, chainId, kind) if err != nil { return nil, err @@ -146,7 +145,7 @@ func parseL2Message(rd io.Reader, poster common.Address, timestamp uint64, reque var nextRequestId *common.Hash if requestId != nil { - subRequestId := crypto.Keccak256Hash(requestId[:], math.U256Bytes(index)) + subRequestId := crypto.Keccak256Hash(requestId[:], arbmath.U256Bytes(index)) nextRequestId = &subRequestId } nestedSegments, err := parseL2Message(bytes.NewReader(nextMsg), poster, timestamp, nextRequestId, chainId, depth+1) diff --git a/precompiles/ArbSys.go b/precompiles/ArbSys.go index dc92baf44..0d3df3bbf 100644 --- a/precompiles/ArbSys.go +++ b/precompiles/ArbSys.go @@ -8,7 +8,6 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/vm" "github.com/offchainlabs/nitro/arbos/util" "github.com/offchainlabs/nitro/util/arbmath" @@ -121,9 +120,9 @@ func (con *ArbSys) SendTxToL1(c ctx, evm mech, value huge, destination addr, cal sendHash, err := arbosState.KeccakHash( c.caller.Bytes(), destination.Bytes(), - math.U256Bytes(evm.Context.BlockNumber), - math.U256Bytes(bigL1BlockNum), - math.U256Bytes(&t), + arbmath.U256Bytes(evm.Context.BlockNumber), + arbmath.U256Bytes(bigL1BlockNum), + arbmath.U256Bytes(&t), common.BigToHash(value).Bytes(), calldataForL1, ) diff --git a/staker/assertion.go b/staker/assertion.go index 8d09abf86..3047721e5 100644 --- a/staker/assertion.go +++ b/staker/assertion.go @@ -7,9 +7,10 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" + "github.com/offchainlabs/nitro/solgen/go/rollupgen" + "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/validator" ) @@ -39,8 +40,8 @@ func HashChallengeState( hashesBytes = append(hashesBytes, h[:]...) } return crypto.Keccak256Hash( - math.U256Bytes(new(big.Int).SetUint64(segmentStart)), - math.U256Bytes(new(big.Int).SetUint64(segmentLength)), + arbmath.Uint64ToU256Bytes(segmentStart), + arbmath.Uint64ToU256Bytes(segmentLength), hashesBytes, ) } diff --git a/system_tests/contract_tx_test.go b/system_tests/contract_tx_test.go index 56d79b36d..7d66e516b 100644 --- a/system_tests/contract_tx_test.go +++ b/system_tests/contract_tx_test.go @@ -12,7 +12,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" @@ -64,10 +63,10 @@ func TestContractTxDeploy(t *testing.T) { Data: deployCode, } l2Msg := []byte{arbos.L2MessageKind_ContractTx} - l2Msg = append(l2Msg, math.U256Bytes(arbmath.UintToBig(contractTx.Gas))...) - l2Msg = append(l2Msg, math.U256Bytes(contractTx.GasFeeCap)...) + l2Msg = append(l2Msg, arbmath.Uint64ToU256Bytes(contractTx.Gas)...) + l2Msg = append(l2Msg, arbmath.U256Bytes(contractTx.GasFeeCap)...) l2Msg = append(l2Msg, common.Hash{}.Bytes()...) // to is zero, translated into nil - l2Msg = append(l2Msg, math.U256Bytes(contractTx.Value)...) + l2Msg = append(l2Msg, arbmath.U256Bytes(contractTx.Value)...) l2Msg = append(l2Msg, contractTx.Data...) err = builder.L2.ConsensusNode.TxStreamer.AddMessages(pos, true, []arbostypes.MessageWithMetadata{ diff --git a/system_tests/deployment_test.go b/system_tests/deployment_test.go index a689abaa1..7e89c57cf 100644 --- a/system_tests/deployment_test.go +++ b/system_tests/deployment_test.go @@ -6,18 +6,18 @@ package arbtest import ( "bytes" "context" - "math/big" "strings" "testing" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/params" + + "github.com/offchainlabs/nitro/util/arbmath" ) func testContractDeployment(t *testing.T, ctx context.Context, client *ethclient.Client, contractCode []byte, accountInfo *AccountInfo, expectedEstimateGasError error) { @@ -26,7 +26,7 @@ func testContractDeployment(t *testing.T, ctx context.Context, client *ethclient 0x7F, // PUSH32 } // len(contractCode) - deployCode = append(deployCode, math.U256Bytes(big.NewInt(int64(len(contractCode))))...) + deployCode = append(deployCode, arbmath.Uint64ToU256Bytes(uint64(len(contractCode)))...) var codeOffset byte = 42 deployCode = append(deployCode, []byte{ 0x80, // DUP diff --git a/system_tests/reorg_resequencing_test.go b/system_tests/reorg_resequencing_test.go index fcc6603ae..b188504ac 100644 --- a/system_tests/reorg_resequencing_test.go +++ b/system_tests/reorg_resequencing_test.go @@ -9,9 +9,10 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/params" + "github.com/offchainlabs/nitro/arbos/arbostypes" + "github.com/offchainlabs/nitro/util/arbmath" ) func TestReorgResequencing(t *testing.T) { @@ -69,7 +70,7 @@ func TestReorgResequencing(t *testing.T) { RequestId: &delayedIndexHash, L1BaseFee: common.Big0, }, - L2msg: append(builder.L2Info.GetAddress("User4").Bytes(), math.U256Bytes(big.NewInt(params.Ether))...), + L2msg: append(builder.L2Info.GetAddress("User4").Bytes(), arbmath.Uint64ToU256Bytes(params.Ether)...), } err = builder.L2.ConsensusNode.TxStreamer.AddMessages(startMsgCount, true, []arbostypes.MessageWithMetadata{{ Message: newMessage, diff --git a/util/arbmath/math.go b/util/arbmath/math.go index 467ee58a1..c19750fba 100644 --- a/util/arbmath/math.go +++ b/util/arbmath/math.go @@ -8,6 +8,7 @@ import ( "math/big" "math/bits" + eth_math "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/params" ) @@ -376,3 +377,14 @@ func BalancePerEther(balance *big.Int) float64 { balancePerEther, _ := new(big.Float).Quo(new(big.Float).SetInt(balance), new(big.Float).SetFloat64(params.Ether)).Float64() return balancePerEther } + +// U256Bytes converts big Int to 256bit EVM number. +// This operation makes a copy of big Int. +func U256Bytes(n *big.Int) []byte { + return eth_math.U256Bytes(new(big.Int).Set(n)) +} + +// Uint64ToU256Bytes converts uint64 to 256bit EVM number. +func Uint64ToU256Bytes(n uint64) []byte { + return eth_math.U256Bytes(UintToBig(n)) +} From 502a9391335812e96ef6b06ab00e08a74da4ac31 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 22 Nov 2023 19:34:13 +0530 Subject: [PATCH 418/775] Use U256 from arbmath --- arbos/storage/storage_test.go | 2 +- util/arbmath/math.go | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arbos/storage/storage_test.go b/arbos/storage/storage_test.go index a8d424d14..b2e8bdb2e 100644 --- a/arbos/storage/storage_test.go +++ b/arbos/storage/storage_test.go @@ -53,7 +53,7 @@ func TestStorageBackedBigInt(t *testing.T) { t.Fatal(err) } // Verify that our encoding matches geth's signed complement impl - expectedRawVal := common.BigToHash(math.U256(new(big.Int).Set(in))) + expectedRawVal := common.BigToHash(arbmath.U256(in)) if rawVal != expectedRawVal { t.Fatal("for input", in, "expected raw value", expectedRawVal, "but got", rawVal) } diff --git a/util/arbmath/math.go b/util/arbmath/math.go index c19750fba..2945dd5a2 100644 --- a/util/arbmath/math.go +++ b/util/arbmath/math.go @@ -384,6 +384,12 @@ func U256Bytes(n *big.Int) []byte { return eth_math.U256Bytes(new(big.Int).Set(n)) } +// U256 encodes as a 256 bit two's complement number. +// This operation makes a copy of big Int. +func U256(x *big.Int) *big.Int { + return eth_math.U256(new(big.Int).Set(x)) +} + // Uint64ToU256Bytes converts uint64 to 256bit EVM number. func Uint64ToU256Bytes(n uint64) []byte { return eth_math.U256Bytes(UintToBig(n)) From d1cb68159afe2cf3617335f992ae4beae6143b6f Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 22 Nov 2023 21:37:27 +0530 Subject: [PATCH 419/775] address PR comments --- broadcastclients/broadcastclients.go | 98 ++++++++++++++++------------ 1 file changed, 58 insertions(+), 40 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index 7fe6ca489..b243c5103 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -140,78 +140,86 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { defer startSecondaryFeedTimer.Stop() defer stopSecondaryFeedTimer.Stop() defer primaryFeedIsDownTimer.Stop() + + msgHandler := func(msg broadcaster.BroadcastFeedMessage, router *Router) error { + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + if _, ok := recentFeedItemsNew[msg.SequenceNumber]; ok { + return nil + } + if _, ok := recentFeedItemsOld[msg.SequenceNumber]; ok { + return nil + } + recentFeedItemsNew[msg.SequenceNumber] = time.Now() + if err := router.forwardTxStreamer.AddBroadcastMessages([]*broadcaster.BroadcastFeedMessage{&msg}); err != nil { + return err + } + return nil + } + confSeqHandler := func(cs arbutil.MessageIndex, router *Router) { + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + if cs == lastConfirmed { + return + } + lastConfirmed = cs + if router.forwardConfirmationChan != nil { + router.forwardConfirmationChan <- cs + } + } + + // Two select statements to prioritize reading messages from primary feeds' channels for { select { case <-ctx.Done(): return - // Primary feeds case msg := <-bcs.primaryRouter.messageChan: - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) - if _, ok := recentFeedItemsNew[msg.SequenceNumber]; ok { - continue - } - if _, ok := recentFeedItemsOld[msg.SequenceNumber]; ok { - continue - } - recentFeedItemsNew[msg.SequenceNumber] = time.Now() - if err := bcs.primaryRouter.forwardTxStreamer.AddBroadcastMessages([]*broadcaster.BroadcastFeedMessage{&msg}); err != nil { + if err := msgHandler(msg, bcs.primaryRouter); err != nil { log.Error("Error routing message from Primary Sequencer Feeds", "err", err) } case cs := <-bcs.primaryRouter.confirmedSequenceNumberChan: - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) - if cs == lastConfirmed { - continue - } - lastConfirmed = cs - if bcs.primaryRouter.forwardConfirmationChan != nil { - bcs.primaryRouter.forwardConfirmationChan <- cs - } - + confSeqHandler(cs, bcs.primaryRouter) // Cycle buckets to get rid of old entries case <-recentFeedItemsCleanup.C: recentFeedItemsOld = recentFeedItemsNew recentFeedItemsNew = make(map[arbutil.MessageIndex]time.Time, RECENT_FEED_INITIAL_MAP_SIZE) - // Failed to get messages from both primary and secondary feeds for ~5 seconds, start a new secondary feed case <-startSecondaryFeedTimer.C: bcs.startSecondaryFeed(ctx) - // Failed to get messages from primary feed for ~5 seconds, reset the timer responsible for stopping a secondary case <-primaryFeedIsDownTimer.C: stopSecondaryFeedTimer.Reset(PRIMARY_FEED_UPTIME) - // Primary feeds have been up and running for PRIMARY_FEED_UPTIME=10 mins without a failure, stop the recently started secondary feed case <-stopSecondaryFeedTimer.C: bcs.stopSecondaryFeed() - default: select { + case <-ctx.Done(): + return // Secondary Feeds case msg := <-bcs.secondaryRouter.messageChan: - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) - if _, ok := recentFeedItemsNew[msg.SequenceNumber]; ok { - continue - } - if _, ok := recentFeedItemsOld[msg.SequenceNumber]; ok { - continue - } - recentFeedItemsNew[msg.SequenceNumber] = time.Now() - if err := bcs.secondaryRouter.forwardTxStreamer.AddBroadcastMessages([]*broadcaster.BroadcastFeedMessage{&msg}); err != nil { + if err := msgHandler(msg, bcs.secondaryRouter); err != nil { log.Error("Error routing message from Secondary Sequencer Feeds", "err", err) } case cs := <-bcs.secondaryRouter.confirmedSequenceNumberChan: - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) - if cs == lastConfirmed { - continue - } - lastConfirmed = cs - if bcs.secondaryRouter.forwardConfirmationChan != nil { - bcs.secondaryRouter.forwardConfirmationChan <- cs + confSeqHandler(cs, bcs.secondaryRouter) + + case msg := <-bcs.primaryRouter.messageChan: + primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) + if err := msgHandler(msg, bcs.primaryRouter); err != nil { + log.Error("Error routing message from Primary Sequencer Feeds", "err", err) } - default: + case cs := <-bcs.primaryRouter.confirmedSequenceNumberChan: + primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) + confSeqHandler(cs, bcs.primaryRouter) + case <-recentFeedItemsCleanup.C: + recentFeedItemsOld = recentFeedItemsNew + recentFeedItemsNew = make(map[arbutil.MessageIndex]time.Time, RECENT_FEED_INITIAL_MAP_SIZE) + case <-startSecondaryFeedTimer.C: + bcs.startSecondaryFeed(ctx) + case <-primaryFeedIsDownTimer.C: + stopSecondaryFeedTimer.Reset(PRIMARY_FEED_UPTIME) } } } @@ -244,6 +252,16 @@ func (bcs *BroadcastClients) stopSecondaryFeed() { bcs.secondaryClients = bcs.secondaryClients[:pos] log.Info("disconnected secondary feed", "url", bcs.secondaryURL[pos]) } + // flush the secondary feeds' message and confirmedSequenceNumber channels +f: + for { + select { + case <-bcs.secondaryRouter.messageChan: + case <-bcs.secondaryRouter.confirmedSequenceNumberChan: + default: + break f + } + } } func (bcs *BroadcastClients) StopAndWait() { From ed16798602b9b25889230d862f85ca88f0f272e0 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 22 Nov 2023 22:17:46 +0530 Subject: [PATCH 420/775] Increase the default BatchPosterConfig MaxSize for DAS chains to ~1MB --- cmd/nitro/nitro.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 42ba54c64..9cfb5a04e 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -826,14 +826,19 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c chainDefaults["init.empty"] = true } if parentChainIsArbitrum { - l2MaxTxSize := gethexec.DefaultSequencerConfig.MaxTxDataSize - bufferSpace := 5000 - if l2MaxTxSize < bufferSpace*2 { - return false, fmt.Errorf("not enough room in parent chain max tx size %v for bufferSpace %v * 2", l2MaxTxSize, bufferSpace) - } - safeBatchSize := l2MaxTxSize - bufferSpace - chainDefaults["node.batch-poster.max-size"] = safeBatchSize - chainDefaults["node.sequencer.max-tx-data-size"] = safeBatchSize - bufferSpace + if chainInfo.DasIndexUrl != "" { + chainDefaults["node.batch-poster.max-size"] = 1000000 + chainDefaults["node.sequencer.max-tx-data-size"] = 995000 + } else { + l2MaxTxSize := gethexec.DefaultSequencerConfig.MaxTxDataSize + bufferSpace := 5000 + if l2MaxTxSize < bufferSpace*2 { + return false, fmt.Errorf("not enough room in parent chain max tx size %v for bufferSpace %v * 2", l2MaxTxSize, bufferSpace) + } + safeBatchSize := l2MaxTxSize - bufferSpace + chainDefaults["node.batch-poster.max-size"] = safeBatchSize + chainDefaults["node.sequencer.max-tx-data-size"] = safeBatchSize - bufferSpace + } } err = k.Load(confmap.Provider(chainDefaults, "."), nil) if err != nil { From 5efed8efc1d76cfe4941cf56aa180b229c5189ba Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 22 Nov 2023 10:06:35 -0700 Subject: [PATCH 421/775] Revert "Finalize ArbOS 11" This reverts commit df93361a1293574903f28fbbbe0469a3ea5c644d. --- arbos/arbosState/arbosstate.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arbos/arbosState/arbosstate.go b/arbos/arbosState/arbosstate.go index 46d2c6f3f..8702c62d1 100644 --- a/arbos/arbosState/arbosstate.go +++ b/arbos/arbosState/arbosstate.go @@ -300,6 +300,14 @@ func (state *ArbosState) UpgradeArbosVersion( l1pricing.L1PricerFundsPoolAddress, ))) case 10: + if !chainConfig.DebugMode() { + // This upgrade isn't finalized so we only want to support it for testing + return fmt.Errorf( + "the chain is upgrading to unsupported ArbOS version %v, %w", + state.arbosVersion+1, + ErrFatalNodeOutOfDate, + ) + } // Update the PerBatchGasCost to a more accurate value compared to the old v6 default. ensure(state.l1PricingState.SetPerBatchGasCost(l1pricing.InitialPerBatchGasCostV12)) From 8319b177c948bc36487191ccbd66474fc48c64d9 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 22 Nov 2023 22:40:57 +0530 Subject: [PATCH 422/775] address PR comments --- cmd/nitro/nitro.go | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 9cfb5a04e..1dc898df1 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -826,19 +826,17 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c chainDefaults["init.empty"] = true } if parentChainIsArbitrum { - if chainInfo.DasIndexUrl != "" { - chainDefaults["node.batch-poster.max-size"] = 1000000 - chainDefaults["node.sequencer.max-tx-data-size"] = 995000 - } else { - l2MaxTxSize := gethexec.DefaultSequencerConfig.MaxTxDataSize - bufferSpace := 5000 - if l2MaxTxSize < bufferSpace*2 { - return false, fmt.Errorf("not enough room in parent chain max tx size %v for bufferSpace %v * 2", l2MaxTxSize, bufferSpace) - } - safeBatchSize := l2MaxTxSize - bufferSpace - chainDefaults["node.batch-poster.max-size"] = safeBatchSize - chainDefaults["node.sequencer.max-tx-data-size"] = safeBatchSize - bufferSpace + l2MaxTxSize := gethexec.DefaultSequencerConfig.MaxTxDataSize + bufferSpace := 5000 + if l2MaxTxSize < bufferSpace*2 { + return false, fmt.Errorf("not enough room in parent chain max tx size %v for bufferSpace %v * 2", l2MaxTxSize, bufferSpace) } + safeBatchSize := l2MaxTxSize - bufferSpace + chainDefaults["node.batch-poster.max-size"] = safeBatchSize + chainDefaults["node.sequencer.max-tx-data-size"] = safeBatchSize - bufferSpace + } + if chainInfo.DasIndexUrl != "" { + chainDefaults["node.batch-poster.max-size"] = 1000000 } err = k.Load(confmap.Provider(chainDefaults, "."), nil) if err != nil { From aa80bf9055715dbd45e6931099f6f89cf05f7f9d Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 27 Nov 2023 19:20:12 +0530 Subject: [PATCH 423/775] address PR comments and track last error in init --- execution/gethexec/forwarder.go | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/execution/gethexec/forwarder.go b/execution/gethexec/forwarder.go index 39a8a96e2..dc3420f8d 100644 --- a/execution/gethexec/forwarder.go +++ b/execution/gethexec/forwarder.go @@ -183,33 +183,30 @@ func (f *TxForwarder) Initialize(inctx context.Context) error { if f.ctx == nil { f.ctx = inctx } - - pos := 0 - for pos < len(f.targets) { - if f.targets[pos] == "" { - f.targets = append(f.targets[:pos], f.targets[pos+1:]...) - } else { - pos += 1 - } - } - ctx, cancelFunc := f.ctxWithTimeout() defer cancelFunc() - pos = 0 - for pos < len(f.targets) { - rpcClient, err := rpc.DialTransport(ctx, f.targets[pos], f.transport) + var targets []string + var lastError error + for _, target := range f.targets { + if target == "" { + continue + } + rpcClient, err := rpc.DialTransport(ctx, target, f.transport) if err != nil { - log.Warn("error initializing a forwarding client in txForwarder", "forwarding url", f.targets[pos], "err", err) - f.targets = append(f.targets[:pos], f.targets[pos+1:]...) + log.Warn("error initializing a forwarding client in txForwarder", "forwarding url", target, "err", err) + lastError = err continue } + targets = append(targets, target) ethClient := ethclient.NewClient(rpcClient) f.rpcClients = append(f.rpcClients, rpcClient) f.ethClients = append(f.ethClients, ethClient) - pos += 1 } + f.targets = targets if len(f.rpcClients) > 0 { f.enabled.Store(true) + } else { + return lastError } return nil } From 1f3127c33a3e22afb540854daf4f447a9de45688 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 27 Nov 2023 21:21:39 +0530 Subject: [PATCH 424/775] Rename MaxCodeSize and MaxInitCodeSize to DefaultMaxCodeSize and DefaultMaxInitCodeSize --- go-ethereum | 2 +- system_tests/deployment_test.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go-ethereum b/go-ethereum index f4eec6e6f..197f5ff0c 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit f4eec6e6f9dcc2c2b32b5af049001ca1629bb5f2 +Subproject commit 197f5ff0c9bff867301506aaa459735e3b05b19f diff --git a/system_tests/deployment_test.go b/system_tests/deployment_test.go index a689abaa1..c7767fef9 100644 --- a/system_tests/deployment_test.go +++ b/system_tests/deployment_test.go @@ -115,7 +115,7 @@ func TestContractDeployment(t *testing.T) { defer cleanup() account := builder.L2Info.GetInfoWithPrivKey("Faucet") - for _, size := range []int{0, 1, 1000, 20000, params.MaxCodeSize} { + for _, size := range []int{0, 1, 1000, 20000, params.DefaultMaxCodeSize} { testContractDeployment(t, ctx, builder.L2.Client, makeContractOfLength(size), account, nil) } @@ -128,13 +128,13 @@ func TestExtendedContractDeployment(t *testing.T) { defer cancel() builder := NewNodeBuilder(ctx).DefaultConfig(t, false) - builder.chainConfig.ArbitrumChainParams.MaxCodeSize = params.MaxCodeSize * 3 - builder.chainConfig.ArbitrumChainParams.MaxInitCodeSize = params.MaxInitCodeSize * 3 + builder.chainConfig.ArbitrumChainParams.MaxCodeSize = params.DefaultMaxCodeSize * 3 + builder.chainConfig.ArbitrumChainParams.MaxInitCodeSize = params.DefaultMaxInitCodeSize * 3 cleanup := builder.Build(t) defer cleanup() account := builder.L2Info.GetInfoWithPrivKey("Faucet") - for _, size := range []int{0, 1, 1000, 20000, 30000, 40000, 60000, params.MaxCodeSize * 3} { + for _, size := range []int{0, 1, 1000, 20000, 30000, 40000, 60000, params.DefaultMaxCodeSize * 3} { testContractDeployment(t, ctx, builder.L2.Client, makeContractOfLength(size), account, nil) } From d1a4e3db0a8784acc42f8982e8b952c437d9a9f0 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 27 Nov 2023 22:11:12 +0530 Subject: [PATCH 425/775] code refactor --- broadcastclients/broadcastclients.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index b243c5103..3e048000e 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -251,15 +251,16 @@ func (bcs *BroadcastClients) stopSecondaryFeed() { bcs.secondaryClients[pos].StopAndWait() bcs.secondaryClients = bcs.secondaryClients[:pos] log.Info("disconnected secondary feed", "url", bcs.secondaryURL[pos]) - } - // flush the secondary feeds' message and confirmedSequenceNumber channels -f: - for { - select { - case <-bcs.secondaryRouter.messageChan: - case <-bcs.secondaryRouter.confirmedSequenceNumberChan: - default: - break f + + // flush the secondary feeds' message and confirmedSequenceNumber channels + f: + for { + select { + case <-bcs.secondaryRouter.messageChan: + case <-bcs.secondaryRouter.confirmedSequenceNumberChan: + default: + break f + } } } } From c86e0828dc22141960001df85d7341e844642e0a Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 27 Nov 2023 10:44:46 -0700 Subject: [PATCH 426/775] Bump fastcache pin to latest master --- fastcache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastcache b/fastcache index b66ec7c27..8053d350d 160000 --- a/fastcache +++ b/fastcache @@ -1 +1 @@ -Subproject commit b66ec7c2749658e0b595a7a398cfaaf6abd39270 +Subproject commit 8053d350d785b5dd877e208e1f0205bbd36faee7 From 8d0524de66a64666d6d52c07e493b852bf94459d Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 28 Nov 2023 21:39:00 +0530 Subject: [PATCH 427/775] Add backup transaction submission RPC URLs to arb1 chain information --- cmd/chaininfo/arbitrum_chain_info.json | 1 + cmd/chaininfo/chain_info.go | 15 ++++++++------- cmd/nitro/nitro.go | 3 +++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/cmd/chaininfo/arbitrum_chain_info.json b/cmd/chaininfo/arbitrum_chain_info.json index 421abea20..31d25cfdf 100644 --- a/cmd/chaininfo/arbitrum_chain_info.json +++ b/cmd/chaininfo/arbitrum_chain_info.json @@ -4,6 +4,7 @@ "parent-chain-id": 1, "parent-chain-is-arbitrum": false, "sequencer-url": "https://arb1-sequencer.arbitrum.io/rpc", + "secondary-forwarding-target": "https://arb1-sequencer-fallback-1.arbitrum.io/rpc,https://arb1-sequencer-fallback-2.arbitrum.io/rpc,https://arb1-sequencer-fallback-3.arbitrum.io/rpc,https://arb1-sequencer-fallback-4.arbitrum.io/rpc,https://arb1-sequencer-fallback-5.arbitrum.io/rpc", "feed-url": "wss://arb1-feed.arbitrum.io/feed", "secondary-feed-url": "wss://arb1-delayed-feed.arbitrum.io/feed,wss://arb1-feed-fallback-1.arbitrum.io/feed,wss://arb1-feed-fallback-2.arbitrum.io/feed,wss://arb1-feed-fallback-3.arbitrum.io/feed,wss://arb1-feed-fallback-4.arbitrum.io/feed,wss://arb1-feed-fallback-5.arbitrum.io/feed", "has-genesis-state": true, diff --git a/cmd/chaininfo/chain_info.go b/cmd/chaininfo/chain_info.go index fe499442d..c0d6b3d00 100644 --- a/cmd/chaininfo/chain_info.go +++ b/cmd/chaininfo/chain_info.go @@ -22,13 +22,14 @@ type ChainInfo struct { ParentChainId uint64 `json:"parent-chain-id"` ParentChainIsArbitrum *bool `json:"parent-chain-is-arbitrum"` // This is the forwarding target to submit transactions to, called the sequencer URL for clarity - SequencerUrl string `json:"sequencer-url"` - FeedUrl string `json:"feed-url"` - SecondaryFeedUrl string `json:"secondary-feed-url"` - DasIndexUrl string `json:"das-index-url"` - HasGenesisState bool `json:"has-genesis-state"` - ChainConfig *params.ChainConfig `json:"chain-config"` - RollupAddresses *RollupAddresses `json:"rollup"` + SequencerUrl string `json:"sequencer-url"` + SecondaryForwardingTarget string `json:"secondary-forwarding-target"` + FeedUrl string `json:"feed-url"` + SecondaryFeedUrl string `json:"secondary-feed-url"` + DasIndexUrl string `json:"das-index-url"` + HasGenesisState bool `json:"has-genesis-state"` + ChainConfig *params.ChainConfig `json:"chain-config"` + RollupAddresses *RollupAddresses `json:"rollup"` } func GetChainConfig(chainId *big.Int, chainName string, genesisBlockNum uint64, l2ChainInfoFiles []string, l2ChainInfoJson string) (*params.ChainConfig, error) { diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 7e089d946..9b34d2371 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -814,6 +814,9 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c if chainInfo.SequencerUrl != "" { chainDefaults["execution.forwarding-target"] = chainInfo.SequencerUrl } + if chainInfo.SecondaryForwardingTarget != "" { + chainDefaults["execution.secondary-forwarding-target"] = strings.Split(chainInfo.SecondaryForwardingTarget, ",") + } if chainInfo.FeedUrl != "" { chainDefaults["node.feed.input.url"] = strings.Split(chainInfo.FeedUrl, ",") } From 5a478894297eb437bd9d4d75ab60657af47a90d0 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 28 Nov 2023 22:59:33 +0530 Subject: [PATCH 428/775] minor fix --- execution/gethexec/node.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 8e640ea6c..7dd6e301f 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -7,7 +7,6 @@ import ( "reflect" "sync/atomic" "testing" - "time" "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" @@ -103,7 +102,6 @@ var ConfigDefault = Config{ func ConfigDefaultNonSequencerTest() *Config { config := ConfigDefault - config.ParentChainReader = headerreader.Config{OldHeaderTimeout: 5 * time.Minute} config.ParentChainReader = headerreader.TestConfig config.Sequencer.Enable = false config.Forwarder = DefaultTestForwarderConfig From 3c7cbcd71e4d609c15891ee3a063cc1a816cf75a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Nov 2023 17:48:05 +0000 Subject: [PATCH 429/775] Bump github.com/consensys/gnark-crypto from 0.10.0 to 0.12.1 Bumps [github.com/consensys/gnark-crypto](https://github.com/consensys/gnark-crypto) from 0.10.0 to 0.12.1. - [Release notes](https://github.com/consensys/gnark-crypto/releases) - [Changelog](https://github.com/Consensys/gnark-crypto/blob/master/CHANGELOG.md) - [Commits](https://github.com/consensys/gnark-crypto/compare/v0.10.0...v0.12.1) --- updated-dependencies: - dependency-name: github.com/consensys/gnark-crypto dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 11 ++--------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 5ddcf86e3..598c48e92 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ replace github.com/VictoriaMetrics/fastcache => ./fastcache replace github.com/ethereum/go-ethereum => ./go-ethereum require ( + github.com/Shopify/toxiproxy v2.1.4+incompatible github.com/alicebob/miniredis/v2 v2.21.0 github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 github.com/andybalholm/brotli v1.0.4 @@ -51,7 +52,6 @@ require ( bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc // indirect github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect github.com/DataDog/zstd v1.5.2 // indirect - github.com/Shopify/toxiproxy v2.1.4+incompatible // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect @@ -82,7 +82,7 @@ require ( github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect github.com/consensys/bavard v0.1.13 // indirect - github.com/consensys/gnark-crypto v0.10.0 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect diff --git a/go.sum b/go.sum index d9105964c..1fb8a405f 100644 --- a/go.sum +++ b/go.sum @@ -233,15 +233,14 @@ github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoG github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= -github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codeclysm/extract/v3 v3.0.2 h1:sB4LcE3Php7LkhZwN0n2p8GCwZe92PEQutdbGURf5xc= github.com/codeclysm/extract/v3 v3.0.2/go.mod h1:NKsw+hqua9H+Rlwy/w/3Qgt9jDonYEgB6wJu+25eOKw= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.10.0 h1:zRh22SR7o4K35SoNqouS9J/TKHTyU2QWaj5ldehyXtA= -github.com/consensys/gnark-crypto v0.10.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= @@ -278,7 +277,6 @@ github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6Uh github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= @@ -396,7 +394,6 @@ github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -893,7 +890,6 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -1272,7 +1268,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= @@ -1414,7 +1409,6 @@ github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAv github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk= -github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -1651,7 +1645,6 @@ github.com/wealdtech/go-merkletree v1.0.0/go.mod h1:cdil512d/8ZC7Kx3bfrDvGMQXB25 github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4= github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= -github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa h1:EyA027ZAkuaCLoxVX4r1TZMPy1d31fM6hbfQ4OU4I5o= github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= From 2dfe8b45109f913bc8d445d3ab1a34b6a3eca671 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 28 Nov 2023 11:37:04 -0700 Subject: [PATCH 430/775] Use normal gas estimation when possible in the batch poster --- arbnode/batch_poster.go | 60 ++++++++++++++++--------------- arbnode/dataposter/data_poster.go | 20 ++++++++--- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index edfb5c35d..498216cfd 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -27,7 +27,6 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbnode/dataposter" "github.com/offchainlabs/nitro/arbnode/redislock" @@ -757,32 +756,26 @@ func (b *BatchPoster) encodeAddBatch(seqNum *big.Int, prevMsgNum arbutil.Message return fullData, nil } -func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, delayedMessages uint64) (uint64, error) { +func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, delayedMessages uint64, realData []byte, realNonce uint64) (uint64, error) { config := b.config() - callOpts := &bind.CallOpts{ - Context: ctx, - } - if config.DataPoster.WaitForL1Finality { - callOpts.BlockNumber = big.NewInt(int64(rpc.SafeBlockNumber)) - } - safeDelayedMessagesBig, err := b.bridge.DelayedMessageCount(callOpts) - if err != nil { - return 0, fmt.Errorf("failed to get the confirmed delayed message count: %w", err) - } - if !safeDelayedMessagesBig.IsUint64() { - return 0, fmt.Errorf("calling delayedMessageCount() on the bridge returned a non-uint64 result %v", safeDelayedMessagesBig) - } - safeDelayedMessages := safeDelayedMessagesBig.Uint64() - if safeDelayedMessages > delayedMessages { - // On restart, we may be trying to estimate gas for a batch whose successor has - // already made it into pending state, if not latest state. - // In that case, we might get a revert with `DelayedBackwards()`. - // To avoid that, we artificially increase the delayed messages to `safeDelayedMessages`. - // In theory, this might reduce gas usage, but only by a factor that's already - // accounted for in `config.ExtraBatchGas`, as that same factor can appear if a user - // posts a new delayed message that we didn't see while gas estimating. - delayedMessages = safeDelayedMessages + useNormalEstimation := b.dataPoster.MaxMempoolTransactions() == 1 + if !useNormalEstimation { + // Check if we can use normal estimation anyways because we're at the latest nonce + latestNonce, err := b.l1Reader.Client().NonceAt(ctx, b.dataPoster.Sender(), nil) + if err != nil { + return 0, err + } + useNormalEstimation = latestNonce == realNonce + } + if useNormalEstimation { + // If we're at the latest nonce, we can skip the special future tx estimate stuff + return b.l1Reader.Client().EstimateGas(ctx, ethereum.CallMsg{ + From: b.dataPoster.Sender(), + To: &b.seqInboxAddr, + Data: realData, + }) } + // Here we set seqNum to MaxUint256, and prevMsgNum to 0, because it disables the smart contracts' consistency checks. // However, we set nextMsgNum to 1 because it is necessary for a correct estimation for the final to be non-zero. // Because we're likely estimating against older state, this might not be the actual next message, @@ -805,7 +798,6 @@ func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, "error estimating gas for batch", "err", err, "delayedMessages", delayedMessages, - "safeDelayedMessages", safeDelayedMessages, "sequencerMessageHeader", hex.EncodeToString(sequencerMessageHeader), "sequencerMessageLen", len(sequencerMessage), ) @@ -858,6 +850,11 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) } firstMsgTime := time.Unix(int64(firstMsg.Message.Header.Timestamp), 0) + lastPotentialMsg, err := b.streamer.GetMessage(msgCount - 1) + if err != nil { + return false, err + } + config := b.config() forcePostBatch := time.Since(firstMsgTime) >= config.MaxDelay @@ -1000,11 +997,18 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) } } - gasLimit, err := b.estimateGas(ctx, sequencerMsg, b.building.segments.delayedMsg) + data, err := b.encodeAddBatch(new(big.Int).SetUint64(batchPosition.NextSeqNum), batchPosition.MessageCount, b.building.msgCount, sequencerMsg, b.building.segments.delayedMsg) if err != nil { return false, err } - data, err := b.encodeAddBatch(new(big.Int).SetUint64(batchPosition.NextSeqNum), batchPosition.MessageCount, b.building.msgCount, sequencerMsg, b.building.segments.delayedMsg) + // On restart, we may be trying to estimate gas for a batch whose successor has + // already made it into pending state, if not latest state. + // In that case, we might get a revert with `DelayedBackwards()`. + // To avoid that, we artificially increase the delayed messages to `lastPotentialMsg.DelayedMessagesRead`. + // In theory, this might reduce gas usage, but only by a factor that's already + // accounted for in `config.ExtraBatchGas`, as that same factor can appear if a user + // posts a new delayed message that we didn't see while gas estimating. + gasLimit, err := b.estimateGas(ctx, sequencerMsg, lastPotentialMsg.DelayedMessagesRead, data, nonce) if err != nil { return false, err } diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index b5be06af5..266131a6b 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -56,6 +56,7 @@ type DataPoster struct { signer signerFn redisLock AttemptLocker config ConfigFetcher + usingNoOpStorage bool replacementTimes []time.Duration metadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error) @@ -119,8 +120,9 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro if err != nil { return nil, err } + useNoOpStorage := cfg.UseNoOpStorage if opts.HeaderReader.IsParentChainArbitrum() && !cfg.UseNoOpStorage { - cfg.UseNoOpStorage = true + useNoOpStorage = true log.Info("Disabling data poster storage, as parent chain appears to be an Arbitrum chain without a mempool") } encF := func() storage.EncoderDecoderInterface { @@ -131,7 +133,7 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro } var queue QueueStorage switch { - case cfg.UseNoOpStorage: + case useNoOpStorage: queue = &noop.Storage{} case opts.RedisClient != nil: var err error @@ -158,6 +160,7 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro return opts.Auth.Signer(addr, tx) }, config: opts.Config, + usingNoOpStorage: useNoOpStorage, replacementTimes: replacementTimes, metadataRetriever: opts.MetadataRetriever, queue: queue, @@ -252,6 +255,13 @@ func (p *DataPoster) Sender() common.Address { return p.sender } +func (p *DataPoster) MaxMempoolTransactions() uint64 { + if p.usingNoOpStorage { + return 1 + } + return p.config().MaxMempoolTransactions +} + // Does basic check whether posting transaction with specified nonce would // result in exceeding maximum queue length or maximum transactions in mempool. func (p *DataPoster) canPostWithNonce(ctx context.Context, nextNonce uint64) error { @@ -398,7 +408,7 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u latestBalance := p.balance balanceForTx := new(big.Int).Set(latestBalance) - if config.AllocateMempoolBalance && !config.UseNoOpStorage { + if config.AllocateMempoolBalance && !p.usingNoOpStorage { // We reserve half the balance for the first transaction, and then split the remaining balance for all after that. // With noop storage, we don't try to replace-by-fee, so we don't need to worry about this. balanceForTx.Div(balanceForTx, common.Big2) @@ -500,12 +510,12 @@ func (p *DataPoster) sendTx(ctx context.Context, prevTx *storage.QueuedTransacti } if err := p.client.SendTransaction(ctx, newTx.FullTx); err != nil { if !strings.Contains(err.Error(), "already known") && !strings.Contains(err.Error(), "nonce too low") { - log.Warn("DataPoster failed to send transaction", "err", err, "nonce", newTx.FullTx.Nonce(), "feeCap", newTx.FullTx.GasFeeCap(), "tipCap", newTx.FullTx.GasTipCap()) + log.Warn("DataPoster failed to send transaction", "err", err, "nonce", newTx.FullTx.Nonce(), "feeCap", newTx.FullTx.GasFeeCap(), "tipCap", newTx.FullTx.GasTipCap(), "gas", newTx.FullTx.Gas()) return err } log.Info("DataPoster transaction already known", "err", err, "nonce", newTx.FullTx.Nonce(), "hash", newTx.FullTx.Hash()) } else { - log.Info("DataPoster sent transaction", "nonce", newTx.FullTx.Nonce(), "hash", newTx.FullTx.Hash(), "feeCap", newTx.FullTx.GasFeeCap()) + log.Info("DataPoster sent transaction", "nonce", newTx.FullTx.Nonce(), "hash", newTx.FullTx.Hash(), "feeCap", newTx.FullTx.GasFeeCap(), "tipCap", newTx.FullTx.GasTipCap(), "gas", newTx.FullTx.Gas()) } newerTx := *newTx newerTx.Sent = true From 8c23ffc327ef8465dc406e1ac32e3e3216597ba5 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 28 Nov 2023 14:07:48 -0700 Subject: [PATCH 431/775] Don't forget ExtraBatchGas for normal estimation --- arbnode/batch_poster.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 498216cfd..d96ed5723 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -769,11 +769,15 @@ func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, } if useNormalEstimation { // If we're at the latest nonce, we can skip the special future tx estimate stuff - return b.l1Reader.Client().EstimateGas(ctx, ethereum.CallMsg{ + gas, err := b.l1Reader.Client().EstimateGas(ctx, ethereum.CallMsg{ From: b.dataPoster.Sender(), To: &b.seqInboxAddr, Data: realData, }) + if err != nil { + return 0, err + } + return gas + config.ExtraBatchGas, nil } // Here we set seqNum to MaxUint256, and prevMsgNum to 0, because it disables the smart contracts' consistency checks. From 28a22cf660143edd11f3426f587560af441df1ac Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Tue, 28 Nov 2023 16:22:11 -0700 Subject: [PATCH 432/775] Pull in offchainlabs/go-ethereum #270 & 272 Add these fixes: * https://github.com/OffchainLabs/go-ethereum/pull/270 * https://github.com/OffchainLabs/go-ethereum/pull/272 --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 197f5ff0c..b1622e6ac 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 197f5ff0c9bff867301506aaa459735e3b05b19f +Subproject commit b1622e6ac4bf3762aebde92a585de2889d90823f From 4f97815165b40933f3a2c76ed6d6db29ab88d0fb Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 29 Nov 2023 11:07:04 +0530 Subject: [PATCH 433/775] code refactor --- broadcastclients/broadcastclients.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index 3e048000e..aa5f39ad9 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -253,13 +253,12 @@ func (bcs *BroadcastClients) stopSecondaryFeed() { log.Info("disconnected secondary feed", "url", bcs.secondaryURL[pos]) // flush the secondary feeds' message and confirmedSequenceNumber channels - f: for { select { case <-bcs.secondaryRouter.messageChan: case <-bcs.secondaryRouter.confirmedSequenceNumberChan: default: - break f + return } } } From 23ca62779a23cfc61188e23596e07fa33578264f Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 29 Nov 2023 21:33:46 +0530 Subject: [PATCH 434/775] Validate that sequencer MaxTxDataSize and batch poster MaxSize are below sequencer inbox requirements --- cmd/nitro/nitro.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 393f23c52..527da6a97 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -14,6 +14,7 @@ import ( "os/signal" "path/filepath" "reflect" + "regexp" "strings" "syscall" "time" @@ -50,6 +51,7 @@ import ( "github.com/offchainlabs/nitro/cmd/util/confighelpers" "github.com/offchainlabs/nitro/execution/gethexec" _ "github.com/offchainlabs/nitro/nodeInterface" + "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/staker/validatorwallet" @@ -488,6 +490,42 @@ func mainImpl() int { log.Error("failed to create node", "err", err) return 1 } + + // Validate sequencer's MaxTxDataSize and batchPoster's MaxSize params + config := liveNodeConfig.Get() + executionRevertedRegexp := regexp.MustCompile("(?i)execution reverted") + seqInboxMaxDataSize := 117964 + if config.Node.ParentChainReader.Enable { + seqInbox, err := bridgegen.NewSequencerInbox(rollupAddrs.SequencerInbox, l1Client) + if err != nil { + log.Error("failed to create sequencer inbox for validating sequencer's MaxTxDataSize and batchposter's MaxSize", "err", err) + return 1 + } + res, err := seqInbox.MaxDataSize(&bind.CallOpts{Context: ctx}) + seqInboxMaxDataSize = int(res.Int64()) + if err != nil && !executionRevertedRegexp.MatchString(err.Error()) { + log.Error("error fetching MaxDataSize from sequencer inbox", "err", err) + return 1 + } + } + // If sequencer is enabled, validate MaxTxDataSize to be at least 5kB below the batch poster MaxSize, and at least 15kB below the sequencer inbox’s max data size. + if config.Execution.Sequencer.Enable { + seqMaxTxDataSize := config.Execution.Sequencer.MaxTxDataSize + batchPosterMaxSize := config.Node.BatchPoster.MaxSize + if seqMaxTxDataSize > batchPosterMaxSize-5000 || seqMaxTxDataSize > seqInboxMaxDataSize-15000 { + log.Error("sequencer's MaxTxDataSize too large") + return 1 + } + } + // If batchPoster is enabled, validate MaxSize to be at least 10kB below the sequencer inbox’s max data size if the data availability service is not enabled. + if config.Node.BatchPoster.Enable && !config.Node.DataAvailability.Enable { + batchPosterMaxSize := config.Node.BatchPoster.MaxSize + if batchPosterMaxSize > seqInboxMaxDataSize-10000 { + log.Error("batchPoster's MaxSize is too large") + return 1 + } + } + liveNodeConfig.SetOnReloadHook(func(oldCfg *NodeConfig, newCfg *NodeConfig) error { if err := genericconf.InitLog(newCfg.LogType, log.Lvl(newCfg.LogLevel), &newCfg.FileLogging, pathResolver(nodeConfig.Persistent.LogDir)); err != nil { return fmt.Errorf("failed to re-init logging: %w", err) From 0be22bc96361aa2a08a22d0a7dc792f5855ce89d Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:07:47 +1300 Subject: [PATCH 435/775] change lookupByKey to containers.SyncMap and remove lookupLock --- broadcaster/backlog/backlog.go | 22 +++++++--------------- broadcaster/backlog/backlog_test.go | 9 +++++---- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 999dd3b6a..391d85614 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/log" m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/containers" ) var ( @@ -31,15 +32,14 @@ type Backlog interface { type backlog struct { head atomic.Pointer[backlogSegment] tail atomic.Pointer[backlogSegment] - lookupLock sync.RWMutex - lookupByIndex map[uint64]*backlogSegment + lookupByIndex containers.SyncMap[uint64, *backlogSegment] config ConfigFetcher messageCount atomic.Uint64 } // NewBacklog creates a backlog. func NewBacklog(c ConfigFetcher) Backlog { - lookup := make(map[uint64]*backlogSegment) + lookup := containers.SyncMap[uint64, *backlogSegment]{} return &backlog{ lookupByIndex: lookup, config: c, @@ -93,9 +93,7 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { } else if err != nil { return err } - b.lookupLock.Lock() - b.lookupByIndex[uint64(msg.SequenceNumber)] = segment - b.lookupLock.Unlock() + b.lookupByIndex.Store(uint64(msg.SequenceNumber), segment) b.messageCount.Add(1) } @@ -211,18 +209,14 @@ func (b *backlog) delete(confirmed uint64) { // removeFromLookup removes all entries from the head segment's start index to // the given confirmed index. func (b *backlog) removeFromLookup(start, end uint64) { - b.lookupLock.Lock() - defer b.lookupLock.Unlock() for i := start; i <= end; i++ { - delete(b.lookupByIndex, i) + b.lookupByIndex.Delete(i) } } // Lookup attempts to find the backlogSegment storing the given message index. func (b *backlog) Lookup(i uint64) (BacklogSegment, error) { - b.lookupLock.RLock() - segment, ok := b.lookupByIndex[i] - b.lookupLock.RUnlock() + segment, ok := b.lookupByIndex.Load(i) if !ok { return nil, fmt.Errorf("error finding backlog segment containing message with SequenceNumber %d", i) } @@ -237,11 +231,9 @@ func (s *backlog) Count() uint64 { // reset removes all segments from the backlog. func (b *backlog) reset() { - b.lookupLock.Lock() - defer b.lookupLock.Unlock() b.head = atomic.Pointer[backlogSegment]{} b.tail = atomic.Pointer[backlogSegment]{} - b.lookupByIndex = map[uint64]*backlogSegment{} + b.lookupByIndex = containers.SyncMap[uint64, *backlogSegment]{} b.messageCount.Store(0) } diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go index e7b4f5f63..251f11e33 100644 --- a/broadcaster/backlog/backlog_test.go +++ b/broadcaster/backlog/backlog_test.go @@ -9,6 +9,7 @@ import ( "github.com/offchainlabs/nitro/arbutil" m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/containers" ) func validateBacklog(t *testing.T, b *backlog, count, start, end uint64, lookupKeys []arbutil.MessageIndex) { @@ -33,7 +34,7 @@ func validateBacklog(t *testing.T, b *backlog, count, start, end uint64, lookupK } expLen := len(lookupKeys) - actualLen := len(b.lookupByIndex) + actualLen := int(b.Count()) if expLen != actualLen { t.Errorf("expected length of lookupByIndex map (%d) does not equal actual length (%d)", expLen, actualLen) } @@ -56,7 +57,7 @@ func validateBroadcastMessage(t *testing.T, bm *m.BroadcastMessage, expectedCoun func createDummyBacklog(indexes []arbutil.MessageIndex) (*backlog, error) { b := &backlog{ - lookupByIndex: map[uint64]*backlogSegment{}, + lookupByIndex: containers.SyncMap[uint64, *backlogSegment]{}, config: func() *Config { return &DefaultTestConfig }, } bm := &m.BroadcastMessage{Messages: m.CreateDummyBroadcastMessages(indexes)} @@ -160,8 +161,8 @@ func TestDeleteInvalidBacklog(t *testing.T) { s.end.Store(42) s.messageCount.Store(2) - lookup := make(map[uint64]*backlogSegment) - lookup[40] = s + lookup := containers.SyncMap[uint64, *backlogSegment]{} + lookup.Store(40, s) b := &backlog{ lookupByIndex: lookup, config: func() *Config { return &DefaultTestConfig }, From ffa66361a8d59b475ba8e8fdd65c08b666362e4d Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:10:07 +1300 Subject: [PATCH 436/775] fix log.info line --- broadcaster/backlog/backlog.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 391d85614..b625217ea 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -88,7 +88,7 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { b.messageCount.Store(0) log.Warn(err.Error()) } else if errors.Is(err, errSequenceNumberSeen) { - log.Info("ignoring message sequence number (%s), already in backlog", msg.SequenceNumber) + log.Info("ignoring message sequence number, already in backlog", "message sequence number", msg.SequenceNumber) continue } else if err != nil { return err From 3403b7bb15da861f77256a1760baf8c85989501a Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:27:39 +1300 Subject: [PATCH 437/775] fix potential delete race condition in backlog.Get --- broadcaster/backlog/backlog.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index b625217ea..002031c6c 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -108,16 +108,17 @@ func (b *backlog) Get(start, end uint64) (*m.BroadcastMessage, error) { return nil, errOutOfBounds } - if start < head.Start() { - start = head.Start() - } - if end > tail.End() { return nil, errOutOfBounds } found, err := b.Lookup(start) - if err != nil { + if start < head.Start() { + // doing this check after the Lookup call ensures there is no race + // condition with a delete call + start = head.Start() + found = head + } else if err != nil { return nil, err } segment, ok := found.(*backlogSegment) From d9d479dd5ba42a193b29e8d8724dba9f97db13de Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:30:39 +1300 Subject: [PATCH 438/775] remove backlogSegment type assertion --- broadcaster/backlog/backlog.go | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 002031c6c..718468b23 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -112,30 +112,26 @@ func (b *backlog) Get(start, end uint64) (*m.BroadcastMessage, error) { return nil, errOutOfBounds } - found, err := b.Lookup(start) + segment, err := b.Lookup(start) if start < head.Start() { // doing this check after the Lookup call ensures there is no race // condition with a delete call start = head.Start() - found = head + segment = head } else if err != nil { return nil, err } - segment, ok := found.(*backlogSegment) - if !ok { - return nil, fmt.Errorf("error in backlogSegment type assertion") - } bm := &m.BroadcastMessage{Version: 1} required := int(end-start) + 1 for { - segMsgs, err := segment.get(arbmath.MaxInt(start, segment.Start()), arbmath.MinInt(end, segment.End())) + segMsgs, err := segment.Get(arbmath.MaxInt(start, segment.Start()), arbmath.MinInt(end, segment.End())) if err != nil { return nil, err } bm.Messages = append(bm.Messages, segMsgs...) - segment = segment.nextSegment.Load() + segment = segment.Next() if len(bm.Messages) == required { break } else if segment == nil { @@ -245,6 +241,7 @@ type BacklogSegment interface { Next() BacklogSegment Contains(uint64) bool Messages() []*m.BroadcastFeedMessage + Get(uint64, uint64) ([]*m.BroadcastFeedMessage, error) } // backlogSegment stores messages up to a limit defined by the backlog. It also @@ -297,8 +294,8 @@ func (s *backlogSegment) Messages() []*m.BroadcastFeedMessage { return s.messages } -// get reads messages from the given start to end message index. -func (s *backlogSegment) get(start, end uint64) ([]*m.BroadcastFeedMessage, error) { +// Get reads messages from the given start to end message index. +func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, error) { noMsgs := []*m.BroadcastFeedMessage{} if start < s.start.Load() { return noMsgs, errOutOfBounds From 1fc038c4e5262081878104f461c4de0807133df1 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:22:05 +1300 Subject: [PATCH 439/775] remove backlogSegment.start, backlogSegment.end and backlogSegment.messageCount, use the backlogSegment.messagesLock to calculate these when required --- broadcaster/backlog/backlog.go | 58 +++++++++++++---------------- broadcaster/backlog/backlog_test.go | 11 ++---- 2 files changed, 29 insertions(+), 40 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 718468b23..f469abe56 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -157,7 +157,7 @@ func (b *backlog) delete(confirmed uint64) { } if confirmed > tail.End() { - log.Error("confirmed sequence number is past the end of stored messages", "confirmed sequence number", confirmed, "last stored sequence number", tail.end.Load()) + log.Error("confirmed sequence number is past the end of stored messages", "confirmed sequence number", confirmed, "last stored sequence number", tail.End()) b.reset() return } @@ -247,11 +247,8 @@ type BacklogSegment interface { // backlogSegment stores messages up to a limit defined by the backlog. It also // points to the next backlogSegment in the list. type backlogSegment struct { - start atomic.Uint64 - end atomic.Uint64 messagesLock sync.RWMutex messages []*m.BroadcastFeedMessage - messageCount atomic.Uint64 nextSegment atomic.Pointer[backlogSegment] previousSegment atomic.Pointer[backlogSegment] } @@ -274,12 +271,23 @@ func IsBacklogSegmentNil(segment BacklogSegment) bool { // Start returns the first message index within the backlogSegment. func (s *backlogSegment) Start() uint64 { - return uint64(s.start.Load()) + s.messagesLock.RLock() + defer s.messagesLock.RUnlock() + if len(s.messages) > 0 { + return uint64(s.messages[0].SequenceNumber) + } + return uint64(0) } // End returns the last message index within the backlogSegment. func (s *backlogSegment) End() uint64 { - return uint64(s.end.Load()) + s.messagesLock.RLock() + defer s.messagesLock.RUnlock() + c := len(s.messages) + if c == 0 { + return uint64(0) + } + return uint64(s.messages[c-1].SequenceNumber) } // Next returns the next backlogSegment. @@ -297,16 +305,16 @@ func (s *backlogSegment) Messages() []*m.BroadcastFeedMessage { // Get reads messages from the given start to end message index. func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, error) { noMsgs := []*m.BroadcastFeedMessage{} - if start < s.start.Load() { + if start < s.Start() { return noMsgs, errOutOfBounds } - if end > s.end.Load() { + if end > s.End() { return noMsgs, errOutOfBounds } - startIndex := start - s.start.Load() - endIndex := end - s.start.Load() + 1 + startIndex := start - s.Start() + endIndex := end - s.Start() + 1 s.messagesLock.RLock() defer s.messagesLock.RUnlock() @@ -321,8 +329,6 @@ func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, erro func (s *backlogSegment) append(prevMsgIdx uint64, msg *m.BroadcastFeedMessage) error { s.messagesLock.Lock() defer s.messagesLock.Unlock() - seen := false - defer s.updateSegment(&seen) if expSeqNum := prevMsgIdx + 1; prevMsgIdx == 0 || uint64(msg.SequenceNumber) == expSeqNum { s.messages = append(s.messages, msg) @@ -331,7 +337,6 @@ func (s *backlogSegment) append(prevMsgIdx uint64, msg *m.BroadcastFeedMessage) s.messages = append(s.messages, msg) return fmt.Errorf("new message sequence number (%d) is greater than the expected sequence number (%d): %w", msg.SequenceNumber, expSeqNum, errDropSegments) } else { - seen = true return errSequenceNumberSeen } return nil @@ -340,8 +345,8 @@ func (s *backlogSegment) append(prevMsgIdx uint64, msg *m.BroadcastFeedMessage) // Contains confirms whether the segment contains a message with the given // sequence number. func (s *backlogSegment) Contains(i uint64) bool { - start := s.start.Load() - if i < start || i > s.end.Load() { + start := s.Start() + if i < start || i > s.End() { return false } @@ -355,11 +360,8 @@ func (s *backlogSegment) Contains(i uint64) bool { // delete removes messages from the backlogSegment up to and including the // given confirmed message index. func (s *backlogSegment) delete(confirmed uint64) error { - seen := false - defer s.updateSegment(&seen) - - start := s.start.Load() - end := s.end.Load() + start := s.Start() + end := s.End() msgIndex := confirmed - start if !s.Contains(confirmed) { return fmt.Errorf("confirmed message (%d) is not in expected index (%d) in current backlog (%d-%d)", confirmed, msgIndex, start, end) @@ -371,19 +373,9 @@ func (s *backlogSegment) delete(confirmed uint64) error { return nil } -// updateSegment updates the messageCount, start and end indices of the segment -// this should be called using defer whenever a method updates the messages. It -// will do nothing if the message has already been seen by the backlog. -func (s *backlogSegment) updateSegment(seen *bool) { - if !*seen { - c := len(s.messages) - s.messageCount.Store(uint64(c)) - s.start.Store(uint64(s.messages[0].SequenceNumber)) - s.end.Store(uint64(s.messages[c-1].SequenceNumber)) - } -} - // count returns the number of messages stored in the backlog segment. func (s *backlogSegment) count() int { - return int(s.messageCount.Load()) + s.messagesLock.RLock() + defer s.messagesLock.RUnlock() + return len(s.messages) } diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go index 251f11e33..4591f268d 100644 --- a/broadcaster/backlog/backlog_test.go +++ b/broadcaster/backlog/backlog_test.go @@ -18,13 +18,13 @@ func validateBacklog(t *testing.T, b *backlog, count, start, end uint64, lookupK } head := b.head.Load() - if start != 0 && head.start.Load() != start { - t.Errorf("head of backlog (%d) does not equal expected head (%d)", head.start.Load(), start) + if start != 0 && head.Start() != start { + t.Errorf("head of backlog (%d) does not equal expected head (%d)", head.Start(), start) } tail := b.tail.Load() - if end != 0 && tail.end.Load() != end { - t.Errorf("tail of backlog (%d) does not equal expected tail (%d)", tail.end.Load(), end) + if end != 0 && tail.End() != end { + t.Errorf("tail of backlog (%d) does not equal expected tail (%d)", tail.End(), end) } for _, k := range lookupKeys { @@ -157,9 +157,6 @@ func TestDeleteInvalidBacklog(t *testing.T) { s := &backlogSegment{ messages: m.CreateDummyBroadcastMessages([]arbutil.MessageIndex{40, 42}), } - s.start.Store(40) - s.end.Store(42) - s.messageCount.Store(2) lookup := containers.SyncMap[uint64, *backlogSegment]{} lookup.Store(40, s) From 11e26ed0a7a4f530346a30de9d112f14483e94c4 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:33:06 +1300 Subject: [PATCH 440/775] fix go vet errors from containers.SyncMap addition, change to a pointer to containers.SyncMap --- broadcaster/backlog/backlog.go | 6 +++--- broadcaster/backlog/backlog_test.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index f469abe56..86a13e277 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -32,14 +32,14 @@ type Backlog interface { type backlog struct { head atomic.Pointer[backlogSegment] tail atomic.Pointer[backlogSegment] - lookupByIndex containers.SyncMap[uint64, *backlogSegment] + lookupByIndex *containers.SyncMap[uint64, *backlogSegment] config ConfigFetcher messageCount atomic.Uint64 } // NewBacklog creates a backlog. func NewBacklog(c ConfigFetcher) Backlog { - lookup := containers.SyncMap[uint64, *backlogSegment]{} + lookup := &containers.SyncMap[uint64, *backlogSegment]{} return &backlog{ lookupByIndex: lookup, config: c, @@ -230,7 +230,7 @@ func (s *backlog) Count() uint64 { func (b *backlog) reset() { b.head = atomic.Pointer[backlogSegment]{} b.tail = atomic.Pointer[backlogSegment]{} - b.lookupByIndex = containers.SyncMap[uint64, *backlogSegment]{} + b.lookupByIndex = &containers.SyncMap[uint64, *backlogSegment]{} b.messageCount.Store(0) } diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go index 4591f268d..ab25a523f 100644 --- a/broadcaster/backlog/backlog_test.go +++ b/broadcaster/backlog/backlog_test.go @@ -57,7 +57,7 @@ func validateBroadcastMessage(t *testing.T, bm *m.BroadcastMessage, expectedCoun func createDummyBacklog(indexes []arbutil.MessageIndex) (*backlog, error) { b := &backlog{ - lookupByIndex: containers.SyncMap[uint64, *backlogSegment]{}, + lookupByIndex: &containers.SyncMap[uint64, *backlogSegment]{}, config: func() *Config { return &DefaultTestConfig }, } bm := &m.BroadcastMessage{Messages: m.CreateDummyBroadcastMessages(indexes)} @@ -158,7 +158,7 @@ func TestDeleteInvalidBacklog(t *testing.T) { messages: m.CreateDummyBroadcastMessages([]arbutil.MessageIndex{40, 42}), } - lookup := containers.SyncMap[uint64, *backlogSegment]{} + lookup := &containers.SyncMap[uint64, *backlogSegment]{} lookup.Store(40, s) b := &backlog{ lookupByIndex: lookup, From c098840875f35395705d27c282b8ffebbb30ea8b Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:58:37 +1300 Subject: [PATCH 441/775] return nil interface from backlogSegment.Next rather than nil *backlogSegment --- broadcaster/backlog/backlog.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 86a13e277..232a0ab6c 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -292,7 +292,11 @@ func (s *backlogSegment) End() uint64 { // Next returns the next backlogSegment. func (s *backlogSegment) Next() BacklogSegment { - return s.nextSegment.Load() + next := s.nextSegment.Load() + if next == nil { + return nil // return a nil interface instead of a nil *backlogSegment + } + return next } // Messages returns all of the messages stored in the backlogSegment. From ccb64991ec0cf65bcf1dfa014f7a221b08c8598c Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:25:29 +1300 Subject: [PATCH 442/775] return copies of messages slice from backlogSegment.Get and backlogSegment.Messages --- broadcaster/backlog/backlog.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 232a0ab6c..d694b0287 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -64,14 +64,14 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { for _, msg := range bm.Messages { segment := b.tail.Load() if segment == nil { - segment = newBacklogSegment() + segment = newBacklogSegment(b.config) b.head.Store(segment) b.tail.Store(segment) } prevMsgIdx := segment.End() if segment.count() >= b.config().SegmentLimit { - nextSegment := newBacklogSegment() + nextSegment := newBacklogSegment(b.config) segment.nextSegment.Store(nextSegment) prevMsgIdx = segment.End() nextSegment.previousSegment.Store(segment) @@ -247,6 +247,7 @@ type BacklogSegment interface { // backlogSegment stores messages up to a limit defined by the backlog. It also // points to the next backlogSegment in the list. type backlogSegment struct { + config ConfigFetcher messagesLock sync.RWMutex messages []*m.BroadcastFeedMessage nextSegment atomic.Pointer[backlogSegment] @@ -256,8 +257,9 @@ type backlogSegment struct { // newBacklogSegment creates a backlogSegment object with an empty slice of // messages. It does not return an interface as it is only used inside the // backlog library. -func newBacklogSegment() *backlogSegment { +func newBacklogSegment(c ConfigFetcher) *backlogSegment { return &backlogSegment{ + config: c, messages: []*m.BroadcastFeedMessage{}, } } @@ -303,7 +305,9 @@ func (s *backlogSegment) Next() BacklogSegment { func (s *backlogSegment) Messages() []*m.BroadcastFeedMessage { s.messagesLock.RLock() defer s.messagesLock.RUnlock() - return s.messages + tmp := make([]*m.BroadcastFeedMessage, s.config().SegmentLimit) + copy(tmp, s.messages) + return tmp } // Get reads messages from the given start to end message index. @@ -322,7 +326,9 @@ func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, erro s.messagesLock.RLock() defer s.messagesLock.RUnlock() - return s.messages[startIndex:endIndex], nil + tmp := make([]*m.BroadcastFeedMessage, s.config().SegmentLimit) + copy(tmp, s.messages) + return tmp[startIndex:endIndex], nil } // append appends the given BroadcastFeedMessage to messages if it is the first From 25372473fc2ce3f0f5491df45ea53346bfe4f848 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:27:06 +1300 Subject: [PATCH 443/775] get messagesLock for entire backlogSegment.Get and backlogSegment.Contains functions --- broadcaster/backlog/backlog.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index d694b0287..9b5c7dd10 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -312,6 +312,8 @@ func (s *backlogSegment) Messages() []*m.BroadcastFeedMessage { // Get reads messages from the given start to end message index. func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, error) { + s.messagesLock.RLock() + defer s.messagesLock.RUnlock() noMsgs := []*m.BroadcastFeedMessage{} if start < s.Start() { return noMsgs, errOutOfBounds @@ -324,8 +326,6 @@ func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, erro startIndex := start - s.Start() endIndex := end - s.Start() + 1 - s.messagesLock.RLock() - defer s.messagesLock.RUnlock() tmp := make([]*m.BroadcastFeedMessage, s.config().SegmentLimit) copy(tmp, s.messages) return tmp[startIndex:endIndex], nil @@ -355,15 +355,15 @@ func (s *backlogSegment) append(prevMsgIdx uint64, msg *m.BroadcastFeedMessage) // Contains confirms whether the segment contains a message with the given // sequence number. func (s *backlogSegment) Contains(i uint64) bool { + s.messagesLock.RLock() + defer s.messagesLock.RUnlock() start := s.Start() if i < start || i > s.End() { return false } msgIndex := i - start - s.messagesLock.RLock() msg := s.messages[msgIndex] - s.messagesLock.RUnlock() return uint64(msg.SequenceNumber) == i } From 369b5ea649bb063c68e315a98809e90ee2433935 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:31:11 +1300 Subject: [PATCH 444/775] remove metric TODO --- broadcaster/backlog/backlog.go | 1 - 1 file changed, 1 deletion(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 9b5c7dd10..89ee371f1 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -58,7 +58,6 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { if bm.ConfirmedSequenceNumberMessage != nil { b.delete(uint64(bm.ConfirmedSequenceNumberMessage.SequenceNumber)) - // TODO(clamb): add to metric? } for _, msg := range bm.Messages { From 02b66733aa99c9894430353d221d71fecbca0f2d Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 30 Nov 2023 19:12:20 +0530 Subject: [PATCH 445/775] address PR comments --- broadcastclients/broadcastclients.go | 34 +++++++++++++++------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index aa5f39ad9..ed11ab87d 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -142,7 +142,6 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { defer primaryFeedIsDownTimer.Stop() msgHandler := func(msg broadcaster.BroadcastFeedMessage, router *Router) error { - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) if _, ok := recentFeedItemsNew[msg.SequenceNumber]; ok { return nil } @@ -156,7 +155,6 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { return nil } confSeqHandler := func(cs arbutil.MessageIndex, router *Router) { - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) if cs == lastConfirmed { return } @@ -166,56 +164,60 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { } } - // Two select statements to prioritize reading messages from primary feeds' channels + // Multiple select statements to prioritize reading messages from primary feeds' channels and avoid starving of timers for { + select { + // Cycle buckets to get rid of old entries + case <-recentFeedItemsCleanup.C: + recentFeedItemsOld = recentFeedItemsNew + recentFeedItemsNew = make(map[arbutil.MessageIndex]time.Time, RECENT_FEED_INITIAL_MAP_SIZE) + // Primary feeds have been up and running for PRIMARY_FEED_UPTIME=10 mins without a failure, stop the recently started secondary feed + case <-stopSecondaryFeedTimer.C: + bcs.stopSecondaryFeed() + default: + } + select { case <-ctx.Done(): return // Primary feeds case msg := <-bcs.primaryRouter.messageChan: + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) if err := msgHandler(msg, bcs.primaryRouter); err != nil { log.Error("Error routing message from Primary Sequencer Feeds", "err", err) } case cs := <-bcs.primaryRouter.confirmedSequenceNumberChan: + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) confSeqHandler(cs, bcs.primaryRouter) - // Cycle buckets to get rid of old entries - case <-recentFeedItemsCleanup.C: - recentFeedItemsOld = recentFeedItemsNew - recentFeedItemsNew = make(map[arbutil.MessageIndex]time.Time, RECENT_FEED_INITIAL_MAP_SIZE) - // Failed to get messages from both primary and secondary feeds for ~5 seconds, start a new secondary feed - case <-startSecondaryFeedTimer.C: - bcs.startSecondaryFeed(ctx) // Failed to get messages from primary feed for ~5 seconds, reset the timer responsible for stopping a secondary case <-primaryFeedIsDownTimer.C: stopSecondaryFeedTimer.Reset(PRIMARY_FEED_UPTIME) - // Primary feeds have been up and running for PRIMARY_FEED_UPTIME=10 mins without a failure, stop the recently started secondary feed - case <-stopSecondaryFeedTimer.C: - bcs.stopSecondaryFeed() default: select { case <-ctx.Done(): return // Secondary Feeds case msg := <-bcs.secondaryRouter.messageChan: + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) if err := msgHandler(msg, bcs.secondaryRouter); err != nil { log.Error("Error routing message from Secondary Sequencer Feeds", "err", err) } case cs := <-bcs.secondaryRouter.confirmedSequenceNumberChan: + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) confSeqHandler(cs, bcs.secondaryRouter) case msg := <-bcs.primaryRouter.messageChan: + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) if err := msgHandler(msg, bcs.primaryRouter); err != nil { log.Error("Error routing message from Primary Sequencer Feeds", "err", err) } case cs := <-bcs.primaryRouter.confirmedSequenceNumberChan: + startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) confSeqHandler(cs, bcs.primaryRouter) - case <-recentFeedItemsCleanup.C: - recentFeedItemsOld = recentFeedItemsNew - recentFeedItemsNew = make(map[arbutil.MessageIndex]time.Time, RECENT_FEED_INITIAL_MAP_SIZE) case <-startSecondaryFeedTimer.C: bcs.startSecondaryFeed(ctx) case <-primaryFeedIsDownTimer.C: From 59f151b3fbf48b6c0fe03d60b3cf0adab3224235 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 30 Nov 2023 17:58:05 -0700 Subject: [PATCH 446/775] Update arbitrator OSP fuzzer to work with new OSP ABI --- arbitrator/prover/fuzz/fuzz_targets/osp.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arbitrator/prover/fuzz/fuzz_targets/osp.rs b/arbitrator/prover/fuzz/fuzz_targets/osp.rs index 1ceef8355..ddb5ebfdf 100644 --- a/arbitrator/prover/fuzz/fuzz_targets/osp.rs +++ b/arbitrator/prover/fuzz/fuzz_targets/osp.rs @@ -39,10 +39,9 @@ fn get_contract_deployed_bytecode(contract: &str) -> Vec { lazy_static::lazy_static! { static ref OSP_PREFIX: Vec = { let mut data = Vec::new(); - data.extend(hex::decode("2fae8811").unwrap()); // function selector + data.extend(hex::decode("5d3adcfb").unwrap()); // function selector data.extend([0; 32]); // maxInboxMessagesRead - data.extend([0; 32]); // sequencerInbox - data.extend([0; 32]); // delayedInbox + data.extend([0; 32]); // bridge data }; static ref EVM_VICINITY: evm::backend::MemoryVicinity = { From c86fcfdbf5b730cba510cda25ac93a87cdec1868 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:12:29 +1300 Subject: [PATCH 447/775] use length of messages slice in copy rather than segment limit to avoid slice being populated with nils --- broadcaster/backlog/backlog.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 89ee371f1..6e051713b 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -63,14 +63,14 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { for _, msg := range bm.Messages { segment := b.tail.Load() if segment == nil { - segment = newBacklogSegment(b.config) + segment = newBacklogSegment() b.head.Store(segment) b.tail.Store(segment) } prevMsgIdx := segment.End() if segment.count() >= b.config().SegmentLimit { - nextSegment := newBacklogSegment(b.config) + nextSegment := newBacklogSegment() segment.nextSegment.Store(nextSegment) prevMsgIdx = segment.End() nextSegment.previousSegment.Store(segment) @@ -246,7 +246,6 @@ type BacklogSegment interface { // backlogSegment stores messages up to a limit defined by the backlog. It also // points to the next backlogSegment in the list. type backlogSegment struct { - config ConfigFetcher messagesLock sync.RWMutex messages []*m.BroadcastFeedMessage nextSegment atomic.Pointer[backlogSegment] @@ -256,9 +255,8 @@ type backlogSegment struct { // newBacklogSegment creates a backlogSegment object with an empty slice of // messages. It does not return an interface as it is only used inside the // backlog library. -func newBacklogSegment(c ConfigFetcher) *backlogSegment { +func newBacklogSegment() *backlogSegment { return &backlogSegment{ - config: c, messages: []*m.BroadcastFeedMessage{}, } } @@ -304,7 +302,7 @@ func (s *backlogSegment) Next() BacklogSegment { func (s *backlogSegment) Messages() []*m.BroadcastFeedMessage { s.messagesLock.RLock() defer s.messagesLock.RUnlock() - tmp := make([]*m.BroadcastFeedMessage, s.config().SegmentLimit) + tmp := make([]*m.BroadcastFeedMessage, len(s.messages)) copy(tmp, s.messages) return tmp } @@ -325,7 +323,7 @@ func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, erro startIndex := start - s.Start() endIndex := end - s.Start() + 1 - tmp := make([]*m.BroadcastFeedMessage, s.config().SegmentLimit) + tmp := make([]*m.BroadcastFeedMessage, len(s.messages)) copy(tmp, s.messages) return tmp[startIndex:endIndex], nil } From b70648145cee50871a2d1fec24af4cfa6579b01f Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:15:08 +1300 Subject: [PATCH 448/775] change IsBacklogSegmentNil to check for nil interface as backlogSegment.Next now returns a nil interface --- broadcaster/backlog/backlog.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 6e051713b..d39cde29a 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -265,7 +265,12 @@ func newBacklogSegment() *backlogSegment { // variable of type BacklogSegment is nil or not. Comparing whether an // interface is nil directly will not work. func IsBacklogSegmentNil(segment BacklogSegment) bool { - return segment.(*backlogSegment) == nil + if segment == nil { + return true + } else if segment.(*backlogSegment) == nil { + return true + } + return false } // Start returns the first message index within the backlogSegment. From 7334858d0f311a5bdbddec9749e7c4f782fb8d67 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:18:55 +1300 Subject: [PATCH 449/775] add version as a constant to messages lib --- broadcaster/message/message.go | 4 ++++ wsbroadcastserver/clientconnection.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/broadcaster/message/message.go b/broadcaster/message/message.go index d42e0c8b6..f436e765c 100644 --- a/broadcaster/message/message.go +++ b/broadcaster/message/message.go @@ -6,6 +6,10 @@ import ( "github.com/offchainlabs/nitro/arbutil" ) +const ( + V1 = 1 +) + // BroadcastMessage is the base message type for messages to send over the network. // // Acts as a variant holding the message types. The type of the message is diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 9e82b09a6..9036fc8f2 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -137,7 +137,7 @@ func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.Ba msgs = msgs[requestedIdx:] } bm := &m.BroadcastMessage{ - Version: 1, // TODO(clamb): I am unsure if it is correct to hard code the version here like this? It seems to be done in other places though + Version: m.V1, Messages: msgs, } err := cc.writeBroadcastMessage(bm) From 01dd072c106609ec3c3cdb5c12415141a5585f97 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 1 Dec 2023 22:11:48 +0530 Subject: [PATCH 450/775] Make the formula to calculate max fee cap configurable and add time based factor to default formula --- arbnode/dataposter/data_poster.go | 54 ++++++++++++++++++++------- arbnode/dataposter/dataposter_test.go | 25 +++++++++++++ go.mod | 1 + go.sum | 1 + 4 files changed, 67 insertions(+), 14 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 266131a6b..999e2de59 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -17,6 +17,7 @@ import ( "sync" "time" + "github.com/Knetic/govaluate" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -71,6 +72,8 @@ type DataPoster struct { nonce uint64 queue QueueStorage errorCount map[uint64]int // number of consecutive intermittent errors rbf-ing or sending, per nonce + + maxFeeCapExpression *govaluate.EvaluableExpression } // signerFn is a signer function callback when a contract requires a method to @@ -152,6 +155,10 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro default: queue = slice.NewStorage(func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) } + expression, err := govaluate.NewEvaluableExpression(cfg.MaxFeeCapFormula) + if err != nil { + return nil, fmt.Errorf("error creating govaluate evaluable expression for calculating maxFeeCap: %w", err) + } dp := &DataPoster{ headerReader: opts.HeaderReader, client: opts.HeaderReader.Client(), @@ -159,13 +166,14 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro signer: func(_ context.Context, addr common.Address, tx *types.Transaction) (*types.Transaction, error) { return opts.Auth.Signer(addr, tx) }, - config: opts.Config, - usingNoOpStorage: useNoOpStorage, - replacementTimes: replacementTimes, - metadataRetriever: opts.MetadataRetriever, - queue: queue, - redisLock: opts.RedisLock, - errorCount: make(map[uint64]int), + config: opts.Config, + usingNoOpStorage: useNoOpStorage, + replacementTimes: replacementTimes, + metadataRetriever: opts.MetadataRetriever, + queue: queue, + redisLock: opts.RedisLock, + errorCount: make(map[uint64]int), + maxFeeCapExpression: expression, } if cfg.ExternalSigner.URL != "" { signer, sender, err := externalSigner(ctx, &cfg.ExternalSigner) @@ -389,13 +397,19 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u } elapsed := time.Since(dataCreatedAt) - // MaxFeeCap = (BacklogOfBatches^2 * UrgencyGWei^2 + TargetPriceGWei) * GWei - maxFeeCap := - arbmath.FloatToBig( - (float64(arbmath.SquareUint(backlogOfBatches))* - arbmath.SquareFloat(config.UrgencyGwei) + - config.TargetPriceGwei) * - params.GWei) + parameters := make(map[string]interface{}) + parameters["BacklogOfBatches"] = float64(backlogOfBatches) + parameters["UrgencyGWei"] = config.UrgencyGwei + parameters["ElapsedTime"] = float64(elapsed) + parameters["ElapsedTimeBase"] = float64(config.ElapsedTimeBase) + parameters["ElapsedTimeImportance"] = config.ElapsedTimeImportance + parameters["TargetPriceGWei"] = config.TargetPriceGwei + parameters["GWei"] = params.GWei + result, err := p.maxFeeCapExpression.Evaluate(parameters) + if err != nil { + return nil, nil, fmt.Errorf("error evaluating maxFeeCapExpression: %w", err) + } + maxFeeCap := arbmath.FloatToBig(result.(float64)) if arbmath.BigGreaterThan(newFeeCap, maxFeeCap) { log.Warn( "reducing proposed fee cap to current maximum", @@ -756,6 +770,9 @@ type DataPosterConfig struct { LegacyStorageEncoding bool `koanf:"legacy-storage-encoding" reload:"hot"` Dangerous DangerousConfig `koanf:"dangerous"` ExternalSigner ExternalSignerCfg `koanf:"external-signer"` + MaxFeeCapFormula string `koanf:"max-fee-cap-formula" reload:"hot"` + ElapsedTimeBase time.Duration `koanf:"elapsed-time-base" reload:"hot"` + ElapsedTimeImportance float64 `koanf:"elapsed-time-importance" reload:"hot"` } type ExternalSignerCfg struct { @@ -802,6 +819,9 @@ func DataPosterConfigAddOptions(prefix string, f *pflag.FlagSet, defaultDataPost f.Bool(prefix+".use-db-storage", defaultDataPosterConfig.UseDBStorage, "uses database storage when enabled") f.Bool(prefix+".use-noop-storage", defaultDataPosterConfig.UseNoOpStorage, "uses noop storage, it doesn't store anything") f.Bool(prefix+".legacy-storage-encoding", defaultDataPosterConfig.LegacyStorageEncoding, "encodes items in a legacy way (as it was before dropping generics)") + f.String(prefix+".max-fee-cap-formula", defaultDataPosterConfig.MaxFeeCapFormula, "mathematical formula to calculate maximum fee cap") + f.Duration(prefix+".elapsed-time-base", defaultDataPosterConfig.ElapsedTimeBase, "unit to measure the time elapsed since creation of transaction used for maximum fee cap calculation") + f.Float64(prefix+".elapsed-time-importance", defaultDataPosterConfig.ElapsedTimeImportance, "weight given to the units of time elapsed used for maximum fee cap calculation") signature.SimpleHmacConfigAddOptions(prefix+".redis-signer", f) addDangerousOptions(prefix+".dangerous", f) @@ -836,6 +856,9 @@ var DefaultDataPosterConfig = DataPosterConfig{ LegacyStorageEncoding: false, Dangerous: DangerousConfig{ClearDBStorage: false}, ExternalSigner: ExternalSignerCfg{Method: "eth_signTransaction"}, + MaxFeeCapFormula: "(BacklogOfBatches * BacklogOfBatches * UrgencyGWei * UrgencyGWei + (ElapsedTime/ElapsedTimeBase) * (ElapsedTime/ElapsedTimeBase) * ElapsedTimeImportance + TargetPriceGWei) * GWei", + ElapsedTimeBase: 10 * time.Minute, + ElapsedTimeImportance: 10, } var DefaultDataPosterConfigForValidator = func() DataPosterConfig { @@ -859,6 +882,9 @@ var TestDataPosterConfig = DataPosterConfig{ UseNoOpStorage: false, LegacyStorageEncoding: false, ExternalSigner: ExternalSignerCfg{Method: "eth_signTransaction"}, + MaxFeeCapFormula: "(BacklogOfBatches * BacklogOfBatches * UrgencyGWei * UrgencyGWei + (ElapsedTime/ElapsedTimeBase) * (ElapsedTime/ElapsedTimeBase) * ElapsedTimeImportance + TargetPriceGWei) * GWei", + ElapsedTimeBase: 10 * time.Minute, + ElapsedTimeImportance: 10, } var TestDataPosterConfigForValidator = func() DataPosterConfig { diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index d4d72bbbf..0038ed221 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -13,6 +13,7 @@ import ( "testing" "time" + "github.com/Knetic/govaluate" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" @@ -242,3 +243,27 @@ func (s *server) mux(w http.ResponseWriter, r *http.Request) { fmt.Printf("error writing response: %v\n", err) } } + +func TestMaxFeeCapFormulaCalculation(t *testing.T) { + // This test alerts, by failing, if the max fee cap formula were to be changed in the DefaultDataPosterConfig to + // use new variables other than the ones that are keys of 'parameters' map below + expression, err := govaluate.NewEvaluableExpression(DefaultDataPosterConfig.MaxFeeCapFormula) + if err != nil { + t.Fatalf("error creating govaluate evaluable expression for default maxFeeCap formula: %t", err) + } + parameters := make(map[string]interface{}) + parameters["BacklogOfBatches"] = 0 + parameters["UrgencyGWei"] = DefaultDataPosterConfig.UrgencyGwei + parameters["ElapsedTime"] = 0 + parameters["ElapsedTimeBase"] = float64(DefaultDataPosterConfig.ElapsedTimeBase) + parameters["ElapsedTimeImportance"] = DefaultDataPosterConfig.ElapsedTimeImportance + parameters["TargetPriceGWei"] = DefaultDataPosterConfig.TargetPriceGwei + parameters["GWei"] = 0 + result, err := expression.Evaluate(parameters) + if err != nil { + t.Fatalf("error evaluating expression:: %t", err) + } + if result.(float64) != 0 { + t.Fatalf("unexpected result. Got error: %f, want: %d", result.(float64), 0) + } +} diff --git a/go.mod b/go.mod index 598c48e92..bdda6a61a 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ replace github.com/VictoriaMetrics/fastcache => ./fastcache replace github.com/ethereum/go-ethereum => ./go-ethereum require ( + github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible github.com/Shopify/toxiproxy v2.1.4+incompatible github.com/alicebob/miniredis/v2 v2.21.0 github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 diff --git a/go.sum b/go.sum index 1fb8a405f..bf8b4b826 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,7 @@ github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMd github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= From aa59d344b37422beeb42a13ffb9f03527c069e09 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Fri, 1 Dec 2023 13:53:36 -0700 Subject: [PATCH 451/775] Fix chain parameter default Chain parameters were updated to prepare for execution split, but one mention was missed --- cmd/nitro/nitro.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index cee86ab40..cf2155444 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -839,7 +839,7 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c } safeBatchSize := l2MaxTxSize - bufferSpace chainDefaults["node.batch-poster.max-size"] = safeBatchSize - chainDefaults["node.sequencer.max-tx-data-size"] = safeBatchSize - bufferSpace + chainDefaults["execution.sequencer.max-tx-data-size"] = safeBatchSize - bufferSpace } if chainInfo.DasIndexUrl != "" { chainDefaults["node.batch-poster.max-size"] = 1000000 From 1d691791f86329bd7cc16aab100efd33b2e14dfb Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Fri, 1 Dec 2023 14:18:01 -0700 Subject: [PATCH 452/775] Use field name instead of variable name in warning message --- cmd/nitro/nitro.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index cee86ab40..e0b6d326a 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -800,7 +800,7 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c if chainInfo.ParentChainIsArbitrum != nil { parentChainIsArbitrum = *chainInfo.ParentChainIsArbitrum } else { - log.Warn("Chain information parentChainIsArbitrum field missing, in the future this will be required", "chainId", chainInfo.ChainConfig.ChainID, "parentChainId", chainInfo.ParentChainId) + log.Warn("Chain info field parent-chain-is-arbitrum is missing, in the future this will be required", "chainId", chainInfo.ChainConfig.ChainID, "parentChainId", chainInfo.ParentChainId) _, err := chaininfo.ProcessChainInfo(chainInfo.ParentChainId, "", combinedL2ChainInfoFiles, "") if err == nil { parentChainIsArbitrum = true From 55f56f035b05365fa098398c81e4a269410d9dd5 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Fri, 1 Dec 2023 18:29:22 -0700 Subject: [PATCH 453/775] Enable data availability if chaininfo dac is enabled --- cmd/nitro/nitro.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 4089508a1..34319db4e 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -827,6 +827,8 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c chainDefaults["node.data-availability.enable"] = true chainDefaults["node.data-availability.rest-aggregator.enable"] = true chainDefaults["node.data-availability.rest-aggregator.online-url-list"] = chainInfo.DasIndexUrl + } else if chainInfo.ChainConfig.ArbitrumChainParams.DataAvailabilityCommittee { + chainDefaults["node.data-availability.enable"] = true } if !chainInfo.HasGenesisState { chainDefaults["init.empty"] = true From 3eb4212a5657bb7bdb60602136c7989843d905fc Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sat, 2 Dec 2023 12:04:30 -0700 Subject: [PATCH 454/775] Always initialize staker wallet --- arbnode/node.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index e52a698e4..c6e117e70 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -615,10 +615,8 @@ func createNodeImpl( if err != nil { return nil, err } - if stakerObj.Strategy() == staker.WatchtowerStrategy { - if err := wallet.Initialize(ctx); err != nil { - return nil, err - } + if err := wallet.Initialize(ctx); err != nil { + return nil, err } var txValidatorSenderPtr *common.Address if txOptsValidator != nil { From 39514fc316cacb0a184d397d8006616624c381e5 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:09:06 +1300 Subject: [PATCH 455/775] correct broadcaster lib --- broadcastclients/broadcastclients.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index bdf5f16d2..d85ecb2c2 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -141,7 +141,7 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { defer stopSecondaryFeedTimer.Stop() defer primaryFeedIsDownTimer.Stop() - msgHandler := func(msg broadcaster.BroadcastFeedMessage, router *Router) error { + msgHandler := func(msg m.BroadcastFeedMessage, router *Router) error { if _, ok := recentFeedItemsNew[msg.SequenceNumber]; ok { return nil } @@ -149,7 +149,7 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { return nil } recentFeedItemsNew[msg.SequenceNumber] = time.Now() - if err := router.forwardTxStreamer.AddBroadcastMessages([]*broadcaster.BroadcastFeedMessage{&msg}); err != nil { + if err := router.forwardTxStreamer.AddBroadcastMessages([]*m.BroadcastFeedMessage{&msg}); err != nil { return err } return nil From 6d1eca1d246413c0708b0f5095f5bb338abdd24d Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:51:19 +1300 Subject: [PATCH 456/775] only send one message with the confirmed sequence number --- wsbroadcastserver/clientmanager.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/wsbroadcastserver/clientmanager.go b/wsbroadcastserver/clientmanager.go index 7dc0cdcb5..1777da642 100644 --- a/wsbroadcastserver/clientmanager.go +++ b/wsbroadcastserver/clientmanager.go @@ -326,9 +326,12 @@ func (cm *ClientManager) Start(parentCtx context.Context) { var err error for _, msg := range bm.Messages { m := &m.BroadcastMessage{ - Version: bm.Version, - Messages: []*m.BroadcastFeedMessage{msg}, - ConfirmedSequenceNumberMessage: bm.ConfirmedSequenceNumberMessage, + Version: bm.Version, + Messages: []*m.BroadcastFeedMessage{msg}, + } + // This ensures that only one message is sent with the confirmed sequence number + if i == 0 { + m.ConfirmedSequenceNumberMessage = bm.ConfirmedSequenceNumberMessage } clientDeleteList, err = cm.doBroadcast(m) logError(err, "failed to do broadcast") From 511d97493ad20b4f9876dbf1f7313fd5d14c332a Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Sun, 3 Dec 2023 20:31:49 -0700 Subject: [PATCH 457/775] Use chain info if only given one chain info If no chain ID, no chain name, and only a single chain info is specified, use that single chain info. --- cmd/chaininfo/chain_info.go | 10 +++++++++- cmd/nitro/nitro.go | 22 ++++++---------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/cmd/chaininfo/chain_info.go b/cmd/chaininfo/chain_info.go index c0d6b3d00..13e586ced 100644 --- a/cmd/chaininfo/chain_info.go +++ b/cmd/chaininfo/chain_info.go @@ -6,6 +6,7 @@ package chaininfo import ( _ "embed" "encoding/json" + "errors" "fmt" "math/big" "os" @@ -86,7 +87,10 @@ func ProcessChainInfo(chainId uint64, chainName string, l2ChainInfoFiles []strin if chainId != 0 { return nil, fmt.Errorf("unsupported chain ID %v", chainId) } - return nil, fmt.Errorf("unsupported chain name %v", chainName) + if chainName != "" { + return nil, fmt.Errorf("unsupported chain name %v", chainName) + } + return nil, errors.New("must specify --chain.id or --chain.name to choose rollup") } func findChainInfo(chainId uint64, chainName string, chainsInfoBytes []byte) (*ChainInfo, error) { @@ -95,6 +99,10 @@ func findChainInfo(chainId uint64, chainName string, chainsInfoBytes []byte) (*C if err != nil { return nil, err } + if chainId == 0 && chainName == "" && len(chainsInfo) == 1 { + // If single chain info and no chain id/name given, default to single chain info + return &chainsInfo[0], nil + } for _, chainInfo := range chainsInfo { if (chainId == 0 || chainInfo.ChainConfig.ChainID.Uint64() == chainId) && (chainName == "" || chainInfo.ChainName == chainName) { return &chainInfo, nil diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 4089508a1..e50bc960a 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -718,12 +718,9 @@ func ParseNode(ctx context.Context, args []string) (*NodeConfig, *genericconf.Wa l2ChainName := k.String("chain.name") l2ChainInfoIpfsUrl := k.String("chain.info-ipfs-url") l2ChainInfoIpfsDownloadPath := k.String("chain.info-ipfs-download-path") - if l2ChainId == 0 && l2ChainName == "" { - return nil, nil, nil, errors.New("must specify --chain.id or --chain.name to choose rollup") - } l2ChainInfoFiles := k.Strings("chain.info-files") l2ChainInfoJson := k.String("chain.info-json") - chainFound, err := applyChainParameters(ctx, k, uint64(l2ChainId), l2ChainName, l2ChainInfoFiles, l2ChainInfoJson, l2ChainInfoIpfsUrl, l2ChainInfoIpfsDownloadPath) + err = applyChainParameters(ctx, k, uint64(l2ChainId), l2ChainName, l2ChainInfoFiles, l2ChainInfoJson, l2ChainInfoIpfsUrl, l2ChainInfoIpfsDownloadPath) if err != nil { return nil, nil, nil, err } @@ -752,13 +749,6 @@ func ParseNode(ctx context.Context, args []string) (*NodeConfig, *genericconf.Wa } if nodeConfig.Persistent.Chain == "" { - if !chainFound { - // If persistent-chain not defined, user not creating custom chain - if l2ChainId != 0 { - return nil, nil, nil, fmt.Errorf("Unknown chain id: %d, L2ChainInfoFiles: %v. update chain id, modify --chain.info-files or provide --persistent.chain\n", l2ChainId, l2ChainInfoFiles) - } - return nil, nil, nil, fmt.Errorf("Unknown chain name: %s, L2ChainInfoFiles: %v. update chain name, modify --chain.info-files or provide --persistent.chain\n", l2ChainName, l2ChainInfoFiles) - } return nil, nil, nil, errors.New("--persistent.chain not specified") } @@ -783,7 +773,7 @@ func ParseNode(ctx context.Context, args []string) (*NodeConfig, *genericconf.Wa return &nodeConfig, &l1Wallet, &l2DevWallet, nil } -func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, chainName string, l2ChainInfoFiles []string, l2ChainInfoJson string, l2ChainInfoIpfsUrl string, l2ChainInfoIpfsDownloadPath string) (bool, error) { +func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, chainName string, l2ChainInfoFiles []string, l2ChainInfoJson string, l2ChainInfoIpfsUrl string, l2ChainInfoIpfsDownloadPath string) error { combinedL2ChainInfoFiles := l2ChainInfoFiles if l2ChainInfoIpfsUrl != "" { l2ChainInfoIpfsFile, err := util.GetL2ChainInfoIpfsFile(ctx, l2ChainInfoIpfsUrl, l2ChainInfoIpfsDownloadPath) @@ -794,7 +784,7 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c } chainInfo, err := chaininfo.ProcessChainInfo(chainId, chainName, combinedL2ChainInfoFiles, l2ChainInfoJson) if err != nil { - return false, err + return err } var parentChainIsArbitrum bool if chainInfo.ParentChainIsArbitrum != nil { @@ -835,7 +825,7 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c l2MaxTxSize := gethexec.DefaultSequencerConfig.MaxTxDataSize bufferSpace := 5000 if l2MaxTxSize < bufferSpace*2 { - return false, fmt.Errorf("not enough room in parent chain max tx size %v for bufferSpace %v * 2", l2MaxTxSize, bufferSpace) + return fmt.Errorf("not enough room in parent chain max tx size %v for bufferSpace %v * 2", l2MaxTxSize, bufferSpace) } safeBatchSize := l2MaxTxSize - bufferSpace chainDefaults["node.batch-poster.max-size"] = safeBatchSize @@ -846,9 +836,9 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c } err = k.Load(confmap.Provider(chainDefaults, "."), nil) if err != nil { - return false, err + return err } - return true, nil + return nil } type NodeConfigFetcher struct { From ebed210b79746213ef53e89a8a2cb185061c78c5 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Mon, 4 Dec 2023 16:53:17 +1300 Subject: [PATCH 458/775] add comment explaining additional doBroadcast call for confirmed messages --- wsbroadcastserver/clientmanager.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wsbroadcastserver/clientmanager.go b/wsbroadcastserver/clientmanager.go index 1777da642..432864dd6 100644 --- a/wsbroadcastserver/clientmanager.go +++ b/wsbroadcastserver/clientmanager.go @@ -337,6 +337,8 @@ func (cm *ClientManager) Start(parentCtx context.Context) { logError(err, "failed to do broadcast") } + // A message with ConfirmedSequenceNumberMessage could be sent without any messages + // this section ensures that message is still sent. if len(bm.Messages) == 0 { clientDeleteList, err = cm.doBroadcast(bm) logError(err, "failed to do broadcast") From fb177175a36afa5c1d8d703a7feec1aa8a319e34 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Mon, 4 Dec 2023 17:02:50 +1300 Subject: [PATCH 459/775] move last sent sequence number check from client manager to client connection --- wsbroadcastserver/clientconnection.go | 5 +++++ wsbroadcastserver/clientmanager.go | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 9036fc8f2..8069c847b 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -226,6 +226,11 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { case <-ctx.Done(): return case msg := <-cc.out: + if msg.sequenceNumber != nil && uint64(*msg.sequenceNumber) <= cc.LastSentSeqNum.Load() { + log.Debug("client has already sent message with this sequence number, skipping the message", "client", client.Name, "sequence number", *seqNum) + continue + } + expSeqNum := cc.LastSentSeqNum.Load() + 1 if !cc.backlogSent && msg.sequenceNumber != nil && uint64(*msg.sequenceNumber) > expSeqNum { catchupSeqNum := uint64(*msg.sequenceNumber) - 1 diff --git a/wsbroadcastserver/clientmanager.go b/wsbroadcastserver/clientmanager.go index 432864dd6..82113874c 100644 --- a/wsbroadcastserver/clientmanager.go +++ b/wsbroadcastserver/clientmanager.go @@ -197,11 +197,6 @@ func (cm *ClientManager) doBroadcast(bm *m.BroadcastMessage) ([]*ClientConnectio return nil, fmt.Errorf("doBroadcast was sent %d BroadcastFeedMessages, it can only parse 1 BroadcastFeedMessage at a time", n) } - if seqNum != nil && uint64(*seqNum) <= client.LastSentSeqNum.Load() { - log.Warn("client has already sent message with this sequence number, skipping the message", "client", client.Name, "sequence number", *seqNum) - continue - } - m := message{ sequenceNumber: seqNum, data: data, From 93144bf2fa572b4965548caf8bb61507ac5842b4 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Mon, 4 Dec 2023 17:31:51 +1300 Subject: [PATCH 460/775] fix sending only 1 message on confirm --- wsbroadcastserver/clientmanager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsbroadcastserver/clientmanager.go b/wsbroadcastserver/clientmanager.go index 82113874c..a88716756 100644 --- a/wsbroadcastserver/clientmanager.go +++ b/wsbroadcastserver/clientmanager.go @@ -319,7 +319,7 @@ func (cm *ClientManager) Start(parentCtx context.Context) { } case bm := <-cm.broadcastChan: var err error - for _, msg := range bm.Messages { + for i, msg := range bm.Messages { m := &m.BroadcastMessage{ Version: bm.Version, Messages: []*m.BroadcastFeedMessage{msg}, From 42388916747ced7c77c92d5bfb4e681e98a1d31f Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Mon, 4 Dec 2023 17:32:05 +1300 Subject: [PATCH 461/775] change warn to debug --- wsbroadcastserver/clientconnection.go | 1 - 1 file changed, 1 deletion(-) diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 8069c847b..0c875f7fc 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -237,7 +237,6 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { bm, err := cc.backlog.Get(expSeqNum, catchupSeqNum) if err != nil { logWarn(err, fmt.Sprintf("error reading messages %d to %d from backlog", expSeqNum, catchupSeqNum)) - cc.Remove() return } From 0bd866ada50dd3df78aa75b0d380d80acc790920 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Mon, 4 Dec 2023 17:55:46 +1300 Subject: [PATCH 462/775] fix moving last sent check --- wsbroadcastserver/clientconnection.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 0c875f7fc..49cd2af7e 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -227,7 +227,7 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { return case msg := <-cc.out: if msg.sequenceNumber != nil && uint64(*msg.sequenceNumber) <= cc.LastSentSeqNum.Load() { - log.Debug("client has already sent message with this sequence number, skipping the message", "client", client.Name, "sequence number", *seqNum) + log.Debug("client has already sent message with this sequence number, skipping the message", "client", cc.Name, "sequence number", *msg.sequenceNumber) continue } From f242dea2defdce1e40663d2fafca55302ff1faa2 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 4 Dec 2023 13:05:01 +0100 Subject: [PATCH 463/775] Set dataposter address in batchposter after initializing dataposter --- arbnode/batch_poster.go | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index d96ed5723..cc9d2f428 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -270,16 +270,6 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e bridgeAddr: opts.DeployInfo.Bridge, daWriter: opts.DAWriter, redisLock: redisLock, - accessList: func(SequencerInboxAccs, AfterDelayedMessagesRead int) types.AccessList { - return AccessList(&AccessListOpts{ - SequencerInboxAddr: opts.DeployInfo.SequencerInbox, - DataPosterAddr: opts.TransactOpts.From, - BridgeAddr: opts.DeployInfo.Bridge, - GasRefunderAddr: opts.Config().gasRefunder, - SequencerInboxAccs: SequencerInboxAccs, - AfterDelayedMessagesRead: AfterDelayedMessagesRead, - }) - }, } dataPosterConfigFetcher := func() *dataposter.DataPosterConfig { return &(opts.Config().DataPoster) @@ -298,6 +288,18 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e if err != nil { return nil, err } + // Dataposter sender may be external signer address, so we should initialize + // access list after initializing dataposter. + b.accessList = func(SequencerInboxAccs, AfterDelayedMessagesRead int) types.AccessList { + return AccessList(&AccessListOpts{ + SequencerInboxAddr: opts.DeployInfo.SequencerInbox, + DataPosterAddr: b.dataPoster.Sender(), + BridgeAddr: opts.DeployInfo.Bridge, + GasRefunderAddr: opts.Config().gasRefunder, + SequencerInboxAccs: SequencerInboxAccs, + AfterDelayedMessagesRead: AfterDelayedMessagesRead, + }) + } return b, nil } From 089855af86794c7da88bff3f49dad0f319ade356 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 4 Dec 2023 14:57:24 +0100 Subject: [PATCH 464/775] Implement e2e test with nitro node and external signer --- system_tests/batch_poster_test.go | 56 ++++++++- system_tests/external_signer.go | 188 ++++++++++++++++++++++++++++++ 2 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 system_tests/external_signer.go diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 8561e3ffc..026c892fa 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -8,14 +8,20 @@ import ( "crypto/rand" "fmt" "math/big" + "net/http" + "os" + "strings" "testing" "time" "github.com/andybalholm/brotli" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/solgen/go/bridgegen" + "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" "github.com/offchainlabs/nitro/util/redisutil" ) @@ -27,8 +33,49 @@ func TestRedisBatchPosterParallel(t *testing.T) { testBatchPosterParallel(t, true) } +func addNewBatchPoster(ctx context.Context, t *testing.T, builder *NodeBuilder, address common.Address) { + t.Helper() + upgradeExecutor, err := upgrade_executorgen.NewUpgradeExecutor(builder.L2.ConsensusNode.DeployInfo.UpgradeExecutor, builder.L1.Client) + if err != nil { + t.Fatal("Failed to get new upgrade executor", err) + } + sequencerInboxABI, err := abi.JSON(strings.NewReader(bridgegen.SequencerInboxABI)) + if err != nil { + t.Fatal("Failed to parse sequencer inbox abi", err) + } + setIsBatchPoster, err := sequencerInboxABI.Pack("setIsBatchPoster", address, true) + if err != nil { + t.Fatal("Failed to pack setIsBatchPoster", err) + } + ownerOpts := builder.L1Info.GetDefaultTransactOpts("RollupOwner", ctx) + tx, err := upgradeExecutor.ExecuteCall( + &ownerOpts, + builder.L1Info.GetAddress("SequencerInbox"), + setIsBatchPoster) + if err != nil { + t.Fatalf("Error creating transaction to set batch poster: %v", err) + } + if _, err := builder.L1.EnsureTxSucceeded(tx); err != nil { + t.Fatalf("Error setting batch poster: %v", err) + } +} + func testBatchPosterParallel(t *testing.T, useRedis bool) { t.Parallel() + ctx := context.Background() + httpSrv, srv := newServer(ctx, t) + t.Cleanup(func() { + if err := httpSrv.Shutdown(ctx); err != nil { + t.Fatalf("Error shutting down http server: %v", err) + } + }) + go func() { + fmt.Println("Server is listening on port 1234...") + if err := httpSrv.ListenAndServeTLS(signerServerCert, signerServerKey); err != nil && err != http.ErrServerClosed { + fmt.Fprintf(os.Stdout, "ListenAndServeTLS() unexpected error: %v", err) + return + } + }() ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -48,14 +95,19 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { builder := NewNodeBuilder(ctx).DefaultConfig(t, true) builder.nodeConfig.BatchPoster.Enable = false builder.nodeConfig.BatchPoster.RedisUrl = redisUrl + builder.nodeConfig.BatchPoster.DataPoster.ExternalSigner = *externalSignerTestCfg(srv.address) + cleanup := builder.Build(t) defer cleanup() - testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{}) defer cleanupB() - builder.L2Info.GenerateAccount("User2") + addNewBatchPoster(ctx, t, builder, srv.address) + + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTxTo("Faucet", &srv.address, 30000, big.NewInt(1e18), nil)}) + var txs []*types.Transaction for i := 0; i < 100; i++ { diff --git a/system_tests/external_signer.go b/system_tests/external_signer.go new file mode 100644 index 000000000..1ee9c8558 --- /dev/null +++ b/system_tests/external_signer.go @@ -0,0 +1,188 @@ +package arbtest + +import ( + "context" + "crypto/tls" + "crypto/x509" + "encoding/json" + "fmt" + "io" + "math/big" + "net/http" + "os" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/signer/core/apitypes" + "github.com/offchainlabs/nitro/arbnode/dataposter" +) + +var ( + signerPort = 1234 + signerURL = fmt.Sprintf("https://localhost:%v", signerPort) + signerMethod = "test_signTransaction" + signerServerCert = "../arbnode/dataposter/testdata/localhost.crt" + signerServerKey = "../arbnode/dataposter/testdata/localhost.key" + signerClientCert = "../arbnode/dataposter/testdata/client.crt" + signerClientPrivateKey = "../arbnode/dataposter/testdata/client.key" +) + +func externalSignerTestCfg(addr common.Address) *dataposter.ExternalSignerCfg { + return &dataposter.ExternalSignerCfg{ + Address: common.Bytes2Hex(addr.Bytes()), + URL: signerURL, + Method: signerMethod, + RootCA: signerServerCert, + ClientCert: signerClientCert, + ClientPrivateKey: signerClientPrivateKey, + } +} + +type server struct { + handlers map[string]func(*json.RawMessage) (string, error) + signerFn bind.SignerFn + address common.Address +} + +type request struct { + ID *json.RawMessage `json:"id"` + Method string `json:"method"` + Params *json.RawMessage `json:"params"` +} + +type response struct { + ID *json.RawMessage `json:"id"` + Result string `json:"result,omitempty"` +} + +// newServer returns http server and server struct that implements RPC methods. +// It sets up an account in temporary directory and cleans up after test is +// done. +func newServer(ctx context.Context, t *testing.T) (*http.Server, *server) { + t.Helper() + signer, address, err := setupAccount("/tmp/keystore") + if err != nil { + t.Fatalf("Error setting up account: %v", err) + } + t.Cleanup(func() { os.RemoveAll("/tmp/keystore") }) + + s := &server{signerFn: signer, address: address} + s.handlers = map[string]func(*json.RawMessage) (string, error){ + signerMethod: s.signTransaction, + } + m := http.NewServeMux() + + clientCert, err := os.ReadFile(signerClientCert) + if err != nil { + t.Fatalf("Error reading client certificate: %v", err) + } + pool := x509.NewCertPool() + pool.AppendCertsFromPEM(clientCert) + + httpSrv := &http.Server{ + Addr: fmt.Sprintf(":%v", signerPort), + Handler: m, + ReadTimeout: 5 * time.Second, + TLSConfig: &tls.Config{ + MinVersion: tls.VersionTLS12, + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: pool, + }, + } + m.HandleFunc("/", s.mux) + return httpSrv, s +} + +// setupAccount creates a new account in a given directory, unlocks it, creates +// signer with that account and returns it along with account address. +func setupAccount(dir string) (bind.SignerFn, common.Address, error) { + ks := keystore.NewKeyStore( + dir, + keystore.StandardScryptN, + keystore.StandardScryptP, + ) + a, err := ks.NewAccount("password") + if err != nil { + return nil, common.Address{}, fmt.Errorf("creating account account: %w", err) + } + if err := ks.Unlock(a, "password"); err != nil { + return nil, common.Address{}, fmt.Errorf("unlocking account: %w", err) + } + txOpts, err := bind.NewKeyStoreTransactorWithChainID(ks, a, big.NewInt(1337)) + if err != nil { + return nil, common.Address{}, fmt.Errorf("creating transactor: %w", err) + } + return txOpts.Signer, a.Address, nil +} + +// UnmarshallFirst unmarshalls slice of params and returns the first one. +// Parameters in Go ethereum RPC calls are marashalled as slices. E.g. +// eth_sendRawTransaction or eth_signTransaction, marshall transaction as a +// slice of transactions in a message: +// https://github.com/ethereum/go-ethereum/blob/0004c6b229b787281760b14fb9460ffd9c2496f1/rpc/client.go#L548 +func unmarshallFirst(params []byte) (*types.Transaction, error) { + var arr []apitypes.SendTxArgs + if err := json.Unmarshal(params, &arr); err != nil { + return nil, fmt.Errorf("unmarshaling first param: %w", err) + } + if len(arr) != 1 { + return nil, fmt.Errorf("argument should be a single transaction, but got: %d", len(arr)) + } + return arr[0].ToTransaction(), nil +} + +func (s *server) signTransaction(params *json.RawMessage) (string, error) { + tx, err := unmarshallFirst(*params) + if err != nil { + return "", err + } + signedTx, err := s.signerFn(s.address, tx) + if err != nil { + return "", fmt.Errorf("signing transaction: %w", err) + } + data, err := rlp.EncodeToBytes(signedTx) + if err != nil { + return "", fmt.Errorf("rlp encoding transaction: %w", err) + } + return hexutil.Encode(data), nil +} + +func (s *server) mux(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "can't read body", http.StatusBadRequest) + return + } + var req request + if err := json.Unmarshal(body, &req); err != nil { + http.Error(w, "can't unmarshal JSON request", http.StatusBadRequest) + return + } + method, ok := s.handlers[req.Method] + if !ok { + http.Error(w, "method not found", http.StatusNotFound) + return + } + result, err := method(req.Params) + if err != nil { + fmt.Printf("error calling method: %v\n", err) + http.Error(w, "error calling method", http.StatusInternalServerError) + return + } + resp := response{ID: req.ID, Result: result} + respBytes, err := json.Marshal(resp) + if err != nil { + http.Error(w, fmt.Sprintf("error encoding response: %v", err), http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + if _, err := w.Write(respBytes); err != nil { + fmt.Printf("error writing response: %v\n", err) + } +} From a7bf03a959e7a295b1d493ad36e179f48cd973e2 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 4 Dec 2023 15:09:20 +0100 Subject: [PATCH 465/775] Use already created context object instead of creating new one again --- system_tests/batch_poster_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 026c892fa..61f13cab8 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -62,7 +62,8 @@ func addNewBatchPoster(ctx context.Context, t *testing.T, builder *NodeBuilder, func testBatchPosterParallel(t *testing.T, useRedis bool) { t.Parallel() - ctx := context.Background() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() httpSrv, srv := newServer(ctx, t) t.Cleanup(func() { if err := httpSrv.Shutdown(ctx); err != nil { @@ -76,8 +77,6 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { return } }() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() var redisUrl string if useRedis { From 8db341a024fa6adef8f9b2238e5c073c7d917d23 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 4 Dec 2023 15:12:00 +0100 Subject: [PATCH 466/775] Use log instead of fmt --- system_tests/batch_poster_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 61f13cab8..f0c115e2f 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -9,7 +9,6 @@ import ( "fmt" "math/big" "net/http" - "os" "strings" "testing" "time" @@ -18,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/solgen/go/bridgegen" @@ -71,9 +71,9 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { } }) go func() { - fmt.Println("Server is listening on port 1234...") + log.Debug("Server is listening on port 1234...") if err := httpSrv.ListenAndServeTLS(signerServerCert, signerServerKey); err != nil && err != http.ErrServerClosed { - fmt.Fprintf(os.Stdout, "ListenAndServeTLS() unexpected error: %v", err) + log.Debug("ListenAndServeTLS() failed", "error", err) return } }() From a378c577f7a3ecfb580e69752be6c713c3fa790a Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 4 Dec 2023 20:02:09 +0530 Subject: [PATCH 467/775] address PR comments --- cmd/nitro/nitro.go | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 527da6a97..c113d0897 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -491,9 +491,10 @@ func mainImpl() int { return 1 } - // Validate sequencer's MaxTxDataSize and batchPoster's MaxSize params + // Validate sequencer's MaxTxDataSize and batchPoster's MaxSize params. config := liveNodeConfig.Get() executionRevertedRegexp := regexp.MustCompile("(?i)execution reverted") + // SequencerInbox's maxDataSize is defaulted to 117964 which is 90% of Geth's 128KB tx size limit, leaving ~13KB for proving. seqInboxMaxDataSize := 117964 if config.Node.ParentChainReader.Enable { seqInbox, err := bridgegen.NewSequencerInbox(rollupAddrs.SequencerInbox, l1Client) @@ -508,20 +509,20 @@ func mainImpl() int { return 1 } } - // If sequencer is enabled, validate MaxTxDataSize to be at least 5kB below the batch poster MaxSize, and at least 15kB below the sequencer inbox’s max data size. - if config.Execution.Sequencer.Enable { - seqMaxTxDataSize := config.Execution.Sequencer.MaxTxDataSize - batchPosterMaxSize := config.Node.BatchPoster.MaxSize - if seqMaxTxDataSize > batchPosterMaxSize-5000 || seqMaxTxDataSize > seqInboxMaxDataSize-15000 { - log.Error("sequencer's MaxTxDataSize too large") + // If batchPoster is enabled, validate MaxSize to be at least 10kB below the sequencer inbox’s maxDataSize if the data availability service is not enabled. + // The 10kB gap is because its possible for the batch poster to exceed its MaxSize limit and produce batches of slightly larger size. + if config.Node.BatchPoster.Enable && !config.Node.DataAvailability.Enable { + if config.Node.BatchPoster.MaxSize > seqInboxMaxDataSize-10000 { + log.Error("batchPoster's MaxSize is too large") return 1 } } - // If batchPoster is enabled, validate MaxSize to be at least 10kB below the sequencer inbox’s max data size if the data availability service is not enabled. - if config.Node.BatchPoster.Enable && !config.Node.DataAvailability.Enable { - batchPosterMaxSize := config.Node.BatchPoster.MaxSize - if batchPosterMaxSize > seqInboxMaxDataSize-10000 { - log.Error("batchPoster's MaxSize is too large") + // If sequencer is enabled, validate MaxTxDataSize to be at least 5kB below the batch poster's MaxSize to allow space for headers and such. + // And since batchposter's MaxSize is to be at least 10kB below the sequencer inbox’s maxDataSize, this leads to another condition of atlest 15kB below the sequencer inbox’s maxDataSize. + if config.Execution.Sequencer.Enable { + if config.Execution.Sequencer.MaxTxDataSize > config.Node.BatchPoster.MaxSize-5000 || + config.Execution.Sequencer.MaxTxDataSize > seqInboxMaxDataSize-15000 { + log.Error("sequencer's MaxTxDataSize too large") return 1 } } From 514ccbcf0b0b4221be0772f03d72d1887a5dba09 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 4 Dec 2023 17:20:11 +0100 Subject: [PATCH 468/775] Don't require account for sequencer if external signer is enabled --- cmd/nitro/nitro.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 4089508a1..ddb18beeb 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -232,7 +232,10 @@ func mainImpl() int { var dataSigner signature.DataSignerFunc var l1TransactionOptsValidator *bind.TransactOpts var l1TransactionOptsBatchPoster *bind.TransactOpts - sequencerNeedsKey := (nodeConfig.Node.Sequencer && !nodeConfig.Node.Feed.Output.DisableSigning) || nodeConfig.Node.BatchPoster.Enable + // If sequencer and signing is enabled or batchposter is enabled without + // external signing sequencer will need a key. + sequencerNeedsKey := (nodeConfig.Node.Sequencer && !nodeConfig.Node.Feed.Output.DisableSigning) || + (nodeConfig.Node.BatchPoster.Enable && nodeConfig.Node.BatchPoster.DataPoster.ExternalSigner.URL != "") validatorNeedsKey := nodeConfig.Node.Staker.OnlyCreateWalletContract || nodeConfig.Node.Staker.Enable && !strings.EqualFold(nodeConfig.Node.Staker.Strategy, "watchtower") l1Wallet.ResolveDirectoryNames(nodeConfig.Persistent.Chain) From 04274025c1e380f36a7c33402ef75ed947dd5af2 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 4 Dec 2023 17:38:19 +0100 Subject: [PATCH 469/775] Fix logit when to require sequencer key --- cmd/nitro/nitro.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index ddb18beeb..da88060dd 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -235,7 +235,7 @@ func mainImpl() int { // If sequencer and signing is enabled or batchposter is enabled without // external signing sequencer will need a key. sequencerNeedsKey := (nodeConfig.Node.Sequencer && !nodeConfig.Node.Feed.Output.DisableSigning) || - (nodeConfig.Node.BatchPoster.Enable && nodeConfig.Node.BatchPoster.DataPoster.ExternalSigner.URL != "") + (nodeConfig.Node.BatchPoster.Enable && nodeConfig.Node.BatchPoster.DataPoster.ExternalSigner.URL == "") validatorNeedsKey := nodeConfig.Node.Staker.OnlyCreateWalletContract || nodeConfig.Node.Staker.Enable && !strings.EqualFold(nodeConfig.Node.Staker.Strategy, "watchtower") l1Wallet.ResolveDirectoryNames(nodeConfig.Persistent.Chain) From 5af2a8e573a53187338faa205a82b5b9f2495bf7 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 4 Dec 2023 17:41:38 +0100 Subject: [PATCH 470/775] Fix Validator when using external signer to use correct From address, don't require wallet for validator if external signer is enabled --- arbnode/dataposter/data_poster.go | 34 ++++++++++++++++++++----------- arbnode/node.go | 4 ++-- cmd/nitro/nitro.go | 5 +++-- contracts | 2 +- staker/validatorwallet/eoa.go | 4 ++-- system_tests/staker_test.go | 34 ++++++++++++++++++++++++------- 6 files changed, 57 insertions(+), 26 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 266131a6b..50d8bfcc9 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -52,7 +52,7 @@ type DataPoster struct { stopwaiter.StopWaiter headerReader *headerreader.HeaderReader client arbutil.L1Interface - sender common.Address + auth *bind.TransactOpts signer signerFn redisLock AttemptLocker config ConfigFetcher @@ -155,7 +155,7 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro dp := &DataPoster{ headerReader: opts.HeaderReader, client: opts.HeaderReader.Client(), - sender: opts.Auth.From, + auth: opts.Auth, signer: func(_ context.Context, addr common.Address, tx *types.Transaction) (*types.Transaction, error) { return opts.Auth.Signer(addr, tx) }, @@ -172,7 +172,13 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro if err != nil { return nil, err } - dp.signer, dp.sender = signer, sender + dp.signer = signer + dp.auth = &bind.TransactOpts{ + From: sender, + Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) { + return signer(context.TODO(), address, tx) + }, + } } return dp, nil } @@ -251,8 +257,12 @@ func externalSigner(ctx context.Context, opts *ExternalSignerCfg) (signerFn, com }, sender, nil } +func (p *DataPoster) Auth() *bind.TransactOpts { + return p.auth +} + func (p *DataPoster) Sender() common.Address { - return p.sender + return p.auth.From } func (p *DataPoster) MaxMempoolTransactions() uint64 { @@ -279,7 +289,7 @@ func (p *DataPoster) canPostWithNonce(ctx context.Context, nextNonce uint64) err // Check that posting a new transaction won't exceed maximum pending // transactions in mempool. if cfg.MaxMempoolTransactions > 0 { - unconfirmedNonce, err := p.client.NonceAt(ctx, p.sender, nil) + unconfirmedNonce, err := p.client.NonceAt(ctx, p.Sender(), nil) if err != nil { return fmt.Errorf("getting nonce of a dataposter sender: %w", err) } @@ -322,7 +332,7 @@ func (p *DataPoster) getNextNonceAndMaybeMeta(ctx context.Context) (uint64, []by // Fall back to using a recent block to get the nonce. This is safe because there's nothing in the queue. nonceQueryBlock := arbmath.UintToBig(arbmath.SaturatingUSub(blockNum, 1)) log.Warn("failed to update nonce with queue empty; falling back to using a recent block", "recentBlock", nonceQueryBlock, "err", err) - nonce, err := p.client.NonceAt(ctx, p.sender, nonceQueryBlock) + nonce, err := p.client.NonceAt(ctx, p.Sender(), nonceQueryBlock) if err != nil { return 0, nil, false, fmt.Errorf("failed to get nonce at block %v: %w", nonceQueryBlock, err) } @@ -360,7 +370,7 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u return nil, nil, fmt.Errorf("latest parent chain block %v missing BaseFee (either the parent chain does not have EIP-1559 or the parent chain node is not synced)", latestHeader.Number) } softConfBlock := arbmath.BigSubByUint(latestHeader.Number, config.NonceRbfSoftConfs) - softConfNonce, err := p.client.NonceAt(ctx, p.sender, softConfBlock) + softConfNonce, err := p.client.NonceAt(ctx, p.Sender(), softConfBlock) if err != nil { return nil, nil, fmt.Errorf("failed to get latest nonce %v blocks ago (block %v): %w", config.NonceRbfSoftConfs, softConfBlock, err) } @@ -476,7 +486,7 @@ func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Tim Data: calldata, AccessList: accessList, } - fullTx, err := p.signer(ctx, p.sender, types.NewTx(&inner)) + fullTx, err := p.signer(ctx, p.Sender(), types.NewTx(&inner)) if err != nil { return nil, fmt.Errorf("signing transaction: %w", err) } @@ -555,7 +565,7 @@ func (p *DataPoster) replaceTx(ctx context.Context, prevTx *storage.QueuedTransa newTx.Sent = false newTx.Data.GasFeeCap = newFeeCap newTx.Data.GasTipCap = newTipCap - newTx.FullTx, err = p.signer(ctx, p.sender, types.NewTx(&newTx.Data)) + newTx.FullTx, err = p.signer(ctx, p.Sender(), types.NewTx(&newTx.Data)) if err != nil { return err } @@ -578,7 +588,7 @@ func (p *DataPoster) updateNonce(ctx context.Context) error { if p.lastBlock != nil && arbmath.BigEquals(p.lastBlock, header.Number) { return nil } - nonce, err := p.client.NonceAt(ctx, p.sender, header.Number) + nonce, err := p.client.NonceAt(ctx, p.Sender(), header.Number) if err != nil { if p.lastBlock != nil { log.Warn("Failed to get current nonce", "lastBlock", p.lastBlock, "newBlock", header.Number, "err", err) @@ -616,7 +626,7 @@ func (p *DataPoster) updateNonce(ctx context.Context) error { func (p *DataPoster) updateBalance(ctx context.Context) error { // Use the pending (representated as -1) balance because we're looking at batches we'd post, // so we want to see how much gas we could afford with our pending state. - balance, err := p.client.BalanceAt(ctx, p.sender, big.NewInt(-1)) + balance, err := p.client.BalanceAt(ctx, p.Sender(), big.NewInt(-1)) if err != nil { return err } @@ -671,7 +681,7 @@ func (p *DataPoster) Start(ctxIn context.Context) { if maxTxsToRbf == 0 { maxTxsToRbf = 512 } - unconfirmedNonce, err := p.client.NonceAt(ctx, p.sender, nil) + unconfirmedNonce, err := p.client.NonceAt(ctx, p.Sender(), nil) if err != nil { log.Warn("Failed to get latest nonce", "err", err) return minWait diff --git a/arbnode/node.go b/arbnode/node.go index c6e117e70..87afcd7a2 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -580,7 +580,7 @@ func createNodeImpl( // creation into multiple helpers. var wallet staker.ValidatorWalletInterface = validatorwallet.NewNoOp(l1client, deployInfo.Rollup) if !strings.EqualFold(config.Staker.Strategy, "watchtower") { - if config.Staker.UseSmartContractWallet || txOptsValidator == nil { + if config.Staker.UseSmartContractWallet || (txOptsValidator == nil && config.Staker.DataPoster.ExternalSigner.URL == "") { var existingWalletAddress *common.Address if len(config.Staker.ContractWalletAddress) > 0 { if !common.IsHexAddress(config.Staker.ContractWalletAddress) { @@ -598,7 +598,7 @@ func createNodeImpl( if len(config.Staker.ContractWalletAddress) > 0 { return nil, errors.New("validator contract wallet specified but flag to use a smart contract wallet was not specified") } - wallet, err = validatorwallet.NewEOA(dp, deployInfo.Rollup, l1client, txOptsValidator, getExtraGas) + wallet, err = validatorwallet.NewEOA(dp, deployInfo.Rollup, l1client, getExtraGas) if err != nil { return nil, err } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index ddb18beeb..82dfa894f 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -235,8 +235,9 @@ func mainImpl() int { // If sequencer and signing is enabled or batchposter is enabled without // external signing sequencer will need a key. sequencerNeedsKey := (nodeConfig.Node.Sequencer && !nodeConfig.Node.Feed.Output.DisableSigning) || - (nodeConfig.Node.BatchPoster.Enable && nodeConfig.Node.BatchPoster.DataPoster.ExternalSigner.URL != "") - validatorNeedsKey := nodeConfig.Node.Staker.OnlyCreateWalletContract || nodeConfig.Node.Staker.Enable && !strings.EqualFold(nodeConfig.Node.Staker.Strategy, "watchtower") + (nodeConfig.Node.BatchPoster.Enable && nodeConfig.Node.BatchPoster.DataPoster.ExternalSigner.URL == "") + validatorNeedsKey := nodeConfig.Node.Staker.OnlyCreateWalletContract || + (nodeConfig.Node.Staker.Enable && !strings.EqualFold(nodeConfig.Node.Staker.Strategy, "watchtower") && nodeConfig.Node.Staker.DataPoster.ExternalSigner.URL == "") l1Wallet.ResolveDirectoryNames(nodeConfig.Persistent.Chain) defaultL1WalletConfig := conf.DefaultL1WalletConfig diff --git a/contracts b/contracts index 4184926b5..0a149d2af 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 4184926b5ea855365fb60b13a4bd52e59b9136ca +Subproject commit 0a149d2af9aee566c4abf493479ec15e5fc32d98 diff --git a/staker/validatorwallet/eoa.go b/staker/validatorwallet/eoa.go index d86181f42..44af5e2b6 100644 --- a/staker/validatorwallet/eoa.go +++ b/staker/validatorwallet/eoa.go @@ -28,9 +28,9 @@ type EOA struct { getExtraGas func() uint64 } -func NewEOA(dataPoster *dataposter.DataPoster, rollupAddress common.Address, l1Client arbutil.L1Interface, auth *bind.TransactOpts, getExtraGas func() uint64) (*EOA, error) { +func NewEOA(dataPoster *dataposter.DataPoster, rollupAddress common.Address, l1Client arbutil.L1Interface, getExtraGas func() uint64) (*EOA, error) { return &EOA{ - auth: auth, + auth: dataPoster.Auth(), client: l1Client, rollupAddress: rollupAddress, dataPoster: dataPoster, diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 6ac8dfddc..ce726dcf8 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -12,6 +12,7 @@ import ( "errors" "fmt" "math/big" + "net/http" "strings" "testing" "time" @@ -59,6 +60,19 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) t.Parallel() ctx, cancelCtx := context.WithCancel(context.Background()) defer cancelCtx() + httpSrv, srv := newServer(ctx, t) + t.Cleanup(func() { + if err := httpSrv.Shutdown(ctx); err != nil { + t.Fatalf("Error shutting down http server: %v", err) + } + }) + go func() { + log.Debug("Server is listening on port 1234...") + if err := httpSrv.ListenAndServeTLS(signerServerCert, signerServerKey); err != nil && err != http.ErrServerClosed { + log.Debug("ListenAndServeTLS() failed", "error", err) + return + } + }() var transferGas = util.NormalizeL2GasForL1GasInitial(800_000, params.GWei) // include room for aggregator L1 costs builder := NewNodeBuilder(ctx).DefaultConfig(t, true) @@ -72,6 +86,11 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) cleanupA := builder.Build(t) defer cleanupA() + addNewBatchPoster(ctx, t, builder, srv.address) + + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTxTo("Faucet", &srv.address, 30000, big.NewInt(1).Mul(big.NewInt(1e18), big.NewInt(1e18)), nil)}) + l2nodeA := builder.L2.ConsensusNode execNodeA := builder.L2.ExecNode @@ -133,7 +152,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) rollupABI, err := abi.JSON(strings.NewReader(rollupgen.RollupAdminLogicABI)) Require(t, err, "unable to parse rollup ABI") - setValidatorCalldata, err := rollupABI.Pack("setValidator", []common.Address{valWalletAddrA, l1authB.From}, []bool{true, true}) + setValidatorCalldata, err := rollupABI.Pack("setValidator", []common.Address{valWalletAddrA, l1authB.From, srv.address}, []bool{true, true, true}) Require(t, err, "unable to generate setValidator calldata") tx, err := upgradeExecutor.ExecuteCall(&deployAuth, l2nodeA.DeployInfo.Rollup, setValidatorCalldata) Require(t, err, "unable to set validators") @@ -199,12 +218,13 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err) } Require(t, err) - - dpB, err := arbnode.StakerDataposter(ctx, rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeB.L1Reader, &l1authB, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) + cfg := arbnode.ConfigDefaultL1NonSequencerTest() + cfg.Staker.DataPoster.ExternalSigner = *externalSignerTestCfg(srv.address) + dpB, err := arbnode.StakerDataposter(ctx, rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeB.L1Reader, &l1authB, NewFetcherFromConfig(cfg), nil) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } - valWalletB, err := validatorwallet.NewEOA(dpB, l2nodeB.DeployInfo.Rollup, l2nodeB.L1Reader.Client(), &l1authB, func() uint64 { return 0 }) + valWalletB, err := validatorwallet.NewEOA(dpB, l2nodeB.DeployInfo.Rollup, l2nodeB.L1Reader.Client(), func() uint64 { return 0 }) Require(t, err) valConfig.Strategy = "MakeNodes" statelessB, err := staker.NewStatelessBlockValidator( @@ -365,14 +385,14 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err, "EnsureTxSucceeded failed for staker", stakerName, "tx") } if faultyStaker { - conflictInfo, err := validatorUtils.FindStakerConflict(&bind.CallOpts{}, l2nodeA.DeployInfo.Rollup, l1authA.From, l1authB.From, big.NewInt(1024)) + conflictInfo, err := validatorUtils.FindStakerConflict(&bind.CallOpts{}, l2nodeA.DeployInfo.Rollup, l1authA.From, srv.address, big.NewInt(1024)) Require(t, err) if staker.ConflictType(conflictInfo.Ty) == staker.CONFLICT_TYPE_FOUND { cancelBackgroundTxs() } } if faultyStaker && !sawStakerZombie { - sawStakerZombie, err = rollup.IsZombie(&bind.CallOpts{}, l1authB.From) + sawStakerZombie, err = rollup.IsZombie(&bind.CallOpts{}, srv.address) Require(t, err) } isHonestZombie, err := rollup.IsZombie(&bind.CallOpts{}, valWalletAddrA) @@ -393,7 +413,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err) } if !stakerBWasStaked { - stakerBWasStaked, err = rollup.IsStaked(&bind.CallOpts{}, l1authB.From) + stakerBWasStaked, err = rollup.IsStaked(&bind.CallOpts{}, srv.address) Require(t, err) } for j := 0; j < 5; j++ { From a9721ace85f1d54bce44411e4d979452ffc46d93 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 4 Dec 2023 16:10:38 -0700 Subject: [PATCH 471/775] Clear out the channel when resetting feed timers --- broadcastclients/broadcastclients.go | 36 ++++++++++++++++++---------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index ed11ab87d..1997c6d21 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -120,6 +120,18 @@ func (bcs *BroadcastClients) adjustCount(delta int32) { } } +// Clears out a ticker's channel and resets it to the interval +func clearAndResetTicker(timer *time.Ticker, interval time.Duration) { + timer.Stop() + // Clear out any previous ticks + // A ticker's channel is only buffers one tick, so we don't need a loop here + select { + case <-timer.C: + default: + } + timer.Reset(interval) +} + func (bcs *BroadcastClients) Start(ctx context.Context) { bcs.primaryRouter.StopWaiter.Start(ctx, bcs.primaryRouter) bcs.secondaryRouter.StopWaiter.Start(ctx, bcs.secondaryRouter) @@ -182,46 +194,46 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { return // Primary feeds case msg := <-bcs.primaryRouter.messageChan: - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) - primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) + clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) + clearAndResetTicker(primaryFeedIsDownTimer, MAX_FEED_INACTIVE_TIME) if err := msgHandler(msg, bcs.primaryRouter); err != nil { log.Error("Error routing message from Primary Sequencer Feeds", "err", err) } case cs := <-bcs.primaryRouter.confirmedSequenceNumberChan: - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) - primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) + clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) + clearAndResetTicker(primaryFeedIsDownTimer, MAX_FEED_INACTIVE_TIME) confSeqHandler(cs, bcs.primaryRouter) // Failed to get messages from primary feed for ~5 seconds, reset the timer responsible for stopping a secondary case <-primaryFeedIsDownTimer.C: - stopSecondaryFeedTimer.Reset(PRIMARY_FEED_UPTIME) + clearAndResetTicker(stopSecondaryFeedTimer, PRIMARY_FEED_UPTIME) default: select { case <-ctx.Done(): return // Secondary Feeds case msg := <-bcs.secondaryRouter.messageChan: - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) if err := msgHandler(msg, bcs.secondaryRouter); err != nil { log.Error("Error routing message from Secondary Sequencer Feeds", "err", err) } case cs := <-bcs.secondaryRouter.confirmedSequenceNumberChan: - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) + clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) confSeqHandler(cs, bcs.secondaryRouter) case msg := <-bcs.primaryRouter.messageChan: - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) - primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) + clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) + clearAndResetTicker(primaryFeedIsDownTimer, MAX_FEED_INACTIVE_TIME) if err := msgHandler(msg, bcs.primaryRouter); err != nil { log.Error("Error routing message from Primary Sequencer Feeds", "err", err) } case cs := <-bcs.primaryRouter.confirmedSequenceNumberChan: - startSecondaryFeedTimer.Reset(MAX_FEED_INACTIVE_TIME) - primaryFeedIsDownTimer.Reset(MAX_FEED_INACTIVE_TIME) + clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) + clearAndResetTicker(primaryFeedIsDownTimer, MAX_FEED_INACTIVE_TIME) confSeqHandler(cs, bcs.primaryRouter) case <-startSecondaryFeedTimer.C: bcs.startSecondaryFeed(ctx) case <-primaryFeedIsDownTimer.C: - stopSecondaryFeedTimer.Reset(PRIMARY_FEED_UPTIME) + clearAndResetTicker(stopSecondaryFeedTimer, PRIMARY_FEED_UPTIME) } } } From 135f5dd7549e8b3a555cc91ca00365b368103371 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 5 Dec 2023 00:24:22 -0700 Subject: [PATCH 472/775] Move clearAndResetTicker calls to after effects --- broadcastclients/broadcastclients.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index 1997c6d21..16c465b9b 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -194,15 +194,15 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { return // Primary feeds case msg := <-bcs.primaryRouter.messageChan: - clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) - clearAndResetTicker(primaryFeedIsDownTimer, MAX_FEED_INACTIVE_TIME) if err := msgHandler(msg, bcs.primaryRouter); err != nil { log.Error("Error routing message from Primary Sequencer Feeds", "err", err) } - case cs := <-bcs.primaryRouter.confirmedSequenceNumberChan: clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) clearAndResetTicker(primaryFeedIsDownTimer, MAX_FEED_INACTIVE_TIME) + case cs := <-bcs.primaryRouter.confirmedSequenceNumberChan: confSeqHandler(cs, bcs.primaryRouter) + clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) + clearAndResetTicker(primaryFeedIsDownTimer, MAX_FEED_INACTIVE_TIME) // Failed to get messages from primary feed for ~5 seconds, reset the timer responsible for stopping a secondary case <-primaryFeedIsDownTimer.C: clearAndResetTicker(stopSecondaryFeedTimer, PRIMARY_FEED_UPTIME) @@ -212,24 +212,23 @@ func (bcs *BroadcastClients) Start(ctx context.Context) { return // Secondary Feeds case msg := <-bcs.secondaryRouter.messageChan: - clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) if err := msgHandler(msg, bcs.secondaryRouter); err != nil { log.Error("Error routing message from Secondary Sequencer Feeds", "err", err) } - case cs := <-bcs.secondaryRouter.confirmedSequenceNumberChan: clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) + case cs := <-bcs.secondaryRouter.confirmedSequenceNumberChan: confSeqHandler(cs, bcs.secondaryRouter) - - case msg := <-bcs.primaryRouter.messageChan: clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) - clearAndResetTicker(primaryFeedIsDownTimer, MAX_FEED_INACTIVE_TIME) + case msg := <-bcs.primaryRouter.messageChan: if err := msgHandler(msg, bcs.primaryRouter); err != nil { log.Error("Error routing message from Primary Sequencer Feeds", "err", err) } - case cs := <-bcs.primaryRouter.confirmedSequenceNumberChan: clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) clearAndResetTicker(primaryFeedIsDownTimer, MAX_FEED_INACTIVE_TIME) + case cs := <-bcs.primaryRouter.confirmedSequenceNumberChan: confSeqHandler(cs, bcs.primaryRouter) + clearAndResetTicker(startSecondaryFeedTimer, MAX_FEED_INACTIVE_TIME) + clearAndResetTicker(primaryFeedIsDownTimer, MAX_FEED_INACTIVE_TIME) case <-startSecondaryFeedTimer.C: bcs.startSecondaryFeed(ctx) case <-primaryFeedIsDownTimer.C: From ab98a73e70882f4e2778f50780ca3a88bf70a06d Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 5 Dec 2023 20:36:40 +0530 Subject: [PATCH 473/775] address PR comments --- arbnode/dataposter/data_poster.go | 38 +++++++++++++++++---------- arbnode/dataposter/dataposter_test.go | 24 ++++++++--------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 999e2de59..a03ac78d5 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -358,6 +358,25 @@ func (p *DataPoster) GetNextNonceAndMeta(ctx context.Context) (uint64, []byte, e const minRbfIncrease = arbmath.OneInBips * 11 / 10 +// evalMaxFeeCapExpr uses MaxFeeCapFormula from config to calculate the expression's result by plugging in appropriate parameter values +func (p *DataPoster) evalMaxFeeCapExpr(backlogOfBatches uint64, elapsed time.Duration) (*big.Int, error) { + config := p.config() + parameters := map[string]any{ + "BacklogOfBatches": float64(backlogOfBatches), + "UrgencyGWei": config.UrgencyGwei, + "ElapsedTime": float64(elapsed), + "ElapsedTimeBase": float64(config.ElapsedTimeBase), + "ElapsedTimeImportance": config.ElapsedTimeImportance, + "TargetPriceGWei": config.TargetPriceGwei, + "GWei": params.GWei, + } + result, err := p.maxFeeCapExpression.Evaluate(parameters) + if err != nil { + return nil, fmt.Errorf("error evaluating maxFeeCapExpression: %w", err) + } + return arbmath.FloatToBig(result.(float64)), nil +} + func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit uint64, lastFeeCap *big.Int, lastTipCap *big.Int, dataCreatedAt time.Time, backlogOfBatches uint64) (*big.Int, *big.Int, error) { config := p.config() latestHeader, err := p.headerReader.LastHeader(ctx) @@ -397,19 +416,10 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u } elapsed := time.Since(dataCreatedAt) - parameters := make(map[string]interface{}) - parameters["BacklogOfBatches"] = float64(backlogOfBatches) - parameters["UrgencyGWei"] = config.UrgencyGwei - parameters["ElapsedTime"] = float64(elapsed) - parameters["ElapsedTimeBase"] = float64(config.ElapsedTimeBase) - parameters["ElapsedTimeImportance"] = config.ElapsedTimeImportance - parameters["TargetPriceGWei"] = config.TargetPriceGwei - parameters["GWei"] = params.GWei - result, err := p.maxFeeCapExpression.Evaluate(parameters) + maxFeeCap, err := p.evalMaxFeeCapExpr(backlogOfBatches, elapsed) if err != nil { - return nil, nil, fmt.Errorf("error evaluating maxFeeCapExpression: %w", err) + return nil, nil, err } - maxFeeCap := arbmath.FloatToBig(result.(float64)) if arbmath.BigGreaterThan(newFeeCap, maxFeeCap) { log.Warn( "reducing proposed fee cap to current maximum", @@ -819,7 +829,7 @@ func DataPosterConfigAddOptions(prefix string, f *pflag.FlagSet, defaultDataPost f.Bool(prefix+".use-db-storage", defaultDataPosterConfig.UseDBStorage, "uses database storage when enabled") f.Bool(prefix+".use-noop-storage", defaultDataPosterConfig.UseNoOpStorage, "uses noop storage, it doesn't store anything") f.Bool(prefix+".legacy-storage-encoding", defaultDataPosterConfig.LegacyStorageEncoding, "encodes items in a legacy way (as it was before dropping generics)") - f.String(prefix+".max-fee-cap-formula", defaultDataPosterConfig.MaxFeeCapFormula, "mathematical formula to calculate maximum fee cap") + f.String(prefix+".max-fee-cap-formula", defaultDataPosterConfig.MaxFeeCapFormula, "mathematical formula to calculate maximum fee cap. Refer https://github.com/Knetic/govaluate/blob/master/MANUAL.md to find all available mathematical operators") f.Duration(prefix+".elapsed-time-base", defaultDataPosterConfig.ElapsedTimeBase, "unit to measure the time elapsed since creation of transaction used for maximum fee cap calculation") f.Float64(prefix+".elapsed-time-importance", defaultDataPosterConfig.ElapsedTimeImportance, "weight given to the units of time elapsed used for maximum fee cap calculation") @@ -856,7 +866,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ LegacyStorageEncoding: false, Dangerous: DangerousConfig{ClearDBStorage: false}, ExternalSigner: ExternalSignerCfg{Method: "eth_signTransaction"}, - MaxFeeCapFormula: "(BacklogOfBatches * BacklogOfBatches * UrgencyGWei * UrgencyGWei + (ElapsedTime/ElapsedTimeBase) * (ElapsedTime/ElapsedTimeBase) * ElapsedTimeImportance + TargetPriceGWei) * GWei", + MaxFeeCapFormula: "(((BacklogOfBatches * UrgencyGWei) ** 2) + ((ElapsedTime/ElapsedTimeBase) ** 2) * ElapsedTimeImportance + TargetPriceGWei) * GWei", ElapsedTimeBase: 10 * time.Minute, ElapsedTimeImportance: 10, } @@ -882,7 +892,7 @@ var TestDataPosterConfig = DataPosterConfig{ UseNoOpStorage: false, LegacyStorageEncoding: false, ExternalSigner: ExternalSignerCfg{Method: "eth_signTransaction"}, - MaxFeeCapFormula: "(BacklogOfBatches * BacklogOfBatches * UrgencyGWei * UrgencyGWei + (ElapsedTime/ElapsedTimeBase) * (ElapsedTime/ElapsedTimeBase) * ElapsedTimeImportance + TargetPriceGWei) * GWei", + MaxFeeCapFormula: "(((BacklogOfBatches * UrgencyGWei) ** 2) + ((ElapsedTime/ElapsedTimeBase) ** 2) * ElapsedTimeImportance + TargetPriceGWei) * GWei", ElapsedTimeBase: 10 * time.Minute, ElapsedTimeImportance: 10, } diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index 0038ed221..8c18288e5 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -249,21 +249,19 @@ func TestMaxFeeCapFormulaCalculation(t *testing.T) { // use new variables other than the ones that are keys of 'parameters' map below expression, err := govaluate.NewEvaluableExpression(DefaultDataPosterConfig.MaxFeeCapFormula) if err != nil { - t.Fatalf("error creating govaluate evaluable expression for default maxFeeCap formula: %t", err) + t.Fatalf("Error creating govaluate evaluable expression for calculating default maxFeeCap formula: %v", err) } - parameters := make(map[string]interface{}) - parameters["BacklogOfBatches"] = 0 - parameters["UrgencyGWei"] = DefaultDataPosterConfig.UrgencyGwei - parameters["ElapsedTime"] = 0 - parameters["ElapsedTimeBase"] = float64(DefaultDataPosterConfig.ElapsedTimeBase) - parameters["ElapsedTimeImportance"] = DefaultDataPosterConfig.ElapsedTimeImportance - parameters["TargetPriceGWei"] = DefaultDataPosterConfig.TargetPriceGwei - parameters["GWei"] = 0 - result, err := expression.Evaluate(parameters) + config := DefaultDataPosterConfig + config.TargetPriceGwei = 0 + p := &DataPoster{ + config: func() *DataPosterConfig { return &config }, + maxFeeCapExpression: expression, + } + result, err := p.evalMaxFeeCapExpr(0, 0) if err != nil { - t.Fatalf("error evaluating expression:: %t", err) + t.Fatalf("Error evaluating MaxFeeCap expression: %v", err) } - if result.(float64) != 0 { - t.Fatalf("unexpected result. Got error: %f, want: %d", result.(float64), 0) + if result.Cmp(common.Big0) != 0 { + t.Fatalf("Unexpected result. Got: %d, want: 0", result.Uint64()) } } From 781f0f9dca14f3d2277c28807f6ac132bc7bc170 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Tue, 5 Dec 2023 18:08:35 +0100 Subject: [PATCH 474/775] Take external signer into account when creating staker dataposter --- arbnode/node.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 87afcd7a2..fc415c117 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -302,10 +302,10 @@ func StakerDataposter( ctx context.Context, db ethdb.Database, l1Reader *headerreader.HeaderReader, transactOpts *bind.TransactOpts, cfgFetcher ConfigFetcher, syncMonitor *SyncMonitor, ) (*dataposter.DataPoster, error) { - if transactOpts == nil { + cfg := cfgFetcher.Get() + if transactOpts == nil && cfg.BatchPoster.DataPoster.ExternalSigner.URL == "" { return nil, nil } - cfg := cfgFetcher.Get() mdRetriever := func(ctx context.Context, blockNum *big.Int) ([]byte, error) { return nil, nil } From 7264943cad6d70659dc922d0169aad6b42544be5 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Tue, 5 Dec 2023 18:20:13 +0100 Subject: [PATCH 475/775] Fix external signer check (use correct config flag) when creating dataposter for staker --- arbnode/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/node.go b/arbnode/node.go index fc415c117..4a08c9d71 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -303,7 +303,7 @@ func StakerDataposter( transactOpts *bind.TransactOpts, cfgFetcher ConfigFetcher, syncMonitor *SyncMonitor, ) (*dataposter.DataPoster, error) { cfg := cfgFetcher.Get() - if transactOpts == nil && cfg.BatchPoster.DataPoster.ExternalSigner.URL == "" { + if transactOpts == nil && cfg.Staker.DataPoster.ExternalSigner.URL == "" { return nil, nil } mdRetriever := func(ctx context.Context, blockNum *big.Int) ([]byte, error) { From 9ad1980a6b630dec5018d9ee14213626ba1a1f54 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Wed, 6 Dec 2023 13:23:52 +0100 Subject: [PATCH 476/775] Use external signer address for redis key, log correct tx sender address --- arbnode/node.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 4a08c9d71..593079feb 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -323,6 +323,12 @@ func StakerDataposter( dpCfg := func() *dataposter.DataPosterConfig { return &cfg.Staker.DataPoster } + var sender string + if transactOpts != nil { + sender = transactOpts.From.String() + } else { + sender = cfg.Staker.DataPoster.ExternalSigner.Address + } return dataposter.NewDataPoster(ctx, &dataposter.DataPosterOpts{ Database: db, @@ -332,8 +338,7 @@ func StakerDataposter( RedisLock: redisLock, Config: dpCfg, MetadataRetriever: mdRetriever, - // transactOpts is non-nil, it's checked at the beginning. - RedisKey: transactOpts.From.String() + ".staker-data-poster.queue", + RedisKey: sender + ".staker-data-poster.queue", }) } @@ -618,15 +623,17 @@ func createNodeImpl( if err := wallet.Initialize(ctx); err != nil { return nil, err } - var txValidatorSenderPtr *common.Address + var validatorAddr string if txOptsValidator != nil { - txValidatorSenderPtr = &txOptsValidator.From + validatorAddr = txOptsValidator.From.String() + } else { + validatorAddr = config.Staker.DataPoster.ExternalSigner.Address } whitelisted, err := stakerObj.IsWhitelisted(ctx) if err != nil { return nil, err } - log.Info("running as validator", "txSender", txValidatorSenderPtr, "actingAsWallet", wallet.Address(), "whitelisted", whitelisted, "strategy", config.Staker.Strategy) + log.Info("running as validator", "txSender", validatorAddr, "actingAsWallet", wallet.Address(), "whitelisted", whitelisted, "strategy", config.Staker.Strategy) } var batchPoster *BatchPoster From 5b03014769375d993baf117aaca99e06c6c89d71 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 6 Dec 2023 20:14:57 +0530 Subject: [PATCH 477/775] Update log message when no blocks validated yet --- staker/staker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staker/staker.go b/staker/staker.go index 4f35c1bc9..ac05abf51 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -453,7 +453,7 @@ func (s *Staker) Start(ctxIn context.Context) { backoff = time.Minute log.Error("error acting as staker", "err", err) } else { - log.Warn("error acting as staker", "err", err) + log.Warn("block validation is still pending") } return backoff }) From 02747d558091c7609ffc5eadc10080af0e243d93 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 6 Dec 2023 20:38:23 +0530 Subject: [PATCH 478/775] update flag usage --- arbnode/dataposter/data_poster.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index a03ac78d5..824499433 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -829,7 +829,9 @@ func DataPosterConfigAddOptions(prefix string, f *pflag.FlagSet, defaultDataPost f.Bool(prefix+".use-db-storage", defaultDataPosterConfig.UseDBStorage, "uses database storage when enabled") f.Bool(prefix+".use-noop-storage", defaultDataPosterConfig.UseNoOpStorage, "uses noop storage, it doesn't store anything") f.Bool(prefix+".legacy-storage-encoding", defaultDataPosterConfig.LegacyStorageEncoding, "encodes items in a legacy way (as it was before dropping generics)") - f.String(prefix+".max-fee-cap-formula", defaultDataPosterConfig.MaxFeeCapFormula, "mathematical formula to calculate maximum fee cap. Refer https://github.com/Knetic/govaluate/blob/master/MANUAL.md to find all available mathematical operators") + f.String(prefix+".max-fee-cap-formula", defaultDataPosterConfig.MaxFeeCapFormula, "mathematical formula to calculate maximum fee cap the result of which would be float64.\n"+ + "This expression is expected to be evaluated please refer https://github.com/Knetic/govaluate/blob/master/MANUAL.md to find all available mathematical operators.\n"+ + "Currently available variables to construct the formula are BacklogOfBatches, UrgencyGWei, ElapsedTime, ElapsedTimeBase, ElapsedTimeImportance, TargetPriceGWei and GWei") f.Duration(prefix+".elapsed-time-base", defaultDataPosterConfig.ElapsedTimeBase, "unit to measure the time elapsed since creation of transaction used for maximum fee cap calculation") f.Float64(prefix+".elapsed-time-importance", defaultDataPosterConfig.ElapsedTimeImportance, "weight given to the units of time elapsed used for maximum fee cap calculation") From 677f708e5631b6bdac3fe70649d856f56874e810 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 6 Dec 2023 23:38:38 +0530 Subject: [PATCH 479/775] address PR comments --- staker/l1_validator.go | 3 +++ staker/staker.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/staker/l1_validator.go b/staker/l1_validator.go index 09bcc6446..4e7aa22cb 100644 --- a/staker/l1_validator.go +++ b/staker/l1_validator.go @@ -315,6 +315,9 @@ func (v *L1Validator) generateNodeAction( } if !wasmRootValid { if !stakerConfig.Dangerous.IgnoreRollupWasmModuleRoot { + if len(valInfo.WasmRoots) == 0 { + return nil, false, fmt.Errorf("block validation is still pending") + } return nil, false, fmt.Errorf( "wasmroot doesn't match rollup : %v, valid: %v", v.lastWasmModuleRoot, valInfo.WasmRoots, diff --git a/staker/staker.go b/staker/staker.go index ac05abf51..4f35c1bc9 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -453,7 +453,7 @@ func (s *Staker) Start(ctxIn context.Context) { backoff = time.Minute log.Error("error acting as staker", "err", err) } else { - log.Warn("block validation is still pending") + log.Warn("error acting as staker", "err", err) } return backoff }) From d30c781e54de85f4657877064272b0a8fed0746e Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 6 Dec 2023 12:55:34 -0700 Subject: [PATCH 480/775] Don't use access lists for L3 batch posting --- arbnode/batch_poster.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index cc9d2f428..20b7f98a6 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -291,6 +291,11 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e // Dataposter sender may be external signer address, so we should initialize // access list after initializing dataposter. b.accessList = func(SequencerInboxAccs, AfterDelayedMessagesRead int) types.AccessList { + if opts.L1Reader.IsParentChainArbitrum() { + // Access lists cost gas instead of saving gas on L2s, + // because data is expensive in comparison to computation. + return nil + } return AccessList(&AccessListOpts{ SequencerInboxAddr: opts.DeployInfo.SequencerInbox, DataPosterAddr: b.dataPoster.Sender(), @@ -758,7 +763,7 @@ func (b *BatchPoster) encodeAddBatch(seqNum *big.Int, prevMsgNum arbutil.Message return fullData, nil } -func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, delayedMessages uint64, realData []byte, realNonce uint64) (uint64, error) { +func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, delayedMessages uint64, realData []byte, realNonce uint64, realAccessList types.AccessList) (uint64, error) { config := b.config() useNormalEstimation := b.dataPoster.MaxMempoolTransactions() == 1 if !useNormalEstimation { @@ -772,9 +777,10 @@ func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, if useNormalEstimation { // If we're at the latest nonce, we can skip the special future tx estimate stuff gas, err := b.l1Reader.Client().EstimateGas(ctx, ethereum.CallMsg{ - From: b.dataPoster.Sender(), - To: &b.seqInboxAddr, - Data: realData, + From: b.dataPoster.Sender(), + To: &b.seqInboxAddr, + Data: realData, + AccessList: realAccessList, }) if err != nil { return 0, err @@ -794,6 +800,9 @@ func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, From: b.dataPoster.Sender(), To: &b.seqInboxAddr, Data: data, + // This isn't perfect because we're probably estimating the batch at a different sequence number, + // but it should overestimate rather than underestimate which is fine. + AccessList: realAccessList, }) if err != nil { sequencerMessageHeader := sequencerMessage @@ -1007,6 +1016,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) if err != nil { return false, err } + accessList := b.accessList(int(batchPosition.NextSeqNum), int(b.building.segments.delayedMsg)) // On restart, we may be trying to estimate gas for a batch whose successor has // already made it into pending state, if not latest state. // In that case, we might get a revert with `DelayedBackwards()`. @@ -1014,7 +1024,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) // In theory, this might reduce gas usage, but only by a factor that's already // accounted for in `config.ExtraBatchGas`, as that same factor can appear if a user // posts a new delayed message that we didn't see while gas estimating. - gasLimit, err := b.estimateGas(ctx, sequencerMsg, lastPotentialMsg.DelayedMessagesRead, data, nonce) + gasLimit, err := b.estimateGas(ctx, sequencerMsg, lastPotentialMsg.DelayedMessagesRead, data, nonce, accessList) if err != nil { return false, err } @@ -1034,9 +1044,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) data, gasLimit, new(big.Int), - b.accessList( - int(batchPosition.NextSeqNum), - int(b.building.segments.delayedMsg)), + accessList, ) if err != nil { return false, err From 817a02bcb82d162268674cf26e435d35964975de Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 6 Dec 2023 13:01:31 -0700 Subject: [PATCH 481/775] Clarify comment --- arbnode/batch_poster.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 20b7f98a6..7a4cfc21c 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -292,7 +292,7 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e // access list after initializing dataposter. b.accessList = func(SequencerInboxAccs, AfterDelayedMessagesRead int) types.AccessList { if opts.L1Reader.IsParentChainArbitrum() { - // Access lists cost gas instead of saving gas on L2s, + // Access lists cost gas instead of saving gas when posting to L2s, // because data is expensive in comparison to computation. return nil } From 28714a129715399f044d0395a256ff9ca78039eb Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Thu, 7 Dec 2023 10:07:34 +0530 Subject: [PATCH 482/775] Fix sequencer Inbox MaxDataSize retrieval --- cmd/nitro/nitro.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index f23fbc90d..e391a7614 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -495,36 +495,36 @@ func mainImpl() int { } // Validate sequencer's MaxTxDataSize and batchPoster's MaxSize params. - config := liveNodeConfig.Get() - executionRevertedRegexp := regexp.MustCompile("(?i)execution reverted") // SequencerInbox's maxDataSize is defaulted to 117964 which is 90% of Geth's 128KB tx size limit, leaving ~13KB for proving. seqInboxMaxDataSize := 117964 - if config.Node.ParentChainReader.Enable { + executionRevertedRegexp := regexp.MustCompile("(?i)execution reverted") + if nodeConfig.Node.ParentChainReader.Enable { seqInbox, err := bridgegen.NewSequencerInbox(rollupAddrs.SequencerInbox, l1Client) if err != nil { log.Error("failed to create sequencer inbox for validating sequencer's MaxTxDataSize and batchposter's MaxSize", "err", err) return 1 } res, err := seqInbox.MaxDataSize(&bind.CallOpts{Context: ctx}) - seqInboxMaxDataSize = int(res.Int64()) - if err != nil && !executionRevertedRegexp.MatchString(err.Error()) { + if err == nil { + seqInboxMaxDataSize = int(res.Int64()) + } else if !executionRevertedRegexp.MatchString(err.Error()) { log.Error("error fetching MaxDataSize from sequencer inbox", "err", err) return 1 } } // If batchPoster is enabled, validate MaxSize to be at least 10kB below the sequencer inbox’s maxDataSize if the data availability service is not enabled. // The 10kB gap is because its possible for the batch poster to exceed its MaxSize limit and produce batches of slightly larger size. - if config.Node.BatchPoster.Enable && !config.Node.DataAvailability.Enable { - if config.Node.BatchPoster.MaxSize > seqInboxMaxDataSize-10000 { + if nodeConfig.Node.BatchPoster.Enable && !nodeConfig.Node.DataAvailability.Enable { + if nodeConfig.Node.BatchPoster.MaxSize > seqInboxMaxDataSize-10000 { log.Error("batchPoster's MaxSize is too large") return 1 } } // If sequencer is enabled, validate MaxTxDataSize to be at least 5kB below the batch poster's MaxSize to allow space for headers and such. // And since batchposter's MaxSize is to be at least 10kB below the sequencer inbox’s maxDataSize, this leads to another condition of atlest 15kB below the sequencer inbox’s maxDataSize. - if config.Execution.Sequencer.Enable { - if config.Execution.Sequencer.MaxTxDataSize > config.Node.BatchPoster.MaxSize-5000 || - config.Execution.Sequencer.MaxTxDataSize > seqInboxMaxDataSize-15000 { + if nodeConfig.Execution.Sequencer.Enable { + if nodeConfig.Execution.Sequencer.MaxTxDataSize > nodeConfig.Node.BatchPoster.MaxSize-5000 || + nodeConfig.Execution.Sequencer.MaxTxDataSize > seqInboxMaxDataSize-15000 { log.Error("sequencer's MaxTxDataSize too large") return 1 } From b83126e39deee092dca63aad8f2ea9e40d9ec407 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 7 Dec 2023 16:49:10 +0100 Subject: [PATCH 483/775] Don't error out if batchposter txopts aren'ts specified but external signer is enabled --- arbnode/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/node.go b/arbnode/node.go index 593079feb..f2ed2941f 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -639,7 +639,7 @@ func createNodeImpl( var batchPoster *BatchPoster var delayedSequencer *DelayedSequencer if config.BatchPoster.Enable { - if txOptsBatchPoster == nil { + if txOptsBatchPoster == nil && config.BatchPoster.DataPoster.ExternalSigner.URL == "" { return nil, errors.New("batchposter, but no TxOpts") } batchPoster, err = NewBatchPoster(ctx, &BatchPosterOpts{ From 02295212355c195556661c776f2c730eba42ff7a Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 7 Dec 2023 18:50:12 +0100 Subject: [PATCH 484/775] Don't run batch_poster system tests in parallel --- system_tests/batch_poster_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index f0c115e2f..873a87c6f 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -61,7 +61,6 @@ func addNewBatchPoster(ctx context.Context, t *testing.T, builder *NodeBuilder, } func testBatchPosterParallel(t *testing.T, useRedis bool) { - t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() httpSrv, srv := newServer(ctx, t) From c430f35e539fc9bc44d741816de0e390d7fb3f44 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 8 Dec 2023 21:21:07 +0530 Subject: [PATCH 485/775] Check that on-chain WASM module root is compatible with node --- cmd/nitro/nitro.go | 48 ++++++++++++++++++++++++++++++++++++ validator/valnode/valnode.go | 10 ++++++-- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 8bbceecab..c7f9d57b0 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -53,12 +53,14 @@ import ( _ "github.com/offchainlabs/nitro/nodeInterface" "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" + "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/staker/validatorwallet" "github.com/offchainlabs/nitro/util/colors" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/rpcclient" "github.com/offchainlabs/nitro/util/signature" + "github.com/offchainlabs/nitro/validator/server_common" "github.com/offchainlabs/nitro/validator/valnode" ) @@ -420,6 +422,52 @@ func mainImpl() int { } }() + // Check that node is compatible with on-chain WASM module root on startup and before any ArbOS upgrades take effect to prevent divergences + if nodeConfig.Node.ParentChainReader.Enable && nodeConfig.Validation.Wasm.EnableWasmrootsCheck { + // Fetch current on-chain WASM module root + rollupUserLogic, err := rollupgen.NewRollupUserLogic(rollupAddrs.Rollup, l1Client) + if err != nil { + log.Error("failed to create rollupUserLogic", "err", err) + return 1 + } + moduleRoot, err := rollupUserLogic.WasmModuleRoot(&bind.CallOpts{Context: ctx}) + if err != nil { + log.Error("failed to get on-chain WASM module root", "err", err) + return 1 + } + if (moduleRoot == common.Hash{}) { + log.Error("on-chain WASM module root is zero") + return 1 + } + // Check if the on-chain WASM module root belongs to the set of allowed module roots + allowedWasmModuleRoots := nodeConfig.Validation.Wasm.AllowedWasmModuleRoots + if len(allowedWasmModuleRoots) > 0 { + moduleRootMatched := false + for _, root := range allowedWasmModuleRoots { + if common.HexToHash(root) == moduleRoot { + moduleRootMatched = true + break + } + } + if !moduleRootMatched { + log.Error("on-chain WASM module root did not match with any of the allowed WASM module roots") + return 1 + } + } else { + // If no allowed module roots were provided in config, check if we have a validator machine directory for the on-chain WASM module root + locator, err := server_common.NewMachineLocator(nodeConfig.Validation.Wasm.RootPath) + if err != nil { + log.Error("failed to create machine locator", "err", err) + return 1 + } + path := locator.GetMachinePath(moduleRoot) + if _, err := os.Stat(path); err != nil { + log.Error("unable to find validator machine directory for the on-chain WASM module root", "err", err) + return 1 + } + } + } + chainDb, l2BlockChain, err := openInitializeChainDb(ctx, stack, nodeConfig, new(big.Int).SetUint64(nodeConfig.Chain.ID), gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching), l1Client, rollupAddrs) if l2BlockChain != nil { deferFuncs = append(deferFuncs, func() { l2BlockChain.Stop() }) diff --git a/validator/valnode/valnode.go b/validator/valnode/valnode.go index ea9980e54..ca954094f 100644 --- a/validator/valnode/valnode.go +++ b/validator/valnode/valnode.go @@ -16,15 +16,21 @@ import ( ) type WasmConfig struct { - RootPath string `koanf:"root-path"` + RootPath string `koanf:"root-path"` + EnableWasmrootsCheck bool `koanf:"enable-wasmroots-check"` + AllowedWasmModuleRoots []string `koanf:"allowed-wasm-module-roots"` } func WasmConfigAddOptions(prefix string, f *flag.FlagSet) { f.String(prefix+".root-path", DefaultWasmConfig.RootPath, "path to machine folders, each containing wasm files (machine.wavm.br, replay.wasm)") + f.Bool(prefix+".enable-wasmroots-check", DefaultWasmConfig.EnableWasmrootsCheck, "enable check for compatibility of on-chain WASM module root with node") + f.StringSlice(prefix+".allowed-wasm-module-roots", DefaultWasmConfig.AllowedWasmModuleRoots, "list of WASM module roots to check if the on-chain WASM module root belongs to on node startup") } var DefaultWasmConfig = WasmConfig{ - RootPath: "", + RootPath: "", + EnableWasmrootsCheck: true, + AllowedWasmModuleRoots: []string{}, } type Config struct { From 93d5f7be54a1c56ac4c1dc30be090572ed32e162 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sat, 9 Dec 2023 17:07:32 -0700 Subject: [PATCH 486/775] Add argv[0]="js" to Go in jit runtime --- arbitrator/jit/src/main.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arbitrator/jit/src/main.rs b/arbitrator/jit/src/main.rs index d18b0de10..fa9f3478f 100644 --- a/arbitrator/jit/src/main.rs +++ b/arbitrator/jit/src/main.rs @@ -57,8 +57,22 @@ fn main() { let (instance, env, mut store) = machine::create(&opts, env); + let memory = instance.exports.get_memory("mem").unwrap(); + let memory = memory.view(&store); + + // To pass in the program name argument, we need to put it in memory. + // The Go linker guarantees a section of memory starting at byte 4096 is available for this purpose. + // https://github.com/golang/go/blob/252324e879e32f948d885f787decf8af06f82be9/misc/wasm/wasm_exec.js#L520 + let free_memory_base: i32 = 4096; + let name = free_memory_base; + let argv = name + 8; + + memory.write(name as u64, b"js\0").unwrap(); // write "js\0" to the name ptr + memory.write(argv as u64, &name.to_le_bytes()).unwrap(); // write the name ptr to the argv ptr + let run_args = vec![Value::I32(1), Value::I32(argv)]; // pass argv with our single name arg + let main = instance.exports.get_function("run").unwrap(); - let outcome = main.call(&mut store, &[Value::I32(0), Value::I32(0)]); + let outcome = main.call(&mut store, &run_args); let escape = match outcome { Ok(outcome) => { println!("Go returned values {:?}", outcome); From 9522e3e47b1719efdb82d28069c9e9742fd43943 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 10 Dec 2023 14:39:48 -0700 Subject: [PATCH 487/775] Finalize ArbOS 11 in the node software --- arbos/arbosState/arbosstate.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arbos/arbosState/arbosstate.go b/arbos/arbosState/arbosstate.go index 8702c62d1..46d2c6f3f 100644 --- a/arbos/arbosState/arbosstate.go +++ b/arbos/arbosState/arbosstate.go @@ -300,14 +300,6 @@ func (state *ArbosState) UpgradeArbosVersion( l1pricing.L1PricerFundsPoolAddress, ))) case 10: - if !chainConfig.DebugMode() { - // This upgrade isn't finalized so we only want to support it for testing - return fmt.Errorf( - "the chain is upgrading to unsupported ArbOS version %v, %w", - state.arbosVersion+1, - ErrFatalNodeOutOfDate, - ) - } // Update the PerBatchGasCost to a more accurate value compared to the old v6 default. ensure(state.l1PricingState.SetPerBatchGasCost(l1pricing.InitialPerBatchGasCostV12)) From 4f377a90a62e723711da50e57b276e4d0364bf78 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 10 Dec 2023 14:54:50 -0700 Subject: [PATCH 488/775] Add support for consensus v11 to Dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index b966125b6..b62e56925 100644 --- a/Dockerfile +++ b/Dockerfile @@ -164,6 +164,7 @@ RUN ./download-machine.sh consensus-v10 0x6b94a7fc388fd8ef3def759297828dc311761e RUN ./download-machine.sh consensus-v10.1 0xda4e3ad5e7feacb817c21c8d0220da7650fe9051ece68a3f0b1c5d38bbb27b21 RUN ./download-machine.sh consensus-v10.2 0x0754e09320c381566cc0449904c377a52bd34a6b9404432e80afd573b67f7b17 RUN ./download-machine.sh consensus-v10.3 0xf559b6d4fa869472dabce70fe1c15221bdda837533dfd891916836975b434dec +RUN ./download-machine.sh consensus-v11 0xf4389b835497a910d7ba3ebfb77aa93da985634f3c052de1290360635be40c4a FROM golang:1.20-bullseye as node-builder WORKDIR /workspace From e7cbd35f6d8fcc80f356629e5190301fc8dd3443 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 10 Dec 2023 15:00:11 -0700 Subject: [PATCH 489/775] Push back ArbOS 12 to ArbOS 20 to give room for orbit --- arbos/arbosState/arbosstate.go | 4 +++- precompiles/precompile.go | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/arbos/arbosState/arbosstate.go b/arbos/arbosState/arbosstate.go index 46d2c6f3f..caf44e2a9 100644 --- a/arbos/arbosState/arbosstate.go +++ b/arbos/arbosState/arbosstate.go @@ -315,7 +315,9 @@ func (state *ArbosState) UpgradeArbosVersion( if !firstTime { ensure(state.chainOwners.ClearList()) } - case 11: + // ArbOS versions 12 through 19 are left to Orbit chains for custom upgrades. + // TODO: currently you can't get to ArbOS 20 without hitting the default case. + case 19: if !chainConfig.DebugMode() { // This upgrade isn't finalized so we only want to support it for testing return fmt.Errorf( diff --git a/precompiles/precompile.go b/precompiles/precompile.go index ded90ebdf..330eb9a2e 100644 --- a/precompiles/precompile.go +++ b/precompiles/precompile.go @@ -554,7 +554,7 @@ func Precompiles() map[addr]ArbosPrecompile { ArbOwnerPublic := insert(MakePrecompile(templates.ArbOwnerPublicMetaData, &ArbOwnerPublic{Address: hex("6b")})) ArbOwnerPublic.methodsByName["GetInfraFeeAccount"].arbosVersion = 5 ArbOwnerPublic.methodsByName["RectifyChainOwner"].arbosVersion = 11 - ArbOwnerPublic.methodsByName["GetBrotliCompressionLevel"].arbosVersion = 12 + ArbOwnerPublic.methodsByName["GetBrotliCompressionLevel"].arbosVersion = 20 ArbRetryableImpl := &ArbRetryableTx{Address: types.ArbRetryableTxAddress} ArbRetryable := insert(MakePrecompile(templates.ArbRetryableTxMetaData, ArbRetryableImpl)) @@ -590,7 +590,7 @@ func Precompiles() map[addr]ArbosPrecompile { ArbOwner.methodsByName["SetInfraFeeAccount"].arbosVersion = 5 ArbOwner.methodsByName["ReleaseL1PricerSurplusFunds"].arbosVersion = 10 ArbOwner.methodsByName["SetChainConfig"].arbosVersion = 11 - ArbOwner.methodsByName["SetBrotliCompressionLevel"].arbosVersion = 12 + ArbOwner.methodsByName["SetBrotliCompressionLevel"].arbosVersion = 20 insert(ownerOnly(ArbOwnerImpl.Address, ArbOwner, emitOwnerActs)) insert(debugOnly(MakePrecompile(templates.ArbDebugMetaData, &ArbDebug{Address: hex("ff")}))) From fed7de239389a8b35e5e644d70aac6a5ebde1afc Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Mon, 11 Dec 2023 08:34:49 +0000 Subject: [PATCH 490/775] remove recursive lock calls from backlogSegment object --- broadcaster/backlog/backlog.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index d39cde29a..18d3af2e3 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -277,6 +277,12 @@ func IsBacklogSegmentNil(segment BacklogSegment) bool { func (s *backlogSegment) Start() uint64 { s.messagesLock.RLock() defer s.messagesLock.RUnlock() + return s.start() +} + +// start allows the first message to be retrieved from functions that already +// have the messagesLock. +func (s *backlogSegment) start() uint64 { if len(s.messages) > 0 { return uint64(s.messages[0].SequenceNumber) } @@ -317,7 +323,7 @@ func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, erro s.messagesLock.RLock() defer s.messagesLock.RUnlock() noMsgs := []*m.BroadcastFeedMessage{} - if start < s.Start() { + if start < s.start() { return noMsgs, errOutOfBounds } @@ -325,8 +331,8 @@ func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, erro return noMsgs, errOutOfBounds } - startIndex := start - s.Start() - endIndex := end - s.Start() + 1 + startIndex := start - s.start() + endIndex := end - s.start() + 1 tmp := make([]*m.BroadcastFeedMessage, len(s.messages)) copy(tmp, s.messages) @@ -359,7 +365,7 @@ func (s *backlogSegment) append(prevMsgIdx uint64, msg *m.BroadcastFeedMessage) func (s *backlogSegment) Contains(i uint64) bool { s.messagesLock.RLock() defer s.messagesLock.RUnlock() - start := s.Start() + start := s.start() if i < start || i > s.End() { return false } From 5a7ac9eabb2a0ec8b06faba991f67393054562db Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Mon, 11 Dec 2023 08:36:18 +0000 Subject: [PATCH 491/775] reload head after lookup call --- broadcaster/backlog/backlog.go | 1 + 1 file changed, 1 insertion(+) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 18d3af2e3..e25d32136 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -112,6 +112,7 @@ func (b *backlog) Get(start, end uint64) (*m.BroadcastMessage, error) { } segment, err := b.Lookup(start) + head := b.head.Load() if start < head.Start() { // doing this check after the Lookup call ensures there is no race // condition with a delete call From 3b4c9b6d5137580e497c5dfb911c236b729bed22 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Mon, 11 Dec 2023 09:03:51 +0000 Subject: [PATCH 492/775] fix no new var error --- broadcaster/backlog/backlog.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index e25d32136..1b9f6e8dd 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -112,7 +112,7 @@ func (b *backlog) Get(start, end uint64) (*m.BroadcastMessage, error) { } segment, err := b.Lookup(start) - head := b.head.Load() + head = b.head.Load() if start < head.Start() { // doing this check after the Lookup call ensures there is no race // condition with a delete call From da08db5a02fc1e99ff47af628ac54f7b232b3622 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:14:30 +0000 Subject: [PATCH 493/775] change copy slice to only copy the selected elements --- broadcaster/backlog/backlog.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 1b9f6e8dd..dee3aa92e 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -335,9 +335,9 @@ func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, erro startIndex := start - s.start() endIndex := end - s.start() + 1 - tmp := make([]*m.BroadcastFeedMessage, len(s.messages)) - copy(tmp, s.messages) - return tmp[startIndex:endIndex], nil + tmp := make([]*m.BroadcastFeedMessage, endIndex-startIndex) + copy(tmp, s.messages[startIndex:endIndex]) + return tmp, nil } // append appends the given BroadcastFeedMessage to messages if it is the first From f291e2477d36479eea87e81e621371b3a563ddd3 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 11 Dec 2023 20:04:56 +0530 Subject: [PATCH 494/775] Change default PrerecordedBlocks to number of CPUs * 2 --- staker/block_validator.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/staker/block_validator.go b/staker/block_validator.go index 108d6d1d4..61e5ed519 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + "runtime" "sync" "sync/atomic" "testing" @@ -119,7 +120,7 @@ var DefaultBlockValidatorConfig = BlockValidatorConfig{ ValidationServer: rpcclient.DefaultClientConfig, ValidationPoll: time.Second, ForwardBlocks: 1024, - PrerecordedBlocks: 128, + PrerecordedBlocks: uint64(2 * runtime.NumCPU()), CurrentModuleRoot: "current", PendingUpgradeModuleRoot: "latest", FailureIsFatal: true, @@ -131,7 +132,7 @@ var TestBlockValidatorConfig = BlockValidatorConfig{ ValidationServer: rpcclient.TestClientConfig, ValidationPoll: 100 * time.Millisecond, ForwardBlocks: 128, - PrerecordedBlocks: 64, + PrerecordedBlocks: uint64(2 * runtime.NumCPU()), CurrentModuleRoot: "latest", PendingUpgradeModuleRoot: "latest", FailureIsFatal: true, From 3440d26969324b3e800a41ef6fac78bf4e5067b1 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 11 Dec 2023 10:30:42 -0700 Subject: [PATCH 495/775] Don't create a vec for run_args --- arbitrator/jit/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbitrator/jit/src/main.rs b/arbitrator/jit/src/main.rs index fa9f3478f..513cd067c 100644 --- a/arbitrator/jit/src/main.rs +++ b/arbitrator/jit/src/main.rs @@ -69,10 +69,10 @@ fn main() { memory.write(name as u64, b"js\0").unwrap(); // write "js\0" to the name ptr memory.write(argv as u64, &name.to_le_bytes()).unwrap(); // write the name ptr to the argv ptr - let run_args = vec![Value::I32(1), Value::I32(argv)]; // pass argv with our single name arg + let run_args = &[Value::I32(1), Value::I32(argv)]; // pass argv with our single name arg let main = instance.exports.get_function("run").unwrap(); - let outcome = main.call(&mut store, &run_args); + let outcome = main.call(&mut store, run_args); let escape = match outcome { Ok(outcome) => { println!("Go returned values {:?}", outcome); From 13aecae7820c1832a390909e6d5d646c7238a157 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 11 Dec 2023 10:49:57 -0700 Subject: [PATCH 496/775] Fix FloatToBig overflowing on values greater than an int64 --- arbnode/dataposter/data_poster.go | 26 ++++++++++++++++++++------ util/arbmath/math.go | 3 ++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 4138aa840..bf12d109e 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -10,6 +10,7 @@ import ( "crypto/x509" "errors" "fmt" + "math" "math/big" "net/http" "os" @@ -378,13 +379,26 @@ func (p *DataPoster) evalMaxFeeCapExpr(backlogOfBatches uint64, elapsed time.Dur "ElapsedTimeBase": float64(config.ElapsedTimeBase), "ElapsedTimeImportance": config.ElapsedTimeImportance, "TargetPriceGWei": config.TargetPriceGwei, - "GWei": params.GWei, } result, err := p.maxFeeCapExpression.Evaluate(parameters) if err != nil { return nil, fmt.Errorf("error evaluating maxFeeCapExpression: %w", err) } - return arbmath.FloatToBig(result.(float64)), nil + resultFloat, ok := result.(float64) + if !ok { + return nil, fmt.Errorf("maxFeeCapExpression evaluated to non-float64: %v", result) + } + // 1e9 gwei gas price is practically speaking an infinite gas price, so we cap it there. + // This also allows the formula to return positive infinity safely. + resultFloat = math.Min(resultFloat, 1e9) + resultBig := arbmath.FloatToBig(resultFloat * params.GWei) + if resultBig == nil { + return nil, fmt.Errorf("maxFeeCapExpression evaluated to float64 not convertible to integer: %v", resultFloat) + } + if resultBig.Sign() <= 0 { + return nil, fmt.Errorf("maxFeeCapExpression evaluated <= 0: %v", resultFloat) + } + return resultBig, nil } func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit uint64, lastFeeCap *big.Int, lastTipCap *big.Int, dataCreatedAt time.Time, backlogOfBatches uint64) (*big.Int, *big.Int, error) { @@ -839,9 +853,9 @@ func DataPosterConfigAddOptions(prefix string, f *pflag.FlagSet, defaultDataPost f.Bool(prefix+".use-db-storage", defaultDataPosterConfig.UseDBStorage, "uses database storage when enabled") f.Bool(prefix+".use-noop-storage", defaultDataPosterConfig.UseNoOpStorage, "uses noop storage, it doesn't store anything") f.Bool(prefix+".legacy-storage-encoding", defaultDataPosterConfig.LegacyStorageEncoding, "encodes items in a legacy way (as it was before dropping generics)") - f.String(prefix+".max-fee-cap-formula", defaultDataPosterConfig.MaxFeeCapFormula, "mathematical formula to calculate maximum fee cap the result of which would be float64.\n"+ + f.String(prefix+".max-fee-cap-formula", defaultDataPosterConfig.MaxFeeCapFormula, "mathematical formula to calculate maximum fee cap gwei the result of which would be float64.\n"+ "This expression is expected to be evaluated please refer https://github.com/Knetic/govaluate/blob/master/MANUAL.md to find all available mathematical operators.\n"+ - "Currently available variables to construct the formula are BacklogOfBatches, UrgencyGWei, ElapsedTime, ElapsedTimeBase, ElapsedTimeImportance, TargetPriceGWei and GWei") + "Currently available variables to construct the formula are BacklogOfBatches, UrgencyGWei, ElapsedTime, ElapsedTimeBase, ElapsedTimeImportance, and TargetPriceGWei") f.Duration(prefix+".elapsed-time-base", defaultDataPosterConfig.ElapsedTimeBase, "unit to measure the time elapsed since creation of transaction used for maximum fee cap calculation") f.Float64(prefix+".elapsed-time-importance", defaultDataPosterConfig.ElapsedTimeImportance, "weight given to the units of time elapsed used for maximum fee cap calculation") @@ -878,7 +892,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ LegacyStorageEncoding: false, Dangerous: DangerousConfig{ClearDBStorage: false}, ExternalSigner: ExternalSignerCfg{Method: "eth_signTransaction"}, - MaxFeeCapFormula: "(((BacklogOfBatches * UrgencyGWei) ** 2) + ((ElapsedTime/ElapsedTimeBase) ** 2) * ElapsedTimeImportance + TargetPriceGWei) * GWei", + MaxFeeCapFormula: "((BacklogOfBatches * UrgencyGWei) ** 2) + ((ElapsedTime/ElapsedTimeBase) ** 2) * ElapsedTimeImportance + TargetPriceGWei", ElapsedTimeBase: 10 * time.Minute, ElapsedTimeImportance: 10, } @@ -904,7 +918,7 @@ var TestDataPosterConfig = DataPosterConfig{ UseNoOpStorage: false, LegacyStorageEncoding: false, ExternalSigner: ExternalSignerCfg{Method: "eth_signTransaction"}, - MaxFeeCapFormula: "(((BacklogOfBatches * UrgencyGWei) ** 2) + ((ElapsedTime/ElapsedTimeBase) ** 2) * ElapsedTimeImportance + TargetPriceGWei) * GWei", + MaxFeeCapFormula: "((BacklogOfBatches * UrgencyGWei) ** 2) + ((ElapsedTime/ElapsedTimeBase) ** 2) * ElapsedTimeImportance + TargetPriceGWei", ElapsedTimeBase: 10 * time.Minute, ElapsedTimeImportance: 10, } diff --git a/util/arbmath/math.go b/util/arbmath/math.go index 2945dd5a2..a5618438c 100644 --- a/util/arbmath/math.go +++ b/util/arbmath/math.go @@ -76,7 +76,8 @@ func UintToBig(value uint64) *big.Int { // FloatToBig casts a float to a huge func FloatToBig(value float64) *big.Int { - return new(big.Int).SetInt64(int64(value)) + result, _ := new(big.Float).SetFloat64(value).Int(nil) + return result } // UintToBigFloat casts a uint to a big float From 2ac0bfdee2f2afe28991fcedfb09e23f7fe19210 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 11 Dec 2023 11:09:55 -0700 Subject: [PATCH 497/775] Add support for nethermind's version of "execution reverted" --- cmd/nitro/nitro.go | 4 +--- staker/rollup_watcher.go | 7 ++----- .../headerreader}/execution_reverted_test.go | 11 ++++++++--- util/headerreader/header_reader.go | 4 ++++ 4 files changed, 15 insertions(+), 11 deletions(-) rename {staker => util/headerreader}/execution_reverted_test.go (66%) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index c7f9d57b0..86093a85d 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -14,7 +14,6 @@ import ( "os/signal" "path/filepath" "reflect" - "regexp" "strings" "syscall" "time" @@ -546,7 +545,6 @@ func mainImpl() int { // Validate sequencer's MaxTxDataSize and batchPoster's MaxSize params. // SequencerInbox's maxDataSize is defaulted to 117964 which is 90% of Geth's 128KB tx size limit, leaving ~13KB for proving. seqInboxMaxDataSize := 117964 - executionRevertedRegexp := regexp.MustCompile("(?i)execution reverted") if nodeConfig.Node.ParentChainReader.Enable { seqInbox, err := bridgegen.NewSequencerInbox(rollupAddrs.SequencerInbox, l1Client) if err != nil { @@ -556,7 +554,7 @@ func mainImpl() int { res, err := seqInbox.MaxDataSize(&bind.CallOpts{Context: ctx}) if err == nil { seqInboxMaxDataSize = int(res.Int64()) - } else if !executionRevertedRegexp.MatchString(err.Error()) { + } else if !headerreader.ExecutionRevertedRegexp.MatchString(err.Error()) { log.Error("error fetching MaxDataSize from sequencer inbox", "err", err) return 1 } diff --git a/staker/rollup_watcher.go b/staker/rollup_watcher.go index 59a23d891..c9fa3b132 100644 --- a/staker/rollup_watcher.go +++ b/staker/rollup_watcher.go @@ -9,7 +9,6 @@ import ( "errors" "fmt" "math/big" - "regexp" "sync/atomic" "github.com/ethereum/go-ethereum/common" @@ -17,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/solgen/go/rollupgen" + "github.com/offchainlabs/nitro/util/headerreader" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -72,9 +72,6 @@ func (r *RollupWatcher) getCallOpts(ctx context.Context) *bind.CallOpts { return &opts } -// A regexp matching "execution reverted" errors returned from the parent chain RPC. -var executionRevertedRegexp = regexp.MustCompile("(?i)execution reverted") - func (r *RollupWatcher) getNodeCreationBlock(ctx context.Context, nodeNum uint64) (*big.Int, error) { callOpts := r.getCallOpts(ctx) if !r.unSupportedL3Method.Load() { @@ -83,7 +80,7 @@ func (r *RollupWatcher) getNodeCreationBlock(ctx context.Context, nodeNum uint64 return createdAtBlock, nil } log.Trace("failed to call getNodeCreationBlockForLogLookup, falling back on node CreatedAtBlock field", "err", err) - if executionRevertedRegexp.MatchString(err.Error()) { + if headerreader.ExecutionRevertedRegexp.MatchString(err.Error()) { r.unSupportedL3Method.Store(true) } else { return nil, err diff --git a/staker/execution_reverted_test.go b/util/headerreader/execution_reverted_test.go similarity index 66% rename from staker/execution_reverted_test.go rename to util/headerreader/execution_reverted_test.go index 98a3bdfd6..d9b73b844 100644 --- a/staker/execution_reverted_test.go +++ b/util/headerreader/execution_reverted_test.go @@ -1,4 +1,7 @@ -package staker +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package headerreader import ( "io" @@ -13,14 +16,16 @@ func TestExecutionRevertedRegexp(t *testing.T) { "execution reverted: FOO", // besu returns "Execution reverted" "Execution reverted", + // nethermind returns "VM execution error." + "VM execution error.", } for _, errString := range executionRevertedErrors { - if !executionRevertedRegexp.MatchString(errString) { + if !ExecutionRevertedRegexp.MatchString(errString) { t.Fatalf("execution reverted regexp didn't match %q", errString) } } // This regexp should not match random IO errors - if executionRevertedRegexp.MatchString(io.ErrUnexpectedEOF.Error()) { + if ExecutionRevertedRegexp.MatchString(io.ErrUnexpectedEOF.Error()) { t.Fatal("execution reverted regexp matched unexpected EOF") } } diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index 678c3099f..a5100f74f 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "math/big" + "regexp" "sync" "time" @@ -22,6 +23,9 @@ import ( flag "github.com/spf13/pflag" ) +// A regexp matching "execution reverted" errors returned from the parent chain RPC. +var ExecutionRevertedRegexp = regexp.MustCompile(`(?i)execution reverted|VM execution error\.?`) + type ArbSysInterface interface { ArbBlockNumber(*bind.CallOpts) (*big.Int, error) } From a1898787cf31accf8328a898afc4ac20961b9a45 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 11 Dec 2023 11:54:41 -0700 Subject: [PATCH 498/775] rpcclient: enable retries by default --- util/rpcclient/rpcclient.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/util/rpcclient/rpcclient.go b/util/rpcclient/rpcclient.go index 61c125eae..dee6e9252 100644 --- a/util/rpcclient/rpcclient.go +++ b/util/rpcclient/rpcclient.go @@ -53,6 +53,8 @@ var TestClientConfig = ClientConfig{ var DefaultClientConfig = ClientConfig{ URL: "self-auth", JWTSecret: "", + Retries: 3, + RetryErrors: "websocket: close.*|dial tcp .*|.*i/o timeout|.*connection reset by peer|.*connection refused", ArgLogLimit: 2048, } From 67d99d315cdcd3769598bc0e84e8a45a5b7d5478 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 11 Dec 2023 11:54:59 -0700 Subject: [PATCH 499/775] rpcclient: use default config in toxiproxy test --- util/rpcclient/rpcclient_toxiproxy_test.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/util/rpcclient/rpcclient_toxiproxy_test.go b/util/rpcclient/rpcclient_toxiproxy_test.go index 31385d50d..647a37d69 100644 --- a/util/rpcclient/rpcclient_toxiproxy_test.go +++ b/util/rpcclient/rpcclient_toxiproxy_test.go @@ -22,15 +22,12 @@ func TestToxiRpcClient(t *testing.T) { Require(t, err) defer proxy.Delete() - config := &ClientConfig{ - URL: "ws://" + proxy.Listen, - Timeout: time.Second * 5, - Retries: 3, - RetryErrors: "websocket: close.*|.* i/o timeout|.*connection reset by peer|dial tcp .*", - RetryDelay: time.Millisecond * 500, - } + config := DefaultClientConfig + config.URL = "ws://" + proxy.Listen + config.Timeout = time.Second * 5 + config.RetryDelay = time.Millisecond * 500 Require(t, config.Validate()) - configFetcher := func() *ClientConfig { return config } + configFetcher := func() *ClientConfig { return &config } client := NewRpcClient(configFetcher, server1) From fa0fd2800fd03c1f797c996504593870c432ec20 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Mon, 11 Dec 2023 12:16:12 -0700 Subject: [PATCH 500/775] Update util/headerreader/execution_reverted_test.go --- util/headerreader/execution_reverted_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/headerreader/execution_reverted_test.go b/util/headerreader/execution_reverted_test.go index d9b73b844..d7bebd38b 100644 --- a/util/headerreader/execution_reverted_test.go +++ b/util/headerreader/execution_reverted_test.go @@ -1,4 +1,4 @@ -// Copyright 2021-2022, Offchain Labs, Inc. +// Copyright 2021-2023, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE package headerreader From a59891ddb810422dcc4eef23e2538b9b556c7d2b Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 11 Dec 2023 13:29:33 -0700 Subject: [PATCH 501/775] Allow for zero max fee cap from expression --- arbnode/dataposter/data_poster.go | 4 ++-- arbnode/dataposter/dataposter_test.go | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index bf12d109e..f1ba185e3 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -395,8 +395,8 @@ func (p *DataPoster) evalMaxFeeCapExpr(backlogOfBatches uint64, elapsed time.Dur if resultBig == nil { return nil, fmt.Errorf("maxFeeCapExpression evaluated to float64 not convertible to integer: %v", resultFloat) } - if resultBig.Sign() <= 0 { - return nil, fmt.Errorf("maxFeeCapExpression evaluated <= 0: %v", resultFloat) + if resultBig.Sign() < 0 { + return nil, fmt.Errorf("maxFeeCapExpression evaluated < 0: %v", resultFloat) } return resultBig, nil } diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index 8c18288e5..74b4aff18 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -19,6 +19,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/google/go-cmp/cmp" @@ -262,6 +263,14 @@ func TestMaxFeeCapFormulaCalculation(t *testing.T) { t.Fatalf("Error evaluating MaxFeeCap expression: %v", err) } if result.Cmp(common.Big0) != 0 { - t.Fatalf("Unexpected result. Got: %d, want: 0", result.Uint64()) + t.Fatalf("Unexpected result. Got: %d, want: 0", result) + } + + result, err = p.evalMaxFeeCapExpr(0, time.Since(time.Time{})) + if err != nil { + t.Fatalf("Error evaluating MaxFeeCap expression: %v", err) + } + if result.Cmp(big.NewInt(params.GWei)) <= 0 { + t.Fatalf("Unexpected result. Got: %d, want: >0", result) } } From 650bed6de8c98d3020b71a21c7687fc8d5e2142f Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 11 Dec 2023 14:35:33 -0700 Subject: [PATCH 502/775] Fix data poster time RLP encoding --- arbnode/dataposter/dbstorage/storage.go | 3 +- arbnode/dataposter/slice/slicestorage.go | 3 +- arbnode/dataposter/storage/storage.go | 42 ++++++++++++++++++++++++ arbnode/dataposter/storage/time.go | 34 +++++++++++++++++++ arbnode/dataposter/storage_test.go | 19 +++++++++++ 5 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 arbnode/dataposter/storage/time.go diff --git a/arbnode/dataposter/dbstorage/storage.go b/arbnode/dataposter/dbstorage/storage.go index f2b185449..473bfa2c3 100644 --- a/arbnode/dataposter/dbstorage/storage.go +++ b/arbnode/dataposter/dbstorage/storage.go @@ -6,6 +6,7 @@ package dbstorage import ( "bytes" "context" + "encoding/hex" "errors" "fmt" "strconv" @@ -140,7 +141,7 @@ func (s *Storage) Put(ctx context.Context, index uint64, prev, new *storage.Queu return fmt.Errorf("encoding previous item: %w", err) } if !bytes.Equal(stored, prevEnc) { - return fmt.Errorf("replacing different item than expected at index: %v, stored: %v, prevEnc: %v", index, stored, prevEnc) + return fmt.Errorf("replacing different item than expected at index: %v, stored: %v, prevEnc: %v", index, hex.EncodeToString(stored), hex.EncodeToString(prevEnc)) } newEnc, err := s.encDec().Encode(new) if err != nil { diff --git a/arbnode/dataposter/slice/slicestorage.go b/arbnode/dataposter/slice/slicestorage.go index 04286df41..dbd7a3ea5 100644 --- a/arbnode/dataposter/slice/slicestorage.go +++ b/arbnode/dataposter/slice/slicestorage.go @@ -6,6 +6,7 @@ package slice import ( "bytes" "context" + "encoding/hex" "errors" "fmt" @@ -90,7 +91,7 @@ func (s *Storage) Put(_ context.Context, index uint64, prev, new *storage.Queued return fmt.Errorf("encoding previous item: %w", err) } if !bytes.Equal(prevEnc, s.queue[queueIdx]) { - return fmt.Errorf("replacing different item than expected at index: %v, stored: %v, prevEnc: %v", index, s.queue[queueIdx], prevEnc) + return fmt.Errorf("replacing different item than expected at index: %v, stored: %v, prevEnc: %v", index, hex.EncodeToString(s.queue[queueIdx]), hex.EncodeToString(prevEnc)) } s.queue[queueIdx] = newEnc } else { diff --git a/arbnode/dataposter/storage/storage.go b/arbnode/dataposter/storage/storage.go index 70637c48e..b55f6363f 100644 --- a/arbnode/dataposter/storage/storage.go +++ b/arbnode/dataposter/storage/storage.go @@ -1,8 +1,12 @@ +// Copyright 2021-2023, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + package storage import ( "errors" "fmt" + "io" "time" "github.com/ethereum/go-ethereum/core/types" @@ -30,6 +34,44 @@ type QueuedTransaction struct { NextReplacement time.Time } +type QueuedTransactionForEncoding struct { + FullTx *types.Transaction + Data types.DynamicFeeTx + Meta []byte + Sent bool + Created *RlpTime `rlp:"optional"` // may be earlier than the tx was given to the tx poster + NextReplacement *RlpTime `rlp:"optional"` +} + +func (qt *QueuedTransaction) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, QueuedTransactionForEncoding{ + FullTx: qt.FullTx, + Data: qt.Data, + Meta: qt.Meta, + Sent: qt.Sent, + Created: (*RlpTime)(&qt.Created), + NextReplacement: (*RlpTime)(&qt.NextReplacement), + }) +} + +func (qt *QueuedTransaction) DecodeRLP(s *rlp.Stream) error { + var qtEnc QueuedTransactionForEncoding + if err := s.Decode(&qtEnc); err != nil { + return err + } + qt.FullTx = qtEnc.FullTx + qt.Data = qtEnc.Data + qt.Meta = qtEnc.Meta + qt.Sent = qtEnc.Sent + if qtEnc.Created != nil { + qt.Created = time.Time(*qtEnc.Created) + } + if qtEnc.NextReplacement != nil { + qt.NextReplacement = time.Time(*qtEnc.NextReplacement) + } + return nil +} + // LegacyQueuedTransaction is used for backwards compatibility. // Before https://github.com/OffchainLabs/nitro/pull/1773: the queuedTransaction // looked like this and was rlp encoded directly. After the pr, we are store diff --git a/arbnode/dataposter/storage/time.go b/arbnode/dataposter/storage/time.go new file mode 100644 index 000000000..d9911de99 --- /dev/null +++ b/arbnode/dataposter/storage/time.go @@ -0,0 +1,34 @@ +// Copyright 2021-2023, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package storage + +import ( + "io" + "time" + + "github.com/ethereum/go-ethereum/rlp" +) + +// time.Time doesn't encode as anything in RLP. This fixes that. +// It encodes a timestamp as a uint64 unix timestamp in seconds, +// so any subsecond precision is lost. +type RlpTime time.Time + +func (b *RlpTime) DecodeRLP(s *rlp.Stream) error { + var nanos uint64 + err := s.Decode(&nanos) + if err != nil { + return err + } + *b = RlpTime(time.Unix(int64(nanos), 0)) + return nil +} + +func (b RlpTime) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, uint64(time.Time(b).Unix())) +} + +func (b RlpTime) String() string { + return time.Time(b).String() +} diff --git a/arbnode/dataposter/storage_test.go b/arbnode/dataposter/storage_test.go index adea2073e..ff5623f77 100644 --- a/arbnode/dataposter/storage_test.go +++ b/arbnode/dataposter/storage_test.go @@ -5,6 +5,7 @@ import ( "math/big" "path" "testing" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" @@ -366,3 +367,21 @@ func TestLength(t *testing.T) { } } + +func TestTimeEncoding(t *testing.T) { + // RlpTime cuts off subsecond precision, so for this test, + // we'll use a time that doesn't have any subsecond precision. + now := storage.RlpTime(time.Unix(time.Now().Unix(), 0)) + enc, err := rlp.EncodeToBytes(now) + if err != nil { + t.Fatal("failed to encode time", err) + } + var dec storage.RlpTime + err = rlp.DecodeBytes(enc, &dec) + if err != nil { + t.Fatal("failed to decode time", err) + } + if !time.Time(dec).Equal(time.Time(now)) { + t.Fatalf("time %v encoded then decoded to %v", now, dec) + } +} From 0bc7f5035d16de248f4d8316cc1185916c398445 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 11 Dec 2023 14:43:33 -0700 Subject: [PATCH 503/775] Always saveTx in sendTx --- arbnode/dataposter/data_poster.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 4138aa840..f53527911 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -537,10 +537,8 @@ func (p *DataPoster) saveTx(ctx context.Context, prevTx, newTx *storage.QueuedTr } func (p *DataPoster) sendTx(ctx context.Context, prevTx *storage.QueuedTransaction, newTx *storage.QueuedTransaction) error { - if prevTx == nil || (newTx.FullTx.Hash() != prevTx.FullTx.Hash()) { - if err := p.saveTx(ctx, prevTx, newTx); err != nil { - return err - } + if err := p.saveTx(ctx, prevTx, newTx); err != nil { + return err } if err := p.client.SendTransaction(ctx, newTx.FullTx); err != nil { if !strings.Contains(err.Error(), "already known") && !strings.Contains(err.Error(), "nonce too low") { From f7275cfb109041e102858a54f2778c94a0b794b8 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 11 Dec 2023 17:05:29 -0700 Subject: [PATCH 504/775] Make saveTx skipping check comprehensive --- arbnode/dataposter/data_poster.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index f53527911..23b63cad4 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -5,6 +5,7 @@ package dataposter import ( + "bytes" "context" "crypto/tls" "crypto/x509" @@ -527,8 +528,24 @@ func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Tim // the mutex must be held by the caller func (p *DataPoster) saveTx(ctx context.Context, prevTx, newTx *storage.QueuedTransaction) error { - if prevTx != nil && prevTx.Data.Nonce != newTx.Data.Nonce { - return fmt.Errorf("prevTx nonce %v doesn't match newTx nonce %v", prevTx.Data.Nonce, newTx.Data.Nonce) + if prevTx != nil { + if prevTx.Data.Nonce != newTx.Data.Nonce { + return fmt.Errorf("prevTx nonce %v doesn't match newTx nonce %v", prevTx.Data.Nonce, newTx.Data.Nonce) + } + + // Check if prevTx is the same as newTx and we don't need to do anything + oldEnc, err := rlp.EncodeToBytes(prevTx) + if err != nil { + return fmt.Errorf("failed to encode prevTx: %w", err) + } + newEnc, err := rlp.EncodeToBytes(newTx) + if err != nil { + return fmt.Errorf("failed to encode newTx: %w", err) + } + if bytes.Equal(oldEnc, newEnc) { + // No need to save newTx as it's the same as prevTx + return nil + } } if err := p.queue.Put(ctx, newTx.Data.Nonce, prevTx, newTx); err != nil { return fmt.Errorf("putting new tx in the queue: %w", err) From c3c08335b73f5180ab9536642ae7c4e9ccc022fc Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 12 Dec 2023 14:14:42 +0530 Subject: [PATCH 505/775] Validate execution node config at startup and update --dev flag parameter --- cmd/nitro/nitro.go | 3 +++ cmd/util/confighelpers/configuration.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 86093a85d..08d80cff1 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -786,6 +786,9 @@ func (c *NodeConfig) Validate() error { if err := c.Node.Validate(); err != nil { return err } + if err := c.Execution.Validate(); err != nil { + return err + } return c.Persistent.Validate() } diff --git a/cmd/util/confighelpers/configuration.go b/cmd/util/confighelpers/configuration.go index 85a8f4ade..81e124d9b 100644 --- a/cmd/util/confighelpers/configuration.go +++ b/cmd/util/confighelpers/configuration.go @@ -147,7 +147,7 @@ func devFlagArgs() []string { "--parent-chain.id=1337", "--chain.id=412346", "--persistent.chain", "/tmp/dev-test", - "--node.sequencer", + "--execution.sequencer.enable=true", "--node.dangerous.no-sequencer-coordinator", "--node.staker.enable=false", "--init.empty=false", From 698b448fd667f3fd3c674246513a7940a20d7dfb Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 12 Dec 2023 15:16:23 +0530 Subject: [PATCH 506/775] fix using of sequencer-url as default forwarding-target --- cmd/nitro/nitro.go | 3 ++- cmd/util/confighelpers/configuration.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 08d80cff1..3efba5df2 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -893,7 +893,8 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c "chain.id": chainInfo.ChainConfig.ChainID.Uint64(), "parent-chain.id": chainInfo.ParentChainId, } - if chainInfo.SequencerUrl != "" { + // Only use chainInfo.SequencerUrl as default forwarding-target if sequencer is not enabled + if !k.Bool("execution.sequencer.enable") && chainInfo.SequencerUrl != "" { chainDefaults["execution.forwarding-target"] = chainInfo.SequencerUrl } if chainInfo.SecondaryForwardingTarget != "" { diff --git a/cmd/util/confighelpers/configuration.go b/cmd/util/confighelpers/configuration.go index 81e124d9b..3ff27d65c 100644 --- a/cmd/util/confighelpers/configuration.go +++ b/cmd/util/confighelpers/configuration.go @@ -147,7 +147,8 @@ func devFlagArgs() []string { "--parent-chain.id=1337", "--chain.id=412346", "--persistent.chain", "/tmp/dev-test", - "--execution.sequencer.enable=true", + "--node.sequencer", + "--execution.sequencer.enable", "--node.dangerous.no-sequencer-coordinator", "--node.staker.enable=false", "--init.empty=false", From 74d889ed531f1aee9fcda3792308ad671dfa5a52 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Tue, 12 Dec 2023 17:53:37 +0100 Subject: [PATCH 507/775] Add prysms recursivelock lint to nitro --- Makefile | 1 + go.mod | 32 +++++++++--------- go.sum | 47 +++++++++++++++++++++++++++ linter/recursivelock/recursivelock.go | 11 +++++++ 4 files changed, 76 insertions(+), 15 deletions(-) create mode 100644 linter/recursivelock/recursivelock.go diff --git a/Makefile b/Makefile index 422110096..42fd1e359 100644 --- a/Makefile +++ b/Makefile @@ -307,6 +307,7 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro # strategic rules to minimize dependency building .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make + go run ./linter/recursivelock ./... go run ./linter/koanf ./... go run ./linter/pointercheck ./... golangci-lint run --fix diff --git a/go.mod b/go.mod index bdda6a61a..e504542a2 100644 --- a/go.mod +++ b/go.mod @@ -18,11 +18,11 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.10 github.com/aws/aws-sdk-go-v2/service/s3 v1.26.9 github.com/cavaliergopher/grab/v3 v3.0.1 - github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 + github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 github.com/codeclysm/extract/v3 v3.0.2 github.com/dgraph-io/badger/v3 v3.2103.2 github.com/enescakir/emoji v1.0.0 - github.com/ethereum/go-ethereum v1.10.26 + github.com/ethereum/go-ethereum v1.13.1 github.com/fatih/structtag v1.2.0 github.com/gdamore/tcell/v2 v2.6.0 github.com/google/go-cmp v0.5.9 @@ -73,7 +73,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect @@ -97,7 +97,7 @@ require ( github.com/dgraph-io/ristretto v0.1.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -131,7 +131,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect - github.com/huin/goupnp v1.1.0 // indirect + github.com/huin/goupnp v1.3.0 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect github.com/ipfs/go-block-format v0.1.1 // indirect @@ -195,7 +195,7 @@ require ( github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect github.com/libp2p/go-libp2p-kad-dht v0.21.1 // indirect github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect - github.com/libp2p/go-libp2p-pubsub v0.9.0 // indirect + github.com/libp2p/go-libp2p-pubsub v0.9.3 // indirect github.com/libp2p/go-libp2p-pubsub-router v0.6.0 // indirect github.com/libp2p/go-libp2p-record v0.2.0 // indirect github.com/libp2p/go-libp2p-routing-helpers v0.6.2 // indirect @@ -238,6 +238,7 @@ require ( github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect + github.com/prysmaticlabs/prysm/v4 v4.1.1 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-19 v0.3.3 // indirect github.com/quic-go/qtls-go1-20 v0.2.3 // indirect @@ -245,13 +246,13 @@ require ( github.com/quic-go/webtransport-go v0.5.2 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/rhnvrm/simples3 v0.6.1 // indirect - github.com/rivo/uniseg v0.4.3 // indirect + github.com/rivo/uniseg v0.4.4 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/samber/lo v1.36.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/supranational/blst v0.3.11 // indirect - github.com/urfave/cli/v2 v2.24.1 // indirect + github.com/urfave/cli/v2 v2.25.7 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect @@ -261,6 +262,7 @@ require ( github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.7.0 // indirect go.opentelemetry.io/otel/exporters/jaeger v1.7.0 // indirect @@ -308,12 +310,12 @@ require ( require ( github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect - github.com/VictoriaMetrics/fastcache v1.6.0 // indirect + github.com/VictoriaMetrics/fastcache v1.12.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect - github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect - github.com/go-ole/go-ole v1.2.1 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-redis/redis/v8 v8.11.4 github.com/go-stack/stack v1.8.1 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect @@ -330,11 +332,11 @@ require ( github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/rs/cors v1.7.0 // indirect - github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/tklauser/go-sysconf v0.3.5 // indirect - github.com/tklauser/numcpus v0.2.2 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect ) diff --git a/go.sum b/go.sum index bf8b4b826..0a9649c43 100644 --- a/go.sum +++ b/go.sum @@ -173,6 +173,8 @@ github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13P github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= @@ -198,6 +200,7 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/ceramicnetwork/go-dag-jose v0.1.0 h1:yJ/HVlfKpnD3LdYP03AHyTvbm3BpPiz2oZiOeReJRdU= github.com/ceramicnetwork/go-dag-jose v0.1.0/go.mod h1:qYA1nYt0X8u4XoMAVoOV3upUVKtrxy/I670Dg5F0wjI= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -225,6 +228,7 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/datadriven v1.0.3-0.20230801171734-e384cf455877 h1:1MLK4YpFtIEo3ZtMA5C795Wtv5VuUnrXX7mQG+aHg6o= github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= @@ -232,6 +236,8 @@ github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZe github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= +github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 h1:T+Np/xtzIjYM/P5NAw0e2Rf1FGvzDau1h54MKvx8G7w= +github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06/go.mod h1:bynZ3gvVyhlvjLI7PT6dmZ7g76xzJ7HpxfjgkzCGz6s= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= @@ -307,6 +313,8 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= +github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -360,6 +368,7 @@ github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09 github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= @@ -367,6 +376,8 @@ github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZ github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= @@ -403,6 +414,8 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -536,6 +549,7 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b h1:Qcx5LM0fSiks9uCyFZwDBUasd3lxd1RM0GYpL+Li5o4= github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= @@ -640,9 +654,12 @@ github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmK github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -1058,6 +1075,8 @@ github.com/libp2p/go-libp2p-peerstore v0.2.7/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuD github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= github.com/libp2p/go-libp2p-pubsub v0.9.0 h1:mcLb4WzwhUG4OKb0rp1/bYMd/DYhvMyzJheQH3LMd1s= github.com/libp2p/go-libp2p-pubsub v0.9.0/go.mod h1:OEsj0Cc/BpkqikXRTrVspWU/Hx7bMZwHP+6vNMd+c7I= +github.com/libp2p/go-libp2p-pubsub v0.9.3 h1:ihcz9oIBMaCK9kcx+yHWm3mLAFBMAUsM4ux42aikDxo= +github.com/libp2p/go-libp2p-pubsub v0.9.3/go.mod h1:RYA7aM9jIic5VV47WXu4GkcRxRhrdElWf8xtyli+Dzc= github.com/libp2p/go-libp2p-pubsub-router v0.6.0 h1:D30iKdlqDt5ZmLEYhHELCMRj8b4sFAqrUcshIUvVP/s= github.com/libp2p/go-libp2p-pubsub-router v0.6.0/go.mod h1:FY/q0/RBTKsLA7l4vqC2cbRbOvyDotg8PJQ7j8FDudE= github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= @@ -1372,6 +1391,7 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= @@ -1381,6 +1401,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= @@ -1464,6 +1486,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prysmaticlabs/prysm/v4 v4.1.1 h1:sbBkgfPzo/SGTJ5IimtsZSGECoRlhbowR1rEhTOdvHo= +github.com/prysmaticlabs/prysm/v4 v4.1.1/go.mod h1:+o907dc4mwEE0wJkQ8RrzCroC+q2WCzdCLtikwonw8c= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/qtls-go1-19 v0.3.3 h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE= @@ -1488,6 +1512,8 @@ github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703/go.mod h1:nVwGv4MP47T0j github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1513,6 +1539,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= @@ -1588,6 +1616,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= @@ -1596,12 +1625,18 @@ github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3 github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= @@ -1620,6 +1655,8 @@ github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60Nt github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.24.1 h1:/QYYr7g0EhwXEML8jO+8OYt5trPnLHS0p3mrgExJ5NU= github.com/urfave/cli/v2 v2.24.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -1684,6 +1721,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLCur2yWnJzwQEKRcAHXo6seXGuSwWw= github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= @@ -1886,6 +1925,8 @@ golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= @@ -1948,6 +1989,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2000,8 +2042,10 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2009,6 +2053,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -2103,6 +2149,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= diff --git a/linter/recursivelock/recursivelock.go b/linter/recursivelock/recursivelock.go new file mode 100644 index 000000000..9349759cf --- /dev/null +++ b/linter/recursivelock/recursivelock.go @@ -0,0 +1,11 @@ +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/recursivelock" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(recursivelock.Analyzer) +} From 8b64fa27317f46785cdae557ea2fb0f68f3ef6dd Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 12 Dec 2023 10:21:58 -0700 Subject: [PATCH 508/775] Add nanoseconds to time storage --- arbnode/dataposter/storage/storage.go | 6 +++--- arbnode/dataposter/storage/time.go | 16 ++++++++++++---- arbnode/dataposter/storage_test.go | 4 +--- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/arbnode/dataposter/storage/storage.go b/arbnode/dataposter/storage/storage.go index b55f6363f..87bfa8d83 100644 --- a/arbnode/dataposter/storage/storage.go +++ b/arbnode/dataposter/storage/storage.go @@ -34,7 +34,7 @@ type QueuedTransaction struct { NextReplacement time.Time } -type QueuedTransactionForEncoding struct { +type queuedTransactionForEncoding struct { FullTx *types.Transaction Data types.DynamicFeeTx Meta []byte @@ -44,7 +44,7 @@ type QueuedTransactionForEncoding struct { } func (qt *QueuedTransaction) EncodeRLP(w io.Writer) error { - return rlp.Encode(w, QueuedTransactionForEncoding{ + return rlp.Encode(w, queuedTransactionForEncoding{ FullTx: qt.FullTx, Data: qt.Data, Meta: qt.Meta, @@ -55,7 +55,7 @@ func (qt *QueuedTransaction) EncodeRLP(w io.Writer) error { } func (qt *QueuedTransaction) DecodeRLP(s *rlp.Stream) error { - var qtEnc QueuedTransactionForEncoding + var qtEnc queuedTransactionForEncoding if err := s.Decode(&qtEnc); err != nil { return err } diff --git a/arbnode/dataposter/storage/time.go b/arbnode/dataposter/storage/time.go index d9911de99..df07c5cff 100644 --- a/arbnode/dataposter/storage/time.go +++ b/arbnode/dataposter/storage/time.go @@ -15,18 +15,26 @@ import ( // so any subsecond precision is lost. type RlpTime time.Time +type rlpTimeEncoding struct { + Seconds uint64 + Nanos uint64 +} + func (b *RlpTime) DecodeRLP(s *rlp.Stream) error { - var nanos uint64 - err := s.Decode(&nanos) + var enc rlpTimeEncoding + err := s.Decode(&enc) if err != nil { return err } - *b = RlpTime(time.Unix(int64(nanos), 0)) + *b = RlpTime(time.Unix(int64(enc.Seconds), int64(enc.Nanos))) return nil } func (b RlpTime) EncodeRLP(w io.Writer) error { - return rlp.Encode(w, uint64(time.Time(b).Unix())) + return rlp.Encode(w, rlpTimeEncoding{ + Seconds: uint64(time.Time(b).Unix()), + Nanos: uint64(time.Time(b).Nanosecond()), + }) } func (b RlpTime) String() string { diff --git a/arbnode/dataposter/storage_test.go b/arbnode/dataposter/storage_test.go index ff5623f77..3344215e9 100644 --- a/arbnode/dataposter/storage_test.go +++ b/arbnode/dataposter/storage_test.go @@ -369,9 +369,7 @@ func TestLength(t *testing.T) { } func TestTimeEncoding(t *testing.T) { - // RlpTime cuts off subsecond precision, so for this test, - // we'll use a time that doesn't have any subsecond precision. - now := storage.RlpTime(time.Unix(time.Now().Unix(), 0)) + now := storage.RlpTime(time.Now()) enc, err := rlp.EncodeToBytes(now) if err != nil { t.Fatal("failed to encode time", err) From 34cdd3645291fe29a6442e7ea001d65d31890940 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 12 Dec 2023 12:13:48 -0700 Subject: [PATCH 509/775] Comment that we should always get a float from expression --- arbnode/dataposter/data_poster.go | 1 + 1 file changed, 1 insertion(+) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index f1ba185e3..c079ebca4 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -386,6 +386,7 @@ func (p *DataPoster) evalMaxFeeCapExpr(backlogOfBatches uint64, elapsed time.Dur } resultFloat, ok := result.(float64) if !ok { + // This shouldn't be possible because we only pass in float64s as arguments return nil, fmt.Errorf("maxFeeCapExpression evaluated to non-float64: %v", result) } // 1e9 gwei gas price is practically speaking an infinite gas price, so we cap it there. From 2a059e78ed00ad9757913df834f6c18a1a40df66 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 12 Dec 2023 12:14:04 -0700 Subject: [PATCH 510/775] Handle NaN in FloatToBig and comment on when it can return nil --- util/arbmath/math.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/util/arbmath/math.go b/util/arbmath/math.go index a5618438c..3d1df0ce6 100644 --- a/util/arbmath/math.go +++ b/util/arbmath/math.go @@ -75,7 +75,11 @@ func UintToBig(value uint64) *big.Int { } // FloatToBig casts a float to a huge +// Returns nil when passed NaN or Infinity func FloatToBig(value float64) *big.Int { + if math.IsNaN(value) { + return nil + } result, _ := new(big.Float).SetFloat64(value).Int(nil) return result } From 7985488ab71341ea4ac7ff4e82ba7b4ec8b9b595 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 13 Dec 2023 19:42:57 +0530 Subject: [PATCH 511/775] Pause nitro node block validator validation when memory is running low --- .../resourcemanager/resource_management.go | 32 ++++++------- .../resource_management_test.go | 8 ++-- staker/block_validator.go | 47 +++++++++++++++++++ 3 files changed, 67 insertions(+), 20 deletions(-) diff --git a/arbnode/resourcemanager/resource_management.go b/arbnode/resourcemanager/resource_management.go index cb1ae9d6e..aba823cc2 100644 --- a/arbnode/resourcemanager/resource_management.go +++ b/arbnode/resourcemanager/resource_management.go @@ -39,14 +39,14 @@ func Init(conf *Config) error { return nil } - limit, err := parseMemLimit(conf.MemFreeLimit) + limit, err := ParseMemLimit(conf.MemFreeLimit) if err != nil { return err } node.WrapHTTPHandler = func(srv http.Handler) (http.Handler, error) { - var c limitChecker - c, err := newCgroupsMemoryLimitCheckerIfSupported(limit) + var c LimitChecker + c, err := NewCgroupsMemoryLimitCheckerIfSupported(limit) if errors.Is(err, errNotSupported) { log.Error("No method for determining memory usage and limits was discovered, disabled memory limit RPC throttling") c = &trivialLimitChecker{} @@ -57,7 +57,7 @@ func Init(conf *Config) error { return nil } -func parseMemLimit(limitStr string) (int, error) { +func ParseMemLimit(limitStr string) (int, error) { var ( limit int = 1 s string @@ -105,10 +105,10 @@ func ConfigAddOptions(prefix string, f *pflag.FlagSet) { // limit check. type httpServer struct { inner http.Handler - c limitChecker + c LimitChecker } -func newHttpServer(inner http.Handler, c limitChecker) *httpServer { +func newHttpServer(inner http.Handler, c LimitChecker) *httpServer { return &httpServer{inner: inner, c: c} } @@ -116,7 +116,7 @@ func newHttpServer(inner http.Handler, c limitChecker) *httpServer { // limit is exceeded, in which case it returns a HTTP 429 error. func (s *httpServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { start := time.Now() - exceeded, err := s.c.isLimitExceeded() + exceeded, err := s.c.IsLimitExceeded() limitCheckDurationHistogram.Update(time.Since(start).Nanoseconds()) if err != nil { log.Error("Error checking memory limit", "err", err, "checker", s.c.String()) @@ -130,19 +130,19 @@ func (s *httpServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { s.inner.ServeHTTP(w, req) } -type limitChecker interface { - isLimitExceeded() (bool, error) +type LimitChecker interface { + IsLimitExceeded() (bool, error) String() string } -func isSupported(c limitChecker) bool { - _, err := c.isLimitExceeded() +func isSupported(c LimitChecker) bool { + _, err := c.IsLimitExceeded() return err == nil } -// newCgroupsMemoryLimitCheckerIfSupported attempts to auto-discover whether +// NewCgroupsMemoryLimitCheckerIfSupported attempts to auto-discover whether // Cgroups V1 or V2 is supported for checking system memory limits. -func newCgroupsMemoryLimitCheckerIfSupported(memLimitBytes int) (*cgroupsMemoryLimitChecker, error) { +func NewCgroupsMemoryLimitCheckerIfSupported(memLimitBytes int) (*cgroupsMemoryLimitChecker, error) { c := newCgroupsMemoryLimitChecker(cgroupsV1MemoryFiles, memLimitBytes) if isSupported(c) { log.Info("Cgroups v1 detected, enabling memory limit RPC throttling") @@ -161,7 +161,7 @@ func newCgroupsMemoryLimitCheckerIfSupported(memLimitBytes int) (*cgroupsMemoryL // trivialLimitChecker checks no limits, so its limits are never exceeded. type trivialLimitChecker struct{} -func (_ trivialLimitChecker) isLimitExceeded() (bool, error) { +func (_ trivialLimitChecker) IsLimitExceeded() (bool, error) { return false, nil } @@ -202,7 +202,7 @@ func newCgroupsMemoryLimitChecker(files cgroupsMemoryFiles, memLimitBytes int) * } } -// isLimitExceeded checks if the system memory free is less than the limit. +// IsLimitExceeded checks if the system memory free is less than the limit. // It returns true if the limit is exceeded. // // container_memory_working_set_bytes in prometheus is calculated as @@ -223,7 +223,7 @@ func newCgroupsMemoryLimitChecker(files cgroupsMemoryFiles, memLimitBytes int) * // free memory for the page cache, to avoid cache thrashing on chain state // access. How much "reasonable" is will depend on access patterns, state // size, and your application's tolerance for latency. -func (c *cgroupsMemoryLimitChecker) isLimitExceeded() (bool, error) { +func (c *cgroupsMemoryLimitChecker) IsLimitExceeded() (bool, error) { var limit, usage, active, inactive int var err error if limit, err = readIntFromFile(c.files.limitFile); err != nil { diff --git a/arbnode/resourcemanager/resource_management_test.go b/arbnode/resourcemanager/resource_management_test.go index 4f52ad017..449539606 100644 --- a/arbnode/resourcemanager/resource_management_test.go +++ b/arbnode/resourcemanager/resource_management_test.go @@ -52,7 +52,7 @@ func makeCgroupsTestDir(cgroupDir string) cgroupsMemoryFiles { func TestCgroupsFailIfCantOpen(t *testing.T) { testFiles := makeCgroupsTestDir(t.TempDir()) c := newCgroupsMemoryLimitChecker(testFiles, 1024*1024*512) - if _, err := c.isLimitExceeded(); err == nil { + if _, err := c.IsLimitExceeded(); err == nil { t.Fatal("Should fail open if can't read files") } } @@ -124,7 +124,7 @@ func TestCgroupsMemoryLimit(t *testing.T) { } { t.Run(tc.desc, func(t *testing.T) { testFiles := makeCgroupsTestDir(t.TempDir()) - memLimit, err := parseMemLimit(tc.memLimit) + memLimit, err := ParseMemLimit(tc.memLimit) if err != nil { t.Fatalf("Parsing memory limit failed: %v", err) } @@ -132,12 +132,12 @@ func TestCgroupsMemoryLimit(t *testing.T) { if err := updateFakeCgroupFiles(c, tc.sysLimit, tc.usage, tc.inactive, tc.active); err != nil { t.Fatalf("Updating cgroup files: %v", err) } - exceeded, err := c.isLimitExceeded() + exceeded, err := c.IsLimitExceeded() if err != nil { t.Fatalf("Checking if limit exceeded: %v", err) } if exceeded != tc.want { - t.Errorf("isLimitExceeded() = %t, want %t", exceeded, tc.want) + t.Errorf("IsLimitExceeded() = %t, want %t", exceeded, tc.want) } }, ) diff --git a/staker/block_validator.go b/staker/block_validator.go index 61e5ed519..d54fa60c1 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -20,6 +20,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" + "github.com/offchainlabs/nitro/arbnode/resourcemanager" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/util/containers" "github.com/offchainlabs/nitro/util/rpcclient" @@ -75,6 +76,8 @@ type BlockValidator struct { testingProgressMadeChan chan struct{} fatalErr chan<- error + + MemoryFreeLimitChecker resourcemanager.LimitChecker } type BlockValidatorConfig struct { @@ -87,6 +90,7 @@ type BlockValidatorConfig struct { PendingUpgradeModuleRoot string `koanf:"pending-upgrade-module-root"` // TODO(magic) requires StatelessBlockValidator recreation on hot reload FailureIsFatal bool `koanf:"failure-is-fatal" reload:"hot"` Dangerous BlockValidatorDangerousConfig `koanf:"dangerous"` + MemoryFreeLimit string `koanf:"memory-free-limit" reload:"hot"` } func (c *BlockValidatorConfig) Validate() error { @@ -109,6 +113,7 @@ func BlockValidatorConfigAddOptions(prefix string, f *flag.FlagSet) { f.String(prefix+".pending-upgrade-module-root", DefaultBlockValidatorConfig.PendingUpgradeModuleRoot, "pending upgrade wasm module root to additionally validate (hash, 'latest' or empty)") f.Bool(prefix+".failure-is-fatal", DefaultBlockValidatorConfig.FailureIsFatal, "failing a validation is treated as a fatal error") BlockValidatorDangerousConfigAddOptions(prefix+".dangerous", f) + f.String(prefix+".memory-free-limit", DefaultBlockValidatorConfig.MemoryFreeLimit, "minimum free-memory limit after reaching which the blockvalidator pauses validation") } func BlockValidatorDangerousConfigAddOptions(prefix string, f *flag.FlagSet) { @@ -125,6 +130,7 @@ var DefaultBlockValidatorConfig = BlockValidatorConfig{ PendingUpgradeModuleRoot: "latest", FailureIsFatal: true, Dangerous: DefaultBlockValidatorDangerousConfig, + MemoryFreeLimit: "1GB", } var TestBlockValidatorConfig = BlockValidatorConfig{ @@ -137,6 +143,7 @@ var TestBlockValidatorConfig = BlockValidatorConfig{ PendingUpgradeModuleRoot: "latest", FailureIsFatal: true, Dangerous: DefaultBlockValidatorDangerousConfig, + MemoryFreeLimit: "1GB", } var DefaultBlockValidatorDangerousConfig = BlockValidatorDangerousConfig{ @@ -215,6 +222,19 @@ func NewBlockValidator( } streamer.SetBlockValidator(ret) inbox.SetBlockValidator(ret) + if config().MemoryFreeLimit != "" { + limit, err := resourcemanager.ParseMemLimit(config().MemoryFreeLimit) + if err != nil { + return nil, fmt.Errorf("failed to parse MemoryFreeLimit string from config: %w", err) + } + limtchecker, err := resourcemanager.NewCgroupsMemoryLimitCheckerIfSupported(limit) + if err != nil { + log.Warn("failed to create MemoryFreeLimitChecker, Cgroups V1 or V2 is unsupported") + } + if limtchecker != nil { + ret.MemoryFreeLimitChecker = limtchecker + } + } return ret, nil } @@ -521,6 +541,15 @@ func (v *BlockValidator) iterativeValidationEntryCreator(ctx context.Context, ig } func (v *BlockValidator) sendNextRecordRequests(ctx context.Context) (bool, error) { + if v.MemoryFreeLimitChecker != nil { + exceeded, err := v.MemoryFreeLimitChecker.IsLimitExceeded() + if err != nil { + log.Error("error checking if free-memory limit exceeded using MemoryFreeLimitChecker", "err", err) + } + if exceeded { + return false, nil + } + } v.reorgMutex.RLock() pos := v.recordSent() created := v.created() @@ -550,6 +579,15 @@ func (v *BlockValidator) sendNextRecordRequests(ctx context.Context) (bool, erro return true, nil } for pos <= recordUntil { + if v.MemoryFreeLimitChecker != nil { + exceeded, err := v.MemoryFreeLimitChecker.IsLimitExceeded() + if err != nil { + log.Error("error checking if free-memory limit exceeded using MemoryFreeLimitChecker", "err", err) + } + if exceeded { + return false, nil + } + } validationStatus, found := v.validations.Load(pos) if !found { return false, fmt.Errorf("not found entry for pos %d", pos) @@ -699,6 +737,15 @@ validationsLoop: log.Trace("advanceValidations: no more room", "pos", pos) return nil, nil } + if v.MemoryFreeLimitChecker != nil { + exceeded, err := v.MemoryFreeLimitChecker.IsLimitExceeded() + if err != nil { + log.Error("error checking if free-memory limit exceeded using MemoryFreeLimitChecker", "err", err) + } + if exceeded { + return nil, nil + } + } if currentStatus == Prepared { input, err := validationStatus.Entry.ToInput() if err != nil && ctx.Err() == nil { From 0638a0b15bdaea8903b732ecf149712ec67ddf21 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Wed, 13 Dec 2023 16:14:39 +0100 Subject: [PATCH 512/775] Add linters from prysm --- Makefile | 38 +++++++++++++++++++ arbos/l1pricing/l1pricing.go | 6 +-- go.mod | 2 + go.sum | 16 ++++++++ linter/comparesame/comparesame.go | 12 ++++++ linter/cryptorand/cryptorand.go | 13 +++++++ linter/errcheck/errcheck.go | 12 ++++++ linter/featureconfig/featureconfig.go | 12 ++++++ linter/gocognit/gocognit.go | 13 +++++++ linter/ineffassign/ineffassign.go | 12 ++++++ linter/interfacechecker/interfacechecker.go | 12 ++++++ linter/logruswitherror/logruswitherror.go | 12 ++++++ linter/maligned/maligned.go | 12 ++++++ linter/properpermissions/properpermissions.go | 12 ++++++ linter/recursivelock/recursivelock.go | 1 + linter/shadowpredecl/shadowpredecl.go | 12 ++++++ linter/slicedirect/slicedirect.go | 12 ++++++ linter/uintcast/uintcast.go | 12 ++++++ 18 files changed, 218 insertions(+), 3 deletions(-) create mode 100644 linter/comparesame/comparesame.go create mode 100644 linter/cryptorand/cryptorand.go create mode 100644 linter/errcheck/errcheck.go create mode 100644 linter/featureconfig/featureconfig.go create mode 100644 linter/gocognit/gocognit.go create mode 100644 linter/ineffassign/ineffassign.go create mode 100644 linter/interfacechecker/interfacechecker.go create mode 100644 linter/logruswitherror/logruswitherror.go create mode 100644 linter/maligned/maligned.go create mode 100644 linter/properpermissions/properpermissions.go create mode 100644 linter/shadowpredecl/shadowpredecl.go create mode 100644 linter/slicedirect/slicedirect.go create mode 100644 linter/uintcast/uintcast.go diff --git a/Makefile b/Makefile index 42fd1e359..ddb94d97a 100644 --- a/Makefile +++ b/Makefile @@ -308,6 +308,44 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make go run ./linter/recursivelock ./... + go run ./linter/comparesame ./... + + # Disabled since we have a lot of use of math/rand package. + # We should probably move to crypto/rand at some point even though most of + # our uses doesn't seem to be security sensitive. + # TODO fix this and enable. + # go run ./linter/cryptorand ./... + + # This yields lot of legitimate warnings, most of which in practice would + # probably never happen. + # # TODO fix this and enable. + # go run ./linter/errcheck ./... + + go run ./linter/featureconfig ./... + + # Disabled since we have high cognitive complexity several places. + # TODO fix this and enable. + # go run ./linter/gocognit ./... + + go run ./linter/ineffassign ./... + go run ./linter/interfacechecker ./... + go run ./linter/logruswitherror ./... + + # Yields several non-optimally sorted structs, not sure this is very + # for us. Probably fine to not have this linter. + # go run ./linter/maligned ./... + + # Don't think this is really relevant for us. + # go run ./linter/properpermissions ./... + + go run ./linter/shadowpredecl ./... + go run ./linter/slicedirect ./... + + # Disabled since it fails many places, although ones I looked into seem + # to be false positives logically. + # TODO fix this and enable and mark false positives with lint ignore. + # go run ./linter/uintcast ./... + go run ./linter/koanf ./... go run ./linter/pointercheck ./... golangci-lint run --fix diff --git a/arbos/l1pricing/l1pricing.go b/arbos/l1pricing/l1pricing.go index 27ecae8b8..be5540b60 100644 --- a/arbos/l1pricing/l1pricing.go +++ b/arbos/l1pricing/l1pricing.go @@ -259,11 +259,11 @@ func (ps *L1PricingState) AddToL1FeesAvailable(delta *big.Int) (*big.Int, error) if err != nil { return nil, err } - new := new(big.Int).Add(old, delta) - if err := ps.SetL1FeesAvailable(new); err != nil { + newFee := new(big.Int).Add(old, delta) + if err := ps.SetL1FeesAvailable(newFee); err != nil { return nil, err } - return new, nil + return newFee, nil } func (ps *L1PricingState) TransferFromL1FeesAvailable( diff --git a/go.mod b/go.mod index e504542a2..f87887e18 100644 --- a/go.mod +++ b/go.mod @@ -124,6 +124,7 @@ require ( github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b // indirect github.com/gorilla/mux v1.8.0 // indirect + github.com/gostaticanalysis/comment v1.4.2 // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect github.com/h2non/filetype v1.0.6 // indirect @@ -253,6 +254,7 @@ require ( github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/urfave/cli/v2 v2.25.7 // indirect + github.com/uudashr/gocognit v1.0.5 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect diff --git a/go.sum b/go.sum index 0a9649c43..4e3f0f62b 100644 --- a/go.sum +++ b/go.sum @@ -581,6 +581,9 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= +github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= +github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= @@ -625,6 +628,7 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -1420,6 +1424,11 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.4.0 h1:CtfRrOVZtbDj8rt1WXjklw0kqqJQwICrCKmlfUuBUUw= github.com/openzipkin/zipkin-go v0.4.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0R4l6Zg0P1tTQ= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1628,6 +1637,8 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45 github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= +github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= @@ -1658,6 +1669,8 @@ github.com/urfave/cli/v2 v2.24.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6f github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/uudashr/gocognit v1.0.5 h1:rrSex7oHr3/pPLQ0xoWq108XMU8s678FJcQ+aSfOHa4= +github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= @@ -1863,6 +1876,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= @@ -2139,8 +2153,10 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= diff --git a/linter/comparesame/comparesame.go b/linter/comparesame/comparesame.go new file mode 100644 index 000000000..1d91592e9 --- /dev/null +++ b/linter/comparesame/comparesame.go @@ -0,0 +1,12 @@ +// Static Analyzer to ensure code does not contain comparisons of identical expressions. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/comparesame" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(comparesame.Analyzer) +} diff --git a/linter/cryptorand/cryptorand.go b/linter/cryptorand/cryptorand.go new file mode 100644 index 000000000..a7cd1ca65 --- /dev/null +++ b/linter/cryptorand/cryptorand.go @@ -0,0 +1,13 @@ +// Static Analyzer to ensure the crypto/rand package is used for randomness +// throughout the codebase. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/cryptorand" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(cryptorand.Analyzer) +} diff --git a/linter/errcheck/errcheck.go b/linter/errcheck/errcheck.go new file mode 100644 index 000000000..8275b2bab --- /dev/null +++ b/linter/errcheck/errcheck.go @@ -0,0 +1,12 @@ +// Static analyzer to ensure that errors are handled in go code. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/errcheck" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(errcheck.Analyzer) +} diff --git a/linter/featureconfig/featureconfig.go b/linter/featureconfig/featureconfig.go new file mode 100644 index 000000000..bb9c2dd3a --- /dev/null +++ b/linter/featureconfig/featureconfig.go @@ -0,0 +1,12 @@ +// Static analyzer to prevent leaking globals in tests. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/featureconfig" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(featureconfig.Analyzer) +} diff --git a/linter/gocognit/gocognit.go b/linter/gocognit/gocognit.go new file mode 100644 index 000000000..a50d0ac08 --- /dev/null +++ b/linter/gocognit/gocognit.go @@ -0,0 +1,13 @@ +// Static analyzer that checks for high cognitive complexity and complains when +// it's too high. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/gocognit" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(gocognit.Analyzer) +} diff --git a/linter/ineffassign/ineffassign.go b/linter/ineffassign/ineffassign.go new file mode 100644 index 000000000..df986b57e --- /dev/null +++ b/linter/ineffassign/ineffassign.go @@ -0,0 +1,12 @@ +// Static analyzer to prevent leaking globals in tests. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/ineffassign" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(ineffassign.Analyzer) +} diff --git a/linter/interfacechecker/interfacechecker.go b/linter/interfacechecker/interfacechecker.go new file mode 100644 index 000000000..a12c71a61 --- /dev/null +++ b/linter/interfacechecker/interfacechecker.go @@ -0,0 +1,12 @@ +// Static analyzer to prevent leaking globals in tests. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/interfacechecker" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(interfacechecker.Analyzer) +} diff --git a/linter/logruswitherror/logruswitherror.go b/linter/logruswitherror/logruswitherror.go new file mode 100644 index 000000000..a868cdbee --- /dev/null +++ b/linter/logruswitherror/logruswitherror.go @@ -0,0 +1,12 @@ +// Static analyzer to prevent leaking globals in tests. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/logruswitherror" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(logruswitherror.Analyzer) +} diff --git a/linter/maligned/maligned.go b/linter/maligned/maligned.go new file mode 100644 index 000000000..3a693fad8 --- /dev/null +++ b/linter/maligned/maligned.go @@ -0,0 +1,12 @@ +// Static analyzer to prevent leaking globals in tests. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/maligned" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(maligned.Analyzer) +} diff --git a/linter/properpermissions/properpermissions.go b/linter/properpermissions/properpermissions.go new file mode 100644 index 000000000..e9047125b --- /dev/null +++ b/linter/properpermissions/properpermissions.go @@ -0,0 +1,12 @@ +// Static analyzer to prevent leaking globals in tests. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/properpermissions" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(properpermissions.Analyzer) +} diff --git a/linter/recursivelock/recursivelock.go b/linter/recursivelock/recursivelock.go index 9349759cf..8c8caff38 100644 --- a/linter/recursivelock/recursivelock.go +++ b/linter/recursivelock/recursivelock.go @@ -1,3 +1,4 @@ +// Static Analyzer for detecting nested or recursive mutex read lock statements. package main import ( diff --git a/linter/shadowpredecl/shadowpredecl.go b/linter/shadowpredecl/shadowpredecl.go new file mode 100644 index 000000000..d11c1c04c --- /dev/null +++ b/linter/shadowpredecl/shadowpredecl.go @@ -0,0 +1,12 @@ +// Static analyzer to prevent leaking globals in tests. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/shadowpredecl" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(shadowpredecl.Analyzer) +} diff --git a/linter/slicedirect/slicedirect.go b/linter/slicedirect/slicedirect.go new file mode 100644 index 000000000..c51cd9da9 --- /dev/null +++ b/linter/slicedirect/slicedirect.go @@ -0,0 +1,12 @@ +// Static analyzer to prevent leaking globals in tests. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/slicedirect" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(slicedirect.Analyzer) +} diff --git a/linter/uintcast/uintcast.go b/linter/uintcast/uintcast.go new file mode 100644 index 000000000..bce88a8b9 --- /dev/null +++ b/linter/uintcast/uintcast.go @@ -0,0 +1,12 @@ +// Static analyzer to prevent leaking globals in tests. +package main + +import ( + "github.com/prysmaticlabs/prysm/v4/tools/analyzers/uintcast" + + "golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { + singlechecker.Main(uintcast.Analyzer) +} From a361d296f85fd8eaf443b4a966ef1dd8610b8e5d Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Wed, 13 Dec 2023 16:24:12 +0100 Subject: [PATCH 513/775] Drop linters that do not seem too relevant for nitro --- Makefile | 7 ------- linter/ineffassign/ineffassign.go | 2 +- linter/interfacechecker/interfacechecker.go | 2 +- linter/logruswitherror/logruswitherror.go | 3 ++- linter/maligned/maligned.go | 12 ------------ linter/properpermissions/properpermissions.go | 12 ------------ linter/shadowpredecl/shadowpredecl.go | 3 ++- linter/slicedirect/slicedirect.go | 3 ++- linter/uintcast/uintcast.go | 3 ++- 9 files changed, 10 insertions(+), 37 deletions(-) delete mode 100644 linter/maligned/maligned.go delete mode 100644 linter/properpermissions/properpermissions.go diff --git a/Makefile b/Makefile index ddb94d97a..d7f4599db 100644 --- a/Makefile +++ b/Makefile @@ -331,13 +331,6 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro go run ./linter/interfacechecker ./... go run ./linter/logruswitherror ./... - # Yields several non-optimally sorted structs, not sure this is very - # for us. Probably fine to not have this linter. - # go run ./linter/maligned ./... - - # Don't think this is really relevant for us. - # go run ./linter/properpermissions ./... - go run ./linter/shadowpredecl ./... go run ./linter/slicedirect ./... diff --git a/linter/ineffassign/ineffassign.go b/linter/ineffassign/ineffassign.go index df986b57e..697e10482 100644 --- a/linter/ineffassign/ineffassign.go +++ b/linter/ineffassign/ineffassign.go @@ -1,4 +1,4 @@ -// Static analyzer to prevent leaking globals in tests. +// Static analyzer for detecting ineffectual assignments. package main import ( diff --git a/linter/interfacechecker/interfacechecker.go b/linter/interfacechecker/interfacechecker.go index a12c71a61..50bb56f74 100644 --- a/linter/interfacechecker/interfacechecker.go +++ b/linter/interfacechecker/interfacechecker.go @@ -1,4 +1,4 @@ -// Static analyzer to prevent leaking globals in tests. +// Static analyzer to prevent conditional checks on select interfaces. package main import ( diff --git a/linter/logruswitherror/logruswitherror.go b/linter/logruswitherror/logruswitherror.go index a868cdbee..d0da1fcb1 100644 --- a/linter/logruswitherror/logruswitherror.go +++ b/linter/logruswitherror/logruswitherror.go @@ -1,4 +1,5 @@ -// Static analyzer to prevent leaking globals in tests. +// Static analyzer to ensure that log statements do not use errors in +// templated log statements. Authors should use logrus.WithError(). package main import ( diff --git a/linter/maligned/maligned.go b/linter/maligned/maligned.go deleted file mode 100644 index 3a693fad8..000000000 --- a/linter/maligned/maligned.go +++ /dev/null @@ -1,12 +0,0 @@ -// Static analyzer to prevent leaking globals in tests. -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/maligned" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(maligned.Analyzer) -} diff --git a/linter/properpermissions/properpermissions.go b/linter/properpermissions/properpermissions.go deleted file mode 100644 index e9047125b..000000000 --- a/linter/properpermissions/properpermissions.go +++ /dev/null @@ -1,12 +0,0 @@ -// Static analyzer to prevent leaking globals in tests. -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/properpermissions" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(properpermissions.Analyzer) -} diff --git a/linter/shadowpredecl/shadowpredecl.go b/linter/shadowpredecl/shadowpredecl.go index d11c1c04c..e51ff0da8 100644 --- a/linter/shadowpredecl/shadowpredecl.go +++ b/linter/shadowpredecl/shadowpredecl.go @@ -1,4 +1,5 @@ -// Static analyzer to prevent leaking globals in tests. +// Static analyzer which disallows declaring constructs that shadow predeclared +// Go identifiers by having the same name. package main import ( diff --git a/linter/slicedirect/slicedirect.go b/linter/slicedirect/slicedirect.go index c51cd9da9..b31404013 100644 --- a/linter/slicedirect/slicedirect.go +++ b/linter/slicedirect/slicedirect.go @@ -1,4 +1,5 @@ -// Static analyzer to prevent leaking globals in tests. +// Static analyzer to ensure that code does not contain applications of [:] +// on expressions which are already slices. package main import ( diff --git a/linter/uintcast/uintcast.go b/linter/uintcast/uintcast.go index bce88a8b9..1f0eb7857 100644 --- a/linter/uintcast/uintcast.go +++ b/linter/uintcast/uintcast.go @@ -1,4 +1,5 @@ -// Static analyzer to prevent leaking globals in tests. +// Static analyzer for detecting unsafe uint to int casts. +// Use `lint:ignore uintcast` with proper justification to ignore this check. package main import ( From 69e8dde1dfc14758957ce4d3b45dd4e95ed49923 Mon Sep 17 00:00:00 2001 From: Christopher Lamb <37453482+lambchr@users.noreply.github.com> Date: Wed, 13 Dec 2023 16:19:09 +0000 Subject: [PATCH 514/775] remove recursive lock calls from backlogSegment object --- broadcaster/backlog/backlog.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index dee3aa92e..a1bd2c302 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -294,6 +294,12 @@ func (s *backlogSegment) start() uint64 { func (s *backlogSegment) End() uint64 { s.messagesLock.RLock() defer s.messagesLock.RUnlock() + return s.end() +} + +// end allows the first message to be retrieved from functions that already +// have the messagesLock. +func (s *backlogSegment) end() uint64 { c := len(s.messages) if c == 0 { return uint64(0) @@ -328,7 +334,7 @@ func (s *backlogSegment) Get(start, end uint64) ([]*m.BroadcastFeedMessage, erro return noMsgs, errOutOfBounds } - if end > s.End() { + if end > s.end() { return noMsgs, errOutOfBounds } @@ -367,7 +373,7 @@ func (s *backlogSegment) Contains(i uint64) bool { s.messagesLock.RLock() defer s.messagesLock.RUnlock() start := s.start() - if i < start || i > s.End() { + if i < start || i > s.end() { return false } From 629c9e3e2e167efc7bf158cefa313cee864b862c Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 13 Dec 2023 10:25:34 -0700 Subject: [PATCH 515/775] Make makeClient function a field instead of a global --- broadcastclients/broadcastclients.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/broadcastclients/broadcastclients.go b/broadcastclients/broadcastclients.go index 16c465b9b..29f5e5192 100644 --- a/broadcastclients/broadcastclients.go +++ b/broadcastclients/broadcastclients.go @@ -43,6 +43,7 @@ type BroadcastClients struct { primaryClients []*broadcastclient.BroadcastClient secondaryClients []*broadcastclient.BroadcastClient secondaryURL []string + makeClient func(string, *Router) (*broadcastclient.BroadcastClient, error) primaryRouter *Router secondaryRouter *Router @@ -51,8 +52,6 @@ type BroadcastClients struct { connected int32 } -var makeClient func(string, *Router) (*broadcastclient.BroadcastClient, error) - func NewBroadcastClients( configFetcher broadcastclient.ConfigFetcher, l2ChainId uint64, @@ -81,7 +80,7 @@ func NewBroadcastClients( secondaryClients: make([]*broadcastclient.BroadcastClient, 0, len(config.SecondaryURL)), secondaryURL: config.SecondaryURL, } - makeClient = func(url string, router *Router) (*broadcastclient.BroadcastClient, error) { + clients.makeClient = func(url string, router *Router) (*broadcastclient.BroadcastClient, error) { return broadcastclient.NewBroadcastClient( configFetcher, url, @@ -97,7 +96,7 @@ func NewBroadcastClients( var lastClientErr error for _, address := range config.URL { - client, err := makeClient(address, clients.primaryRouter) + client, err := clients.makeClient(address, clients.primaryRouter) if err != nil { lastClientErr = err log.Warn("init broadcast client failed", "address", address) @@ -243,7 +242,7 @@ func (bcs *BroadcastClients) startSecondaryFeed(ctx context.Context) { pos := len(bcs.secondaryClients) if pos < len(bcs.secondaryURL) { url := bcs.secondaryURL[pos] - client, err := makeClient(url, bcs.secondaryRouter) + client, err := bcs.makeClient(url, bcs.secondaryRouter) if err != nil { log.Warn("init broadcast secondary client failed", "address", url) bcs.secondaryURL = append(bcs.secondaryURL[:pos], bcs.secondaryURL[pos+1:]...) From 7e4e4e7f77e8fb4c7b473dc0eab746e2aab95cd9 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 15 Dec 2023 15:36:01 +0530 Subject: [PATCH 516/775] address PR comments --- staker/block_validator.go | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/staker/block_validator.go b/staker/block_validator.go index d54fa60c1..e649b112b 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -91,9 +91,25 @@ type BlockValidatorConfig struct { FailureIsFatal bool `koanf:"failure-is-fatal" reload:"hot"` Dangerous BlockValidatorDangerousConfig `koanf:"dangerous"` MemoryFreeLimit string `koanf:"memory-free-limit" reload:"hot"` + + memoryFreeLimit int } func (c *BlockValidatorConfig) Validate() error { + if c.MemoryFreeLimit == "default" { + c.memoryFreeLimit = 1073741824 // 1GB + _, err := resourcemanager.NewCgroupsMemoryLimitCheckerIfSupported(c.memoryFreeLimit) + if err != nil { + log.Warn("Cgroups V1 or V2 is unsupported, memory-free-limit feature inside block-validator is disabled") + c.MemoryFreeLimit = "" + } + } else if c.MemoryFreeLimit != "" { + limit, err := resourcemanager.ParseMemLimit(c.MemoryFreeLimit) + if err != nil { + return fmt.Errorf("failed to parse block-validator config memory-free-limit string: %w", err) + } + c.memoryFreeLimit = limit + } return c.ValidationServer.Validate() } @@ -113,7 +129,7 @@ func BlockValidatorConfigAddOptions(prefix string, f *flag.FlagSet) { f.String(prefix+".pending-upgrade-module-root", DefaultBlockValidatorConfig.PendingUpgradeModuleRoot, "pending upgrade wasm module root to additionally validate (hash, 'latest' or empty)") f.Bool(prefix+".failure-is-fatal", DefaultBlockValidatorConfig.FailureIsFatal, "failing a validation is treated as a fatal error") BlockValidatorDangerousConfigAddOptions(prefix+".dangerous", f) - f.String(prefix+".memory-free-limit", DefaultBlockValidatorConfig.MemoryFreeLimit, "minimum free-memory limit after reaching which the blockvalidator pauses validation") + f.String(prefix+".memory-free-limit", DefaultBlockValidatorConfig.MemoryFreeLimit, "minimum free-memory limit after reaching which the blockvalidator pauses validation. Enabled by default as 1GB, to disable provide empty string") } func BlockValidatorDangerousConfigAddOptions(prefix string, f *flag.FlagSet) { @@ -130,7 +146,7 @@ var DefaultBlockValidatorConfig = BlockValidatorConfig{ PendingUpgradeModuleRoot: "latest", FailureIsFatal: true, Dangerous: DefaultBlockValidatorDangerousConfig, - MemoryFreeLimit: "1GB", + MemoryFreeLimit: "default", } var TestBlockValidatorConfig = BlockValidatorConfig{ @@ -143,7 +159,7 @@ var TestBlockValidatorConfig = BlockValidatorConfig{ PendingUpgradeModuleRoot: "latest", FailureIsFatal: true, Dangerous: DefaultBlockValidatorDangerousConfig, - MemoryFreeLimit: "1GB", + MemoryFreeLimit: "default", } var DefaultBlockValidatorDangerousConfig = BlockValidatorDangerousConfig{ @@ -223,17 +239,11 @@ func NewBlockValidator( streamer.SetBlockValidator(ret) inbox.SetBlockValidator(ret) if config().MemoryFreeLimit != "" { - limit, err := resourcemanager.ParseMemLimit(config().MemoryFreeLimit) - if err != nil { - return nil, fmt.Errorf("failed to parse MemoryFreeLimit string from config: %w", err) - } - limtchecker, err := resourcemanager.NewCgroupsMemoryLimitCheckerIfSupported(limit) + limtchecker, err := resourcemanager.NewCgroupsMemoryLimitCheckerIfSupported(config().memoryFreeLimit) if err != nil { - log.Warn("failed to create MemoryFreeLimitChecker, Cgroups V1 or V2 is unsupported") - } - if limtchecker != nil { - ret.MemoryFreeLimitChecker = limtchecker + return nil, fmt.Errorf("failed to create MemoryFreeLimitChecker, Cgroups V1 or V2 is unsupported") } + ret.MemoryFreeLimitChecker = limtchecker } return ret, nil } From fa44e50c84d2ddf4984555da39d58a104975eafb Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 14 Dec 2023 23:42:22 +0000 Subject: [PATCH 517/775] add prunning test --- cmd/conf/init.go | 57 +++++++ cmd/nitro/init.go | 288 +--------------------------------- cmd/nitro/nitro.go | 6 +- cmd/prunning/prunning.go | 250 +++++++++++++++++++++++++++++ go-ethereum | 2 +- system_tests/common_test.go | 4 +- system_tests/prunning_test.go | 121 ++++++++++++++ 7 files changed, 439 insertions(+), 289 deletions(-) create mode 100644 cmd/conf/init.go create mode 100644 cmd/prunning/prunning.go create mode 100644 system_tests/prunning_test.go diff --git a/cmd/conf/init.go b/cmd/conf/init.go new file mode 100644 index 000000000..f228891b9 --- /dev/null +++ b/cmd/conf/init.go @@ -0,0 +1,57 @@ +package conf + +import ( + "time" + + "github.com/spf13/pflag" +) + +type InitConfig struct { + Force bool `koanf:"force"` + Url string `koanf:"url"` + DownloadPath string `koanf:"download-path"` + DownloadPoll time.Duration `koanf:"download-poll"` + DevInit bool `koanf:"dev-init"` + DevInitAddress string `koanf:"dev-init-address"` + DevInitBlockNum uint64 `koanf:"dev-init-blocknum"` + Empty bool `koanf:"empty"` + AccountsPerSync uint `koanf:"accounts-per-sync"` + ImportFile string `koanf:"import-file"` + ThenQuit bool `koanf:"then-quit"` + Prune string `koanf:"prune"` + PruneBloomSize uint64 `koanf:"prune-bloom-size"` + ResetToMessage int64 `koanf:"reset-to-message"` +} + +var InitConfigDefault = InitConfig{ + Force: false, + Url: "", + DownloadPath: "/tmp/", + DownloadPoll: time.Minute, + DevInit: false, + DevInitAddress: "", + DevInitBlockNum: 0, + ImportFile: "", + AccountsPerSync: 100000, + ThenQuit: false, + Prune: "", + PruneBloomSize: 2048, + ResetToMessage: -1, +} + +func InitConfigAddOptions(prefix string, f *pflag.FlagSet) { + f.Bool(prefix+".force", InitConfigDefault.Force, "if true: in case database exists init code will be reexecuted and genesis block compared to database") + f.String(prefix+".url", InitConfigDefault.Url, "url to download initializtion data - will poll if download fails") + f.String(prefix+".download-path", InitConfigDefault.DownloadPath, "path to save temp downloaded file") + f.Duration(prefix+".download-poll", InitConfigDefault.DownloadPoll, "how long to wait between polling attempts") + f.Bool(prefix+".dev-init", InitConfigDefault.DevInit, "init with dev data (1 account with balance) instead of file import") + f.String(prefix+".dev-init-address", InitConfigDefault.DevInitAddress, "Address of dev-account. Leave empty to use the dev-wallet.") + f.Uint64(prefix+".dev-init-blocknum", InitConfigDefault.DevInitBlockNum, "Number of preinit blocks. Must exist in ancient database.") + f.Bool(prefix+".empty", InitConfigDefault.Empty, "init with empty state") + f.Bool(prefix+".then-quit", InitConfigDefault.ThenQuit, "quit after init is done") + f.String(prefix+".import-file", InitConfigDefault.ImportFile, "path for json data to import") + f.Uint(prefix+".accounts-per-sync", InitConfigDefault.AccountsPerSync, "during init - sync database every X accounts. Lower value for low-memory systems. 0 disables.") + f.String(prefix+".prune", InitConfigDefault.Prune, "pruning for a given use: \"full\" for full nodes serving RPC requests, or \"validator\" for validators") + 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.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") +} diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 1427ef161..745e16837 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -10,93 +10,37 @@ import ( "fmt" "math/big" "os" - "reflect" - "regexp" "runtime" "strings" "sync" "time" + "github.com/offchainlabs/nitro/cmd/conf" + "github.com/offchainlabs/nitro/cmd/prunning" "github.com/offchainlabs/nitro/cmd/util" "github.com/cavaliergopher/grab/v3" extract "github.com/codeclysm/extract/v3" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state/pruner" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbos/arbosState" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/cmd/chaininfo" "github.com/offchainlabs/nitro/cmd/ipfshelper" "github.com/offchainlabs/nitro/execution/gethexec" - "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/statetransfer" - "github.com/spf13/pflag" ) -type InitConfig struct { - Force bool `koanf:"force"` - Url string `koanf:"url"` - DownloadPath string `koanf:"download-path"` - DownloadPoll time.Duration `koanf:"download-poll"` - DevInit bool `koanf:"dev-init"` - DevInitAddress string `koanf:"dev-init-address"` - DevInitBlockNum uint64 `koanf:"dev-init-blocknum"` - Empty bool `koanf:"empty"` - AccountsPerSync uint `koanf:"accounts-per-sync"` - ImportFile string `koanf:"import-file"` - ThenQuit bool `koanf:"then-quit"` - Prune string `koanf:"prune"` - PruneBloomSize uint64 `koanf:"prune-bloom-size"` - ResetToMessage int64 `koanf:"reset-to-message"` -} - -var InitConfigDefault = InitConfig{ - Force: false, - Url: "", - DownloadPath: "/tmp/", - DownloadPoll: time.Minute, - DevInit: false, - DevInitAddress: "", - DevInitBlockNum: 0, - ImportFile: "", - AccountsPerSync: 100000, - ThenQuit: false, - Prune: "", - PruneBloomSize: 2048, - ResetToMessage: -1, -} - -func InitConfigAddOptions(prefix string, f *pflag.FlagSet) { - f.Bool(prefix+".force", InitConfigDefault.Force, "if true: in case database exists init code will be reexecuted and genesis block compared to database") - f.String(prefix+".url", InitConfigDefault.Url, "url to download initializtion data - will poll if download fails") - f.String(prefix+".download-path", InitConfigDefault.DownloadPath, "path to save temp downloaded file") - f.Duration(prefix+".download-poll", InitConfigDefault.DownloadPoll, "how long to wait between polling attempts") - f.Bool(prefix+".dev-init", InitConfigDefault.DevInit, "init with dev data (1 account with balance) instead of file import") - f.String(prefix+".dev-init-address", InitConfigDefault.DevInitAddress, "Address of dev-account. Leave empty to use the dev-wallet.") - f.Uint64(prefix+".dev-init-blocknum", InitConfigDefault.DevInitBlockNum, "Number of preinit blocks. Must exist in ancient database.") - f.Bool(prefix+".empty", InitConfigDefault.Empty, "init with empty state") - f.Bool(prefix+".then-quit", InitConfigDefault.ThenQuit, "quit after init is done") - f.String(prefix+".import-file", InitConfigDefault.ImportFile, "path for json data to import") - f.Uint(prefix+".accounts-per-sync", InitConfigDefault.AccountsPerSync, "during init - sync database every X accounts. Lower value for low-memory systems. 0 disables.") - f.String(prefix+".prune", InitConfigDefault.Prune, "pruning for a given use: \"full\" for full nodes serving RPC requests, or \"validator\" for validators") - 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.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") -} - -func downloadInit(ctx context.Context, initConfig *InitConfig) (string, error) { +func downloadInit(ctx context.Context, initConfig *conf.InitConfig) (string, error) { if initConfig.Url == "" { return "", nil } @@ -215,228 +159,6 @@ func validateBlockChain(blockChain *core.BlockChain, chainConfig *params.ChainCo return nil } -type importantRoots struct { - chainDb ethdb.Database - roots []common.Hash - heights []uint64 -} - -// The minimum block distance between two important roots -const minRootDistance = 2000 - -// Marks a header as important, and records its root and height. -// If overwrite is true, it'll remove any future roots and replace them with this header. -// If overwrite is false, it'll ignore this header if it has future roots. -func (r *importantRoots) addHeader(header *types.Header, overwrite bool) error { - targetBlockNum := header.Number.Uint64() - for { - if header == nil || header.Root == (common.Hash{}) { - log.Error("missing state of pruning target", "blockNum", targetBlockNum) - return nil - } - exists, err := r.chainDb.Has(header.Root.Bytes()) - if err != nil { - return err - } - if exists { - break - } - num := header.Number.Uint64() - if num%3000 == 0 { - log.Info("looking for old block with state to keep", "current", num, "target", targetBlockNum) - } - // An underflow is fine here because it'll just return nil due to not found - header = rawdb.ReadHeader(r.chainDb, header.ParentHash, num-1) - } - height := header.Number.Uint64() - for len(r.heights) > 0 && r.heights[len(r.heights)-1] > height { - if !overwrite { - return nil - } - r.roots = r.roots[:len(r.roots)-1] - r.heights = r.heights[:len(r.heights)-1] - } - if len(r.heights) > 0 && r.heights[len(r.heights)-1]+minRootDistance > height { - return nil - } - r.roots = append(r.roots, header.Root) - r.heights = append(r.heights, height) - return nil -} - -var hashListRegex = regexp.MustCompile("^(0x)?[0-9a-fA-F]{64}(,(0x)?[0-9a-fA-F]{64})*$") - -// Finds important roots to retain while proving -func findImportantRoots(ctx context.Context, chainDb ethdb.Database, stack *node.Node, nodeConfig *NodeConfig, cacheConfig *core.CacheConfig, l1Client arbutil.L1Interface, rollupAddrs chaininfo.RollupAddresses) ([]common.Hash, error) { - initConfig := &nodeConfig.Init - chainConfig := gethexec.TryReadStoredChainConfig(chainDb) - if chainConfig == nil { - return nil, errors.New("database doesn't have a chain config (was this node initialized?)") - } - arbDb, err := stack.OpenDatabase("arbitrumdata", 0, 0, "", true) - if err != nil { - return nil, err - } - defer func() { - err := arbDb.Close() - if err != nil { - log.Warn("failed to close arbitrum database after finding pruning targets", "err", err) - } - }() - roots := importantRoots{ - chainDb: chainDb, - } - genesisNum := chainConfig.ArbitrumChainParams.GenesisBlockNum - genesisHash := rawdb.ReadCanonicalHash(chainDb, genesisNum) - genesisHeader := rawdb.ReadHeader(chainDb, genesisHash, genesisNum) - if genesisHeader == nil { - return nil, errors.New("missing L2 genesis block header") - } - err = roots.addHeader(genesisHeader, false) - if err != nil { - return nil, err - } - if initConfig.Prune == "validator" { - if l1Client == nil || reflect.ValueOf(l1Client).IsNil() { - return nil, errors.New("an L1 connection is required for validator pruning") - } - callOpts := bind.CallOpts{ - Context: ctx, - BlockNumber: big.NewInt(int64(rpc.FinalizedBlockNumber)), - } - rollup, err := staker.NewRollupWatcher(rollupAddrs.Rollup, l1Client, callOpts) - if err != nil { - return nil, err - } - latestConfirmedNum, err := rollup.LatestConfirmed(&callOpts) - if err != nil { - return nil, err - } - latestConfirmedNode, err := rollup.LookupNode(ctx, latestConfirmedNum) - if err != nil { - return nil, err - } - confirmedHash := latestConfirmedNode.Assertion.AfterState.GlobalState.BlockHash - confirmedNumber := rawdb.ReadHeaderNumber(chainDb, confirmedHash) - var confirmedHeader *types.Header - if confirmedNumber != nil { - confirmedHeader = rawdb.ReadHeader(chainDb, confirmedHash, *confirmedNumber) - } - if confirmedHeader != nil { - err = roots.addHeader(confirmedHeader, false) - if err != nil { - return nil, err - } - } else { - log.Warn("missing latest confirmed block", "hash", confirmedHash) - } - - validatorDb := rawdb.NewTable(arbDb, storage.BlockValidatorPrefix) - lastValidated, err := staker.ReadLastValidatedInfo(validatorDb) - if err != nil { - return nil, err - } - if lastValidated != nil { - var lastValidatedHeader *types.Header - headerNum := rawdb.ReadHeaderNumber(chainDb, lastValidated.GlobalState.BlockHash) - if headerNum != nil { - lastValidatedHeader = rawdb.ReadHeader(chainDb, lastValidated.GlobalState.BlockHash, *headerNum) - } - if lastValidatedHeader != nil { - err = roots.addHeader(lastValidatedHeader, false) - if err != nil { - return nil, err - } - } else { - log.Warn("missing latest validated block", "hash", lastValidated.GlobalState.BlockHash) - } - } - } else if initConfig.Prune == "full" { - if nodeConfig.Node.ValidatorRequired() { - return nil, errors.New("refusing to prune to full-node level when validator is enabled (you should prune in validator mode)") - } - } else if hashListRegex.MatchString(initConfig.Prune) { - parts := strings.Split(initConfig.Prune, ",") - roots := []common.Hash{genesisHeader.Root} - for _, part := range parts { - root := common.HexToHash(part) - if root == genesisHeader.Root { - // This was already included in the builtin list - continue - } - roots = append(roots, root) - } - return roots, nil - } else { - return nil, fmt.Errorf("unknown pruning mode: \"%v\"", initConfig.Prune) - } - if l1Client != nil { - // Find the latest finalized block and add it as a pruning target - l1Block, err := l1Client.BlockByNumber(ctx, big.NewInt(int64(rpc.FinalizedBlockNumber))) - if err != nil { - return nil, fmt.Errorf("failed to get finalized block: %w", err) - } - l1BlockNum := l1Block.NumberU64() - tracker, err := arbnode.NewInboxTracker(arbDb, nil, nil) - if err != nil { - return nil, err - } - batch, err := tracker.GetBatchCount() - if err != nil { - return nil, err - } - for { - if ctx.Err() != nil { - return nil, ctx.Err() - } - if batch == 0 { - // No batch has been finalized - break - } - batch -= 1 - meta, err := tracker.GetBatchMetadata(batch) - if err != nil { - return nil, err - } - if meta.ParentChainBlock <= l1BlockNum { - signedBlockNum := arbutil.MessageCountToBlockNumber(meta.MessageCount, genesisNum) - blockNum := uint64(signedBlockNum) - l2Hash := rawdb.ReadCanonicalHash(chainDb, blockNum) - l2Header := rawdb.ReadHeader(chainDb, l2Hash, blockNum) - if l2Header == nil { - log.Warn("latest finalized L2 block is unknown", "blockNum", signedBlockNum) - break - } - err = roots.addHeader(l2Header, false) - if err != nil { - return nil, err - } - break - } - } - } - roots.roots = append(roots.roots, common.Hash{}) // the latest snapshot - log.Info("found pruning target blocks", "heights", roots.heights, "roots", roots.roots) - return roots.roots, nil -} - -func pruneChainDb(ctx context.Context, chainDb ethdb.Database, stack *node.Node, nodeConfig *NodeConfig, cacheConfig *core.CacheConfig, l1Client arbutil.L1Interface, rollupAddrs chaininfo.RollupAddresses) error { - config := &nodeConfig.Init - if config.Prune == "" { - return pruner.RecoverPruning(stack.InstanceDir(), chainDb) - } - root, err := findImportantRoots(ctx, chainDb, stack, nodeConfig, cacheConfig, l1Client, rollupAddrs) - if err != nil { - return fmt.Errorf("failed to find root to retain for pruning: %w", err) - } - - pruner, err := pruner.NewPruner(chainDb, pruner.Config{Datadir: stack.InstanceDir(), BloomSize: config.PruneBloomSize}) - if err != nil { - return err - } - return pruner.Prune(root) -} - func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeConfig, chainId *big.Int, cacheConfig *core.CacheConfig, l1Client arbutil.L1Interface, rollupAddrs chaininfo.RollupAddresses) (ethdb.Database, *core.BlockChain, error) { if !config.Init.Force { if readOnlyDb, err := stack.OpenDatabaseWithFreezer("l2chaindata", 0, 0, "", "", true); err == nil { @@ -446,7 +168,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if err != nil { return chainDb, nil, err } - err = pruneChainDb(ctx, chainDb, stack, config, cacheConfig, l1Client, rollupAddrs) + err = prunning.PruneChainDb(ctx, chainDb, stack, &config.Init, cacheConfig, l1Client, rollupAddrs, config.Node.ValidatorRequired()) if err != nil { return chainDb, nil, fmt.Errorf("error pruning: %w", err) } @@ -642,7 +364,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo return chainDb, l2BlockChain, err } - err = pruneChainDb(ctx, chainDb, stack, config, cacheConfig, l1Client, rollupAddrs) + err = prunning.PruneChainDb(ctx, chainDb, stack, &config.Init, cacheConfig, l1Client, rollupAddrs, config.Node.ValidatorRequired()) if err != nil { return chainDb, nil, fmt.Errorf("error pruning: %w", err) } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 86093a85d..ca0d3496f 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -677,7 +677,7 @@ type NodeConfig struct { MetricsServer genericconf.MetricsServerConfig `koanf:"metrics-server"` PProf bool `koanf:"pprof"` PprofCfg genericconf.PProf `koanf:"pprof-cfg"` - Init InitConfig `koanf:"init"` + Init conf.InitConfig `koanf:"init"` Rpc genericconf.RpcConfig `koanf:"rpc"` } @@ -699,7 +699,7 @@ var NodeConfigDefault = NodeConfig{ GraphQL: genericconf.GraphQLConfigDefault, Metrics: false, MetricsServer: genericconf.MetricsServerConfigDefault, - Init: InitConfigDefault, + Init: conf.InitConfigDefault, Rpc: genericconf.DefaultRpcConfig, PProf: false, PprofCfg: genericconf.PProfDefault, @@ -726,7 +726,7 @@ func NodeConfigAddOptions(f *flag.FlagSet) { f.Bool("pprof", NodeConfigDefault.PProf, "enable pprof") genericconf.PProfAddOptions("pprof-cfg", f) - InitConfigAddOptions("init", f) + conf.InitConfigAddOptions("init", f) genericconf.RpcConfigAddOptions("rpc", f) } diff --git a/cmd/prunning/prunning.go b/cmd/prunning/prunning.go new file mode 100644 index 000000000..7538c68a1 --- /dev/null +++ b/cmd/prunning/prunning.go @@ -0,0 +1,250 @@ +package prunning + +import ( + "context" + "errors" + "fmt" + "math/big" + "reflect" + "regexp" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state/pruner" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/rpc" + "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/arbnode/dataposter/storage" + "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/cmd/chaininfo" + "github.com/offchainlabs/nitro/cmd/conf" + "github.com/offchainlabs/nitro/execution/gethexec" + "github.com/offchainlabs/nitro/staker" +) + +type importantRoots struct { + chainDb ethdb.Database + roots []common.Hash + heights []uint64 +} + +// The minimum block distance between two important roots +const minRootDistance = 2000 + +// Marks a header as important, and records its root and height. +// If overwrite is true, it'll remove any future roots and replace them with this header. +// If overwrite is false, it'll ignore this header if it has future roots. +func (r *importantRoots) addHeader(header *types.Header, overwrite bool) error { + targetBlockNum := header.Number.Uint64() + for { + if header == nil || header.Root == (common.Hash{}) { + log.Error("missing state of pruning target", "blockNum", targetBlockNum) + return nil + } + exists, err := r.chainDb.Has(header.Root.Bytes()) + if err != nil { + return err + } + if exists { + break + } + num := header.Number.Uint64() + if num%3000 == 0 { + log.Info("looking for old block with state to keep", "current", num, "target", targetBlockNum) + } + // An underflow is fine here because it'll just return nil due to not found + header = rawdb.ReadHeader(r.chainDb, header.ParentHash, num-1) + } + height := header.Number.Uint64() + for len(r.heights) > 0 && r.heights[len(r.heights)-1] > height { + if !overwrite { + return nil + } + r.roots = r.roots[:len(r.roots)-1] + r.heights = r.heights[:len(r.heights)-1] + } + if len(r.heights) > 0 && r.heights[len(r.heights)-1]+minRootDistance > height { + return nil + } + r.roots = append(r.roots, header.Root) + r.heights = append(r.heights, height) + return nil +} + +var hashListRegex = regexp.MustCompile("^(0x)?[0-9a-fA-F]{64}(,(0x)?[0-9a-fA-F]{64})*$") + +// Finds important roots to retain while proving +func findImportantRoots(ctx context.Context, chainDb ethdb.Database, stack *node.Node, initConfig *conf.InitConfig, cacheConfig *core.CacheConfig, l1Client arbutil.L1Interface, rollupAddrs chaininfo.RollupAddresses, validatorRequired bool) ([]common.Hash, error) { + chainConfig := gethexec.TryReadStoredChainConfig(chainDb) + if chainConfig == nil { + return nil, errors.New("database doesn't have a chain config (was this node initialized?)") + } + arbDb, err := stack.OpenDatabase("arbitrumdata", 0, 0, "", true) + if err != nil { + return nil, err + } + defer func() { + err := arbDb.Close() + if err != nil { + log.Warn("failed to close arbitrum database after finding pruning targets", "err", err) + } + }() + roots := importantRoots{ + chainDb: chainDb, + } + genesisNum := chainConfig.ArbitrumChainParams.GenesisBlockNum + genesisHash := rawdb.ReadCanonicalHash(chainDb, genesisNum) + genesisHeader := rawdb.ReadHeader(chainDb, genesisHash, genesisNum) + log.Warn("XXX", "genesisNum", genesisNum, "genesisHash", genesisHash) + if genesisHeader == nil { + return nil, errors.New("missing L2 genesis block header") + } + err = roots.addHeader(genesisHeader, false) + if err != nil { + return nil, err + } + if initConfig.Prune == "validator" { + if l1Client == nil || reflect.ValueOf(l1Client).IsNil() { + return nil, errors.New("an L1 connection is required for validator pruning") + } + callOpts := bind.CallOpts{ + Context: ctx, + BlockNumber: big.NewInt(int64(rpc.FinalizedBlockNumber)), + } + rollup, err := staker.NewRollupWatcher(rollupAddrs.Rollup, l1Client, callOpts) + if err != nil { + return nil, err + } + latestConfirmedNum, err := rollup.LatestConfirmed(&callOpts) + if err != nil { + return nil, err + } + latestConfirmedNode, err := rollup.LookupNode(ctx, latestConfirmedNum) + if err != nil { + return nil, err + } + confirmedHash := latestConfirmedNode.Assertion.AfterState.GlobalState.BlockHash + confirmedNumber := rawdb.ReadHeaderNumber(chainDb, confirmedHash) + var confirmedHeader *types.Header + if confirmedNumber != nil { + confirmedHeader = rawdb.ReadHeader(chainDb, confirmedHash, *confirmedNumber) + } + if confirmedHeader != nil { + err = roots.addHeader(confirmedHeader, false) + if err != nil { + return nil, err + } + } else { + log.Warn("missing latest confirmed block", "hash", confirmedHash) + } + + validatorDb := rawdb.NewTable(arbDb, storage.BlockValidatorPrefix) + lastValidated, err := staker.ReadLastValidatedInfo(validatorDb) + if err != nil { + return nil, err + } + if lastValidated != nil { + var lastValidatedHeader *types.Header + headerNum := rawdb.ReadHeaderNumber(chainDb, lastValidated.GlobalState.BlockHash) + if headerNum != nil { + lastValidatedHeader = rawdb.ReadHeader(chainDb, lastValidated.GlobalState.BlockHash, *headerNum) + } + if lastValidatedHeader != nil { + err = roots.addHeader(lastValidatedHeader, false) + if err != nil { + return nil, err + } + } else { + log.Warn("missing latest validated block", "hash", lastValidated.GlobalState.BlockHash) + } + } + } else if initConfig.Prune == "full" { + if validatorRequired { + return nil, errors.New("refusing to prune to full-node level when validator is enabled (you should prune in validator mode)") + } + } else if hashListRegex.MatchString(initConfig.Prune) { + parts := strings.Split(initConfig.Prune, ",") + roots := []common.Hash{genesisHeader.Root} + for _, part := range parts { + root := common.HexToHash(part) + if root == genesisHeader.Root { + // This was already included in the builtin list + continue + } + roots = append(roots, root) + } + return roots, nil + } else { + return nil, fmt.Errorf("unknown pruning mode: \"%v\"", initConfig.Prune) + } + if l1Client != nil { + // Find the latest finalized block and add it as a pruning target + l1Block, err := l1Client.BlockByNumber(ctx, big.NewInt(int64(rpc.FinalizedBlockNumber))) + if err != nil { + return nil, fmt.Errorf("failed to get finalized block: %w", err) + } + l1BlockNum := l1Block.NumberU64() + tracker, err := arbnode.NewInboxTracker(arbDb, nil, nil) + if err != nil { + return nil, err + } + batch, err := tracker.GetBatchCount() + if err != nil { + return nil, err + } + for { + if ctx.Err() != nil { + return nil, ctx.Err() + } + if batch == 0 { + // No batch has been finalized + break + } + batch -= 1 + meta, err := tracker.GetBatchMetadata(batch) + if err != nil { + return nil, err + } + if meta.ParentChainBlock <= l1BlockNum { + signedBlockNum := arbutil.MessageCountToBlockNumber(meta.MessageCount, genesisNum) + blockNum := uint64(signedBlockNum) + l2Hash := rawdb.ReadCanonicalHash(chainDb, blockNum) + l2Header := rawdb.ReadHeader(chainDb, l2Hash, blockNum) + if l2Header == nil { + log.Warn("latest finalized L2 block is unknown", "blockNum", signedBlockNum) + break + } + err = roots.addHeader(l2Header, false) + if err != nil { + return nil, err + } + break + } + } + } + roots.roots = append(roots.roots, common.Hash{}) // the latest snapshot + log.Info("found pruning target blocks", "heights", roots.heights, "roots", roots.roots) + return roots.roots, nil +} + +func PruneChainDb(ctx context.Context, chainDb ethdb.Database, stack *node.Node, initConfig *conf.InitConfig, cacheConfig *core.CacheConfig, l1Client arbutil.L1Interface, rollupAddrs chaininfo.RollupAddresses, validatorRequired bool) error { + if initConfig.Prune == "" { + return pruner.RecoverPruning(stack.InstanceDir(), chainDb) + } + root, err := findImportantRoots(ctx, chainDb, stack, initConfig, cacheConfig, l1Client, rollupAddrs, validatorRequired) + if err != nil { + return fmt.Errorf("failed to find root to retain for pruning: %w", err) + } + + pruner, err := pruner.NewPruner(chainDb, pruner.Config{Datadir: stack.InstanceDir(), BloomSize: initConfig.PruneBloomSize}) + if err != nil { + return err + } + return pruner.Prune(root) +} diff --git a/go-ethereum b/go-ethereum index b1622e6ac..1e2855b24 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit b1622e6ac4bf3762aebde92a585de2889d90823f +Subproject commit 1e2855b24d6555c8cfaf471bd9e2c3d19ab5c32c diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 7752fbd34..937b8980f 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -698,7 +698,7 @@ func createL2BlockChainWithStackConfig( chainDb, err := stack.OpenDatabase("chaindb", 0, 0, "", false) Require(t, err) - arbDb, err := stack.OpenDatabase("arbdb", 0, 0, "", false) + arbDb, err := stack.OpenDatabase("arbitrumdata", 0, 0, "", false) Require(t, err) initReader := statetransfer.NewMemoryInitDataReader(&l2info.ArbInitData) @@ -903,7 +903,7 @@ func Create2ndNodeWithConfig( l2chainDb, err := l2stack.OpenDatabase("chaindb", 0, 0, "", false) Require(t, err) - l2arbDb, err := l2stack.OpenDatabase("arbdb", 0, 0, "", false) + l2arbDb, err := l2stack.OpenDatabase("arbitrumdata", 0, 0, "", false) Require(t, err) initReader := statetransfer.NewMemoryInitDataReader(l2InitData) diff --git a/system_tests/prunning_test.go b/system_tests/prunning_test.go new file mode 100644 index 000000000..aadf3c5e9 --- /dev/null +++ b/system_tests/prunning_test.go @@ -0,0 +1,121 @@ +package arbtest + +import ( + "context" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/node" + "github.com/offchainlabs/nitro/cmd/conf" + "github.com/offchainlabs/nitro/cmd/prunning" + "github.com/offchainlabs/nitro/execution/gethexec" + "github.com/offchainlabs/nitro/util/testhelpers" +) + +func countDbEntries(db ethdb.Iteratee) int { + entries := 0 + it := db.NewIterator(nil, nil) + for it.Next() { + entries++ + } + it.Release() + return entries +} + +func TestPrunning(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + var dataDir string + + func() { + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + _ = builder.Build(t) + dataDir = builder.dataDir + l2cleanupDone := false + defer func() { + if !l2cleanupDone { + builder.L2.cleanup() + } + builder.L1.cleanup() + }() + builder.L2Info.GenerateAccount("User2") + var txs []*types.Transaction + for i := uint64(0); i < 1000; i++ { + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) + txs = append(txs, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) + Require(t, err) + } + for _, tx := range txs { + _, err := builder.L2.EnsureTxSucceeded(tx) + Require(t, err) + } + l2cleanupDone = true + builder.L2.cleanup() + t.Log("stopped l2 node") + + stack, err := node.New(builder.l2StackConfig) + Require(t, err) + defer stack.Close() + chainDb, err := stack.OpenDatabase("chaindb", 0, 0, "", false) + Require(t, err) + defer chainDb.Close() + entriesBeforePrunning := countDbEntries(chainDb) + + prand := testhelpers.NewPseudoRandomDataSource(t, 1) + var testKeys [][]byte + for i := 0; i < 100; i++ { + // generate test keys with length of hash to emulate legacy state trie nodes + testKeys = append(testKeys, prand.GetHash().Bytes()) + } + for _, key := range testKeys { + err = chainDb.Put(key, common.FromHex("0xdeadbeef")) + Require(t, err) + } + for _, key := range testKeys { + if has, _ := chainDb.Has(key); !has { + Fatal(t, "internal test error - failed to check existence of test key") + } + } + + initConfig := conf.InitConfigDefault + initConfig.Prune = "full" + coreCacheConfig := gethexec.DefaultCacheConfigFor(stack, &builder.execConfig.Caching) + err = prunning.PruneChainDb(ctx, chainDb, stack, &initConfig, coreCacheConfig, builder.L1.Client, *builder.L2.ConsensusNode.DeployInfo, false) + Require(t, err) + + for _, key := range testKeys { + if has, _ := chainDb.Has(key); has { + Fatal(t, "test key hasn't been prunned as expected") + } + } + + entriesAfterPrunning := countDbEntries(chainDb) + t.Log("db entries pre-prunning:", entriesBeforePrunning) + t.Log("db entries post-prunning:", entriesAfterPrunning) + + if entriesAfterPrunning >= entriesBeforePrunning { + Fatal(t, "The db doesn't have less entires after prunning then before. Before:", entriesBeforePrunning, "After:", entriesAfterPrunning) + } + }() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.dataDir = dataDir + cancel = builder.Build(t) + defer cancel() + + builder.L2Info.GenerateAccount("User2") + var txs []*types.Transaction + for i := uint64(0); i < 10; i++ { + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) + txs = append(txs, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) + Require(t, err) + } + for _, tx := range txs { + _, err := builder.L2.EnsureTxSucceeded(tx) + Require(t, err) + } +} From 875c558d9b0350d0d1923a1a7028a95c6107940d Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 15 Dec 2023 15:29:08 +0000 Subject: [PATCH 518/775] add missing default value of InitConfig.Empty --- cmd/conf/init.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/conf/init.go b/cmd/conf/init.go index f228891b9..bebf1955b 100644 --- a/cmd/conf/init.go +++ b/cmd/conf/init.go @@ -31,6 +31,7 @@ var InitConfigDefault = InitConfig{ DevInit: false, DevInitAddress: "", DevInitBlockNum: 0, + Empty: false, ImportFile: "", AccountsPerSync: 100000, ThenQuit: false, From efe6f059557baa9b9377cd52bdb736a80d5db34d Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Fri, 15 Dec 2023 21:09:40 +0530 Subject: [PATCH 519/775] Add loglevel for ephemeral errors, make data poster nonce ahead of on-chain error an ephemeral error --- arbnode/batch_poster.go | 48 ++++++++++++++++++++--------------------- staker/staker.go | 9 ++++++-- util/log.go | 42 ++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 util/log.go diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 7a4cfc21c..513f57364 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -37,6 +37,7 @@ import ( "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/das" "github.com/offchainlabs/nitro/solgen/go/bridgegen" + "github.com/offchainlabs/nitro/util" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/redisutil" @@ -57,22 +58,22 @@ type batchPosterPosition struct { type BatchPoster struct { stopwaiter.StopWaiter - l1Reader *headerreader.HeaderReader - inbox *InboxTracker - streamer *TransactionStreamer - config BatchPosterConfigFetcher - seqInbox *bridgegen.SequencerInbox - bridge *bridgegen.Bridge - syncMonitor *SyncMonitor - seqInboxABI *abi.ABI - seqInboxAddr common.Address - bridgeAddr common.Address - gasRefunderAddr common.Address - building *buildingBatch - daWriter das.DataAvailabilityServiceWriter - dataPoster *dataposter.DataPoster - redisLock *redislock.Simple - firstEphemeralError time.Time // first time a continuous error suspected to be ephemeral occurred + l1Reader *headerreader.HeaderReader + inbox *InboxTracker + streamer *TransactionStreamer + config BatchPosterConfigFetcher + seqInbox *bridgegen.SequencerInbox + bridge *bridgegen.Bridge + syncMonitor *SyncMonitor + seqInboxABI *abi.ABI + seqInboxAddr common.Address + bridgeAddr common.Address + gasRefunderAddr common.Address + building *buildingBatch + daWriter das.DataAvailabilityServiceWriter + dataPoster *dataposter.DataPoster + redisLock *redislock.Simple + // An estimate of the number of batches we want to post but haven't yet. // This doesn't include batches which we don't want to post yet due to the L1 bounds. backlog uint64 @@ -1103,6 +1104,8 @@ func (b *BatchPoster) Start(ctxIn context.Context) { b.redisLock.Start(ctxIn) b.StopWaiter.Start(ctxIn, b) b.LaunchThread(b.pollForReverts) + commonEphemeralError := time.Time{} + exceedMaxMempoolSizeEphemeralError := time.Time{} b.CallIteratively(func(ctx context.Context) time.Duration { var err error if common.HexToAddress(b.config().GasRefunderAddress) != (common.Address{}) { @@ -1127,21 +1130,16 @@ func (b *BatchPoster) Start(ctxIn context.Context) { } posted, err := b.maybePostSequencerBatch(ctx) if err == nil { - b.firstEphemeralError = time.Time{} + commonEphemeralError = time.Time{} + exceedMaxMempoolSizeEphemeralError = time.Time{} } if err != nil { b.building = nil logLevel := log.Error // Likely the inbox tracker just isn't caught up. // Let's see if this error disappears naturally. - if b.firstEphemeralError == (time.Time{}) { - b.firstEphemeralError = time.Now() - logLevel = log.Warn - } else if time.Since(b.firstEphemeralError) < time.Minute { - logLevel = log.Warn - } else if time.Since(b.firstEphemeralError) < time.Minute*5 && strings.Contains(err.Error(), "will exceed max mempool size") { - logLevel = log.Warn - } + logLevel = util.LogLevelEphemeralError(err, "", time.Minute, &commonEphemeralError, logLevel) + logLevel = util.LogLevelEphemeralError(err, "will exceed max mempool size", 5*time.Minute, &exceedMaxMempoolSizeEphemeralError, logLevel) logLevel("error posting batch", "err", err) return b.config().ErrorDelay } else if posted { diff --git a/staker/staker.go b/staker/staker.go index 4f35c1bc9..522f5e0c5 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -25,6 +25,7 @@ import ( "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/staker/txbuilder" + "github.com/offchainlabs/nitro/util" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/stopwaiter" @@ -406,6 +407,7 @@ func (s *Staker) Start(ctxIn context.Context) { } s.StopWaiter.Start(ctxIn, s) backoff := time.Second + ephemeralError := time.Time{} s.CallIteratively(func(ctx context.Context) (returningWait time.Duration) { defer func() { panicErr := recover() @@ -438,6 +440,7 @@ func (s *Staker) Start(ctxIn context.Context) { } } if err == nil { + ephemeralError = time.Time{} backoff = time.Second stakerLastSuccessfulActionGauge.Update(time.Now().Unix()) stakerActionSuccessCounter.Inc(1) @@ -449,12 +452,14 @@ func (s *Staker) Start(ctxIn context.Context) { } stakerActionFailureCounter.Inc(1) backoff *= 2 + logLevel := log.Error if backoff > time.Minute { backoff = time.Minute - log.Error("error acting as staker", "err", err) } else { - log.Warn("error acting as staker", "err", err) + logLevel = log.Warn } + logLevel = util.LogLevelEphemeralError(err, "is ahead of on-chain nonce", 10*time.Minute, &ephemeralError, logLevel) + logLevel("error acting as staker", "err", err) return backoff }) s.CallIteratively(func(ctx context.Context) time.Duration { diff --git a/util/log.go b/util/log.go new file mode 100644 index 000000000..4e0453638 --- /dev/null +++ b/util/log.go @@ -0,0 +1,42 @@ +package util + +import ( + "strings" + "time" + + "github.com/ethereum/go-ethereum/log" +) + +// LogLevelEphemeralError is a convenient intermediary level between log levels Warn and Error +// +// For a given error, errorSubstring, duration, firstOccuranceTime and logLevel +// the function defaults to returning the given logLevel if the error doesnt contain the errorSubstring, +// but if it does, then returns one of the corresponding loglevels as follows +// - Warn: For firstOccuranceTime of error being less than the duration amount of time from Now +// - Error: Otherwise +// +// # Usage Examples +// +// log.LogLevelEphemeralError(err, "not supported yet", 5*time.Minute, &firstEphemeralError, log.Error)("msg") +// log.LogLevelEphemeralError(err, "not supported yet", 5*time.Minute, &firstEphemeralError, log.Error)("msg", "key1", val1) +// log.LogLevelEphemeralError(err, "not supported yet", 5*time.Minute, &firstEphemeralError, log.Error)("msg", "key1", val1, "key2", val2) +func LogLevelEphemeralError( + err error, + errorSubstring string, + ephemeralDuration time.Duration, + firstOccuranceTime *time.Time, + currentLogLevel func(msg string, ctx ...interface{})) func(string, ...interface{}) { + if strings.Contains(err.Error(), errorSubstring) || errorSubstring == "" { + logLevel := log.Error + if *firstOccuranceTime == (time.Time{}) { + *firstOccuranceTime = time.Now() + logLevel = log.Warn + } else if time.Since(*firstOccuranceTime) < ephemeralDuration { + logLevel = log.Warn + } + return logLevel + } else { + *firstOccuranceTime = time.Time{} + return currentLogLevel + } +} From ae5c2f28227b7e9ea9353a8ae9c581232bca5aa7 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 15 Dec 2023 15:43:18 +0000 Subject: [PATCH 520/775] cleanup imports --- cmd/nitro/init.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 745e16837..00012ac62 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -15,10 +15,6 @@ import ( "sync" "time" - "github.com/offchainlabs/nitro/cmd/conf" - "github.com/offchainlabs/nitro/cmd/prunning" - "github.com/offchainlabs/nitro/cmd/util" - "github.com/cavaliergopher/grab/v3" extract "github.com/codeclysm/extract/v3" "github.com/ethereum/go-ethereum/common" @@ -35,7 +31,10 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/cmd/chaininfo" + "github.com/offchainlabs/nitro/cmd/conf" "github.com/offchainlabs/nitro/cmd/ipfshelper" + "github.com/offchainlabs/nitro/cmd/prunning" + "github.com/offchainlabs/nitro/cmd/util" "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/statetransfer" ) From e64474fce3ed04f0769a06ba6c18e3b072b187d4 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 15 Dec 2023 12:18:57 -0700 Subject: [PATCH 521/775] Add back in metric for latest confirmed sequence number --- broadcaster/backlog/backlog.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index a1bd2c302..448bb79b1 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -7,6 +7,7 @@ import ( "sync/atomic" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" m "github.com/offchainlabs/nitro/broadcaster/message" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/containers" @@ -16,6 +17,8 @@ var ( errDropSegments = errors.New("remove previous segments from backlog") errSequenceNumberSeen = errors.New("sequence number already present in backlog") errOutOfBounds = errors.New("message not found in backlog") + + confirmedSequenceNumberGauge = metrics.NewRegisteredGauge("arb/sequencenumber/confirmed", nil) ) // Backlog defines the interface for backlog. @@ -162,6 +165,8 @@ func (b *backlog) delete(confirmed uint64) { return } + confirmedSequenceNumberGauge.Update(int64(confirmed)) + // find the segment containing the confirmed message found, err := b.Lookup(confirmed) if err != nil { From 52f5b7dce22716555361a3faabfb37b51279e060 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 15 Dec 2023 12:26:16 -0700 Subject: [PATCH 522/775] Increase default data poster MaxMempoolTransactions --- arbnode/dataposter/data_poster.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index d8373c4b0..042a5487d 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -898,7 +898,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ WaitForL1Finality: true, TargetPriceGwei: 60., UrgencyGwei: 2., - MaxMempoolTransactions: 10, + MaxMempoolTransactions: 20, MinTipCapGwei: 0.05, MaxTipCapGwei: 5, NonceRbfSoftConfs: 1, @@ -925,7 +925,7 @@ var TestDataPosterConfig = DataPosterConfig{ WaitForL1Finality: false, TargetPriceGwei: 60., UrgencyGwei: 2., - MaxMempoolTransactions: 10, + MaxMempoolTransactions: 20, MinTipCapGwei: 0.05, MaxTipCapGwei: 5, NonceRbfSoftConfs: 1, From ac196ecab4c2af008fc41d28cbf224796e07dc21 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 15 Dec 2023 14:36:14 -0700 Subject: [PATCH 523/775] Disable feed output compression by default --- wsbroadcastserver/wsbroadcastserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsbroadcastserver/wsbroadcastserver.go b/wsbroadcastserver/wsbroadcastserver.go index eb47f8a63..ee21cbaae 100644 --- a/wsbroadcastserver/wsbroadcastserver.go +++ b/wsbroadcastserver/wsbroadcastserver.go @@ -123,7 +123,7 @@ var DefaultBroadcasterConfig = BroadcasterConfig{ DisableSigning: true, LogConnect: false, LogDisconnect: false, - EnableCompression: true, + EnableCompression: false, RequireCompression: false, LimitCatchup: false, MaxCatchup: -1, From ba66b82c3272ed5fba7151547c6c601b47a16bcc Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 15 Dec 2023 15:24:59 -0700 Subject: [PATCH 524/775] Ensure sequencer backlog is populated before any clients connect --- arbnode/node.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index f2ed2941f..8be2a982c 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -773,9 +773,9 @@ func (n *Node) Start(ctx context.Context) error { return fmt.Errorf("error initializing feed broadcast server: %w", err) } } - if n.InboxTracker != nil && n.BroadcastServer != nil && config.Sequencer && !config.SeqCoordinator.Enable { - // Normally, the sequencer would populate the feed backlog when it acquires the lockout. - // However, if the sequencer coordinator is not enabled, we must populate the backlog on startup. + if n.InboxTracker != nil && n.BroadcastServer != nil && config.Sequencer { + // Even if the sequencer coordinator will populate this backlog, + // we want to make sure it's populated before any clients connect. err = n.InboxTracker.PopulateFeedBacklog(n.BroadcastServer) if err != nil { return fmt.Errorf("error populating feed backlog on startup: %w", err) From f76ba8e8aca952fc7f4dba597c904410f699d8ce Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 15 Dec 2023 16:10:07 -0700 Subject: [PATCH 525/775] Ensure confirmed sequence number metric is populated --- broadcaster/backlog/backlog.go | 1 + 1 file changed, 1 insertion(+) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 448bb79b1..851561f48 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -69,6 +69,7 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { segment = newBacklogSegment() b.head.Store(segment) b.tail.Store(segment) + confirmedSequenceNumberGauge.Update(int64(msg.SequenceNumber)) } prevMsgIdx := segment.End() From 21b8a20a24c3719dca561997b55aad13a62ca265 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 15 Dec 2023 16:20:21 -0700 Subject: [PATCH 526/775] Recognize batch poster backlog from the data poster --- arbnode/batch_poster.go | 19 +++++++++++++------ arbnode/dataposter/data_poster.go | 13 +++++++++++-- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 7a4cfc21c..5d61bc5f1 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -73,6 +73,7 @@ type BatchPoster struct { dataPoster *dataposter.DataPoster redisLock *redislock.Simple firstEphemeralError time.Time // first time a continuous error suspected to be ephemeral occurred + // This is an atomic variable that should only be accessed atomically. // An estimate of the number of batches we want to post but haven't yet. // This doesn't include batches which we don't want to post yet due to the L1 bounds. backlog uint64 @@ -283,6 +284,7 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e RedisLock: redisLock, Config: dataPosterConfigFetcher, MetadataRetriever: b.getBatchPosterPosition, + ExtraBacklog: b.GetBacklogEstimate, RedisKey: "data-poster.queue", }) if err != nil { @@ -846,7 +848,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) if b.building == nil || b.building.startMsgCount != batchPosition.MessageCount { b.building = &buildingBatch{ - segments: newBatchSegments(batchPosition.DelayedMessageCount, b.config(), b.backlog), + segments: newBatchSegments(batchPosition.DelayedMessageCount, b.config(), b.GetBacklogEstimate()), msgCount: batchPosition.MessageCount, startMsgCount: batchPosition.MessageCount, } @@ -1061,12 +1063,12 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) recentlyHitL1Bounds := time.Since(b.lastHitL1Bounds) < config.PollInterval*3 postedMessages := b.building.msgCount - batchPosition.MessageCount unpostedMessages := msgCount - b.building.msgCount - b.backlog = uint64(unpostedMessages) / uint64(postedMessages) - if b.backlog > 10 { + backlog := uint64(unpostedMessages) / uint64(postedMessages) + if backlog > 10 { logLevel := log.Warn if recentlyHitL1Bounds { logLevel = log.Info - } else if b.backlog > 30 { + } else if backlog > 30 { logLevel = log.Error } logLevel( @@ -1076,14 +1078,15 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) "messageCount", msgCount, "lastPostedMessages", postedMessages, "unpostedMessages", unpostedMessages, - "batchBacklogEstimate", b.backlog, + "batchBacklogEstimate", backlog, ) } if recentlyHitL1Bounds { // This backlog isn't "real" in that we don't want to post any more messages. // Setting the backlog to 0 here ensures that we don't lower compression as a result. - b.backlog = 0 + backlog = 0 } + atomic.StoreUint64(&b.backlog, backlog) b.building = nil // If we aren't queueing up transactions, wait for the receipt before moving on to the next batch. @@ -1098,6 +1101,10 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) return true, nil } +func (b *BatchPoster) GetBacklogEstimate() uint64 { + return atomic.LoadUint64(&b.backlog) +} + func (b *BatchPoster) Start(ctxIn context.Context) { b.dataPoster.Start(ctxIn) b.redisLock.Start(ctxIn) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index d8373c4b0..10d148371 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -62,6 +62,7 @@ type DataPoster struct { usingNoOpStorage bool replacementTimes []time.Duration metadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error) + extraBacklog func() uint64 // These fields are protected by the mutex. // TODO: factor out these fields into separate structure, since now one @@ -116,6 +117,7 @@ type DataPosterOpts struct { RedisLock AttemptLocker Config ConfigFetcher MetadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error) + ExtraBacklog func() uint64 RedisKey string // Redis storage key } @@ -176,6 +178,10 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro redisLock: opts.RedisLock, errorCount: make(map[uint64]int), maxFeeCapExpression: expression, + extraBacklog: opts.ExtraBacklog, + } + if dp.extraBacklog == nil { + dp.extraBacklog = func() uint64 { return 0 } } if cfg.ExternalSigner.URL != "" { signer, sender, err := externalSigner(ctx, &cfg.ExternalSigner) @@ -371,6 +377,7 @@ func (p *DataPoster) GetNextNonceAndMeta(ctx context.Context) (uint64, []byte, e const minRbfIncrease = arbmath.OneInBips * 11 / 10 // evalMaxFeeCapExpr uses MaxFeeCapFormula from config to calculate the expression's result by plugging in appropriate parameter values +// backlogOfBatches should already include extraBacklog func (p *DataPoster) evalMaxFeeCapExpr(backlogOfBatches uint64, elapsed time.Duration) (*big.Int, error) { config := p.config() parameters := map[string]any{ @@ -403,8 +410,10 @@ func (p *DataPoster) evalMaxFeeCapExpr(backlogOfBatches uint64, elapsed time.Dur return resultBig, nil } -func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit uint64, lastFeeCap *big.Int, lastTipCap *big.Int, dataCreatedAt time.Time, backlogOfBatches uint64) (*big.Int, *big.Int, error) { +// The dataPosterBacklog argument should *not* include extraBacklog (it's added in in this function) +func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit uint64, lastFeeCap *big.Int, lastTipCap *big.Int, dataCreatedAt time.Time, dataPosterBacklog uint64) (*big.Int, *big.Int, error) { config := p.config() + dataPosterBacklog += p.extraBacklog() latestHeader, err := p.headerReader.LastHeader(ctx) if err != nil { return nil, nil, err @@ -442,7 +451,7 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u } elapsed := time.Since(dataCreatedAt) - maxFeeCap, err := p.evalMaxFeeCapExpr(backlogOfBatches, elapsed) + maxFeeCap, err := p.evalMaxFeeCapExpr(dataPosterBacklog, elapsed) if err != nil { return nil, nil, err } From e4243568c57444c60f01c08da3dfa839e56773e7 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 15 Dec 2023 22:54:55 -0700 Subject: [PATCH 527/775] Speed up the inbox reader for L3 chains --- cmd/nitro/nitro.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 3efba5df2..b850b9898 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -925,9 +925,12 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c safeBatchSize := l2MaxTxSize - bufferSpace chainDefaults["node.batch-poster.max-size"] = safeBatchSize chainDefaults["execution.sequencer.max-tx-data-size"] = safeBatchSize - bufferSpace + // Arbitrum chains produce blocks more quickly, so the inbox reader should read more blocks at once. + // Even if this is too large, on error the inbox reader will reset its query size down to the default. + chainDefaults["node.inbox-reader.max-blocks-to-read"] = 10_000 } if chainInfo.DasIndexUrl != "" { - chainDefaults["node.batch-poster.max-size"] = 1000000 + chainDefaults["node.batch-poster.max-size"] = 1_000_000 } err = k.Load(confmap.Provider(chainDefaults, "."), nil) if err != nil { From 3e36ab5b5f29d4a44f76979489f91b5b3bb8d714 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sat, 16 Dec 2023 10:51:58 -0700 Subject: [PATCH 528/775] Fix queued transaction time encoding --- arbnode/dataposter/storage/rlp_test.go | 120 +++++++++++++++++++++++++ arbnode/dataposter/storage/storage.go | 16 ++-- arbnode/dataposter/storage/time.go | 10 ++- arbnode/dataposter/storage_test.go | 20 +---- 4 files changed, 138 insertions(+), 28 deletions(-) create mode 100644 arbnode/dataposter/storage/rlp_test.go diff --git a/arbnode/dataposter/storage/rlp_test.go b/arbnode/dataposter/storage/rlp_test.go new file mode 100644 index 000000000..6a2b6c5c6 --- /dev/null +++ b/arbnode/dataposter/storage/rlp_test.go @@ -0,0 +1,120 @@ +// Copyright 2021-2023, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package storage + +import ( + "bytes" + "testing" + "time" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" +) + +func TestTimeEncoding(t *testing.T) { + now := RlpTime(time.Now()) + enc, err := rlp.EncodeToBytes(now) + if err != nil { + t.Fatal("failed to encode time", err) + } + var dec RlpTime + err = rlp.DecodeBytes(enc, &dec) + if err != nil { + t.Fatal("failed to decode time", err) + } + if !time.Time(dec).Equal(time.Time(now)) { + t.Fatalf("time %v encoded then decoded to %v", now, dec) + } +} + +func TestOldTimeEncoding(t *testing.T) { + type OldQueuedTransaction struct { + FullTx *types.Transaction + Data types.DynamicFeeTx + Meta []byte + Sent bool + Created time.Time + NextReplacement time.Time + } + + oldTx := OldQueuedTransaction{ + FullTx: types.NewTx(&types.DynamicFeeTx{}), + Meta: []byte{0}, + } + + enc, err := rlp.EncodeToBytes(oldTx) + if err != nil { + t.Fatal("failed to encode old queued tx", err) + } + var dec QueuedTransaction + err = rlp.DecodeBytes(enc, &dec) + if err != nil { + t.Fatal("failed to decode old queued tx", err) + } + + if !bytes.Equal(oldTx.Meta, dec.Meta) { + t.Fatalf("meta %v encoded then decoded to %v", oldTx.Meta, dec.Meta) + } +} + +func TestWeirdTimeEncoding(t *testing.T) { + type OldQueuedTransaction struct { + FullTx *types.Transaction + Data types.DynamicFeeTx + Meta []byte + Sent bool + Created *RlpTime `rlp:"optional"` + NextReplacement *RlpTime `rlp:"optional"` + } + + now := time.Now() + oldTx := OldQueuedTransaction{ + FullTx: types.NewTx(&types.DynamicFeeTx{}), + Meta: []byte{0}, + Created: (*RlpTime)(&now), + NextReplacement: (*RlpTime)(&now), + } + + enc, err := rlp.EncodeToBytes(oldTx) + if err != nil { + t.Fatal("failed to encode old queued tx", err) + } + var dec QueuedTransaction + err = rlp.DecodeBytes(enc, &dec) + if err != nil { + t.Fatal("failed to decode old queued tx", err) + } + + if !bytes.Equal(oldTx.Meta, dec.Meta) { + t.Fatalf("meta %v encoded then decoded to %v", oldTx.Meta, dec.Meta) + } + if !(time.Time)(*oldTx.Created).Equal(dec.Created) { + t.Fatalf("created %v encoded then decoded to %v", oldTx.Created, dec.Created) + } +} + +func TestNewQueuedTransactionEncoding(t *testing.T) { + oldTx := &QueuedTransaction{ + FullTx: types.NewTx(&types.DynamicFeeTx{}), + Meta: []byte{0}, + Created: time.Now(), + } + + enc, err := rlp.EncodeToBytes(oldTx) + if err != nil { + t.Fatal("failed to encode old queued tx", err) + } + var dec QueuedTransaction + err = rlp.DecodeBytes(enc, &dec) + if err != nil { + t.Fatal("failed to decode old queued tx", err) + } + + if !bytes.Equal(oldTx.Meta, dec.Meta) { + t.Fatalf("meta %v encoded then decoded to %v", oldTx.Meta, dec.Meta) + } + if !oldTx.Created.Equal(dec.Created) { + t.Fatalf("created %v encoded then decoded to %v", oldTx.Created, dec.Created) + } +} diff --git a/arbnode/dataposter/storage/storage.go b/arbnode/dataposter/storage/storage.go index 87bfa8d83..a9e78fcc5 100644 --- a/arbnode/dataposter/storage/storage.go +++ b/arbnode/dataposter/storage/storage.go @@ -39,8 +39,8 @@ type queuedTransactionForEncoding struct { Data types.DynamicFeeTx Meta []byte Sent bool - Created *RlpTime `rlp:"optional"` // may be earlier than the tx was given to the tx poster - NextReplacement *RlpTime `rlp:"optional"` + Created RlpTime + NextReplacement RlpTime } func (qt *QueuedTransaction) EncodeRLP(w io.Writer) error { @@ -49,8 +49,8 @@ func (qt *QueuedTransaction) EncodeRLP(w io.Writer) error { Data: qt.Data, Meta: qt.Meta, Sent: qt.Sent, - Created: (*RlpTime)(&qt.Created), - NextReplacement: (*RlpTime)(&qt.NextReplacement), + Created: (RlpTime)(qt.Created), + NextReplacement: (RlpTime)(qt.NextReplacement), }) } @@ -63,12 +63,8 @@ func (qt *QueuedTransaction) DecodeRLP(s *rlp.Stream) error { qt.Data = qtEnc.Data qt.Meta = qtEnc.Meta qt.Sent = qtEnc.Sent - if qtEnc.Created != nil { - qt.Created = time.Time(*qtEnc.Created) - } - if qtEnc.NextReplacement != nil { - qt.NextReplacement = time.Time(*qtEnc.NextReplacement) - } + qt.Created = time.Time(qtEnc.Created) + qt.NextReplacement = time.Time(qtEnc.NextReplacement) return nil } diff --git a/arbnode/dataposter/storage/time.go b/arbnode/dataposter/storage/time.go index df07c5cff..aa15f2917 100644 --- a/arbnode/dataposter/storage/time.go +++ b/arbnode/dataposter/storage/time.go @@ -21,8 +21,16 @@ type rlpTimeEncoding struct { } func (b *RlpTime) DecodeRLP(s *rlp.Stream) error { + kind, size, err := s.Kind() + if err != nil { + return err + } + if kind == rlp.List && size == 0 { + // This is an old time.Time without any data + return s.Decode(&time.Time{}) + } var enc rlpTimeEncoding - err := s.Decode(&enc) + err = s.Decode(&enc) if err != nil { return err } diff --git a/arbnode/dataposter/storage_test.go b/arbnode/dataposter/storage_test.go index 3344215e9..fb4aade75 100644 --- a/arbnode/dataposter/storage_test.go +++ b/arbnode/dataposter/storage_test.go @@ -1,3 +1,6 @@ +// Copyright 2021-2023, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + package dataposter import ( @@ -5,7 +8,6 @@ import ( "math/big" "path" "testing" - "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" @@ -367,19 +369,3 @@ func TestLength(t *testing.T) { } } - -func TestTimeEncoding(t *testing.T) { - now := storage.RlpTime(time.Now()) - enc, err := rlp.EncodeToBytes(now) - if err != nil { - t.Fatal("failed to encode time", err) - } - var dec storage.RlpTime - err = rlp.DecodeBytes(enc, &dec) - if err != nil { - t.Fatal("failed to decode time", err) - } - if !time.Time(dec).Equal(time.Time(now)) { - t.Fatalf("time %v encoded then decoded to %v", now, dec) - } -} From a4a323ee9c459ec83f926407da6a1cceb5aaf9e1 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 17 Dec 2023 20:59:03 -0700 Subject: [PATCH 529/775] Modify fee allocation for data poster mempool txs --- arbnode/dataposter/data_poster.go | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 832641959..059e080ee 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -410,6 +410,8 @@ func (p *DataPoster) evalMaxFeeCapExpr(backlogOfBatches uint64, elapsed time.Dur return resultBig, nil } +var big4 = big.NewInt(4) + // The dataPosterBacklog argument should *not* include extraBacklog (it's added in in this function) func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit uint64, lastFeeCap *big.Int, lastTipCap *big.Int, dataCreatedAt time.Time, dataPosterBacklog uint64) (*big.Int, *big.Int, error) { config := p.config() @@ -468,17 +470,35 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u latestBalance := p.balance balanceForTx := new(big.Int).Set(latestBalance) if config.AllocateMempoolBalance && !p.usingNoOpStorage { - // We reserve half the balance for the first transaction, and then split the remaining balance for all after that. + // We split the transactions into three groups: + // - The first transaction gets 1/2 of the balance. + // - The first half of transactions get 1/3 of the balance split among them. + // - The remaining transactions get the remaining 1/6 of the balance split among them. + // This helps ensure batch posting is reliable under a variety of fee conditions. // With noop storage, we don't try to replace-by-fee, so we don't need to worry about this. balanceForTx.Div(balanceForTx, common.Big2) if nonce != softConfNonce && config.MaxMempoolTransactions > 1 { + // Compared to dividing the remaining transactions by balance equally, + // the first half of transactions should get a 4/3 weight, + // and the remaining half should get a 2/3 weight. + // This makes sure the average weight is 1, and the first half of transactions + // have twice the weight of the second half of transactions. + // The +1 and -1 here are to account for the first transaction being handled separately. + if nonce > softConfNonce && nonce < softConfNonce+1+(config.MaxMempoolTransactions-1)/2 { + balanceForTx.Mul(balanceForTx, big4) + } else { + balanceForTx.Mul(balanceForTx, common.Big2) + } + balanceForTx.Div(balanceForTx, common.Big3) + // After weighting, split the balance between each of the transactions + // other than the first tx which already got half. // balanceForTx /= config.MaxMempoolTransactions-1 balanceForTx.Div(balanceForTx, arbmath.UintToBig(config.MaxMempoolTransactions-1)) } } balanceFeeCap := arbmath.BigDivByUint(balanceForTx, gasLimit) if arbmath.BigGreaterThan(newFeeCap, balanceFeeCap) { - log.Error( + log.Warn( "lack of L1 balance prevents posting transaction with desired fee cap", "balance", latestBalance, "maxTransactions", config.MaxMempoolTransactions, From 2473808f76e907bd6e7a92025bb32615b76518ca Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 17 Dec 2023 22:36:45 -0700 Subject: [PATCH 530/775] Use a moving average to determine messages per batch --- arbnode/batch_poster.go | 40 +++++++++++++++---------- util/arbmath/math.go | 8 ++--- util/arbmath/moving_average.go | 45 +++++++++++++++++++++++++++++ util/arbmath/moving_average_test.go | 35 ++++++++++++++++++++++ 4 files changed, 109 insertions(+), 19 deletions(-) create mode 100644 util/arbmath/moving_average.go create mode 100644 util/arbmath/moving_average_test.go diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 5d61bc5f1..594eec40d 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -73,6 +73,7 @@ type BatchPoster struct { dataPoster *dataposter.DataPoster redisLock *redislock.Simple firstEphemeralError time.Time // first time a continuous error suspected to be ephemeral occurred + messagesPerBatch *arbmath.MovingAverage[uint64] // This is an atomic variable that should only be accessed atomically. // An estimate of the number of batches we want to post but haven't yet. // This doesn't include batches which we don't want to post yet due to the L1 bounds. @@ -258,19 +259,20 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e return nil, err } b := &BatchPoster{ - l1Reader: opts.L1Reader, - inbox: opts.Inbox, - streamer: opts.Streamer, - syncMonitor: opts.SyncMonitor, - config: opts.Config, - bridge: bridge, - seqInbox: seqInbox, - seqInboxABI: seqInboxABI, - seqInboxAddr: opts.DeployInfo.SequencerInbox, - gasRefunderAddr: opts.Config().gasRefunder, - bridgeAddr: opts.DeployInfo.Bridge, - daWriter: opts.DAWriter, - redisLock: redisLock, + l1Reader: opts.L1Reader, + inbox: opts.Inbox, + streamer: opts.Streamer, + syncMonitor: opts.SyncMonitor, + config: opts.Config, + bridge: bridge, + seqInbox: seqInbox, + seqInboxABI: seqInboxABI, + seqInboxAddr: opts.DeployInfo.SequencerInbox, + gasRefunderAddr: opts.Config().gasRefunder, + bridgeAddr: opts.DeployInfo.Bridge, + daWriter: opts.DAWriter, + redisLock: redisLock, + messagesPerBatch: arbmath.NewMovingAverage[uint64](20), } dataPosterConfigFetcher := func() *dataposter.DataPosterConfig { return &(opts.Config().DataPoster) @@ -1062,8 +1064,15 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) ) recentlyHitL1Bounds := time.Since(b.lastHitL1Bounds) < config.PollInterval*3 postedMessages := b.building.msgCount - batchPosition.MessageCount + b.messagesPerBatch.Update(uint64(postedMessages)) unpostedMessages := msgCount - b.building.msgCount - backlog := uint64(unpostedMessages) / uint64(postedMessages) + messagesPerBatch := b.messagesPerBatch.Average() + if messagesPerBatch == 0 { + // This should be impossible because we always post at least one message in a batch. + // That said, better safe than sorry, as we would panic if this remained at 0. + messagesPerBatch = 1 + } + backlog := uint64(unpostedMessages) / messagesPerBatch if backlog > 10 { logLevel := log.Warn if recentlyHitL1Bounds { @@ -1076,7 +1085,8 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) "recentlyHitL1Bounds", recentlyHitL1Bounds, "currentPosition", b.building.msgCount, "messageCount", msgCount, - "lastPostedMessages", postedMessages, + "messagesPerBatch", messagesPerBatch, + "postedMessages", postedMessages, "unpostedMessages", unpostedMessages, "batchBacklogEstimate", backlog, ) diff --git a/util/arbmath/math.go b/util/arbmath/math.go index 3d1df0ce6..eaac79bfa 100644 --- a/util/arbmath/math.go +++ b/util/arbmath/math.go @@ -47,14 +47,14 @@ type Float interface { ~float32 | ~float64 } -// Ordered is anything that implements comparison operators such as `<` and `>`. +// Number is anything that implements operators such as `<`, `+` and `/`. // Unfortunately, that doesn't include big ints. -type Ordered interface { +type Number interface { Integer | Float } // MinInt the minimum of two ints -func MinInt[T Ordered](value, ceiling T) T { +func MinInt[T Number](value, ceiling T) T { if value > ceiling { return ceiling } @@ -62,7 +62,7 @@ func MinInt[T Ordered](value, ceiling T) T { } // MaxInt the maximum of two ints -func MaxInt[T Ordered](value, floor T) T { +func MaxInt[T Number](value, floor T) T { if value < floor { return floor } diff --git a/util/arbmath/moving_average.go b/util/arbmath/moving_average.go new file mode 100644 index 000000000..fe5a349f4 --- /dev/null +++ b/util/arbmath/moving_average.go @@ -0,0 +1,45 @@ +// Copyright 2023, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package arbmath + +// A simple moving average of a generic number type. +type MovingAverage[T Number] struct { + period int + buffer []T + bufferPosition int + sum T +} + +func NewMovingAverage[T Number](period int) *MovingAverage[T] { + if period <= 0 { + panic("MovingAverage period must be positive") + } + return &MovingAverage[T]{ + period: period, + buffer: make([]T, 0, period), + } +} + +func (a *MovingAverage[T]) Update(value T) { + if a.period <= 0 { + return + } + if len(a.buffer) < a.period { + a.buffer = append(a.buffer, value) + a.sum += value + } else { + a.sum += value + a.sum -= a.buffer[a.bufferPosition] + a.buffer[a.bufferPosition] = value + a.bufferPosition = (a.bufferPosition + 1) % a.period + } +} + +// Average returns the current moving average, or zero if no values have been added. +func (a *MovingAverage[T]) Average() T { + if len(a.buffer) == 0 { + return 0 + } + return a.sum / T(len(a.buffer)) +} diff --git a/util/arbmath/moving_average_test.go b/util/arbmath/moving_average_test.go new file mode 100644 index 000000000..249080717 --- /dev/null +++ b/util/arbmath/moving_average_test.go @@ -0,0 +1,35 @@ +// Copyright 2023, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package arbmath + +import "testing" + +func TestMovingAverage(t *testing.T) { + ma := NewMovingAverage[int](5) + if ma.Average() != 0 { + t.Errorf("moving average should be 0 at start, got %v", ma.Average()) + } + ma.Update(2) + if ma.Average() != 2 { + t.Errorf("moving average should be 2, got %v", ma.Average()) + } + ma.Update(4) + if ma.Average() != 3 { + t.Errorf("moving average should be 3, got %v", ma.Average()) + } + + for i := 0; i < 5; i++ { + ma.Update(10) + } + if ma.Average() != 10 { + t.Errorf("moving average should be 10, got %v", ma.Average()) + } + + for i := 0; i < 5; i++ { + ma.Update(0) + } + if ma.Average() != 0 { + t.Errorf("moving average should be 0, got %v", ma.Average()) + } +} From e25a59ecb379bbc2b1ec6fd91d90c88165a00936 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 18 Dec 2023 17:46:01 +0530 Subject: [PATCH 531/775] fix typo --- util/log.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/util/log.go b/util/log.go index 4e0453638..9bf508e53 100644 --- a/util/log.go +++ b/util/log.go @@ -9,10 +9,10 @@ import ( // LogLevelEphemeralError is a convenient intermediary level between log levels Warn and Error // -// For a given error, errorSubstring, duration, firstOccuranceTime and logLevel +// For a given error, errorSubstring, duration, firstOccurrenceTime and logLevel // the function defaults to returning the given logLevel if the error doesnt contain the errorSubstring, // but if it does, then returns one of the corresponding loglevels as follows -// - Warn: For firstOccuranceTime of error being less than the duration amount of time from Now +// - Warn: For firstOccurrenceTime of error being less than the duration amount of time from Now // - Error: Otherwise // // # Usage Examples @@ -24,19 +24,19 @@ func LogLevelEphemeralError( err error, errorSubstring string, ephemeralDuration time.Duration, - firstOccuranceTime *time.Time, + firstOccurrenceTime *time.Time, currentLogLevel func(msg string, ctx ...interface{})) func(string, ...interface{}) { if strings.Contains(err.Error(), errorSubstring) || errorSubstring == "" { logLevel := log.Error - if *firstOccuranceTime == (time.Time{}) { - *firstOccuranceTime = time.Now() + if *firstOccurrenceTime == (time.Time{}) { + *firstOccurrenceTime = time.Now() logLevel = log.Warn - } else if time.Since(*firstOccuranceTime) < ephemeralDuration { + } else if time.Since(*firstOccurrenceTime) < ephemeralDuration { logLevel = log.Warn } return logLevel } else { - *firstOccuranceTime = time.Time{} + *firstOccurrenceTime = time.Time{} return currentLogLevel } } From beade38e9edd2ee8b0d044aa761627d0bd32daaa Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 18 Dec 2023 19:18:37 +0530 Subject: [PATCH 532/775] Add a metric for steps taken in arbitrator validation --- validator/server_api/{valiation_api.go => validation_api.go} | 0 validator/server_arb/validator_spawner.go | 4 ++++ 2 files changed, 4 insertions(+) rename validator/server_api/{valiation_api.go => validation_api.go} (100%) diff --git a/validator/server_api/valiation_api.go b/validator/server_api/validation_api.go similarity index 100% rename from validator/server_api/valiation_api.go rename to validator/server_api/validation_api.go diff --git a/validator/server_arb/validator_spawner.go b/validator/server_arb/validator_spawner.go index ab0494287..834c4482c 100644 --- a/validator/server_arb/validator_spawner.go +++ b/validator/server_arb/validator_spawner.go @@ -21,8 +21,11 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" ) +var arbitratorValidationSteps = metrics.NewRegisteredHistogram("arbitrator/validation/steps", nil, metrics.NewBoundedHistogramSample()) + type ArbitratorSpawnerConfig struct { Workers int `koanf:"workers" reload:"hot"` OutputPath string `koanf:"output-path" reload:"hot"` @@ -146,6 +149,7 @@ func (v *ArbitratorSpawner) execute( } steps += count } + arbitratorValidationSteps.Update(int64(steps)) if mach.IsErrored() { log.Error("machine entered errored state during attempted validation", "block", entry.Id) return validator.GoGlobalState{}, errors.New("machine entered errored state during attempted validation") From 06269e0ec3d2efad07dc894a4e929baa0172ecc4 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 18 Dec 2023 09:31:37 -0700 Subject: [PATCH 533/775] Address PR review comments --- arbnode/batch_poster.go | 37 ++++++++++++++++++----------- util/arbmath/moving_average.go | 17 ++++++------- util/arbmath/moving_average_test.go | 24 ++++++++++++++----- 3 files changed, 50 insertions(+), 28 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 594eec40d..a54336fd5 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -259,20 +259,23 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e return nil, err } b := &BatchPoster{ - l1Reader: opts.L1Reader, - inbox: opts.Inbox, - streamer: opts.Streamer, - syncMonitor: opts.SyncMonitor, - config: opts.Config, - bridge: bridge, - seqInbox: seqInbox, - seqInboxABI: seqInboxABI, - seqInboxAddr: opts.DeployInfo.SequencerInbox, - gasRefunderAddr: opts.Config().gasRefunder, - bridgeAddr: opts.DeployInfo.Bridge, - daWriter: opts.DAWriter, - redisLock: redisLock, - messagesPerBatch: arbmath.NewMovingAverage[uint64](20), + l1Reader: opts.L1Reader, + inbox: opts.Inbox, + streamer: opts.Streamer, + syncMonitor: opts.SyncMonitor, + config: opts.Config, + bridge: bridge, + seqInbox: seqInbox, + seqInboxABI: seqInboxABI, + seqInboxAddr: opts.DeployInfo.SequencerInbox, + gasRefunderAddr: opts.Config().gasRefunder, + bridgeAddr: opts.DeployInfo.Bridge, + daWriter: opts.DAWriter, + redisLock: redisLock, + } + b.messagesPerBatch, err = arbmath.NewMovingAverage[uint64](20) + if err != nil { + return nil, err } dataPosterConfigFetcher := func() *dataposter.DataPosterConfig { return &(opts.Config().DataPoster) @@ -1070,6 +1073,12 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) if messagesPerBatch == 0 { // This should be impossible because we always post at least one message in a batch. // That said, better safe than sorry, as we would panic if this remained at 0. + log.Warn( + "messagesPerBatch is somehow zero", + "postedMessages", postedMessages, + "buildingFrom", batchPosition.MessageCount, + "buildingTo", b.building.msgCount, + ) messagesPerBatch = 1 } backlog := uint64(unpostedMessages) / messagesPerBatch diff --git a/util/arbmath/moving_average.go b/util/arbmath/moving_average.go index fe5a349f4..fcd5f6e30 100644 --- a/util/arbmath/moving_average.go +++ b/util/arbmath/moving_average.go @@ -3,36 +3,37 @@ package arbmath +import "fmt" + // A simple moving average of a generic number type. type MovingAverage[T Number] struct { - period int buffer []T bufferPosition int sum T } -func NewMovingAverage[T Number](period int) *MovingAverage[T] { +func NewMovingAverage[T Number](period int) (*MovingAverage[T], error) { if period <= 0 { - panic("MovingAverage period must be positive") + return nil, fmt.Errorf("MovingAverage period specified as %v but it must be positive", period) } return &MovingAverage[T]{ - period: period, buffer: make([]T, 0, period), - } + }, nil } func (a *MovingAverage[T]) Update(value T) { - if a.period <= 0 { + period := cap(a.buffer) + if period == 0 { return } - if len(a.buffer) < a.period { + if len(a.buffer) < period { a.buffer = append(a.buffer, value) a.sum += value } else { a.sum += value a.sum -= a.buffer[a.bufferPosition] a.buffer[a.bufferPosition] = value - a.bufferPosition = (a.bufferPosition + 1) % a.period + a.bufferPosition = (a.bufferPosition + 1) % period } } diff --git a/util/arbmath/moving_average_test.go b/util/arbmath/moving_average_test.go index 249080717..9013d3f48 100644 --- a/util/arbmath/moving_average_test.go +++ b/util/arbmath/moving_average_test.go @@ -6,30 +6,42 @@ package arbmath import "testing" func TestMovingAverage(t *testing.T) { - ma := NewMovingAverage[int](5) + _, err := NewMovingAverage[int](0) + if err == nil { + t.Error("Expected error when creating moving average of period 0") + } + _, err = NewMovingAverage[int](-1) + if err == nil { + t.Error("Expected error when creating moving average of period -1") + } + + ma, err := NewMovingAverage[int](5) + if err != nil { + t.Fatalf("Error creating moving average of period 5: %v", err) + } if ma.Average() != 0 { - t.Errorf("moving average should be 0 at start, got %v", ma.Average()) + t.Errorf("Average() = %v, want 0", ma.Average()) } ma.Update(2) if ma.Average() != 2 { - t.Errorf("moving average should be 2, got %v", ma.Average()) + t.Errorf("Average() = %v, want 2", ma.Average()) } ma.Update(4) if ma.Average() != 3 { - t.Errorf("moving average should be 3, got %v", ma.Average()) + t.Errorf("Average() = %v, want 3", ma.Average()) } for i := 0; i < 5; i++ { ma.Update(10) } if ma.Average() != 10 { - t.Errorf("moving average should be 10, got %v", ma.Average()) + t.Errorf("Average() = %v, want 10", ma.Average()) } for i := 0; i < 5; i++ { ma.Update(0) } if ma.Average() != 0 { - t.Errorf("moving average should be 0, got %v", ma.Average()) + t.Errorf("Average() = %v, want 0", ma.Average()) } } From 9fca6e2af921fa5397ca3aaf2b20718a1bf72df5 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 18 Dec 2023 12:53:09 -0700 Subject: [PATCH 534/775] Fix missing ArgLogLimit in L1 RPC client --- cmd/conf/chain.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/conf/chain.go b/cmd/conf/chain.go index 505957f45..e9ec2af0c 100644 --- a/cmd/conf/chain.go +++ b/cmd/conf/chain.go @@ -22,6 +22,7 @@ var L1ConnectionConfigDefault = rpcclient.ClientConfig{ Retries: 2, Timeout: time.Minute, ConnectionWait: time.Minute, + ArgLogLimit: 2048, } var L1ConfigDefault = L1Config{ From c489750966feee7f593946181ae07e67a92cbda6 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Tue, 19 Dec 2023 10:57:07 +0530 Subject: [PATCH 535/775] address PR comments --- validator/server_arb/validator_spawner.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validator/server_arb/validator_spawner.go b/validator/server_arb/validator_spawner.go index 834c4482c..67aa5477e 100644 --- a/validator/server_arb/validator_spawner.go +++ b/validator/server_arb/validator_spawner.go @@ -149,7 +149,7 @@ func (v *ArbitratorSpawner) execute( } steps += count } - arbitratorValidationSteps.Update(int64(steps)) + arbitratorValidationSteps.Update(int64(mach.GetStepCount())) if mach.IsErrored() { log.Error("machine entered errored state during attempted validation", "block", entry.Id) return validator.GoGlobalState{}, errors.New("machine entered errored state during attempted validation") From 6ca851673ed9b86bdca4c60097712f041509f6c5 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 19 Dec 2023 14:33:30 +0000 Subject: [PATCH 536/775] fix arbitrum data db name in das test --- system_tests/das_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system_tests/das_test.go b/system_tests/das_test.go index 8c9621d57..6db339521 100644 --- a/system_tests/das_test.go +++ b/system_tests/das_test.go @@ -179,7 +179,7 @@ func TestDASRekey(t *testing.T) { l2chainDb, err := l2stackA.OpenDatabase("chaindb", 0, 0, "", false) Require(t, err) - l2arbDb, err := l2stackA.OpenDatabase("arbdb", 0, 0, "", false) + l2arbDb, err := l2stackA.OpenDatabase("arbitrumdata", 0, 0, "", false) Require(t, err) l2blockchain, err := gethexec.GetBlockChain(l2chainDb, nil, chainConfig, gethexec.ConfigDefaultTest().TxLookupLimit) From a0046599c388a8cb1f7837d42ed1d323810a975e Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Tue, 19 Dec 2023 16:46:46 +0100 Subject: [PATCH 537/775] Pass From field from dataposter to external signer --- arbnode/dataposter/data_poster.go | 42 ++++++++++++++++++++++----- arbnode/dataposter/dataposter_test.go | 6 +++- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 059e080ee..e405c32dd 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/go-redis/redis/v8" "github.com/offchainlabs/nitro/arbnode/dataposter/dbstorage" "github.com/offchainlabs/nitro/arbnode/dataposter/noop" @@ -236,6 +237,31 @@ func rpcClient(ctx context.Context, opts *ExternalSignerCfg) (*rpc.Client, error ) } +// txToSendTxArgs converts transaction to SendTxArgs. This is needed for +// external signer to specify From field. +func txToSendTxArgs(addr common.Address, tx *types.Transaction) (*apitypes.SendTxArgs, error) { + if tx.To() == nil { + return nil, fmt.Errorf("transaction %v has no destination", tx.Hash()) + } + to := common.NewMixedcaseAddress(*tx.To()) + data := (hexutil.Bytes)(tx.Data()) + val := (*hexutil.Big)(tx.Value()) + if val == nil { + val = (*hexutil.Big)(big.NewInt(0)) + } + return &apitypes.SendTxArgs{ + From: common.NewMixedcaseAddress(addr), + To: &to, + Gas: hexutil.Uint64(tx.Gas()), + GasPrice: (*hexutil.Big)(tx.GasPrice()), + MaxFeePerGas: (*hexutil.Big)(tx.GasFeeCap()), + MaxPriorityFeePerGas: (*hexutil.Big)(tx.GasTipCap()), + Value: *val, + Data: &data, + Nonce: hexutil.Uint64(tx.Nonce()), + }, nil +} + // externalSigner returns signer function and ethereum address of the signer. // Returns an error if address isn't specified or if it can't connect to the // signer RPC server. @@ -249,25 +275,25 @@ func externalSigner(ctx context.Context, opts *ExternalSignerCfg) (signerFn, com return nil, common.Address{}, fmt.Errorf("error connecting external signer: %w", err) } sender := common.HexToAddress(opts.Address) - - var hasher types.Signer return func(ctx context.Context, addr common.Address, tx *types.Transaction) (*types.Transaction, error) { // According to the "eth_signTransaction" API definition, this should be // RLP encoded transaction object. // https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction var data hexutil.Bytes - if err := client.CallContext(ctx, &data, opts.Method, tx); err != nil { + args, err := txToSendTxArgs(addr, tx) + if err != nil { + return nil, fmt.Errorf("error converting transaction to sendTxArgs: %w", err) + } + if err := client.CallContext(ctx, &data, opts.Method, args); err != nil { return nil, fmt.Errorf("signing transaction: %w", err) } var signedTx types.Transaction if err := rlp.DecodeBytes(data, &signedTx); err != nil { return nil, fmt.Errorf("error decoding signed transaction: %w", err) } - if hasher == nil { - hasher = types.LatestSignerForChainID(tx.ChainId()) - } - if hasher.Hash(tx) != hasher.Hash(&signedTx) { - return nil, fmt.Errorf("transaction: %x from external signer differs from request: %x", hasher.Hash(&signedTx), hasher.Hash(tx)) + hasher := types.LatestSignerForChainID(tx.ChainId()) + if h := hasher.Hash(args.ToTransaction()); h != hasher.Hash(&signedTx) { + return nil, fmt.Errorf("transaction: %x from external signer differs from request: %x", hasher.Hash(&signedTx), h) } return &signedTx, nil }, sender, nil diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index 74b4aff18..e8028963f 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -93,7 +93,11 @@ func TestExternalSigner(t *testing.T) { if err != nil { t.Fatalf("Error signing transaction with external signer: %v", err) } - want, err := srv.signerFn(addr, tx) + args, err := txToSendTxArgs(addr, tx) + if err != nil { + t.Fatalf("Error converting transaction to sendTxArgs: %v", err) + } + want, err := srv.signerFn(addr, args.ToTransaction()) if err != nil { t.Fatalf("Error signing transaction: %v", err) } From e9f0104add0d754a9c653ed384345273d717c133 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Tue, 19 Dec 2023 16:54:06 +0100 Subject: [PATCH 538/775] Include accessList and chainID in signing requrest --- arbnode/dataposter/data_poster.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index e405c32dd..d5b67505f 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -249,6 +249,7 @@ func txToSendTxArgs(addr common.Address, tx *types.Transaction) (*apitypes.SendT if val == nil { val = (*hexutil.Big)(big.NewInt(0)) } + al := tx.AccessList() return &apitypes.SendTxArgs{ From: common.NewMixedcaseAddress(addr), To: &to, @@ -257,8 +258,10 @@ func txToSendTxArgs(addr common.Address, tx *types.Transaction) (*apitypes.SendT MaxFeePerGas: (*hexutil.Big)(tx.GasFeeCap()), MaxPriorityFeePerGas: (*hexutil.Big)(tx.GasTipCap()), Value: *val, - Data: &data, Nonce: hexutil.Uint64(tx.Nonce()), + Data: &data, + AccessList: &al, + ChainID: (*hexutil.Big)(tx.ChainId()), }, nil } From 3bb7fab7fbc73d7d31fe53d4cc5f53da44cad108 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 19 Dec 2023 20:21:37 -0700 Subject: [PATCH 539/775] Increase TxStreamer feed queue size --- arbnode/transaction_streamer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 2d6f7d589..db0658f92 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -79,7 +79,7 @@ type TransactionStreamerConfig struct { type TransactionStreamerConfigFetcher func() *TransactionStreamerConfig var DefaultTransactionStreamerConfig = TransactionStreamerConfig{ - MaxBroadcasterQueueSize: 1024, + MaxBroadcasterQueueSize: 50_000, MaxReorgResequenceDepth: 1024, ExecuteMessageLoopDelay: time.Millisecond * 100, } From eb55d43ec017dd7e8c66e85b0fa1ec81d15bba3c Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Wed, 20 Dec 2023 20:26:57 +0530 Subject: [PATCH 540/775] Update failed to create machine locator error to a warning --- cmd/nitro/nitro.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index b850b9898..966b073ef 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -456,13 +456,13 @@ func mainImpl() int { // If no allowed module roots were provided in config, check if we have a validator machine directory for the on-chain WASM module root locator, err := server_common.NewMachineLocator(nodeConfig.Validation.Wasm.RootPath) if err != nil { - log.Error("failed to create machine locator", "err", err) - return 1 - } - path := locator.GetMachinePath(moduleRoot) - if _, err := os.Stat(path); err != nil { - log.Error("unable to find validator machine directory for the on-chain WASM module root", "err", err) - return 1 + log.Warn("failed to create machine locator. Skipping the check for compatibility with on-chain WASM module root", "err", err) + } else { + path := locator.GetMachinePath(moduleRoot) + if _, err := os.Stat(path); err != nil { + log.Error("unable to find validator machine directory for the on-chain WASM module root", "err", err) + return 1 + } } } } From a4b4bddd3a8ba743c7665932071f380f5e93fe55 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Wed, 20 Dec 2023 20:28:47 +0530 Subject: [PATCH 541/775] Add a metric for memory used by the replay binary WASM in JIT --- arbitrator/jit/src/machine.rs | 3 ++- arbitrator/jit/src/main.rs | 3 ++- validator/server_jit/jit_machine.go | 33 +++++++++++++++++++------- validator/server_jit/machine_loader.go | 12 ++++++---- validator/server_jit/spawner.go | 10 ++++++-- 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/arbitrator/jit/src/machine.rs b/arbitrator/jit/src/machine.rs index ed22e12ef..c9119dd16 100644 --- a/arbitrator/jit/src/machine.rs +++ b/arbitrator/jit/src/machine.rs @@ -280,7 +280,7 @@ impl WasmEnv { Ok(env) } - pub fn send_results(&mut self, error: Option) { + pub fn send_results(&mut self, error: Option, memory_used: u64) { let writer = match &mut self.process.socket { Some((writer, _)) => writer, None => return, @@ -307,6 +307,7 @@ impl WasmEnv { check!(socket::write_u64(writer, self.small_globals[1])); check!(socket::write_bytes32(writer, &self.large_globals[0])); check!(socket::write_bytes32(writer, &self.large_globals[1])); + check!(socket::write_u64(writer, memory_used)); check!(writer.flush()); } } diff --git a/arbitrator/jit/src/main.rs b/arbitrator/jit/src/main.rs index 513cd067c..968da2a97 100644 --- a/arbitrator/jit/src/main.rs +++ b/arbitrator/jit/src/main.rs @@ -114,8 +114,9 @@ fn main() { true => None, false => Some(message), }; + let memory_used = memory.size().0 as u64 * 65_536; - env.send_results(error); + env.send_results(error, memory_used); } // require a usize be at least 32 bits wide diff --git a/validator/server_jit/jit_machine.go b/validator/server_jit/jit_machine.go index f763ce3ea..a41e249cd 100644 --- a/validator/server_jit/jit_machine.go +++ b/validator/server_jit/jit_machine.go @@ -16,17 +16,21 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/validator" ) +var jitWasmMemoryUsage = metrics.NewRegisteredHistogram("jit/wasm/memoryusage", nil, metrics.NewBoundedHistogramSample()) + type JitMachine struct { - binary string - process *exec.Cmd - stdin io.WriteCloser + binary string + process *exec.Cmd + stdin io.WriteCloser + wasmMemoryUsageLimit int } -func createJitMachine(jitBinary string, binaryPath string, cranelift bool, moduleRoot common.Hash, fatalErrChan chan error) (*JitMachine, error) { +func createJitMachine(jitBinary string, binaryPath string, cranelift bool, wasmMemoryUsageLimit int, moduleRoot common.Hash, fatalErrChan chan error) (*JitMachine, error) { invocation := []string{"--binary", binaryPath, "--forks"} if cranelift { invocation = append(invocation, "--cranelift") @@ -45,9 +49,10 @@ func createJitMachine(jitBinary string, binaryPath string, cranelift bool, modul }() machine := &JitMachine{ - binary: binaryPath, - process: process, - stdin: stdin, + binary: binaryPath, + process: process, + stdin: stdin, + wasmMemoryUsageLimit: wasmMemoryUsageLimit, } return machine, nil } @@ -258,8 +263,18 @@ func (machine *JitMachine) prove( if state.BlockHash, err = readHash(); err != nil { return state, err } - state.SendRoot, err = readHash() - return state, err + if state.SendRoot, err = readHash(); err != nil { + return state, err + } + memoryUsed, err := readUint64() + if err != nil { + return state, fmt.Errorf("failed to read memory usage from Jit machine: %w", err) + } + if memoryUsed > uint64(machine.wasmMemoryUsageLimit) { + log.Warn("memory used by jit wasm exceeds the wasm memory usage limit", "limit", machine.wasmMemoryUsageLimit, "memoryUsed", memoryUsed) + } + jitWasmMemoryUsage.Update(int64(memoryUsed)) + return state, nil default: message := "inter-process communication failure" log.Error("Jit Machine Failure", "message", message) diff --git a/validator/server_jit/machine_loader.go b/validator/server_jit/machine_loader.go index 5705a9a38..3a831928b 100644 --- a/validator/server_jit/machine_loader.go +++ b/validator/server_jit/machine_loader.go @@ -13,13 +13,15 @@ import ( ) type JitMachineConfig struct { - ProverBinPath string - JitCranelift bool + ProverBinPath string + JitCranelift bool + WasmMemoryUsageLimit int } var DefaultJitMachineConfig = JitMachineConfig{ - JitCranelift: true, - ProverBinPath: "replay.wasm", + JitCranelift: true, + ProverBinPath: "replay.wasm", + WasmMemoryUsageLimit: 4294967296, } func getJitPath() (string, error) { @@ -57,7 +59,7 @@ func NewJitMachineLoader(config *JitMachineConfig, locator *server_common.Machin } createMachineThreadFunc := func(ctx context.Context, moduleRoot common.Hash) (*JitMachine, error) { binPath := filepath.Join(locator.GetMachinePath(moduleRoot), config.ProverBinPath) - return createJitMachine(jitPath, binPath, config.JitCranelift, moduleRoot, fatalErrChan) + return createJitMachine(jitPath, binPath, config.JitCranelift, config.WasmMemoryUsageLimit, moduleRoot, fatalErrChan) } return &JitMachineLoader{ MachineLoader: *server_common.NewMachineLoader[JitMachine](locator, createMachineThreadFunc), diff --git a/validator/server_jit/spawner.go b/validator/server_jit/spawner.go index ff1749506..6489821b5 100644 --- a/validator/server_jit/spawner.go +++ b/validator/server_jit/spawner.go @@ -18,18 +18,23 @@ import ( type JitSpawnerConfig struct { Workers int `koanf:"workers" reload:"hot"` Cranelift bool `koanf:"cranelift"` + + // TODO: change WasmMemoryUsageLimit to a string and use resourcemanager.ParseMemLimit + WasmMemoryUsageLimit int `koanf:"wasm-memory-usage-limit"` } type JitSpawnerConfigFecher func() *JitSpawnerConfig var DefaultJitSpawnerConfig = JitSpawnerConfig{ - Workers: 0, - Cranelift: true, + Workers: 0, + Cranelift: true, + WasmMemoryUsageLimit: 4294967296, // 2^32 WASM memeory limit } func JitSpawnerConfigAddOptions(prefix string, f *flag.FlagSet) { f.Int(prefix+".workers", DefaultJitSpawnerConfig.Workers, "number of concurrent validation threads") f.Bool(prefix+".cranelift", DefaultJitSpawnerConfig.Cranelift, "use Cranelift instead of LLVM when validating blocks using the jit-accelerated block validator") + f.Int(prefix+".wasm-memory-usage-limit", DefaultJitSpawnerConfig.WasmMemoryUsageLimit, "if memory used by a jit wasm exceeds this limit, a warning is logged") } type JitSpawner struct { @@ -44,6 +49,7 @@ func NewJitSpawner(locator *server_common.MachineLocator, config JitSpawnerConfi // TODO - preload machines machineConfig := DefaultJitMachineConfig machineConfig.JitCranelift = config().Cranelift + machineConfig.WasmMemoryUsageLimit = config().WasmMemoryUsageLimit loader, err := NewJitMachineLoader(&machineConfig, locator, fatalErrChan) if err != nil { return nil, err From 7a26e97d04ef7a26a9adcd6b53db0afc0bf384d6 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 20 Dec 2023 15:03:39 +0000 Subject: [PATCH 542/775] clean up debug log --- cmd/prunning/prunning.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/prunning/prunning.go b/cmd/prunning/prunning.go index 7538c68a1..5efdf8e64 100644 --- a/cmd/prunning/prunning.go +++ b/cmd/prunning/prunning.go @@ -101,7 +101,6 @@ func findImportantRoots(ctx context.Context, chainDb ethdb.Database, stack *node genesisNum := chainConfig.ArbitrumChainParams.GenesisBlockNum genesisHash := rawdb.ReadCanonicalHash(chainDb, genesisNum) genesisHeader := rawdb.ReadHeader(chainDb, genesisHash, genesisNum) - log.Warn("XXX", "genesisNum", genesisNum, "genesisHash", genesisHash) if genesisHeader == nil { return nil, errors.New("missing L2 genesis block header") } From 712bc0ce2658f98b7476375148c72891dd659bb3 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 20 Dec 2023 15:10:26 +0000 Subject: [PATCH 543/775] fix typo --- system_tests/prunning_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system_tests/prunning_test.go b/system_tests/prunning_test.go index aadf3c5e9..cfb1a4bcf 100644 --- a/system_tests/prunning_test.go +++ b/system_tests/prunning_test.go @@ -98,7 +98,7 @@ func TestPrunning(t *testing.T) { t.Log("db entries post-prunning:", entriesAfterPrunning) if entriesAfterPrunning >= entriesBeforePrunning { - Fatal(t, "The db doesn't have less entires after prunning then before. Before:", entriesBeforePrunning, "After:", entriesAfterPrunning) + Fatal(t, "The db doesn't have less entries after prunning then before. Before:", entriesBeforePrunning, "After:", entriesAfterPrunning) } }() builder := NewNodeBuilder(ctx).DefaultConfig(t, true) From b005bd0c1cce855ac100e3bddb66739dc0e912c0 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 20 Dec 2023 18:24:38 +0000 Subject: [PATCH 544/775] count only state entries in diskdb in prunning test --- system_tests/prunning_test.go | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/system_tests/prunning_test.go b/system_tests/prunning_test.go index cfb1a4bcf..d52245820 100644 --- a/system_tests/prunning_test.go +++ b/system_tests/prunning_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/node" @@ -14,11 +15,14 @@ import ( "github.com/offchainlabs/nitro/util/testhelpers" ) -func countDbEntries(db ethdb.Iteratee) int { +func countStateEntries(db ethdb.Iteratee) int { entries := 0 it := db.NewIterator(nil, nil) for it.Next() { - entries++ + isCode, _ := rawdb.IsCodeKey(it.Key()) + if len(it.Key()) == common.HashLength || isCode { + entries++ + } } it.Release() return entries @@ -43,7 +47,7 @@ func TestPrunning(t *testing.T) { }() builder.L2Info.GenerateAccount("User2") var txs []*types.Transaction - for i := uint64(0); i < 1000; i++ { + for i := uint64(0); i < 200; i++ { tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) txs = append(txs, tx) err := builder.L2.Client.SendTransaction(ctx, tx) @@ -63,7 +67,7 @@ func TestPrunning(t *testing.T) { chainDb, err := stack.OpenDatabase("chaindb", 0, 0, "", false) Require(t, err) defer chainDb.Close() - entriesBeforePrunning := countDbEntries(chainDb) + chainDbEntriesBeforePrunning := countStateEntries(chainDb) prand := testhelpers.NewPseudoRandomDataSource(t, 1) var testKeys [][]byte @@ -93,12 +97,12 @@ func TestPrunning(t *testing.T) { } } - entriesAfterPrunning := countDbEntries(chainDb) - t.Log("db entries pre-prunning:", entriesBeforePrunning) - t.Log("db entries post-prunning:", entriesAfterPrunning) + chainDbEntriesAfterPrunning := countStateEntries(chainDb) + t.Log("db entries pre-prunning:", chainDbEntriesBeforePrunning) + t.Log("db entries post-prunning:", chainDbEntriesAfterPrunning) - if entriesAfterPrunning >= entriesBeforePrunning { - Fatal(t, "The db doesn't have less entries after prunning then before. Before:", entriesBeforePrunning, "After:", entriesAfterPrunning) + if chainDbEntriesAfterPrunning >= chainDbEntriesBeforePrunning { + Fatal(t, "The db doesn't have less entries after prunning then before. Before:", chainDbEntriesBeforePrunning, "After:", chainDbEntriesAfterPrunning) } }() builder := NewNodeBuilder(ctx).DefaultConfig(t, true) From a733e5a1b23d9e2f1aaa678d2a072b6be6d5388f Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 20 Dec 2023 16:25:47 -0700 Subject: [PATCH 545/775] Only lock redis in the batch poster when posting the batch --- arbnode/batch_poster.go | 30 ++++++++++++++++++++++++++++-- arbnode/redislock/redis.go | 21 +++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index a54336fd5..4c8bd36f7 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -16,6 +16,7 @@ import ( "time" "github.com/andybalholm/brotli" + "github.com/go-redis/redis/v8" "github.com/spf13/pflag" "github.com/ethereum/go-ethereum" @@ -117,6 +118,7 @@ type BatchPosterConfig struct { DataPoster dataposter.DataPosterConfig `koanf:"data-poster" reload:"hot"` RedisUrl string `koanf:"redis-url"` RedisLock redislock.SimpleCfg `koanf:"redis-lock" reload:"hot"` + EnableRedisLock bool `koanf:"enable-redis-lock"` ExtraBatchGas uint64 `koanf:"extra-batch-gas" reload:"hot"` ParentChainWallet genericconf.WalletConfig `koanf:"parent-chain-wallet"` L1BlockBound string `koanf:"l1-block-bound" reload:"hot"` @@ -165,6 +167,7 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".gas-refunder-address", DefaultBatchPosterConfig.GasRefunderAddress, "The gas refunder contract address (optional)") f.Uint64(prefix+".extra-batch-gas", DefaultBatchPosterConfig.ExtraBatchGas, "use this much more gas than estimation says is necessary to post batches") f.String(prefix+".redis-url", DefaultBatchPosterConfig.RedisUrl, "if non-empty, the Redis URL to store queued transactions in") + f.Bool(prefix+".enable-redis-lock", DefaultBatchPosterConfig.EnableRedisLock, "if a Redis URL is specified, ensure only one batch poster attempts to post batches at a time") f.String(prefix+".l1-block-bound", DefaultBatchPosterConfig.L1BlockBound, "only post messages to batches when they're within the max future block/timestamp as of this L1 block tag (\"safe\", \"finalized\", \"latest\", or \"ignore\" to ignore this check)") f.Duration(prefix+".l1-block-bound-bypass", DefaultBatchPosterConfig.L1BlockBoundBypass, "post batches even if not within the layer 1 future bounds if we're within this margin of the max delay") redislock.AddConfigOptions(prefix+".redis-lock", f) @@ -190,6 +193,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ L1BlockBound: "", L1BlockBoundBypass: time.Hour, RedisLock: redislock.DefaultCfg, + EnableRedisLock: true, } var DefaultBatchPosterL1WalletConfig = genericconf.WalletConfig{ @@ -215,6 +219,7 @@ var TestBatchPosterConfig = BatchPosterConfig{ ParentChainWallet: DefaultBatchPosterL1WalletConfig, L1BlockBound: "", L1BlockBoundBypass: time.Hour, + EnableRedisLock: true, } type BatchPosterOpts struct { @@ -254,7 +259,11 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e simpleRedisLockConfig.Key = batchPosterSimpleRedisLockKey return &simpleRedisLockConfig } - redisLock, err := redislock.NewSimple(redisClient, redisLockConfigFetcher, func() bool { return opts.SyncMonitor.Synced() }) + var redisClientForLock redis.UniversalClient + if opts.Config().EnableRedisLock { + redisClientForLock = redisClient + } + redisLock, err := redislock.NewSimple(redisClientForLock, redisLockConfigFetcher, func() bool { return opts.SyncMonitor.Synced() }) if err != nil { return nil, err } @@ -830,6 +839,8 @@ func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, const ethPosBlockTime = 12 * time.Second +var errAttemptLockFailed = errors.New("failed to acquire lock; either another batch poster posted a batch or this node fell behind") + func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) { if b.batchReverted.Load() { return false, fmt.Errorf("batch was reverted, not posting any more batches") @@ -1006,6 +1017,10 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) } if b.daWriter != nil { + if !b.redisLock.AttemptLock(ctx) { + return false, errAttemptLockFailed + } + cert, err := b.daWriter.Store(ctx, sequencerMsg, uint64(time.Now().Add(config.DASRetentionPeriod).Unix()), []byte{}) // b.daWriter will append signature if enabled if errors.Is(err, das.BatchToDasFailed) { if config.DisableDasFallbackStoreDataOnChain { @@ -1043,6 +1058,9 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) if err != nil { return false, err } + if !b.redisLock.AttemptLock(ctx) { + return false, errAttemptLockFailed + } tx, err := b.dataPoster.PostTransaction(ctx, firstMsgTime, nonce, @@ -1147,8 +1165,16 @@ func (b *BatchPoster) Start(ctxIn context.Context) { batchPosterWalletBalance.Update(arbmath.BalancePerEther(walletBalance)) } } - if !b.redisLock.AttemptLock(ctx) { + couldLock, err := b.redisLock.CouldAcquireLock(ctx) + if err != nil { + log.Warn("Error checking if we could acquire redis lock", "err", err) + // Might as well try, worst case we fail to lock + couldLock = true + } + if !couldLock { + log.Debug("Not posting batches right now because another batch poster has the lock or this node is behind") b.building = nil + b.firstEphemeralError = time.Time{} return b.config().PollInterval } posted, err := b.maybePostSequencerBatch(ctx) diff --git a/arbnode/redislock/redis.go b/arbnode/redislock/redis.go index c8252e059..fe4661252 100644 --- a/arbnode/redislock/redis.go +++ b/arbnode/redislock/redis.go @@ -143,6 +143,27 @@ func (l *Simple) Locked() bool { return time.Now().Before(atomicTimeRead(&l.lockedUntil)) } +// Returns true if a call to AttemptLock will likely succeed +func (l *Simple) CouldAcquireLock(ctx context.Context) (bool, error) { + if l.Locked() { + return true, nil + } + if l.stopping || !l.readyToLock() { + return false, nil + } + // l.client shouldn't be nil here because Locked would've returned true + current, err := l.client.Get(ctx, l.config().Key).Result() + if errors.Is(err, redis.Nil) { + // Lock is free for the taking + return true, nil + } + if err != nil { + return false, err + } + // return true if the lock is free for the taking or is already ours + return current == "" || current == l.myId, nil +} + func (l *Simple) Release(ctx context.Context) { l.mutex.Lock() defer l.mutex.Unlock() From 4e73be72871aa342b918c568c3439a11256278c6 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 21 Dec 2023 00:37:17 -0700 Subject: [PATCH 546/775] Always broadcast feed, even when the node isn't the sequencer --- arbnode/transaction_streamer.go | 12 ++++++------ broadcaster/broadcaster.go | 25 ++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index db0658f92..24ef2a7cc 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -862,12 +862,6 @@ func (s *TransactionStreamer) WriteMessageFromSequencer(pos arbutil.MessageIndex return err } - if s.broadcastServer != nil { - if err := s.broadcastServer.BroadcastSingle(msgWithMeta, pos); err != nil { - log.Error("failed broadcasting message", "pos", pos, "err", err) - } - } - return nil } @@ -927,6 +921,12 @@ func (s *TransactionStreamer) writeMessages(pos arbutil.MessageIndex, messages [ default: } + if s.broadcastServer != nil { + if err := s.broadcastServer.BroadcastMessages(messages, pos); err != nil { + log.Error("failed broadcasting message", "pos", pos, "err", err) + } + } + return nil } diff --git a/broadcaster/broadcaster.go b/broadcaster/broadcaster.go index 8a70e3981..38ffb0696 100644 --- a/broadcaster/broadcaster.go +++ b/broadcaster/broadcaster.go @@ -5,6 +5,7 @@ package broadcaster import ( "context" + "errors" "net" "github.com/gobwas/ws" @@ -56,10 +57,11 @@ func (b *Broadcaster) NewBroadcastFeedMessage(message arbostypes.MessageWithMeta }, nil } -func (b *Broadcaster) BroadcastSingle(msg arbostypes.MessageWithMetadata, seq arbutil.MessageIndex) error { +func (b *Broadcaster) BroadcastSingle(msg arbostypes.MessageWithMetadata, seq arbutil.MessageIndex) (err error) { defer func() { if r := recover(); r != nil { log.Error("recovered error in BroadcastSingle", "recover", r) + err = errors.New("panic in BroadcastSingle") } }() bfm, err := b.NewBroadcastFeedMessage(msg, seq) @@ -79,6 +81,27 @@ func (b *Broadcaster) BroadcastSingleFeedMessage(bfm *m.BroadcastFeedMessage) { b.BroadcastFeedMessages(broadcastFeedMessages) } +func (b *Broadcaster) BroadcastMessages(messages []arbostypes.MessageWithMetadata, seq arbutil.MessageIndex) (err error) { + defer func() { + if r := recover(); r != nil { + log.Error("recovered error in BroadcastMessages", "recover", r) + err = errors.New("panic in BroadcastMessages") + } + }() + var feedMessages []*m.BroadcastFeedMessage + for _, msg := range messages { + bfm, err := b.NewBroadcastFeedMessage(msg, seq) + if err != nil { + return err + } + feedMessages = append(feedMessages, bfm) + } + + b.BroadcastFeedMessages(feedMessages) + + return nil +} + func (b *Broadcaster) BroadcastFeedMessages(messages []*m.BroadcastFeedMessage) { bm := &m.BroadcastMessage{ From ae54e0852e53e78f6fb7fafd531bdb066dec7369 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 21 Dec 2023 00:42:56 -0700 Subject: [PATCH 547/775] Add comment about PopulateFeedBacklog in seq coordinator being redundant --- arbnode/seq_coordinator.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arbnode/seq_coordinator.go b/arbnode/seq_coordinator.go index cb6f4fe50..ecf38ddf4 100644 --- a/arbnode/seq_coordinator.go +++ b/arbnode/seq_coordinator.go @@ -650,6 +650,8 @@ func (c *SeqCoordinator) update(ctx context.Context) time.Duration { log.Warn("failed sequencing delayed messages after catching lock", "err", err) } } + // This should be redundant now that even non-primary sequencers broadcast over the feed, + // but the backlog efficiently deduplicates messages, so better safe than sorry. err = c.streamer.PopulateFeedBacklog() if err != nil { log.Warn("failed to populate the feed backlog on lockout acquisition", "err", err) From 29a8c854d4d7bdc13dfcb67299dcd5f200d7faa9 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 21 Dec 2023 00:47:13 -0700 Subject: [PATCH 548/775] Don't acquire redis lock in data poster --- arbnode/dataposter/data_poster.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 059e080ee..191fd4070 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -86,6 +86,7 @@ type signerFn func(context.Context, common.Address, *types.Transaction) (*types. type AttemptLocker interface { AttemptLock(context.Context) bool + CouldAcquireLock(context.Context) (bool, error) } func parseReplacementTimes(val string) ([]time.Duration, error) { @@ -745,9 +746,6 @@ func (p *DataPoster) Start(ctxIn context.Context) { p.CallIteratively(func(ctx context.Context) time.Duration { p.mutex.Lock() defer p.mutex.Unlock() - if !p.redisLock.AttemptLock(ctx) { - return minWait - } err := p.updateBalance(ctx) if err != nil { log.Warn("failed to update tx poster balance", "err", err) @@ -777,10 +775,16 @@ func (p *DataPoster) Start(ctxIn context.Context) { log.Error("Failed to fetch tx queue contents", "err", err) return minWait } + tryToReplace, err := p.redisLock.CouldAcquireLock(ctx) + if err != nil { + log.Warn("Error checking if we could acquire redis lock", "err", err) + // Might as well try, worst case we hit contention on redis and fail + tryToReplace = true + } for index, tx := range queueContents { backlogOfBatches := len(queueContents) - index - 1 replacing := false - if now.After(tx.NextReplacement) { + if tryToReplace && now.After(tx.NextReplacement) { replacing = true err := p.replaceTx(ctx, tx, uint64(backlogOfBatches)) p.maybeLogError(err, tx, "failed to replace-by-fee transaction") From 90ddc9286a333d74833aab8666ca96cf0abb9b83 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 21 Dec 2023 14:31:15 +0100 Subject: [PATCH 549/775] Implement test package for external signer, refactor existing tests, set chain ID in dataposter transaction --- arbnode/batch_poster.go | 20 +- arbnode/dataposter/data_poster.go | 28 ++- arbnode/dataposter/dataposter_test.go | 199 +++--------------- .../externalsignertest/externalsignertest.go | 153 ++++++++++++++ arbnode/node.go | 27 ++- arbutil/wait_for_l1.go | 1 + system_tests/batch_poster_test.go | 58 +++-- system_tests/external_signer.go | 188 ----------------- system_tests/staker_test.go | 50 +++-- 9 files changed, 316 insertions(+), 408 deletions(-) create mode 100644 arbnode/dataposter/externalsignertest/externalsignertest.go delete mode 100644 system_tests/external_signer.go diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index a54336fd5..edd9799cc 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -218,15 +218,16 @@ var TestBatchPosterConfig = BatchPosterConfig{ } type BatchPosterOpts struct { - DataPosterDB ethdb.Database - L1Reader *headerreader.HeaderReader - Inbox *InboxTracker - Streamer *TransactionStreamer - SyncMonitor *SyncMonitor - Config BatchPosterConfigFetcher - DeployInfo *chaininfo.RollupAddresses - TransactOpts *bind.TransactOpts - DAWriter das.DataAvailabilityServiceWriter + DataPosterDB ethdb.Database + L1Reader *headerreader.HeaderReader + Inbox *InboxTracker + Streamer *TransactionStreamer + SyncMonitor *SyncMonitor + Config BatchPosterConfigFetcher + DeployInfo *chaininfo.RollupAddresses + TransactOpts *bind.TransactOpts + DAWriter das.DataAvailabilityServiceWriter + ParentChainID *big.Int } func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, error) { @@ -291,6 +292,7 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e MetadataRetriever: b.getBatchPosterPosition, ExtraBacklog: b.GetBacklogEstimate, RedisKey: "data-poster.queue", + ParentChainID: opts.ParentChainID, }) if err != nil { return nil, err diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index d5b67505f..c8a071805 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -64,6 +64,7 @@ type DataPoster struct { replacementTimes []time.Duration metadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error) extraBacklog func() uint64 + parentChainID *big.Int // These fields are protected by the mutex. // TODO: factor out these fields into separate structure, since now one @@ -120,6 +121,7 @@ type DataPosterOpts struct { MetadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error) ExtraBacklog func() uint64 RedisKey string // Redis storage key + ParentChainID *big.Int } func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, error) { @@ -180,6 +182,7 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro errorCount: make(map[uint64]int), maxFeeCapExpression: expression, extraBacklog: opts.ExtraBacklog, + parentChainID: opts.ParentChainID, } if dp.extraBacklog == nil { dp.extraBacklog = func() uint64 { return 0 } @@ -197,6 +200,7 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro }, } } + return dp, nil } @@ -240,10 +244,11 @@ func rpcClient(ctx context.Context, opts *ExternalSignerCfg) (*rpc.Client, error // txToSendTxArgs converts transaction to SendTxArgs. This is needed for // external signer to specify From field. func txToSendTxArgs(addr common.Address, tx *types.Transaction) (*apitypes.SendTxArgs, error) { - if tx.To() == nil { - return nil, fmt.Errorf("transaction %v has no destination", tx.Hash()) + var to *common.MixedcaseAddress + if tx.To() != nil { + to = new(common.MixedcaseAddress) + *to = common.NewMixedcaseAddress(*tx.To()) } - to := common.NewMixedcaseAddress(*tx.To()) data := (hexutil.Bytes)(tx.Data()) val := (*hexutil.Big)(tx.Value()) if val == nil { @@ -252,7 +257,7 @@ func txToSendTxArgs(addr common.Address, tx *types.Transaction) (*apitypes.SendT al := tx.AccessList() return &apitypes.SendTxArgs{ From: common.NewMixedcaseAddress(addr), - To: &to, + To: to, Gas: hexutil.Uint64(tx.Gas()), GasPrice: (*hexutil.Big)(tx.GasPrice()), MaxFeePerGas: (*hexutil.Big)(tx.GasFeeCap()), @@ -288,17 +293,17 @@ func externalSigner(ctx context.Context, opts *ExternalSignerCfg) (signerFn, com return nil, fmt.Errorf("error converting transaction to sendTxArgs: %w", err) } if err := client.CallContext(ctx, &data, opts.Method, args); err != nil { - return nil, fmt.Errorf("signing transaction: %w", err) + return nil, fmt.Errorf("making signing request to external signer: %w", err) } - var signedTx types.Transaction - if err := rlp.DecodeBytes(data, &signedTx); err != nil { - return nil, fmt.Errorf("error decoding signed transaction: %w", err) + signedTx := &types.Transaction{} + if err := signedTx.UnmarshalBinary(data); err != nil { + return nil, fmt.Errorf("unmarshaling signed transaction: %w", err) } hasher := types.LatestSignerForChainID(tx.ChainId()) - if h := hasher.Hash(args.ToTransaction()); h != hasher.Hash(&signedTx) { - return nil, fmt.Errorf("transaction: %x from external signer differs from request: %x", hasher.Hash(&signedTx), h) + if h := hasher.Hash(args.ToTransaction()); h != hasher.Hash(signedTx) { + return nil, fmt.Errorf("transaction: %x from external signer differs from request: %x", hasher.Hash(signedTx), h) } - return &signedTx, nil + return signedTx, nil }, sender, nil } @@ -583,6 +588,7 @@ func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Tim Value: value, Data: calldata, AccessList: accessList, + ChainID: p.parentChainID, } fullTx, err := p.signer(ctx, p.Sender(), types.NewTx(&inner)) if err != nil { diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index e8028963f..3d7fa60dc 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -2,27 +2,18 @@ package dataposter import ( "context" - "crypto/tls" - "crypto/x509" - "encoding/json" "fmt" - "io" "math/big" "net/http" - "os" "testing" "time" "github.com/Knetic/govaluate" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/google/go-cmp/cmp" + "github.com/offchainlabs/nitro/arbnode/dataposter/externalsignertest" ) func TestParseReplacementTimes(t *testing.T) { @@ -60,9 +51,24 @@ func TestParseReplacementTimes(t *testing.T) { } } +func signerTestCfg(addr common.Address) (*ExternalSignerCfg, error) { + cp, err := externalsignertest.CertPaths() + if err != nil { + return nil, fmt.Errorf("getting certificates path: %w", err) + } + return &ExternalSignerCfg{ + Address: common.Bytes2Hex(addr.Bytes()), + URL: externalsignertest.SignerURL, + Method: externalsignertest.SignerMethod, + RootCA: cp.ServerCert, + ClientCert: cp.ClientCert, + ClientPrivateKey: cp.ClientKey, + }, nil +} + func TestExternalSigner(t *testing.T) { ctx := context.Background() - httpSrv, srv := newServer(ctx, t) + httpSrv, srv := externalsignertest.NewServer(ctx, t) t.Cleanup(func() { if err := httpSrv.Shutdown(ctx); err != nil { t.Fatalf("Error shutting down http server: %v", err) @@ -76,19 +82,25 @@ func TestExternalSigner(t *testing.T) { return } }() - signer, addr, err := externalSigner(ctx, - &ExternalSignerCfg{ - Address: srv.address.Hex(), - URL: "https://localhost:1234", - Method: "test_signTransaction", - RootCA: cert, - ClientCert: "./testdata/client.crt", - ClientPrivateKey: "./testdata/client.key", - }) + signerCfg, err := signerTestCfg(srv.Address) + if err != nil { + t.Fatalf("Error getting signer test config: %v", err) + } + signer, addr, err := externalSigner(ctx, signerCfg) if err != nil { t.Fatalf("Error getting external signer: %v", err) } - tx := types.NewTransaction(13, common.HexToAddress("0x01"), big.NewInt(1), 2, big.NewInt(3), []byte{0x01, 0x02, 0x03}) + tx := types.NewTx( + &types.DynamicFeeTx{ + Nonce: 13, + GasTipCap: big.NewInt(1), + GasFeeCap: big.NewInt(1), + Gas: 3, + To: nil, + Value: big.NewInt(1), + Data: []byte{0x01, 0x02, 0x03}, + }, + ) got, err := signer(ctx, addr, tx) if err != nil { t.Fatalf("Error signing transaction with external signer: %v", err) @@ -97,7 +109,7 @@ func TestExternalSigner(t *testing.T) { if err != nil { t.Fatalf("Error converting transaction to sendTxArgs: %v", err) } - want, err := srv.signerFn(addr, args.ToTransaction()) + want, err := srv.SignerFn(addr, args.ToTransaction()) if err != nil { t.Fatalf("Error signing transaction: %v", err) } @@ -106,149 +118,6 @@ func TestExternalSigner(t *testing.T) { } } -type server struct { - handlers map[string]func(*json.RawMessage) (string, error) - signerFn bind.SignerFn - address common.Address -} - -type request struct { - ID *json.RawMessage `json:"id"` - Method string `json:"method"` - Params *json.RawMessage `json:"params"` -} - -type response struct { - ID *json.RawMessage `json:"id"` - Result string `json:"result,omitempty"` -} - -// newServer returns http server and server struct that implements RPC methods. -// It sets up an account in temporary directory and cleans up after test is -// done. -func newServer(ctx context.Context, t *testing.T) (*http.Server, *server) { - t.Helper() - signer, address, err := setupAccount("/tmp/keystore") - if err != nil { - t.Fatalf("Error setting up account: %v", err) - } - t.Cleanup(func() { os.RemoveAll("/tmp/keystore") }) - - s := &server{signerFn: signer, address: address} - s.handlers = map[string]func(*json.RawMessage) (string, error){ - "test_signTransaction": s.signTransaction, - } - m := http.NewServeMux() - - clientCert, err := os.ReadFile("./testdata/client.crt") - if err != nil { - t.Fatalf("Error reading client certificate: %v", err) - } - pool := x509.NewCertPool() - pool.AppendCertsFromPEM(clientCert) - - httpSrv := &http.Server{ - Addr: ":1234", - Handler: m, - ReadTimeout: 5 * time.Second, - TLSConfig: &tls.Config{ - MinVersion: tls.VersionTLS12, - ClientAuth: tls.RequireAndVerifyClientCert, - ClientCAs: pool, - }, - } - m.HandleFunc("/", s.mux) - return httpSrv, s -} - -// setupAccount creates a new account in a given directory, unlocks it, creates -// signer with that account and returns it along with account address. -func setupAccount(dir string) (bind.SignerFn, common.Address, error) { - ks := keystore.NewKeyStore( - dir, - keystore.StandardScryptN, - keystore.StandardScryptP, - ) - a, err := ks.NewAccount("password") - if err != nil { - return nil, common.Address{}, fmt.Errorf("creating account account: %w", err) - } - if err := ks.Unlock(a, "password"); err != nil { - return nil, common.Address{}, fmt.Errorf("unlocking account: %w", err) - } - txOpts, err := bind.NewKeyStoreTransactorWithChainID(ks, a, big.NewInt(1)) - if err != nil { - return nil, common.Address{}, fmt.Errorf("creating transactor: %w", err) - } - return txOpts.Signer, a.Address, nil -} - -// UnmarshallFirst unmarshalls slice of params and returns the first one. -// Parameters in Go ethereum RPC calls are marashalled as slices. E.g. -// eth_sendRawTransaction or eth_signTransaction, marshall transaction as a -// slice of transactions in a message: -// https://github.com/ethereum/go-ethereum/blob/0004c6b229b787281760b14fb9460ffd9c2496f1/rpc/client.go#L548 -func unmarshallFirst(params []byte) (*types.Transaction, error) { - var arr []apitypes.SendTxArgs - if err := json.Unmarshal(params, &arr); err != nil { - return nil, fmt.Errorf("unmarshaling first param: %w", err) - } - if len(arr) != 1 { - return nil, fmt.Errorf("argument should be a single transaction, but got: %d", len(arr)) - } - return arr[0].ToTransaction(), nil -} - -func (s *server) signTransaction(params *json.RawMessage) (string, error) { - tx, err := unmarshallFirst(*params) - if err != nil { - return "", err - } - signedTx, err := s.signerFn(s.address, tx) - if err != nil { - return "", fmt.Errorf("signing transaction: %w", err) - } - data, err := rlp.EncodeToBytes(signedTx) - if err != nil { - return "", fmt.Errorf("rlp encoding transaction: %w", err) - } - return hexutil.Encode(data), nil -} - -func (s *server) mux(w http.ResponseWriter, r *http.Request) { - body, err := io.ReadAll(r.Body) - if err != nil { - http.Error(w, "can't read body", http.StatusBadRequest) - return - } - var req request - if err := json.Unmarshal(body, &req); err != nil { - http.Error(w, "can't unmarshal JSON request", http.StatusBadRequest) - return - } - method, ok := s.handlers[req.Method] - if !ok { - http.Error(w, "method not found", http.StatusNotFound) - return - } - result, err := method(req.Params) - if err != nil { - fmt.Printf("error calling method: %v\n", err) - http.Error(w, "error calling method", http.StatusInternalServerError) - return - } - resp := response{ID: req.ID, Result: result} - respBytes, err := json.Marshal(resp) - if err != nil { - http.Error(w, fmt.Sprintf("error encoding response: %v", err), http.StatusInternalServerError) - return - } - w.Header().Set("Content-Type", "application/json") - if _, err := w.Write(respBytes); err != nil { - fmt.Printf("error writing response: %v\n", err) - } -} - func TestMaxFeeCapFormulaCalculation(t *testing.T) { // This test alerts, by failing, if the max fee cap formula were to be changed in the DefaultDataPosterConfig to // use new variables other than the ones that are keys of 'parameters' map below diff --git a/arbnode/dataposter/externalsignertest/externalsignertest.go b/arbnode/dataposter/externalsignertest/externalsignertest.go new file mode 100644 index 000000000..7d15515fe --- /dev/null +++ b/arbnode/dataposter/externalsignertest/externalsignertest.go @@ -0,0 +1,153 @@ +package externalsignertest + +import ( + "context" + "crypto/tls" + "crypto/x509" + "fmt" + "math/big" + "net/http" + "os" + "path/filepath" + "runtime" + "strings" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/signer/core/apitypes" +) + +var ( + dataPosterPath = "arbnode/dataposter" + selfPath = filepath.Join(dataPosterPath, "externalsignertest") + + SignerPort = 1234 + SignerURL = fmt.Sprintf("https://localhost:%v", SignerPort) + SignerMethod = "test_signTransaction" +) + +type CertAbsPaths struct { + ServerCert string + ServerKey string + ClientCert string + ClientKey string +} + +func basePath() (string, error) { + _, file, _, ok := runtime.Caller(1) + if !ok { + return "", fmt.Errorf("error getting caller") + } + idx := strings.Index(file, selfPath) + if idx == -1 { + return "", fmt.Errorf("error determining base path, selfPath: %q is not substring of current file path: %q", selfPath, file) + } + return file[:idx], nil +} + +func testDataPath() (string, error) { + base, err := basePath() + if err != nil { + return "", fmt.Errorf("getting base path: %w", err) + } + return filepath.Join(base, dataPosterPath, "testdata"), nil +} + +func CertPaths() (*CertAbsPaths, error) { + td, err := testDataPath() + if err != nil { + return nil, fmt.Errorf("getting test data path: %w", err) + } + return &CertAbsPaths{ + ServerCert: filepath.Join(td, "localhost.crt"), + ServerKey: filepath.Join(td, "localhost.key"), + ClientCert: filepath.Join(td, "client.crt"), + ClientKey: filepath.Join(td, "client.key"), + }, nil +} + +func NewServer(ctx context.Context, t *testing.T) (*http.Server, *SignerAPI) { + rpcServer := rpc.NewServer() + signer, address, err := setupAccount("/tmp/keystore") + if err != nil { + t.Fatalf("Error setting up account: %v", err) + } + t.Cleanup(func() { os.RemoveAll("/tmp/keystore") }) + s := &SignerAPI{SignerFn: signer, Address: address} + if err := rpcServer.RegisterName("test", s); err != nil { + t.Fatalf("Failed to register EthSigningAPI, error: %v", err) + } + cp, err := CertPaths() + if err != nil { + t.Fatalf("Error getting certificate paths: %v", err) + } + clientCert, err := os.ReadFile(cp.ClientCert) + if err != nil { + t.Fatalf("Error reading client certificate: %v", err) + } + pool := x509.NewCertPool() + pool.AppendCertsFromPEM(clientCert) + + httpServer := &http.Server{ + Addr: fmt.Sprintf(":%d", SignerPort), + Handler: rpcServer, + ReadTimeout: 30 * time.Second, + ReadHeaderTimeout: 30 * time.Second, + WriteTimeout: 30 * time.Second, + IdleTimeout: 120 * time.Second, + TLSConfig: &tls.Config{ + MinVersion: tls.VersionTLS12, + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: pool, + }, + } + + return httpServer, s +} + +// setupAccount creates a new account in a given directory, unlocks it, creates +// signer with that account and returns it along with account address. +func setupAccount(dir string) (bind.SignerFn, common.Address, error) { + ks := keystore.NewKeyStore( + dir, + keystore.StandardScryptN, + keystore.StandardScryptP, + ) + a, err := ks.NewAccount("password") + if err != nil { + return nil, common.Address{}, fmt.Errorf("creating account account: %w", err) + } + if err := ks.Unlock(a, "password"); err != nil { + return nil, common.Address{}, fmt.Errorf("unlocking account: %w", err) + } + txOpts, err := bind.NewKeyStoreTransactorWithChainID(ks, a, big.NewInt(1337)) + if err != nil { + return nil, common.Address{}, fmt.Errorf("creating transactor: %w", err) + } + return txOpts.Signer, a.Address, nil +} + +type SignerAPI struct { + SignerFn bind.SignerFn + Address common.Address +} + +func (a *SignerAPI) SignTransaction(ctx context.Context, req *apitypes.SendTxArgs) (hexutil.Bytes, error) { + if req == nil { + return nil, fmt.Errorf("nil request") + } + signedTx, err := a.SignerFn(a.Address, req.ToTransaction()) + if err != nil { + return nil, fmt.Errorf("signing transaction: %w", err) + } + signedTxBytes, err := signedTx.MarshalBinary() + if err != nil { + return nil, fmt.Errorf("marshaling signed transaction: %w", err) + } + return signedTxBytes, nil +} diff --git a/arbnode/node.go b/arbnode/node.go index 8be2a982c..4c2da8a6d 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -301,6 +301,7 @@ func checkArbDbSchemaVersion(arbDb ethdb.Database) error { func StakerDataposter( ctx context.Context, db ethdb.Database, l1Reader *headerreader.HeaderReader, transactOpts *bind.TransactOpts, cfgFetcher ConfigFetcher, syncMonitor *SyncMonitor, + parentChainID *big.Int, ) (*dataposter.DataPoster, error) { cfg := cfgFetcher.Get() if transactOpts == nil && cfg.Staker.DataPoster.ExternalSigner.URL == "" { @@ -339,6 +340,7 @@ func StakerDataposter( Config: dpCfg, MetadataRetriever: mdRetriever, RedisKey: sender + ".staker-data-poster.queue", + ParentChainID: parentChainID, }) } @@ -568,6 +570,11 @@ func createNodeImpl( var stakerObj *staker.Staker var messagePruner *MessagePruner + parentChainID, err := l1client.ChainID(ctx) + if err != nil { + return nil, fmt.Errorf("getting parent chain id: %w", err) + } + if config.Staker.Enable { dp, err := StakerDataposter( ctx, @@ -576,6 +583,7 @@ func createNodeImpl( txOptsValidator, configFetcher, syncMonitor, + parentChainID, ) if err != nil { return nil, err @@ -643,15 +651,16 @@ func createNodeImpl( return nil, errors.New("batchposter, but no TxOpts") } batchPoster, err = NewBatchPoster(ctx, &BatchPosterOpts{ - DataPosterDB: rawdb.NewTable(arbDb, storage.BatchPosterPrefix), - L1Reader: l1Reader, - Inbox: inboxTracker, - Streamer: txStreamer, - SyncMonitor: syncMonitor, - Config: func() *BatchPosterConfig { return &configFetcher.Get().BatchPoster }, - DeployInfo: deployInfo, - TransactOpts: txOptsBatchPoster, - DAWriter: daWriter, + DataPosterDB: rawdb.NewTable(arbDb, storage.BatchPosterPrefix), + L1Reader: l1Reader, + Inbox: inboxTracker, + Streamer: txStreamer, + SyncMonitor: syncMonitor, + Config: func() *BatchPosterConfig { return &configFetcher.Get().BatchPoster }, + DeployInfo: deployInfo, + TransactOpts: txOptsBatchPoster, + DAWriter: daWriter, + ParentChainID: parentChainID, }) if err != nil { return nil, err diff --git a/arbutil/wait_for_l1.go b/arbutil/wait_for_l1.go index 12d494a23..b66710dbf 100644 --- a/arbutil/wait_for_l1.go +++ b/arbutil/wait_for_l1.go @@ -24,6 +24,7 @@ type L1Interface interface { TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) BlockNumber(ctx context.Context) (uint64, error) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) + ChainID(ctx context.Context) (*big.Int, error) } func SendTxAsCall(ctx context.Context, client L1Interface, tx *types.Transaction, from common.Address, blockNum *big.Int, unlimitedGas bool) ([]byte, error) { diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 873a87c6f..f7bf74f69 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -20,6 +20,8 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/arbnode/dataposter" + "github.com/offchainlabs/nitro/arbnode/dataposter/externalsignertest" "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" "github.com/offchainlabs/nitro/util/redisutil" @@ -60,10 +62,29 @@ func addNewBatchPoster(ctx context.Context, t *testing.T, builder *NodeBuilder, } } +func externalSignerTestCfg(addr common.Address) (*dataposter.ExternalSignerCfg, error) { + cp, err := externalsignertest.CertPaths() + if err != nil { + return nil, fmt.Errorf("getting certificates path: %w", err) + } + return &dataposter.ExternalSignerCfg{ + Address: common.Bytes2Hex(addr.Bytes()), + URL: externalsignertest.SignerURL, + Method: externalsignertest.SignerMethod, + RootCA: cp.ServerCert, + ClientCert: cp.ClientCert, + ClientPrivateKey: cp.ClientKey, + }, nil +} + func testBatchPosterParallel(t *testing.T, useRedis bool) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - httpSrv, srv := newServer(ctx, t) + httpSrv, srv := externalsignertest.NewServer(ctx, t) + cp, err := externalsignertest.CertPaths() + if err != nil { + t.Fatalf("Error getting cert paths: %v", err) + } t.Cleanup(func() { if err := httpSrv.Shutdown(ctx); err != nil { t.Fatalf("Error shutting down http server: %v", err) @@ -71,7 +92,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { }) go func() { log.Debug("Server is listening on port 1234...") - if err := httpSrv.ListenAndServeTLS(signerServerCert, signerServerKey); err != nil && err != http.ErrServerClosed { + if err := httpSrv.ListenAndServeTLS(cp.ServerCert, cp.ServerKey); err != nil && err != http.ErrServerClosed { log.Debug("ListenAndServeTLS() failed", "error", err) return } @@ -93,7 +114,11 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { builder := NewNodeBuilder(ctx).DefaultConfig(t, true) builder.nodeConfig.BatchPoster.Enable = false builder.nodeConfig.BatchPoster.RedisUrl = redisUrl - builder.nodeConfig.BatchPoster.DataPoster.ExternalSigner = *externalSignerTestCfg(srv.address) + signerCfg, err := externalSignerTestCfg(srv.Address) + if err != nil { + t.Fatalf("Error getting external signer config: %v", err) + } + builder.nodeConfig.BatchPoster.DataPoster.ExternalSigner = *signerCfg cleanup := builder.Build(t) defer cleanup() @@ -101,10 +126,10 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { defer cleanupB() builder.L2Info.GenerateAccount("User2") - addNewBatchPoster(ctx, t, builder, srv.address) + addNewBatchPoster(ctx, t, builder, srv.Address) builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ - builder.L1Info.PrepareTxTo("Faucet", &srv.address, 30000, big.NewInt(1e18), nil)}) + builder.L1Info.PrepareTxTo("Faucet", &srv.Address, 30000, big.NewInt(1e18), nil)}) var txs []*types.Transaction @@ -128,20 +153,25 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { builder.nodeConfig.BatchPoster.MaxSize = len(firstTxData) * 2 startL1Block, err := builder.L1.Client.BlockNumber(ctx) Require(t, err) + parentChainID, err := builder.L1.Client.ChainID(ctx) + if err != nil { + t.Fatalf("Failed to get parent chain id: %v", err) + } for i := 0; i < parallelBatchPosters; i++ { // Make a copy of the batch poster config so NewBatchPoster calling Validate() on it doesn't race batchPosterConfig := builder.nodeConfig.BatchPoster batchPoster, err := arbnode.NewBatchPoster(ctx, &arbnode.BatchPosterOpts{ - DataPosterDB: nil, - L1Reader: builder.L2.ConsensusNode.L1Reader, - Inbox: builder.L2.ConsensusNode.InboxTracker, - Streamer: builder.L2.ConsensusNode.TxStreamer, - SyncMonitor: builder.L2.ConsensusNode.SyncMonitor, - Config: func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, - DeployInfo: builder.L2.ConsensusNode.DeployInfo, - TransactOpts: &seqTxOpts, - DAWriter: nil, + DataPosterDB: nil, + L1Reader: builder.L2.ConsensusNode.L1Reader, + Inbox: builder.L2.ConsensusNode.InboxTracker, + Streamer: builder.L2.ConsensusNode.TxStreamer, + SyncMonitor: builder.L2.ConsensusNode.SyncMonitor, + Config: func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, + DeployInfo: builder.L2.ConsensusNode.DeployInfo, + TransactOpts: &seqTxOpts, + DAWriter: nil, + ParentChainID: parentChainID, }, ) Require(t, err) diff --git a/system_tests/external_signer.go b/system_tests/external_signer.go deleted file mode 100644 index 1ee9c8558..000000000 --- a/system_tests/external_signer.go +++ /dev/null @@ -1,188 +0,0 @@ -package arbtest - -import ( - "context" - "crypto/tls" - "crypto/x509" - "encoding/json" - "fmt" - "io" - "math/big" - "net/http" - "os" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/signer/core/apitypes" - "github.com/offchainlabs/nitro/arbnode/dataposter" -) - -var ( - signerPort = 1234 - signerURL = fmt.Sprintf("https://localhost:%v", signerPort) - signerMethod = "test_signTransaction" - signerServerCert = "../arbnode/dataposter/testdata/localhost.crt" - signerServerKey = "../arbnode/dataposter/testdata/localhost.key" - signerClientCert = "../arbnode/dataposter/testdata/client.crt" - signerClientPrivateKey = "../arbnode/dataposter/testdata/client.key" -) - -func externalSignerTestCfg(addr common.Address) *dataposter.ExternalSignerCfg { - return &dataposter.ExternalSignerCfg{ - Address: common.Bytes2Hex(addr.Bytes()), - URL: signerURL, - Method: signerMethod, - RootCA: signerServerCert, - ClientCert: signerClientCert, - ClientPrivateKey: signerClientPrivateKey, - } -} - -type server struct { - handlers map[string]func(*json.RawMessage) (string, error) - signerFn bind.SignerFn - address common.Address -} - -type request struct { - ID *json.RawMessage `json:"id"` - Method string `json:"method"` - Params *json.RawMessage `json:"params"` -} - -type response struct { - ID *json.RawMessage `json:"id"` - Result string `json:"result,omitempty"` -} - -// newServer returns http server and server struct that implements RPC methods. -// It sets up an account in temporary directory and cleans up after test is -// done. -func newServer(ctx context.Context, t *testing.T) (*http.Server, *server) { - t.Helper() - signer, address, err := setupAccount("/tmp/keystore") - if err != nil { - t.Fatalf("Error setting up account: %v", err) - } - t.Cleanup(func() { os.RemoveAll("/tmp/keystore") }) - - s := &server{signerFn: signer, address: address} - s.handlers = map[string]func(*json.RawMessage) (string, error){ - signerMethod: s.signTransaction, - } - m := http.NewServeMux() - - clientCert, err := os.ReadFile(signerClientCert) - if err != nil { - t.Fatalf("Error reading client certificate: %v", err) - } - pool := x509.NewCertPool() - pool.AppendCertsFromPEM(clientCert) - - httpSrv := &http.Server{ - Addr: fmt.Sprintf(":%v", signerPort), - Handler: m, - ReadTimeout: 5 * time.Second, - TLSConfig: &tls.Config{ - MinVersion: tls.VersionTLS12, - ClientAuth: tls.RequireAndVerifyClientCert, - ClientCAs: pool, - }, - } - m.HandleFunc("/", s.mux) - return httpSrv, s -} - -// setupAccount creates a new account in a given directory, unlocks it, creates -// signer with that account and returns it along with account address. -func setupAccount(dir string) (bind.SignerFn, common.Address, error) { - ks := keystore.NewKeyStore( - dir, - keystore.StandardScryptN, - keystore.StandardScryptP, - ) - a, err := ks.NewAccount("password") - if err != nil { - return nil, common.Address{}, fmt.Errorf("creating account account: %w", err) - } - if err := ks.Unlock(a, "password"); err != nil { - return nil, common.Address{}, fmt.Errorf("unlocking account: %w", err) - } - txOpts, err := bind.NewKeyStoreTransactorWithChainID(ks, a, big.NewInt(1337)) - if err != nil { - return nil, common.Address{}, fmt.Errorf("creating transactor: %w", err) - } - return txOpts.Signer, a.Address, nil -} - -// UnmarshallFirst unmarshalls slice of params and returns the first one. -// Parameters in Go ethereum RPC calls are marashalled as slices. E.g. -// eth_sendRawTransaction or eth_signTransaction, marshall transaction as a -// slice of transactions in a message: -// https://github.com/ethereum/go-ethereum/blob/0004c6b229b787281760b14fb9460ffd9c2496f1/rpc/client.go#L548 -func unmarshallFirst(params []byte) (*types.Transaction, error) { - var arr []apitypes.SendTxArgs - if err := json.Unmarshal(params, &arr); err != nil { - return nil, fmt.Errorf("unmarshaling first param: %w", err) - } - if len(arr) != 1 { - return nil, fmt.Errorf("argument should be a single transaction, but got: %d", len(arr)) - } - return arr[0].ToTransaction(), nil -} - -func (s *server) signTransaction(params *json.RawMessage) (string, error) { - tx, err := unmarshallFirst(*params) - if err != nil { - return "", err - } - signedTx, err := s.signerFn(s.address, tx) - if err != nil { - return "", fmt.Errorf("signing transaction: %w", err) - } - data, err := rlp.EncodeToBytes(signedTx) - if err != nil { - return "", fmt.Errorf("rlp encoding transaction: %w", err) - } - return hexutil.Encode(data), nil -} - -func (s *server) mux(w http.ResponseWriter, r *http.Request) { - body, err := io.ReadAll(r.Body) - if err != nil { - http.Error(w, "can't read body", http.StatusBadRequest) - return - } - var req request - if err := json.Unmarshal(body, &req); err != nil { - http.Error(w, "can't unmarshal JSON request", http.StatusBadRequest) - return - } - method, ok := s.handlers[req.Method] - if !ok { - http.Error(w, "method not found", http.StatusNotFound) - return - } - result, err := method(req.Params) - if err != nil { - fmt.Printf("error calling method: %v\n", err) - http.Error(w, "error calling method", http.StatusInternalServerError) - return - } - resp := response{ID: req.ID, Result: result} - respBytes, err := json.Marshal(resp) - if err != nil { - http.Error(w, fmt.Sprintf("error encoding response: %v", err), http.StatusInternalServerError) - return - } - w.Header().Set("Content-Type", "application/json") - if _, err := w.Write(respBytes); err != nil { - fmt.Printf("error writing response: %v\n", err) - } -} diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index ce726dcf8..6e3ffd612 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -27,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/arbnode/dataposter/externalsignertest" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/solgen/go/mocksgen" @@ -60,7 +61,11 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) t.Parallel() ctx, cancelCtx := context.WithCancel(context.Background()) defer cancelCtx() - httpSrv, srv := newServer(ctx, t) + httpSrv, srv := externalsignertest.NewServer(ctx, t) + cp, err := externalsignertest.CertPaths() + if err != nil { + t.Fatalf("Error getting cert paths: %v", err) + } t.Cleanup(func() { if err := httpSrv.Shutdown(ctx); err != nil { t.Fatalf("Error shutting down http server: %v", err) @@ -68,7 +73,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) }) go func() { log.Debug("Server is listening on port 1234...") - if err := httpSrv.ListenAndServeTLS(signerServerCert, signerServerKey); err != nil && err != http.ErrServerClosed { + if err := httpSrv.ListenAndServeTLS(cp.ServerCert, cp.ServerKey); err != nil && err != http.ErrServerClosed { log.Debug("ListenAndServeTLS() failed", "error", err) return } @@ -86,10 +91,10 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) cleanupA := builder.Build(t) defer cleanupA() - addNewBatchPoster(ctx, t, builder, srv.address) + addNewBatchPoster(ctx, t, builder, srv.Address) builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ - builder.L1Info.PrepareTxTo("Faucet", &srv.address, 30000, big.NewInt(1).Mul(big.NewInt(1e18), big.NewInt(1e18)), nil)}) + builder.L1Info.PrepareTxTo("Faucet", &srv.Address, 30000, big.NewInt(1).Mul(big.NewInt(1e18), big.NewInt(1e18)), nil)}) l2nodeA := builder.L2.ConsensusNode execNodeA := builder.L2.ExecNode @@ -152,7 +157,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) rollupABI, err := abi.JSON(strings.NewReader(rollupgen.RollupAdminLogicABI)) Require(t, err, "unable to parse rollup ABI") - setValidatorCalldata, err := rollupABI.Pack("setValidator", []common.Address{valWalletAddrA, l1authB.From, srv.address}, []bool{true, true, true}) + setValidatorCalldata, err := rollupABI.Pack("setValidator", []common.Address{valWalletAddrA, l1authB.From, srv.Address}, []bool{true, true, true}) Require(t, err, "unable to generate setValidator calldata") tx, err := upgradeExecutor.ExecuteCall(&deployAuth, l2nodeA.DeployInfo.Rollup, setValidatorCalldata) Require(t, err, "unable to set validators") @@ -170,8 +175,18 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err) valConfig := staker.TestL1ValidatorConfig - - dpA, err := arbnode.StakerDataposter(ctx, rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeA.L1Reader, &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), nil) + parentChainID, err := builder.L1.Client.ChainID(ctx) + if err != nil { + t.Fatalf("Failed to get parent chain id: %v", err) + } + dpA, err := arbnode.StakerDataposter( + ctx, + rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), + l2nodeA.L1Reader, + &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), + nil, + parentChainID, + ) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } @@ -219,8 +234,19 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } Require(t, err) cfg := arbnode.ConfigDefaultL1NonSequencerTest() - cfg.Staker.DataPoster.ExternalSigner = *externalSignerTestCfg(srv.address) - dpB, err := arbnode.StakerDataposter(ctx, rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), l2nodeB.L1Reader, &l1authB, NewFetcherFromConfig(cfg), nil) + signerCfg, err := externalSignerTestCfg(srv.Address) + if err != nil { + t.Fatalf("Error getting external signer config: %v", err) + } + cfg.Staker.DataPoster.ExternalSigner = *signerCfg + dpB, err := arbnode.StakerDataposter( + ctx, + rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), + l2nodeB.L1Reader, + &l1authB, NewFetcherFromConfig(cfg), + nil, + parentChainID, + ) if err != nil { t.Fatalf("Error creating validator dataposter: %v", err) } @@ -385,14 +411,14 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err, "EnsureTxSucceeded failed for staker", stakerName, "tx") } if faultyStaker { - conflictInfo, err := validatorUtils.FindStakerConflict(&bind.CallOpts{}, l2nodeA.DeployInfo.Rollup, l1authA.From, srv.address, big.NewInt(1024)) + conflictInfo, err := validatorUtils.FindStakerConflict(&bind.CallOpts{}, l2nodeA.DeployInfo.Rollup, l1authA.From, srv.Address, big.NewInt(1024)) Require(t, err) if staker.ConflictType(conflictInfo.Ty) == staker.CONFLICT_TYPE_FOUND { cancelBackgroundTxs() } } if faultyStaker && !sawStakerZombie { - sawStakerZombie, err = rollup.IsZombie(&bind.CallOpts{}, srv.address) + sawStakerZombie, err = rollup.IsZombie(&bind.CallOpts{}, srv.Address) Require(t, err) } isHonestZombie, err := rollup.IsZombie(&bind.CallOpts{}, valWalletAddrA) @@ -413,7 +439,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err) } if !stakerBWasStaked { - stakerBWasStaked, err = rollup.IsStaked(&bind.CallOpts{}, srv.address) + stakerBWasStaked, err = rollup.IsStaked(&bind.CallOpts{}, srv.Address) Require(t, err) } for j := 0; j < 5; j++ { From 11d76f62213f50540c280253fc0c5dc8efe31b59 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 21 Dec 2023 10:21:31 -0700 Subject: [PATCH 550/775] Fix broadcastSegment Contains and its usage --- broadcaster/backlog/backlog.go | 2 +- wsbroadcastserver/clientconnection.go | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 851561f48..0ef32167f 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -379,7 +379,7 @@ func (s *backlogSegment) Contains(i uint64) bool { s.messagesLock.RLock() defer s.messagesLock.RUnlock() start := s.start() - if i < start || i > s.end() { + if i < start || i > s.end() || len(s.messages) == 0 { return false } diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 49cd2af7e..5e8763bd9 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -134,7 +134,10 @@ func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.Ba msgs := prevSegment.Messages() if prevSegment.Contains(uint64(cc.requestedSeqNum)) { requestedIdx := int(cc.requestedSeqNum) - int(prevSegment.Start()) - msgs = msgs[requestedIdx:] + // This might be false if messages were added after we fetched the segment's messages + if len(msgs) > requestedIdx { + msgs = msgs[requestedIdx:] + } } bm := &m.BroadcastMessage{ Version: m.V1, From 4b816bcb16ce04f20bef2a94c1e98dbd1a3cba58 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 21 Dec 2023 10:23:25 -0700 Subject: [PATCH 551/775] Further improve requestedSeqNum check --- wsbroadcastserver/clientconnection.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 5e8763bd9..82b9603a0 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -119,6 +119,7 @@ func (cc *ClientConnection) Remove() { func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.BacklogSegment) error { var prevSegment backlog.BacklogSegment + isFirstSegment := true for !backlog.IsBacklogSegmentNil(segment) { // must get the next segment before the messages to be sent are // retrieved ensures another segment is not added in between calls. @@ -132,13 +133,14 @@ func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.Ba } msgs := prevSegment.Messages() - if prevSegment.Contains(uint64(cc.requestedSeqNum)) { + if isFirstSegment && prevSegment.Contains(uint64(cc.requestedSeqNum)) { requestedIdx := int(cc.requestedSeqNum) - int(prevSegment.Start()) // This might be false if messages were added after we fetched the segment's messages - if len(msgs) > requestedIdx { + if len(msgs) >= requestedIdx { msgs = msgs[requestedIdx:] } } + isFirstSegment = false bm := &m.BroadcastMessage{ Version: m.V1, Messages: msgs, From 4eeb994a8773c374968a1e6f44d9e627875a12b2 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 21 Dec 2023 09:56:33 -0800 Subject: [PATCH 552/775] Fix help text for batch limits We switched to using geth's batch limiting rather than our own, and the help text was wrong. --- cmd/genericconf/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/genericconf/config.go b/cmd/genericconf/config.go index 6b44ace97..50aafbe22 100644 --- a/cmd/genericconf/config.go +++ b/cmd/genericconf/config.go @@ -121,6 +121,6 @@ func (c *RpcConfig) Apply(stackConf *node.Config) { } func RpcConfigAddOptions(prefix string, f *flag.FlagSet) { - f.Int(prefix+".max-batch-response-size", DefaultRpcConfig.MaxBatchResponseSize, "the maximum response size for a JSON-RPC request measured in bytes (-1 means no limit)") - f.Int(prefix+".batch-request-limit", DefaultRpcConfig.BatchRequestLimit, "the maximum number of requests in a batch") + f.Int(prefix+".max-batch-response-size", DefaultRpcConfig.MaxBatchResponseSize, "the maximum response size for a JSON-RPC request measured in bytes (0 means no limit)") + f.Int(prefix+".batch-request-limit", DefaultRpcConfig.BatchRequestLimit, "the maximum number of requests in a batch (0 means no limit)") } From 8eccd0f7a99c0e2e2bc5aed9659faa5a83e52af3 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Fri, 22 Dec 2023 22:13:08 +0530 Subject: [PATCH 553/775] Add metrics for relay backlog size and backlog size in bytes --- broadcaster/backlog/backlog.go | 36 ++++++++++++++++++++++++++++++++++ broadcaster/message/message.go | 6 ++++++ 2 files changed, 42 insertions(+) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 0ef32167f..ae38bdad1 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -19,6 +19,8 @@ var ( errOutOfBounds = errors.New("message not found in backlog") confirmedSequenceNumberGauge = metrics.NewRegisteredGauge("arb/sequencenumber/confirmed", nil) + backlogSizeInBytesGauge = metrics.NewRegisteredGauge("arb/feed/backlog/sizeinbytes", nil) + backlogSizeGauge = metrics.NewRegisteredGauge("arb/feed/backlog/size", nil) ) // Backlog defines the interface for backlog. @@ -54,6 +56,26 @@ func (b *backlog) Head() BacklogSegment { return b.head.Load() } +func (b *backlog) backlogSizeInBytes() uint64 { + if b.head.Load() == nil || b.tail.Load() == nil { + return 0 + } + headSeg := b.head.Load() + headSeg.messagesLock.RLock() + headMsg := headSeg.messages[0] + headSeg.messagesLock.RUnlock() + + tailSeg := b.tail.Load() + tailSeg.messagesLock.RLock() + tailMsg := tailSeg.messages[len(tailSeg.messages)-1] + size := tailMsg.CumulativeSumMsgSize + tailSeg.messagesLock.RUnlock() + + size -= headMsg.CumulativeSumMsgSize + size += uint64(len(headMsg.Signature) + len(headMsg.Message.Message.L2msg) + 160) + return size +} + // Append will add the given messages to the backlogSegment at head until // that segment reaches its limit. If messages remain to be added a new segment // will be created. @@ -74,6 +96,10 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { prevMsgIdx := segment.End() if segment.count() >= b.config().SegmentLimit { + segment.messagesLock.RLock() + msg.CumulativeSumMsgSize = segment.messages[len(segment.messages)-1].CumulativeSumMsgSize + segment.messagesLock.RUnlock() + nextSegment := newBacklogSegment() segment.nextSegment.Store(nextSegment) prevMsgIdx = segment.End() @@ -100,6 +126,8 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { b.messageCount.Add(1) } + backlogSizeInBytesGauge.Update(int64(b.backlogSizeInBytes())) + backlogSizeGauge.Update(int64(b.Count())) return nil } @@ -238,6 +266,8 @@ func (b *backlog) reset() { b.tail = atomic.Pointer[backlogSegment]{} b.lookupByIndex = &containers.SyncMap[uint64, *backlogSegment]{} b.messageCount.Store(0) + backlogSizeInBytesGauge.Update(0) + backlogSizeGauge.Update(0) } // BacklogSegment defines the interface for backlogSegment. @@ -361,9 +391,15 @@ func (s *backlogSegment) append(prevMsgIdx uint64, msg *m.BroadcastFeedMessage) s.messagesLock.Lock() defer s.messagesLock.Unlock() + prevCumulativeSum := uint64(0) + if len(s.messages) > 0 { + prevCumulativeSum = s.messages[len(s.messages)-1].CumulativeSumMsgSize + } if expSeqNum := prevMsgIdx + 1; prevMsgIdx == 0 || uint64(msg.SequenceNumber) == expSeqNum { + msg.UpdateCumulativeSumMsgSize(prevCumulativeSum) s.messages = append(s.messages, msg) } else if uint64(msg.SequenceNumber) > expSeqNum { + msg.UpdateCumulativeSumMsgSize(prevCumulativeSum) s.messages = nil s.messages = append(s.messages, msg) return fmt.Errorf("new message sequence number (%d) is greater than the expected sequence number (%d): %w", msg.SequenceNumber, expSeqNum, errDropSegments) diff --git a/broadcaster/message/message.go b/broadcaster/message/message.go index f436e765c..076eb9642 100644 --- a/broadcaster/message/message.go +++ b/broadcaster/message/message.go @@ -35,6 +35,12 @@ type BroadcastFeedMessage struct { SequenceNumber arbutil.MessageIndex `json:"sequenceNumber"` Message arbostypes.MessageWithMetadata `json:"message"` Signature []byte `json:"signature"` + + CumulativeSumMsgSize uint64 `json:"-"` +} + +func (m *BroadcastFeedMessage) UpdateCumulativeSumMsgSize(val uint64) { + m.CumulativeSumMsgSize += val + uint64(len(m.Signature)+len(m.Message.Message.L2msg)+160) } func (m *BroadcastFeedMessage) Hash(chainId uint64) (common.Hash, error) { From 603634df0402b76c1c2a19cda2be7585487342a0 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 22 Dec 2023 11:28:45 -0700 Subject: [PATCH 554/775] Only use redis lock for DAS, not for normal batch posting --- arbnode/batch_poster.go | 53 +++++++++++++++++++------------ arbnode/dataposter/data_poster.go | 17 +++------- arbnode/node.go | 9 ------ arbnode/redislock/redis.go | 5 ++- staker/staker.go | 3 -- 5 files changed, 41 insertions(+), 46 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 4c8bd36f7..870df2e0d 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -16,7 +16,6 @@ import ( "time" "github.com/andybalholm/brotli" - "github.com/go-redis/redis/v8" "github.com/spf13/pflag" "github.com/ethereum/go-ethereum" @@ -30,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/rlp" "github.com/offchainlabs/nitro/arbnode/dataposter" + "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbnode/redislock" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbstate" @@ -118,7 +118,6 @@ type BatchPosterConfig struct { DataPoster dataposter.DataPosterConfig `koanf:"data-poster" reload:"hot"` RedisUrl string `koanf:"redis-url"` RedisLock redislock.SimpleCfg `koanf:"redis-lock" reload:"hot"` - EnableRedisLock bool `koanf:"enable-redis-lock"` ExtraBatchGas uint64 `koanf:"extra-batch-gas" reload:"hot"` ParentChainWallet genericconf.WalletConfig `koanf:"parent-chain-wallet"` L1BlockBound string `koanf:"l1-block-bound" reload:"hot"` @@ -167,7 +166,6 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".gas-refunder-address", DefaultBatchPosterConfig.GasRefunderAddress, "The gas refunder contract address (optional)") f.Uint64(prefix+".extra-batch-gas", DefaultBatchPosterConfig.ExtraBatchGas, "use this much more gas than estimation says is necessary to post batches") f.String(prefix+".redis-url", DefaultBatchPosterConfig.RedisUrl, "if non-empty, the Redis URL to store queued transactions in") - f.Bool(prefix+".enable-redis-lock", DefaultBatchPosterConfig.EnableRedisLock, "if a Redis URL is specified, ensure only one batch poster attempts to post batches at a time") f.String(prefix+".l1-block-bound", DefaultBatchPosterConfig.L1BlockBound, "only post messages to batches when they're within the max future block/timestamp as of this L1 block tag (\"safe\", \"finalized\", \"latest\", or \"ignore\" to ignore this check)") f.Duration(prefix+".l1-block-bound-bypass", DefaultBatchPosterConfig.L1BlockBoundBypass, "post batches even if not within the layer 1 future bounds if we're within this margin of the max delay") redislock.AddConfigOptions(prefix+".redis-lock", f) @@ -193,7 +191,6 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ L1BlockBound: "", L1BlockBoundBypass: time.Hour, RedisLock: redislock.DefaultCfg, - EnableRedisLock: true, } var DefaultBatchPosterL1WalletConfig = genericconf.WalletConfig{ @@ -219,7 +216,6 @@ var TestBatchPosterConfig = BatchPosterConfig{ ParentChainWallet: DefaultBatchPosterL1WalletConfig, L1BlockBound: "", L1BlockBoundBypass: time.Hour, - EnableRedisLock: true, } type BatchPosterOpts struct { @@ -259,11 +255,7 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e simpleRedisLockConfig.Key = batchPosterSimpleRedisLockKey return &simpleRedisLockConfig } - var redisClientForLock redis.UniversalClient - if opts.Config().EnableRedisLock { - redisClientForLock = redisClient - } - redisLock, err := redislock.NewSimple(redisClientForLock, redisLockConfigFetcher, func() bool { return opts.SyncMonitor.Synced() }) + redisLock, err := redislock.NewSimple(redisClient, redisLockConfigFetcher, func() bool { return opts.SyncMonitor.Synced() }) if err != nil { return nil, err } @@ -295,7 +287,6 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e HeaderReader: opts.L1Reader, Auth: opts.TransactOpts, RedisClient: redisClient, - RedisLock: redisLock, Config: dataPosterConfigFetcher, MetadataRetriever: b.getBatchPosterPosition, ExtraBacklog: b.GetBacklogEstimate, @@ -779,6 +770,8 @@ func (b *BatchPoster) encodeAddBatch(seqNum *big.Int, prevMsgNum arbutil.Message return fullData, nil } +var ErrNormalGasEstimationFailed = errors.New("normal gas estimation failed") + func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, delayedMessages uint64, realData []byte, realNonce uint64, realAccessList types.AccessList) (uint64, error) { config := b.config() useNormalEstimation := b.dataPoster.MaxMempoolTransactions() == 1 @@ -799,7 +792,7 @@ func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, AccessList: realAccessList, }) if err != nil { - return 0, err + return 0, fmt.Errorf("%w: %w", ErrNormalGasEstimationFailed, err) } return gas + config.ExtraBatchGas, nil } @@ -1021,6 +1014,14 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) return false, errAttemptLockFailed } + gotNonce, gotMeta, err := b.dataPoster.GetNextNonceAndMeta(ctx) + if err != nil { + return false, err + } + if nonce != gotNonce || !bytes.Equal(batchPositionBytes, gotMeta) { + return false, fmt.Errorf("%w: nonce changed from %d to %d while creating batch", storage.ErrStorageRace, nonce, gotNonce) + } + cert, err := b.daWriter.Store(ctx, sequencerMsg, uint64(time.Now().Add(config.DASRetentionPeriod).Unix()), []byte{}) // b.daWriter will append signature if enabled if errors.Is(err, das.BatchToDasFailed) { if config.DisableDasFallbackStoreDataOnChain { @@ -1058,9 +1059,6 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) if err != nil { return false, err } - if !b.redisLock.AttemptLock(ctx) { - return false, errAttemptLockFailed - } tx, err := b.dataPoster.PostTransaction(ctx, firstMsgTime, nonce, @@ -1184,14 +1182,27 @@ func (b *BatchPoster) Start(ctxIn context.Context) { if err != nil { b.building = nil logLevel := log.Error - // Likely the inbox tracker just isn't caught up. - // Let's see if this error disappears naturally. if b.firstEphemeralError == (time.Time{}) { b.firstEphemeralError = time.Now() - logLevel = log.Warn - } else if time.Since(b.firstEphemeralError) < time.Minute { - logLevel = log.Warn - } else if time.Since(b.firstEphemeralError) < time.Minute*5 && strings.Contains(err.Error(), "will exceed max mempool size") { + } + // Likely the inbox tracker just isn't caught up, or there's some other ephemeral error. + // Let's see if this error disappears naturally. + sinceFirstEphemeralError := time.Since(b.firstEphemeralError) + // If the error matches one of these, it's only logged at debug for the first minute, + // then at warn for the next 4 minutes, then at error. If the error isn't one of these, + // it'll be logged at warn for the first minute, then at error. + ignoreAtFirst := errors.Is(err, dataposter.ErrExceedsMaxMempoolSize) || + errors.Is(err, storage.ErrStorageRace) || + errors.Is(err, ErrNormalGasEstimationFailed) || + errors.Is(err, AccumulatorNotFoundErr) || + errors.Is(err, context.Canceled) + if sinceFirstEphemeralError < time.Minute { + if ignoreAtFirst { + logLevel = log.Debug + } else { + logLevel = log.Warn + } + } else if sinceFirstEphemeralError < time.Minute*5 && ignoreAtFirst { logLevel = log.Warn } logLevel("error posting batch", "err", err) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 191fd4070..673fd317e 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -57,7 +57,6 @@ type DataPoster struct { client arbutil.L1Interface auth *bind.TransactOpts signer signerFn - redisLock AttemptLocker config ConfigFetcher usingNoOpStorage bool replacementTimes []time.Duration @@ -115,7 +114,6 @@ type DataPosterOpts struct { HeaderReader *headerreader.HeaderReader Auth *bind.TransactOpts RedisClient redis.UniversalClient - RedisLock AttemptLocker Config ConfigFetcher MetadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error) ExtraBacklog func() uint64 @@ -176,7 +174,6 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro replacementTimes: replacementTimes, metadataRetriever: opts.MetadataRetriever, queue: queue, - redisLock: opts.RedisLock, errorCount: make(map[uint64]int), maxFeeCapExpression: expression, extraBacklog: opts.ExtraBacklog, @@ -289,6 +286,8 @@ func (p *DataPoster) MaxMempoolTransactions() uint64 { return p.config().MaxMempoolTransactions } +var ErrExceedsMaxMempoolSize = errors.New("posting this transaction will exceed max mempool size") + // Does basic check whether posting transaction with specified nonce would // result in exceeding maximum queue length or maximum transactions in mempool. func (p *DataPoster) canPostWithNonce(ctx context.Context, nextNonce uint64) error { @@ -311,7 +310,7 @@ func (p *DataPoster) canPostWithNonce(ctx context.Context, nextNonce uint64) err return fmt.Errorf("getting nonce of a dataposter sender: %w", err) } if nextNonce >= cfg.MaxMempoolTransactions+unconfirmedNonce { - return fmt.Errorf("posting a transaction with nonce: %d will exceed max mempool size: %d, unconfirmed nonce: %d", nextNonce, cfg.MaxMempoolTransactions, unconfirmedNonce) + return fmt.Errorf("%w: transaction nonce: %d, unconfirmed nonce: %d, max mempool size: %d", ErrExceedsMaxMempoolSize, nextNonce, unconfirmedNonce, cfg.MaxMempoolTransactions) } } return nil @@ -534,7 +533,7 @@ func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Tim return nil, err } if nonce != expectedNonce { - return nil, fmt.Errorf("data poster expected next transaction to have nonce %v but was requested to post transaction with nonce %v", expectedNonce, nonce) + return nil, fmt.Errorf("%w: data poster expected next transaction to have nonce %v but was requested to post transaction with nonce %v", storage.ErrStorageRace, expectedNonce, nonce) } err = p.updateBalance(ctx) @@ -775,16 +774,10 @@ func (p *DataPoster) Start(ctxIn context.Context) { log.Error("Failed to fetch tx queue contents", "err", err) return minWait } - tryToReplace, err := p.redisLock.CouldAcquireLock(ctx) - if err != nil { - log.Warn("Error checking if we could acquire redis lock", "err", err) - // Might as well try, worst case we hit contention on redis and fail - tryToReplace = true - } for index, tx := range queueContents { backlogOfBatches := len(queueContents) - index - 1 replacing := false - if tryToReplace && now.After(tx.NextReplacement) { + if now.After(tx.NextReplacement) { replacing = true err := p.replaceTx(ctx, tx, uint64(backlogOfBatches)) p.maybeLogError(err, tx, "failed to replace-by-fee transaction") diff --git a/arbnode/node.go b/arbnode/node.go index 8be2a982c..accca10e4 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -25,7 +25,6 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbnode/dataposter" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" - "github.com/offchainlabs/nitro/arbnode/redislock" "github.com/offchainlabs/nitro/arbnode/resourcemanager" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcastclient" @@ -313,13 +312,6 @@ func StakerDataposter( if err != nil { return nil, fmt.Errorf("creating redis client from url: %w", err) } - lockCfgFetcher := func() *redislock.SimpleCfg { - return &cfg.Staker.RedisLock - } - redisLock, err := redislock.NewSimple(redisC, lockCfgFetcher, func() bool { return syncMonitor.Synced() }) - if err != nil { - return nil, err - } dpCfg := func() *dataposter.DataPosterConfig { return &cfg.Staker.DataPoster } @@ -335,7 +327,6 @@ func StakerDataposter( HeaderReader: l1Reader, Auth: transactOpts, RedisClient: redisC, - RedisLock: redisLock, Config: dpCfg, MetadataRetriever: mdRetriever, RedisKey: sender + ".staker-data-poster.queue", diff --git a/arbnode/redislock/redis.go b/arbnode/redislock/redis.go index fe4661252..09296e3c7 100644 --- a/arbnode/redislock/redis.go +++ b/arbnode/redislock/redis.go @@ -29,6 +29,7 @@ type Simple struct { } type SimpleCfg struct { + Enable bool `koanf:"enable"` MyId string `koanf:"my-id"` LockoutDuration time.Duration `koanf:"lockout-duration" reload:"hot"` RefreshDuration time.Duration `koanf:"refresh-duration" reload:"hot"` @@ -39,6 +40,7 @@ type SimpleCfg struct { type SimpleCfgFetcher func() *SimpleCfg func AddConfigOptions(prefix string, f *flag.FlagSet) { + f.Bool(prefix+".enable", DefaultCfg.Enable, "if false, always treat this as locked and don't write the lock to redis") f.String(prefix+".my-id", "", "this node's id prefix when acquiring the lock (optional)") f.Duration(prefix+".lockout-duration", DefaultCfg.LockoutDuration, "how long lock is held") f.Duration(prefix+".refresh-duration", DefaultCfg.RefreshDuration, "how long between consecutive calls to redis") @@ -60,6 +62,7 @@ func NewSimple(client redis.UniversalClient, config SimpleCfgFetcher, readyToLoc } var DefaultCfg = SimpleCfg{ + Enable: true, LockoutDuration: time.Minute, RefreshDuration: time.Second * 10, Key: "", @@ -137,7 +140,7 @@ func (l *Simple) AttemptLock(ctx context.Context) bool { } func (l *Simple) Locked() bool { - if l.client == nil { + if l.client == nil || !l.config().Enable { return true } return time.Now().Before(atomicTimeRead(&l.lockedUntil)) diff --git a/staker/staker.go b/staker/staker.go index 4f35c1bc9..5b930dde5 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -87,7 +87,6 @@ type L1ValidatorConfig struct { GasRefunderAddress string `koanf:"gas-refunder-address"` DataPoster dataposter.DataPosterConfig `koanf:"data-poster" reload:"hot"` RedisUrl string `koanf:"redis-url"` - RedisLock redislock.SimpleCfg `koanf:"redis-lock" reload:"hot"` ExtraGas uint64 `koanf:"extra-gas" reload:"hot"` Dangerous DangerousConfig `koanf:"dangerous"` ParentChainWallet genericconf.WalletConfig `koanf:"parent-chain-wallet"` @@ -154,7 +153,6 @@ var DefaultL1ValidatorConfig = L1ValidatorConfig{ GasRefunderAddress: "", DataPoster: dataposter.DefaultDataPosterConfigForValidator, RedisUrl: "", - RedisLock: redislock.DefaultCfg, ExtraGas: 50000, Dangerous: DefaultDangerousConfig, ParentChainWallet: DefaultValidatorL1WalletConfig, @@ -175,7 +173,6 @@ var TestL1ValidatorConfig = L1ValidatorConfig{ GasRefunderAddress: "", DataPoster: dataposter.TestDataPosterConfigForValidator, RedisUrl: "", - RedisLock: redislock.DefaultCfg, ExtraGas: 50000, Dangerous: DefaultDangerousConfig, ParentChainWallet: DefaultValidatorL1WalletConfig, From 063164e6be44f29f7f562129c415d9e47f8515de Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 22 Dec 2023 11:47:09 -0700 Subject: [PATCH 555/775] Fix redis lock removal from staker config --- staker/staker.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/staker/staker.go b/staker/staker.go index 5b930dde5..5fa6c400c 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -21,7 +21,6 @@ import ( flag "github.com/spf13/pflag" "github.com/offchainlabs/nitro/arbnode/dataposter" - "github.com/offchainlabs/nitro/arbnode/redislock" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/staker/txbuilder" @@ -202,7 +201,6 @@ func L1ValidatorConfigAddOptions(prefix string, f *flag.FlagSet) { f.String(prefix+".redis-url", DefaultL1ValidatorConfig.RedisUrl, "redis url for L1 validator") f.Uint64(prefix+".extra-gas", DefaultL1ValidatorConfig.ExtraGas, "use this much more gas than estimation says is necessary to post transactions") dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f, dataposter.DefaultDataPosterConfigForValidator) - redislock.AddConfigOptions(prefix+".redis-lock", f) DangerousConfigAddOptions(prefix+".dangerous", f) genericconf.WalletConfigAddOptions(prefix+".parent-chain-wallet", f, DefaultL1ValidatorConfig.ParentChainWallet.Pathname) } From 8f9bd0e3f93fa0bbf94173177e8a0d9f44164d96 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 22 Dec 2023 12:06:10 -0700 Subject: [PATCH 556/775] Fix simple redis lock test --- arbnode/simple_redis_lock_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/arbnode/simple_redis_lock_test.go b/arbnode/simple_redis_lock_test.go index b7506145c..c9dd57674 100644 --- a/arbnode/simple_redis_lock_test.go +++ b/arbnode/simple_redis_lock_test.go @@ -48,6 +48,7 @@ func simpleRedisLockTest(t *testing.T, redisKeySuffix string, chosen int, backgo Require(t, redisClient.Del(ctx, redisKey).Err()) conf := &redislock.SimpleCfg{ + Enable: true, LockoutDuration: test_delay * test_attempts * 10, RefreshDuration: test_delay * 2, Key: redisKey, From 32883f183ceb4073bffec6d6394ddd87aa36281a Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 22 Dec 2023 20:27:51 +0000 Subject: [PATCH 557/775] fix typo --- cmd/nitro/init.go | 6 +++--- .../prunning.go => pruning/pruning.go} | 2 +- .../{prunning_test.go => pruning_test.go} | 20 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) rename cmd/{prunning/prunning.go => pruning/pruning.go} (99%) rename system_tests/{prunning_test.go => pruning_test.go} (79%) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 00012ac62..ada195b5c 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -33,7 +33,7 @@ import ( "github.com/offchainlabs/nitro/cmd/chaininfo" "github.com/offchainlabs/nitro/cmd/conf" "github.com/offchainlabs/nitro/cmd/ipfshelper" - "github.com/offchainlabs/nitro/cmd/prunning" + "github.com/offchainlabs/nitro/cmd/pruning" "github.com/offchainlabs/nitro/cmd/util" "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/statetransfer" @@ -167,7 +167,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if err != nil { return chainDb, nil, err } - err = prunning.PruneChainDb(ctx, chainDb, stack, &config.Init, cacheConfig, l1Client, rollupAddrs, config.Node.ValidatorRequired()) + err = pruning.PruneChainDb(ctx, chainDb, stack, &config.Init, cacheConfig, l1Client, rollupAddrs, config.Node.ValidatorRequired()) if err != nil { return chainDb, nil, fmt.Errorf("error pruning: %w", err) } @@ -363,7 +363,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo return chainDb, l2BlockChain, err } - err = prunning.PruneChainDb(ctx, chainDb, stack, &config.Init, cacheConfig, l1Client, rollupAddrs, config.Node.ValidatorRequired()) + err = pruning.PruneChainDb(ctx, chainDb, stack, &config.Init, cacheConfig, l1Client, rollupAddrs, config.Node.ValidatorRequired()) if err != nil { return chainDb, nil, fmt.Errorf("error pruning: %w", err) } diff --git a/cmd/prunning/prunning.go b/cmd/pruning/pruning.go similarity index 99% rename from cmd/prunning/prunning.go rename to cmd/pruning/pruning.go index 5efdf8e64..68d89302f 100644 --- a/cmd/prunning/prunning.go +++ b/cmd/pruning/pruning.go @@ -1,4 +1,4 @@ -package prunning +package pruning import ( "context" diff --git a/system_tests/prunning_test.go b/system_tests/pruning_test.go similarity index 79% rename from system_tests/prunning_test.go rename to system_tests/pruning_test.go index d52245820..e6eefdabd 100644 --- a/system_tests/prunning_test.go +++ b/system_tests/pruning_test.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/node" "github.com/offchainlabs/nitro/cmd/conf" - "github.com/offchainlabs/nitro/cmd/prunning" + "github.com/offchainlabs/nitro/cmd/pruning" "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/testhelpers" ) @@ -28,7 +28,7 @@ func countStateEntries(db ethdb.Iteratee) int { return entries } -func TestPrunning(t *testing.T) { +func TestPruning(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -67,7 +67,7 @@ func TestPrunning(t *testing.T) { chainDb, err := stack.OpenDatabase("chaindb", 0, 0, "", false) Require(t, err) defer chainDb.Close() - chainDbEntriesBeforePrunning := countStateEntries(chainDb) + chainDbEntriesBeforePruning := countStateEntries(chainDb) prand := testhelpers.NewPseudoRandomDataSource(t, 1) var testKeys [][]byte @@ -88,21 +88,21 @@ func TestPrunning(t *testing.T) { initConfig := conf.InitConfigDefault initConfig.Prune = "full" coreCacheConfig := gethexec.DefaultCacheConfigFor(stack, &builder.execConfig.Caching) - err = prunning.PruneChainDb(ctx, chainDb, stack, &initConfig, coreCacheConfig, builder.L1.Client, *builder.L2.ConsensusNode.DeployInfo, false) + err = pruning.PruneChainDb(ctx, chainDb, stack, &initConfig, coreCacheConfig, builder.L1.Client, *builder.L2.ConsensusNode.DeployInfo, false) Require(t, err) for _, key := range testKeys { if has, _ := chainDb.Has(key); has { - Fatal(t, "test key hasn't been prunned as expected") + Fatal(t, "test key hasn't been pruned as expected") } } - chainDbEntriesAfterPrunning := countStateEntries(chainDb) - t.Log("db entries pre-prunning:", chainDbEntriesBeforePrunning) - t.Log("db entries post-prunning:", chainDbEntriesAfterPrunning) + chainDbEntriesAfterPruning := countStateEntries(chainDb) + t.Log("db entries pre-pruning:", chainDbEntriesBeforePruning) + t.Log("db entries post-pruning:", chainDbEntriesAfterPruning) - if chainDbEntriesAfterPrunning >= chainDbEntriesBeforePrunning { - Fatal(t, "The db doesn't have less entries after prunning then before. Before:", chainDbEntriesBeforePrunning, "After:", chainDbEntriesAfterPrunning) + if chainDbEntriesAfterPruning >= chainDbEntriesBeforePruning { + Fatal(t, "The db doesn't have less entries after pruning then before. Before:", chainDbEntriesBeforePruning, "After:", chainDbEntriesAfterPruning) } }() builder := NewNodeBuilder(ctx).DefaultConfig(t, true) From cb4d3c5374be0d9ed155fe6ed2514b27747f7366 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 22 Dec 2023 20:30:11 +0000 Subject: [PATCH 558/775] make only one test tx after pruning --- system_tests/pruning_test.go | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/system_tests/pruning_test.go b/system_tests/pruning_test.go index e6eefdabd..ef82c0466 100644 --- a/system_tests/pruning_test.go +++ b/system_tests/pruning_test.go @@ -111,15 +111,9 @@ func TestPruning(t *testing.T) { defer cancel() builder.L2Info.GenerateAccount("User2") - var txs []*types.Transaction - for i := uint64(0); i < 10; i++ { - tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) - txs = append(txs, tx) - err := builder.L2.Client.SendTransaction(ctx, tx) - Require(t, err) - } - for _, tx := range txs { - _, err := builder.L2.EnsureTxSucceeded(tx) - Require(t, err) - } + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) + err := builder.L2.Client.SendTransaction(ctx, tx) + Require(t, err) + _, err = builder.L2.EnsureTxSucceeded(tx) + Require(t, err) } From 51e9b557371048362623878df2939c3c5ffbcacd Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 22 Dec 2023 16:23:15 -0700 Subject: [PATCH 559/775] Clean up code a bit to address two comments --- arbnode/batch_poster.go | 7 +++++-- arbnode/dataposter/data_poster.go | 5 ----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 870df2e0d..8c0fdd332 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -1180,6 +1180,10 @@ func (b *BatchPoster) Start(ctxIn context.Context) { b.firstEphemeralError = time.Time{} } if err != nil { + if ctx.Err() != nil { + // Shutting down. No need to print the context canceled error. + return 0 + } b.building = nil logLevel := log.Error if b.firstEphemeralError == (time.Time{}) { @@ -1194,8 +1198,7 @@ func (b *BatchPoster) Start(ctxIn context.Context) { ignoreAtFirst := errors.Is(err, dataposter.ErrExceedsMaxMempoolSize) || errors.Is(err, storage.ErrStorageRace) || errors.Is(err, ErrNormalGasEstimationFailed) || - errors.Is(err, AccumulatorNotFoundErr) || - errors.Is(err, context.Canceled) + errors.Is(err, AccumulatorNotFoundErr) if sinceFirstEphemeralError < time.Minute { if ignoreAtFirst { logLevel = log.Debug diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 673fd317e..ff5a945a1 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -83,11 +83,6 @@ type DataPoster struct { // This can be local or external, hence the context parameter. type signerFn func(context.Context, common.Address, *types.Transaction) (*types.Transaction, error) -type AttemptLocker interface { - AttemptLock(context.Context) bool - CouldAcquireLock(context.Context) (bool, error) -} - func parseReplacementTimes(val string) ([]time.Duration, error) { var res []time.Duration var lastReplacementTime time.Duration From ce3a42560fa3a64560475c2cc927254a8ddec231 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Sat, 23 Dec 2023 07:12:36 +0530 Subject: [PATCH 560/775] fix typo --- arbnode/batch_poster.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 4c708c302..827609ee6 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -1164,7 +1164,7 @@ func (b *BatchPoster) Start(ctxIn context.Context) { // Likely the inbox tracker just isn't caught up. // Let's see if this error disappears naturally. logLevel = commonEphemeralErrorHandler.LogLevel(err, logLevel) - logLevel = commonEphemeralErrorHandler.LogLevel(err, logLevel) + logLevel = exceedMaxMempoolSizeEphemeralErrorHandler.LogLevel(err, logLevel) logLevel("error posting batch", "err", err) return b.config().ErrorDelay } else if posted { From c95a374c37742d7cfe9e247e7396765e86c1d305 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 22 Dec 2023 22:11:54 -0700 Subject: [PATCH 561/775] Stop execution node after everything else --- arbnode/node.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index accca10e4..c26d78b89 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -864,9 +864,6 @@ func (n *Node) Start(ctx context.Context) error { } func (n *Node) StopAndWait() { - if n.Execution != nil { - n.Execution.StopAndWait() - } if n.MaintenanceRunner != nil && n.MaintenanceRunner.Started() { n.MaintenanceRunner.StopAndWait() } @@ -919,7 +916,10 @@ func (n *Node) StopAndWait() { if n.DASLifecycleManager != nil { n.DASLifecycleManager.StopAndWaitUntil(2 * time.Second) } + if n.Execution != nil { + n.Execution.StopAndWait() + } if err := n.Stack.Close(); err != nil { - log.Error("error on stak close", "err", err) + log.Error("error on stack close", "err", err) } } From ac8dbc95784209c3419855bc55db0dbfaf30f150 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 22 Dec 2023 22:15:07 -0700 Subject: [PATCH 562/775] Log invalid txs in the STF when the chain is in debug mode --- arbos/block_processor.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/arbos/block_processor.go b/arbos/block_processor.go index 4864a3125..f1838132a 100644 --- a/arbos/block_processor.go +++ b/arbos/block_processor.go @@ -42,6 +42,21 @@ var EmitReedeemScheduledEvent func(*vm.EVM, uint64, uint64, [32]byte, [32]byte, var EmitTicketCreatedEvent func(*vm.EVM, [32]byte) error var gasUsedSinceStartupCounter = metrics.NewRegisteredCounter("arb/gas_used", nil) +// A helper struct that implements String() by marshalling to JSON. +// This is useful for logging because it's lazy, so if the log level is too high to print the transaction, +// it doesn't waste compute marshalling the transaction when the result wouldn't be used. +type printTxAsJson struct { + tx *types.Transaction +} + +func (p printTxAsJson) String() string { + json, err := p.tx.MarshalJSON() + if err != nil { + return fmt.Sprintf("[error marshalling tx: %v]", err) + } + return string(json) +} + type L1Info struct { poster common.Address l1BlockNumber uint64 @@ -357,7 +372,11 @@ func ProduceBlockAdvanced( hooks.TxErrors = append(hooks.TxErrors, err) if err != nil { - log.Debug("error applying transaction", "tx", tx, "err", err) + logLevel := log.Debug + if chainConfig.DebugMode() { + logLevel = log.Warn + } + logLevel("error applying transaction", "tx", printTxAsJson{tx}, "err", err) if !hooks.DiscardInvalidTxsEarly { // we'll still deduct a TxGas's worth from the block-local rate limiter even if the tx was invalid blockGasLeft = arbmath.SaturatingUSub(blockGasLeft, params.TxGas) From 279dea45f9f0edd123f2e5e7155f7275d903307a Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sat, 23 Dec 2023 11:37:06 -0700 Subject: [PATCH 563/775] Fix enabling pprof on the relay --- cmd/relay/relay.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cmd/relay/relay.go b/cmd/relay/relay.go index b25aadf57..40f4f26ee 100644 --- a/cmd/relay/relay.go +++ b/cmd/relay/relay.go @@ -6,7 +6,6 @@ package main import ( "context" "fmt" - "net/http" "os" "os/signal" "syscall" @@ -22,10 +21,6 @@ import ( "github.com/offchainlabs/nitro/relay" ) -func init() { - http.DefaultServeMux = http.NewServeMux() -} - func main() { if err := startup(); err != nil { log.Error("Error running relay", "err", err) From e0f35dd40eaefa6fff4e6077ebef58cf5d0e2e74 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sat, 23 Dec 2023 13:02:03 -0700 Subject: [PATCH 564/775] Fix memory leak in relay --- broadcaster/backlog/backlog.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 0ef32167f..461ec3a6f 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -77,7 +77,6 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { nextSegment := newBacklogSegment() segment.nextSegment.Store(nextSegment) prevMsgIdx = segment.End() - nextSegment.previousSegment.Store(segment) segment = nextSegment b.tail.Store(segment) } @@ -253,10 +252,9 @@ type BacklogSegment interface { // backlogSegment stores messages up to a limit defined by the backlog. It also // points to the next backlogSegment in the list. type backlogSegment struct { - messagesLock sync.RWMutex - messages []*m.BroadcastFeedMessage - nextSegment atomic.Pointer[backlogSegment] - previousSegment atomic.Pointer[backlogSegment] + messagesLock sync.RWMutex + messages []*m.BroadcastFeedMessage + nextSegment atomic.Pointer[backlogSegment] } // newBacklogSegment creates a backlogSegment object with an empty slice of From fd5edcb829a9c440edffcfc7961e4668c4ab9c5c Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sat, 23 Dec 2023 13:21:31 -0700 Subject: [PATCH 565/775] Fix race conditions in backlog.reset() --- broadcaster/backlog/backlog.go | 26 ++++++++++++++------------ broadcaster/backlog/backlog_test.go | 8 ++++---- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 461ec3a6f..549a38ff8 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -35,18 +35,18 @@ type Backlog interface { type backlog struct { head atomic.Pointer[backlogSegment] tail atomic.Pointer[backlogSegment] - lookupByIndex *containers.SyncMap[uint64, *backlogSegment] + lookupByIndex atomic.Pointer[containers.SyncMap[uint64, *backlogSegment]] config ConfigFetcher messageCount atomic.Uint64 } // NewBacklog creates a backlog. func NewBacklog(c ConfigFetcher) Backlog { - lookup := &containers.SyncMap[uint64, *backlogSegment]{} - return &backlog{ - lookupByIndex: lookup, - config: c, + b := &backlog{ + config: c, } + b.lookupByIndex.Store(&containers.SyncMap[uint64, *backlogSegment]{}) + return b } // Head return the head backlogSegment within the backlog. @@ -63,6 +63,7 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { b.delete(uint64(bm.ConfirmedSequenceNumberMessage.SequenceNumber)) } + lookupByIndex := b.lookupByIndex.Load() for _, msg := range bm.Messages { segment := b.tail.Load() if segment == nil { @@ -95,7 +96,7 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { } else if err != nil { return err } - b.lookupByIndex.Store(uint64(msg.SequenceNumber), segment) + lookupByIndex.Store(uint64(msg.SequenceNumber), segment) b.messageCount.Add(1) } @@ -160,7 +161,7 @@ func (b *backlog) delete(confirmed uint64) { } if confirmed > tail.End() { - log.Error("confirmed sequence number is past the end of stored messages", "confirmed sequence number", confirmed, "last stored sequence number", tail.End()) + log.Warn("confirmed sequence number is past the end of stored messages", "confirmed sequence number", confirmed, "last stored sequence number", tail.End()) b.reset() return } @@ -211,14 +212,15 @@ func (b *backlog) delete(confirmed uint64) { // removeFromLookup removes all entries from the head segment's start index to // the given confirmed index. func (b *backlog) removeFromLookup(start, end uint64) { + lookupByIndex := b.lookupByIndex.Load() for i := start; i <= end; i++ { - b.lookupByIndex.Delete(i) + lookupByIndex.Delete(i) } } // Lookup attempts to find the backlogSegment storing the given message index. func (b *backlog) Lookup(i uint64) (BacklogSegment, error) { - segment, ok := b.lookupByIndex.Load(i) + segment, ok := b.lookupByIndex.Load().Load(i) if !ok { return nil, fmt.Errorf("error finding backlog segment containing message with SequenceNumber %d", i) } @@ -233,9 +235,9 @@ func (s *backlog) Count() uint64 { // reset removes all segments from the backlog. func (b *backlog) reset() { - b.head = atomic.Pointer[backlogSegment]{} - b.tail = atomic.Pointer[backlogSegment]{} - b.lookupByIndex = &containers.SyncMap[uint64, *backlogSegment]{} + b.head.Store(nil) + b.tail.Store(nil) + b.lookupByIndex.Store(&containers.SyncMap[uint64, *backlogSegment]{}) b.messageCount.Store(0) } diff --git a/broadcaster/backlog/backlog_test.go b/broadcaster/backlog/backlog_test.go index ab25a523f..ee712de9e 100644 --- a/broadcaster/backlog/backlog_test.go +++ b/broadcaster/backlog/backlog_test.go @@ -57,9 +57,9 @@ func validateBroadcastMessage(t *testing.T, bm *m.BroadcastMessage, expectedCoun func createDummyBacklog(indexes []arbutil.MessageIndex) (*backlog, error) { b := &backlog{ - lookupByIndex: &containers.SyncMap[uint64, *backlogSegment]{}, - config: func() *Config { return &DefaultTestConfig }, + config: func() *Config { return &DefaultTestConfig }, } + b.lookupByIndex.Store(&containers.SyncMap[uint64, *backlogSegment]{}) bm := &m.BroadcastMessage{Messages: m.CreateDummyBroadcastMessages(indexes)} err := b.Append(bm) return b, err @@ -161,9 +161,9 @@ func TestDeleteInvalidBacklog(t *testing.T) { lookup := &containers.SyncMap[uint64, *backlogSegment]{} lookup.Store(40, s) b := &backlog{ - lookupByIndex: lookup, - config: func() *Config { return &DefaultTestConfig }, + config: func() *Config { return &DefaultTestConfig }, } + b.lookupByIndex.Store(lookup) b.messageCount.Store(2) b.head.Store(s) b.tail.Store(s) From d7b8d02dac1914643c17fff4ba127c425df3b718 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 24 Dec 2023 10:28:46 -0700 Subject: [PATCH 566/775] Fix Broadcaster BroadcastMessages sequence numbers --- arbnode/node.go | 2 +- broadcaster/broadcaster.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index accca10e4..951403244 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -764,7 +764,7 @@ func (n *Node) Start(ctx context.Context) error { return fmt.Errorf("error initializing feed broadcast server: %w", err) } } - if n.InboxTracker != nil && n.BroadcastServer != nil && config.Sequencer { + if n.InboxTracker != nil && n.BroadcastServer != nil { // Even if the sequencer coordinator will populate this backlog, // we want to make sure it's populated before any clients connect. err = n.InboxTracker.PopulateFeedBacklog(n.BroadcastServer) diff --git a/broadcaster/broadcaster.go b/broadcaster/broadcaster.go index 38ffb0696..ed3088ca2 100644 --- a/broadcaster/broadcaster.go +++ b/broadcaster/broadcaster.go @@ -89,8 +89,8 @@ func (b *Broadcaster) BroadcastMessages(messages []arbostypes.MessageWithMetadat } }() var feedMessages []*m.BroadcastFeedMessage - for _, msg := range messages { - bfm, err := b.NewBroadcastFeedMessage(msg, seq) + for i, msg := range messages { + bfm, err := b.NewBroadcastFeedMessage(msg, seq+arbutil.MessageIndex(i)) if err != nil { return err } From 11cd4efb596c76d5f15091cf1be167bbf9880969 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 24 Dec 2023 10:42:17 -0700 Subject: [PATCH 567/775] Fix unused variable --- arbnode/node.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 951403244..45ef7206e 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -731,8 +731,6 @@ func CreateNode( } func (n *Node) Start(ctx context.Context) error { - // config is the static config at start, not a dynamic config - config := n.configFetcher.Get() execClient, ok := n.Execution.(*gethexec.ExecutionNode) if !ok { execClient = nil From 96fe66249283f57acfa8cf55ebfd5c485b311d81 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 24 Dec 2023 11:49:03 -0700 Subject: [PATCH 568/775] Revert "Merge pull request #2018 from OffchainLabs/linters" This reverts commit 1786f770eacb3d1ceb90fc019b37f69ba198e45c, reversing changes made to fd8d0b4295e638157b102e3cff91cf41a389c35c. --- Makefile | 31 --------------------- arbos/l1pricing/l1pricing.go | 6 ++-- go.mod | 2 -- go.sum | 16 ----------- linter/comparesame/comparesame.go | 12 -------- linter/cryptorand/cryptorand.go | 13 --------- linter/errcheck/errcheck.go | 12 -------- linter/featureconfig/featureconfig.go | 12 -------- linter/gocognit/gocognit.go | 13 --------- linter/ineffassign/ineffassign.go | 12 -------- linter/interfacechecker/interfacechecker.go | 12 -------- linter/logruswitherror/logruswitherror.go | 13 --------- linter/recursivelock/recursivelock.go | 1 - linter/shadowpredecl/shadowpredecl.go | 13 --------- linter/slicedirect/slicedirect.go | 13 --------- linter/uintcast/uintcast.go | 13 --------- 16 files changed, 3 insertions(+), 191 deletions(-) delete mode 100644 linter/comparesame/comparesame.go delete mode 100644 linter/cryptorand/cryptorand.go delete mode 100644 linter/errcheck/errcheck.go delete mode 100644 linter/featureconfig/featureconfig.go delete mode 100644 linter/gocognit/gocognit.go delete mode 100644 linter/ineffassign/ineffassign.go delete mode 100644 linter/interfacechecker/interfacechecker.go delete mode 100644 linter/logruswitherror/logruswitherror.go delete mode 100644 linter/shadowpredecl/shadowpredecl.go delete mode 100644 linter/slicedirect/slicedirect.go delete mode 100644 linter/uintcast/uintcast.go diff --git a/Makefile b/Makefile index d7f4599db..42fd1e359 100644 --- a/Makefile +++ b/Makefile @@ -308,37 +308,6 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make go run ./linter/recursivelock ./... - go run ./linter/comparesame ./... - - # Disabled since we have a lot of use of math/rand package. - # We should probably move to crypto/rand at some point even though most of - # our uses doesn't seem to be security sensitive. - # TODO fix this and enable. - # go run ./linter/cryptorand ./... - - # This yields lot of legitimate warnings, most of which in practice would - # probably never happen. - # # TODO fix this and enable. - # go run ./linter/errcheck ./... - - go run ./linter/featureconfig ./... - - # Disabled since we have high cognitive complexity several places. - # TODO fix this and enable. - # go run ./linter/gocognit ./... - - go run ./linter/ineffassign ./... - go run ./linter/interfacechecker ./... - go run ./linter/logruswitherror ./... - - go run ./linter/shadowpredecl ./... - go run ./linter/slicedirect ./... - - # Disabled since it fails many places, although ones I looked into seem - # to be false positives logically. - # TODO fix this and enable and mark false positives with lint ignore. - # go run ./linter/uintcast ./... - go run ./linter/koanf ./... go run ./linter/pointercheck ./... golangci-lint run --fix diff --git a/arbos/l1pricing/l1pricing.go b/arbos/l1pricing/l1pricing.go index be5540b60..27ecae8b8 100644 --- a/arbos/l1pricing/l1pricing.go +++ b/arbos/l1pricing/l1pricing.go @@ -259,11 +259,11 @@ func (ps *L1PricingState) AddToL1FeesAvailable(delta *big.Int) (*big.Int, error) if err != nil { return nil, err } - newFee := new(big.Int).Add(old, delta) - if err := ps.SetL1FeesAvailable(newFee); err != nil { + new := new(big.Int).Add(old, delta) + if err := ps.SetL1FeesAvailable(new); err != nil { return nil, err } - return newFee, nil + return new, nil } func (ps *L1PricingState) TransferFromL1FeesAvailable( diff --git a/go.mod b/go.mod index f87887e18..e504542a2 100644 --- a/go.mod +++ b/go.mod @@ -124,7 +124,6 @@ require ( github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b // indirect github.com/gorilla/mux v1.8.0 // indirect - github.com/gostaticanalysis/comment v1.4.2 // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect github.com/h2non/filetype v1.0.6 // indirect @@ -254,7 +253,6 @@ require ( github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/urfave/cli/v2 v2.25.7 // indirect - github.com/uudashr/gocognit v1.0.5 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect diff --git a/go.sum b/go.sum index 4e3f0f62b..0a9649c43 100644 --- a/go.sum +++ b/go.sum @@ -581,9 +581,6 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= -github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= -github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= @@ -628,7 +625,6 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -1424,11 +1420,6 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.4.0 h1:CtfRrOVZtbDj8rt1WXjklw0kqqJQwICrCKmlfUuBUUw= github.com/openzipkin/zipkin-go v0.4.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0R4l6Zg0P1tTQ= -github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= -github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= -github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1637,8 +1628,6 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45 github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= -github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= @@ -1669,8 +1658,6 @@ github.com/urfave/cli/v2 v2.24.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6f github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= -github.com/uudashr/gocognit v1.0.5 h1:rrSex7oHr3/pPLQ0xoWq108XMU8s678FJcQ+aSfOHa4= -github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= @@ -1876,7 +1863,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= @@ -2153,10 +2139,8 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= diff --git a/linter/comparesame/comparesame.go b/linter/comparesame/comparesame.go deleted file mode 100644 index 1d91592e9..000000000 --- a/linter/comparesame/comparesame.go +++ /dev/null @@ -1,12 +0,0 @@ -// Static Analyzer to ensure code does not contain comparisons of identical expressions. -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/comparesame" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(comparesame.Analyzer) -} diff --git a/linter/cryptorand/cryptorand.go b/linter/cryptorand/cryptorand.go deleted file mode 100644 index a7cd1ca65..000000000 --- a/linter/cryptorand/cryptorand.go +++ /dev/null @@ -1,13 +0,0 @@ -// Static Analyzer to ensure the crypto/rand package is used for randomness -// throughout the codebase. -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/cryptorand" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(cryptorand.Analyzer) -} diff --git a/linter/errcheck/errcheck.go b/linter/errcheck/errcheck.go deleted file mode 100644 index 8275b2bab..000000000 --- a/linter/errcheck/errcheck.go +++ /dev/null @@ -1,12 +0,0 @@ -// Static analyzer to ensure that errors are handled in go code. -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/errcheck" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(errcheck.Analyzer) -} diff --git a/linter/featureconfig/featureconfig.go b/linter/featureconfig/featureconfig.go deleted file mode 100644 index bb9c2dd3a..000000000 --- a/linter/featureconfig/featureconfig.go +++ /dev/null @@ -1,12 +0,0 @@ -// Static analyzer to prevent leaking globals in tests. -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/featureconfig" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(featureconfig.Analyzer) -} diff --git a/linter/gocognit/gocognit.go b/linter/gocognit/gocognit.go deleted file mode 100644 index a50d0ac08..000000000 --- a/linter/gocognit/gocognit.go +++ /dev/null @@ -1,13 +0,0 @@ -// Static analyzer that checks for high cognitive complexity and complains when -// it's too high. -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/gocognit" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(gocognit.Analyzer) -} diff --git a/linter/ineffassign/ineffassign.go b/linter/ineffassign/ineffassign.go deleted file mode 100644 index 697e10482..000000000 --- a/linter/ineffassign/ineffassign.go +++ /dev/null @@ -1,12 +0,0 @@ -// Static analyzer for detecting ineffectual assignments. -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/ineffassign" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(ineffassign.Analyzer) -} diff --git a/linter/interfacechecker/interfacechecker.go b/linter/interfacechecker/interfacechecker.go deleted file mode 100644 index 50bb56f74..000000000 --- a/linter/interfacechecker/interfacechecker.go +++ /dev/null @@ -1,12 +0,0 @@ -// Static analyzer to prevent conditional checks on select interfaces. -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/interfacechecker" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(interfacechecker.Analyzer) -} diff --git a/linter/logruswitherror/logruswitherror.go b/linter/logruswitherror/logruswitherror.go deleted file mode 100644 index d0da1fcb1..000000000 --- a/linter/logruswitherror/logruswitherror.go +++ /dev/null @@ -1,13 +0,0 @@ -// Static analyzer to ensure that log statements do not use errors in -// templated log statements. Authors should use logrus.WithError(). -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/logruswitherror" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(logruswitherror.Analyzer) -} diff --git a/linter/recursivelock/recursivelock.go b/linter/recursivelock/recursivelock.go index 8c8caff38..9349759cf 100644 --- a/linter/recursivelock/recursivelock.go +++ b/linter/recursivelock/recursivelock.go @@ -1,4 +1,3 @@ -// Static Analyzer for detecting nested or recursive mutex read lock statements. package main import ( diff --git a/linter/shadowpredecl/shadowpredecl.go b/linter/shadowpredecl/shadowpredecl.go deleted file mode 100644 index e51ff0da8..000000000 --- a/linter/shadowpredecl/shadowpredecl.go +++ /dev/null @@ -1,13 +0,0 @@ -// Static analyzer which disallows declaring constructs that shadow predeclared -// Go identifiers by having the same name. -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/shadowpredecl" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(shadowpredecl.Analyzer) -} diff --git a/linter/slicedirect/slicedirect.go b/linter/slicedirect/slicedirect.go deleted file mode 100644 index b31404013..000000000 --- a/linter/slicedirect/slicedirect.go +++ /dev/null @@ -1,13 +0,0 @@ -// Static analyzer to ensure that code does not contain applications of [:] -// on expressions which are already slices. -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/slicedirect" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(slicedirect.Analyzer) -} diff --git a/linter/uintcast/uintcast.go b/linter/uintcast/uintcast.go deleted file mode 100644 index 1f0eb7857..000000000 --- a/linter/uintcast/uintcast.go +++ /dev/null @@ -1,13 +0,0 @@ -// Static analyzer for detecting unsafe uint to int casts. -// Use `lint:ignore uintcast` with proper justification to ignore this check. -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/uintcast" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(uintcast.Analyzer) -} From 68917ae115f3a777420d7874e73dd8e7c97feddd Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 24 Dec 2023 11:49:17 -0700 Subject: [PATCH 569/775] Revert "Merge pull request #2016 from OffchainLabs/recursivelock-lint" This reverts commit 459a63be17fc52566c26c50af75f6f5617ae2c1d, reversing changes made to a0e63172ca4c6ed08612622cb1605da02b599c6a. --- Makefile | 1 - go.mod | 32 +++++++++--------- go.sum | 47 --------------------------- linter/recursivelock/recursivelock.go | 11 ------- 4 files changed, 15 insertions(+), 76 deletions(-) delete mode 100644 linter/recursivelock/recursivelock.go diff --git a/Makefile b/Makefile index 42fd1e359..422110096 100644 --- a/Makefile +++ b/Makefile @@ -307,7 +307,6 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro # strategic rules to minimize dependency building .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make - go run ./linter/recursivelock ./... go run ./linter/koanf ./... go run ./linter/pointercheck ./... golangci-lint run --fix diff --git a/go.mod b/go.mod index e504542a2..bdda6a61a 100644 --- a/go.mod +++ b/go.mod @@ -18,11 +18,11 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.10 github.com/aws/aws-sdk-go-v2/service/s3 v1.26.9 github.com/cavaliergopher/grab/v3 v3.0.1 - github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 + github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 github.com/codeclysm/extract/v3 v3.0.2 github.com/dgraph-io/badger/v3 v3.2103.2 github.com/enescakir/emoji v1.0.0 - github.com/ethereum/go-ethereum v1.13.1 + github.com/ethereum/go-ethereum v1.10.26 github.com/fatih/structtag v1.2.0 github.com/gdamore/tcell/v2 v2.6.0 github.com/google/go-cmp v0.5.9 @@ -73,7 +73,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect @@ -97,7 +97,7 @@ require ( github.com/dgraph-io/ristretto v0.1.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -131,7 +131,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect - github.com/huin/goupnp v1.3.0 // indirect + github.com/huin/goupnp v1.1.0 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect github.com/ipfs/go-block-format v0.1.1 // indirect @@ -195,7 +195,7 @@ require ( github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect github.com/libp2p/go-libp2p-kad-dht v0.21.1 // indirect github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect - github.com/libp2p/go-libp2p-pubsub v0.9.3 // indirect + github.com/libp2p/go-libp2p-pubsub v0.9.0 // indirect github.com/libp2p/go-libp2p-pubsub-router v0.6.0 // indirect github.com/libp2p/go-libp2p-record v0.2.0 // indirect github.com/libp2p/go-libp2p-routing-helpers v0.6.2 // indirect @@ -238,7 +238,6 @@ require ( github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect - github.com/prysmaticlabs/prysm/v4 v4.1.1 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-19 v0.3.3 // indirect github.com/quic-go/qtls-go1-20 v0.2.3 // indirect @@ -246,13 +245,13 @@ require ( github.com/quic-go/webtransport-go v0.5.2 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/rhnvrm/simples3 v0.6.1 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.3 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/samber/lo v1.36.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/supranational/blst v0.3.11 // indirect - github.com/urfave/cli/v2 v2.25.7 // indirect + github.com/urfave/cli/v2 v2.24.1 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect @@ -262,7 +261,6 @@ require ( github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 // indirect - github.com/yusufpapurcu/wmi v1.2.2 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.7.0 // indirect go.opentelemetry.io/otel/exporters/jaeger v1.7.0 // indirect @@ -310,12 +308,12 @@ require ( require ( github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect - github.com/VictoriaMetrics/fastcache v1.12.0 // indirect + github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect - github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect + github.com/go-ole/go-ole v1.2.1 // indirect github.com/go-redis/redis/v8 v8.11.4 github.com/go-stack/stack v1.8.1 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect @@ -332,11 +330,11 @@ require ( github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/rs/cors v1.7.0 // indirect - github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + github.com/tklauser/go-sysconf v0.3.5 // indirect + github.com/tklauser/numcpus v0.2.2 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect ) diff --git a/go.sum b/go.sum index 0a9649c43..bf8b4b826 100644 --- a/go.sum +++ b/go.sum @@ -173,8 +173,6 @@ github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13P github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= -github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= -github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= @@ -200,7 +198,6 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/ceramicnetwork/go-dag-jose v0.1.0 h1:yJ/HVlfKpnD3LdYP03AHyTvbm3BpPiz2oZiOeReJRdU= github.com/ceramicnetwork/go-dag-jose v0.1.0/go.mod h1:qYA1nYt0X8u4XoMAVoOV3upUVKtrxy/I670Dg5F0wjI= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= -github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -228,7 +225,6 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/datadriven v1.0.3-0.20230801171734-e384cf455877 h1:1MLK4YpFtIEo3ZtMA5C795Wtv5VuUnrXX7mQG+aHg6o= github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= @@ -236,8 +232,6 @@ github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZe github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= -github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 h1:T+Np/xtzIjYM/P5NAw0e2Rf1FGvzDau1h54MKvx8G7w= -github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06/go.mod h1:bynZ3gvVyhlvjLI7PT6dmZ7g76xzJ7HpxfjgkzCGz6s= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= @@ -313,8 +307,6 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= -github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -368,7 +360,6 @@ github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09 github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= @@ -376,8 +367,6 @@ github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZ github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= @@ -414,8 +403,6 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -549,7 +536,6 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b h1:Qcx5LM0fSiks9uCyFZwDBUasd3lxd1RM0GYpL+Li5o4= github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= @@ -654,12 +640,9 @@ github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmK github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= -github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -1075,8 +1058,6 @@ github.com/libp2p/go-libp2p-peerstore v0.2.7/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuD github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= github.com/libp2p/go-libp2p-pubsub v0.9.0 h1:mcLb4WzwhUG4OKb0rp1/bYMd/DYhvMyzJheQH3LMd1s= github.com/libp2p/go-libp2p-pubsub v0.9.0/go.mod h1:OEsj0Cc/BpkqikXRTrVspWU/Hx7bMZwHP+6vNMd+c7I= -github.com/libp2p/go-libp2p-pubsub v0.9.3 h1:ihcz9oIBMaCK9kcx+yHWm3mLAFBMAUsM4ux42aikDxo= -github.com/libp2p/go-libp2p-pubsub v0.9.3/go.mod h1:RYA7aM9jIic5VV47WXu4GkcRxRhrdElWf8xtyli+Dzc= github.com/libp2p/go-libp2p-pubsub-router v0.6.0 h1:D30iKdlqDt5ZmLEYhHELCMRj8b4sFAqrUcshIUvVP/s= github.com/libp2p/go-libp2p-pubsub-router v0.6.0/go.mod h1:FY/q0/RBTKsLA7l4vqC2cbRbOvyDotg8PJQ7j8FDudE= github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= @@ -1391,7 +1372,6 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= @@ -1401,8 +1381,6 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= @@ -1486,8 +1464,6 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/prysmaticlabs/prysm/v4 v4.1.1 h1:sbBkgfPzo/SGTJ5IimtsZSGECoRlhbowR1rEhTOdvHo= -github.com/prysmaticlabs/prysm/v4 v4.1.1/go.mod h1:+o907dc4mwEE0wJkQ8RrzCroC+q2WCzdCLtikwonw8c= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/qtls-go1-19 v0.3.3 h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE= @@ -1512,8 +1488,6 @@ github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703/go.mod h1:nVwGv4MP47T0j github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1539,8 +1513,6 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= -github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= @@ -1616,7 +1588,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= @@ -1625,18 +1596,12 @@ github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3 github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= -github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= @@ -1655,8 +1620,6 @@ github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60Nt github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.24.1 h1:/QYYr7g0EhwXEML8jO+8OYt5trPnLHS0p3mrgExJ5NU= github.com/urfave/cli/v2 v2.24.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= -github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= -github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -1721,8 +1684,6 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLCur2yWnJzwQEKRcAHXo6seXGuSwWw= github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= -github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= -github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= @@ -1925,8 +1886,6 @@ golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= @@ -1989,7 +1948,6 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2042,10 +2000,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2053,8 +2009,6 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -2149,7 +2103,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= diff --git a/linter/recursivelock/recursivelock.go b/linter/recursivelock/recursivelock.go deleted file mode 100644 index 9349759cf..000000000 --- a/linter/recursivelock/recursivelock.go +++ /dev/null @@ -1,11 +0,0 @@ -package main - -import ( - "github.com/prysmaticlabs/prysm/v4/tools/analyzers/recursivelock" - - "golang.org/x/tools/go/analysis/singlechecker" -) - -func main() { - singlechecker.Main(recursivelock.Analyzer) -} From 1fac15d8bd2b0c3152c937cd444ba89d4abdedd2 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 27 Dec 2023 11:38:27 -0700 Subject: [PATCH 570/775] Fix sequencer forwarder panic on lack of targets --- execution/gethexec/forwarder.go | 2 ++ execution/gethexec/sequencer.go | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/execution/gethexec/forwarder.go b/execution/gethexec/forwarder.go index dc3420f8d..7fec46c63 100644 --- a/execution/gethexec/forwarder.go +++ b/execution/gethexec/forwarder.go @@ -205,6 +205,8 @@ func (f *TxForwarder) Initialize(inctx context.Context) error { f.targets = targets if len(f.rpcClients) > 0 { f.enabled.Store(true) + } else if lastError == nil { + return errors.New("no non-empty forwarding targets specified") } else { return lastError } diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 1c60702c8..b21a27452 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -487,7 +487,7 @@ func (s *Sequencer) CheckHealth(ctx context.Context) error { func (s *Sequencer) ForwardTarget() string { s.activeMutex.Lock() defer s.activeMutex.Unlock() - if s.forwarder == nil { + if s.forwarder == nil || len(s.forwarder.targets) == 0 { return "" } return s.forwarder.targets[0] @@ -497,7 +497,7 @@ func (s *Sequencer) ForwardTo(url string) error { s.activeMutex.Lock() defer s.activeMutex.Unlock() if s.forwarder != nil { - if s.forwarder.targets[0] == url { + if len(s.forwarder.targets) > 0 && s.forwarder.targets[0] == url { log.Warn("attempted to update sequencer forward target with existing target", "url", url) return nil } From 966a1724ac5bcf0eb94e9c245c44c6a33a6ba692 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 27 Dec 2023 12:04:48 -0700 Subject: [PATCH 571/775] Fix broken NodeInterface methods --- execution/gethexec/node.go | 2 +- system_tests/nodeinterface_test.go | 37 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 7dd6e301f..00337cc35 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -248,7 +248,7 @@ func CreateExecutionNode( } func (n *ExecutionNode) Initialize(ctx context.Context, arbnode interface{}, sync arbitrum.SyncProgressBackend) error { - n.ArbInterface.Initialize(n) + n.ArbInterface.Initialize(arbnode) err := n.Backend.Start() if err != nil { return fmt.Errorf("error starting geth backend: %w", err) diff --git a/system_tests/nodeinterface_test.go b/system_tests/nodeinterface_test.go index 40953a449..3424a58e9 100644 --- a/system_tests/nodeinterface_test.go +++ b/system_tests/nodeinterface_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/offchainlabs/nitro/arbos/util" "github.com/offchainlabs/nitro/solgen/go/node_interfacegen" @@ -73,3 +74,39 @@ func TestL2BlockRangeForL1(t *testing.T) { t.Fatalf("GetL2BlockRangeForL1 didn't fail for an invalid input") } } + +func TestGetL1Confirmations(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() + + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, builder.L2.Client) + Require(t, err) + + genesisBlock, err := builder.L2.Client.BlockByNumber(ctx, big.NewInt(0)) + Require(t, err) + l1Confs, err := nodeInterface.GetL1Confirmations(&bind.CallOpts{}, genesisBlock.Hash()) + Require(t, err) + + numTransactions := 200 + + if l1Confs >= uint64(numTransactions) { + t.Fatalf("L1Confirmations for latest block %v is already %v (over %v)", genesisBlock.Number(), l1Confs, numTransactions) + } + + for i := 0; i < numTransactions; i++ { + builder.L1.TransferBalance(t, "User", "User", common.Big0, builder.L1Info) + } + + l1Confs, err = nodeInterface.GetL1Confirmations(&bind.CallOpts{}, genesisBlock.Hash()) + Require(t, err) + + // Allow a gap of 10 for asynchronicity, just in case + if l1Confs+10 < uint64(numTransactions) { + t.Fatalf("L1Confirmations for latest block %v is only %v (did not hit expected %v)", genesisBlock.Number(), l1Confs, numTransactions) + } +} From c75e6049a787889d5bbcb20787b49d47573254f9 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 27 Dec 2023 12:22:20 -0700 Subject: [PATCH 572/775] Allow the TxForwarder to be empty --- execution/gethexec/forwarder.go | 16 ++++++++++++---- execution/gethexec/sequencer.go | 6 +++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/execution/gethexec/forwarder.go b/execution/gethexec/forwarder.go index 7fec46c63..9783c604a 100644 --- a/execution/gethexec/forwarder.go +++ b/execution/gethexec/forwarder.go @@ -151,7 +151,7 @@ func (f *TxForwarder) PublishTransaction(inctx context.Context, tx *types.Transa if err == nil || !f.tryNewForwarderErrors.MatchString(err.Error()) { return err } - log.Info("error forwarding transaction to a backup target", "target", f.targets[pos], "err", err) + log.Warn("error forwarding transaction to a backup target", "target", f.targets[pos], "err", err) } return errors.New("failed to publish transaction to any of the forwarding targets") } @@ -161,7 +161,9 @@ const maxHealthTimeout = 10 * time.Second // CheckHealth returns health of the highest priority forwarding target func (f *TxForwarder) CheckHealth(inctx context.Context) error { - if !f.enabled.Load() { + // If f.enabled is false, len(f.rpcClients) should always be greater than zero, + // but better safe than sorry. + if !f.enabled.Load() || len(f.rpcClients) == 0 { return ErrNoSequencer } f.healthMutex.Lock() @@ -205,8 +207,6 @@ func (f *TxForwarder) Initialize(inctx context.Context) error { f.targets = targets if len(f.rpcClients) > 0 { f.enabled.Store(true) - } else if lastError == nil { - return errors.New("no non-empty forwarding targets specified") } else { return lastError } @@ -232,6 +232,14 @@ func (f *TxForwarder) Started() bool { return true } +// Returns the URL of the first forwarding target, or an empty string if none are set. +func (f *TxForwarder) PrimaryTarget() string { + if len(f.targets) == 0 { + return "" + } + return f.targets[0] +} + type TxDropper struct{} func NewTxDropper() *TxDropper { diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index b21a27452..5db38cbb4 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -487,17 +487,17 @@ func (s *Sequencer) CheckHealth(ctx context.Context) error { func (s *Sequencer) ForwardTarget() string { s.activeMutex.Lock() defer s.activeMutex.Unlock() - if s.forwarder == nil || len(s.forwarder.targets) == 0 { + if s.forwarder == nil { return "" } - return s.forwarder.targets[0] + return s.forwarder.PrimaryTarget() } func (s *Sequencer) ForwardTo(url string) error { s.activeMutex.Lock() defer s.activeMutex.Unlock() if s.forwarder != nil { - if len(s.forwarder.targets) > 0 && s.forwarder.targets[0] == url { + if s.forwarder.PrimaryTarget() == url { log.Warn("attempted to update sequencer forward target with existing target", "url", url) return nil } From 02bfe08a2da0ce08522c52f0507d5fc49927b841 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 27 Dec 2023 12:26:01 -0700 Subject: [PATCH 573/775] Fix comment --- execution/gethexec/forwarder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execution/gethexec/forwarder.go b/execution/gethexec/forwarder.go index 9783c604a..984c7224e 100644 --- a/execution/gethexec/forwarder.go +++ b/execution/gethexec/forwarder.go @@ -161,7 +161,7 @@ const maxHealthTimeout = 10 * time.Second // CheckHealth returns health of the highest priority forwarding target func (f *TxForwarder) CheckHealth(inctx context.Context) error { - // If f.enabled is false, len(f.rpcClients) should always be greater than zero, + // If f.enabled is true, len(f.rpcClients) should always be greater than zero, // but better safe than sorry. if !f.enabled.Load() || len(f.rpcClients) == 0 { return ErrNoSequencer From 3d4111ca9b6bd9759c66c1182b0e693ae827da9b Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Sat, 30 Dec 2023 17:21:57 -0600 Subject: [PATCH 574/775] update change date --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 0739c2d8b..e16976d32 100644 --- a/LICENSE +++ b/LICENSE @@ -30,7 +30,7 @@ Additional Use Grant: You may use the Licensed Work in a production environment -Change Date: Dec 31, 2027 +Change Date: Dec 31, 2028 Change License: Apache License Version 2.0 From 172765d50b35c7fbd77031893bf37c35a3a50f12 Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Sat, 30 Dec 2023 17:45:29 -0600 Subject: [PATCH 575/775] update license year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index e16976d32..c96c4d6cb 100644 --- a/LICENSE +++ b/LICENSE @@ -10,7 +10,7 @@ Parameters Licensor: Offchain Labs Licensed Work: Arbitrum Nitro - The Licensed Work is (c) 2021-2023 Offchain Labs + The Licensed Work is (c) 2021-2024 Offchain Labs Additional Use Grant: You may use the Licensed Work in a production environment solely to provide a point of interface to permit end users or applications From e2086163542bf28ee70b1dcfb2d302e4ed5b8cbf Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 1 Jan 2024 21:58:48 -0600 Subject: [PATCH 576/775] Hide error when getting latest confirmed block --- util/headerreader/header_reader.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index a5100f74f..c5b8fa23f 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -53,6 +53,7 @@ type HeaderReader struct { type cachedHeader struct { mutex sync.Mutex + blockTag string // "safe" or "finalized" rpcBlockNum *big.Int headWhenCached *types.Header header *types.Header @@ -135,8 +136,8 @@ func New(ctx context.Context, client arbutil.L1Interface, config ConfigFetcher, arbSys: arbSys, outChannels: make(map[chan<- *types.Header]struct{}), outChannelsBehind: make(map[chan<- *types.Header]struct{}), - safe: cachedHeader{rpcBlockNum: big.NewInt(rpc.SafeBlockNumber.Int64())}, - finalized: cachedHeader{rpcBlockNum: big.NewInt(rpc.FinalizedBlockNumber.Int64())}, + safe: cachedHeader{blockTag: "safe", rpcBlockNum: big.NewInt(rpc.SafeBlockNumber.Int64())}, + finalized: cachedHeader{blockTag: "finalized", rpcBlockNum: big.NewInt(rpc.FinalizedBlockNumber.Int64())}, }, nil } @@ -470,6 +471,11 @@ func (s *HeaderReader) getCached(ctx context.Context, c *cachedHeader) (*types.H } header, err := s.client.HeaderByNumber(ctx, c.rpcBlockNum) if err != nil { + if !errors.Is(err, context.Canceled) { + log.Warn("Failed to get latest confirmed block", "blockTag", c.blockTag, "err", err) + // Hide error to caller to avoid exposing potentially sensitive L1 information. + err = fmt.Errorf("failed to get latest %v block", c.blockTag) + } return nil, err } c.header = header From ef961aef3af2e5b1651024428af51a85f0d2655b Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 2 Jan 2024 11:26:11 +0530 Subject: [PATCH 577/775] enable EphemeralErrorHandler to ignore error for a certain duration --- arbnode/batch_poster.go | 26 ++++++++++++++++++++------ staker/staker.go | 2 +- util/log.go | 20 ++++++++++++++++---- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 005012c5a..8885dab13 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -1145,8 +1145,18 @@ func (b *BatchPoster) Start(ctxIn context.Context) { b.redisLock.Start(ctxIn) b.StopWaiter.Start(ctxIn, b) b.LaunchThread(b.pollForReverts) - commonEphemeralErrorHandler := util.NewEphemeralErrorHandler(time.Minute, "") - exceedMaxMempoolSizeEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, "will exceed max mempool size") + commonEphemeralErrorHandler := util.NewEphemeralErrorHandler(time.Minute, "", 0, nil) + exceedMaxMempoolSizeEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, dataposter.ErrExceedsMaxMempoolSize.Error(), time.Minute, log.Debug) + storageRaceEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, storage.ErrStorageRace.Error(), time.Minute, log.Debug) + normalGasEstimationFailedEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, ErrNormalGasEstimationFailed.Error(), time.Minute, log.Debug) + accumulatorNotFoundEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, AccumulatorNotFoundErr.Error(), time.Minute, log.Debug) + resetAllEphemeralErrs := func() { + commonEphemeralErrorHandler.Reset() + exceedMaxMempoolSizeEphemeralErrorHandler.Reset() + storageRaceEphemeralErrorHandler.Reset() + normalGasEstimationFailedEphemeralErrorHandler.Reset() + accumulatorNotFoundEphemeralErrorHandler.Reset() + } b.CallIteratively(func(ctx context.Context) time.Duration { var err error if common.HexToAddress(b.config().GasRefunderAddress) != (common.Address{}) { @@ -1174,14 +1184,12 @@ func (b *BatchPoster) Start(ctxIn context.Context) { if !couldLock { log.Debug("Not posting batches right now because another batch poster has the lock or this node is behind") b.building = nil - commonEphemeralErrorHandler.Reset() - exceedMaxMempoolSizeEphemeralErrorHandler.Reset() + resetAllEphemeralErrs() return b.config().PollInterval } posted, err := b.maybePostSequencerBatch(ctx) if err == nil { - commonEphemeralErrorHandler.Reset() - exceedMaxMempoolSizeEphemeralErrorHandler.Reset() + resetAllEphemeralErrs() } if err != nil { if ctx.Err() != nil { @@ -1193,7 +1201,13 @@ func (b *BatchPoster) Start(ctxIn context.Context) { // Likely the inbox tracker just isn't caught up. // Let's see if this error disappears naturally. logLevel = commonEphemeralErrorHandler.LogLevel(err, logLevel) + // If the error matches one of these, it's only logged at debug for the first minute, + // then at warn for the next 4 minutes, then at error. If the error isn't one of these, + // it'll be logged at warn for the first minute, then at error. logLevel = exceedMaxMempoolSizeEphemeralErrorHandler.LogLevel(err, logLevel) + logLevel = storageRaceEphemeralErrorHandler.LogLevel(err, logLevel) + logLevel = normalGasEstimationFailedEphemeralErrorHandler.LogLevel(err, logLevel) + logLevel = accumulatorNotFoundEphemeralErrorHandler.LogLevel(err, logLevel) logLevel("error posting batch", "err", err) return b.config().ErrorDelay } else if posted { diff --git a/staker/staker.go b/staker/staker.go index 7a2342c26..002dd1f75 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -402,7 +402,7 @@ func (s *Staker) Start(ctxIn context.Context) { } s.StopWaiter.Start(ctxIn, s) backoff := time.Second - ephemeralErrorHandler := util.NewEphemeralErrorHandler(10*time.Minute, "is ahead of on-chain nonce") + ephemeralErrorHandler := util.NewEphemeralErrorHandler(10*time.Minute, "is ahead of on-chain nonce", 0, nil) s.CallIteratively(func(ctx context.Context) (returningWait time.Duration) { defer func() { panicErr := recover() diff --git a/util/log.go b/util/log.go index b68f503f5..0d87b5597 100644 --- a/util/log.go +++ b/util/log.go @@ -13,13 +13,18 @@ type EphemeralErrorHandler struct { Duration time.Duration ErrorString string FirstOccurrence *time.Time + + IgnoreDuration time.Duration + IgnoredErrLogLevel func(string, ...interface{}) // Default IgnoredErrLogLevel is log.Debug } -func NewEphemeralErrorHandler(duration time.Duration, errorString string) *EphemeralErrorHandler { +func NewEphemeralErrorHandler(duration time.Duration, errorString string, ignoreDuration time.Duration, ignoredErrLogLevel func(msg string, ctx ...interface{})) *EphemeralErrorHandler { return &EphemeralErrorHandler{ - Duration: duration, - ErrorString: errorString, - FirstOccurrence: &time.Time{}, + Duration: duration, + ErrorString: errorString, + FirstOccurrence: &time.Time{}, + IgnoreDuration: ignoreDuration, + IgnoredErrLogLevel: ignoredErrLogLevel, } } @@ -39,6 +44,13 @@ func (h *EphemeralErrorHandler) LogLevel(err error, currentLogLevel func(msg str return currentLogLevel } + if h.IgnoreDuration != 0 && time.Since(*h.FirstOccurrence) < h.IgnoreDuration { + if h.IgnoredErrLogLevel != nil { + return h.IgnoredErrLogLevel + } + return log.Debug + } + logLevel := log.Error if *h.FirstOccurrence == (time.Time{}) { *h.FirstOccurrence = time.Now() From b19326290ce9518ebfd704b8a87eb2021b9a2769 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 2 Jan 2024 20:01:07 +0530 Subject: [PATCH 578/775] code refactor --- arbnode/batch_poster.go | 10 +++--- staker/staker.go | 2 +- util/log.go | 21 +++++++------ util/log_test.go | 70 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 util/log_test.go diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 8885dab13..4bd0e2490 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -1145,11 +1145,11 @@ func (b *BatchPoster) Start(ctxIn context.Context) { b.redisLock.Start(ctxIn) b.StopWaiter.Start(ctxIn, b) b.LaunchThread(b.pollForReverts) - commonEphemeralErrorHandler := util.NewEphemeralErrorHandler(time.Minute, "", 0, nil) - exceedMaxMempoolSizeEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, dataposter.ErrExceedsMaxMempoolSize.Error(), time.Minute, log.Debug) - storageRaceEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, storage.ErrStorageRace.Error(), time.Minute, log.Debug) - normalGasEstimationFailedEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, ErrNormalGasEstimationFailed.Error(), time.Minute, log.Debug) - accumulatorNotFoundEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, AccumulatorNotFoundErr.Error(), time.Minute, log.Debug) + commonEphemeralErrorHandler := util.NewEphemeralErrorHandler(time.Minute, "", 0) + exceedMaxMempoolSizeEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, dataposter.ErrExceedsMaxMempoolSize.Error(), time.Minute) + storageRaceEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, storage.ErrStorageRace.Error(), time.Minute) + normalGasEstimationFailedEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, ErrNormalGasEstimationFailed.Error(), time.Minute) + accumulatorNotFoundEphemeralErrorHandler := util.NewEphemeralErrorHandler(5*time.Minute, AccumulatorNotFoundErr.Error(), time.Minute) resetAllEphemeralErrs := func() { commonEphemeralErrorHandler.Reset() exceedMaxMempoolSizeEphemeralErrorHandler.Reset() diff --git a/staker/staker.go b/staker/staker.go index 002dd1f75..2a95e9c9f 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -402,7 +402,7 @@ func (s *Staker) Start(ctxIn context.Context) { } s.StopWaiter.Start(ctxIn, s) backoff := time.Second - ephemeralErrorHandler := util.NewEphemeralErrorHandler(10*time.Minute, "is ahead of on-chain nonce", 0, nil) + ephemeralErrorHandler := util.NewEphemeralErrorHandler(10*time.Minute, "is ahead of on-chain nonce", 0) s.CallIteratively(func(ctx context.Context) (returningWait time.Duration) { defer func() { panicErr := recover() diff --git a/util/log.go b/util/log.go index 0d87b5597..dbeed8051 100644 --- a/util/log.go +++ b/util/log.go @@ -18,18 +18,19 @@ type EphemeralErrorHandler struct { IgnoredErrLogLevel func(string, ...interface{}) // Default IgnoredErrLogLevel is log.Debug } -func NewEphemeralErrorHandler(duration time.Duration, errorString string, ignoreDuration time.Duration, ignoredErrLogLevel func(msg string, ctx ...interface{})) *EphemeralErrorHandler { +func NewEphemeralErrorHandler(duration time.Duration, errorString string, ignoreDuration time.Duration) *EphemeralErrorHandler { return &EphemeralErrorHandler{ Duration: duration, ErrorString: errorString, FirstOccurrence: &time.Time{}, IgnoreDuration: ignoreDuration, - IgnoredErrLogLevel: ignoredErrLogLevel, + IgnoredErrLogLevel: log.Debug, } } -// LogLevel method defaults to returning the input currentLogLevel if the givenerror doesnt contain the errorSubstring, +// LogLevel method defaults to returning the input currentLogLevel if the given error doesnt contain the errorSubstring, // but if it does, then returns one of the corresponding loglevels as follows +// - IgnoredErrLogLevel - if the error has been repeating for less than the IgnoreDuration of time. Defaults to log.Debug // - log.Warn - if the error has been repeating for less than the given duration of time // - log.Error - Otherwise // @@ -44,6 +45,10 @@ func (h *EphemeralErrorHandler) LogLevel(err error, currentLogLevel func(msg str return currentLogLevel } + if *h.FirstOccurrence == (time.Time{}) { + *h.FirstOccurrence = time.Now() + } + if h.IgnoreDuration != 0 && time.Since(*h.FirstOccurrence) < h.IgnoreDuration { if h.IgnoredErrLogLevel != nil { return h.IgnoredErrLogLevel @@ -51,14 +56,10 @@ func (h *EphemeralErrorHandler) LogLevel(err error, currentLogLevel func(msg str return log.Debug } - logLevel := log.Error - if *h.FirstOccurrence == (time.Time{}) { - *h.FirstOccurrence = time.Now() - logLevel = log.Warn - } else if time.Since(*h.FirstOccurrence) < h.Duration { - logLevel = log.Warn + if time.Since(*h.FirstOccurrence) < h.Duration { + return log.Warn } - return logLevel + return log.Error } func (h *EphemeralErrorHandler) Reset() { diff --git a/util/log_test.go b/util/log_test.go new file mode 100644 index 000000000..f8007373f --- /dev/null +++ b/util/log_test.go @@ -0,0 +1,70 @@ +package util + +import ( + "errors" + "reflect" + "testing" + "time" + + "github.com/ethereum/go-ethereum/log" +) + +func compareFunctions(f1, f2 func(msg string, ctx ...interface{})) bool { + return reflect.ValueOf(f1).Pointer() == reflect.ValueOf(f2).Pointer() +} +func TestSimple(t *testing.T) { + allErrHandler := NewEphemeralErrorHandler(2500*time.Millisecond, "", time.Second) + err := errors.New("sample error") + logLevel := allErrHandler.LogLevel(err, log.Error) + if !compareFunctions(log.Debug, logLevel) { + t.Fatalf("incorrect loglevel output. Want: Debug") + } + + time.Sleep(1 * time.Second) + logLevel = allErrHandler.LogLevel(err, log.Error) + if !compareFunctions(log.Warn, logLevel) { + t.Fatalf("incorrect loglevel output. Want: Warn") + } + + time.Sleep(2 * time.Second) + logLevel = allErrHandler.LogLevel(err, log.Error) + if !compareFunctions(log.Error, logLevel) { + t.Fatalf("incorrect loglevel output. Want: Error") + } +} + +func TestComplex(t *testing.T) { + // Simulation: errorA happens continuously for 2 seconds and then errorB happens + errorAHandler := NewEphemeralErrorHandler(time.Second, "errorA", 0) + errorBHandler := NewEphemeralErrorHandler(1500*time.Millisecond, "errorB", 0) + + // Computes result of chaining two ephemeral error handlers for a given recurring error + chainingErrHandlers := func(err error) func(string, ...interface{}) { + logLevel := log.Error + logLevel = errorAHandler.LogLevel(err, logLevel) + logLevel = errorBHandler.LogLevel(err, logLevel) + return logLevel + } + + errA := errors.New("this is a sample errorA") + if !compareFunctions(log.Warn, chainingErrHandlers(errA)) { + t.Fatalf("incorrect loglevel output. Want: Warn") + } + time.Sleep(2 * time.Second) + if !compareFunctions(log.Error, chainingErrHandlers(errA)) { + t.Fatalf("incorrect loglevel output. Want: Error") + } + + errB := errors.New("this is a sample errorB") + if !compareFunctions(log.Warn, chainingErrHandlers(errB)) { + t.Fatalf("incorrect loglevel output. Want: Warn") + } + if !compareFunctions(log.Warn, chainingErrHandlers(errA)) { + t.Fatalf("incorrect loglevel output. Want: Warn") + } + + errC := errors.New("random error") + if !compareFunctions(log.Error, chainingErrHandlers(errC)) { + t.Fatalf("incorrect loglevel output. Want: Error") + } +} From 716e8c5b65e1e7bb8070e1be0b227d9efdc84598 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 2 Jan 2024 15:39:07 -0600 Subject: [PATCH 579/775] Add WAVM KZG preimage proof --- Makefile | 12 +- arbitrator/Cargo.lock | 409 +- arbitrator/arbutil/src/types.rs | 13 +- arbitrator/prover/Cargo.toml | 2 + arbitrator/prover/src/host.rs | 34 +- arbitrator/prover/src/kzg-trusted-setup.json | 4167 +++++++++++++++++ arbitrator/prover/src/kzg.rs | 59 + arbitrator/prover/src/lib.rs | 1 + arbitrator/prover/src/machine.rs | 89 +- arbitrator/prover/src/main.rs | 14 +- arbitrator/prover/src/utils.rs | 22 + arbitrator/prover/test-cases/go/main.go | 27 + arbitrator/prover/test-cases/rust/Cargo.lock | 72 + arbitrator/prover/test-cases/rust/Cargo.toml | 2 + .../prover/test-cases/rust/data/preimages.bin | Bin 40 -> 0 bytes .../prover/test-cases/rust/src/bin/host-io.rs | 45 + arbitrator/wasm-libraries/Cargo.lock | 8 +- arbitrator/wasm-libraries/host-io/src/lib.rs | 2 + arbutil/preimage_type.go | 1 + contracts | 2 +- scripts/create-test-preimages.py | 39 + 21 files changed, 4954 insertions(+), 66 deletions(-) create mode 100644 arbitrator/prover/src/kzg-trusted-setup.json create mode 100644 arbitrator/prover/src/kzg.rs delete mode 100644 arbitrator/prover/test-cases/rust/data/preimages.bin create mode 100644 scripts/create-test-preimages.py diff --git a/Makefile b/Makefile index 422110096..97c47079e 100644 --- a/Makefile +++ b/Makefile @@ -291,11 +291,15 @@ contracts/test/prover/proofs/float%.json: $(arbitrator_cases)/float%.wasm $(arbi contracts/test/prover/proofs/no-stack-pollution.json: $(arbitrator_cases)/no-stack-pollution.wasm $(arbitrator_prover_bin) $(arbitrator_prover_bin) $< -o $@ --allow-hostapi --require-success --always-merkleize -contracts/test/prover/proofs/rust-%.json: $(arbitrator_cases)/rust/target/wasm32-wasi/release/%.wasm $(arbitrator_prover_bin) $(arbitrator_wasm_libs_nogo) - $(arbitrator_prover_bin) $< $(arbitrator_wasm_lib_flags_nogo) -o $@ -b --allow-hostapi --require-success --inbox-add-stub-headers --inbox $(arbitrator_cases)/rust/data/msg0.bin --inbox $(arbitrator_cases)/rust/data/msg1.bin --delayed-inbox $(arbitrator_cases)/rust/data/msg0.bin --delayed-inbox $(arbitrator_cases)/rust/data/msg1.bin --preimages $(arbitrator_cases)/rust/data/preimages.bin +target/testdata/preimages.bin: + mkdir -p `dirname $@` + python3 scripts/create-test-preimages.py $@ -contracts/test/prover/proofs/go.json: $(arbitrator_cases)/go/main $(arbitrator_prover_bin) $(arbitrator_wasm_libs) - $(arbitrator_prover_bin) $< $(arbitrator_wasm_lib_flags) -o $@ -i 5000000 --require-success --preimages $(arbitrator_cases)/rust/data/preimages.bin +contracts/test/prover/proofs/rust-%.json: $(arbitrator_cases)/rust/target/wasm32-wasi/release/%.wasm $(arbitrator_prover_bin) $(arbitrator_wasm_libs_nogo) target/testdata/preimages.bin + $(arbitrator_prover_bin) $< $(arbitrator_wasm_lib_flags_nogo) -o $@ -b --allow-hostapi --require-success --inbox-add-stub-headers --inbox $(arbitrator_cases)/rust/data/msg0.bin --inbox $(arbitrator_cases)/rust/data/msg1.bin --delayed-inbox $(arbitrator_cases)/rust/data/msg0.bin --delayed-inbox $(arbitrator_cases)/rust/data/msg1.bin --preimages target/testdata/preimages.bin + +contracts/test/prover/proofs/go.json: $(arbitrator_cases)/go/main $(arbitrator_prover_bin) $(arbitrator_wasm_libs) target/testdata/preimages.bin + $(arbitrator_prover_bin) $< $(arbitrator_wasm_lib_flags) -o $@ -i 5000000 --require-success --preimages target/testdata/preimages.bin # avoid testing read-inboxmsg-10 in onestepproofs. It's used for go challenge testing. contracts/test/prover/proofs/read-inboxmsg-10.json: diff --git a/arbitrator/Cargo.lock b/arbitrator/Cargo.lock index 472c9e4b5..165fee89c 100644 --- a/arbitrator/Cargo.lock +++ b/arbitrator/Cargo.lock @@ -58,7 +58,7 @@ version = "0.1.0" dependencies = [ "digest 0.10.7", "num_enum", - "sha2", + "sha2 0.10.8", "sha3 0.10.8", ] @@ -109,12 +109,41 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.66.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" +dependencies = [ + "bitflags 2.4.1", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.45", + "which", +] + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "block-buffer" version = "0.9.0" @@ -140,6 +169,18 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +[[package]] +name = "blst" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + [[package]] name = "brotli-sys" version = "0.3.2" @@ -199,11 +240,38 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +[[package]] +name = "c-kzg" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32700dc7904064bb64e857d38a1766607372928e2466ee5f02a869829b3297d7" +dependencies = [ + "bindgen", + "blst", + "cc", + "glob", + "hex", + "libc", + "serde", +] + [[package]] name = "cc" -version = "1.0.73" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cexpr" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] [[package]] name = "cfg-if" @@ -211,6 +279,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "2.33.3" @@ -219,7 +298,7 @@ checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ "ansi_term", "atty", - "bitflags", + "bitflags 1.3.2", "strsim 0.8.0", "textwrap", "unicode-width", @@ -475,6 +554,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "eyre" version = "0.6.5" @@ -538,6 +627,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "hashbrown" version = "0.11.2" @@ -589,6 +684,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -667,9 +771,9 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jit" @@ -715,6 +819,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "leb128" version = "0.2.5" @@ -723,9 +833,25 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.132" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" + +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "llvm-sys" @@ -939,7 +1065,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.45", ] [[package]] @@ -993,7 +1119,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.45", ] [[package]] @@ -1044,6 +1170,12 @@ dependencies = [ "windows-sys 0.36.1", ] +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "pest" version = "2.3.0" @@ -1060,6 +1192,16 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +[[package]] +name = "prettyplease" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282" +dependencies = [ + "proc-macro2", + "syn 2.0.45", +] + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -1096,9 +1238,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" dependencies = [ "unicode-ident", ] @@ -1110,6 +1252,7 @@ dependencies = [ "arbutil", "bincode", "brotli2", + "c-kzg", "digest 0.9.0", "eyre", "fnv", @@ -1124,6 +1267,7 @@ dependencies = [ "serde", "serde_json", "serde_with", + "sha2 0.9.9", "sha3 0.9.1", "smallvec", "static_assertions", @@ -1154,9 +1298,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a" dependencies = [ "proc-macro2", ] @@ -1216,7 +1360,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1254,7 +1398,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", "mach", "winapi", @@ -1301,6 +1445,12 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" @@ -1310,6 +1460,19 @@ dependencies = [ "semver 1.0.13", ] +[[package]] +name = "rustix" +version = "0.38.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + [[package]] name = "rustversion" version = "1.0.6" @@ -1360,9 +1523,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.132" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] @@ -1380,20 +1543,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.132" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 1.0.76", + "syn 2.0.45", ] [[package]] name = "serde_json" -version = "1.0.67" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f9e390c27c3c0ce8bc5d725f6e4d30a29d26659494aa4b17535f7522c5c950" +checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" dependencies = [ "itoa", "ryu", @@ -1425,9 +1588,22 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -1456,6 +1632,12 @@ dependencies = [ "keccak", ] +[[package]] +name = "shlex" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" + [[package]] name = "slice-group-by" version = "0.3.0" @@ -1532,9 +1714,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.18" +version = "2.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "0eae3c679c56dc214320b67a1bc04ef3dfbd6411f6443974b5e4893231298e66" dependencies = [ "proc-macro2", "quote", @@ -1576,6 +1758,15 @@ dependencies = [ "syn 1.0.76", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "toml_datetime" version = "0.6.3" @@ -1945,6 +2136,18 @@ dependencies = [ "wast", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1993,6 +2196,66 @@ dependencies = [ "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.33.0" @@ -2005,6 +2268,18 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.33.0" @@ -2017,6 +2292,18 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.33.0" @@ -2029,6 +2316,18 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.33.0" @@ -2041,6 +2340,30 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.33.0" @@ -2053,6 +2376,18 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" version = "0.4.7" @@ -2061,3 +2396,23 @@ checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" dependencies = [ "memchr", ] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.45", +] diff --git a/arbitrator/arbutil/src/types.rs b/arbitrator/arbutil/src/types.rs index 165a90d8c..9b6cf4638 100644 --- a/arbitrator/arbutil/src/types.rs +++ b/arbitrator/arbutil/src/types.rs @@ -1,7 +1,6 @@ -// Copyright 2022-2023, Offchain Labs, Inc. +// Copyright 2022-2024, Offchain Labs, Inc. // For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE -use digest::Digest; use num_enum::{IntoPrimitive, TryFromPrimitive}; // These values must be kept in sync with `arbutil/preimage_type.go`, @@ -13,13 +12,5 @@ use num_enum::{IntoPrimitive, TryFromPrimitive}; pub enum PreimageType { Keccak256, Sha2_256, -} - -impl PreimageType { - pub fn hash(&self, preimage: &[u8]) -> [u8; 32] { - match self { - Self::Keccak256 => sha3::Keccak256::digest(preimage).into(), - Self::Sha2_256 => sha2::Sha256::digest(preimage).into(), - } - } + EthVersionedHash, } diff --git a/arbitrator/prover/Cargo.toml b/arbitrator/prover/Cargo.toml index 05d0f40ad..51cbe8439 100644 --- a/arbitrator/prover/Cargo.toml +++ b/arbitrator/prover/Cargo.toml @@ -28,6 +28,8 @@ serde_with = "1.12.1" lazy_static = "1.4.0" smallvec = { version = "1.10.0", features = ["serde"] } arbutil = { path = "../arbutil/" } +c-kzg = "0.4.0" # TODO: look into switching to rust-kzg (no crates.io release or hosted rustdoc yet) +sha2 = "0.9.9" [lib] name = "prover" diff --git a/arbitrator/prover/src/host.rs b/arbitrator/prover/src/host.rs index c66052ad5..cb8b222ca 100644 --- a/arbitrator/prover/src/host.rs +++ b/arbitrator/prover/src/host.rs @@ -51,6 +51,7 @@ pub enum Hostio { WavmSetGlobalStateU64, WavmReadKeccakPreimage, WavmReadSha256Preimage, + WavmReadEthVersionedHashPreimage, WavmReadInboxMessage, WavmReadDelayedInboxMessage, WavmHaltAndSetFinished, @@ -74,6 +75,7 @@ impl FromStr for Hostio { ("env", "wavm_set_globalstate_u64") => WavmSetGlobalStateU64, ("env", "wavm_read_keccak_256_preimage") => WavmReadKeccakPreimage, ("env", "wavm_read_sha2_256_preimage") => WavmReadSha256Preimage, + ("env", "wavm_read_eth_versioned_hash_preimage") => WavmReadEthVersionedHashPreimage, ("env", "wavm_read_inbox_message") => WavmReadInboxMessage, ("env", "wavm_read_delayed_inbox_message") => WavmReadDelayedInboxMessage, ("env", "wavm_halt_and_set_finished") => WavmHaltAndSetFinished, @@ -101,19 +103,20 @@ impl Hostio { #[rustfmt::skip] let ty = match self { - WavmCallerLoad8 => InternalFunc::WavmCallerLoad8.ty(), - WavmCallerLoad32 => InternalFunc::WavmCallerLoad32.ty(), - WavmCallerStore8 => InternalFunc::WavmCallerStore8.ty(), - WavmCallerStore32 => InternalFunc::WavmCallerStore32.ty(), - WavmGetGlobalStateBytes32 => func!([I32, I32]), - WavmSetGlobalStateBytes32 => func!([I32, I32]), - WavmGetGlobalStateU64 => func!([I32], [I64]), - WavmSetGlobalStateU64 => func!([I32, I64]), - WavmReadKeccakPreimage => func!([I32, I32], [I32]), - WavmReadSha256Preimage => func!([I32, I32], [I32]), - WavmReadInboxMessage => func!([I64, I32, I32], [I32]), - WavmReadDelayedInboxMessage => func!([I64, I32, I32], [I32]), - WavmHaltAndSetFinished => func!(), + WavmCallerLoad8 => InternalFunc::WavmCallerLoad8.ty(), + WavmCallerLoad32 => InternalFunc::WavmCallerLoad32.ty(), + WavmCallerStore8 => InternalFunc::WavmCallerStore8.ty(), + WavmCallerStore32 => InternalFunc::WavmCallerStore32.ty(), + WavmGetGlobalStateBytes32 => func!([I32, I32]), + WavmSetGlobalStateBytes32 => func!([I32, I32]), + WavmGetGlobalStateU64 => func!([I32], [I64]), + WavmSetGlobalStateU64 => func!([I32, I64]), + WavmReadKeccakPreimage => func!([I32, I32], [I32]), + WavmReadSha256Preimage => func!([I32, I32], [I32]), + WavmReadEthVersionedHashPreimage => func!([I32, I32], [I32]), + WavmReadInboxMessage => func!([I64, I32, I32], [I32]), + WavmReadDelayedInboxMessage => func!([I64, I32, I32], [I32]), + WavmHaltAndSetFinished => func!(), }; ty } @@ -180,6 +183,11 @@ impl Hostio { opcode!(LocalGet, 1); opcode!(ReadPreImage, PreimageType::Sha2_256); } + WavmReadEthVersionedHashPreimage => { + opcode!(LocalGet, 0); + opcode!(LocalGet, 1); + opcode!(ReadPreImage, PreimageType::EthVersionedHash); + } WavmReadInboxMessage => { opcode!(LocalGet, 0); opcode!(LocalGet, 1); diff --git a/arbitrator/prover/src/kzg-trusted-setup.json b/arbitrator/prover/src/kzg-trusted-setup.json new file mode 100644 index 000000000..c6d724efa --- /dev/null +++ b/arbitrator/prover/src/kzg-trusted-setup.json @@ -0,0 +1,4167 @@ +{ + "g1_lagrange": [ + "0xa0413c0dcafec6dbc9f47d66785cf1e8c981044f7d13cfe3e4fcbb71b5408dfde6312493cb3c1d30516cb3ca88c03654", + "0x8b997fb25730d661918371bb41f2a6e899cac23f04fc5365800b75433c0a953250e15e7a98fb5ca5cc56a8cd34c20c57", + "0x83302852db89424d5699f3f157e79e91dc1380f8d5895c5a772bb4ea3a5928e7c26c07db6775203ce33e62a114adaa99", + "0xa759c48b7e4a685e735c01e5aa6ef9c248705001f470f9ad856cd87806983e917a8742a3bd5ee27db8d76080269b7c83", + "0x967f8dc45ebc3be14c8705f43249a30ff48e96205fb02ae28daeab47b72eb3f45df0625928582aa1eb4368381c33e127", + "0xa418eb1e9fb84cb32b370610f56f3cb470706a40ac5a47c411c464299c45c91f25b63ae3fcd623172aa0f273c0526c13", + "0x8f44e3f0387293bc7931e978165abbaed08f53acd72a0a23ac85f6da0091196b886233bcee5b4a194db02f3d5a9b3f78", + "0x97173434b336be73c89412a6d70d416e170ea355bf1956c32d464090b107c090ef2d4e1a467a5632fbc332eeb679bf2d", + "0xa24052ad8d55ad04bc5d951f78e14213435681594110fd18173482609d5019105b8045182d53ffce4fc29fc8810516c1", + "0xb950768136b260277590b5bec3f56bbc2f7a8bc383d44ce8600e85bf8cf19f479898bcc999d96dfbd2001ede01d94949", + "0x92ab8077871037bd3b57b95cbb9fb10eb11efde9191690dcac655356986fd02841d8fdb25396faa0feadfe3f50baf56d", + "0xa79b096dff98038ac30f91112dd14b78f8ad428268af36d20c292e2b3b6d9ed4fb28480bb04e465071cc67d05786b6d1", + "0xb9ff71461328f370ce68bf591aa7fb13027044f42a575517f3319e2be4aa4843fa281e756d0aa5645428d6dfa857cef2", + "0x8d765808c00b3543ff182e2d159c38ae174b12d1314da88ea08e13bd9d1c37184cb515e6bf6420531b5d41767987d7ce", + "0xb8c9a837d20c3b53e6f578e4a257bb7ef8fc43178614ec2a154915b267ad2be135981d01ed2ee1b5fbd9d9bb27f0800a", + "0xa9773d92cf23f65f98ef68f6cf95c72b53d0683af2f9bf886bb9036e4a38184b1131b26fd24397910b494fbef856f3aa", + "0xb41ebe38962d112da4a01bf101cb248d808fbd50aaf749fc7c151cf332032eb3e3bdbd716db899724b734d392f26c412", + "0x90fbb030167fb47dcc13d604a726c0339418567c1d287d1d87423fa0cb92eec3455fbb46bcbe2e697144a2d3972142e4", + "0xb11d298bd167464b35fb923520d14832bd9ed50ed841bf6d7618424fd6f3699190af21759e351b89142d355952149da1", + "0x8bc36066f69dc89f7c4d1e58d67497675050c6aa002244cebd9fc957ec5e364c46bab4735ea3db02b73b3ca43c96e019", + "0xab7ab92c5d4d773068e485aa5831941ebd63db7118674ca38089635f3b4186833af2455a6fb9ed2b745df53b3ce96727", + "0xaf191ca3089892cb943cd97cf11a51f38e38bd9be50844a4e8da99f27e305e876f9ed4ab0628e8ae3939066b7d34a15f", + "0xa3204c1747feabc2c11339a542195e7cb6628fd3964f846e71e2e3f2d6bb379a5e51700682ea1844eba12756adb13216", + "0x903a29883846b7c50c15968b20e30c471aeac07b872c40a4d19eb1a42da18b649d5bbfde4b4cf6225d215a461b0deb6d", + "0x8e6e9c15ffbf1e16e5865a5fef7ed751dc81957a9757b535cb38b649e1098cda25d42381dc4f776778573cdf90c3e6e0", + "0xa8f6dd26100b512a8c96c52e00715c4b2cb9ac457f17aed8ffe1cf1ea524068fe5a1ddf218149845fc1417b789ecfc98", + "0xa5b0ffc819451ea639cfd1c18cbc9365cc79368d3b2e736c0ae54eba2f0801e6eb0ee14a5f373f4a70ca463bdb696c09", + "0x879f91ccd56a1b9736fbfd20d8747354da743fb121f0e308a0d298ff0d9344431890e41da66b5009af3f442c636b4f43", + "0x81bf3a2d9755e206b515a508ac4d1109bf933c282a46a4ae4a1b4cb4a94e1d23642fad6bd452428845afa155742ade7e", + "0x8de778d4742f945df40004964e165592f9c6b1946263adcdd5a88b00244bda46c7bb49098c8eb6b3d97a0dd46148a8ca", + "0xb7a57b21d13121907ee28c5c1f80ee2e3e83a3135a8101e933cf57171209a96173ff5037f5af606e9fd6d066de6ed693", + "0xb0877d1963fd9200414a38753dffd9f23a10eb3198912790d7eddbc9f6b477019d52ddd4ebdcb9f60818db076938a5a9", + "0x88da2d7a6611bc16adc55fc1c377480c828aba4496c645e3efe0e1a67f333c05a0307f7f1d2df8ac013602c655c6e209", + "0x95719eb02e8a9dede1a888c656a778b1c69b7716fbe3d1538fe8afd4a1bc972183c7d32aa7d6073376f7701df80116d8", + "0x8e8a1ca971f2444b35af3376e85dccda3abb8e8e11d095d0a4c37628dfe5d3e043a377c3de68289ef142e4308e9941a0", + "0xb720caaff02f6d798ac84c4f527203e823ff685869e3943c979e388e1c34c3f77f5c242c6daa7e3b30e511aab917b866", + "0x86040d55809afeec10e315d1ad950d269d37cfee8c144cd8dd4126459e3b15a53b3e68df5981df3c2346d23c7b4baaf4", + "0x82d8cabf13ab853db0377504f0aec00dba3a5cd3119787e8ad378ddf2c40b022ecfc67c642b7acc8c1e3dd03ab50993e", + "0xb8d873927936719d2484cd03a6687d65697e17dcf4f0d5aed6f5e4750f52ef2133d4645894e7ebfc4ef6ce6788d404c8", + "0xb1235594dbb15b674a419ff2b2deb644ad2a93791ca05af402823f87114483d6aa1689b7a9bea0f547ad12fe270e4344", + "0xa53fda86571b0651f5affb74312551a082fffc0385cfd24c1d779985b72a5b1cf7c78b42b4f7e51e77055f8e5e915b00", + "0xb579adcfd9c6ef916a5a999e77a0cb21d378c4ea67e13b7c58709d5da23a56c2e54218691fc4ac39a4a3d74f88cc31f7", + "0xab79e584011713e8a2f583e483a91a0c2a40771b77d91475825b5acbea82db4262132901cb3e4a108c46d7c9ee217a4e", + "0xa0fe58ea9eb982d7654c8aaf9366230578fc1362f6faae0594f8b9e659bcb405dff4aac0c7888bbe07f614ecf0d800a6", + "0x867e50e74281f28ecd4925560e2e7a6f8911b135557b688254623acce0dbc41e23ac3e706a184a45d54c586edc416eb0", + "0x89f81b61adda20ea9d0b387a36d0ab073dc7c7cbff518501962038be19867042f11fcc7ff78096e5d3b68c6d8dc04d9b", + "0xa58ee91bb556d43cf01f1398c5811f76dc0f11efdd569eed9ef178b3b0715e122060ec8f945b4dbf6eebfa2b90af6fa6", + "0xac460be540f4c840def2eef19fc754a9af34608d107cbadb53334cf194cc91138d53b9538fcd0ec970b5d4aa455b224a", + "0xb09b91f929de52c09d48ca0893be6eb44e2f5210a6c394689dc1f7729d4be4e11d0474b178e80cea8c2ac0d081f0e811", + "0x8d37a442a76b06a02a4e64c2504aea72c8b9b020ab7bcc94580fe2b9603c7c50d7b1e9d70d2a7daea19c68667e8f8c31", + "0xa9838d4c4e3f3a0075a952cf7dd623307ec633fcc81a7cf9e52e66c31780de33dbb3d74c320dc7f0a4b72f7a49949515", + "0xa44766b6251af458fe4f5f9ed1e02950f35703520b8656f09fc42d9a2d38a700c11a7c8a0436ac2e5e9f053d0bb8ff91", + "0xad78d9481c840f5202546bea0d13c776826feb8b1b7c72e83d99a947622f0bf38a4208551c4c41beb1270d7792075457", + "0xb619ffa8733b470039451e224b777845021e8dc1125f247a4ff2476cc774657d0ff9c5279da841fc1236047de9d81c60", + "0xaf760b0a30a1d6af3bc5cd6686f396bd41779aeeb6e0d70a09349bd5da17ca2e7965afc5c8ec22744198fbe3f02fb331", + "0xa0cc209abdb768b589fcb7b376b6e1cac07743288c95a1cf1a0354b47f0cf91fca78a75c1fcafa6f5926d6c379116608", + "0x864add673c89c41c754eeb3cd8dcff5cdde1d739fce65c30e474a082bb5d813cba6412e61154ce88fdb6c12c5d9be35b", + "0xb091443b0ce279327dc37cb484e9a5b69b257a714ce21895d67539172f95ffa326903747b64a3649e99aea7bb10d03f7", + "0xa8c452b8c4ca8e0a61942a8e08e28f17fb0ef4c5b018b4e6d1a64038280afa2bf1169202f05f14af24a06ca72f448ccd", + "0xa23c24721d18bc48d5dcf70effcbef89a7ae24e67158d70ae1d8169ee75d9a051d34b14e9cf06488bac324fe58549f26", + "0x92a730e30eb5f3231feb85f6720489dbb1afd42c43f05a1610c6b3c67bb949ec8fde507e924498f4ffc646f7b07d9123", + "0x8dbe5abf4031ec9ba6bb06d1a47dd1121fb9e03b652804069250967fd5e9577d0039e233441b7f837a7c9d67ba18c28e", + "0xaa456bcfef6a21bb88181482b279df260297b3778e84594ebddbdf337e85d9e3d46ca1d0b516622fb0b103df8ec519b7", + "0xa3b31ae621bd210a2b767e0e6f22eb28fe3c4943498a7e91753225426168b9a26da0e02f1dc5264da53a5ad240d9f51b", + "0xaa8d66857127e6e71874ce2202923385a7d2818b84cb73a6c42d71afe70972a70c6bdd2aad1a6e8c5e4ca728382a8ea8", + "0xac7e8e7a82f439127a5e40558d90d17990f8229852d21c13d753c2e97facf077cf59582b603984c3dd3faebd80aff4f5", + "0x93a8bcf4159f455d1baa73d2ef2450dcd4100420de84169bbe28b8b7a5d1746273f870091a87a057e834f754f34204b1", + "0x89d0ebb287c3613cdcae7f5acc43f17f09c0213fc40c074660120b755d664109ffb9902ed981ede79e018ddb0c845698", + "0xa87ccbfad431406aadbee878d9cf7d91b13649d5f7e19938b7dfd32645a43b114eef64ff3a13201398bd9b0337832e5a", + "0x833c51d0d0048f70c3eefb4e70e4ff66d0809c41838e8d2c21c288dd3ae9d9dfaf26d1742bf4976dab83a2b381677011", + "0x8bcd6b1c3b02fffead432e8b1680bad0a1ac5a712d4225e220690ee18df3e7406e2769e1f309e2e803b850bc96f0e768", + "0xb61e3dbd88aaf4ff1401521781e2eea9ef8b66d1fac5387c83b1da9e65c2aa2a56c262dea9eceeb4ad86c90211672db0", + "0x866d3090db944ecf190dd0651abf67659caafd31ae861bab9992c1e3915cb0952da7c561cc7e203560a610f48fae633b", + "0xa5e8971543c14274a8dc892b0be188c1b4fbc75c692ed29f166e0ea80874bc5520c2791342b7c1d2fb5dd454b03b8a5b", + "0x8f2f9fc50471bae9ea87487ebd1bc8576ef844cc42d606af5c4c0969670fdf2189afd643e4de3145864e7773d215f37f", + "0xb1bb0f2527db6d51f42b9224383c0f96048bbc03d469bf01fe1383173ef8b1cc9455d9dd8ba04d46057f46949bfc92b5", + "0xaa7c99d906b4d7922296cfe2520473fc50137c03d68b7865c5bfb8adbc316b1034310ec4b5670c47295f4a80fb8d61e9", + "0xa5d1da4d6aba555919df44cbaa8ff79378a1c9e2cfdfbf9d39c63a4a00f284c5a5724e28ecbc2d9dba27fe4ee5018bd5", + "0xa8db53224f70af4d991b9aae4ffe92d2aa5b618ad9137784b55843e9f16cefbfd25ada355d308e9bbf55f6d2f7976fb3", + "0xb6536c4232bb20e22af1a8bb12de76d5fec2ad9a3b48af1f38fa67e0f8504ef60f305a73d19385095bb6a9603fe29889", + "0x87f7e371a1817a63d6838a8cf4ab3a8473d19ce0d4f40fd013c03d5ddd5f4985df2956531cc9f187928ef54c68f4f9a9", + "0xae13530b1dbc5e4dced9d909ea61286ec09e25c12f37a1ed2f309b0eb99863d236c3b25ed3484acc8c076ad2fa8cd430", + "0x98928d850247c6f7606190e687d5c94a627550198dbdbea0161ef9515eacdb1a0f195cae3bb293112179082daccf8b35", + "0x918528bb8e6a055ad4db6230d3a405e9e55866da15c4721f5ddd1f1f37962d4904aad7a419218fe6d906fe191a991806", + "0xb71e31a06afe065773dd3f4a6e9ef81c3292e27a3b7fdfdd452d03e05af3b6dd654c355f7516b2a93553360c6681a73a", + "0x8870b83ab78a98820866f91ac643af9f3ff792a2b7fda34185a9456a63abdce42bfe8ad4dc67f08a6392f250d4062df4", + "0x91eea1b668e52f7a7a5087fabf1cab803b0316f78d9fff469fbfde2162f660c250e4336a9eea4cb0450bd30ac067bc8b", + "0x8b74990946de7b72a92147ceac1bd9d55999a8b576e8df68639e40ed5dc2062cfcd727903133de482b6dca19d0aaed82", + "0x8ebad537fece090ebbab662bdf2618e21ca30cf6329c50935e8346d1217dcbe3c1fe1ea28efca369c6003ce0a94703c1", + "0xa8640479556fb59ebd1c40c5f368fbd960932fdbb782665e4a0e24e2bdb598fc0164ce8c0726d7759cfc59e60a62e182", + "0xa9a52a6bf98ee4d749f6d38be2c60a6d54b64d5cbe4e67266633dc096cf28c97fe998596707d31968cbe2064b72256bf", + "0x847953c48a4ce6032780e9b39d0ed4384e0be202c2bbe2dfda3910f5d87aa5cd3c2ffbfcfae4dddce16d6ab657599b95", + "0xb6f6e1485d3ec2a06abaecd23028b200b2e4a0096c16144d07403e1720ff8f9ba9d919016b5eb8dc5103880a7a77a1d3", + "0x98dfc2065b1622f596dbe27131ea60bef7a193b12922cecb27f8c571404f483014f8014572e86ae2e341ab738e4887ef", + "0xacb0d205566bacc87bbe2e25d10793f63f7a1f27fd9e58f4f653ceae3ffeba511eaf658e068fad289eeb28f9edbeb35b", + "0xae4411ed5b263673cee894c11fe4abc72a4bf642d94022a5c0f3369380fcdfc1c21e277f2902972252503f91ada3029a", + "0xac4a7a27ba390a75d0a247d93d4a8ef1f0485f8d373a4af4e1139369ec274b91b3464d9738eeaceb19cd6f509e2f8262", + "0x87379c3bf231fdafcf6472a79e9e55a938d851d4dd662ab6e0d95fd47a478ed99e2ad1e6e39be3c0fc4f6d996a7dd833", + "0x81316904b035a8bcc2041199a789a2e6879486ba9fddcba0a82c745cc8dd8374a39e523b91792170cd30be7aa3005b85", + "0xb8206809c6cd027ed019f472581b45f7e12288f89047928ba32b4856b6560ad30395830d71e5e30c556f6f182b1fe690", + "0x88d76c028f534a62e019b4a52967bb8642ede6becfa3807be68fdd36d366fc84a4ac8dc176e80a68bc59eb62caf5dff9", + "0x8c3b8be685b0f8aad131ee7544d0e12f223f08a6f8edaf464b385ac644e0ddc9eff7cc7cb5c1b50ab5d71ea0f41d2213", + "0x8d91410e004f76c50fdc05784157b4d839cb5090022c629c7c97a5e0c3536eeafee17a527b54b1165c3cd81774bb54ce", + "0xb25c2863bc28ec5281ce800ddf91a7e1a53f4c6d5da1e6c86ef4616e93bcf55ed49e297216d01379f5c6e7b3c1e46728", + "0x865f7b09ac3ca03f20be90c48f6975dd2588838c2536c7a3532a6aa5187ed0b709cd03d91ff4048061c10d0aa72b69ce", + "0xb3f7477c90c11596eb4f8bbf34adbcb832638c4ff3cdd090d4d477ee50472ac9ddaf5be9ad7eca3f148960d362bbd098", + "0x8db35fd53fca04faecd1c76a8227160b3ab46ac1af070f2492445a19d8ff7c25bbaef6c9fa0c8c088444561e9f7e4eb2", + "0xa478b6e9d058a2e01d2fc053b739092e113c23a6a2770a16afbef044a3709a9e32f425ace9ba7981325f02667c3f9609", + "0x98caa6bd38916c08cf221722a675a4f7577f33452623de801d2b3429595f988090907a7e99960fff7c076d6d8e877b31", + "0xb79aaaacefc49c3038a14d2ac468cfec8c2161e88bdae91798d63552cdbe39e0e02f9225717436b9b8a40a022c633c6e", + "0x845a31006c680ee6a0cc41d3dc6c0c95d833fcf426f2e7c573fa15b2c4c641fbd6fe5ebb0e23720cc3467d6ee1d80dc4", + "0xa1bc287e272cf8b74dbf6405b3a5190883195806aa351f1dc8e525aa342283f0a35ff687e3b434324dedee74946dd185", + "0xa4fd2dc8db75d3783a020856e2b3aa266dc6926e84f5c491ef739a3bddd46dc8e9e0fc1177937839ef1b18d062ffbb9e", + "0xacbf0d3c697f57c202bb8c5dc4f3fc341b8fc509a455d44bd86acc67cad2a04495d5537bcd3e98680185e8aa286f2587", + "0xa5caf423a917352e1b8e844f5968a6da4fdeae467d10c6f4bbd82b5eea46a660b82d2f5440d3641c717b2c3c9ed0be52", + "0x8a39d763c08b926599ab1233219c49c825368fad14d9afc7c0c039224d37c00d8743293fd21645bf0b91eaf579a99867", + "0xb2b53a496def0ba06e80b28f36530fbe0fb5d70a601a2f10722e59abee529369c1ae8fd0f2db9184dd4a2519bb832d94", + "0xa73980fcef053f1b60ebbb5d78ba6332a475e0b96a0c724741a3abf3b59dd344772527f07203cf4c9cb5155ebed81fa0", + "0xa070d20acce42518ece322c9db096f16aed620303a39d8d5735a0df6e70fbeceb940e8d9f5cc38f3314b2240394ec47b", + "0xa50cf591f522f19ca337b73089557f75929d9f645f3e57d4f241e14cdd1ea3fb48d84bcf05e4f0377afbb789fbdb5d20", + "0x82a5ffce451096aca8eeb0cd2ae9d83db3ed76da3f531a80d9a70a346359bf05d74863ce6a7c848522b526156a5e20cd", + "0x88e0e84d358cbb93755a906f329db1537c3894845f32b9b0b691c29cbb455373d9452fadd1e77e20a623f6eaf624de6f", + "0xaa07ac7b84a6d6838826e0b9e350d8ec75e398a52e9824e6b0da6ae4010e5943fec4f00239e96433f291fef9d1d1e609", + "0xac8887bf39366034bc63f6cc5db0c26fd27307cbc3d6cce47894a8a019c22dd51322fb5096edc018227edfafc053a8f6", + "0xb7d26c26c5b33f77422191dca94977588ab1d4b9ce7d0e19c4a3b4cd1c25211b78c328dbf81e755e78cd7d1d622ad23e", + "0x99a676d5af49f0ba44047009298d8474cabf2d5bca1a76ba21eff7ee3c4691a102fdefea27bc948ccad8894a658abd02", + "0xb0d09a91909ab3620c183bdf1d53d43d39eb750dc7a722c661c3de3a1a5d383ad221f71bae374f8a71867505958a3f76", + "0x84681a883de8e4b93d68ac10e91899c2bbb815ce2de74bb48a11a6113b2a3f4df8aceabda1f5f67bc5aacac8c9da7221", + "0x9470259957780fa9b43521fab3644f555f5343281c72582b56d2efd11991d897b3b481cafa48681c5aeb80c9663b68f7", + "0xab1b29f7ece686e6fa968a4815da1d64f3579fed3bc92e1f3e51cd13a3c076b6cf695ed269d373300a62463dc98a4234", + "0x8ab415bfcd5f1061f7687597024c96dd9c7cb4942b5989379a7a3b5742f7d394337886317659cbeacaf030234a24f972", + "0xb9b524aad924f9acc63d002d617488f31b0016e0f0548f050cada285ce7491b74a125621638f19e9c96eabb091d945be", + "0x8c4c373e79415061837dd0def4f28a2d5d74d21cb13a76c9049ad678ca40228405ab0c3941df49249847ecdefc1a5b78", + "0xa8edf4710b5ab2929d3db6c1c0e3e242261bbaa8bcec56908ddadd7d2dad2dca9d6eb9de630b960b122ebeea41040421", + "0x8d66bb3b50b9df8f373163629f9221b3d4b6980a05ea81dc3741bfe9519cf3ebba7ab98e98390bae475e8ede5821bd5c", + "0x8d3c21bae7f0cfb97c56952bb22084b58e7bb718890935b73103f33adf5e4d99cd262f929c6eeab96209814f0dbae50a", + "0xa5c66cfab3d9ebf733c4af24bebc97070e7989fe3c73e79ac85fb0e4d40ae44fb571e0fad4ad72560e13ed453900d14f", + "0x9362e6b50b43dbefbc3254471372297b5dcce809cd3b60bf74a1268ab68bdb50e46e462cbd78f0d6c056330e982846af", + "0x854630d08e3f0243d570cc2e856234cb4c1a158d9c1883bf028a76525aaa34be897fe918d5f6da9764a3735fa9ebd24a", + "0x8c7d246985469ff252c3f4df6c7c9196fc79f05c1c66a609d84725c78001d0837c7a7049394ba5cf7e863e2d58af8417", + "0xae050271e01b528925302e71903f785b782f7bf4e4e7a7f537140219bc352dc7540c657ed03d3a297ad36798ecdb98cd", + "0x8d2ae9179fcf2b0c69850554580b52c1f4a5bd865af5f3028f222f4acad9c1ad69a8ef6c7dc7b03715ee5c506b74325e", + "0xb8ef8de6ce6369a8851cd36db0ccf00a85077e816c14c4e601f533330af9e3acf0743a95d28962ed8bfcfc2520ef3cfe", + "0xa6ecad6fdfb851b40356a8b1060f38235407a0f2706e7b8bb4a13465ca3f81d4f5b99466ac2565c60af15f022d26732e", + "0x819ff14cdea3ab89d98e133cd2d0379361e2e2c67ad94eeddcdb9232efd509f51d12f4f03ebd4dd953bd262a886281f7", + "0x8561cd0f7a6dbcddd83fcd7f472d7dbcba95b2d4fb98276f48fccf69f76d284e626d7e41314b633352df8e6333fd52a1", + "0xb42557ccce32d9a894d538c48712cb3e212d06ac05cd5e0527ccd2db1078ee6ae399bf6a601ffdab1f5913d35fc0b20c", + "0x89b4008d767aad3c6f93c349d3b956e28307311a5b1cec237e8d74bb0dee7e972c24f347fd56afd915a2342bd7bc32f0", + "0x877487384b207e53f5492f4e36c832c2227f92d1bb60542cfeb35e025a4a7afc2b885fae2528b33b40ab09510398f83e", + "0x8c411050b63c9053dd0cd81dacb48753c3d7f162028098e024d17cd6348482703a69df31ad6256e3d25a8bbf7783de39", + "0xa8506b54a88d17ac10fb1b0d1fe4aa40eae7553a064863d7f6b52ccc4236dd4b82d01dca6ba87da9a239e3069ba879fb", + "0xb1a24caef9df64750c1350789bb8d8a0db0f39474a1c74ea9ba064b1516db6923f00af8d57c632d58844fb8786c3d47a", + "0x959d6e255f212b0708c58a2f75cb1fe932248c9d93424612c1b8d1e640149656059737e4db2139afd5556bcdacf3eda2", + "0x84525af21a8d78748680b6535bbc9dc2f0cf9a1d1740d12f382f6ecb2e73811d6c1da2ad9956070b1a617c61fcff9fe5", + "0xb74417d84597a485d0a8e1be07bf78f17ebb2e7b3521b748f73935b9afbbd82f34b710fb7749e7d4ab55b0c7f9de127d", + "0xa4a9aecb19a6bab167af96d8b9d9aa5308eab19e6bfb78f5a580f9bf89bdf250a7b52a09b75f715d651cb73febd08e84", + "0x9777b30be2c5ffe7d29cc2803a562a32fb43b59d8c3f05a707ab60ec05b28293716230a7d264d7cd9dd358fc031cc13e", + "0x95dce7a3d4f23ac0050c510999f5fbf8042f771e8f8f94192e17bcbfa213470802ebdbe33a876cb621cf42e275cbfc8b", + "0xb0b963ebcbbee847ab8ae740478544350b3ac7e86887e4dfb2299ee5096247cd2b03c1de74c774d9bde94ae2ee2dcd59", + "0xa4ab20bafa316030264e13f7ef5891a2c3b29ab62e1668fcb5881f50a9acac6adbe3d706c07e62f2539715db768f6c43", + "0x901478a297669d608e406fe4989be75264b6c8be12169aa9e0ad5234f459ca377f78484ffd2099a2fe2db5e457826427", + "0x88c76e5c250810c057004a03408b85cd918e0c8903dc55a0dd8bb9b4fc2b25c87f9b8cf5943eb19fbbe99d36490050c5", + "0x91607322bbad4a4f03fc0012d0821eff5f8c516fda45d1ec1133bface6f858bf04b25547be24159cab931a7aa08344d4", + "0x843203e07fce3c6c81f84bc6dc5fb5e9d1c50c8811ace522dc66e8658433a0ef9784c947e6a62c11bf705307ef05212e", + "0x91dd8813a5d6dddcda7b0f87f672b83198cd0959d8311b2b26fb1fae745185c01f796fbd03aad9db9b58482483fdadd8", + "0x8d15911aacf76c8bcd7136e958febd6963104addcd751ce5c06b6c37213f9c4fb0ffd4e0d12c8e40c36d658999724bfd", + "0x8a36c5732d3f1b497ebe9250610605ee62a78eaa9e1a45f329d09aaa1061131cf1d9df00f3a7d0fe8ad614a1ff9caaae", + "0xa407d06affae03660881ce20dab5e2d2d6cddc23cd09b95502a9181c465e57597841144cb34d22889902aff23a76d049", + "0xb5fd856d0578620a7e25674d9503be7d97a2222900e1b4738c1d81ff6483b144e19e46802e91161e246271f90270e6cf", + "0x91b7708869cdb5a7317f88c0312d103f8ce90be14fb4f219c2e074045a2a83636fdc3e69e862049fc7c1ef000e832541", + "0xb64719cc5480709d1dae958f1d3082b32a43376da446c8f9f64cb02a301effc9c34d9102051733315a8179aed94d53cc", + "0x94347a9542ff9d18f7d9eaa2f4d9b832d0e535fe49d52aa2de08aa8192400eddabdb6444a2a78883e27c779eed7fdf5a", + "0x840ef44a733ff1376466698cd26f82cf56bb44811e196340467f932efa3ae1ef9958a0701b3b032f50fd9c1d2aed9ab5", + "0x90ab3f6f67688888a31ffc2a882bb37adab32d1a4b278951a21646f90d03385fc976715fc639a785d015751171016f10", + "0xb56f35d164c24b557dbcbc8a4bfa681ec916f8741ffcb27fb389c164f4e3ed2be325210ef5bdaeae7a172ca9599ab442", + "0xa7921a5a80d7cf6ae81ba9ee05e0579b18c20cd2852762c89d6496aa4c8ca9d1ca2434a67b2c16d333ea8e382cdab1e3", + "0xa506bcfbd7e7e5a92f68a1bd87d07ad5fe3b97aeee40af2bf2cae4efcd77fff03f872732c5b7883aa6584bee65d6f8cb", + "0xa8c46cff58931a1ce9cbe1501e1da90b174cddd6d50f3dfdfb759d1d4ad4673c0a8feed6c1f24c7af32865a7d6c984e5", + "0xb45686265a83bff69e312c5149db7bb70ac3ec790dc92e392b54d9c85a656e2bf58596ce269f014a906eafc97461aa5f", + "0x8d4009a75ccb2f29f54a5f16684b93202c570d7a56ec1a8b20173269c5f7115894f210c26b41e8d54d4072de2d1c75d0", + "0xaef8810af4fc676bf84a0d57b189760ddc3375c64e982539107422e3de2580b89bd27aa6da44e827b56db1b5555e4ee8", + "0x888f0e1e4a34f48eb9a18ef4de334c27564d72f2cf8073e3d46d881853ac1424d79e88d8ddb251914890588937c8f711", + "0xb64b0aa7b3a8f6e0d4b3499fe54e751b8c3e946377c0d5a6dbb677be23736b86a7e8a6be022411601dd75012012c3555", + "0x8d57776f519f0dd912ea14f79fbab53a30624e102f9575c0bad08d2dc754e6be54f39b11278c290977d9b9c7c0e1e0ad", + "0xa018fc00d532ceb2e4de908a15606db9b6e0665dd77190e2338da7c87a1713e6b9b61554e7c1462f0f6d4934b960b15c", + "0x8c932be83ace46f65c78e145b384f58e41546dc0395270c1397874d88626fdeda395c8a289d602b4c312fe98c1311856", + "0x89174838e21639d6bdd91a0621f04dc056907b88e305dd66e46a08f6d65f731dea72ae87ca5e3042d609e8de8de9aa26", + "0xb7b7f508bb74f7a827ac8189daa855598ff1d96fa3a02394891fd105d8f0816224cd50ac4bf2ed1cf469ace516c48184", + "0xb31877ad682583283baadd68dc1bebd83f5748b165aadd7fe9ef61a343773b88bcd3a022f36d6c92f339b7bfd72820a9", + "0xb79d77260b25daf9126dab7a193df2d7d30542786fa1733ffaf6261734770275d3ca8bae1d9915d1181a78510b3439db", + "0x91894fb94cd4c1dd2ceaf9c53a7020c5799ba1217cf2d251ea5bc91ed26e1159dd758e98282ebe35a0395ef9f1ed15a0", + "0xab59895cdafd33934ceedfc3f0d5d89880482cba6c99a6db93245f9e41987efd76e0640e80aef31782c9a8c7a83fccec", + "0xaa22ea63654315e033e09d4d4432331904a6fc5fb1732557987846e3c564668ca67c60a324b4af01663a23af11a9ce4b", + "0xb53ba3ef342601467e1f71aa280e100fbabbd38518fa0193e0099505036ee517c1ac78e96e9baeb549bb6879bb698fb0", + "0x943fd69fd656f37487cca3605dc7e5a215fddd811caf228595ec428751fc1de484a0cb84c667fe4d7c35599bfa0e5e34", + "0x9353128b5ebe0dddc555093cf3e5942754f938173541033e8788d7331fafc56f68d9f97b4131e37963ab7f1c8946f5f1", + "0xa76cd3c566691f65cfb86453b5b31dbaf3cab8f84fe1f795dd1e570784b9b01bdd5f0b3c1e233942b1b5838290e00598", + "0x983d84b2e53ffa4ae7f3ba29ef2345247ea2377686b74a10479a0ef105ecf90427bf53b74c96dfa346d0f842b6ffb25b", + "0x92e0fe9063306894a2c6970c001781cff416c87e87cb5fbac927a3192655c3da4063e6fa93539f6ff58efac6adcc5514", + "0xb00a81f03c2b8703acd4e2e4c21e06973aba696415d0ea1a648ace2b0ea19b242fede10e4f9d7dcd61c546ab878bc8f9", + "0xb0d08d880f3b456a10bf65cff983f754f545c840c413aea90ce7101a66eb0a0b9b1549d6c4d57725315828607963f15a", + "0x90cb64d03534f913b411375cce88a9e8b1329ce67a9f89ca5df8a22b8c1c97707fec727dbcbb9737f20c4cf751359277", + "0x8327c2d42590dfcdb78477fc18dcf71608686ad66c49bce64d7ee874668be7e1c17cc1042a754bbc77c9daf50b2dae07", + "0x8532171ea13aa7e37178e51a6c775da469d2e26ec854eb16e60f3307db4acec110d2155832c202e9ba525fc99174e3b0", + "0x83ca44b15393d021de2a511fa5511c5bd4e0ac7d67259dce5a5328f38a3cce9c3a269405959a2486016bc27bb140f9ff", + "0xb1d36e8ca812be545505c8214943b36cabee48112cf0de369957afa796d37f86bf7249d9f36e8e990f26f1076f292b13", + "0x9803abf45be5271e2f3164c328d449efc4b8fc92dfc1225d38e09630909fe92e90a5c77618daa5f592d23fc3ad667094", + "0xb268ad68c7bf432a01039cd889afae815c3e120f57930d463aece10af4fd330b5bd7d8869ef1bcf6b2e78e4229922edc", + "0xa4c91a0d6f16b1553264592b4cbbbf3ca5da32ab053ffbdd3dbb1aed1afb650fb6e0dc5274f71a51d7160856477228db", + "0xad89d043c2f0f17806277ffdf3ecf007448e93968663f8a0b674254f36170447b7527d5906035e5e56f4146b89b5af56", + "0x8b6964f757a72a22a642e4d69102951897e20c21449184e44717bd0681d75f7c5bfa5ee5397f6e53febf85a1810d6ed1", + "0xb08f5cdaabec910856920cd6e836c830b863eb578423edf0b32529488f71fe8257d90aed4a127448204df498b6815d79", + "0xaf26bb3358be9d280d39b21d831bb53145c4527a642446073fee5a86215c4c89ff49a3877a7a549486262f6f57a0f476", + "0xb4010b37ec4d7c2af20800e272539200a6b623ae4636ecbd0e619484f4ab9240d02bc5541ace3a3fb955dc0a3d774212", + "0x82752ab52bdcc3cc2fc405cb05a2e694d3df4a3a68f2179ec0652536d067b43660b96f85f573f26fbd664a9ef899f650", + "0x96d392dde067473a81faf2d1fea55b6429126b88b160e39b4210d31d0a82833ffd3a80e07d24d495aea2d96be7251547", + "0xa76d8236d6671204d440c33ac5b8deb71fa389f6563d80e73be8b043ec77d4c9b06f9a586117c7f957f4af0331cbc871", + "0xb6c90961f68b5e385d85c9830ec765d22a425f506904c4d506b87d8944c2b2c09615e740ed351df0f9321a7b93979cae", + "0xa6ec5ea80c7558403485b3b1869cdc63bde239bafdf936d9b62a37031628402a36a2cfa5cfbb8e26ac922cb0a209b3ba", + "0x8c3195bbdbf9bc0fc95fa7e3d7f739353c947f7767d1e3cb24d8c8602d8ea0a1790ac30b815be2a2ba26caa5227891e2", + "0xa7f8a63d809f1155722c57f375ea00412b00147776ae4444f342550279ef4415450d6f400000a326bf11fea6c77bf941", + "0x97fa404df48433a00c85793440e89bb1af44c7267588ae937a1f5d53e01e1c4d4fc8e4a6d517f3978bfdd6c2dfde012f", + "0xa984a0a3836de3d8d909c4629a2636aacb85393f6f214a2ef68860081e9db05ad608024762db0dc35e895dc00e2d4cdd", + "0x9526cf088ab90335add1db4d3a4ac631b58cbfbe88fa0845a877d33247d1cfeb85994522e1eb8f8874651bfb1df03e2a", + "0xac83443fd0afe99ad49de9bf8230158c118e2814c9c89db5ac951c240d6c2ce45e7677221279d9e97848ec466b99aafe", + "0xaeeefdbaba612e971697798ceaf63b247949dc823a0ad771ae5b988a5e882b338a98d3d0796230f49d533ec5ba411b39", + "0xae3f248b5a7b0f92b7820a6c5ae21e5bd8f4265d4f6e21a22512079b8ee9be06393fd3133ce8ebac0faf23f4f8517e36", + "0xa64a831b908eee784b8388b45447d2885ec0551b26b0c2b15e5f417d0a12c79e867fb7bd3d008d0af98b44336f8ec1ad", + "0xb242238cd8362b6e440ba21806905714dd55172db25ec7195f3fc4937b2aba146d5cbf3cf691a1384b4752dc3b54d627", + "0x819f97f337eea1ffb2a678cc25f556f1aab751c6b048993a1d430fe1a3ddd8bb411c152e12ca60ec6e057c190cd1db9a", + "0xb9d7d187407380df54ee9fef224c54eec1bfabf17dc8abf60765b7951f538f59aa26fffd5846cfe05546c35f59b573f4", + "0xaa6e3c14efa6a5962812e3f94f8ce673a433f4a82d07a67577285ea0eaa07f8be7115853122d12d6d4e1fdf64c504be1", + "0x82268bee9c1662d3ddb5fb785abfae6fb8b774190f30267f1d47091d2cd4b3874db4372625aa36c32f27b0eee986269b", + "0xb236459565b7b966166c4a35b2fa71030b40321821b8e96879d95f0e83a0baf33fa25721f30af4a631df209e25b96061", + "0x8708d752632d2435d2d5b1db4ad1fa2558d776a013655f88e9a3556d86b71976e7dfe5b8834fdec97682cd94560d0d0d", + "0xae1424a68ae2dbfb0f01211f11773732a50510b5585c1fb005cb892b2c6a58f4a55490b5c5b4483c6fce40e9d3236a52", + "0xb3f5f722af9dddb07293c871ce97abbccba0093ca98c8d74b1318fa21396fc1b45b69c15084f63d728f9908442024506", + "0x9606f3ce5e63886853ca476dc0949e7f1051889d529365c0cb0296fdc02abd088f0f0318ecd2cf36740a3634132d36f6", + "0xb11a833a49fa138db46b25ff8cdda665295226595bc212c0931b4931d0a55c99da972c12b4ef753f7e37c6332356e350", + "0xafede34e7dab0a9e074bc19a7daddb27df65735581ca24ad70c891c98b1349fcebbcf3ba6b32c2617fe06a5818dabc2d", + "0x97993d456e459e66322d01f8eb13918979761c3e8590910453944bdff90b24091bb018ac6499792515c9923be289f99f", + "0x977e3e967eff19290a192cd11df3667d511b398fb3ac9a5114a0f3707e25a0edcb56105648b1b85a8b7519fc529fc6f6", + "0xb873a7c88bf58731fe1bf61ff6828bf114cf5228f254083304a4570e854e83748fc98683ddba62d978fff7909f2c5c47", + "0xad4b2691f6f19da1d123aaa23cca3e876247ed9a4ab23c599afdbc0d3aa49776442a7ceaa996ac550d0313d9b9a36cee", + "0xb9210713c78e19685608c6475bfa974b57ac276808a443f8b280945c5d5f9c39da43effa294bfb1a6c6f7b6b9f85bf6c", + "0xa65152f376113e61a0e468759de38d742caa260291b4753391ee408dea55927af08a4d4a9918600a3bdf1df462dffe76", + "0x8bf8c27ad5140dde7f3d2280fd4cc6b29ab76537e8d7aa7011a9d2796ee3e56e9a60c27b5c2da6c5e14fc866301dc195", + "0x92fde8effc9f61393a2771155812b863cff2a0c5423d7d40aa04d621d396b44af94ddd376c28e7d2f53c930aea947484", + "0x97a01d1dd9ee30553ce676011aea97fa93d55038ada95f0057d2362ae9437f3ed13de8290e2ff21e3167dd7ba10b9c3f", + "0x89affffaa63cb2df3490f76f0d1e1d6ca35c221dd34057176ba739fa18d492355e6d2a5a5ad93a136d3b1fed0bb8aa19", + "0x928b8e255a77e1f0495c86d3c63b83677b4561a5fcbbe5d3210f1e0fc947496e426d6bf3b49394a5df796c9f25673fc4", + "0x842a0af91799c9b533e79ee081efe2a634cac6c584c2f054fb7d1db67dde90ae36de36cbf712ec9cd1a0c7ee79e151ea", + "0xa65b946cf637e090baf2107c9a42f354b390e7316beb8913638130dbc67c918926eb87bec3b1fe92ef72bc77a170fa3b", + "0xaafc0f19bfd71ab5ae4a8510c7861458b70ad062a44107b1b1dbacbfa44ba3217028c2824bd7058e2fa32455f624040b", + "0x95269dc787653814e0be899c95dba8cfa384f575a25e671c0806fd80816ad6797dc819d30ae06e1d0ed9cb01c3950d47", + "0xa1e760f7fa5775a1b2964b719ff961a92083c5c617f637fc46e0c9c20ab233f8686f7f38c3cb27d825c54dd95e93a59b", + "0xac3b8a7c2317ea967f229eddc3e23e279427f665c4705c7532ed33443f1243d33453c1088f57088d2ab1e3df690a9cc9", + "0xb787beeddfbfe36dd51ec4efd9cf83e59e84d354c3353cc9c447be53ae53d366ed1c59b686e52a92f002142c8652bfe0", + "0xb7a64198300cb6716aa7ac6b25621f8bdec46ad5c07a27e165b3f774cdf65bcfdbf31e9bae0c16b44de4b00ada7a4244", + "0xb8ae9f1452909e0c412c7a7fe075027691ea8df1347f65a5507bc8848f1d2c833d69748076db1129e5b4fb912f65c86c", + "0x9682e41872456b9fa67def89e71f06d362d6c8ca85c9c48536615bc401442711e1c9803f10ab7f8ab5feaec0f9df20a6", + "0x88889ff4e271dc1c7e21989cc39f73cde2f0475acd98078281591ff6c944fadeb9954e72334319050205d745d4df73df", + "0x8f79b5b8159e7fd0d93b0645f3c416464f39aec353b57d99ecf24f96272df8a068ad67a6c90c78d82c63b40bb73989bb", + "0x838c01a009a3d8558a3f0bdd5e22de21af71ca1aefc8423c91dc577d50920e9516880e87dce3e6d086e11cd45c9052d9", + "0xb97f1c6eee8a78f137c840667cc288256e39294268a3009419298a04a1d0087c9c9077b33c917c65caf76637702dda8a", + "0x972284ce72f96a61c899260203dfa06fc3268981732bef74060641c1a5068ead723e3399431c247ca034b0dae861e8df", + "0x945a8d52d6d3db6663dbd3110c6587f9e9c44132045eeffba15621576d178315cb52870fa5861669f84f0bee646183fe", + "0xa0a547b5f0967b1c3e5ec6c6a9a99f0578521489180dfdfbb5561f4d166baac43a2f06f950f645ce991664e167537eed", + "0xa0592cda5cdddf1340033a745fd13a6eff2021f2e26587116c61c60edead067e0f217bc2bef4172a3c9839b0b978ab35", + "0xb9c223b65a3281587fa44ec829e609154b32f801fd1de6950e01eafb07a8324243b960d5735288d0f89f0078b2c42b5b", + "0x99ebfc3b8f9f98249f4d37a0023149ed85edd7a5abe062c8fb30c8c84555258b998bdcdd1d400bc0fa2a4aaa8b224466", + "0x955b68526e6cb3937b26843270f4e60f9c6c8ece2fa9308fe3e23afa433309c068c66a4bc16ee2cf04220f095e9afce4", + "0xb766caeafcc00378135ae53397f8a67ed586f5e30795462c4a35853de6681b1f17401a1c40958de32b197c083b7279c1", + "0x921bf87cad947c2c33fa596d819423c10337a76fe5a63813c0a9dc78a728207ae7b339407a402fc4d0f7cba3af6da6fc", + "0xa74ba1f3bc3e6c025db411308f49b347ec91da1c916bda9da61e510ec8d71d25e0ac0f124811b7860e5204f93099af27", + "0xa29b4d144e0bf17a7e8353f2824cef0ce85621396babe8a0b873ca1e8a5f8d508b87866cf86da348470649fceefd735c", + "0xa8040e12ffc3480dd83a349d06741d1572ef91932c46f5cf03aee8454254156ee95786fd013d5654725e674c920cec32", + "0x8c4cf34ca60afd33923f219ffed054f90cd3f253ffeb2204a3b61b0183417e366c16c07fae860e362b0f2bfe3e1a1d35", + "0x8195eede4ddb1c950459df6c396b2e99d83059f282b420acc34220cadeed16ab65c856f2c52568d86d3c682818ed7b37", + "0x91fff19e54c15932260aa990c7fcb3c3c3da94845cc5aa8740ef56cf9f58d19b4c3c55596f8d6c877f9f4d22921d93aa", + "0xa3e0bf7e5d02a80b75cf75f2db7e66cb625250c45436e3c136d86297d652590ec97c2311bafe407ad357c79ab29d107b", + "0x81917ff87e5ed2ae4656b481a63ced9e6e5ff653b8aa6b7986911b8bc1ee5b8ef4f4d7882c3f250f2238e141b227e510", + "0x915fdbe5e7de09c66c0416ae14a8750db9412e11dc576cf6158755fdcaf67abdbf0fa79b554cac4fe91c4ec245be073f", + "0x8df27eafb5c3996ba4dc5773c1a45ca77e626b52e454dc1c4058aa94c2067c18332280630cc3d364821ee53bf2b8c130", + "0x934f8a17c5cbb827d7868f5c8ca00cb027728a841000a16a3428ab16aa28733f16b52f58c9c4fbf75ccc45df72d9c4df", + "0xb83f4da811f9183c25de8958bc73b504cf790e0f357cbe74ef696efa7aca97ad3b7ead1faf76e9f982c65b6a4d888fc2", + "0x87188213c8b5c268dc2b6da413f0501c95749e953791b727450af3e43714149c115b596b33b63a2f006a1a271b87efd0", + "0x83e9e888ab9c3e30761de635d9aabd31248cdd92f7675fc43e4b21fd96a03ec1dc4ad2ec94fec857ffb52683ac98e360", + "0xb4b9a1823fe2d983dc4ec4e3aaea297e581c3fc5ab4b4af5fa1370caa37af2d1cc7fc6bfc5e7da60ad8fdce27dfe4b24", + "0x856388bc78aef465dbcdd1f559252e028c9e9a2225c37d645c138e78f008f764124522705822a61326a6d1c79781e189", + "0xa6431b36db93c3b47353ba22e7c9592c9cdfb9cbdd052ecf2cc3793f5b60c1e89bc96e6bae117bfd047f2308da00dd2f", + "0xb619972d48e7e4291542dcde08f7a9cdc883c892986ded2f23ccb216e245cd8d9ad1d285347b0f9d7611d63bf4cee2bc", + "0x8845cca6ff8595955f37440232f8e61d5351500bd016dfadd182b9d39544db77a62f4e0102ff74dd4173ae2c181d24ef", + "0xb2f5f7fa26dcd3b6550879520172db2d64ee6aaa213cbef1a12befbce03f0973a22eb4e5d7b977f466ac2bf8323dcedd", + "0x858b7f7e2d44bdf5235841164aa8b4f3d33934e8cb122794d90e0c1cac726417b220529e4f896d7b77902ab0ccd35b3a", + "0x80b0408a092dae2b287a5e32ea1ad52b78b10e9c12f49282976cd738f5d834e03d1ad59b09c5ccaccc39818b87d06092", + "0xb996b0a9c6a2d14d984edcd6ab56bc941674102980d65b3ad9733455f49473d3f587c8cbf661228a7e125ddbe07e3198", + "0x90224fcebb36865293bd63af786e0c5ade6b67c4938d77eb0cbae730d514fdd0fe2d6632788e858afd29d46310cf86df", + "0xb71351fdfff7168b0a5ec48397ecc27ac36657a8033d9981e97002dcca0303e3715ce6dd3f39423bc8ef286fa2e9e669", + "0xae2a3f078b89fb753ce4ed87e0c1a58bb19b4f0cfb6586dedb9fcab99d097d659a489fb40e14651741e1375cfc4b6c5f", + "0x8ef476b118e0b868caed297c161f4231bbeb863cdfa5e2eaa0fc6b6669425ce7af50dc374abceac154c287de50c22307", + "0x92e46ab472c56cfc6458955270d3c72b7bde563bb32f7d4ab4d959db6f885764a3d864e1aa19802fefaa5e16b0cb0b54", + "0x96a3f68323d1c94e73d5938a18a377af31b782f56212de3f489d22bc289cf24793a95b37f1d6776edf88114b5c1fa695", + "0x962cc068cfce6faaa27213c4e43e44eeff0dfbb6d25b814e82c7da981fb81d7d91868fa2344f05fb552362f98cfd4a72", + "0x895d4e4c4ad670abf66d43d59675b1add7afad7438ada8f42a0360c704cee2060f9ac15b4d27e9b9d0996bb801276fe3", + "0xb3ad18d7ece71f89f2ef749b853c45dc56bf1c796250024b39a1e91ed11ca32713864049c9aaaea60cde309b47486bbf", + "0x8f05404e0c0258fdbae50e97ccb9b72ee17e0bd2400d9102c0dad981dac8c4c71585f03e9b5d50086d0a2d3334cb55d1", + "0x8bd877e9d4591d02c63c6f9fc9976c109de2d0d2df2bfa5f6a3232bab5b0b8b46e255679520480c2d7a318545efa1245", + "0x8d4c16b5d98957c9da13d3f36c46f176e64e5be879f22be3179a2c0e624fe4758a82bf8c8027410002f973a3b84cd55a", + "0x86e2a8dea86427b424fa8eada881bdff896907084a495546e66556cbdf070b78ba312bf441eb1be6a80006d25d5097a3", + "0x8608b0c117fd8652fdab0495b08fadbeba95d9c37068e570de6fddfef1ba4a1773b42ac2be212836141d1bdcdef11a17", + "0xa13d6febf5fb993ae76cae08423ca28da8b818d6ef0fde32976a4db57839cd45b085026b28ee5795f10a9a8e3098c683", + "0x8e261967fa6de96f00bc94a199d7f72896a6ad8a7bbb1d6187cca8fad824e522880e20f766620f4f7e191c53321d70f9", + "0x8b8e8972ac0218d7e3d922c734302803878ad508ca19f5f012bc047babd8a5c5a53deb5fe7c15a4c00fd6d1cb9b1dbd0", + "0xb5616b233fb3574a2717d125a434a2682ff68546dccf116dd8a3b750a096982f185614b9fb6c7678107ff40a451f56fa", + "0xaa6adf9b0c3334b0d0663f583a4914523b2ac2e7adffdb026ab9109295ff6af003ef8357026dbcf789896d2afded8d73", + "0xacb72df56a0b65496cd534448ed4f62950bb1e11e50873b6ed349c088ee364441821294ce0f7c61bd7d38105bea3b442", + "0xabae12df83e01ec947249fedd0115dc501d2b03ff7232092979eda531dbbca29ace1d46923427c7dde4c17bdf3fd7708", + "0x820b4fc2b63a9fda7964acf5caf19a2fc4965007cb6d6b511fcafcb1f71c3f673a1c0791d3f86e3a9a1eb6955b191cc0", + "0xaf277259d78c6b0f4f030a10c53577555df5e83319ddbad91afbd7c30bc58e7671c56d00d66ec3ab5ef56470cd910cee", + "0xad4a861c59f1f5ca1beedd488fb3d131dea924fffd8e038741a1a7371fad7370ca5cf80dc01f177fbb9576713bb9a5b3", + "0xb67a5162982ce6a55ccfb2f177b1ec26b110043cf18abd6a6c451cf140b5af2d634591eb4f28ad92177d8c7e5cd0a5e8", + "0x96176d0a83816330187798072d449cbfccff682561e668faf6b1220c9a6535b32a6e4f852e8abb00f79abb87493df16b", + "0xb0afe6e7cb672e18f0206e4423f51f8bd0017bf464c4b186d46332c5a5847647f89ff7fa4801a41c1b0b42f6135bcc92", + "0x8fc5e7a95ef20c1278c645892811f6fe3f15c431ebc998a32ec0da44e7213ea934ed2be65239f3f49b8ec471e9914160", + "0xb7793e41adda6c82ba1f2a31f656f6205f65bf8a3d50d836ee631bc7ce77c153345a2d0fc5c60edf8b37457c3729c4ec", + "0xa504dd7e4d6b2f4379f22cc867c65535079c75ccc575955f961677fa63ecb9f74026fa2f60c9fb6323c1699259e5e9c8", + "0xab899d00ae693649cc1afdf30fb80d728973d2177c006e428bf61c7be01e183866614e05410041bc82cb14a33330e69c", + "0x8a3bd8b0b1be570b65c4432a0f6dc42f48a2000e30ab089cf781d38f4090467b54f79c0d472fcbf18ef6a00df69cc6f3", + "0xb4d7028f7f76a96a3d7803fca7f507ae11a77c5346e9cdfccb120a833a59bda1f4264e425aa588e7a16f8e7638061d84", + "0xb9c7511a76ea5fb105de905d44b02edb17008335766ee357ed386b7b3cf19640a98b38785cb14603c1192bee5886c9b6", + "0x8563afb12e53aed71ac7103ab8602bfa8371ae095207cb0d59e8fd389b6ad1aff0641147e53cb6a7ca16c7f37c9c5e6b", + "0x8e108be614604e09974a9ed90960c28c4ea330a3d9a0cb4af6dd6f193f84ab282b243ecdf549b3131036bebc8905690c", + "0xb794d127fbedb9c5b58e31822361706ffac55ce023fbfe55716c3c48c2fd2f2c7660a67346864dfe588812d369cb50b6", + "0xb797a3442fc3b44f41baefd30346f9ac7f96e770d010d53c146ce74ce424c10fb62758b7e108b8abfdc5fafd89d745cb", + "0x993bb71e031e8096442e6205625e1bfddfe6dd6a83a81f3e2f84fafa9e5082ab4cad80a099f21eff2e81c83457c725c3", + "0x8711ab833fc03e37acf2e1e74cfd9133b101ff4144fe30260654398ae48912ab46549d552eb9d15d2ea57760d35ac62e", + "0xb21321fd2a12083863a1576c5930e1aecb330391ef83326d9d92e1f6f0d066d1394519284ddab55b2cb77417d4b0292f", + "0x877d98f731ffe3ee94b0b5b72d127630fa8a96f6ca4f913d2aa581f67732df6709493693053b3e22b0181632ac6c1e3b", + "0xae391c12e0eb8c145103c62ea64f41345973311c3bf7281fa6bf9b7faafac87bcf0998e5649b9ef81e288c369c827e07", + "0xb83a2842f36998890492ab1cd5a088d9423d192681b9a3a90ec518d4c541bce63e6c5f4df0f734f31fbfdd87785a2463", + "0xa21b6a790011396e1569ec5b2a423857b9bec16f543e63af28024e116c1ea24a3b96e8e4c75c6537c3e4611fd265e896", + "0xb4251a9c4aab3a495da7a42e684ba4860dbcf940ad1da4b6d5ec46050cbe8dab0ab9ae6b63b5879de97b905723a41576", + "0x8222f70aebfe6ac037f8543a08498f4cadb3edaac00336fc00437eb09f2cba758f6c38e887cc634b4d5b7112b6334836", + "0x86f05038e060594c46b5d94621a1d9620aa8ba59a6995baf448734e21f58e23c1ea2993d3002ad5250d6edd5ba59b34f", + "0xa7c0c749baef811ab31b973c39ceb1d94750e2bc559c90dc5eeb20d8bb6b78586a2b363c599ba2107d6be65cd435f24e", + "0x861d46a5d70b38d6c1cd72817a2813803d9f34c00320c8b62f8b9deb67f5b5687bc0b37c16d28fd017367b92e05da9ca", + "0xb3365d3dab639bffbe38e35383686a435c8c88b397b717cd4aeced2772ea1053ceb670f811f883f4e02975e5f1c4ac58", + "0xa5750285f61ab8f64cd771f6466e2c0395e01b692fd878f2ef2d5c78bdd8212a73a3b1dfa5e4c8d9e1afda7c84857d3b", + "0x835a10809ccf939bc46cf950a33b36d71be418774f51861f1cd98a016ade30f289114a88225a2c11e771b8b346cbe6ef", + "0xa4f59473a037077181a0a62f1856ec271028546ca9452b45cedfcb229d0f4d1aabfc13062b07e536cc8a0d4b113156a2", + "0x95cd14802180b224d44a73cc1ed599d6c4ca62ddcaa503513ccdc80aaa8be050cc98bd4b4f3b639549beb4587ac6caf9", + "0x973b731992a3e69996253d7f36dd7a0af1982b5ed21624b77a7965d69e9a377b010d6dabf88a8a97eec2a476259859cc", + "0xaf8a1655d6f9c78c8eb9a95051aa3baaf9c811adf0ae8c944a8d3fcba87b15f61021f3baf6996fa0aa51c81b3cb69de1", + "0x835aad5c56872d2a2d6c252507b85dd742bf9b8c211ccb6b25b52d15c07245b6d89b2a40f722aeb5083a47cca159c947", + "0xabf4e970b02bef8a102df983e22e97e2541dd3650b46e26be9ee394a3ea8b577019331857241d3d12b41d4eacd29a3ac", + "0xa13c32449dbedf158721c13db9539ae076a6ce5aeaf68491e90e6ad4e20e20d1cdcc4a89ed9fd49cb8c0dd50c17633c1", + "0x8c8f78f88b7e22dd7e9150ab1c000f10c28e696e21d85d6469a6fe315254740f32e73d81ab1f3c1cf8f544c86df506e8", + "0xb4b77f2acfe945abf81f2605f906c10b88fb4d28628487fb4feb3a09f17f28e9780445dfcee4878349d4c6387a9d17d4", + "0x8d255c235f3812c6ecc646f855fa3832be5cb4dbb9c9e544989fafdf3f69f05bfd370732eaf954012f0044aa013fc9c6", + "0xb982efd3f34b47df37c910148ac56a84e8116647bea24145a49e34e0a6c0176e3284d838dae6230cb40d0be91c078b85", + "0x983f365aa09bd85df2a6a2ad8e4318996b1e27d02090755391d4486144e40d80b1fbfe1c798d626db92f52e33aa634da", + "0x95fd1981271f3ea3a41d654cf497e6696730d9ff7369f26bc4d7d15c7adb4823dd0c42e4a005a810af12d234065e5390", + "0xa9f5219bd4b913c186ef30c02f995a08f0f6f1462614ea5f236964e02bdaa33db9d9b816c4aee5829947840a9a07ba60", + "0x9210e6ceb05c09b46fd09d036287ca33c45124ab86315e5d6911ff89054f1101faaa3e83d123b7805056d388bcec6664", + "0x8ed9cbf69c6ff3a5c62dd9fe0d7264578c0f826a29e614bc2fb4d621d90c8c9992438accdd7a614b1dca5d1bb73dc315", + "0x85cf2a8cca93e00da459e3cecd22c342d697eee13c74d5851634844fc215f60053cf84b0e03c327cb395f48d1c71a8a4", + "0x8818a18e9a2ec90a271b784400c1903089ffb0e0b40bc5abbbe12fbebe0f731f91959d98c5519ef1694543e31e2016d4", + "0x8dabc130f296fa7a82870bf9a8405aaf542b222ed9276bba9bd3c3555a0f473acb97d655ee7280baff766a827a8993f0", + "0xac7952b84b0dc60c4d858f034093b4d322c35959605a3dad2b806af9813a4680cb038c6d7f4485b4d6b2ff502aaeca25", + "0xad65cb6d57b48a2602568d2ec8010baed0eb440eec7638c5ec8f02687d764e9de5b5d42ad5582934e592b48471c22d26", + "0xa02ab8bd4c3d114ea23aebdd880952f9495912817da8c0c08eabc4e6755439899d635034413d51134c72a6320f807f1c", + "0x8319567764b8295402ec1ebef4c2930a138480b37e6d7d01c8b4c9cd1f2fc3f6e9a44ae6e380a0c469b25b06db23305f", + "0xafec53b2301dc0caa8034cd9daef78c48905e6068d692ca23d589b84a6fa9ddc2ed24a39480597e19cb3e83eec213b3f", + "0xac0b4ffdb5ae08e586a9cdb98f9fe56f4712af3a97065e89e274feacfb52b53c839565aee93c4cfaaccfe51432c4fab0", + "0x8972cbf07a738549205b1094c5987818124144bf187bc0a85287c94fdb22ce038c0f11df1aa16ec5992e91b44d1af793", + "0xb7267aa6f9e3de864179b7da30319f1d4cb2a3560f2ea980254775963f1523b44c680f917095879bebfa3dc2b603efcf", + "0x80f68f4bfc337952e29504ee5149f15093824ea7ab02507efd1317a670f6cbc3611201848560312e3e52e9d9af72eccf", + "0x8897fee93ce8fc1e1122e46b6d640bba309384dbd92e46e185e6364aa8210ebf5f9ee7e5e604b6ffba99aa80a10dd7d0", + "0xb58ea6c02f2360be60595223d692e82ee64874fda41a9f75930f7d28586f89be34b1083e03bbc1575bbfdda2d30db1ea", + "0x85a523a33d903280d70ac5938770453a58293480170c84926457ac2df45c10d5ff34322ab130ef4a38c916e70d81af53", + "0xa2cbf045e1bed38937492c1f2f93a5ba41875f1f262291914bc1fc40c60bd0740fb3fea428faf6da38b7c180fe8ac109", + "0x8c09328770ed8eb17afc6ac7ddd87bb476de18ed63cab80027234a605806895959990c47bd10d259d7f3e2ecb50074c9", + "0xb4b9e19edb4a33bde8b7289956568a5b6b6557404e0a34584b5721fe6f564821091013fbb158e2858c6d398293bb4b59", + "0x8a47377df61733a2aa5a0e945fce00267f8e950f37e109d4487d92d878fb8b573317bb382d902de515b544e9e233458d", + "0xb5804c9d97efeff5ca94f3689b8088c62422d92a1506fd1d8d3b1b30e8a866ad0d6dad4abfa051dfc4471250cac4c5d9", + "0x9084a6ee8ec22d4881e9dcc8a9eb3c2513523d8bc141942370fd191ad2601bf9537a0b1e84316f3209b3d8a54368051e", + "0x85447eea2fa26656a649f8519fa67279183044791d61cf8563d0783d46d747d96af31d0a93507bbb2242666aa87d3720", + "0x97566a84481027b60116c751aec552adfff2d9038e68d48c4db9811fb0cbfdb3f1d91fc176a0b0d988a765f8a020bce1", + "0xae87e5c1b9e86c49a23dceda4ecfd1dcf08567f1db8e5b6ec752ebd45433c11e7da4988573cdaebbb6f4135814fc059e", + "0xabee05cf9abdbc52897ac1ce9ed157f5466ed6c383d6497de28616238d60409e5e92619e528af8b62cc552bf09970dc2", + "0xae6d31cd7bf9599e5ee0828bab00ceb4856d829bba967278a73706b5f388465367aa8a6c7da24b5e5f1fdd3256ef8e63", + "0xac33e7b1ee47e1ee4af472e37ab9e9175260e506a4e5ce449788075da1b53c44cb035f3792d1eea2aa24b1f688cc6ed3", + "0x80f65b205666b0e089bb62152251c48c380a831e5f277f11f3ef4f0d52533f0851c1b612267042802f019ec900dc0e8f", + "0x858520ad7aa1c9fed738e3b583c84168f2927837ad0e1d326afe9935c26e9b473d7f8c382e82ef1fe37d2b39bb40a1ee", + "0xb842dd4af8befe00a97c2d0f0c33c93974761e2cb9e5ab8331b25170318ddd5e4bdbc02d8f90cbfdd5f348f4f371c1f7", + "0x8bf2cb79bc783cb57088aae7363320cbeaabd078ffdec9d41bc74ff49e0043d0dad0086a30e5112b689fd2f5a606365d", + "0x982eb03bbe563e8850847cd37e6a3306d298ab08c4d63ab6334e6b8c1fa13fce80cf2693b09714c7621d74261a0ff306", + "0xb143edb113dec9f1e5105d4a93fbe502b859e587640d3db2f628c09a17060e6aec9e900e2c8c411cda99bc301ff96625", + "0xaf472d9befa750dcebc5428fe1a024f18ec1c07bca0f95643ce6b5f4189892a910285afb03fd7ed7068fbe614e80d33c", + "0xa97e3bc57ede73ecd1bbf02de8f51b4e7c1a067da68a3cd719f4ba26a0156cbf1cef2169fd35a18c5a4cced50d475998", + "0xa862253c937cf3d75d7183e5f5be6a4385d526aeda5171c1c60a8381fea79f88f5f52a4fab244ecc70765d5765e6dfd5", + "0x90cb776f8e5a108f1719df4a355bebb04bf023349356382cae55991b31720f0fd03206b895fa10c56c98f52453be8778", + "0xa7614e8d0769dccd520ea4b46f7646e12489951efaef5176bc889e9eb65f6e31758df136b5bf1e9107e68472fa9b46ec", + "0xac3a9b80a3254c42e5ed3a090a0dd7aee2352f480de96ad187027a3bb6c791eddfc3074b6ffd74eea825188f107cda4d", + "0x82a01d0168238ef04180d4b6e0a0e39024c02c2d75b065017c2928039e154d093e1af4503f4d1f3d8a948917abb5d09f", + "0x8fab000a2b0eef851a483aec8d2dd85fe60504794411a2f73ed82e116960547ac58766cb73df71aea71079302630258d", + "0x872451a35c6db61c63e9b8bb9f16b217f985c20be4451c14282c814adb29d7fb13f201367c664435c7f1d4d9375d7a58", + "0x887d9ff54cc96b35d562df4a537ff972d7c4b3fd91ab06354969a4cfede0b9fc68bbffb61d0dbf1a58948dc701e54f5a", + "0x8cb5c2a6bd956875d88f41ae24574434f1308514d44057b55c9c70f13a3366ed054150eed0955a38fda3f757be73d55f", + "0x89ad0163cad93e24129d63f8e38422b7674632a8d0a9016ee8636184cab177659a676c4ee7efba3abe1a68807c656d60", + "0xb9ec01c7cab6d00359b5a0b4a1573467d09476e05ca51a9227cd16b589a9943d161eef62dcc73f0de2ec504d81f4d252", + "0x8031d17635d39dfe9705c485d2c94830b6fc9bc67b91300d9d2591b51e36a782e77ab5904662effa9382d9cca201f525", + "0x8be5a5f6bc8d680e5092d6f9a6585acbaaaa2ddc671da560dcf5cfa4472f4f184b9597b5b539438accd40dda885687cc", + "0xb1fc0f052fae038a2e3de3b3a96b0a1024b009de8457b8b3adb2d315ae68a89af905720108a30038e5ab8d0d97087785", + "0x8b8bdc77bd3a6bc7ca5492b6f8c614852c39a70d6c8a74916eaca0aeb4533b11898b8820a4c2620a97bf35e275480029", + "0xaf35f4dc538d4ad5cdf710caa38fd1eb496c3fa890a047b6a659619c5ad3054158371d1e88e0894428282eed9f47f76b", + "0x8166454a7089cc07758ad78724654f4e7a1a13e305bbf88ddb86f1a4b2904c4fc8ab872d7da364cdd6a6c0365239e2ad", + "0xab287c7d3addce74ce40491871c768abe01daaa0833481276ff2e56926b38a7c6d2681ffe837d2cc323045ad1a4414f9", + "0xb90317f4505793094d89365beb35537f55a6b5618904236258dd04ca61f21476837624a2f45fef8168acf732cab65579", + "0x98ae5ea27448e236b6657ab5ef7b1cccb5372f92ab25f5fa651fbac97d08353a1dae1b280b1cd42b17d2c6a70a63ab9d", + "0xadcf54e752d32cbaa6cb98fbca48d8cd087b1db1d131d465705a0d8042c8393c8f4d26b59006eb50129b21e6240f0c06", + "0xb591a3e4db18a7345fa935a8dd7994bbac5cc270b8ebd84c8304c44484c7a74afb45471fdbe4ab22156a30fae1149b40", + "0x806b53ac049a42f1dcc1d6335505371da0bf27c614f441b03bbf2e356be7b2fb4eed7117eabcce9e427a542eaa2bf7d8", + "0x800482e7a772d49210b81c4a907f5ce97f270b959e745621ee293cf8c71e8989363d61f66a98f2d16914439544ca84c7", + "0x99de9eafdad3617445312341644f2bb888680ff01ce95ca9276b1d2e5ef83fa02dab5e948ebf66c17df0752f1bd37b70", + "0x961ee30810aa4c93ae157fbe9009b8e443c082192bd36a73a6764ff9b2ad8b0948fe9a73344556e01399dd77badb4257", + "0xae0a361067c52efbe56c8adf982c00432cd478929459fc7f74052c8ee9531cd031fe1335418fde53f7c2ef34254eb7ac", + "0xa3503d16b6b27eb20c1b177bcf90d13706169220523a6271b85b2ce35a9a2b9c5bed088540031c0a4ebfdae3a4c6ab04", + "0x909420122c3e723289ca4e7b81c2df5aff312972a2203f4c45821b176e7c862bf9cac7f7df3adf1d59278f02694d06e7", + "0x989f42380ae904b982f85d0c6186c1aef5d6bcba29bcfbb658e811b587eb2749c65c6e4a8cc6409c229a107499a4f5d7", + "0x8037a6337195c8e26a27ea4ef218c6e7d79a9720aaab43932d343192abc2320fe72955f5e431c109093bda074103330a", + "0xb312e168663842099b88445e940249cc508f080ab0c94331f672e7760258dbd86be5267e4cf25ea25facb80bff82a7e9", + "0xaaa3ff8639496864fcdbfdda1ac97edc4f08e3c9288b768f6c8073038c9fbbf7e1c4bea169b4d45c31935cdf0680d45e", + "0x97dbd3df37f0b481a311dfc5f40e59227720f367912200d71908ef6650f32cc985cb05b981e3eea38958f7e48d10a15d", + "0xa89d49d1e267bb452d6cb621b9a90826fe55e9b489c0427b94442d02a16f390eed758e209991687f73f6b5a032321f42", + "0x9530dea4e0e19d6496f536f2e75cf7d814d65fde567055eb20db48fd8d20d501cd2a22fb506db566b94c9ee10f413d43", + "0x81a7009b9e67f1965fa7da6a57591c307de91bf0cd35ab4348dc4a98a4961e096d004d7e7ad318000011dc4342c1b809", + "0x83440a9402b766045d7aca61a58bba2aa29cac1cf718199e472ba086f5d48093d9dda4d135292ba51d049a23964eceae", + "0xa06c9ce5e802df14f6b064a3d1a0735d429b452f0e2e276042800b0a4f16df988fd94cf3945921d5dd3802ab2636f867", + "0xb1359e358b89936dee9e678a187aad3e9ab14ac40e96a0a68f70ee2583cdcf467ae03bef4215e92893f4e12f902adec8", + "0x835304f8619188b4d14674d803103d5a3fa594d48e96d9699e653115dd05fdc2dda6ba3641cf7ad53994d448da155f02", + "0x8327cba5a9ff0d3f5cd0ae55e77167448926d5fcf76550c0ad978092a14122723090c51c415e88e42a2b62eb07cc3981", + "0xb373dcdaea85f85ce9978b1426a7ef4945f65f2d3467a9f1cc551a99766aac95df4a09e2251d3f89ca8c9d1a7cfd7b0e", + "0xab1422dc41af2a227b973a6fd124dfcb2367e2a11a21faa1d381d404f51b7257e5bc82e9cf20cd7fe37d7ae761a2ab37", + "0xa93774a03519d2f20fdf2ef46547b0a5b77c137d6a3434b48d56a2cbef9e77120d1b85d0092cf8842909213826699477", + "0x8eb967a495a38130ea28711580b7e61bcd1d051cd9e4f2dbf62f1380bd86e0d60e978d72f6f31e909eb97b3b9a2b867c", + "0xae8213378da1287ba1fe4242e1acaec19b877b6fe872400013c6eac1084b8d03156792fa3020201725b08228a1e80f49", + "0xb143daf6893d674d607772b3b02d8ac48f294237e2f2c87963c0d4e26d9227d94a2a13512457c3d5883544bbc259f0ef", + "0xb343bd2aca8973888e42542218924e2dda2e938fd1150d06878af76f777546213912b7c7a34a0f94186817d80ffa185c", + "0xb188ebc6a8c3007001aa347ae72cc0b15d09bc6c19a80e386ee4b334734ec0cc2fe8b493c2422f38d1e6d133cc3db6fe", + "0xb795f6a8b9b826aaeee18ccd6baf6c5adeeec85f95eb5b6d19450085ec7217e95a2d9e221d77f583b297d0872073ba0e", + "0xb1c7dbd998ad32ae57bfa95deafa147024afd57389e98992c36b6e52df915d3d5a39db585141ec2423173e85d212fed8", + "0x812bcdeb9fe5f12d0e1df9964798056e1f1c3de3b17b6bd2919b6356c4b86d8e763c01933efbe0224c86a96d5198a4be", + "0xb19ebeda61c23d255cbf472ef0b8a441f4c55b70f0d8ed47078c248b1d3c7c62e076b43b95c00a958ec8b16d5a7cb0d7", + "0xb02adc9aaa20e0368a989c2af14ff48b67233d28ebee44ff3418bb0473592e6b681af1cc45450bd4b175df9051df63d9", + "0x8d87f0714acee522eb58cec00360e762adc411901dba46adc9227124fa70ee679f9a47e91a6306d6030dd4eb8de2f3c1", + "0x8be54cec21e74bcc71de29dc621444263737db15f16d0bb13670f64e42f818154e04b484593d19ef95f2ee17e4b3fe21", + "0xab8e20546c1db38d31493b5d5f535758afb17e459645c1b70813b1cf7d242fd5d1f4354a7c929e8f7259f6a25302e351", + "0x89f035a1ed8a1e302ac893349ba8ddf967580fcb6e73d44af09e3929cde445e97ff60c87dafe489e2c0ab9c9986cfa00", + "0x8b2b0851a795c19191a692af55f7e72ad2474efdc5401bc3733cfdd910e34c918aaebe69d5ea951bdddf3c01cabbfc67", + "0xa4edb52c2b51495ccd1ee6450fc14b7b3ede8b3d106808929d02fb31475bacb403e112ba9c818d2857651e508b3a7dd1", + "0x9569341fded45d19f00bcf3cbf3f20eb2b4d82ef92aba3c8abd95866398438a2387437e580d8b646f17cf6fde8c5af23", + "0xaa4b671c6d20f72f2f18a939a6ff21cc37e0084b44b4a717f1be859a80b39fb1be026b3205adec2a66a608ec2bcd578f", + "0x94902e980de23c4de394ad8aec91b46f888d18f045753541492bfbb92c59d3daa8de37ae755a6853744af8472ba7b72b", + "0xaf651ef1b2a0d30a7884557edfad95b6b5d445a7561caebdc46a485aedd25932c62c0798465c340a76f6feaa196dd712", + "0xb7b669b8e5a763452128846dd46b530dca4893ace5cc5881c7ddcd3d45969d7e73fbebdb0e78aa81686e5f7b22ec5759", + "0x82507fd4ebe9fa656a7f2e084d64a1fa6777a2b0bc106d686e2d9d2edafc58997e58cb6bfd0453b2bf415704aa82ae62", + "0xb40bce2b42b88678400ecd52955bbdadd15f8b9e1b3751a1a3375dc0efb5ca3ee258cf201e1140b3c09ad41217d1d49e", + "0xb0210d0cbb3fbf3b8cdb39e862f036b0ff941cd838e7aaf3a8354e24246e64778d22f3de34572e6b2a580614fb6425be", + "0x876693cba4301b251523c7d034108831df3ce133d8be5a514e7a2ca494c268ca0556fa2ad8310a1d92a16b55bcd99ea9", + "0x8660281406d22a4950f5ef050bf71dd3090edb16eff27fa29ef600cdea628315e2054211ed2cc6eaf8f2a1771ef689fd", + "0xa610e7e41e41ab66955b809ba4ade0330b8e9057d8efc9144753caed81995edeb1a42a53f93ce93540feca1fae708dac", + "0xa49e2c176a350251daef1218efaccc07a1e06203386ede59c136699d25ca5cb2ac1b800c25b28dd05678f14e78e51891", + "0x83e0915aa2b09359604566080d411874af8c993beba97d4547782fdbe1a68e59324b800ff1f07b8db30c71adcbd102a8", + "0xa19e84e3541fb6498e9bb8a099c495cbfcad113330e0262a7e4c6544495bb8a754b2208d0c2d895c93463558013a5a32", + "0x87f2bd49859a364912023aca7b19a592c60214b8d6239e2be887ae80b69ebdeb59742bdebcfa73a586ab23b2c945586c", + "0xb8e8fdddae934a14b57bc274b8dcd0d45ebb95ddbaabef4454e0f6ce7d3a5a61c86181929546b3d60c447a15134d08e1", + "0x87e0c31dcb736ea4604727e92dc1d9a3cf00adcff79df3546e02108355260f3dd171531c3c0f57be78d8b28058fcc8c0", + "0x9617d74e8f808a4165a8ac2e30878c349e1c3d40972006f0787b31ea62d248c2d9f3fc3da83181c6e57e95feedfd0e8c", + "0x8949e2cee582a2f8db86e89785a6e46bc1565c2d8627d5b6bf43ba71ffadfab7e3c5710f88dcb5fb2fc6edf6f4fae216", + "0xad3fa7b0edceb83118972a2935a09f409d09a8db3869f30be3a76f67aa9fb379cabb3a3aff805ba023a331cad7d7eb64", + "0x8c95718a4112512c4efbd496be38bf3ca6cdcaad8a0d128f32a3f9aae57f3a57bdf295a3b372a8c549fda8f4707cffed", + "0x88f3261d1e28a58b2dee3fcc799777ad1c0eb68b3560f9b4410d134672d9533532a91ea7be28a041784872632d3c9d80", + "0xb47472a41d72dd2e8b72f5c4f8ad626737dde3717f63d6bc776639ab299e564cbad0a2ad5452a07f02ff49a359c437e5", + "0x9896d21dc2e8aad87b76d6df1654f10cd7bceed4884159d50a818bea391f8e473e01e14684814c7780235f28e69dca6e", + "0x82d47c332bbd31bbe83b5eb44a23da76d4a7a06c45d7f80f395035822bc27f62f59281d5174e6f8e77cc9b5c3193d6f0", + "0x95c74cd46206e7f70c9766117c34c0ec45c2b0f927a15ea167901a160e1530d8522943c29b61e03568aa0f9c55926c53", + "0xa89d7757825ae73a6e81829ff788ea7b3d7409857b378ebccd7df73fdbe62c8d9073741cf038314971b39af6c29c9030", + "0x8c1cd212d0b010905d560688cfc036ae6535bc334fa8b812519d810b7e7dcf1bb7c5f43deaa40f097158358987324a7f", + "0xb86993c383c015ed8d847c6b795164114dd3e9efd25143f509da318bfba89389ea72a420699e339423afd68b6512fafb", + "0x8d06bd379c6d87c6ed841d8c6e9d2d0de21653a073725ff74be1934301cc3a79b81ef6dd0aad4e7a9dc6eac9b73019bc", + "0x81af4d2d87219985b9b1202d724fe39ef988f14fef07dfe3c3b11714e90ffba2a97250838e8535eb63f107abfe645e96", + "0x8c5e0af6330a8becb787e4b502f34f528ef5756e298a77dc0c7467433454347f3a2e0bd2641fbc2a45b95e231c6e1c02", + "0x8e2a8f0f04562820dc8e7da681d5cad9fe2e85dd11c785fb6fba6786c57a857e0b3bd838fb849b0376c34ce1665e4837", + "0xa39be8269449bfdfc61b1f62077033649f18dae9bef7c6163b9314ca8923691fb832f42776f0160b9e8abd4d143aa4e1", + "0x8c154e665706355e1cc98e0a4cabf294ab019545ba9c4c399d666e6ec5c869ca9e1faf8fb06cd9c0a5c2f51a7d51b70a", + "0xa046a7d4de879d3ebd4284f08f24398e9e3bf006cd4e25b5c67273ade248689c69affff92ae810c07941e4904296a563", + "0xafd94c1cb48758e5917804df03fb38a6da0e48cd9b6262413ea13b26973f9e266690a1b7d9d24bbaf7e82718e0e594b0", + "0x859e21080310c8d6a38e12e2ac9f90a156578cdeb4bb2e324700e97d9a5511cd6045dc39d1d0de3f94aeed043a24119d", + "0xa219fb0303c379d0ab50893264919f598e753aac9065e1f23ef2949abc992577ab43c636a1d2c089203ec9ddb941e27d", + "0xb0fdb639d449588a2ca730afcba59334e7c387342d56defdfb7ef79c493f7fd0e5277eff18e7203e756c7bdda5803047", + "0x87f9c3b7ed01f54368aca6dbcf2f6e06bff96e183c4b2c65f8baa23b377988863a0a125d5cdd41a072da8462ced4c070", + "0x99ef7a5d5ac2f1c567160e1f8c95f2f38d41881850f30c461a205f7b1b9fb181277311333839b13fb3ae203447e17727", + "0xaeaca9b1c2afd24e443326cc68de67b4d9cedb22ad7b501a799d30d39c85bb2ea910d4672673e39e154d699e12d9b3dc", + "0xa11675a1721a4ba24dd3d0e4c3c33a6edf4cd1b9f6b471070b4386c61f77452266eae6e3f566a40cfc885eada9a29f23", + "0xb228334445e37b9b49cb4f2cc56b454575e92173ddb01370a553bba665adadd52df353ad74470d512561c2c3473c7bb9", + "0xa18177087c996572d76f81178d18ed1ceebc8362a396348ce289f1d8bd708b9e99539be6fccd4acb1112381cfc5749b4", + "0x8e7b8bf460f0d3c99abb19803b9e43422e91507a1c0c22b29ee8b2c52d1a384da4b87c292e28eff040db5be7b1f8641f", + "0xb03d038d813e29688b6e6f444eb56fec3abba64c3d6f890a6bcf2e916507091cdb2b9d2c7484617be6b26552ed1c56cb", + "0xa1c88ccd30e934adfc5494b72655f8afe1865a84196abfb376968f22ddc07761210b6a9fb7638f1413d1b4073d430290", + "0x961b714faebf172ad2dbc11902461e286e4f24a99a939152a53406117767682a571057044decbeb3d3feef81f4488497", + "0xa03dc4059b46effdd786a0a03cc17cfee8585683faa35bb07936ded3fa3f3a097f518c0b8e2db92fd700149db1937789", + "0xadf60180c99ca574191cbcc23e8d025b2f931f98ca7dfcebfc380226239b6329347100fcb8b0fcb12db108c6ad101c07", + "0x805d4f5ef24d46911cbf942f62cb84b0346e5e712284f82b0db223db26d51aabf43204755eb19519b00e665c7719fcaa", + "0x8dea7243e9c139662a7fe3526c6c601eee72fd8847c54c8e1f2ad93ef7f9e1826b170afe58817dac212427164a88e87f", + "0xa2ba42356606d651b077983de1ad643650997bb2babb188c9a3b27245bb65d2036e46667c37d4ce02cb1be5ae8547abe", + "0xaf2ae50b392bdc013db2d12ce2544883472d72424fc767d3f5cb0ca2d973fc7d1f425880101e61970e1a988d0670c81b", + "0x98e6bec0568d3939b31d00eb1040e9b8b2a35db46ddf4369bdaee41bbb63cc84423d29ee510a170fb5b0e2df434ba589", + "0x822ff3cd12fbef4f508f3ca813c04a2e0b9b799c99848e5ad3563265979e753ee61a48f6adc2984a850f1b46c1a43d35", + "0x891e8b8b92a394f36653d55725ef514bd2e2a46840a0a2975c76c2a935577f85289026aaa74384da0afe26775cbddfb9", + "0xb2a3131a5d2fe7c8967047aa66e4524babae941d90552171cc109527f345f42aa0df06dcbb2fa01b33d0043917bbed69", + "0x80c869469900431f3eeefafdbe07b8afd8cee7739e659e6d0109b397cacff85a88247698f87dc4e2fe39a592f250ac64", + "0x9091594f488b38f9d2bb5df49fd8b4f8829d9c2f11a197dd1431ed5abbc5c954bbde3387088f9ee3a5a834beb7619bce", + "0xb472e241e6956146cca57b97a8a204668d050423b4e76f857bad5b47f43b203a04c8391ba9d9c3e95093c071f9d376a1", + "0xb7dd2de0284844392f7dfb56fe7ca3ede41e27519753ffc579a0a8d2d65ceb8108d06b6b0d4c3c1a2588951297bd1a1e", + "0x902116ce70d0a079ac190321c1f48701318c05f8e69ee09694754885d33a835a849cafe56f499a2f49f6cda413ddf9a7", + "0xb18105cc736787fafaf7c3c11c448bce9466e683159dff52723b7951dff429565e466e4841d982e3aaa9ee2066838666", + "0x97ab9911f3f659691762d568ae0b7faa1047b0aed1009c319fa79d15d0db8db9f808fc385dc9a68fa388c10224985379", + "0xb2a2cba65f5b927e64d2904ba412e2bac1cf18c9c3eda9c72fb70262497ecf505b640827e2afebecf10eebbcf48ccd3e", + "0xb36a3fd677baa0d3ef0dac4f1548ff50a1730286b8c99d276a0a45d576e17b39b3cbadd2fe55e003796d370d4be43ce3", + "0xa5dfec96ca3c272566e89dc453a458909247e3895d3e44831528130bc47cc9d0a0dac78dd3cad680a4351d399d241967", + "0x8029382113909af6340959c3e61db27392531d62d90f92370a432aec3eb1e4c36ae1d4ef2ba8ec6edb4d7320c7a453f6", + "0x971d85121ea108e6769d54f9c51299b0381ece8b51d46d49c89f65bedc123bab4d5a8bc14d6f67f4f680077529cbae4c", + "0x98ff6afc01d0bec80a278f25912e1b1ebff80117adae72e31d5b9fa4d9624db4ba2065b444df49b489b0607c45e26c4c", + "0x8fa29be10fb3ab30ce25920fec0187e6e91e458947009dabb869aade7136c8ba23602682b71e390c251f3743164cbdaa", + "0xb3345c89eb1653418fe3940cf3e56a9a9c66526389b98f45ca02dd62bfb37baa69a4baaa7132d7320695f8ea6ad1fd94", + "0xb72c7f5541c9ac6b60a7ec9f5415e7fb14da03f7164ea529952a29399f3a071576608dbbcc0d45994f21f92ddbeb1e19", + "0xaa3450bb155a5f9043d0ef95f546a2e6ade167280bfb75c9f09c6f9cdb1fffb7ce8181436161a538433afa3681c7a141", + "0x92a18fecaded7854b349f441e7102b638ababa75b1b0281dd0bded6541abe7aa37d96693595be0b01fe0a2e2133d50f9", + "0x980756ddf9d2253cfe6c94960b516c94889d09e612810935150892627d2ecee9a2517e04968eea295d0106850c04ca44", + "0xae68c6ccc454318cdd92f32b11d89116a3b8350207a36d22a0f626718cad671d960090e054c0c77ac3162ae180ecfd4b", + "0x99f31f66eaaa551749ad91d48a0d4e3ff4d82ef0e8b28f3184c54e852422ba1bdafd53b1e753f3a070f3b55f3c23b6a2", + "0xa44eaeaa6589206069e9c0a45ff9fc51c68da38d4edff1d15529b7932e6f403d12b9387019c44a1488a5d5f27782a51f", + "0xb80b5d54d4b344840e45b79e621bd77a3f83fb4ce6d8796b7d6915107b3f3c34d2e7d95bdafd120f285669e5acf2437a", + "0xb36c069ec085a612b5908314d6b84c00a83031780261d1c77a0384c406867c9847d5b0845deddfa512cc04a8df2046fb", + "0xb09dbe501583220f640d201acea7ee3e39bf9eda8b91aa07b5c50b7641d86d71acb619b38d27835ce97c3759787f08e9", + "0x87403d46a2bf63170fff0b857acacf42ee801afe9ccba8e5b4aea967b68eac73a499a65ca46906c2eb4c8f27bc739faa", + "0x82b93669f42a0a2aa5e250ffe6097269da06a9c02fcd1801abbad415a7729a64f830754bafc702e64600ba47671c2208", + "0x8e3a3029be7edb8dd3ab1f8216664c8dc50d395f603736061d802cef77627db7b859ef287ed850382c13b4d22d6a2d80", + "0x968e9ec7194ff424409d182ce0259acd950c384c163c04463bc8700a40b79beba6146d22b7fa7016875a249b7b31c602", + "0x8b42c984bbe4996e0c20862059167c6bdc5164b1ffcd928f29512664459212d263e89f0f0e30eed4e672ffa5ed0b01b5", + "0x96bac54062110dada905363211133f1f15dc7e4fd80a4c6e4a83bc9a0bcbbaba11cd2c7a13debcf0985e1a954c1da66b", + "0xa16dc8a653d67a7cd7ae90b2fffac0bf1ca587005430fe5ba9403edd70ca33e38ba5661d2ed6e9d2864400d997626a62", + "0xa68ab11a570a27853c8d67e491591dcba746bfbee08a2e75ae0790399130d027ed387f41ef1d7de8df38b472df309161", + "0x92532b74886874447c0300d07eda9bbe4b41ed25349a3da2e072a93fe32c89d280f740d8ff70d5816793d7f2b97373cc", + "0x88e35711b471e89218fd5f4d0eadea8a29405af1cd81974427bc4a5fb26ed60798daaf94f726c96e779b403a2cd82820", + "0xb5c72aa4147c19f8c4f3a0a62d32315b0f4606e0a7025edc5445571eaf4daff64f4b7a585464821574dd50dbe1b49d08", + "0x9305d9b4095258e79744338683fd93f9e657367b3ab32d78080e51d54eec331edbc224fad5093ebf8ee4bd4286757eb8", + "0xb2a17abb3f6a05bcb14dc7b98321fa8b46d299626c73d7c6eb12140bf4c3f8e1795250870947af817834f033c88a59d6", + "0xb3477004837dbd8ba594e4296f960fc91ab3f13551458445e6c232eb04b326da803c4d93e2e8dcd268b4413305ff84da", + "0x924b4b2ebaafdcfdfedb2829a8bf46cd32e1407d8d725a5bd28bdc821f1bafb3614f030ea4352c671076a63494275a3f", + "0x8b81b9ef6125c82a9bece6fdcb9888a767ac16e70527753428cc87c56a1236e437da8be4f7ecfe57b9296dc3ae7ba807", + "0x906e19ec8b8edd58bdf9ae05610a86e4ea2282b1bbc1e8b00b7021d093194e0837d74cf27ac9916bdb8ec308b00da3da", + "0xb41c5185869071760ac786078a57a2ab4e2af60a890037ac0c0c28d6826f15c2cf028fddd42a9b6de632c3d550bfbc14", + "0xa646e5dec1b713ae9dfdf7bdc6cd474d5731a320403c7dfcfd666ffc9ae0cff4b5a79530e8df3f4aa9cb80568cb138e9", + "0xb0efad22827e562bd3c3e925acbd0d9425d19057868608d78c2209a531cccd0f2c43dc5673acf9822247428ffa2bb821", + "0xa94c19468d14b6f99002fc52ac06bbe59e5c472e4a0cdb225144a62f8870b3f10593749df7a2de0bd3c9476ce682e148", + "0x803864a91162f0273d49271dafaab632d93d494d1af935aefa522768af058fce52165018512e8d6774976d52bd797e22", + "0xa08711c2f7d45c68fb340ac23597332e1bcaec9198f72967b9921204b9d48a7843561ff318f87908c05a44fc35e3cc9d", + "0x91c3cad94a11a3197ae4f9461faab91a669e0dddb0371d3cab3ed9aeb1267badc797d8375181130e461eadd05099b2a2", + "0x81bdaaf48aae4f7b480fc13f1e7f4dd3023a41439ba231760409ce9292c11128ab2b0bdbbf28b98af4f97b3551f363af", + "0x8d60f9df9fd303f625af90e8272c4ecb95bb94e6efc5da17b8ab663ee3b3f673e9f6420d890ccc94acf4d2cae7a860d8", + "0xa7b75901520c06e9495ab983f70b61483504c7ff2a0980c51115d11e0744683ce022d76e3e09f4e99e698cbd21432a0d", + "0x82956072df0586562fda7e7738226f694e1c73518dd86e0799d2e820d7f79233667192c9236dcb27637e4c65ef19d493", + "0xa586beb9b6ffd06ad200957490803a7cd8c9bf76e782734e0f55e04a3dc38949de75dc607822ec405736c576cf83bca3", + "0xa179a30d00def9b34a7e85607a447eea0401e32ab5abeee1a281f2acd1cf6ec81a178020666f641d9492b1bdf66f05a3", + "0x83e129705c538787ed8e0fdc1275e6466a3f4ee21a1e6abedd239393b1df72244723b92f9d9d9339a0cab6ebf28f5a16", + "0x811bd8d1e3722b64cd2f5b431167e7f91456e8bba2cc669d3fbbce7d553e29c3c19f629fcedd2498bc26d33a24891d17", + "0xa243c030c858f1f60cccd26b45b024698cc6d9d9e6198c1ed4964a235d9f8d0baf9cde10c8e63dfaa47f8e74e51a6e85", + "0xab839eb82e23ca52663281f863b55b0a3d6d4425c33ffb4eeb1d7979488ab068bf99e2a60e82cea4dc42c56c26cbfebe", + "0x8b896f9bb21d49343e67aec6ad175b58c0c81a3ca73d44d113ae4354a0065d98eb1a5cafedaf232a2bb9cdc62152f309", + "0xaf6230340cc0b66f5bf845540ed4fc3e7d6077f361d60762e488d57834c3e7eb7eacc1b0ed73a7d134f174a01410e50c", + "0x88975e1b1af678d1b5179f72300a30900736af580dd748fd9461ef7afccc91ccd9bed33f9da55c8711a7635b800e831f", + "0xa97486bb9047391661718a54b8dd5a5e363964e495eae6c692730264478c927cf3e66dd3602413189a3699fbeae26e15", + "0xa5973c161ab38732885d1d2785fd74bf156ba34881980cba27fe239caef06b24a533ffe6dbbbeca5e6566682cc00300a", + "0xa24776e9a840afda0003fa73b415d5bd6ecd9b5c2cc842b643ee51b8c6087f4eead4d0bfbd987eb174c489a7b952ff2a", + "0xa8a6ee06e3af053b705a12b59777267c546f33ba8a0f49493af8e6df4e15cf8dd2d4fb4daf7e84c6b5d3a7363118ff03", + "0xa28e59ce6ad02c2ce725067c0123117e12ac5a52c8f5af13eec75f4a9efc4f696777db18a374fa33bcae82e0734ebd16", + "0x86dfc3b78e841c708aff677baa8ee654c808e5d257158715097c1025d46ece94993efe12c9d188252ad98a1e0e331fec", + "0xa88d0275510f242eab11fdb0410ff6e1b9d7a3cbd3658333539815f1b450a84816e6613d15aa8a8eb15d87cdad4b27a2", + "0x8440acea2931118a5b481268ff9f180ee4ede85d14a52c026adc882410825b8275caa44aff0b50c2b88d39f21b1a0696", + "0xa7c3182eab25bd6785bacf12079d0afb0a9b165d6ed327814e2177148539f249eb9b5b2554538f54f3c882d37c0a8abe", + "0x85291fbe10538d7da38efdd55a7acebf03b1848428a2f664c3ce55367aece60039f4f320b1771c9c89a35941797f717c", + "0xa2c6414eeb1234728ab0de94aa98fc06433a58efa646ca3fcbd97dbfb8d98ae59f7ce6d528f669c8149e1e13266f69c9", + "0x840c8462785591ee93aee2538d9f1ec44ba2ca61a569ab51d335ac873f5d48099ae8d7a7efa0725d9ff8f9475bfa4f56", + "0xa7065a9d02fb3673acf7702a488fbc01aa69580964932f6f40b6c2d1c386b19e50b0e104fcac24ea26c4e723611d0238", + "0xb72db6d141267438279e032c95e6106c2ccb3164b842ba857a2018f3a35f4b040da92680881eb17cd61d0920d5b8f006", + "0xa8005d6c5960e090374747307ef0be2871a7a43fa4e76a16c35d2baab808e9777b496e9f57a4218b23390887c33a0b55", + "0x8e152cea1e00a451ca47c20a1e8875873419700af15a5f38ee2268d3fbc974d4bd5f4be38008fa6f404dbdedd6e6e710", + "0xa3391aed1fcd68761f06a7d1008ec62a09b1cb3d0203cd04e300a0c91adfed1812d8bc1e4a3fd7976dc0aae0e99f52f1", + "0x967eb57bf2aa503ee0c6e67438098149eac305089c155f1762cf5e84e31f0fbf27c34a9af05621e34645c1ec96afaec8", + "0x88af97ddc4937a95ec0dcd25e4173127260f91c8db2f6eac84afb789b363705fb3196235af631c70cafd09411d233589", + "0xa32df75b3f2c921b8767638fd289bcfc61e08597170186637a7128ffedd52c798c434485ac2c7de07014f9e895c2c3d8", + "0xb0a783832153650aa0d766a3a73ec208b6ce5caeb40b87177ffc035ab03c7705ecdd1090b6456a29f5fb7e90e2fa8930", + "0xb59c8e803b4c3486777d15fc2311b97f9ded1602fa570c7b0200bada36a49ee9ef4d4c1474265af8e1c38a93eb66b18b", + "0x982f2c85f83e852022998ff91bafbb6ff093ef22cf9d5063e083a48b29175ccbd51b9c6557151409e439096300981a6c", + "0x939e3b5989fefebb9d272a954659a4eb125b98c9da6953f5e628d26266bd0525ec38304b8d56f08d65abc4d6da4a8dbb", + "0x8898212fe05bc8de7d18503cb84a1c1337cc2c09d1eeef2b475aa79185b7322bf1f8e065f1bf871c0c927dd19faf1f6d", + "0x94b0393a41cd00f724aee2d4bc72103d626a5aecb4b5486dd1ef8ac27528398edf56df9db5c3d238d8579af368afeb09", + "0x96ac564450d998e7445dd2ea8e3fc7974d575508fa19e1c60c308d83b645864c029f2f6b7396d4ff4c1b24e92e3bac37", + "0x8adf6638e18aff3eb3b47617da696eb6c4bdfbecbbc3c45d3d0ab0b12cbad00e462fdfbe0c35780d21aa973fc150285e", + "0xb53f94612f818571b5565bbb295e74bada9b5f9794b3b91125915e44d6ddcc4da25510eab718e251a09c99534d6042d9", + "0x8b96462508d77ee083c376cd90807aebad8de96bca43983c84a4a6f196d5faf6619a2351f43bfeec101864c3bf255519", + "0xaeadf34657083fc71df33bd44af73bf5281c9ca6d906b9c745536e1819ea90b56107c55e2178ebad08f3ba75b3f81c86", + "0x9784ba29b2f0057b5af1d3ab2796d439b8753f1f749c73e791037461bdfc3f7097394283105b8ab01788ea5255a96710", + "0x8756241bda159d4a33bf74faba0d4594d963c370fb6a18431f279b4a865b070b0547a6d1613cf45b8cfb5f9236bbf831", + "0xb03ebfd6b71421dfd49a30460f9f57063eebfe31b9ceaa2a05c37c61522b35bdc09d7db3ad75c76c253c00ba282d3cd2", + "0xb34e7e6341fa9d854b2d3153bdda0c4ae2b2f442ab7af6f99a0975d45725aa48e36ae5f7011edd249862e91f499687d4", + "0xb462ee09dc3963a14354244313e3444de5cc37ea5ccfbf14cd9aca8027b59c4cb2a949bc30474497cab8123e768460e6", + "0xaea753290e51e2f6a21a9a0ee67d3a2713f95c2a5c17fe41116c87d3aa77b1683761264d704df1ac34f8b873bc88ef7b", + "0x98430592afd414394f98ddfff9f280fcb1c322dbe3510f45e1e9c4bb8ee306b3e0cf0282c0ee73ebb8ba087d4d9e0858", + "0xb95d3b5aaf54ffca11f4be8d57f76e14afdb20afc859dc7c7471e0b42031e8f3d461b726ecb979bdb2f353498dfe95ea", + "0x984d17f9b11a683132e0b5a9ee5945e3ff7054c2d5c716be73b29078db1d36f54c6e652fd2f52a19da313112e97ade07", + "0xab232f756b3fff3262be418a1af61a7e0c95ceebbc775389622a8e10610508cd6784ab7960441917a83cc191c58829ea", + "0xa28f41678d6e60de76b0e36ab10e4516e53e02e9c77d2b5af3cfeee3ce94cfa30c5797bd1daab20c98e1cad83ad0f633", + "0xb55395fca84dd3ccc05dd480cb9b430bf8631ff06e24cb51d54519703d667268c2f8afcde4ba4ed16bece8cc7bc8c6e0", + "0x8a8a5392a0e2ea3c7a8c51328fab11156004e84a9c63483b64e8f8ebf18a58b6ffa8fe8b9d95af0a2f655f601d096396", + "0xab480000fe194d23f08a7a9ec1c392334e9c687e06851f083845121ce502c06b54dda8c43092bcc1035df45cc752fe9b", + "0xb265644c29f628d1c7e8e25a5e845cabb21799371814730a41a363e1bda8a7be50fee7c3996a365b7fcba4642add10db", + "0xb8a915a3c685c2d4728f6931c4d29487cad764c5ce23c25e64b1a3259ac27235e41b23bfe7ae982921b4cb84463097df", + "0x8efa7338442a4b6318145a5440fc213b97869647eeae41b9aa3c0a27ee51285b73e3ae3b4a9423df255e6add58864aa9", + "0x9106d65444f74d217f4187dfc8fcf3810b916d1e4275f94f6a86d1c4f3565b131fd6cde1fa708bc05fe183c49f14941a", + "0x948252dac8026bbbdb0a06b3c9d66ec4cf9532163bab68076fda1bd2357b69e4b514729c15aaa83b5618b1977bbc60c4", + "0xae6596ccfdf5cbbc5782efe3bb0b101bb132dbe1d568854ca24cacc0b2e0e9fabcb2ca7ab42aecec412efd15cf8cb7a2", + "0x84a0b6c198ff64fd7958dfd1b40eac9638e8e0b2c4cd8cf5d8cdf80419baee76a05184bce6c5b635f6bf2d30055476a7", + "0x8893118be4a055c2b3da593dbca51b1ae2ea2469911acfb27ee42faf3e6c3ad0693d3914c508c0b05b36a88c8b312b76", + "0xb097479e967504deb6734785db7e60d1d8034d6ca5ba9552887e937f5e17bb413fccac2c1d1082154ed76609127860ad", + "0xa0294e6b9958f244d29943debf24b00b538b3da1116269b6e452bb12dc742226712fd1a15b9c88195afeb5d2415f505c", + "0xb3cc15f635080bc038f61b615f62b5b5c6f2870586191f59476e8368a73641d6ac2f7d0c1f54621982defdb318020230", + "0x99856f49b9fe1604d917c94d09cc0ed753d13d015d30587a94e6631ffd964b214e607deb8a69a8b5e349a7edf4309206", + "0xa8571e113ea22b4b4fce41a094da8c70de37830ae32e62c65c2fa5ad06a9bc29e884b945e73d448c72b176d6ecebfb58", + "0xa9e9c6e52beb0013273c29844956b3ce291023678107cdc785f7b44eff5003462841ad8780761b86aefc6b734adde7cf", + "0x80a784b0b27edb51ef2bad3aee80e51778dcaa0f3f5d3dcb5dc5d4f4b2cf7ae35b08de6680ea9dac53f8438b92eb09ef", + "0x827b543e609ea328e97e373f70ad72d4915a2d1daae0c60d44ac637231070e164c43a2a58db80a64df1c624a042b38f9", + "0xb449c65e8195202efdcb9bdb4e869a437313b118fef8b510cbbf8b79a4e99376adb749b37e9c20b51b31ed3310169e27", + "0x8ea3028f4548a79a94c717e1ed28ad4d8725b8d6ab18b021063ce46f665c79da3c49440c6577319dab2d036b7e08f387", + "0x897798431cfb17fe39f08f5f854005dc37b1c1ec1edba6c24bc8acb3b88838d0534a75475325a5ea98b326ad47dbad75", + "0x89cf232e6303b0751561960fd4dea5754a28c594daf930326b4541274ffb03c7dd75938e411eb9a375006a70ce38097f", + "0x9727c6ae7f0840f0b6c8bfb3a1a5582ceee705e0b5c59b97def7a7a2283edd4d3f47b7971e902a3a2079e40b53ff69b8", + "0xb76ed72b122c48679d221072efc0eeea063cb205cbf5f9ef0101fd10cb1075b8628166c83577cced654e1c001c7882f7", + "0xae908c42d208759da5ee9b405df85a6532ea35c6f0f6a1288d22870f59d98edc896841b8ac890a538e6c8d1e8b02d359", + "0x809d12fe4039a0ec80dc9be6a89acaab7797e5f7f9b163378f52f9a75a1d73b2e9ae6e3dd49e32ced439783c1cabbef5", + "0xa4149530b7f85d1098ba534d69548c6c612c416e8d35992fc1f64f4deeb41e09e49c6cf7aadbed7e846b91299358fe2d", + "0xa49342eacd1ec1148b8df1e253b1c015f603c39de11fa0a364ccb86ea32d69c34fd7aa6980a1fadcd8e785a57fa46f60", + "0x87d43eff5a006dc4dddcf76cc96c656a1f3a68f19f124181feab86c6cc9a52cb9189cdbb423414defdd9bb0ca8ff1ddc", + "0x861367e87a9aa2f0f68296ba50aa5dbc5713008d260cc2c7e62d407c2063064749324c4e8156dc21b749656cfebce26b", + "0xb5303c2f72e84e170e66ae1b0fbd51b8c7a6f27476eaf5694b64e8737d5c84b51fe90100b256465a4c4156dd873cddb0", + "0xb62849a4f891415d74f434cdc1d23c4a69074487659ca96e1762466b2b7a5d8525b056b891d0feea6fe6845cba8bc7fb", + "0x923dd9e0d6590a9307e8c4c23f13bae3306b580e297a937711a8b13e8de85e41a61462f25b7d352b682e8437bf2b4ab3", + "0x9147379860cd713cd46c94b8cdf75125d36c37517fbecf81ace9680b98ce6291cd1c3e472f84249cc3b2b445e314b1b6", + "0xa808a4f17ac21e3fb5cfef404e61fae3693ca3e688d375f99b6116779696059a146c27b06de3ac36da349b0649befd56", + "0x87787e9322e1b75e66c1f0d9ea0915722a232770930c2d2a95e9478c4b950d15ab767e30cea128f9ed65893bfc2d0743", + "0x9036a6ee2577223be105defe1081c48ea7319e112fff9110eb9f61110c319da25a6cea0464ce65e858635b079691ef1f", + "0xaf5548c7c24e1088c23b57ee14d26c12a83484c9fd9296edf1012d8dcf88243f20039b43c8c548c265ef9a1ffe9c1c88", + "0xa0fff520045e14065965fb8accd17e878d3fcaf9e0af2962c8954e50be6683d31fa0bf4816ab68f08630dbac6bfce52a", + "0xb4c1b249e079f6ae1781af1d97a60b15855f49864c50496c09c91fe1946266915b799f0406084d7783f5b1039116dd8b", + "0x8b0ffa5e7c498cb3879dddca34743b41eee8e2dea3d4317a6e961b58adb699ef0c92400c068d5228881a2b08121226bf", + "0x852ae8b19a1d80aa8ae5382e7ee5c8e7670ceb16640871c56b20b96b66b3b60e00015a3dde039446972e57b49a999ddd", + "0xa49942f04234a7d8492169da232cfff8051df86e8e1ba3db46aede02422c689c87dc1d99699c25f96cb763f5ca0983e5", + "0xb04b597b7760cf5dcf411ef896d1661e6d5b0db3257ac2cf64b20b60c6cc18fa10523bb958a48d010b55bac7b02ab3b1", + "0xa494591b51ea8285daecc194b5e5bd45ae35767d0246ac94fae204d674ee180c8e97ff15f71f28b7aeb175b8aea59710", + "0x97d2624919e78406e7460730680dea8e71c8571cf988e11441aeea54512b95bd820e78562c99372d535d96f7e200d20d", + "0xac693ddb00e48f76e667243b9b6a7008424043fb779e4f2252330285232c3fccac4da25cbd6d95fe9ad959ff305a91f6", + "0x8d20ca0a71a64a3f702a0825bb46bd810d03bebfb227683680d474a52f965716ff99e19a165ebaf6567987f4f9ee3c94", + "0xa5c516a438f916d1d68ca76996404792e0a66e97b7f18fc54c917bf10cf3211b62387932756e39e67e47b0bd6e88385a", + "0xb089614d830abc0afa435034cec7f851f2f095d479cacf1a3fb57272da826c499a52e7dcbc0eb85f4166fb94778e18e9", + "0xa8dacc943765d930848288192f4c69e2461c4b9bc6e79e30eeef9a543318cf9ae9569d6986c65c5668a89d49993f8e07", + "0xab5a9361fa339eec8c621bdad0a58078983abd8942d4282b22835d7a3a47e132d42414b7c359694986f7db39386c2e19", + "0x94230517fb57bd8eb26c6f64129b8b2abd0282323bf7b94b8bac7fab27b4ecc2c4290c294275e1a759de19f2216134f3", + "0xb8f158ea5006bc3b90b285246625faaa6ac9b5f5030dc69701b12f3b79a53ec7e92eeb5a63bbd1f9509a0a3469ff3ffc", + "0x8b6944fd8cb8540957a91a142fdcda827762aa777a31e8810ca6d026e50370ee1636fc351724767e817ca38804ebe005", + "0x82d1ee40fe1569c29644f79fa6c4033b7ed45cd2c3b343881f6eb0de2e79548fded4787fae19bed6ee76ed76ff9f2f11", + "0xa8924c7035e99eaed244ca165607e7e568b6c8085510dcdbaf6ebdbed405af2e6c14ee27d94ffef10d30aa52a60bf66d", + "0x956f82a6c2ae044635e85812581e4866c5fa2f427b01942047d81f6d79a14192f66fbbe77c9ffeaef4e6147097fdd2b5", + "0xb1100255a1bcf5e05b6aff1dfeb6e1d55b5d68d43a7457ba10cc76b61885f67f4d0d5179abda786e037ae95deb8eea45", + "0x99510799025e3e5e8fbf06dedb14c060c6548ba2bda824f687d3999dc395e794b1fb6514b9013f3892b6cf65cb0d65aa", + "0x8f9091cebf5e9c809aab415942172258f894e66e625d7388a05289183f01b8d994d52e05a8e69f784fba41db9ea357f0", + "0xa13d2eeb0776bdee9820ecb6693536720232848c51936bb4ef4fe65588d3f920d08a21907e1fdb881c1ad70b3725e726", + "0xa68b8f18922d550284c5e5dc2dda771f24c21965a6a4d5e7a71678178f46df4d8a421497aad8fcb4c7e241aba26378a0", + "0x8b7601f0a3c6ad27f03f2d23e785c81c1460d60100f91ea9d1cab978aa03b523150206c6d52ce7c7769c71d2c8228e9e", + "0xa8e02926430813caa851bb2b46de7f0420f0a64eb5f6b805401c11c9091d3b6d67d841b5674fa2b1dce0867714124cd8", + "0xb7968ecba568b8193b3058400af02c183f0a6df995a744450b3f7e0af7a772454677c3857f99c140bbdb2a09e832e8e0", + "0x8f20b1e9ba87d0a3f35309b985f3c18d2e8800f1ca7f0c52cadef773f1496b6070c936eea48c4a1cae83fd2524e9d233", + "0x88aef260042db0d641a51f40639dbeeefa9e9811df30bee695f3791f88a2f84d318f04e8926b7f47bf25956cb9e3754f", + "0x9725345893b647e9ba4e6a29e12f96751f1ae25fcaec2173e9a259921a1a7edb7a47159b3c8767e44d9e2689f5aa0f72", + "0x8c281e6f72752cb11e239e4df9341c45106eb7993c160e54423c2bffe10bc39d42624b45a1f673936ef2e1a02fc92f1a", + "0x90aba2f68bddb2fcce6c51430dacdfeec43ea8dc379660c99095df11017691ccf5faa27665cf4b9f0eea7728ae53c327", + "0xb7022695c16521c5704f49b7ddbdbec9b5f57ce0ceebe537bc0ebb0906d8196cc855a9afeb8950a1710f6a654464d93f", + "0x8fe1b9dd3c6a258116415d36e08374e094b22f0afb104385a5da48be17123e86fb8327baacc4f0d9ebae923d55d99bb5", + "0x817e85d8e3d19a4cbc1dec31597142c2daa4871bda89c2177fa719c00eda3344eb08b82eb92d4aa91a9eaacb3fc09783", + "0xb59053e1081d2603f1ca0ba553804d6fa696e1fd996631db8f62087b26a40dfef02098b0326bb75f99ec83b9267ca738", + "0x990a173d857d3ba81ff3789b931bfc9f5609cde0169b7f055fa3cb56451748d593d62d46ba33f80f9cafffe02b68dd14", + "0xb0c538dbba4954b809ab26f9f94a3cf1dcb77ce289eaec1d19f556c0ae4be1fa03af4a9b7057837541c3cc0a80538736", + "0xac3ba42f5f44f9e1fc453ce49c4ab79d0e1d5c42d3b30b1e098f3ab3f414c4c262fa12fb2be249f52d4aaf3c5224beb9", + "0xaf47467eb152e59870e21f0d4da2f43e093daf40180ab01438030684b114d025326928eaab12c41b81a066d94fce8436", + "0x98d1b58ba22e7289b1c45c79a24624f19b1d89e00f778eef327ec4856a9a897278e6f1a9a7e673844b31dde949153000", + "0x97ccb15dfadc7c59dca08cfe0d22df2e52c684cf97de1d94bc00d7ba24e020025130b0a39c0f4d46e4fc872771ee7875", + "0xb699e4ed9a000ff96ca296b2f09dce278832bc8ac96851ff3cff99ed3f6f752cfc0fea8571be28cd9b5a7ec36f1a08ee", + "0xb9f49f0edb7941cc296435ff0a912e3ad16848ee8765ab5f60a050b280d6ea585e5b34051b15f6b8934ef01ceb85f648", + "0xac3893df7b4ceab23c6b9054e48e8ba40d6e5beda8fbe90b814f992f52494186969b35d8c4cdc3c99890a222c9c09008", + "0xa41293ad22fae81dea94467bc1488c3707f3d4765059173980be93995fa4fcc3c9340796e3eed0beeb0ba0d9bb4fa3aa", + "0xa0543e77acd2aeecde13d18d258aeb2c7397b77f17c35a1992e8666ea7abcd8a38ec6c2741bd929abba2f766138618cc", + "0x92e79b22bc40e69f6527c969500ca543899105837b6b1075fa1796755c723462059b3d1b028e0b3df2559fa440e09175", + "0xa1fa1eac8f41a5197a6fb4aa1eae1a031c89f9c13ff9448338b222780cf9022e0b0925d930c37501a0ef7b2b00fdaf83", + "0xb3cb29ff73229f0637335f28a08ad8c5f166066f27c6c175164d0f26766a927f843b987ee9b309ed71cbf0a65d483831", + "0x84d4ab787f0ac00f104f4a734dc693d62d48c2aeb03913153da62c2ae2c27d11b1110dcef8980368dd84682ea2c1a308", + "0xab6a8e4bbc78d4a7b291ad3e9a8fe2d65f640524ba3181123b09d2d18a9e300e2509ccf7000fe47e75b65f3e992a2e7e", + "0xb7805ebe4f1a4df414003dc10bca805f2ab86ca75820012653e8f9b79c405196b0e2cab099f2ab953d67f0d60d31a0f9", + "0xb12c582454148338ea605d22bd00a754109063e22617f1f8ac8ddf5502c22a181c50c216c3617b9852aa5f26af56b323", + "0x86333ad9f898947e31ce747728dc8c887479e18d36ff3013f69ebef807d82c6981543b5c3788af93c4d912ba084d3cba", + "0xb514efa310dc4ad1258add138891e540d8c87142a881b5f46563cc58ecd1488e6d3a2fca54c0b72a929f3364ca8c333e", + "0xaa0a30f92843cf2f484066a783a1d75a7aa6f41f00b421d4baf20a6ac7886c468d0eea7ca8b17dd22f4f74631b62b640", + "0xb3b7dc63baec9a752e8433c0cdee4d0f9bc41f66f2b8d132faf925eef9cf89aae756fc132c45910f057122462605dc10", + "0xb9b8190dac5bfdeb59fd44f4da41a57e7f1e7d2c21faba9da91fa45cbeca06dcf299c9ae22f0c89ece11ac46352d619f", + "0x89f8cf36501ad8bdfeab863752a9090e3bfda57cf8fdeca2944864dc05925f501e252c048221bcc57136ab09a64b64b2", + "0xb0cbfaf317f05f97be47fc9d69eda2dd82500e00d42612f271a1fe24626408c28881f171e855bd5bd67409f9847502b4", + "0xa7c21a8fcede581bfd9847b6835eda62ba250bea81f1bb17372c800a19c732abe03064e64a2f865d974fb636cab4b859", + "0x95f9df524ba7a4667351696c4176b505d8ea3659f5ff2701173064acc624af69a0fad4970963736383b979830cb32260", + "0x856a74fe8b37a2e3afeac858c8632200485d438422a16ae3b29f359e470e8244995c63ad79c7e007ed063f178d0306fd", + "0xb37faa4d78fdc0bb9d403674dbea0176c2014a171c7be8527b54f7d1a32a76883d3422a3e7a5f5fcc5e9b31b57822eeb", + "0x8d37234d8594ec3fe75670b5c9cc1ec3537564d4739b2682a75b18b08401869a4264c0f264354219d8d896cded715db4", + "0xb5289ee5737f0e0bde485d32096d23387d68dab8f01f47821ab4f06cc79a967afe7355e72dc0c751d96b2747b26f6255", + "0x9085e1fdf9f813e9c3b8232d3c8863cd84ab30d45e8e0d3d6a0abd9ebc6fd70cdf749ff4d04390000e14c7d8c6655fc7", + "0x93a388c83630331eca4da37ea4a97b3b453238af474817cc0a0727fd3138dcb4a22de38c04783ec829c22cb459cb4e8e", + "0xa5377116027c5d061dbe24c240b891c08cdd8cd3f0899e848d682c873aff5b8132c1e7cfe76d2e5ed97ee0eb1d42cb68", + "0xa274c84b04338ed28d74683e2a7519c2591a3ce37c294d6f6e678f7d628be2db8eff253ede21823e2df7183e6552f622", + "0x8bc201147a842453a50bec3ac97671397bc086d6dfc9377fa38c2124cdc286abda69b7324f47d64da094ae011d98d9d9", + "0x9842d0c066c524592b76fbec5132bc628e5e1d21c424bec4555efca8619cc1fd8ea3161febcb8b9e8ab54702f4e815e2", + "0xa19191b713a07efe85c266f839d14e25660ee74452e6c691cd9997d85ae4f732052d802d3deb018bdd847caa298a894b", + "0xa24f71fc0db504da4e287dd118a4a74301cbcd16033937ba2abc8417956fcb4ae19b8e63b931795544a978137eff51cb", + "0xa90eec4a6a3a4b8f9a5b93d978b5026fcf812fe65585b008d7e08c4aaf21195a1d0699f12fc16f79b6a18a369af45771", + "0x8b551cf89737d7d06d9b3b9c4c1c73b41f2ea0af4540999c70b82dabff8580797cf0a3caf34c86c59a7069eb2e38f087", + "0xb8d312e6c635e7a216a1cda075ae77ba3e1d2fd501dc31e83496e6e81ed5d9c7799f8e578869c2e0e256fb29f5de10a7", + "0x8d144bdb8cae0b2cdb5b33d44bbc96984a5925202506a8cc65eb67ac904b466f5a7fe3e1cbf04aa785bbb7348c4bb73c", + "0xa101b3d58b7a98659244b88de0b478b3fb87dc5fc6031f6e689b99edf498abd43e151fd32bd4bbd240e0b3e59c440359", + "0x907453abca7d8e7151a05cc3d506c988007692fe7401395dc93177d0d07d114ab6cca0cc658eb94c0223fe8658295cad", + "0x825329ffbe2147ddb68f63a0a67f32d7f309657b8e5d9ab5bb34b3730bfa2c77a23eaaadb05def7d9f94a9e08fdc1e96", + "0x88ee923c95c1dac99ae7ed6067906d734d793c5dc5d26339c1bb3314abe201c5dccb33b9007351885eb2754e9a8ea06c", + "0x98bc9798543f5f1adc9f2cfcfa72331989420e9c3f6598c45269f0dc9b7c8607bbeaf03faa0aea2ddde2b8f17fdceff5", + "0x8ee87877702a79aef923ab970db6fa81561b3c07d5bf1a072af0a7bad765b4cbaec910afe1a91703feacc7822fa38a94", + "0x8060b9584aa294fe8adc2b22f67e988bc6da768eae91e429dcc43ddc53cfcc5d6753fdc1b420b268c7eb2fb50736a970", + "0xb344a5524d80a2f051870c7001f74fcf348a70fcf78dbd20c6ff9ca85d81567d2318c8b8089f2c4f195d6aec9fc15fa6", + "0x8f5a5d893e1936ed062149d20eb73d98b62b7f50ab5d93a6429c03656b36688d1c80cb5010e4977491e51fa0d7dd35d5", + "0x86fa32ebbf97328c5f5f15564e1238297e289ec3219b9a741724e9f3ae8d5c15277008f555863a478b247ba5dc601d44", + "0x9557e55377e279f4b6b5e0ffe01eca037cc13aac242d67dfcd0374a1e775c5ed5cb30c25fe21143fee54e3302d34a3ea", + "0x8cb6bcbc39372d23464a416ea7039f57ba8413cf3f00d9a7a5b356ab20dcb8ed11b3561f7bce372b8534d2870c7ee270", + "0xb5d59075cb5abde5391f64b6c3b8b50adc6e1f654e2a580b6d6d6eff3f4fbdd8fffc92e06809c393f5c8eab37f774c4b", + "0xafcfb6903ef13e493a1f7308675582f15af0403b6553e8c37afb8b2808ad21b88b347dc139464367dc260df075fea1ad", + "0x810fbbe808375735dd22d5bc7fc3828dc49fdd22cc2d7661604e7ac9c4535c1df578780affb3b895a0831640a945bcad", + "0x8056b0c678803b416f924e09a6299a33cf9ad7da6fe1ad7accefe95c179e0077da36815fde3716711c394e2c5ea7127f", + "0x8b67403702d06979be19f1d6dc3ec73cc2e81254d6b7d0cc49cd4fdda8cd51ab0835c1d2d26fc0ecab5df90585c2f351", + "0x87f97f9e6d4be07e8db250e5dd2bffdf1390665bc5709f2b631a6fa69a7fca958f19bd7cc617183da1f50ee63e9352b5", + "0xae151310985940471e6803fcf37600d7fa98830613e381e00dab943aec32c14162d51c4598e8847148148000d6e5af5c", + "0x81eb537b35b7602c45441cfc61b27fa9a30d3998fad35a064e05bc9479e9f10b62eba2b234b348219eea3cadcaac64bb", + "0x8a441434934180ab6f5bc541f86ebd06eadbee01f438836d797e930fa803a51510e005c9248cecc231a775b74d12b5e9", + "0x81f3c250a27ba14d8496a5092b145629eb2c2e6a5298438670375363f57e2798207832c8027c3e9238ad94ecdadfc4df", + "0xa6217c311f2f3db02ceaa5b6096849fe92b6f4b6f1491535ef8525f6ccee6130bed2809e625073ecbaddd4a3eb3df186", + "0x82d1c396f0388b942cf22b119d7ef1ad03d3dad49a74d9d01649ee284f377c8daddd095d596871669e16160299a210db", + "0xa40ddf7043c5d72a7246bd727b07f7fff1549f0e443d611de6f9976c37448b21664c5089c57f20105102d935ab82f27b", + "0xb6c03c1c97adf0c4bf4447ec71366c6c1bff401ba46236cd4a33d39291e7a1f0bb34bd078ba3a18d15c98993b153a279", + "0x8a94f5f632068399c359c4b3a3653cb6df2b207379b3d0cdace51afdf70d6d5cce6b89a2b0fee66744eba86c98fb21c2", + "0xb2f19e78ee85073f680c3bba1f07fd31b057c00b97040357d97855b54a0b5accb0d3b05b2a294568fcd6a4be6f266950", + "0xa74632d13bbe2d64b51d7a9c3ae0a5a971c19f51cf7596a807cea053e6a0f3719700976d4e394b356c0329a2dced9aa2", + "0xafef616d341a9bc94393b8dfba68ff0581436aa3a3adb7c26a1bbf2cf19fa877066191681f71f17f3cd6f9cf6bf70b5a", + "0x8ce96d93ae217408acf7eb0f9cbb9563363e5c7002e19bbe1e80760bc9d449daee2118f3878b955163ed664516b97294", + "0x8414f79b496176bc8b8e25f8e4cfee28f4f1c2ddab099d63d2aca1b6403d26a571152fc3edb97794767a7c4686ad557c", + "0xb6c61d01fd8ce087ef9f079bf25bf10090db483dd4f88c4a786d31c1bdf52065651c1f5523f20c21e75cea17df69ab73", + "0xa5790fd629be70545093631efadddc136661f63b65ec682609c38ef7d3d7fa4e56bdf94f06e263bc055b90cb1c6bcefe", + "0xb515a767e95704fb7597bca9e46f1753abacdc0e56e867ee3c6f4cd382643c2a28e65312c05ad040eaa3a8cbe7217a65", + "0x8135806a02ead6aa92e9adb6fefb91349837ab73105aaa7be488ef966aa8dfaafdfa64bbae30fcbfa55dd135a036a863", + "0x8f22435702716d76b1369750694540742d909d5e72b54d0878245fab7c269953b1c6f2b29c66f08d5e0263ca3a731771", + "0x8e0f8a8e8753e077dac95848212aeffd51c23d9b6d611df8b102f654089401954413ecbedc6367561ca599512ae5dda7", + "0x815a9084e3e2345f24c5fa559deec21ee1352fb60f4025c0779be65057f2d528a3d91593bd30d3a185f5ec53a9950676", + "0x967e6555ccba395b2cc1605f8484c5112c7b263f41ce8439a99fd1c71c5ed14ad02684d6f636364199ca48afbbde13be", + "0x8cd0ccf17682950b34c796a41e2ea7dd5367aba5e80a907e01f4cdc611e4a411918215e5aebf4292f8b24765d73314a6", + "0xa58bf1bbb377e4b3915df6f058a0f53b8fb8130fdec8c391f6bc82065694d0be59bb67ffb540e6c42cc8b380c6e36359", + "0x92af3151d9e6bfb3383d85433e953c0160859f759b0988431ec5893542ba40288f65db43c78a904325ef8d324988f09d", + "0x8011bbb05705167afb47d4425065630f54cb86cd462095e83b81dfebf348f846e4d8fbcf1c13208f5de1931f81da40b9", + "0x81c743c104fc3cb047885c9fa0fb9705c3a83ee24f690f539f4985509c3dafd507af3f6a2128276f45d5939ef70c167f", + "0xa2c9679b151c041aaf5efeac5a737a8f70d1631d931609fca16be1905682f35e291292874cb3b03f14994f98573c6f44", + "0xa4949b86c4e5b1d5c82a337e5ce6b2718b1f7c215148c8bfb7e7c44ec86c5c9476048fc5c01f57cb0920876478c41ad6", + "0x86c2495088bd1772152e527a1da0ef473f924ea9ab0e5b8077df859c28078f73c4e22e3a906b507fdf217c3c80808b5c", + "0x892e0a910dcf162bcea379763c3e2349349e4cda9402949255ac4a78dd5a47e0bf42f5bd0913951576b1d206dc1e536a", + "0xa7009b2c6b396138afe4754b7cc10dee557c51c7f1a357a11486b3253818531f781ea8107360c8d4c3b1cd96282353c0", + "0x911763ef439c086065cc7b4e57484ed6d693ea44acee4b18c9fd998116da55fbe7dcb8d2a0f0f9b32132fca82d73dff6", + "0xa722000b95a4a2d40bed81870793f15ba2af633f9892df507f2842e52452e02b5ea8dea6a043c2b2611d82376e33742a", + "0x9387ac49477bd719c2f92240d0bdfcf9767aad247ca93dc51e56106463206bc343a8ec855eb803471629a66fffb565d6", + "0x92819a1fa48ab4902939bb72a0a4e6143c058ea42b42f9bc6cea5df45f49724e2530daf3fc4f097cceefa2a8b9db0076", + "0x98eac7b04537653bc0f4941aae732e4b1f84bd276c992c64a219b8715eb1fb829b5cbd997d57feb15c7694c468f95f70", + "0xb275e7ba848ce21bf7996e12dbeb8dadb5d0e4f1cb5a0248a4f8f9c9fe6c74e3c93f4b61edbcb0a51af5a141e1c14bc7", + "0x97243189285aba4d49c53770c242f2faf5fd3914451da4931472e3290164f7663c726cf86020f8f181e568c72fd172d1", + "0x839b0b3c25dd412bee3dc24653b873cc65454f8f16186bb707bcd58259c0b6765fa4c195403209179192a4455c95f3b8", + "0x8689d1a870514568a074a38232e2ceb4d7df30fabeb76cff0aed5b42bf7f02baea12c5fadf69f4713464dbd52aafa55f", + "0x8958ae7b290f0b00d17c3e9fdb4dbf168432b457c7676829299dd428984aba892de1966fc106cfc58a772862ecce3976", + "0xa422bc6bd68b8870cfa5bc4ce71781fd7f4368b564d7f1e0917f6013c8bbb5b240a257f89ecfdbecb40fe0f3aa31d310", + "0xaa61f78130cebe09bc9a2c0a37f0dd57ed2d702962e37d38b1df7f17dc554b1d4b7a39a44182a452ce4c5eb31fa4cfcc", + "0xb7918bd114f37869bf1a459023386825821bfadce545201929d13ac3256d92a431e34f690a55d944f77d0b652cefeffc", + "0x819bba35fb6ace1510920d4dcff30aa682a3c9af9022e287751a6a6649b00c5402f14b6309f0aeef8fce312a0402915e", + "0x8b7c9ad446c6f63c11e1c24e24014bd570862b65d53684e107ba9ad381e81a2eaa96731b4b33536efd55e0f055071274", + "0x8fe79b53f06d33386c0ec7d6d521183c13199498594a46d44a8a716932c3ec480c60be398650bbfa044fa791c4e99b65", + "0x9558e10fb81250b9844c99648cf38fa05ec1e65d0ccbb18aa17f2d1f503144baf59d802c25be8cc0879fff82ed5034ad", + "0xb538a7b97fbd702ba84645ca0a63725be1e2891c784b1d599e54e3480e4670d0025526674ef5cf2f87dddf2290ba09f0", + "0x92eafe2e869a3dd8519bbbceb630585c6eb21712b2f31e1b63067c0acb5f9bdbbcbdb612db4ea7f9cc4e7be83d31973f", + "0xb40d21390bb813ab7b70a010dff64c57178418c62685761784e37d327ba3cb9ef62df87ecb84277c325a637fe3709732", + "0xb349e6fbf778c4af35fbed33130bd8a7216ed3ba0a79163ebb556e8eb8e1a7dad3456ddd700dad9d08d202491c51b939", + "0xa8fdaedecb251f892b66c669e34137f2650509ade5d38fbe8a05d9b9184bb3b2d416186a3640429bd1f3e4b903c159dd", + "0xac6167ebfee1dbab338eff7642f5e785fc21ef0b4ddd6660333fe398068cbd6c42585f62e81e4edbb72161ce852a1a4f", + "0x874b1fbf2ebe140c683bd7e4e0ab017afa5d4ad38055aaa83ee6bbef77dbc88a6ce8eb0dcc48f0155244af6f86f34c2d", + "0x903c58e57ddd9c446afab8256a6bb6c911121e6ccfb4f9b4ed3e2ed922a0e500a5cb7fa379d5285bc16e11dac90d1fda", + "0x8dae7a0cffa2fd166859cd1bf10ff82dd1932e488af377366b7efc0d5dec85f85fe5e8150ff86a79a39cefc29631733a", + "0xaa047857a47cc4dfc08585f28640420fcf105b881fd59a6cf7890a36516af0644d143b73f3515ab48faaa621168f8c31", + "0x864508f7077c266cc0cb3f7f001cb6e27125ebfe79ab57a123a8195f2e27d3799ff98413e8483c533b46a816a3557f1f", + "0x8bcd45ab1f9cbab36937a27e724af819838f66dfeb15923f8113654ff877bd8667c54f6307aaf0c35027ca11b6229bfd", + "0xb21aa34da9ab0a48fcfdd291df224697ce0c1ebc0e9b022fdee8750a1a4b5ba421c419541ed5c98b461eecf363047471", + "0xa9a18a2ab2fae14542dc336269fe612e9c1af6cf0c9ac933679a2f2cb77d3c304114f4d219ca66fe288adde30716775b", + "0xb5205989b92c58bdda71817f9a897e84100b5c4e708de1fced5c286f7a6f01ae96b1c8d845f3a320d77c8e2703c0e8b1", + "0xa364059412bbcc17b8907d43ac8e5df90bc87fd1724b5f99832d0d24559fae6fa76a74cff1d1eac8cbac6ec80b44af20", + "0xae709f2c339886b31450834cf29a38b26eb3b0779bd77c9ac269a8a925d1d78ea3837876c654b61a8fe834b3b6940808", + "0x8802581bba66e1952ac4dab36af371f66778958f4612901d95e5cac17f59165e6064371d02de8fb6fccf89c6dc8bd118", + "0xa313252df653e29c672cbcfd2d4f775089cb77be1077381cf4dc9533790e88af6cedc8a119158e7da5bf6806ad9b91a1", + "0x992a065b4152c7ef11515cd54ba9d191fda44032a01aed954acff3443377ee16680c7248d530b746b8c6dee2d634e68c", + "0xb627b683ee2b32c1ab4ccd27b9f6cce2fe097d96386fa0e5c182ad997c4c422ab8dfc03870cd830b8c774feb66537282", + "0xb823cf8a9aee03dadd013eb9efe40a201b4b57ef67efaae9f99683005f5d1bf55e950bf4af0774f50859d743642d3fea", + "0xb8a7449ffac0a3f206677097baf7ce00ca07a4d2bd9b5356fbcb83f3649b0fda07cfebad220c1066afba89e5a52abf4b", + "0xb2dd1a2f986395bb4e3e960fbbe823dbb154f823284ebc9068502c19a7609790ec0073d08bfa63f71e30c7161b6ef966", + "0x98e5236de4281245234f5d40a25b503505af140b503a035fc25a26159a9074ec81512b28f324c56ea2c9a5aa7ce90805", + "0x89070847dc8bbf5bc4ed073aa2e2a1f699cf0c2ca226f185a0671cecc54e7d3e14cd475c7752314a7a8e7476829da4bc", + "0xa9402dc9117fdb39c4734c0688254f23aed3dce94f5f53f5b7ef2b4bf1b71a67f85ab1a38ec224a59691f3bee050aeb3", + "0x957288f9866a4bf56a4204218ccc583f717d7ce45c01ea27142a7e245ad04a07f289cc044f8cf1f21d35e67e39299e9c", + "0xb2fb31ccb4e69113763d7247d0fc8edaae69b550c5c56aecacfd780c7217dc672f9fb7496edf4aba65dacf3361268e5b", + "0xb44a4526b2f1d6eb2aa8dba23bfa385ff7634572ab2afddd0546c3beb630fbfe85a32f42dd287a7fec069041411537f7", + "0x8db5a6660c3ac7fd7a093573940f068ee79a82bc17312af900b51c8c439336bc86ca646c6b7ab13aaaa008a24ca508ab", + "0x8f9899a6d7e8eb4367beb5c060a1f8e94d8a21099033ae582118477265155ba9e72176a67f7f25d7bad75a152b56e21a", + "0xa67de0e91ade8d69a0e00c9ff33ee2909b8a609357095fa12319e6158570c232e5b6f4647522efb7345ce0052aa9d489", + "0x82eb2414898e9c3023d57907a2b17de8e7eea5269029d05a94bfd7bf5685ac4a799110fbb375eb5e0e2bd16acf6458ae", + "0x94451fc7fea3c5a89ba701004a9693bab555cb622caf0896b678faba040409fdfd14a978979038b2a81e8f0abc4994d2", + "0xac879a5bb433998e289809a4a966bd02b4bf6a9c1cc276454e39c886efcf4fc68baebed575826bde577ab5aa71d735a9", + "0x880c0f8f49c875dfd62b4ddedde0f5c8b19f5687e693717f7e5c031bc580e58e13ab497d48b4874130a18743c59fdce3", + "0xb582af8d8ff0bf76f0a3934775e0b54c0e8fed893245d7d89cae65b03c8125b7237edc29dc45b4fe1a3fe6db45d280ee", + "0x89f337882ed3ae060aaee98efa20d79b6822bde9708c1c5fcee365d0ec9297f694cae37d38fd8e3d49717c1e86f078e7", + "0x826d2c1faea54061848b484e288a5f4de0d221258178cf87f72e14baaa4acc21322f8c9eab5dde612ef497f2d2e1d60b", + "0xa5333d4f227543e9cd741ccf3b81db79f2f03ca9e649e40d6a6e8ff9073e06da83683566d3b3c8d7b258c62970fb24d1", + "0xa28f08c473db06aaf4c043a2fae82b3c8cfaa160bce793a4c208e4e168fb1c65115ff8139dea06453c5963d95e922b94", + "0x8162546135cc5e124e9683bdfaa45833c18553ff06a0861c887dc84a5b12ae8cd4697f6794c7ef6230492c32faba7014", + "0xb23f0d05b74c08d6a7df1760792be83a761b36e3f8ae360f3c363fb196e2a9dd2de2e492e49d36561366e14daa77155c", + "0xb6f70d6c546722d3907c708d630dbe289771d2c8bf059c2e32b77f224696d750b4dda9b3a014debda38e7d02c9a77585", + "0x83bf4c4a9f3ca022c631017e7a30ea205ba97f7f5927cba8fc8489a4646eac6712cb821c5668c9ffe94d69d524374a27", + "0xb0371475425a8076d0dd5f733f55aabbe42d20a7c8ea7da352e736d4d35a327b2beb370dfcb05284e22cfd69c5f6c4cc", + "0xa0031ba7522c79211416c2cca3aa5450f96f8fee711552a30889910970ba13608646538781a2c08b834b140aadd7166f", + "0x99d273c80c7f2dc6045d4ed355d9fc6f74e93549d961f4a3b73cd38683f905934d359058cd1fc4da8083c7d75070487f", + "0xb0e4b0efa3237793e9dcce86d75aafe9879c5fa23f0d628649aef2130454dcf72578f9bf227b9d2b9e05617468e82588", + "0xa5ab076fa2e1c5c51f3ae101afdd596ad9d106bba7882b359c43d8548b64f528af19afa76cd6f40da1e6c5fca4def3fa", + "0x8ce2299e570331d60f6a6eff1b271097cd5f1c0e1113fc69b89c6a0f685dabea3e5bc2ac6bd789aa492ab189f89be494", + "0x91b829068874d911a310a5f9dee001021f97471307b5a3de9ec336870ec597413e1d92010ce320b619f38bed7c4f7910", + "0xb14fe91f4b07bf33b046e9285b66cb07927f3a8da0af548ac2569b4c4fb1309d3ced76d733051a20814e90dd5b75ffd1", + "0xabaab92ea6152d40f82940277c725aa768a631ee0b37f5961667f82fb990fc11e6d3a6a2752b0c6f94563ed9bb28265c", + "0xb7fe28543eca2a716859a76ab9092f135337e28109544f6bd2727728d0a7650428af5713171ea60bfc273d1c821d992c", + "0x8a4917b2ab749fc7343fc64bdf51b6c0698ff15d740cc7baf248c030475c097097d5a473bcc00d8c25817563fe0447b4", + "0xaa96156d1379553256350a0a3250166add75948fb9cde62aa555a0a9dc0a9cb7f2f7b8428aff66097bf6bfedaf14bbe2", + "0xae4ffeb9bdc76830d3eca2b705f30c1bdede6412fa064260a21562c8850c7fb611ec62bc68479fe48f692833e6f66d8d", + "0xb96543caaba9d051600a14997765d49e4ab10b07c7a92cccf0c90b309e6da334fdd6d18c96806cbb67a7801024fbd3c7", + "0x97b2b9ad76f19f500fcc94ca8e434176249f542ac66e5881a3dccd07354bdab6a2157018b19f8459437a68d8b86ba8e0", + "0xa8d206f6c5a14c80005849474fde44b1e7bcf0b2d52068f5f97504c3c035b09e65e56d1cf4b5322791ae2c2fdbd61859", + "0x936bad397ad577a70cf99bf9056584a61bd7f02d2d5a6cf219c05d770ae30a5cd902ba38366ce636067fc1dd10108d31", + "0xa77e30195ee402b84f3882e2286bf5380c0ed374a112dbd11e16cef6b6b61ab209d4635e6f35cdaaa72c1a1981d5dabe", + "0xa46ba4d3947188590a43c180757886a453a0503f79cc435322d92490446f37419c7b999fdf868a023601078070e03346", + "0x80d8d4c5542f223d48240b445d4d8cf6a75d120b060bc08c45e99a13028b809d910b534d2ac47fb7068930c54efd8da9", + "0x803be9c68c91b42b68e1f55e58917a477a9a6265e679ca44ee30d3eb92453f8c89c64eafc04c970d6831edd33d066902", + "0xb14b2b3d0dfe2bb57cee4cd72765b60ac33c1056580950be005790176543826c1d4fbd737f6cfeada6c735543244ab57", + "0xa9e480188bba1b8fb7105ff12215706665fd35bf1117bacfb6ab6985f4dbc181229873b82e5e18323c2b8f5de03258e0", + "0xa66a0f0779436a9a3999996d1e6d3000f22c2cac8e0b29cddef9636393c7f1457fb188a293b6c875b05d68d138a7cc4a", + "0x848397366300ab40c52d0dbbdafbafef6cd3dadf1503bb14b430f52bb9724188928ac26f6292a2412bc7d7aa620763c8", + "0x95466cc1a78c9f33a9aaa3829a4c8a690af074916b56f43ae46a67a12bb537a5ac6dbe61590344a25b44e8512355a4a7", + "0x8b5f7a959f818e3baf0887f140f4575cac093d0aece27e23b823cf421f34d6e4ff4bb8384426e33e8ec7b5eed51f6b5c", + "0x8d5e1368ec7e3c65640d216bcc5d076f3d9845924c734a34f3558ac0f16e40597c1a775a25bf38b187213fbdba17c93b", + "0xb4647c1b823516880f60d20c5cc38c7f80b363c19d191e8992226799718ee26b522a12ecb66556ed3d483aa4824f3326", + "0xac3abaea9cd283eb347efda4ed9086ea3acf495043e08d0d19945876329e8675224b685612a6badf8fd72fb6274902b1", + "0x8eae1ce292d317aaa71bcf6e77e654914edd5090e2e1ebab78b18bb41b9b1bc2e697439f54a44c0c8aa0d436ebe6e1a9", + "0x94dc7d1aec2c28eb43d93b111fa59aaa0d77d5a09501220bd411768c3e52208806abf973c6a452fd8292ff6490e0c9e2", + "0x8fd8967f8e506fef27d17b435d6b86b232ec71c1036351f12e6fb8a2e12daf01d0ee04451fb944d0f1bf7fd20e714d02", + "0x824e6865be55d43032f0fec65b3480ea89b0a2bf860872237a19a54bc186a85d2f8f9989cc837fbb325b7c72d9babe2c", + "0x8bd361f5adb27fd6f4e3f5de866e2befda6a8454efeb704aacc606f528c03f0faae888f60310e49440496abd84083ce2", + "0xb098a3c49f2aaa28b6b3e85bc40ce6a9cdd02134ee522ae73771e667ad7629c8d82c393fba9f27f5416986af4c261438", + "0xb385f5ca285ff2cfe64dcaa32dcde869c28996ed091542600a0b46f65f3f5a38428cca46029ede72b6cf43e12279e3d3", + "0x8196b03d011e5be5288196ef7d47137d6f9237a635ab913acdf9c595fa521d9e2df722090ec7eb0203544ee88178fc5f", + "0x8ed1270211ef928db18e502271b7edf24d0bbd11d97f2786aee772d70c2029e28095cf8f650b0328cc8a4c38d045316d", + "0xa52ab60e28d69b333d597a445884d44fd2a7e1923dd60f763951e1e45f83e27a4dac745f3b9eff75977b3280e132c15d", + "0x91e9fe78cdac578f4a4687f71b800b35da54b824b1886dafec073a3c977ce7a25038a2f3a5b1e35c2c8c9d1a7312417c", + "0xa42832173f9d9491c7bd93b21497fbfa4121687cd4d2ab572e80753d7edcbb42cfa49f460026fbde52f420786751a138", + "0x97b947126d84dcc70c97be3c04b3de3f239b1c4914342fa643b1a4bb8c4fe45c0fcb585700d13a7ed50784790c54bef9", + "0x860e407d353eac070e2418ef6cb80b96fc5f6661d6333e634f6f306779651588037be4c2419562c89c61f9aa2c4947f5", + "0xb2c9d93c3ba4e511b0560b55d3501bf28a510745fd666b3cb532db051e6a8617841ea2f071dda6c9f15619c7bfd2737f", + "0x8596f4d239aeeac78311207904d1bd863ef68e769629cc379db60e019aaf05a9d5cd31dc8e630b31e106a3a93e47cbc5", + "0x8b26e14e2e136b65c5e9e5c2022cee8c255834ea427552f780a6ca130a6446102f2a6f334c3f9a0308c53df09e3dba7e", + "0xb54724354eb515a3c8bed0d0677ff1db94ac0a07043459b4358cb90e3e1aa38ac23f2caa3072cf9647275d7cd61d0e80", + "0xb7ce9fe0e515e7a6b2d7ddcb92bc0196416ff04199326aea57996eef8c5b1548bd8569012210da317f7c0074691d01b7", + "0xa1a13549c82c877253ddefa36a29ea6a23695ee401fdd48e65f6f61e5ebd956d5e0edeff99484e9075cb35071fec41e2", + "0x838ba0c1e5bd1a6da05611ff1822b8622457ebd019cb065ece36a2d176bd2d889511328120b8a357e44569e7f640c1e6", + "0xb916eccff2a95519400bbf76b5f576cbe53cf200410370a19d77734dc04c05b585cfe382e8864e67142d548cd3c4c2f4", + "0xa610447cb7ca6eea53a6ff1f5fe562377dcb7f4aaa7300f755a4f5e8eba61e863c51dc2aa9a29b35525b550fbc32a0fe", + "0x9620e8f0f0ee9a4719aa9685eeb1049c5c77659ba6149ec4c158f999cfd09514794b23388879931fe26fea03fa471fd3", + "0xa9dcf8b679e276583cf5b9360702a185470d09aea463dc474ee9c8aee91ef089dacb073e334e47fbc78ec5417c90465c", + "0x8c9adee8410bdd99e5b285744cee61e2593b6300ff31a8a83b0ec28da59475a5c6fb9346fe43aadea2e6c3dad2a8e30a", + "0x97d5afe9b3897d7b8bb628b7220cf02d8ee4e9d0b78f5000d500aaf4c1df9251aaaabfd1601626519f9d66f00a821d4e", + "0x8a382418157b601ce4c3501d3b8409ca98136a4ef6abcbf62885e16e215b76b035c94d149cc41ff92e42ccd7c43b9b3d", + "0xb64b8d11fb3b01abb2646ac99fdb9c02b804ce15d98f9fe0fbf1c9df8440c71417487feb6cdf51e3e81d37104b19e012", + "0x849d7d044f9d8f0aab346a9374f0b3a5d14a9d1faa83dbacccbdc629ad1ef903a990940255564770537f8567521d17f0", + "0x829dbb0c76b996c2a91b4cbbe93ba455ca0d5729755e5f0c92aaee37dff7f36fcdc06f33aca41f1b609c784127b67d88", + "0x85a7c0069047b978422d264d831ab816435f63938015d2e977222b6b5746066c0071b7f89267027f8a975206ed25c1b0", + "0x84b9fbc1cfb302df1acdcf3dc5d66fd1edfe7839f7a3b2fb3a0d5548656249dd556104d7c32b73967bccf0f5bdcf9e3b", + "0x972220ac5b807f53eac37dccfc2ad355d8b21ea6a9c9b011c09fe440ddcdf7513e0b43d7692c09ded80d7040e26aa28f", + "0x855885ed0b21350baeca890811f344c553cf9c21024649c722453138ba29193c6b02c4b4994cd414035486f923472e28", + "0x841874783ae6d9d0e59daea03e96a01cbbe4ecaced91ae4f2c8386e0d87b3128e6d893c98d17c59e4de1098e1ad519dd", + "0x827e50fc9ce56f97a4c3f2f4cbaf0b22f1c3ce6f844ff0ef93a9c57a09b8bf91ebfbd2ba9c7f83c442920bffdaf288cc", + "0xa441f9136c7aa4c08d5b3534921b730e41ee91ab506313e1ba5f7c6f19fd2d2e1594e88c219834e92e6fb95356385aa7", + "0x97d75b144471bf580099dd6842b823ec0e6c1fb86dd0da0db195e65524129ea8b6fd4a7a9bbf37146269e938a6956596", + "0xa4b6fa87f09d5a29252efb2b3aaab6b3b6ea9fab343132a651630206254a25378e3e9d6c96c3d14c150d01817d375a8e", + "0xa31a671876d5d1e95fe2b8858dc69967231190880529d57d3cab7f9f4a2b9b458ac9ee5bdaa3289158141bf18f559efb", + "0x90bee6fff4338ba825974021b3b2a84e36d617e53857321f13d2b3d4a28954e6de3b3c0e629d61823d18a9763313b3bf", + "0x96b622a63153f393bb419bfcf88272ea8b3560dbd46b0aa07ada3a6223990d0abdd6c2adb356ef4be5641688c8d83941", + "0x84c202adeaff9293698022bc0381adba2cd959f9a35a4e8472288fd68f96f6de8be9da314c526d88e291c96b1f3d6db9", + "0x8ca01a143b8d13809e5a8024d03e6bc9492e22226073ef6e327edf1328ef4aff82d0bcccee92cb8e212831fa35fe1204", + "0xb2f970dbad15bfbefb38903c9bcc043d1367055c55dc1100a850f5eb816a4252c8c194b3132c929105511e14ea10a67d", + "0xa5e36556472a95ad57eb90c3b6623671b03eafd842238f01a081997ffc6e2401f76e781d049bb4aa94d899313577a9cf", + "0x8d1057071051772f7c8bedce53a862af6fd530dd56ae6321eaf2b9fc6a68beff5ed745e1c429ad09d5a118650bfd420a", + "0x8aadc4f70ace4fcb8d93a78610779748dcffc36182d45b932c226dc90e48238ea5daa91f137c65ed532352c4c4d57416", + "0xa2ea05ae37e673b4343232ae685ee14e6b88b867aef6dfac35db3589cbcd76f99540fed5c2641d5bb5a4a9f808e9bf0d", + "0x947f1abad982d65648ae4978e094332b4ecb90f482c9be5741d5d1cf5a28acf4680f1977bf6e49dd2174c37f11e01296", + "0xa27b144f1565e4047ba0e3f4840ef19b5095d1e281eaa463c5358f932114cbd018aa6dcf97546465cf2946d014d8e6d6", + "0x8574e1fc3acade47cd4539df578ce9205e745e161b91e59e4d088711a7ab5aa3b410d517d7304b92109924d9e2af8895", + "0xa48ee6b86b88015d6f0d282c1ae01d2a5b9e8c7aa3d0c18b35943dceb1af580d08a65f54dc6903cde82fd0d73ce94722", + "0x8875650cec543a7bf02ea4f2848a61d167a66c91ffaefe31a9e38dc8511c6a25bde431007eefe27a62af3655aca208dc", + "0x999b0a6e040372e61937bf0d68374e230346b654b5a0f591a59d33a4f95bdb2f3581db7c7ccb420cd7699ed709c50713", + "0x878c9e56c7100c5e47bbe77dc8da5c5fe706cec94d37fa729633bca63cace7c40102eee780fcdabb655f5fa47a99600e", + "0x865006fb5b475ada5e935f27b96f9425fc2d5449a3c106aa366e55ebed3b4ee42adc3c3f0ac19fd129b40bc7d6bc4f63", + "0xb7a7da847f1202e7bc1672553e68904715e84fd897d529243e3ecda59faa4e17ba99c649a802d53f6b8dfdd51f01fb74", + "0x8b2fb4432c05653303d8c8436473682933a5cb604da10c118ecfcd2c8a0e3132e125afef562bdbcc3df936164e5ce4f2", + "0x808d95762d33ddfa5d0ee3d7d9f327de21a994d681a5f372e2e3632963ea974da7f1f9e5bac8ccce24293509d1f54d27", + "0x932946532e3c397990a1df0e94c90e1e45133e347a39b6714c695be21aeb2d309504cb6b1dde7228ff6f6353f73e1ca2", + "0x9705e7c93f0cdfaa3fa96821f830fe53402ad0806036cd1b48adc2f022d8e781c1fbdab60215ce85c653203d98426da3", + "0xaa180819531c3ec1feb829d789cb2092964c069974ae4faad60e04a6afcce5c3a59aec9f11291e6d110a788d22532bc6", + "0x88f755097f7e25cb7dd3c449520c89b83ae9e119778efabb54fbd5c5714b6f37c5f9e0346c58c6ab09c1aef2483f895d", + "0x99fc03ab7810e94104c494f7e40b900f475fde65bdec853e60807ffd3f531d74de43335c3b2646b5b8c26804a7448898", + "0xaf2dea9683086bed1a179110efb227c9c00e76cd00a2015b089ccbcee46d1134aa18bda5d6cab6f82ae4c5cd2461ac21", + "0xa500f87ba9744787fdbb8e750702a3fd229de6b8817594348dec9a723b3c4240ddfa066262d002844b9e38240ce55658", + "0x924d0e45c780f5bc1c1f35d15dfc3da28036bdb59e4c5440606750ecc991b85be18bc9a240b6c983bc5430baa4c68287", + "0x865b11e0157b8bf4c5f336024b016a0162fc093069d44ac494723f56648bc4ded13dfb3896e924959ea11c96321afefc", + "0x93672d8607d4143a8f7894f1dcca83fb84906dc8d6dd7dd063bb0049cfc20c1efd933e06ca7bd03ea4cb5a5037990bfe", + "0x826891efbdff0360446825a61cd1fa04326dd90dae8c33dfb1ed97b045e165766dd070bd7105560994d0b2044bdea418", + "0x93c4a4a8bcbc8b190485cc3bc04175b7c0ed002c28c98a540919effd6ed908e540e6594f6db95cd65823017258fb3b1c", + "0xaeb2a0af2d2239fda9aa6b8234b019708e8f792834ff0dd9c487fa09d29800ddceddd6d7929faa9a3edcb9e1b3aa0d6b", + "0x87f11de7236d387863ec660d2b04db9ac08143a9a2c4dfff87727c95b4b1477e3bc473a91e5797313c58754905079643", + "0x80dc1db20067a844fe8baceca77f80db171a5ca967acb24e2d480eae9ceb91a3343c31ad1c95b721f390829084f0eae6", + "0x9825c31f1c18da0de3fa84399c8b40f8002c3cae211fb6a0623c76b097b4d39f5c50058f57a16362f7a575909d0a44a2", + "0xa99fc8de0c38dbf7b9e946de83943a6b46a762167bafe2a603fb9b86f094da30d6de7ed55d639aafc91936923ee414b3", + "0xad594678b407db5d6ea2e90528121f84f2b96a4113a252a30d359a721429857c204c1c1c4ff71d8bb5768c833f82e80e", + "0xb33d985e847b54510b9b007e31053732c8a495e43be158bd2ffcea25c6765bcbc7ca815f7c60b36ad088b955dd6e9350", + "0x815f8dfc6f90b3342ca3fbd968c67f324dae8f74245cbf8bc3bef10e9440c65d3a2151f951e8d18959ba01c1b50b0ec1", + "0x94c608a362dd732a1abc56e338637c900d59013db8668e49398b3c7a0cae3f7e2f1d1bf94c0299eeafe6af7f76c88618", + "0x8ebd8446b23e5adfcc393adc5c52fe172f030a73e63cd2d515245ca0dd02782ceed5bcdd9ccd9c1b4c5953dfac9c340c", + "0x820437f3f6f9ad0f5d7502815b221b83755eb8dc56cd92c29e9535eb0b48fb8d08c9e4fcc26945f9c8cca60d89c44710", + "0x8910e4e8a56bf4be9cc3bbf0bf6b1182a2f48837a2ed3c2aaec7099bfd7f0c83e14e608876b17893a98021ff4ab2f20d", + "0x9633918fde348573eec15ce0ad53ac7e1823aac86429710a376ad661002ae6d049ded879383faaa139435122f64047c6", + "0xa1f5e3fa558a9e89318ca87978492f0fb4f6e54a9735c1b8d2ecfb1d1c57194ded6e0dd82d077b2d54251f3bee1279e1", + "0xb208e22d04896abfd515a95c429ff318e87ff81a5d534c8ac2c33c052d6ffb73ef1dccd39c0bbe0734b596c384014766", + "0x986d5d7d2b5bde6d16336f378bd13d0e671ad23a8ec8a10b3fc09036faeeb069f60662138d7a6df3dfb8e0d36180f770", + "0xa2d4e6c5f5569e9cef1cddb569515d4b6ace38c8aed594f06da7434ba6b24477392cc67ba867c2b079545ca0c625c457", + "0xb5ac32b1d231957d91c8b7fc43115ce3c5c0d8c13ca633374402fa8000b6d9fb19499f9181844f0c10b47357f3f757ce", + "0x96b8bf2504b4d28fa34a4ec378e0e0b684890c5f44b7a6bb6e19d7b3db2ab27b1e2686389d1de9fbd981962833a313ea", + "0x953bfd7f6c3a0469ad432072b9679a25486f5f4828092401eff494cfb46656c958641a4e6d0d97d400bc59d92dba0030", + "0x876ab3cea7484bbfd0db621ec085b9ac885d94ab55c4bb671168d82b92e609754b86aaf472c55df3d81421d768fd108a", + "0x885ff4e67d9ece646d02dd425aa5a087e485c3f280c3471b77532b0db6145b69b0fbefb18aa2e3fa5b64928b43a94e57", + "0xb91931d93f806d0b0e6cc62a53c718c099526140f50f45d94b8bbb57d71e78647e06ee7b42aa5714aed9a5c05ac8533f", + "0xa0313eeadd39c720c9c27b3d671215331ab8d0a794e71e7e690f06bcd87722b531d6525060c358f35f5705dbb7109ccb", + "0x874c0944b7fedc6701e53344100612ddcb495351e29305c00ec40a7276ea5455465ffb7bded898886c1853139dfb1fc7", + "0x8dc31701a01ee8137059ca1874a015130d3024823c0576aa9243e6942ec99d377e7715ed1444cd9b750a64b85dcaa3e5", + "0x836d2a757405e922ec9a2dfdcf489a58bd48b5f9683dd46bf6047688f778c8dee9bc456de806f70464df0b25f3f3d238", + "0xb30b0a1e454a503ea3e2efdec7483eaf20b0a5c3cefc42069e891952b35d4b2c955cf615f3066285ed8fafd9fcfbb8f6", + "0x8e6d4044b55ab747e83ec8762ea86845f1785cc7be0279c075dadf08aca3ccc5a096c015bb3c3f738f647a4eadea3ba5", + "0xad7735d16ab03cbe09c029610aa625133a6daecfc990b297205b6da98eda8c136a7c50db90f426d35069708510d5ae9c", + "0x8d62d858bbb59ec3c8cc9acda002e08addab4d3ad143b3812098f3d9087a1b4a1bb255dcb1635da2402487d8d0249161", + "0x805beec33238b832e8530645a3254aeef957e8f7ea24bcfc1054f8b9c69421145ebb8f9d893237e8a001c857fedfc77e", + "0xb1005644be4b085e3f5775aa9bd3e09a283e87ddada3082c04e7a62d303dcef3b8cf8f92944c200c7ae6bb6bdf63f832", + "0xb4ba0e0790dc29063e577474ffe3b61f5ea2508169f5adc1e394934ebb473e356239413a17962bc3e5d3762d72cce8c2", + "0xa157ba9169c9e3e6748d9f1dd67fbe08b9114ade4c5d8fc475f87a764fb7e6f1d21f66d7905cd730f28a1c2d8378682a", + "0x913e52b5c93989b5d15e0d91aa0f19f78d592bc28bcfdfddc885a9980c732b1f4debb8166a7c4083c42aeda93a702898", + "0x90fbfc1567e7cd4e096a38433704d3f96a2de2f6ed3371515ccc30bc4dd0721a704487d25a97f3c3d7e4344472702d8d", + "0x89646043028ffee4b69d346907586fd12c2c0730f024acb1481abea478e61031966e72072ff1d5e65cb8c64a69ad4eb1", + "0xb125a45e86117ee11d2fb42f680ab4a7894edd67ff927ae2c808920c66c3e55f6a9d4588eee906f33a05d592e5ec3c04", + "0xaad47f5b41eae9be55fb4f67674ff1e4ae2482897676f964a4d2dcb6982252ee4ff56aac49578b23f72d1fced707525e", + "0xb9ddff8986145e33851b4de54d3e81faa3352e8385895f357734085a1616ef61c692d925fe62a5ed3be8ca49f5d66306", + "0xb3cb0963387ed28c0c0adf7fe645f02606e6e1780a24d6cecef5b7c642499109974c81a7c2a198b19862eedcea2c2d8c", + "0xac9c53c885457aaf5cb36c717a6f4077af701e0098eebd7aa600f5e4b14e6c1067255b3a0bc40e4a552025231be7de60", + "0x8e1a8d823c4603f6648ec21d064101094f2a762a4ed37dd2f0a2d9aa97b2d850ce1e76f4a4b8cae58819b058180f7031", + "0xb268b73bf7a179b6d22bd37e5e8cb514e9f5f8968c78e14e4f6d5700ca0d0ca5081d0344bb73b028970eebde3cb4124e", + "0xa7f57d71940f0edbd29ed8473d0149cae71d921dd15d1ff589774003e816b54b24de2620871108cec1ab9fa956ad6ce6", + "0x8053e6416c8b120e2b999cc2fc420a6a55094c61ac7f2a6c6f0a2c108a320890e389af96cbe378936132363c0d551277", + "0xb3823f4511125e5aa0f4269e991b435a0d6ceb523ebd91c04d7add5534e3df5fc951c504b4fd412a309fd3726b7f940b", + "0xae6eb04674d04e982ca9a6add30370ab90e303c71486f43ed3efbe431af1b0e43e9d06c11c3412651f304c473e7dbf39", + "0x96ab55e641ed2e677591f7379a3cd126449614181fce403e93e89b1645d82c4af524381ff986cae7f9cebe676878646d", + "0xb52423b4a8c37d3c3e2eca8f0ddbf7abe0938855f33a0af50f117fab26415fb0a3da5405908ec5fdc22a2c1f2ca64892", + "0x82a69ce1ee92a09cc709d0e3cd22116c9f69d28ea507fe5901f5676000b5179b9abe4c1875d052b0dd42d39925e186bb", + "0xa84c8cb84b9d5cfb69a5414f0a5283a5f2e90739e9362a1e8c784b96381b59ac6c18723a4aa45988ee8ef5c1f45cc97d", + "0xafd7efce6b36813082eb98257aae22a4c1ae97d51cac7ea9c852d4a66d05ef2732116137d8432e3f117119725a817d24", + "0xa0f5fe25af3ce021b706fcff05f3d825384a272284d04735574ce5fb256bf27100fad0b1f1ba0e54ae9dcbb9570ecad3", + "0x8751786cb80e2e1ff819fc7fa31c2833d25086534eb12b373d31f826382430acfd87023d2a688c65b5e983927e146336", + "0x8cf5c4b17fa4f3d35c78ce41e1dc86988fd1135cd5e6b2bb0c108ee13538d0d09ae7102609c6070f39f937b439b31e33", + "0xa9108967a2fedd7c322711eca8159c533dd561bedcb181b646de98bf5c3079449478eab579731bee8d215ae8852c7e21", + "0xb54c5171704f42a6f0f4e70767cdb3d96ffc4888c842eece343a01557da405961d53ffdc34d2f902ea25d3e1ed867cad", + "0xae8d4b764a7a25330ba205bf77e9f46182cd60f94a336bbd96773cf8064e3d39caf04c310680943dc89ed1fbad2c6e0d", + "0xaa5150e911a8e1346868e1b71c5a01e2a4bb8632c195861fb6c3038a0e9b85f0e09b3822e9283654a4d7bb17db2fc5f4", + "0x9685d3756ce9069bf8bb716cf7d5063ebfafe37e15b137fc8c3159633c4e006ff4887ddd0ae90360767a25c3f90cba7f", + "0x82155fd70f107ab3c8e414eadf226c797e07b65911508c76c554445422325e71af8c9a8e77fd52d94412a6fc29417cd3", + "0xabfae52f53a4b6e00760468d973a267f29321997c3dbb5aee36dc1f20619551229c0c45b9d9749f410e7f531b73378e8", + "0x81a76d921f8ef88e774fd985e786a4a330d779b93fad7def718c014685ca0247379e2e2a007ad63ee7f729cd9ed6ce1b", + "0x81947c84bc5e28e26e2e533af5ae8fe10407a7b77436dbf8f1d5b0bbe86fc659eae10f974659dc7c826c6dabd03e3a4b", + "0x92b8c07050d635b8dd4fd09df9054efe4edae6b86a63c292e73cc819a12a21dd7d104ce51fa56af6539dedf6dbe6f7b6", + "0xb44c579e3881f32b32d20c82c207307eca08e44995dd2aac3b2692d2c8eb2a325626c80ac81c26eeb38c4137ff95add5", + "0x97efab8941c90c30860926dea69a841f2dcd02980bf5413b9fd78d85904588bf0c1021798dbc16c8bbb32cce66c82621", + "0x913363012528b50698e904de0588bf55c8ec5cf6f0367cfd42095c4468fcc64954fbf784508073e542fee242d0743867", + "0x8ed203cf215148296454012bd10fddaf119203db1919a7b3d2cdc9f80e66729464fdfae42f1f2fc5af1ed53a42b40024", + "0xab84312db7b87d711e9a60824f4fe50e7a6190bf92e1628688dfcb38930fe87b2d53f9e14dd4de509b2216856d8d9188", + "0x880726def069c160278b12d2258eac8fa63f729cd351a710d28b7e601c6712903c3ac1e7bbd0d21e4a15f13ca49db5aa", + "0x980699cd51bac6283959765f5174e543ed1e5f5584b5127980cbc2ef18d984ecabba45042c6773b447b8e694db066028", + "0xaeb019cb80dc4cb4207430d0f2cd24c9888998b6f21d9bf286cc638449668d2eec0018a4cf3fe6448673cd6729335e2b", + "0xb29852f6aa6c60effdffe96ae88590c88abae732561d35cc19e82d3a51e26cb35ea00986193e07f90060756240f5346e", + "0xa0fa855adc5ba469f35800c48414b8921455950a5c0a49945d1ef6e8f2a1881f2e2dfae47de6417270a6bf49deeb091d", + "0xb6c7332e3b14813641e7272d4f69ecc7e09081df0037d6dab97ce13a9e58510f5c930d300633f208181d9205c5534001", + "0x85a6c050f42fce560b5a8d54a11c3bbb8407abbadd859647a7b0c21c4b579ec65671098b74f10a16245dc779dff7838e", + "0x8f3eb34bb68759d53c6677de4de78a6c24dd32c8962a7fb355ed362572ef8253733e6b52bc21c9f92ecd875020a9b8de", + "0xa17dd44181e5dab4dbc128e1af93ec22624b57a448ca65d2d9e246797e4af7d079e09c6e0dfb62db3a9957ce92f098d5", + "0xa56a1b854c3183082543a8685bb34cae1289f86cfa8123a579049dbd059e77982886bfeb61bf6e05b4b1fe4e620932e7", + "0xaedae3033cb2fb7628cb4803435bdd7757370a86f808ae4cecb9a268ad0e875f308c048c80cbcac523de16b609683887", + "0x9344905376aa3982b1179497fac5a1d74b14b7038fd15e3b002db4c11c8bfc7c39430db492cdaf58b9c47996c9901f28", + "0xa3bfafdae011a19f030c749c3b071f83580dee97dd6f949e790366f95618ca9f828f1daaeabad6dcd664fcef81b6556d", + "0x81c03d8429129e7e04434dee2c529194ddb01b414feda3adee2271eb680f6c85ec872a55c9fa9d2096f517e13ed5abcc", + "0x98205ef3a72dff54c5a9c82d293c3e45d908946fa74bb749c3aabe1ab994ea93c269bcce1a266d2fe67a8f02133c5985", + "0x85a70aeed09fda24412fadbafbbbf5ba1e00ac92885df329e147bfafa97b57629a3582115b780d8549d07d19b7867715", + "0xb0fbe81c719f89a57d9ea3397705f898175808c5f75f8eb81c2193a0b555869ba7bd2e6bc54ee8a60cea11735e21c68c", + "0xb03a0bd160495ee626ff3a5c7d95bc79d7da7e5a96f6d10116600c8fa20bedd1132f5170f25a22371a34a2d763f2d6d0", + "0xa90ab04091fbca9f433b885e6c1d60ab45f6f1daf4b35ec22b09909d493a6aab65ce41a6f30c98239cbca27022f61a8b", + "0xb66f92aa3bf2549f9b60b86f99a0bd19cbdd97036d4ae71ca4b83d669607f275260a497208f6476cde1931d9712c2402", + "0xb08e1fdf20e6a9b0b4942f14fa339551c3175c1ffc5d0ab5b226b6e6a322e9eb0ba96adc5c8d59ca4259e2bdd04a7eb0", + "0xa2812231e92c1ce74d4f5ac3ab6698520288db6a38398bb38a914ac9326519580af17ae3e27cde26607e698294022c81", + "0xabfcbbcf1d3b9e84c02499003e490a1d5d9a2841a9e50c7babbef0b2dd20d7483371d4dc629ba07faf46db659459d296", + "0xb0fe9f98c3da70927c23f2975a9dc4789194d81932d2ad0f3b00843dd9cbd7fb60747a1da8fe5a79f136a601becf279d", + "0xb130a6dba7645165348cb90f023713bed0eefbd90a976b313521c60a36d34f02032e69a2bdcf5361e343ed46911297ec", + "0x862f0cffe3020cea7a5fd4703353aa1eb1be335e3b712b29d079ff9f7090d1d8b12013011e1bdcbaa80c44641fd37c9f", + "0x8c6f11123b26633e1abb9ed857e0bce845b2b3df91cc7b013b2fc77b477eee445da0285fc6fc793e29d5912977f40916", + "0x91381846126ea819d40f84d3005e9fb233dc80071d1f9bb07f102bf015f813f61e5884ffffb4f5cd333c1b1e38a05a58", + "0x8add7d908de6e1775adbd39c29a391f06692b936518db1f8fde74eb4f533fc510673a59afb86e3a9b52ade96e3004c57", + "0x8780e086a244a092206edcde625cafb87c9ab1f89cc3e0d378bc9ee776313836160960a82ec397bc3800c0a0ec3da283", + "0xa6cb4cd9481e22870fdd757fae0785edf4635e7aacb18072fe8dc5876d0bab53fb99ce40964a7d3e8bcfff6f0ab1332f", + "0xaf30ff47ecc5b543efba1ba4706921066ca8bb625f40e530fb668aea0551c7647a9d126e8aba282fbcce168c3e7e0130", + "0x91b0bcf408ce3c11555dcb80c4410b5bc2386d3c05caec0b653352377efdcb6bab4827f2018671fc8e4a0e90d772acc1", + "0xa9430b975ef138b6b2944c7baded8fe102d31da4cfe3bd3d8778bda79189c99d38176a19c848a19e2d1ee0bddd9a13c1", + "0xaa5a4eef849d7c9d2f4b018bd01271c1dd83f771de860c4261f385d3bdcc130218495860a1de298f14b703ec32fa235f", + "0xb0ce79e7f9ae57abe4ff366146c3b9bfb38b0dee09c28c28f5981a5d234c6810ad4d582751948affb480d6ae1c8c31c4", + "0xb75122748560f73d15c01a8907d36d06dc068e82ce22b84b322ac1f727034493572f7907dec34ebc3ddcc976f2f89ed7", + "0xb0fc7836369a3e4411d34792d6bd5617c14f61d9bba023dda64e89dc5fb0f423244e9b48ee64869258931daa9753a56f", + "0x8956d7455ae9009d70c6e4a0bcd7610e55f37494cf9897a8f9e1b904cc8febc3fd2d642ebd09025cfff4609ad7e3bc52", + "0xad741efe9e472026aa49ae3d9914cb9c1a6f37a54f1a6fe6419bebd8c7d68dca105a751c7859f4389505ede40a0de786", + "0xb52f418797d719f0d0d0ffb0846788b5cba5d0454a69a2925de4b0b80fa4dd7e8c445e5eac40afd92897ed28ca650566", + "0xa0ab65fb9d42dd966cd93b1de01d7c822694669dd2b7a0c04d99cd0f3c3de795f387b9c92da11353412f33af5c950e9a", + "0xa0052f44a31e5741a331f7cac515a08b3325666d388880162d9a7b97598fde8b61f9ff35ff220df224eb5c4e40ef0567", + "0xa0101cfdc94e42b2b976c0d89612a720e55d145a5ef6ef6f1f78cf6de084a49973d9b5d45915349c34ce712512191e3c", + "0xa0dd99fcf3f5cead5aaf08e82212df3a8bb543c407a4d6fab88dc5130c1769df3f147e934a46f291d6c1a55d92b86917", + "0xa5939153f0d1931bbda5cf6bdf20562519ea55fbfa978d6dbc6828d298260c0da7a50c37c34f386e59431301a96c2232", + "0x9568269f3f5257200f9ca44afe1174a5d3cf92950a7f553e50e279c239e156a9faaa2a67f288e3d5100b4142efe64856", + "0xb746b0832866c23288e07f24991bbf687cad794e7b794d3d3b79367566ca617d38af586cdc8d6f4a85a34835be41d54f", + "0xa871ce28e39ab467706e32fec1669fda5a4abba2f8c209c6745df9f7a0fa36bbf1919cf14cb89ea26fa214c4c907ae03", + "0xa08dacdd758e523cb8484f6bd070642c0c20e184abdf8e2a601f61507e93952d5b8b0c723c34fcbdd70a8485eec29db2", + "0x85bdb78d501382bb95f1166b8d032941005661aefd17a5ac32df9a3a18e9df2fc5dc2c1f07075f9641af10353cecc0c9", + "0x98d730c28f6fa692a389e97e368b58f4d95382fad8f0baa58e71a3d7baaea1988ead47b13742ce587456f083636fa98e", + "0xa557198c6f3d5382be9fb363feb02e2e243b0c3c61337b3f1801c4a0943f18e38ce1a1c36b5c289c8fa2aa9d58742bab", + "0x89174f79201742220ac689c403fc7b243eed4f8e3f2f8aba0bf183e6f5d4907cb55ade3e238e3623d9885f03155c4d2b", + "0xb891d600132a86709e06f3381158db300975f73ea4c1f7c100358e14e98c5fbe792a9af666b85c4e402707c3f2db321e", + "0xb9e5b2529ef1043278c939373fc0dbafe446def52ddd0a8edecd3e4b736de87e63e187df853c54c28d865de18a358bb6", + "0x8589b2e9770340c64679062c5badb7bbef68f55476289b19511a158a9a721f197da03ece3309e059fc4468b15ac33aa3", + "0xaad8c6cd01d785a881b446f06f1e9cd71bca74ba98674c2dcddc8af01c40aa7a6d469037498b5602e76e9c91a58d3dbd", + "0xabaccb1bd918a8465f1bf8dbe2c9ad4775c620b055550b949a399f30cf0d9eb909f3851f5b55e38f9e461e762f88f499", + "0xae62339d26db46e85f157c0151bd29916d5cc619bd4b832814b3fd2f00af8f38e7f0f09932ffe5bba692005dab2d9a74", + "0x93a6ff30a5c0edf8058c89aba8c3259e0f1b1be1b80e67682de651e5346f7e1b4b4ac3d87cbaebf198cf779524aff6bf", + "0x8980a2b1d8f574af45b459193c952400b10a86122b71fca2acb75ee0dbd492e7e1ef5b959baf609a5172115e371f3177", + "0x8c2f49f3666faee6940c75e8c7f6f8edc3f704cca7a858bbb7ee5e96bba3b0cf0993996f781ba6be3b0821ef4cb75039", + "0xb14b9e348215b278696018330f63c38db100b0542cfc5be11dc33046e3bca6a13034c4ae40d9cef9ea8b34fef0910c4e", + "0xb59bc3d0a30d66c16e6a411cb641f348cb1135186d5f69fda8b0a0934a5a2e7f6199095ba319ec87d3fe8f1ec4a06368", + "0x8874aca2a3767aa198e4c3fec2d9c62d496bc41ff71ce242e9e082b7f38cdf356089295f80a301a3cf1182bde5308c97", + "0xb1820ebd61376d91232423fc20bf008b2ba37e761199f4ef0648ea2bd70282766799b4de814846d2f4d516d525c8daa7", + "0xa6b202e5dedc16a4073e04a11af3a8509b23dfe5a1952f899adeb240e75c3f5bde0c424f811a81ea48d343591faffe46", + "0xa69becee9c93734805523b92150a59a62eed4934f66056b645728740d42223f2925a1ad38359ba644da24d9414f4cdda", + "0xad72f0f1305e37c7e6b48c272323ee883320994cb2e0d850905d6655fafc9f361389bcb9c66b3ff8d2051dbb58c8aa96", + "0xb563600bd56fad7c8853af21c6a02a16ed9d8a8bbeea2c31731d63b976d83cb05b9779372d898233e8fd597a75424797", + "0xb0abb78ce465bf7051f563c62e8be9c57a2cc997f47c82819300f36e301fefd908894bb2053a9d27ce2d0f8c46d88b5b", + "0xa071a85fb8274bac2202e0cb8e0e2028a5e138a82d6e0374d39ca1884a549c7c401312f00071b91f455c3a2afcfe0cda", + "0xb931c271513a0f267b9f41444a5650b1918100b8f1a64959c552aff4e2193cc1b9927906c6fa7b8a8c68ef13d79aaa52", + "0xa6a1bb9c7d32cb0ca44d8b75af7e40479fbce67d216b48a2bb680d3f3a772003a49d3cd675fc64e9e0f8fabeb86d6d61", + "0xb98d609858671543e1c3b8564162ad828808bb50ded261a9f8690ded5b665ed8368c58f947365ed6e84e5a12e27b423d", + "0xb3dca58cd69ec855e2701a1d66cad86717ff103ef862c490399c771ad28f675680f9500cb97be48de34bcdc1e4503ffd", + "0xb34867c6735d3c49865e246ddf6c3b33baf8e6f164db3406a64ebce4768cb46b0309635e11be985fee09ab7a31d81402", + "0xacb966c554188c5b266624208f31fab250b3aa197adbdd14aee5ab27d7fb886eb4350985c553b20fdf66d5d332bfd3fe", + "0x943c36a18223d6c870d54c3b051ef08d802b85e9dd6de37a51c932f90191890656c06adfa883c87b906557ae32d09da0", + "0x81bca7954d0b9b6c3d4528aadf83e4bc2ef9ea143d6209bc45ae9e7ae9787dbcd8333c41f12c0b6deee8dcb6805e826a", + "0xaba176b92256efb68f574e543479e5cf0376889fb48e3db4ebfb7cba91e4d9bcf19dcfec444c6622d9398f06de29e2b9", + "0xb9f743691448053216f6ece7cd699871fff4217a1409ceb8ab7bdf3312d11696d62c74b0664ba0a631b1e0237a8a0361", + "0xa383c2b6276fa9af346b21609326b53fb14fdf6f61676683076e80f375b603645f2051985706d0401e6fbed7eb0666b6", + "0xa9ef2f63ec6d9beb8f3d04e36807d84bda87bdd6b351a3e4a9bf7edcb5618c46c1f58cfbf89e64b40f550915c6988447", + "0xa141b2d7a82f5005eaea7ae7d112c6788b9b95121e5b70b7168d971812f3381de8b0082ac1f0a82c7d365922ebd2d26a", + "0xb1b76ef8120e66e1535c17038b75255a07849935d3128e3e99e56567b842fb1e8d56ef932d508d2fb18b82f7868fe1a9", + "0x8e2e234684c81f21099f5c54f6bbe2dd01e3b172623836c77668a0c49ce1fe218786c3827e4d9ae2ea25c50a8924fb3c", + "0xa5caf5ff948bfd3c4ca3ffbdfcd91eec83214a6c6017235f309a0bbf7061d3b0b466307c00b44a1009cf575163898b43", + "0x986415a82ca16ebb107b4c50b0c023c28714281db0bcdab589f6cb13d80e473a3034b7081b3c358e725833f6d845cb14", + "0xb94836bf406ac2cbacb10e6df5bcdfcc9d9124ae1062767ca4e322d287fd5e353fdcebd0e52407cb3cd68571258a8900", + "0x83c6d70a640b33087454a4788dfd9ef3ed00272da084a8d36be817296f71c086b23b576f98178ab8ca6a74f04524b46b", + "0xad4115182ad784cfe11bcfc5ce21fd56229cc2ce77ac82746e91a2f0aa53ca6593a22efd2dc4ed8d00f84542643d9c58", + "0xab1434c5e5065da826d10c2a2dba0facccab0e52b506ce0ce42fbe47ced5a741797151d9ecc99dc7d6373cfa1779bbf6", + "0x8a8b591d82358d55e6938f67ea87a89097ab5f5496f7260adb9f649abb289da12b498c5b2539c2f9614fb4e21b1f66b0", + "0x964f355d603264bc1f44c64d6d64debca66f37dff39c971d9fc924f2bc68e6c187b48564a6dc82660a98b035f8addb5d", + "0xb66235eaaf47456bc1dc4bde454a028e2ce494ece6b713a94cd6bf27cf18c717fd0c57a5681caaa2ad73a473593cdd7a", + "0x9103e3bb74304186fa4e3e355a02da77da4aca9b7e702982fc2082af67127ebb23a455098313c88465bc9b7d26820dd5", + "0xb6a42ff407c9dd132670cdb83cbad4b20871716e44133b59a932cd1c3f97c7ac8ff7f61acfaf8628372508d8dc8cad7c", + "0x883a9c21c16a167a4171b0f084565c13b6f28ba7c4977a0de69f0a25911f64099e7bbb4da8858f2e93068f4155d04e18", + "0x8dbb3220abc6a43220adf0331e3903d3bfd1d5213aadfbd8dfcdf4b2864ce2e96a71f35ecfb7a07c3bbabf0372b50271", + "0xb4ad08aee48e176bda390b7d9acf2f8d5eb008f30d20994707b757dc6a3974b2902d29cd9b4d85e032810ad25ac49e97", + "0x865bb0f33f7636ec501bb634e5b65751c8a230ae1fa807a961a8289bbf9c7fe8c59e01fbc4c04f8d59b7f539cf79ddd5", + "0x86a54d4c12ad1e3605b9f93d4a37082fd26e888d2329847d89afa7802e815f33f38185c5b7292293d788ad7d7da1df97", + "0xb26c8615c5e47691c9ff3deca3021714662d236c4d8401c5d27b50152ce7e566266b9d512d14eb63e65bc1d38a16f914", + "0x827639d5ce7db43ba40152c8a0eaad443af21dc92636cc8cc2b35f10647da7d475a1e408901cd220552fddad79db74df", + "0xa2b79a582191a85dbe22dc384c9ca3de345e69f6aa370aa6d3ff1e1c3de513e30b72df9555b15a46586bd27ea2854d9d", + "0xae0d74644aba9a49521d3e9553813bcb9e18f0b43515e4c74366e503c52f47236be92dfbd99c7285b3248c267b1de5a0", + "0x80fb0c116e0fd6822a04b9c25f456bdca704e2be7bdc5d141dbf5d1c5eeb0a2c4f5d80db583b03ef3e47517e4f9a1b10", + "0xac3a1fa3b4a2f30ea7e0a114cdc479eb51773573804c2a158d603ad9902ae8e39ffe95df09c0d871725a5d7f9ba71a57", + "0xb56b2b0d601cba7f817fa76102c68c2e518c6f20ff693aad3ff2e07d6c4c76203753f7f91686b1801e8c4659e4d45c48", + "0x89d50c1fc56e656fb9d3915964ebce703cb723fe411ab3c9eaa88ccc5d2b155a9b2e515363d9c600d3c0cee782c43f41", + "0xb24207e61462f6230f3cd8ccf6828357d03e725769f7d1de35099ef9ee4dca57dbce699bb49ed994462bee17059d25ce", + "0xb886f17fcbcbfcd08ac07f04bb9543ef58510189decaccea4b4158c9174a067cb67d14b6be3c934e6e2a18c77efa9c9c", + "0xb9c050ad9cafd41c6e2e192b70d080076eed59ed38ea19a12bd92fa17b5d8947d58d5546aaf5e8e27e1d3b5481a6ce51", + "0xaaf7a34d3267e3b1ddbc54c641e3922e89303f7c86ebebc7347ebca4cffad5b76117dac0cbae1a133053492799cd936f", + "0xa9ee604ada50adef82e29e893070649d2d4b7136cc24fa20e281ce1a07bd736bf0de7c420369676bcbcecff26fb6e900", + "0x9855315a12a4b4cf80ab90b8bd13003223ba25206e52fd4fe6a409232fbed938f30120a3db23eab9c53f308bd8b9db81", + "0x8cd488dd7a24f548a3cf03c54dec7ff61d0685cb0f6e5c46c2d728e3500d8c7bd6bba0156f4bf600466fda53e5b20444", + "0x890ad4942ebac8f5b16c777701ab80c68f56fa542002b0786f8fea0fb073154369920ac3dbfc07ea598b82f4985b8ced", + "0x8de0cf9ddc84c9b92c59b9b044387597799246b30b9f4d7626fc12c51f6e423e08ee4cbfe9289984983c1f9521c3e19d", + "0xb474dfb5b5f4231d7775b3c3a8744956b3f0c7a871d835d7e4fd9cc895222c7b868d6c6ce250de568a65851151fac860", + "0x86433b6135d9ed9b5ee8cb7a6c40e5c9d30a68774cec04988117302b8a02a11a71a1e03fd8e0264ef6611d219f103007", + "0x80b9ed4adbe9538fb1ef69dd44ec0ec5b57cbfea820054d8d445b4261962624b4c70ac330480594bc5168184378379c3", + "0x8b2e83562ccd23b7ad2d17f55b1ab7ef5fbef64b3a284e6725b800f3222b8bdf49937f4a873917ada9c4ddfb090938c2", + "0xabe78cebc0f5a45d754140d1f685e387489acbfa46d297a8592aaa0d676a470654f417a4f7d666fc0b2508fab37d908e", + "0xa9c5f8ff1f8568e252b06d10e1558326db9901840e6b3c26bbd0cd5e850cb5fb3af3f117dbb0f282740276f6fd84126f", + "0x975f8dc4fb55032a5df3b42b96c8c0ffecb75456f01d4aef66f973cb7270d4eff32c71520ceefc1adcf38d77b6b80c67", + "0xb043306ed2c3d8a5b9a056565afd8b5e354c8c4569fda66b0d797a50a3ce2c08cffbae9bbe292da69f39e89d5dc7911e", + "0x8d2afc36b1e44386ba350c14a6c1bb31ff6ea77128a0c5287584ac3584282d18516901ce402b4644a53db1ed8e7fa581", + "0x8c294058bed53d7290325c363fe243f6ec4f4ea2343692f4bac8f0cb86f115c069ccb8334b53d2e42c067691ad110dba", + "0xb92157b926751aaf7ef82c1aa8c654907dccab6376187ee8b3e8c0c82811eae01242832de953faa13ebaff7da8698b3e", + "0xa780c4bdd9e4ba57254b09d745075cecab87feda78c88ffee489625c5a3cf96aa6b3c9503a374a37927d9b78de9bd22b", + "0x811f548ef3a2e6a654f7dcb28ac9378de9515ed61e5a428515d9594a83e80b35c60f96a5cf743e6fab0d3cb526149f49", + "0x85a4dccf6d90ee8e094731eec53bd00b3887aec6bd81a0740efddf812fd35e3e4fe4f983afb49a8588691c202dabf942", + "0xb152c2da6f2e01c8913079ae2b40a09b1f361a80f5408a0237a8131b429677c3157295e11b365b1b1841924b9efb922e", + "0x849b9efee8742502ffd981c4517c88ed33e4dd518a330802caff168abae3cd09956a5ee5eda15900243bc2e829016b74", + "0x955a933f3c18ec0f1c0e38fa931e4427a5372c46a3906ebe95082bcf878c35246523c23f0266644ace1fa590ffa6d119", + "0x911989e9f43e580c886656377c6f856cdd4ff1bd001b6db3bbd86e590a821d34a5c6688a29b8d90f28680e9fdf03ba69", + "0xb73b8b4f1fd6049fb68d47cd96a18fcba3f716e0a1061aa5a2596302795354e0c39dea04d91d232aec86b0bf2ba10522", + "0x90f87456d9156e6a1f029a833bf3c7dbed98ca2f2f147a8564922c25ae197a55f7ea9b2ee1f81bf7383197c4bad2e20c", + "0x903cba8b1e088574cb04a05ca1899ab00d8960580c884bd3c8a4c98d680c2ad11410f2b75739d6050f91d7208cac33a5", + "0x9329987d42529c261bd15ecedd360be0ea8966e7838f32896522c965adfc4febf187db392bd441fb43bbd10c38fdf68b", + "0x8178ee93acf5353baa349285067b20e9bb41aa32d77b5aeb7384fe5220c1fe64a2461bd7a83142694fe673e8bbf61b7c", + "0xa06a8e53abcff271b1394bcc647440f81fb1c1a5f29c27a226e08f961c3353f4891620f2d59b9d1902bf2f5cc07a4553", + "0xaaf5fe493b337810889e777980e6bbea6cac39ac66bc0875c680c4208807ac866e9fda9b5952aa1d04539b9f4a4bec57", + "0xaa058abb1953eceac14ccfa7c0cc482a146e1232905dcecc86dd27f75575285f06bbae16a8c9fe8e35d8713717f5f19f", + "0x8f15dd732799c879ca46d2763453b359ff483ca33adb1d0e0a57262352e0476c235987dc3a8a243c74bc768f93d3014c", + "0xa61cc8263e9bc03cce985f1663b8a72928a607121005a301b28a278e9654727fd1b22bc8a949af73929c56d9d3d4a273", + "0x98d6dc78502d19eb9f921225475a6ebcc7b44f01a2df6f55ccf6908d65b27af1891be2a37735f0315b6e0f1576c1f8d8", + "0x8bd258b883f3b3793ec5be9472ad1ff3dc4b51bc5a58e9f944acfb927349ead8231a523cc2175c1f98e7e1e2b9f363b8", + "0xaeacc2ecb6e807ad09bedd99654b097a6f39840e932873ace02eabd64ccfbb475abdcb62939a698abf17572d2034c51e", + "0xb8ccf78c08ccd8df59fd6eda2e01de328bc6d8a65824d6f1fc0537654e9bc6bf6f89c422dd3a295cce628749da85c864", + "0x8f91fd8cb253ba2e71cc6f13da5e05f62c2c3b485c24f5d68397d04665673167fce1fc1aec6085c69e87e66ec555d3fd", + "0xa254baa10cb26d04136886073bb4c159af8a8532e3fd36b1e9c3a2e41b5b2b6a86c4ebc14dbe624ee07b7ccdaf59f9ab", + "0x94e3286fe5cd68c4c7b9a7d33ae3d714a7f265cf77cd0e9bc19fc51015b1d1c34ad7e3a5221c459e89f5a043ee84e3a9", + "0xa279da8878af8d449a9539bec4b17cea94f0242911f66fab275b5143ab040825f78c89cb32a793930609415cfa3a1078", + "0xac846ceb89c9e5d43a2991c8443079dc32298cd63e370e64149cec98cf48a6351c09c856f2632fd2f2b3d685a18bbf8b", + "0xa847b27995c8a2e2454aaeb983879fb5d3a23105c33175839f7300b7e1e8ec3efd6450e9fa3f10323609dee7b98c6fd5", + "0xa2f432d147d904d185ff4b2de8c6b82fbea278a2956bc406855b44c18041854c4f0ecccd472d1d0dff1d8aa8e281cb1d", + "0x94a48ad40326f95bd63dff4755f863a1b79e1df771a1173b17937f9baba57b39e651e7695be9f66a472f098b339364fc", + "0xa12a0ccd8f96e96e1bc6494341f7ebce959899341b3a084aa1aa87d1c0d489ac908552b7770b887bb47e7b8cbc3d8e66", + "0x81a1f1681bda923bd274bfe0fbb9181d6d164fe738e54e25e8d4849193d311e2c4253614ed673c98af2c798f19a93468", + "0xabf71106a05d501e84cc54610d349d7d5eae21a70bd0250f1bebbf412a130414d1c8dbe673ffdb80208fd72f1defa4d4", + "0x96266dc2e0df18d8136d79f5b59e489978eee0e6b04926687fe389d4293c14f36f055c550657a8e27be4118b64254901", + "0x8df5dcbefbfb4810ae3a413ca6b4bf08619ca53cd50eb1dde2a1c035efffc7b7ac7dff18d403253fd80104bd83dc029e", + "0x9610b87ff02e391a43324a7122736876d5b3af2a137d749c52f75d07b17f19900b151b7f439d564f4529e77aa057ad12", + "0xa90a5572198b40fe2fcf47c422274ff36c9624df7db7a89c0eb47eb48a73a03c985f4ac5016161c76ca317f64339bce1", + "0x98e5e61a6ab6462ba692124dba7794b6c6bde4249ab4fcc98c9edd631592d5bc2fb5e38466691a0970a38e48d87c2e43", + "0x918cefb8f292f78d4db81462c633daf73b395e772f47b3a7d2cea598025b1d8c3ec0cbff46cdb23597e74929981cde40", + "0xa98918a5dc7cf610fe55f725e4fd24ce581d594cb957bb9b4e888672e9c0137003e1041f83e3f1d7b9caab06462c87d4", + "0xb92b74ac015262ca66c33f2d950221e19d940ba3bf4cf17845f961dc1729ae227aa9e1f2017829f2135b489064565c29", + "0xa053ee339f359665feb178b4e7ee30a85df37debd17cacc5a27d6b3369d170b0114e67ad1712ed26d828f1df641bcd99", + "0x8c3c8bad510b35da5ce5bd84b35c958797fbea024ad1c97091d2ff71d9b962e9222f65a9b776e5b3cc29c36e1063d2ee", + "0xaf99dc7330fe7c37e850283eb47cc3257888e7c197cb0d102edf94439e1e02267b6a56306d246c326c4c79f9dc8c6986", + "0xafecb2dc34d57a725efbd7eb93d61eb29dbe8409b668ab9ea040791f5b796d9be6d4fc10d7f627bf693452f330cf0435", + "0x93334fedf19a3727a81a6b6f2459db859186227b96fe7a391263f69f1a0884e4235de64d29edebc7b99c44d19e7c7d7a", + "0x89579c51ac405ad7e9df13c904061670ce4b38372492764170e4d3d667ed52e5d15c7cd5c5991bbfa3a5e4e3fa16363e", + "0x9778f3e8639030f7ef1c344014f124e375acb8045bd13d8e97a92c5265c52de9d1ffebaa5bc3e1ad2719da0083222991", + "0x88f77f34ee92b3d36791bdf3326532524a67d544297dcf1a47ff00b47c1b8219ff11e34034eab7d23b507caa2fd3c6b9", + "0xa699c1e654e7c484431d81d90657892efeb4adcf72c43618e71ca7bd7c7a7ebbb1db7e06e75b75dc4c74efd306b5df3f", + "0x81d13153baebb2ef672b5bdb069d3cd669ce0be96b742c94e04038f689ff92a61376341366b286eee6bf3ae85156f694", + "0x81efb17de94400fdacc1deec2550cbe3eecb27c7af99d8207e2f9be397e26be24a40446d2a09536bb5172c28959318d9", + "0x989b21ebe9ceab02488992673dc071d4d5edec24bff0e17a4306c8cb4b3c83df53a2063d1827edd8ed16d6e837f0d222", + "0x8d6005d6536825661b13c5fdce177cb37c04e8b109b7eb2b6d82ea1cb70efecf6a0022b64f84d753d165edc2bba784a3", + "0xa32607360a71d5e34af2271211652d73d7756d393161f4cf0da000c2d66a84c6826e09e759bd787d4fd0305e2439d342", + "0xaaad8d6f6e260db45d51b2da723be6fa832e76f5fbcb77a9a31e7f090dd38446d3b631b96230d78208cae408c288ac4e", + "0xabcfe425255fd3c5cffd3a818af7650190c957b6b07b632443f9e33e970a8a4c3bf79ac9b71f4d45f238a04d1c049857", + "0xaeabf026d4c783adc4414b5923dbd0be4b039cc7201219f7260d321f55e9a5b166d7b5875af6129c034d0108fdc5d666", + "0xaf49e740c752d7b6f17048014851f437ffd17413c59797e5078eaaa36f73f0017c3e7da020310cfe7d3c85f94a99f203", + "0x8854ca600d842566e3090040cd66bb0b3c46dae6962a13946f0024c4a8aca447e2ccf6f240045f1ceee799a88cb9210c", + "0xb6c03b93b1ab1b88ded8edfa1b487a1ed8bdce8535244dddb558ffb78f89b1c74058f80f4db2320ad060d0c2a9c351cc", + "0xb5bd7d17372faff4898a7517009b61a7c8f6f0e7ed4192c555db264618e3f6e57fb30a472d169fea01bf2bf0362a19a8", + "0x96eb1d38319dc74afe7e7eb076fcd230d19983f645abd14a71e6103545c01301b31c47ae931e025f3ecc01fb3d2f31fa", + "0xb55a8d30d4403067def9b65e16f867299f8f64c9b391d0846d4780bc196569622e7e5b64ce799b5aefac8f965b2a7a7b", + "0x8356d199a991e5cbbff608752b6291731b6b6771aed292f8948b1f41c6543e4ab1bedc82dd26d10206c907c03508df06", + "0x97f4137445c2d98b0d1d478049de952610ad698c91c9d0f0e7227d2aae690e9935e914ec4a2ea1fbf3fc1dddfeeacebb", + "0xaf5621707e0938320b15ddfc87584ab325fbdfd85c30efea36f8f9bd0707d7ec12c344eff3ec21761189518d192df035", + "0x8ac7817e71ea0825b292687928e349da7140285d035e1e1abff0c3704fa8453faaae343a441b7143a74ec56539687cc4", + "0x8a5e0a9e4758449489df10f3386029ada828d1762e4fb0a8ffe6b79e5b6d5d713cb64ed95960e126398b0cdb89002bc9", + "0x81324be4a71208bbb9bca74b77177f8f1abb9d3d5d9db195d1854651f2cf333cd618d35400da0f060f3e1b025124e4b2", + "0x849971d9d095ae067525b3cbc4a7dfae81f739537ade6d6cec1b42fb692d923176197a8770907c58069754b8882822d6", + "0x89f830825416802477cc81fdf11084885865ee6607aa15aa4eb28e351c569c49b8a1b9b5e95ddc04fa0ebafe20071313", + "0x9240aeeaff37a91af55f860b9badd466e8243af9e8c96a7aa8cf348cd270685ab6301bc135b246dca9eda696f8b0e350", + "0xacf74db78cc33138273127599eba35b0fb4e7b9a69fe02dae18fc6692d748ca332bd00b22afa8e654ed587aab11833f3", + "0xb091e6d37b157b50d76bd297ad752220cd5c9390fac16dc838f8557aed6d9833fc920b61519df21265406216315e883f", + "0xa6446c429ebf1c7793c622250e23594c836b2fbcaf6c5b3d0995e1595a37f50ea643f3e549b0be8bbdadd69044d72ab9", + "0x93e675353bd60e996bf1c914d5267eeaa8a52fc3077987ccc796710ef9becc6b7a00e3d82671a6bdfb8145ee3c80245a", + "0xa2f731e43251d04ed3364aa2f072d05355f299626f2d71a8a38b6f76cf08c544133f7d72dd0ab4162814b674b9fc7fa6", + "0x97a8b791a5a8f6e1d0de192d78615d73d0c38f1e557e4e15d15adc663d649e655bc8da3bcc499ef70112eafe7fb45c7a", + "0x98cd624cbbd6c53a94469be4643c13130916b91143425bcb7d7028adbbfede38eff7a21092af43b12d4fab703c116359", + "0x995783ce38fd5f6f9433027f122d4cf1e1ff3caf2d196ce591877f4a544ce9113ead60de2de1827eaff4dd31a20d79a8", + "0x8cf251d6f5229183b7f3fe2f607a90b4e4b6f020fb4ba2459d28eb8872426e7be8761a93d5413640a661d73e34a5b81f", + "0xb9232d99620652a3aa7880cad0876f153ff881c4ed4c0c2e7b4ea81d5d42b70daf1a56b869d752c3743c6d4c947e6641", + "0x849716f938f9d37250cccb1bf77f5f9fde53096cdfc6f2a25536a6187029a8f1331cdbed08909184b201f8d9f04b792f", + "0x80c7c4de098cbf9c6d17b14eba1805e433b5bc905f6096f8f63d34b94734f2e4ebf4bce8a177efd1186842a61204a062", + "0xb790f410cf06b9b8daadceeb4fd5ff40a2deda820c8df2537e0a7554613ae3948e149504e3e79aa84889df50c8678eeb", + "0x813aab8bd000299cd37485b73cd7cba06e205f8efb87f1efc0bae8b70f6db2bc7702eb39510ad734854fb65515fe9d0f", + "0x94f0ab7388ac71cdb67f6b85dfd5945748afb2e5abb622f0b5ad104be1d4d0062b651f134ba22385c9e32c2dfdcccce1", + "0xab6223dca8bd6a4f969e21ccd9f8106fc5251d321f9e90cc42cea2424b3a9c4e5060a47eeef6b23c7976109b548498e8", + "0x859c56b71343fce4d5c5b87814c47bf55d581c50fd1871a17e77b5e1742f5af639d0e94d19d909ec7dfe27919e954e0c", + "0xaae0d632b6191b8ad71b027791735f1578e1b89890b6c22e37de0e4a6074886126988fe8319ae228ac9ef3b3bcccb730", + "0x8ca9f32a27a024c3d595ecfaf96b0461de57befa3b331ab71dc110ec3be5824fed783d9516597537683e77a11d334338", + "0xa061df379fb3f4b24816c9f6cd8a94ecb89b4c6dc6cd81e4b8096fa9784b7f97ab3540259d1de9c02eb91d9945af4823", + "0x998603102ac63001d63eb7347a4bb2bf4cf33b28079bb48a169076a65c20d511ccd3ef696d159e54cc8e772fb5d65d50", + "0x94444d96d39450872ac69e44088c252c71f46be8333a608a475147752dbb99db0e36acfc5198f158509401959c12b709", + "0xac1b51b6c09fe055c1d7c9176eea9adc33f710818c83a1fbfa073c8dc3a7eb3513cbdd3f5960b7845e31e3e83181e6ba", + "0x803d530523fc9e1e0f11040d2412d02baef3f07eeb9b177fa9bfa396af42eea898a4276d56e1db998dc96ae47b644cb2", + "0x85a3c9fc7638f5bf2c3e15ba8c2fa1ae87eb1ceb44c6598c67a2948667a9dfa41e61f66d535b4e7fda62f013a5a8b885", + "0xa961cf5654c46a1a22c29baf7a4e77837a26b7f138f410e9d1883480ed5fa42411d522aba32040b577046c11f007388e", + "0xad1154142344f494e3061ef45a34fab1aaacf5fdf7d1b26adbb5fbc3d795655fa743444e39d9a4119b4a4f82a6f30441", + "0xb1d6c30771130c77806e7ab893b73d4deb590b2ff8f2f8b5e54c2040c1f3e060e2bd99afc668cf706a2df666a508bbf6", + "0xa00361fd440f9decabd98d96c575cd251dc94c60611025095d1201ef2dedde51cb4de7c2ece47732e5ed9b3526c2012c", + "0xa85c5ab4d17d328bda5e6d839a9a6adcc92ff844ec25f84981e4f44a0e8419247c081530f8d9aa629c7eb4ca21affba6", + "0xa4ddd3eab4527a2672cf9463db38bc29f61460e2a162f426b7852b7a7645fbd62084fd39a8e4d60e1958cce436dd8f57", + "0x811648140080fe55b8618f4cf17f3c5a250adb0cd53d885f2ddba835d2b4433188e41fc0661faac88e4ff910b16278c0", + "0xb85c7f1cfb0ed29addccf7546023a79249e8f15ac2d14a20accbfef4dd9dc11355d599815fa09d2b6b4e966e6ea8cff1", + "0xa10b5d8c260b159043b020d5dd62b3467df2671afea6d480ca9087b7e60ed170c82b121819d088315902842d66c8fb45", + "0x917e191df1bcf3f5715419c1e2191da6b8680543b1ba41fe84ed07ef570376e072c081beb67b375fca3565a2565bcabb", + "0x881fd967407390bfd7badc9ab494e8a287559a01eb07861f527207c127eadea626e9bcc5aa9cca2c5112fbac3b3f0e9c", + "0x959fd71149af82cc733619e0e5bf71760ca2650448c82984b3db74030d0e10f8ab1ce1609a6de6f470fe8b5bd90df5b3", + "0xa3370898a1c5f33d15adb4238df9a6c945f18b9ada4ce2624fc32a844f9ece4c916a64e9442225b6592afa06d2e015f2", + "0x817efb8a791435e4236f7d7b278181a5fa34587578c629dbc14fbf9a5c26772290611395eecd20222a4c58649fc256d8", + "0xa04c9876acf2cfdc8ef96de4879742709270fa1d03fe4c8511fbef2d59eb0aaf0336fa2c7dfe41a651157377fa217813", + "0x81e15875d7ea7f123e418edf14099f2e109d4f3a6ce0eb65f67fe9fb10d2f809a864a29f60ad3fc949f89e2596b21783", + "0xb49f529975c09e436e6bc202fdc16e3fdcbe056db45178016ad6fdece9faad4446343e83aed096209690b21a6910724f", + "0x879e8eda589e1a279f7f49f6dd0580788c040d973748ec4942dbe51ea8fbd05983cc919b78f0c6b92ef3292ae29db875", + "0x81a2b74b2118923f34139a102f3d95e7eee11c4c2929c2576dee200a5abfd364606158535a6c9e4178a6a83dbb65f3c4", + "0x8913f281d8927f2b45fc815d0f7104631cb7f5f7278a316f1327d670d15868daadd2a64e3eb98e1f53fe7e300338cc80", + "0xa6f815fba7ef9af7fbf45f93bc952e8b351f5de6568a27c7c47a00cb39a254c6b31753794f67940fc7d2e9cc581529f4", + "0xb3722a15c66a0014ce4d082de118def8d39190c15678a472b846225585f3a83756ae1b255b2e3f86a26168878e4773b2", + "0x817ae61ab3d0dd5b6e24846b5a5364b1a7dc2e77432d9fed587727520ae2f307264ea0948c91ad29f0aea3a11ff38624", + "0xb3db467464415fcad36dc1de2d6ba7686772a577cc2619242ac040d6734881a45d3b40ed4588db124e4289cfeec4bbf6", + "0xad66a14f5a54ac69603b16e5f1529851183da77d3cc60867f10aea41339dd5e06a5257982e9e90a352cdd32750f42ee4", + "0xadafa3681ef45d685555601a25a55cf23358319a17f61e2179e704f63df83a73bdd298d12cf6cef86db89bd17119e11d", + "0xa379dc44cb6dd3b9d378c07b2ec654fec7ca2f272de6ba895e3d00d20c9e4c5550498a843c8ac67e4221db2115bedc1c", + "0xb7bf81c267a78efc6b9e5a904574445a6487678d7ef70054e3e93ea6a23f966c2b68787f9164918e3b16d2175459ed92", + "0xb41d66a13a4afafd5760062b77f79de7e6ab8ccacde9c6c5116a6d886912fb491dc027af435b1b44aacc6af7b3c887f2", + "0x9904d23a7c1c1d2e4bab85d69f283eb0a8e26d46e8b7b30224438015c936729b2f0af7c7c54c03509bb0500acb42d8a4", + "0xae30d65e9e20c3bfd603994ae2b175ff691d51f3e24b2d058b3b8556d12ca4c75087809062dddd4aaac81c94d15d8a17", + "0x9245162fab42ac01527424f6013310c3eb462982518debef6c127f46ba8a06c705d7dc9f0a41e796ba8d35d60ae6cc64", + "0x87fab853638d7a29a20f3ba2b1a7919d023e9415bfa78ebb27973d8cbc7626f584dc5665d2e7ad71f1d760eba9700d88", + "0x85aac46ecd330608e5272430970e6081ff02a571e8ea444f1e11785ea798769634a22a142d0237f67b75369d3c484a8a", + "0x938c85ab14894cc5dfce3d80456f189a2e98eddbc8828f4ff6b1df1dcb7b42b17ca2ff40226a8a1390a95d63dca698dd", + "0xa18ce1f846e3e3c4d846822f60271eecf0f5d7d9f986385ac53c5ace9589dc7c0188910448c19b91341a1ef556652fa9", + "0x8611608a9d844f0e9d7584ad6ccf62a5087a64f764caf108db648a776b5390feb51e5120f0ef0e9e11301af3987dd7dc", + "0x8106333ba4b4de8d1ae43bc9735d3fea047392e88efd6a2fa6f7b924a18a7a265ca6123c3edc0f36307dd7fb7fe89257", + "0xa91426fa500951ff1b051a248c050b7139ca30dde8768690432d597d2b3c4357b11a577be6b455a1c5d145264dcf81fc", + "0xb7f9f90e0e450f37b081297f7f651bad0496a8b9afd2a4cf4120a2671aaaa8536dce1af301258bfbfdb122afa44c5048", + "0x84126da6435699b0c09fa4032dec73d1fca21d2d19f5214e8b0bea43267e9a8dd1fc44f8132d8315e734c8e2e04d7291", + "0xaff064708103884cb4f1a3c1718b3fc40a238d35cf0a7dc24bdf9823693b407c70da50df585bf5bc4e9c07d1c2d203e8", + "0xa8b40fc6533752983a5329c31d376c7a5c13ce6879cc7faee648200075d9cd273537001fb4c86e8576350eaac6ba60c2", + "0xa02db682bdc117a84dcb9312eb28fcbde12d49f4ce915cc92c610bb6965ec3cc38290f8c5b5ec70afe153956692cda95", + "0x86decd22b25d300508472c9ce75d3e465b737e7ce13bc0fcce32835e54646fe12322ba5bc457be18bfd926a1a6ca4a38", + "0xa18666ef65b8c2904fd598791f5627207165315a85ee01d5fb0e6b2e10bdd9b00babc447da5bd63445e3337de33b9b89", + "0x89bb0c06effadefdaf34ffe4b123e1678a90d4451ee856c863df1e752eef41fd984689ded8f0f878bf8916d5dd8e8024", + "0x97cfcba08ebec05d0073992a66b1d7d6fb9d95871f2cdc36db301f78bf8069294d1c259efef5c93d20dc937eedae3a1a", + "0xac2643b14ece79dcb2e289c96776a47e2bebd40dd6dc74fd035df5bb727b5596f40e3dd2d2202141e69b0993717ede09", + "0xa5e6fd88a2f9174d9bd4c6a55d9c30974be414992f22aa852f552c7648f722ed8077acf5aba030abd47939bb451b2c60", + "0x8ad40a612824a7994487731a40b311b7349038c841145865539c6ada75c56de6ac547a1c23df190e0caaafecddd80ccc", + "0x953a7cea1d857e09202c438c6108060961f195f88c32f0e012236d7a4b39d840c61b162ec86436e8c38567328bea0246", + "0x80d8b47a46dae1868a7b8ccfe7029445bbe1009dad4a6c31f9ef081be32e8e1ac1178c3c8fb68d3e536c84990cc035b1", + "0x81ecd99f22b3766ce0aca08a0a9191793f68c754fdec78b82a4c3bdc2db122bbb9ebfd02fc2dcc6e1567a7d42d0cc16a", + "0xb1dd0446bccc25846fb95d08c1c9cc52fb51c72c4c5d169ffde56ecfe800f108dc1106d65d5c5bd1087c656de3940b63", + "0xb87547f0931e164e96de5c550ca5aa81273648fe34f6e193cd9d69cf729cb432e17aa02e25b1c27a8a0d20a3b795e94e", + "0x820a94e69a927e077082aae66f6b292cfbe4589d932edf9e68e268c9bd3d71ef76cf7d169dd445b93967c25db11f58f1", + "0xb0d07ddf2595270c39adfa0c8cf2ab1322979b0546aa4d918f641be53cd97f36c879bb75d205e457c011aca3bbd9f731", + "0x8700b876b35b4b10a8a9372c5230acecd39539c1bb87515640293ad4464a9e02929d7d6a6a11112e8a29564815ac0de4", + "0xa61a601c5bb27dcb97e37c8e2b9ce479c6b192a5e04d9ed5e065833c5a1017ee5f237b77d1a17be5d48f8e7cc0bcacf6", + "0x92fb88fe774c1ba1d4a08cae3c0e05467ad610e7a3f1d2423fd47751759235fe0a3036db4095bd6404716aa03820f484", + "0xb274f140d77a3ce0796f5e09094b516537ccaf27ae1907099bff172e6368ba85e7c3ef8ea2a07457cac48ae334da95b3", + "0xb2292d9181f16581a9a9142490b2bdcdfb218ca6315d1effc8592100d792eb89d5356996c890441f04f2b4a95763503e", + "0x8897e73f576d86bc354baa3bd96e553107c48cf5889dcc23c5ba68ab8bcd4e81f27767be2233fdfa13d39f885087e668", + "0xa29eac6f0829791c728d71abc49569df95a4446ecbfc534b39f24f56c88fe70301838dfc1c19751e7f3c5c1b8c6af6a0", + "0x9346dc3720adc5df500a8df27fd9c75ef38dc5c8f4e8ed66983304750e66d502c3c59b8e955be781b670a0afc70a2167", + "0x9566d534e0e30a5c5f1428665590617e95fd05d45f573715f58157854ad596ece3a3cfec61356aee342308d623e029d5", + "0xa464fb8bffe6bd65f71938c1715c6e296cc6d0311a83858e4e7eb5873b7f2cf0c584d2101e3407b85b64ca78b2ac93ce", + "0xb54088f7217987c87e9498a747569ac5b2f8afd5348f9c45bf3fd9fbf713a20f495f49c8572d087efe778ac7313ad6d3", + "0x91fa9f5f8000fe050f5b224d90b59fcce13c77e903cbf98ded752e5b3db16adb2bc1f8c94be48b69f65f1f1ad81d6264", + "0x92d04a5b0ac5d8c8e313709b432c9434ecd3e73231f01e9b4e7952b87df60cbfa97b5dedd2200bd033b4b9ea8ba45cc1", + "0xa94b90ad3c3d6c4bbe169f8661a790c40645b40f0a9d1c7220f01cf7fc176e04d80bab0ced9323fcafb93643f12b2760", + "0x94d86149b9c8443b46196f7e5a3738206dd6f3be7762df488bcbb9f9ee285a64c997ed875b7b16b26604fa59020a8199", + "0x82efe4ae2c50a2d7645240c173a047f238536598c04a2c0b69c96e96bd18e075a99110f1206bc213f39edca42ba00cc1", + "0xab8667685f831bc14d4610f84a5da27b4ea5b133b4d991741a9e64dceb22cb64a3ce8f1b6e101d52af6296df7127c9ad", + "0x83ba433661c05dcc5d562f4a9a261c8110dac44b8d833ae1514b1fc60d8b4ee395b18804baea04cb10adb428faf713c3", + "0xb5748f6f660cc5277f1211d2b8649493ed8a11085b871cd33a5aea630abd960a740f08c08be5f9c21574600ac9bf5737", + "0xa5c8dd12af48fb710642ad65ebb97ca489e8206741807f7acfc334f8035d3c80593b1ff2090c9bb7bd138f0c48714ca8", + "0xa2b382fd5744e3babf454b1d806cc8783efeb4761bc42b6914ea48a46a2eae835efbe0a18262b6bc034379e03cf1262b", + "0xb3145ffaf603f69f15a64936d32e3219eea5ed49fdfd2f5bf40ea0dfd974b36fb6ff12164d4c2282d892db4cf3ff3ce1", + "0x87a316fb213f4c5e30c5e3face049db66be4f28821bd96034714ec23d3e97849d7b301930f90a4323c7ccf53de23050c", + "0xb9de09a919455070fed6220fc179c8b7a4c753062bcd27acf28f5b9947a659c0b364298daf7c85c4ca6fca7f945add1f", + "0x806fbd98d411b76979464c40ad88bc07a151628a27fcc1012ba1dfbaf5b5cc9d962fb9b3386008978a12515edce934bc", + "0xa15268877fae0d21610ae6a31061ed7c20814723385955fac09fdc9693a94c33dea11db98bb89fdfe68f933490f5c381", + "0x8d633fb0c4da86b2e0b37d8fad5972d62bff2ac663c5ec815d095cd4b7e1fe66ebef2a2590995b57eaf941983c7ad7a4", + "0x8139e5dd9cf405e8ef65f11164f0440827d98389ce1b418b0c9628be983a9ddd6cf4863036ccb1483b40b8a527acd9ed", + "0x88b15fa94a08eac291d2b94a2b30eb851ff24addf2cc30b678e72e32cfcb3424cf4b33aa395d741803f3e578ddf524de", + "0xb5eaf0c8506e101f1646bcf049ee38d99ea1c60169730da893fd6020fd00a289eb2f415947e44677af49e43454a7b1be", + "0x8489822ad0647a7e06aa2aa5595960811858ddd4542acca419dd2308a8c5477648f4dd969a6740bb78aa26db9bfcc555", + "0xb1e9a7b9f3423c220330d45f69e45fa03d7671897cf077f913c252e3e99c7b1b1cf6d30caad65e4228d5d7b80eb86e5e", + "0xb28fe9629592b9e6a55a1406903be76250b1c50c65296c10c5e48c64b539fb08fe11f68cf462a6edcbba71b0cee3feb2", + "0xa41acf96a02c96cd8744ff6577c244fc923810d17ade133587e4c223beb7b4d99fa56eae311a500d7151979267d0895c", + "0x880798938fe4ba70721be90e666dfb62fcab4f3556fdb7b0dc8ec5bc34f6b4513df965eae78527136eb391889fe2caf9", + "0x98d4d89d358e0fb7e212498c73447d94a83c1b66e98fc81427ab13acddb17a20f52308983f3a5a8e0aaacec432359604", + "0x81430b6d2998fc78ba937a1639c6020199c52da499f68109da227882dc26d005b73d54c5bdcac1a04e8356a8ca0f7017", + "0xa8d906a4786455eb74613aba4ce1c963c60095ffb8658d368df9266fdd01e30269ce10bf984e7465f34b4fd83beba26a", + "0xaf54167ac1f954d10131d44a8e0045df00d581dd9e93596a28d157543fbe5fb25d213806ed7fb3cba6b8f5b5423562db", + "0x8511e373a978a12d81266b9afbd55035d7bc736835cfa921903a92969eeba3624437d1346b55382e61415726ab84a448", + "0x8cf43eea93508ae586fa9a0f1354a1e16af659782479c2040874a46317f9e8d572a23238efa318fdfb87cc63932602b7", + "0xb0bdd3bacff077173d302e3a9678d1d37936188c7ecc34950185af6b462b7c679815176f3cce5db19aac8b282f2d60ad", + "0xa355e9b87f2f2672052f5d4d65b8c1c827d24d89b0d8594641fccfb69aef1b94009105f3242058bb31c8bf51caae5a41", + "0xb8baa9e4b950b72ff6b88a6509e8ed1304bc6fd955748b2e59a523a1e0c5e99f52aec3da7fa9ff407a7adf259652466c", + "0x840bc3dbb300ea6f27d1d6dd861f15680bd098be5174f45d6b75b094d0635aced539fa03ddbccb453879de77fb5d1fe9", + "0xb4bc7e7e30686303856472bae07e581a0c0bfc815657c479f9f5931cff208d5c12930d2fd1ff413ebd8424bcd7a9b571", + "0x89b5d514155d7999408334a50822508b9d689add55d44a240ff2bdde2eee419d117031f85e924e2a2c1ca77db9b91eea", + "0xa8604b6196f87a04e1350302e8aa745bba8dc162115d22657b37a1d1a98cb14876ddf7f65840b5dbd77e80cd22b4256c", + "0x83cb7acdb9e03247515bb2ce0227486ccf803426717a14510f0d59d45e998b245797d356f10abca94f7a14e1a2f0d552", + "0xaeb3266a9f16649210ab2df0e1908ac259f34ce1f01162c22b56cf1019096ee4ea5854c36e30bb2feb06c21a71e8a45c", + "0x89e72e86edf2aa032a0fc9acf4d876a40865fbb2c8f87cb7e4d88856295c4ac14583e874142fd0c314a49aba68c0aa3c", + "0x8c3576eba0583c2a7884976b4ed11fe1fda4f6c32f6385d96c47b0e776afa287503b397fa516a455b4b8c3afeedc76db", + "0xa31e5b633bda9ffa174654fee98b5d5930a691c3c42fcf55673d927dbc8d91c58c4e42e615353145431baa646e8bbb30", + "0x89f2f3f7a8da1544f24682f41c68114a8f78c86bd36b066e27da13acb70f18d9f548773a16bd8e24789420e17183f137", + "0xada27fa4e90a086240c9164544d2528621a415a5497badb79f8019dc3dce4d12eb6b599597e47ec6ac39c81efda43520", + "0x90dc1eb21bf21c0187f359566fc4bf5386abea52799306a0e5a1151c0817c5f5bc60c86e76b1929c092c0f3ff48cedd2", + "0xb702a53ebcc17ae35d2e735a347d2c700e9cbef8eadbece33cac83df483b2054c126593e1f462cfc00a3ce9d737e2af5", + "0x9891b06455ec925a6f8eafffba05af6a38cc5e193acaaf74ffbf199df912c5197106c5e06d72942bbb032ce277b6417f", + "0x8c0ee71eb01197b019275bcf96cae94e81d2cdc3115dbf2d8e3080074260318bc9303597e8f72b18f965ad601d31ec43", + "0x8aaf580aaf75c1b7a5f99ccf60503506e62058ef43b28b02f79b8536a96be3f019c9f71caf327b4e6730134730d1bef5", + "0xae6f9fc21dd7dfa672b25a87eb0a41644f7609fab5026d5cedb6e43a06dbbfd6d6e30322a2598c8dedde88c52eaed626", + "0x8159b953ffece5693edadb2e906ebf76ff080ee1ad22698950d2d3bfc36ac5ea78f58284b2ca180664452d55bd54716c", + "0xab7647c32ca5e9856ac283a2f86768d68de75ceeba9e58b74c5324f8298319e52183739aba4340be901699d66ac9eb3f", + "0xa4d85a5701d89bcfaf1572db83258d86a1a0717603d6f24ac2963ffcf80f1265e5ab376a4529ca504f4396498791253c", + "0x816080c0cdbfe61b4d726c305747a9eb58ac26d9a35f501dd32ba43c098082d20faf3ccd41aad24600aa73bfa453dfac", + "0x84f3afac024f576b0fd9acc6f2349c2fcefc3f77dbe5a2d4964d14b861b88e9b1810334b908cf3427d9b67a8aee74b18", + "0x94b390655557b1a09110018e9b5a14490681ade275bdc83510b6465a1218465260d9a7e2a6e4ec700f58c31dc3659962", + "0xa8c66826b1c04a2dd4c682543242e7a57acae37278bd09888a3d17747c5b5fec43548101e6f46d703638337e2fd3277b", + "0x86e6f4608a00007fa533c36a5b054c5768ccafe41ad52521d772dcae4c8a4bcaff8f7609be30d8fab62c5988cbbb6830", + "0x837da4cf09ae8aa0bceb16f8b3bfcc3b3367aecac9eed6b4b56d7b65f55981ef066490764fb4c108792623ecf8cad383", + "0x941ff3011462f9b5bf97d8cbdb0b6f5d37a1b1295b622f5485b7d69f2cb2bcabc83630dae427f0259d0d9539a77d8424", + "0xb99e5d6d82aa9cf7d5970e7f710f4039ac32c2077530e4c2779250c6b9b373bc380adb0a03b892b652f649720672fc8c", + "0xa791c78464b2d65a15440b699e1e30ebd08501d6f2720adbc8255d989a82fcded2f79819b5f8f201bed84a255211b141", + "0x84af7ad4a0e31fcbb3276ab1ad6171429cf39adcf78dc03750dc5deaa46536d15591e26d53e953dfb31e1622bc0743ab", + "0xa833e62fe97e1086fae1d4917fbaf09c345feb6bf1975b5cb863d8b66e8d621c7989ab3dbecda36bc9eaffc5eaa6fa66", + "0xb4ef79a46a2126f53e2ebe62770feb57fd94600be29459d70a77c5e9cc260fa892be06cd60f886bf48459e48eb50d063", + "0xb43b8f61919ea380bf151c294e54d3a3ff98e20d1ee5efbfe38aa2b66fafbc6a49739793bd5cb1c809f8b30466277c3a", + "0xab37735af2412d2550e62df9d8b3b5e6f467f20de3890bf56faf1abf2bf3bd1d98dc3fa0ad5e7ab3fce0fa20409eb392", + "0x82416b74b1551d484250d85bb151fabb67e29cce93d516125533df585bc80779ab057ea6992801a3d7d5c6dcff87a018", + "0x8145d0787f0e3b5325190ae10c1d6bee713e6765fb6a0e9214132c6f78f4582bb2771aaeae40d3dad4bafb56bf7e36d8", + "0xb6935886349ecbdd5774e12196f4275c97ec8279fdf28ccf940f6a022ebb6de8e97d6d2173c3fe402cbe9643bed3883b", + "0x87ef9b4d3dc71ac86369f8ed17e0dd3b91d16d14ae694bc21a35b5ae37211b043d0e36d8ff07dcc513fb9e6481a1f37f", + "0xae1d0ded32f7e6f1dc8fef495879c1d9e01826f449f903c1e5034aeeabc5479a9e323b162b688317d46d35a42d570d86", + "0xa40d16497004db4104c6794e2f4428d75bdf70352685944f3fbe17526df333e46a4ca6de55a4a48c02ecf0bde8ba03c0", + "0x8d45121efba8cc308a498e8ee39ea6fa5cae9fb2e4aab1c2ff9d448aa8494ccbec9a078f978a86fcd97b5d5e7be7522a", + "0xa8173865c64634ba4ac2fa432740f5c05056a9deaf6427cb9b4b8da94ca5ddbc8c0c5d3185a89b8b28878194de9cdfcd", + "0xb6ec06a74d690f6545f0f0efba236e63d1fdfba54639ca2617408e185177ece28901c457d02b849fd00f1a53ae319d0a", + "0xb69a12df293c014a40070e3e760169b6f3c627caf9e50b35a93f11ecf8df98b2bc481b410eecb7ab210bf213bbe944de", + "0x97e7dc121795a533d4224803e591eef3e9008bab16f12472210b73aaf77890cf6e3877e0139403a0d3003c12c8f45636", + "0xacdfa6fdd4a5acb7738cc8768f7cba84dbb95c639399b291ae8e4e63df37d2d4096900a84d2f0606bf534a9ccaa4993f", + "0x86ee253f3a9446a33e4d1169719b7d513c6b50730988415382faaf751988c10a421020609f7bcdef91be136704b906e2", + "0xaac9438382a856caf84c5a8a234282f71b5fc5f65219103b147e7e6cf565522285fbfd7417b513bdad8277a00f652ca1", + "0x83f3799d8e5772527930f5dc071a2e0a65471618993ec8990a96ccdeee65270e490bda9d26bb877612475268711ffd80", + "0x93f28a81ac8c0ec9450b9d762fae9c7f8feaace87a6ee6bd141ef1d2d0697ef1bbd159fe6e1de640dbdab2b0361fca8a", + "0xa0825c95ba69999b90eac3a31a3fd830ea4f4b2b7409bde5f202b61d741d6326852ce790f41de5cb0eccec7af4db30c1", + "0x83924b0e66233edd603c3b813d698daa05751fc34367120e3cf384ea7432e256ccee4d4daf13858950549d75a377107d", + "0x956fd9fa58345277e06ba2ec72f49ed230b8d3d4ff658555c52d6cddeb84dd4e36f1a614f5242d5ca0192e8daf0543c2", + "0x944869912476baae0b114cced4ff65c0e4c90136f73ece5656460626599051b78802df67d7201c55d52725a97f5f29fe", + "0x865cb25b64b4531fb6fe4814d7c8cd26b017a6c6b72232ff53defc18a80fe3b39511b23f9e4c6c7249d06e03b2282ed2", + "0x81e09ff55214960775e1e7f2758b9a6c4e4cd39edf7ec1adfaad51c52141182b79fe2176b23ddc7df9fd153e5f82d668", + "0xb31006896f02bc90641121083f43c3172b1039334501fbaf1672f7bf5d174ddd185f945adf1a9c6cf77be34c5501483d", + "0x88b92f6f42ae45e9f05b16e52852826e933efd0c68b0f2418ac90957fd018df661bc47c8d43c2a7d7bfcf669dab98c3c", + "0x92fc68f595853ee8683930751789b799f397135d002eda244fe63ecef2754e15849edde3ba2f0cc8b865c9777230b712", + "0x99ca06a49c5cd0bb097c447793fcdd809869b216a34c66c78c7e41e8c22f05d09168d46b8b1f3390db9452d91bc96dea", + "0xb48b9490a5d65296802431852d548d81047bbefc74fa7dc1d4e2a2878faacdfcb365ae59209cb0ade01901a283cbd15d", + "0xaff0fdbef7c188b120a02bc9085d7b808e88f73973773fef54707bf2cd772cd066740b1b6f4127b5c349f657bd97e738", + "0x966fd4463b4f43dd8ccba7ad50baa42292f9f8b2e70da23bb6780e14155d9346e275ef03ddaf79e47020dcf43f3738bd", + "0x9330c3e1fadd9e08ac85f4839121ae20bbeb0a5103d84fa5aadbd1213805bdcda67bf2fb75fc301349cbc851b5559d20", + "0x993bb99867bd9041a71a55ad5d397755cfa7ab6a4618fc526179bfc10b7dc8b26e4372fe9a9b4a15d64f2b63c1052dda", + "0xa29b59bcfab51f9b3c490a3b96f0bf1934265c315349b236012adbd64a56d7f6941b2c8cc272b412044bc7731f71e1dc", + "0xa65c9cefe1fc35d089fe8580c2e7671ebefdb43014ac291528ff4deefd4883fd4df274af83711dad610dad0d615f9d65", + "0x944c78c56fb227ae632805d448ca3884cd3d2a89181cead3d2b7835e63297e6d740aa79a112edb1d4727824991636df5", + "0xa73d782da1db7e4e65d7b26717a76e16dd9fab4df65063310b8e917dc0bc24e0d6755df5546c58504d04d9e68c3b474a", + "0xaf80f0b87811ae3124f68108b4ca1937009403f87928bbc53480e7c5408d072053ace5eeaf5a5aba814dab8a45502085", + "0x88aaf1acfc6e2e19b8387c97da707cb171c69812fefdd4650468e9b2c627bd5ccfb459f4d8e56bdfd84b09ddf87e128f", + "0x92c97276ff6f72bab6e9423d02ad6dc127962dbce15a0dd1e4a393b4510c555df6aa27be0f697c0d847033a9ca8b8dfd", + "0xa0e07d43d96e2d85b6276b3c60aadb48f0aedf2de8c415756dc597249ea64d2093731d8735231dadc961e5682ac59479", + "0xadc9e6718a8f9298957d1da3842a7751c5399bbdf56f8de6c1c4bc39428f4aee6f1ba6613d37bf46b9403345e9d6fc81", + "0x951da434da4b20d949b509ceeba02e24da7ed2da964c2fcdf426ec787779c696b385822c7dbea4df3e4a35921f1e912c", + "0xa04cbce0d2b2e87bbf038c798a12ec828423ca6aca08dc8d481cf6466e3c9c73d4d4a7fa47df9a7e2e15aae9e9f67208", + "0x8f855cca2e440d248121c0469de1f94c2a71b8ee2682bbad3a78243a9e03da31d1925e6760dbc48a1957e040fae9abe8", + "0xb642e5b17c1df4a4e101772d73851180b3a92e9e8b26c918050f51e6dd3592f102d20b0a1e96f0e25752c292f4c903ff", + "0xa92454c300781f8ae1766dbbb50a96192da7d48ef4cbdd72dd8cbb44c6eb5913c112cc38e9144615fdc03684deb99420", + "0x8b74f7e6c2304f8e780df4649ef8221795dfe85fdbdaa477a1542d135b75c8be45bf89adbbb6f3ddf54ca40f02e733e9", + "0x85cf66292cbb30cec5fd835ab10c9fcb3aea95e093aebf123e9a83c26f322d76ebc89c4e914524f6c5f6ee7d74fc917d", + "0xae0bfe0cdc97c09542a7431820015f2d16067b30dca56288013876025e81daa8c519e5e347268e19aa1a85fa1dc28793", + "0x921322fc6a47dc091afa0ad6df18ed14cde38e48c6e71550aa513918b056044983aee402de21051235eecf4ce8040fbe", + "0x96c030381e97050a45a318d307dcb3c8377b79b4dd5daf6337cded114de26eb725c14171b9b8e1b3c08fe1f5ea6b49e0", + "0x90c23b86b6111818c8baaf53a13eaee1c89203b50e7f9a994bf0edf851919b48edbac7ceef14ac9414cf70c486174a77", + "0x8bf6c301240d2d1c8d84c71d33a6dfc6d9e8f1cfae66d4d0f7a256d98ae12b0bcebfa94a667735ee89f810bcd7170cff", + "0xa41a4ffbbea0e36874d65c009ee4c3feffff322f6fc0e30d26ee4dbc1f46040d05e25d9d0ecb378cef0d24a7c2c4b850", + "0xa8d4cdd423986bb392a0a92c12a8bd4da3437eec6ef6af34cf5310944899287452a2eb92eb5386086d5063381189d10e", + "0xa81dd26ec057c4032a4ed7ad54d926165273ed51d09a1267b2e477535cf6966835a257c209e4e92d165d74fa75695fa3", + "0x8d7f708c3ee8449515d94fc26b547303b53d8dd55f177bc3b25d3da2768accd9bc8e9f09546090ebb7f15c66e6c9c723", + "0x839ba65cffcd24cfffa7ab3b21faabe3c66d4c06324f07b2729c92f15cad34e474b0f0ddb16cd652870b26a756b731d3", + "0x87f1a3968afec354d92d77e2726b702847c6afcabb8438634f9c6f7766de4c1504317dc4fa9a4a735acdbf985e119564", + "0x91a8a7fd6542f3e0673f07f510d850864b34ac087eb7eef8845a1d14b2b1b651cbdc27fa4049bdbf3fea54221c5c8549", + "0xaef3cf5f5e3a2385ead115728d7059e622146c3457d266c612e778324b6e06fbfb8f98e076624d2f3ce1035d65389a07", + "0x819915d6232e95ccd7693fdd78d00492299b1983bc8f96a08dcb50f9c0a813ed93ae53c0238345d5bea0beda2855a913", + "0x8e9ba68ded0e94935131b392b28218315a185f63bf5e3c1a9a9dd470944509ca0ba8f6122265f8da851b5cc2abce68f1", + "0xb28468e9b04ee9d69003399a3cf4457c9bf9d59f36ab6ceeb8e964672433d06b58beeea198fedc7edbaa1948577e9fa2", + "0xa633005e2c9f2fd94c8bce2dd5bb708fe946b25f1ec561ae65e54e15cdd88dc339f1a083e01f0d39610c8fe24151aaf0", + "0x841d0031e22723f9328dd993805abd13e0c99b0f59435d2426246996b08d00ce73ab906f66c4eab423473b409e972ce0", + "0x85758d1b084263992070ec8943f33073a2d9b86a8606672550c17545507a5b3c88d87382b41916a87ee96ff55a7aa535", + "0x8581b06b0fc41466ef94a76a1d9fb8ae0edca6d018063acf6a8ca5f4b02d76021902feba58972415691b4bdbc33ae3b4", + "0x83539597ff5e327357ee62bc6bf8c0bcaec2f227c55c7c385a4806f0d37fb461f1690bad5066b8a5370950af32fafbef", + "0xaee3557290d2dc10827e4791d00e0259006911f3f3fce4179ed3c514b779160613eca70f720bff7804752715a1266ffa", + "0xb48d2f0c4e90fc307d5995464e3f611a9b0ef5fe426a289071f4168ed5cc4f8770c9332960c2ca5c8c427f40e6bb389f", + "0x847af8973b4e300bb06be69b71b96183fd1a0b9d51b91701bef6fcfde465068f1eb2b1503b07afda380f18d69de5c9e1", + "0xa70a6a80ce407f07804c0051ac21dc24d794b387be94eb24e1db94b58a78e1bcfb48cd0006db8fc1f9bedaece7a44fbe", + "0xb40e942b8fa5336910ff0098347df716bff9d1fa236a1950c16eeb966b3bc1a50b8f7b0980469d42e75ae13ced53cead", + "0xb208fabaa742d7db3148515330eb7a3577487845abdb7bd9ed169d0e081db0a5816595c33d375e56aeac5b51e60e49d3", + "0xb7c8194b30d3d6ef5ab66ec88ad7ebbc732a3b8a41731b153e6f63759a93f3f4a537eab9ad369705bd730184bdbbdc34", + "0x9280096445fe7394d04aa1bc4620c8f9296e991cc4d6c131bd703cb1cc317510e6e5855ac763f4d958c5edfe7eebeed7", + "0xabc2aa4616a521400af1a12440dc544e3c821313d0ab936c86af28468ef8bbe534837e364598396a81cf8d06274ed5a6", + "0xb18ca8a3325adb0c8c18a666d4859535397a1c3fe08f95eebfac916a7a99bbd40b3c37b919e8a8ae91da38bc00fa56c0", + "0x8a40c33109ecea2a8b3558565877082f79121a432c45ec2c5a5e0ec4d1c203a6788e6b69cb37f1fd5b8c9a661bc5476d", + "0x88c47301dd30998e903c84e0b0f2c9af2e1ce6b9f187dab03528d44f834dc991e4c86d0c474a2c63468cf4020a1e24a0", + "0x920c832853e6ab4c851eecfa9c11d3acc7da37c823be7aa1ab15e14dfd8beb5d0b91d62a30cec94763bd8e4594b66600", + "0x98e1addbe2a6b8edc7f12ecb9be81c3250aeeca54a1c6a7225772ca66549827c15f3950d01b8eb44aecb56fe0fff901a", + "0x8cfb0fa1068be0ec088402f5950c4679a2eb9218c729da67050b0d1b2d7079f3ddf4bf0f57d95fe2a8db04bc6bcdb20c", + "0xb70f381aafe336b024120453813aeab70baac85b9c4c0f86918797b6aee206e6ed93244a49950f3d8ec9f81f4ac15808", + "0xa4c8edf4aa33b709a91e1062939512419711c1757084e46f8f4b7ed64f8e682f4e78b7135920c12f0eb0422fe9f87a6a", + "0xb4817e85fd0752d7ebb662d3a51a03367a84bac74ebddfba0e5af5e636a979500f72b148052d333b3dedf9edd2b4031b", + "0xa87430169c6195f5d3e314ff2d1c2f050e766fd5d2de88f5207d72dba4a7745bb86d0baca6e9ae156582d0d89e5838c7", + "0x991b00f8b104566b63a12af4826b61ce7aa40f4e5b8fff3085e7a99815bdb4471b6214da1e480214fac83f86a0b93cc5", + "0xb39966e3076482079de0678477df98578377a094054960ee518ef99504d6851f8bcd3203e8da5e1d4f6f96776e1fe6eb", + "0xa448846d9dc2ab7a0995fa44b8527e27f6b3b74c6e03e95edb64e6baa4f1b866103f0addb97c84bef1d72487b2e21796", + "0x894bec21a453ae84b592286e696c35bc30e820e9c2fd3e63dd4fbe629e07df16439c891056070faa490155f255bf7187", + "0xa9ec652a491b11f6a692064e955f3f3287e7d2764527e58938571469a1e29b5225b9415bd602a45074dfbfe9c131d6ca", + "0xb39d37822e6cbe28244b5f42ce467c65a23765bd16eb6447c5b3e942278069793763483dafd8c4dd864f8917aad357fe", + "0x88dba51133f2019cb266641c56101e3e5987d3b77647a2e608b5ff9113dfc5f85e2b7c365118723131fbc0c9ca833c9c", + "0xb566579d904b54ecf798018efcb824dccbebfc6753a0fd2128ac3b4bd3b038c2284a7c782b5ca6f310eb7ea4d26a3f0a", + "0xa97a55c0a492e53c047e7d6f9d5f3e86fb96f3dddc68389c0561515343b66b4bc02a9c0d5722dff1e3445308240b27f7", + "0xa044028ab4bcb9e1a2b9b4ca4efbf04c5da9e4bf2fff0e8bd57aa1fc12a71e897999c25d9117413faf2f45395dee0f13", + "0xa78dc461decbeaeed8ebd0909369b491a5e764d6a5645a7dac61d3140d7dc0062526f777b0eb866bff27608429ebbdde", + "0xb2c2a8991f94c39ca35fea59f01a92cb3393e0eccb2476dfbf57261d406a68bd34a6cff33ed80209991688c183609ef4", + "0x84189eefb521aff730a4fd3fd5b10ddfd29f0d365664caef63bb015d07e689989e54c33c2141dd64427805d37a7e546e", + "0x85ac80bd734a52235da288ff042dea9a62e085928954e8eacd2c751013f61904ed110e5b3afe1ab770a7e6485efb7b5e", + "0x9183a560393dcb22d0d5063e71182020d0fbabb39e32493eeffeb808df084aa243eb397027f150b55a247d1ed0c8513e", + "0x81c940944df7ecc58d3c43c34996852c3c7915ed185d7654627f7af62abae7e0048dd444a6c09961756455000bd96d09", + "0xaa8c34e164019743fd8284b84f06c3b449aae7996e892f419ee55d82ad548cb300fd651de329da0384243954c0ef6a60", + "0x89a7b7bdfc7e300d06a14d463e573d6296d8e66197491900cc9ae49504c4809ff6e61b758579e9091c61085ba1237b83", + "0x878d21809ba540f50bd11f4c4d9590fb6f3ab9de5692606e6e2ef4ed9d18520119e385be5e1f4b3f2e2b09c319f0e8fc", + "0x8eb248390193189cf0355365e630b782cd15751e672dc478b39d75dc681234dcd9309df0d11f4610dbb249c1e6be7ef9", + "0xa1d7fb3aecb896df3a52d6bd0943838b13f1bd039c936d76d03de2044c371d48865694b6f532393b27fd10a4cf642061", + "0xa34bca58a24979be442238cbb5ece5bee51ae8c0794dd3efb3983d4db713bc6f28a96e976ac3bd9a551d3ed9ba6b3e22", + "0x817c608fc8cacdd178665320b5a7587ca21df8bdd761833c3018b967575d25e3951cf3d498a63619a3cd2ad4406f5f28", + "0x86c95707db0495689afd0c2e39e97f445f7ca0edffad5c8b4cacd1421f2f3cc55049dfd504f728f91534e20383955582", + "0x99c3b0bb15942c301137765d4e19502f65806f3b126dc01a5b7820c87e8979bce6a37289a8f6a4c1e4637227ad5bf3bf", + "0x8aa1518a80ea8b074505a9b3f96829f5d4afa55a30efe7b4de4e5dbf666897fdd2cf31728ca45921e21a78a80f0e0f10", + "0x8d74f46361c79e15128ac399e958a91067ef4cec8983408775a87eca1eed5b7dcbf0ddf30e66f51780457413496c7f07", + "0xa41cde4a786b55387458a1db95171aca4fd146507b81c4da1e6d6e495527c3ec83fc42fad1dfe3d92744084a664fd431", + "0x8c352852c906fae99413a84ad11701f93f292fbf7bd14738814f4c4ceab32db02feb5eb70bc73898b0bc724a39d5d017", + "0xa5993046e8f23b71ba87b7caa7ace2d9023fb48ce4c51838813174880d918e9b4d2b0dc21a2b9c6f612338c31a289df8", + "0x83576d3324bf2d8afbfb6eaecdc5d767c8e22e7d25160414924f0645491df60541948a05e1f4202e612368e78675de8a", + "0xb43749b8df4b15bc9a3697e0f1c518e6b04114171739ef1a0c9c65185d8ec18e40e6954d125cbc14ebc652cf41ad3109", + "0xb4eebd5d80a7327a040cafb9ccdb12b2dfe1aa86e6bc6d3ac8a57fadfb95a5b1a7332c66318ff72ba459f525668af056", + "0x9198be7f1d413c5029b0e1c617bcbc082d21abe2c60ec8ce9b54ca1a85d3dba637b72fda39dae0c0ae40d047eab9f55a", + "0x8d96a0232832e24d45092653e781e7a9c9520766c3989e67bbe86b3a820c4bf621ea911e7cd5270a4bfea78b618411f6", + "0x8d7160d0ea98161a2d14d46ef01dff72d566c330cd4fabd27654d300e1bc7644c68dc8eabf2a20a59bfe7ba276545f9b", + "0xabb60fce29dec7ba37e3056e412e0ec3e05538a1fc0e2c68877378c867605966108bc5742585ab6a405ce0c962b285b6", + "0x8fabffa3ed792f05e414f5839386f6449fd9f7b41a47595c5d71074bd1bb3784cc7a1a7e1ad6b041b455035957e5b2dc", + "0x90ff017b4804c2d0533b72461436b10603ab13a55f86fd4ec11b06a70ef8166f958c110519ca1b4cc7beba440729fe2d", + "0xb340cfd120f6a4623e3a74cf8c32bfd7cd61a280b59dfd17b15ca8fae4d82f64a6f15fbde4c02f424debc72b7db5fe67", + "0x871311c9c7220c932e738d59f0ecc67a34356d1429fe570ca503d340c9996cb5ee2cd188fad0e3bd16e4c468ec1dbebd", + "0xa772470262186e7b94239ba921b29f2412c148d6f97c4412e96d21e55f3be73f992f1ad53c71008f0558ec3f84e2b5a7", + "0xb2a897dcb7ffd6257f3f2947ec966f2077d57d5191a88840b1d4f67effebe8c436641be85524d0a21be734c63ab5965d", + "0xa044f6eacc48a4a061fa149500d96b48cbf14853469aa4d045faf3dca973be1bd4b4ce01646d83e2f24f7c486d03205d", + "0x981af5dc2daa73f7fa9eae35a93d81eb6edba4a7f673b55d41f6ecd87a37685d31bb40ef4f1c469b3d72f2f18b925a17", + "0x912d2597a07864de9020ac77083eff2f15ceb07600f15755aba61251e8ce3c905a758453b417f04d9c38db040954eb65", + "0x9642b7f6f09394ba5e0805734ef6702c3eddf9eea187ba98c676d5bbaec0e360e3e51dc58433aaa1e2da6060c8659cb7", + "0x8ab3836e0a8ac492d5e707d056310c4c8e0489ca85eb771bff35ba1d658360084e836a6f51bb990f9e3d2d9aeb18fbb5", + "0x879e058e72b73bb1f4642c21ffdb90544b846868139c6511f299aafe59c2d0f0b944dffc7990491b7c4edcd6a9889250", + "0xb9e60b737023f61479a4a8fd253ed0d2a944ea6ba0439bbc0a0d3abf09b0ad1f18d75555e4a50405470ae4990626f390", + "0xb9c2535d362796dcd673640a9fa2ebdaec274e6f8b850b023153b0a7a30fffc87f96e0b72696f647ebe7ab63099a6963", + "0x94aeff145386a087b0e91e68a84a5ede01f978f9dd9fe7bebca78941938469495dc30a96bba9508c0d017873aeea9610", + "0x98b179f8a3d9f0d0a983c30682dd425a2ddc7803be59bd626c623c8951a5179117d1d2a68254c95c9952989877d0ee55", + "0x889ecf5f0ee56938273f74eb3e9ecfb5617f04fb58e83fe4c0e4aef51615cf345bc56f3f61b17f6eed3249d4afd54451", + "0xa0f2b2c39bcea4b50883e2587d16559e246248a66ecb4a4b7d9ab3b51fb39fe98d83765e087eee37a0f86b0ba4144c02", + "0xb2a61e247ed595e8a3830f7973b07079cbda510f28ad8c78c220b26cb6acde4fbb5ee90c14a665f329168ee951b08cf0", + "0x95bd0fcfb42f0d6d8a8e73d7458498a85bcddd2fb132fd7989265648d82ac2707d6d203fac045504977af4f0a2aca4b7", + "0x843e5a537c298666e6cf50fcc044f13506499ef83c802e719ff2c90e85003c132024e04711be7234c04d4b0125512d5d", + "0xa46d1797c5959dcd3a5cfc857488f4d96f74277c3d13b98b133620192f79944abcb3a361d939a100187f1b0856eae875", + "0xa1c7786736d6707a48515c38660615fcec67eb8a2598f46657855215f804fd72ab122d17f94fcffad8893f3be658dca7", + "0xb23dc9e610abc7d8bd21d147e22509a0fa49db5be6ea7057b51aae38e31654b3aa044df05b94b718153361371ba2f622", + "0xb00cc8f257d659c22d30e6d641f79166b1e752ea8606f558e4cad6fc01532e8319ea4ee12265ba4140ac45aa4613c004", + "0xac7019af65221b0cc736287b32d7f1a3561405715ba9a6a122342e04e51637ba911c41573de53e4781f2230fdcb2475f", + "0x81a630bc41b3da8b3eb4bf56cba10cd9f93153c3667f009dc332287baeb707d505fb537e6233c8e53d299ec0f013290c", + "0xa6b7aea5c545bb76df0f230548539db92bc26642572cb7dd3d5a30edca2b4c386f44fc8466f056b42de2a452b81aff5b", + "0x8271624ff736b7b238e43943c81de80a1612207d32036d820c11fc830c737972ccc9c60d3c2359922b06652311e3c994", + "0x8a684106458cb6f4db478170b9ad595d4b54c18bf63b9058f095a2fa1b928c15101472c70c648873d5887880059ed402", + "0xa5cc3c35228122f410184e4326cf61a37637206e589fcd245cb5d0cec91031f8f7586b80503070840fdfd8ce75d3c88b", + "0x9443fc631aed8866a7ed220890911057a1f56b0afe0ba15f0a0e295ab97f604b134b1ed9a4245e46ee5f9a93aa74f731", + "0x984b6f7d79835dffde9558c6bb912d992ca1180a2361757bdba4a7b69dc74b056e303adc69fe67414495dd9c2dd91e64", + "0xb15a5c8cba5de080224c274d31c68ed72d2a7126d347796569aef0c4e97ed084afe3da4d4b590b9dda1a07f0c2ff3dfb", + "0x991708fe9650a1f9a4e43938b91d45dc68c230e05ee999c95dbff3bf79b1c1b2bb0e7977de454237c355a73b8438b1d9", + "0xb4f7edc7468b176a4a7c0273700c444fa95c726af6697028bed4f77eee887e3400f9c42ee15b782c0ca861c4c3b8c98a", + "0x8c60dcc16c51087eb477c13e837031d6c6a3dc2b8bf8cb43c23f48006bc7173151807e866ead2234b460c2de93b31956", + "0x83ad63e9c910d1fc44bc114accfb0d4d333b7ebe032f73f62d25d3e172c029d5e34a1c9d547273bf6c0fead5c8801007", + "0x85de73213cc236f00777560756bdbf2b16841ba4b55902cf2cad9742ecaf5d28209b012ceb41f337456dfeca93010cd7", + "0xa7561f8827ccd75b6686ba5398bb8fc3083351c55a589b18984e186820af7e275af04bcd4c28e1dc11be1e8617a0610b", + "0x88c0a4febd4068850557f497ea888035c7fc9f404f6cc7794e7cc8722f048ad2f249e7dc62743e7a339eb7473ad3b0cd", + "0x932b22b1d3e6d5a6409c34980d176feb85ada1bf94332ef5c9fc4d42b907dabea608ceef9b5595ef3feee195151f18d8", + "0xa2867bb3f5ab88fbdae3a16c9143ab8a8f4f476a2643c505bb9f37e5b1fd34d216cab2204c9a017a5a67b7ad2dda10e8", + "0xb573d5f38e4e9e8a3a6fd82f0880dc049efa492a946d00283019bf1d5e5516464cf87039e80aef667cb86fdea5075904", + "0xb948f1b5ab755f3f5f36af27d94f503b070696d793b1240c1bdfd2e8e56890d69e6904688b5f8ff5a4bdf5a6abfe195f", + "0x917eae95ebc4109a2e99ddd8fec7881d2f7aaa0e25fda44dec7ce37458c2ee832f1829db7d2dcfa4ca0f06381c7fe91d", + "0x95751d17ed00a3030bce909333799bb7f4ab641acf585807f355b51d6976dceee410798026a1a004ef4dcdff7ec0f5b8", + "0xb9b7bd266f449a79bbfe075e429613e76c5a42ac61f01c8f0bbbd34669650682efe01ff9dbbc400a1e995616af6aa278", + "0xac1722d097ce9cd7617161f8ec8c23d68f1fb1c9ca533e2a8b4f78516c2fd8fb38f23f834e2b9a03bb06a9d655693ca9", + "0xa7ad9e96ffd98db2ecdb6340c5d592614f3c159abfd832fe27ee9293519d213a578e6246aae51672ee353e3296858873", + "0x989b8814d5de7937c4acafd000eec2b4cd58ba395d7b25f98cafd021e8efa37029b29ad8303a1f6867923f5852a220eb", + "0xa5bfe6282c771bc9e453e964042d44eff4098decacb89aecd3be662ea5b74506e1357ab26f3527110ba377711f3c9f41", + "0x8900a7470b656639721d2abbb7b06af0ac4222ab85a1976386e2a62eb4b88bfb5b72cf7921ddb3cf3a395d7eeb192a2e", + "0x95a71b55cd1f35a438cf5e75f8ff11c5ec6a2ebf2e4dba172f50bfad7d6d5dca5de1b1afc541662c81c858f7604c1163", + "0x82b5d62fea8db8d85c5bc3a76d68dedd25794cf14d4a7bc368938ffca9e09f7e598fdad2a5aac614e0e52f8112ae62b9", + "0x997173f07c729202afcde3028fa7f52cefc90fda2d0c8ac2b58154a5073140683e54c49ed1f254481070d119ce0ce02a", + "0xaeffb91ccc7a72bbd6ffe0f9b99c9e66e67d59cec2e02440465e9636a613ab3017278cfa72ea8bc4aba9a8dc728cb367", + "0x952743b06e8645894aeb6440fc7a5f62dd3acf96dab70a51e20176762c9751ea5f2ba0b9497ccf0114dc4892dc606031", + "0x874c63baeddc56fbbca2ff6031f8634b745f6e34ea6791d7c439201aee8f08ef5ee75f7778700a647f3b21068513fce6", + "0x85128fec9c750c1071edfb15586435cc2f317e3e9a175bb8a9697bcda1eb9375478cf25d01e7fed113483b28f625122d", + "0x85522c9576fd9763e32af8495ae3928ed7116fb70d4378448926bc9790e8a8d08f98cf47648d7da1b6e40d6a210c7924", + "0x97d0f37a13cfb723b848099ca1c14d83e9aaf2f7aeb71829180e664b7968632a08f6a85f557d74b55afe6242f2a36e7c", + "0xabaa472d6ad61a5fccd1a57c01aa1bc081253f95abbcba7f73923f1f11c4e79b904263890eeb66926de3e2652f5d1c70", + "0xb3c04945ba727a141e5e8aec2bf9aa3772b64d8fd0e2a2b07f3a91106a95cbcb249adcd074cbe498caf76fffac20d4ef", + "0x82c46781a3d730d9931bcabd7434a9171372dde57171b6180e5516d4e68db8b23495c8ac3ab96994c17ddb1cf249b9fb", + "0xa202d8b65613c42d01738ccd68ed8c2dbc021631f602d53f751966e04182743ebc8e0747d600b8a8676b1da9ae7f11ab", + "0xae73e7256e9459db04667a899e0d3ea5255211fb486d084e6550b6dd64ca44af6c6b2d59d7aa152de9f96ce9b58d940d", + "0xb67d87b176a9722945ec7593777ee461809861c6cfd1b945dde9ee4ff009ca4f19cf88f4bbb5c80c9cbab2fe25b23ac8", + "0x8f0b7a317a076758b0dac79959ee4a06c08b07d0f10538a4b53d3da2eda16e2af26922feb32c090330dc4d969cf69bd3", + "0x90b36bf56adbd8c4b6cb32febc3a8d5f714370c2ac3305c10fa6d168dffb2a026804517215f9a2d4ec8310cdb6bb459b", + "0xaa80c19b0682ead69934bf18cf476291a0beddd8ef4ed75975d0a472e2ab5c70f119722a8574ae4973aceb733d312e57", + "0xa3fc9abb12574e5c28dcb51750b4339b794b8e558675eef7d26126edf1de920c35e992333bcbffcbf6a5f5c0d383ce62", + "0xa1573ff23ab972acdcd08818853b111fc757fdd35aa070186d3e11e56b172fb49d840bf297ac0dd222e072fc09f26a81", + "0x98306f2be4caa92c2b4392212d0cbf430b409b19ff7d5b899986613bd0e762c909fc01999aa94be3bd529d67f0113d7f", + "0x8c1fc42482a0819074241746d17dc89c0304a2acdae8ed91b5009e9e3e70ff725ba063b4a3e68fdce05b74f5180c545e", + "0xa6c6113ebf72d8cf3163b2b8d7f3fa24303b13f55752522c660a98cd834d85d8c79214d900fa649499365e2e7641f77a", + "0xab95eea424f8a2cfd9fb1c78bb724e5b1d71a0d0d1e4217c5d0f98b0d8bbd3f8400a2002abc0a0e4576d1f93f46fefad", + "0x823c5a4fd8cf4a75fdc71d5f2dd511b6c0f189b82affeacd2b7cfcad8ad1a5551227dcc9bfdb2e34b2097eaa00efbb51", + "0xb97314dfff36d80c46b53d87a61b0e124dc94018a0bb680c32765b9a2d457f833a7c42bbc90b3b1520c33a182580398d", + "0xb17566ee3dcc6bb3b004afe4c0136dfe7dd27df9045ae896dca49fb36987501ae069eb745af81ba3fc19ff037e7b1406", + "0xb0bdc0f55cfd98d331e3a0c4fbb776a131936c3c47c6bffdc3aaf7d8c9fa6803fbc122c2fefbb532e634228687d52174", + "0xaa5d9e60cc9f0598559c28bb9bdd52aa46605ab4ffe3d192ba982398e72cec9a2a44c0d0d938ce69935693cabc0887ea", + "0x802b6459d2354fa1d56c592ac1346c428dadea6b6c0a87bf7d309bab55c94e1cf31dd98a7a86bd92a840dd51f218b91b", + "0xa526914efdc190381bf1a73dd33f392ecf01350b9d3f4ae96b1b1c3d1d064721c7d6eec5788162c933245a3943f5ee51", + "0xb3b8fcf637d8d6628620a1a99dbe619eabb3e5c7ce930d6efd2197e261bf394b74d4e5c26b96c4b8009c7e523ccfd082", + "0x8f7510c732502a93e095aba744535f3928f893f188adc5b16008385fb9e80f695d0435bfc5b91cdad4537e87e9d2551c", + "0x97b90beaa56aa936c3ca45698f79273a68dd3ccd0076eab48d2a4db01782665e63f33c25751c1f2e070f4d1a8525bf96", + "0xb9fb798324b1d1283fdc3e48288e3861a5449b2ab5e884b34ebb8f740225324af86e4711da6b5cc8361c1db15466602f", + "0xb6d52b53cea98f1d1d4c9a759c25bf9d8a50b604b144e4912acbdbdc32aab8b9dbb10d64a29aa33a4f502121a6fb481c", + "0x9174ffff0f2930fc228f0e539f5cfd82c9368d26b074467f39c07a774367ff6cccb5039ac63f107677d77706cd431680", + "0xa33b6250d4ac9e66ec51c063d1a6a31f253eb29bbaed12a0d67e2eccfffb0f3a52750fbf52a1c2aaba8c7692346426e7", + "0xa97025fd5cbcebe8ef865afc39cd3ea707b89d4e765ec817fd021d6438e02fa51e3544b1fd45470c58007a08efac6edd", + "0xb32a78480edd9ff6ba2f1eec4088db5d6ceb2d62d7e59e904ecaef7bb4a2e983a4588e51692b3be76e6ffbc0b5f911a5", + "0xb5ab590ef0bb77191f00495b33d11c53c65a819f7d0c1f9dc4a2caa147a69c77a4fff7366a602d743ee1f395ce934c1e", + "0xb3fb0842f9441fb1d0ee0293b6efbc70a8f58d12d6f769b12872db726b19e16f0f65efbc891cf27a28a248b0ef9c7e75", + "0x9372ad12856fefb928ccb0d34e198df99e2f8973b07e9d417a3134d5f69e12e79ff572c4e03ccd65415d70639bc7c73e", + "0xaa8d6e83d09ce216bfe2009a6b07d0110d98cf305364d5529c170a23e693aabb768b2016befb5ada8dabdd92b4d012bb", + "0xa954a75791eeb0ce41c85200c3763a508ed8214b5945a42c79bfdcfb1ec4f86ad1dd7b2862474a368d4ac31911a2b718", + "0x8e2081cfd1d062fe3ab4dab01f68062bac802795545fede9a188f6c9f802cb5f884e60dbe866710baadbf55dc77c11a4", + "0xa2f06003b9713e7dd5929501ed485436b49d43de80ea5b15170763fd6346badf8da6de8261828913ee0dacd8ff23c0e1", + "0x98eecc34b838e6ffd1931ca65eec27bcdb2fdcb61f33e7e5673a93028c5865e0d1bf6d3bec040c5e96f9bd08089a53a4", + "0x88cc16019741b341060b95498747db4377100d2a5bf0a5f516f7dec71b62bcb6e779de2c269c946d39040e03b3ae12b7", + "0xad1135ccbc3019d5b2faf59a688eef2500697642be8cfbdf211a1ab59abcc1f24483e50d653b55ff1834675ac7b4978f", + "0xa946f05ed9972f71dfde0020bbb086020fa35b482cce8a4cc36dd94355b2d10497d7f2580541bb3e81b71ac8bba3c49f", + "0xa83aeed488f9a19d8cfd743aa9aa1982ab3723560b1cd337fc2f91ad82f07afa412b3993afb845f68d47e91ba4869840", + "0x95eebe006bfc316810cb71da919e5d62c2cebb4ac99d8e8ef67be420302320465f8b69873470982de13a7c2e23516be9", + "0xa55f8961295a11e91d1e5deadc0c06c15dacbfc67f04ccba1d069cba89d72aa3b3d64045579c3ea8991b150ac29366ae", + "0xb321991d12f6ac07a5de3c492841d1a27b0d3446082fbce93e7e1f9e8d8fe3b45d41253556261c21b70f5e189e1a7a6f", + "0xa0b0822f15f652ce7962a4f130104b97bf9529797c13d6bd8e24701c213cc37f18157bd07f3d0f3eae6b7cd1cb40401f", + "0x96e2fa4da378aa782cc2d5e6e465fc9e49b5c805ed01d560e9b98abb5c0de8b74a2e7bec3aa5e2887d25cccb12c66f0c", + "0x97e4ab610d414f9210ed6f35300285eb3ccff5b0b6a95ed33425100d7725e159708ea78704497624ca0a2dcabce3a2f9", + "0x960a375b17bdb325761e01e88a3ea57026b2393e1d887b34b8fa5d2532928079ce88dc9fd06a728b26d2bb41b12b9032", + "0x8328a1647398e832aadc05bd717487a2b6fcdaa0d4850d2c4da230c6a2ed44c3e78ec4837b6094f3813f1ee99414713f", + "0xaa283834ebd18e6c99229ce4b401eda83f01d904f250fedd4e24f1006f8fa0712a6a89a7296a9bf2ce8de30e28d1408e", + "0xb29e097f2caadae3e0f0ae3473c072b0cd0206cf6d2e9b22c1a5ad3e07d433e32bd09ed1f4e4276a2da4268633357b7f", + "0x9539c5cbba14538b2fe077ecf67694ef240da5249950baaabea0340718b882a966f66d97f08556b08a4320ceb2cc2629", + "0xb4529f25e9b42ae8cf8338d2eface6ba5cd4b4d8da73af502d081388135c654c0b3afb3aa779ffc80b8c4c8f4425dd2b", + "0x95be0739c4330619fbe7ee2249c133c91d6c07eab846c18c5d6c85fc21ac5528c5d56dcb0145af68ed0c6a79f68f2ccd", + "0xac0c83ea802227bfc23814a24655c9ff13f729619bcffdb487ccbbf029b8eaee709f8bddb98232ef33cd70e30e45ca47", + "0xb503becb90acc93b1901e939059f93e671900ca52c6f64ae701d11ac891d3a050b505d89324ce267bc43ab8275da6ffe", + "0x98e3811b55b1bacb70aa409100abb1b870f67e6d059475d9f278c751b6e1e2e2d6f2e586c81a9fb6597fda06e7923274", + "0xb0b0f61a44053fa6c715dbb0731e35d48dba257d134f851ee1b81fd49a5c51a90ebf5459ec6e489fce25da4f184fbdb1", + "0xb1d2117fe811720bb997c7c93fe9e4260dc50fca8881b245b5e34f724aaf37ed970cdad4e8fcb68e05ac8cf55a274a53", + "0xa10f502051968f14b02895393271776dee7a06db9de14effa0b3471825ba94c3f805302bdddac4d397d08456f620999d", + "0xa3dbad2ef060ae0bb7b02eaa4a13594f3f900450faa1854fc09620b01ac94ab896321dfb1157cf2374c27e5718e8026a", + "0xb550fdec503195ecb9e079dcdf0cad559d64d3c30818ef369b4907e813e689da316a74ad2422e391b4a8c2a2bef25fc0", + "0xa25ba865e2ac8f28186cea497294c8649a201732ecb4620c4e77b8e887403119910423df061117e5f03fc5ba39042db1", + "0xb3f88174e03fdb443dd6addd01303cf88a4369352520187c739fc5ae6b22fa99629c63c985b4383219dab6acc5f6f532", + "0x97a7503248e31e81b10eb621ba8f5210c537ad11b539c96dfb7cf72b846c7fe81bd7532c5136095652a9618000b7f8d3", + "0xa8bcdc1ce5aa8bfa683a2fc65c1e79de8ff5446695dcb8620f7350c26d2972a23da22889f9e2b1cacb3f688c6a2953dc", + "0x8458c111df2a37f5dd91a9bee6c6f4b79f4f161c93fe78075b24a35f9817da8dde71763218d627917a9f1f0c4709c1ed", + "0xac5f061a0541152b876cbc10640f26f1cc923c9d4ae1b6621e4bb3bf2cec59bbf87363a4eb72fb0e5b6d4e1c269b52d5", + "0xa9a25ca87006e8a9203cbb78a93f50a36694aa4aad468b8d80d3feff9194455ca559fcc63838128a0ab75ad78c07c13a", + "0xa450b85f5dfffa8b34dfd8bc985f921318efacf8857cf7948f93884ba09fb831482ee90a44224b1a41e859e19b74962f", + "0x8ed91e7f92f5c6d7a71708b6132f157ac226ecaf8662af7d7468a4fa25627302efe31e4620ad28719318923e3a59bf82", + "0xab524165fd4c71b1fd395467a14272bd2b568592deafa039d8492e9ef36c6d3f96927c95c72d410a768dc0b6d1fbbc9b", + "0xb662144505aa8432c75ffb8d10318526b6d5777ac7af9ebfad87d9b0866c364f7905a6352743bd8fd79ffd9d5dd4f3e6", + "0xa48f1677550a5cd40663bb3ba8f84caaf8454f332d0ceb1d94dbea52d0412fe69c94997f7749929712fd3995298572f7", + "0x8391cd6e2f6b0c242de1117a612be99776c3dc95cb800b187685ea5bf7e2722275eddb79fd7dfc8be8e389c4524cdf70", + "0x875d3acb9af47833b72900bc0a2448999d638f153c5e97e8a14ec02d0c76f6264353a7e275e1f1a5855daced523d243b", + "0x91f1823657d30b59b2f627880a9a9cb530f5aca28a9fd217fe6f2f5133690dfe7ad5a897872e400512db2e788b3f7628", + "0xad3564332aa56cea84123fc7ca79ea70bb4fef2009fa131cb44e4b15e8613bd11ca1d83b9d9bf456e4b7fee9f2e8b017", + "0x8c530b84001936d5ab366c84c0b105241a26d1fb163669f17c8f2e94776895c2870edf3e1bc8ccd04d5e65531471f695", + "0x932d01fa174fdb0c366f1230cffde2571cc47485f37f23ba5a1825532190cc3b722aeb1f15aed62cf83ccae9403ba713", + "0x88b28c20585aca50d10752e84b901b5c2d58efef5131479fbbe53de7bce2029e1423a494c0298e1497669bd55be97a5d", + "0xb914148ca717721144ebb3d3bf3fcea2cd44c30c5f7051b89d8001502f3856fef30ec167174d5b76265b55d70f8716b5", + "0x81d0173821c6ddd2a068d70766d9103d1ee961c475156e0cbd67d54e668a796310474ef698c7ab55abe6f2cf76c14679", + "0x8f28e8d78e2fe7fa66340c53718e0db4b84823c8cfb159c76eac032a62fb53da0a5d7e24ca656cf9d2a890cb2a216542", + "0x8a26360335c73d1ab51cec3166c3cf23b9ea51e44a0ad631b0b0329ef55aaae555420348a544e18d5760969281759b61", + "0x94f326a32ed287545b0515be9e08149eb0a565025074796d72387cc3a237e87979776410d78339e23ef3172ca43b2544", + "0xa785d2961a2fa5e70bffa137858a92c48fe749fee91b02599a252b0cd50d311991a08efd7fa5e96b78d07e6e66ffe746", + "0x94af9030b5ac792dd1ce517eaadcec1482206848bea4e09e55cc7f40fd64d4c2b3e9197027c5636b70d6122c51d2235d", + "0x9722869f7d1a3992850fe7be405ec93aa17dc4d35e9e257d2e469f46d2c5a59dbd504056c85ab83d541ad8c13e8bcd54", + "0xb13c4088b61a06e2c03ac9813a75ff1f68ffdfee9df6a8f65095179a475e29cc49119cad2ce05862c3b1ac217f3aace9", + "0x8c64d51774753623666b10ca1b0fe63ae42f82ed6aa26b81dc1d48c86937c5772eb1402624c52a154b86031854e1fb9f", + "0xb47e4df18002b7dac3fee945bf9c0503159e1b8aafcce2138818e140753011b6d09ef1b20894e08ba3006b093559061b", + "0x93cb5970076522c5a0483693f6a35ffd4ea2aa7aaf3730c4eccd6af6d1bebfc1122fc4c67d53898ae13eb6db647be7e2", + "0xa68873ef80986795ea5ed1a597d1cd99ed978ec25e0abb57fdcc96e89ef0f50aeb779ff46e3dce21dc83ada3157a8498", + "0x8cab67f50949cc8eee6710e27358aea373aae3c92849f8f0b5531c080a6300cdf2c2094fe6fecfef6148de0d28446919", + "0x993e932bcb616dbaa7ad18a4439e0565211d31071ef1b85a0627db74a05d978c60d507695eaeea5c7bd9868a21d06923", + "0xacdadff26e3132d9478a818ef770e9fa0d2b56c6f5f48bd3bd674436ccce9bdfc34db884a73a30c04c5f5e9764cb2218", + "0xa0d3e64c9c71f84c0eef9d7a9cb4fa184224b969db5514d678e93e00f98b41595588ca802643ea225512a4a272f5f534", + "0x91c9140c9e1ba6e330cb08f6b2ce4809cd0d5a0f0516f70032bf30e912b0ed684d07b413b326ab531ee7e5b4668c799b", + "0x87bc2ee7a0c21ba8334cd098e35cb703f9af57f35e091b8151b9b63c3a5b0f89bd7701dbd44f644ea475901fa6d9ef08", + "0x9325ccbf64bf5d71b303e31ee85d486298f9802c5e55b2c3d75427097bf8f60fa2ab4fcaffa9b60bf922c3e24fbd4b19", + "0x95d0506e898318f3dc8d28d16dfd9f0038b54798838b3c9be2a2ae3c2bf204eb496166353fc042220b0bd4f6673b9285", + "0x811de529416331fe9c416726d45df9434c29dcd7e949045eb15740f47e97dde8f31489242200e19922cac2a8b7c6fd1f", + "0xade632d04a4c8bbab6ca7df370b2213cb9225023e7973f0e29f4f5e52e8aeaabc65171306bbdd12a67b195dfbb96d48f", + "0x88b7f029e079b6ae956042c0ea75d53088c5d0efd750dd018adaeacf46be21bf990897c58578c491f41afd3978d08073", + "0x91f477802de507ffd2be3f4319903119225b277ad24f74eb50f28b66c14d32fae53c7edb8c7590704741af7f7f3e3654", + "0x809838b32bb4f4d0237e98108320d4b079ee16ed80c567e7548bd37e4d7915b1192880f4812ac0e00476d246aec1dbc8", + "0x84183b5fc4a7997a8ae5afedb4d21dce69c480d5966b5cbdafd6dd10d29a9a6377f3b90ce44da0eb8b176ac3af0253bb", + "0x8508abbf6d3739a16b9165caf0f95afb3b3ac1b8c38d6d374cf0c91296e2c1809a99772492b539cda184510bce8a0271", + "0x8722054e59bab2062e6419a6e45fc803af77fde912ef2cd23055ad0484963de65a816a2debe1693d93c18218d2b8e81a", + "0x8e895f80e485a7c4f56827bf53d34b956281cdc74856c21eb3b51f6288c01cc3d08565a11cc6f3e2604775885490e8c5", + "0xafc92714771b7aa6e60f3aee12efd9c2595e9659797452f0c1e99519f67c8bc3ac567119c1ddfe82a3e961ee9defea9a", + "0x818ff0fd9cefd32db87b259e5fa32967201016fc02ef44116cdca3c63ce5e637756f60477a408709928444a8ad69c471", + "0x8251e29af4c61ae806fc5d032347fb332a94d472038149225298389495139ce5678fae739d02dfe53a231598a992e728", + "0xa0ea39574b26643f6f1f48f99f276a8a64b5481989cfb2936f9432a3f8ef5075abfe5c067dc5512143ce8bf933984097", + "0xaf67a73911b372bf04e57e21f289fc6c3dfac366c6a01409b6e76fea4769bdb07a6940e52e8d7d3078f235c6d2f632c6", + "0xb5291484ef336024dd2b9b4cf4d3a6b751133a40656d0a0825bcc6d41c21b1c79cb50b0e8f4693f90c29c8f4358641f9", + "0x8bc0d9754d70f2cb9c63f991902165a87c6535a763d5eece43143b5064ae0bcdce7c7a8f398f2c1c29167b2d5a3e6867", + "0x8d7faff53579ec8f6c92f661c399614cc35276971752ce0623270f88be937c414eddcb0997e14724a783905a026c8883", + "0x9310b5f6e675fdf60796f814dbaa5a6e7e9029a61c395761e330d9348a7efab992e4e115c8be3a43d08e90d21290c892", + "0xb5eb4f3eb646038ad2a020f0a42202532d4932e766da82b2c1002bf9c9c2e5336b54c8c0ffcc0e02d19dde2e6a35b6cc", + "0x91dabfd30a66710f1f37a891136c9be1e23af4abf8cb751f512a40c022a35f8e0a4fb05b17ec36d4208de02d56f0d53a", + "0xb3ded14e82d62ac7a5a036122a62f00ff8308498f3feae57d861babaff5a6628d43f0a0c5fc903f10936bcf4e2758ceb", + "0xa88e8348fed2b26acca6784d19ef27c75963450d99651d11a950ea81d4b93acd2c43e0ecce100eaf7e78508263d5baf3", + "0xb1f5bbf7c4756877b87bb42163ac570e08c6667c4528bf68b5976680e19beeff7c5effd17009b0718797077e2955457a", + "0xad2e7b516243f915d4d1415326e98b1a7390ae88897d0b03b66c2d9bd8c3fba283d7e8fe44ed3333296a736454cef6d8", + "0x8f82eae096d5b11f995de6724a9af895f5e1c58d593845ad16ce8fcae8507e0d8e2b2348a0f50a1f66a17fd6fac51a5c", + "0x890e4404d0657c6c1ee14e1aac132ecf7a568bb3e04137b85ac0f84f1d333bd94993e8750f88eee033a33fb00f85dcc7", + "0x82ac7d3385e035115f1d39a99fc73e5919de44f5e6424579776d118d711c8120b8e5916372c6f27bed4cc64cac170b6c", + "0x85ee16d8901c272cfbbe966e724b7a891c1bd5e68efd5d863043ad8520fc409080af61fd726adc680b3f1186fe0ac8b8", + "0x86dc564c9b545567483b43a38f24c41c6551a49cabeebb58ce86404662a12dbfafd0778d30d26e1c93ce222e547e3898", + "0xa29f5b4522db26d88f5f95f18d459f8feefab02e380c2edb65aa0617a82a3c1a89474727a951cef5f15050bcf7b380fb", + "0xa1ce039c8f6cac53352899edb0e3a72c76da143564ad1a44858bd7ee88552e2fe6858d1593bbd74aeee5a6f8034b9b9d", + "0x97f10d77983f088286bd7ef3e7fdd8fa275a56bec19919adf33cf939a90c8f2967d2b1b6fc51195cb45ad561202a3ed7", + "0xa25e2772e8c911aaf8712bdac1dd40ee061c84d3d224c466cfaae8e5c99604053f940cde259bd1c3b8b69595781dbfec", + "0xb31bb95a0388595149409c48781174c340960d59032ab2b47689911d03c68f77a2273576fbe0c2bf4553e330656058c7", + "0xb8b2e9287ad803fb185a13f0d7456b397d4e3c8ad5078f57f49e8beb2e85f661356a3392dbd7bcf6a900baa5582b86a1", + "0xa3d0893923455eb6e96cc414341cac33d2dbc88fba821ac672708cce131761d85a0e08286663a32828244febfcae6451", + "0x82310cb42f647d99a136014a9f881eb0b9791efd2e01fc1841907ad3fc8a9654d3d1dab6689c3607214b4dc2aca01cee", + "0x874022d99c16f60c22de1b094532a0bc6d4de700ad01a31798fac1d5088b9a42ad02bef8a7339af7ed9c0d4f16b186ee", + "0x94981369e120265aed40910eebc37eded481e90f4596b8d57c3bec790ab7f929784bd33ddd05b7870aad6c02e869603b", + "0xa4f1f50e1e2a73f07095e0dd31cb45154f24968dae967e38962341c1241bcd473102fff1ff668b20c6547e9732d11701", + "0xae2328f3b0ad79fcda807e69a1b5278145225083f150f67511dafc97e079f860c3392675f1752ae7e864c056e592205b", + "0x875d8c971e593ca79552c43d55c8c73b17cd20c81ff2c2fed1eb19b1b91e4a3a83d32df150dbfd5db1092d0aebde1e1f", + "0xadd2e80aa46aae95da73a11f130f4bda339db028e24c9b11e5316e75ba5e63bc991d2a1da172c7c8e8fee038baae3433", + "0xb46dbe1cb3424002aa7de51e82f600852248e251465c440695d52538d3f36828ff46c90ed77fc1d11534fe3c487df8ef", + "0xa5e5045d28b4e83d0055863c30c056628c58d4657e6176fd0536f5933f723d60e851bb726d5bf3c546b8ce4ac4a57ef8", + "0x91fec01e86dd1537e498fff7536ea3ca012058b145f29d9ada49370cd7b7193ac380e116989515df1b94b74a55c45df3", + "0xa7428176d6918cd916a310bdc75483c72de660df48cac4e6e7478eef03205f1827ea55afc0df5d5fa7567d14bbea7fc9", + "0x851d89bef45d9761fe5fdb62972209335193610015e16a675149519f9911373bac0919add226ef118d9f3669cfdf4734", + "0xb74acf5c149d0042021cb2422ea022be4c4f72a77855f42393e71ffd12ebb3eec16bdf16f812159b67b79a9706e7156d", + "0x99f35dce64ec99aa595e7894b55ce7b5a435851b396e79036ffb249c28206087db4c85379df666c4d95857db02e21ff9", + "0xb6b9a384f70db9e298415b8ab394ee625dafff04be2886476e59df8d052ca832d11ac68a9b93fba7ab055b7bc36948a4", + "0x898ee4aefa923ffec9e79f2219c7389663eb11eb5b49014e04ed4a336399f6ea1691051d86991f4c46ca65bcd4fdf359", + "0xb0f948217b0d65df7599a0ba4654a5e43c84db477936276e6f11c8981efc6eaf14c90d3650107ed4c09af4cc8ec11137", + "0xaa6286e27ac54f73e63dbf6f41865dd94d24bc0cf732262fcaff67319d162bb43af909f6f8ee27b1971939cfbba08141", + "0x8bca7cdf730cf56c7b2c8a2c4879d61361a6e1dba5a3681a1a16c17a56e168ace0e99cf0d15826a1f5e67e6b8a8a049a", + "0xa746d876e8b1ce225fcafca603b099b36504846961526589af977a88c60d31ba2cc56e66a3dec8a77b3f3531bf7524c9", + "0xa11e2e1927e6704cdb8874c75e4f1842cef84d7d43d7a38e339e61dc8ba90e61bbb20dd3c12e0b11d2471d58eed245be", + "0xa36395e22bc1d1ba8b0459a235203177737397da5643ce54ded3459d0869ff6d8d89f50c73cb62394bf66a959cde9b90", + "0x8b49f12ba2fdf9aca7e5f81d45c07d47f9302a2655610e7634d1e4bd16048381a45ef2c95a8dd5b0715e4b7cf42273af", + "0x91cffa2a17e64eb7f76bccbe4e87280ee1dd244e04a3c9eac12e15d2d04845d876eb24fe2ec6d6d266cce9efb281077f", + "0xa6b8afabf65f2dee01788114e33a2f3ce25376fb47a50b74da7c3c25ff1fdc8aa9f41307534abbf48acb6f7466068f69", + "0x8d13db896ccfea403bd6441191995c1a65365cab7d0b97fbe9526da3f45a877bd1f4ef2edef160e8a56838cd1586330e", + "0x98c717de9e01bef8842c162a5e757fe8552d53269c84862f4d451e7c656ae6f2ae473767b04290b134773f63be6fdb9d", + "0x8c2036ace1920bd13cf018e82848c49eb511fad65fd0ff51f4e4b50cf3bfc294afb63cba682c16f52fb595a98fa84970", + "0xa3520fdff05dbad9e12551b0896922e375f9e5589368bcb2cc303bde252743b74460cb5caf99629325d3620f13adc796", + "0x8d4f83a5bfec05caf5910e0ce538ee9816ee18d0bd44c1d0da2a87715a23cd2733ad4d47552c6dc0eb397687d611dd19", + "0xa7b39a0a6a02823452d376533f39d35029867b3c9a6ad6bca181f18c54132d675613a700f9db2440fb1b4fa13c8bf18a", + "0x80bcb114b2544b80f404a200fc36860ed5e1ad31fe551acd4661d09730c452831751baa9b19d7d311600d267086a70bc", + "0x90dcce03c6f88fc2b08f2b42771eedde90cc5330fe0336e46c1a7d1b5a6c1641e5fcc4e7b3d5db00bd8afca9ec66ed81", + "0xaec15f40805065c98e2965b1ae12a6c9020cfdb094c2d0549acfc7ea2401a5fb48d3ea7d41133cf37c4e096e7ff53eb9", + "0x80e129b735dba49fa627a615d6c273119acec8e219b2f2c4373a332b5f98d66cbbdd688dfbe72a8f8bfefaccc02c50c1", + "0xa9b596da3bdfe23e6799ece5f7975bf7a1979a75f4f546deeaf8b34dfe3e0d623217cb4cf4ccd504cfa3625b88cd53f1", + "0xabcbbb70b16f6e517c0ab4363ab76b46e4ff58576b5f8340e5c0e8cc0e02621b6e23d742d73b015822a238b17cfd7665", + "0xa046937cc6ea6a2e1adae543353a9fe929c1ae4ad655be1cc051378482cf88b041e28b1e9a577e6ccff2d3570f55e200", + "0x831279437282f315e65a60184ef158f0a3dddc15a648dc552bdc88b3e6fe8288d3cfe9f0031846d81350f5e7874b4b33", + "0x993d7916fa213c6d66e7c4cafafc1eaec9a2a86981f91c31eb8a69c5df076c789cbf498a24c84e0ee77af95b42145026", + "0x823907a3b6719f8d49b3a4b7c181bd9bb29fcf842d7c70660c4f351852a1e197ca46cf5e879b47fa55f616fa2b87ce5e", + "0x8d228244e26132b234930ee14c75d88df0943cdb9c276a8faf167d259b7efc1beec2a87c112a6c608ad1600a239e9aae", + "0xab6e55766e5bfb0cf0764ed909a8473ab5047d3388b4f46faeba2d1425c4754c55c6daf6ad4751e634c618b53e549529", + "0xab0cab6860e55a84c5ad2948a7e0989e2b4b1fd637605634b118361497332df32d9549cb854b2327ca54f2bcb85eed8f", + "0xb086b349ae03ef34f4b25a57bcaa5d1b29bd94f9ebf87e22be475adfe475c51a1230c1ebe13506cb72c4186192451658", + "0x8a0b49d8a254ca6d91500f449cbbfbb69bb516c6948ac06808c65595e46773e346f97a5ce0ef7e5a5e0de278af22709c", + "0xac49de11edaaf04302c73c578cc0824bdd165c0d6321be1c421c1950e68e4f3589aa3995448c9699e93c6ebae8803e27", + "0x884f02d841cb5d8f4c60d1402469216b114ab4e93550b5bc1431756e365c4f870a9853449285384a6fa49e12ce6dc654", + "0xb75f3a28fa2cc8d36b49130cb7448a23d73a7311d0185ba803ad55c8219741d451c110f48b786e96c728bc525903a54f", + "0x80ae04dbd41f4a35e33f9de413b6ad518af0919e5a30cb0fa1b061b260420780bb674f828d37fd3b52b5a31673cbd803", + "0xb9a8011eb5fcea766907029bf743b45262db3e49d24f84503687e838651ed11cb64c66281e20a0ae9f6aa51acc552263", + "0x90bfdd75e2dc9cf013e22a5d55d2d2b8a754c96103a17524488e01206e67f8b6d52b1be8c4e3d5307d4fe06d0e51f54c", + "0xb4af353a19b06203a815ec43e79a88578cc678c46f5a954b85bc5c53b84059dddba731f3d463c23bfd5273885c7c56a4", + "0xaa125e96d4553b64f7140e5453ff5d2330318b69d74d37d283e84c26ad672fa00e3f71e530eb7e28be1e94afb9c4612e", + "0xa18e060aee3d49cde2389b10888696436bb7949a79ca7d728be6456a356ea5541b55492b2138da90108bd1ce0e6f5524", + "0x93e55f92bdbccc2de655d14b1526836ea2e52dba65eb3f87823dd458a4cb5079bf22ce6ef625cb6d6bfdd0995ab9a874", + "0x89f5a683526b90c1c3ceebbb8dc824b21cff851ce3531b164f6626e326d98b27d3e1d50982e507d84a99b1e04e86a915", + "0x83d1c38800361633a3f742b1cb2bfc528129496e80232611682ddbe403e92c2ac5373aea0bca93ecb5128b0b2b7a719e", + "0x8ecba560ac94905e19ce8d9c7af217bf0a145d8c8bd38e2db82f5e94cc3f2f26f55819176376b51f154b4aab22056059", + "0xa7e2a4a002b60291924850642e703232994acb4cfb90f07c94d1e0ecd2257bb583443283c20fc6017c37e6bfe85b7366", + "0x93ed7316fa50b528f1636fc6507683a672f4f4403e55e94663f91221cc198199595bd02eef43d609f451acc9d9b36a24", + "0xa1220a8ebc5c50ceed76a74bc3b7e0aa77f6884c71b64b67c4310ac29ce5526cb8992d6abc13ef6c8413ce62486a6795", + "0xb2f6eac5c869ad7f4a25161d3347093e2f70e66cd925032747e901189355022fab3038bca4d610d2f68feb7e719c110b", + "0xb703fa11a4d511ca01c7462979a94acb40b5d933759199af42670eb48f83df202fa0c943f6ab3b4e1cc54673ea3aab1e", + "0xb5422912afbfcb901f84791b04f1ddb3c3fbdc76d961ee2a00c5c320e06d3cc5b5909c3bb805df66c5f10c47a292b13d", + "0xad0934368da823302e1ac08e3ede74b05dfdbfffca203e97ffb0282c226814b65c142e6e15ec1e754518f221f01b30f7", + "0xa1dd302a02e37df15bf2f1147efe0e3c06933a5a767d2d030e1132f5c3ce6b98e216b6145eb39e1e2f74e76a83165b8d", + "0xa346aab07564432f802ae44738049a36f7ca4056df2d8f110dbe7fef4a3e047684dea609b2d03dc6bf917c9c2a47608f", + "0xb96c5f682a5f5d02123568e50f5d0d186e4b2c4c9b956ec7aabac1b3e4a766d78d19bd111adb5176b898e916e49be2aa", + "0x8a96676d56876fc85538db2e806e1cba20fd01aeb9fa3cb43ca6ca94a2c102639f65660db330e5d74a029bb72d6a0b39", + "0xab0048336bd5c3def1a4064eadd49e66480c1f2abb4df46e03afbd8a3342c2c9d74ee35d79f08f4768c1646681440984", + "0x888427bdf76caec90814c57ee1c3210a97d107dd88f7256f14f883ad0f392334b82be11e36dd8bfec2b37935177c7831", + "0xb622b282becf0094a1916fa658429a5292ba30fb48a4c8066ce1ddcefb71037948262a01c95bab6929ed3a76ba5db9fe", + "0xb5b9e005c1f456b6a368a3097634fb455723abe95433a186e8278dceb79d4ca2fbe21f8002e80027b3c531e5bf494629", + "0xa3c6707117a1e48697ed41062897f55d8119403eea6c2ee88f60180f6526f45172664bfee96bf61d6ec0b7fbae6aa058", + "0xb02a9567386a4fbbdb772d8a27057b0be210447348efe6feb935ceec81f361ed2c0c211e54787dc617cdffed6b4a6652", + "0xa9b8364e40ef15c3b5902e5534998997b8493064fa2bea99600def58279bb0f64574c09ba11e9f6f669a8354dd79dc85", + "0x9998a2e553a9aa9a206518fae2bc8b90329ee59ab23005b10972712389f2ec0ee746033c733092ffe43d73d33abbb8ef", + "0x843a4b34d9039bf79df96d79f2d15e8d755affb4d83d61872daf540b68c0a3888cf8fc00d5b8b247b38524bcb3b5a856", + "0x84f7128920c1b0bb40eee95701d30e6fc3a83b7bb3709f16d97e72acbb6057004ee7ac8e8f575936ca9dcb7866ab45f7", + "0x918d3e2222e10e05edb34728162a899ad5ada0aaa491aeb7c81572a9c0d506e31d5390e1803a91ff3bd8e2bb15d47f31", + "0x9442d18e2489613a7d47bb1cb803c8d6f3259d088cd079460976d87f7905ee07dea8f371b2537f6e1d792d36d7e42723", + "0xb491976970fe091995b2ed86d629126523ccf3e9daf8145302faca71b5a71a5da92e0e05b62d7139d3efac5c4e367584", + "0xaa628006235dc77c14cef4c04a308d66b07ac92d377df3de1a2e6ecfe3144f2219ad6d7795e671e1cb37a3641910b940", + "0x99d386adaea5d4981d7306feecac9a555b74ffdc218c907c5aa7ac04abaead0ec2a8237300d42a3fbc464673e417ceed", + "0x8f78e8b1556f9d739648ea3cab9606f8328b52877fe72f9305545a73b74d49884044ba9c1f1c6db7d9b7c7b7c661caba", + "0x8fb357ae49932d0babdf74fc7aa7464a65d3b6a2b3acf4f550b99601d3c0215900cfd67f2b6651ef94cfc323bac79fae", + "0x9906f2fa25c0290775aa001fb6198113d53804262454ae8b83ef371b5271bde189c0460a645829cb6c59f9ee3a55ce4d", + "0x8f4379b3ebb50e052325b27655ca6a82e6f00b87bf0d2b680d205dd2c7afdc9ff32a9047ae71a1cdf0d0ce6b9474d878", + "0xa85534e88c2bd43c043792eaa75e50914b21741a566635e0e107ae857aed0412035f7576cf04488ade16fd3f35fdbb87", + "0xb4ce93199966d3c23251ca7f28ec5af7efea1763d376b0385352ffb2e0a462ef95c69940950278cf0e3dafd638b7bd36", + "0xb10cb3d0317dd570aa73129f4acf63c256816f007607c19b423fb42f65133ce21f2f517e0afb41a5378cccf893ae14d0", + "0xa9b231c9f739f7f914e5d943ed9bff7eba9e2c333fbd7c34eb1648a362ee01a01af6e2f7c35c9fe962b11152cddf35de", + "0x99ff6a899e156732937fb81c0cced80ae13d2d44c40ba99ac183aa246103b31ec084594b1b7feb96da58f4be2dd5c0ed", + "0x8748d15d18b75ff2596f50d6a9c4ce82f61ecbcee123a6ceae0e43cab3012a29b6f83cf67b48c22f6f9d757c6caf76b2", + "0xb88ab05e4248b7fb634cf640a4e6a945d13e331237410f7217d3d17e3e384ddd48897e7a91e4516f1b9cbd30f35f238b", + "0x8d826deaeeb84a3b2d2c04c2300ca592501f992810582d6ae993e0d52f6283a839dba66c6c72278cff5871802b71173b", + "0xb36fed027c2f05a5ef625ca00b0364b930901e9e4420975b111858d0941f60e205546474bb25d6bfa6928d37305ae95f", + "0xaf2fcfc6b87967567e8b8a13a4ed914478185705724e56ce68fb2df6d1576a0cf34a61e880997a0d35dc2c3276ff7501", + "0xac351b919cd1fbf106feb8af2c67692bfcddc84762d18cea681cfa7470a5644839caace27efee5f38c87d3df306f4211", + "0x8d6665fb1d4d8d1fa23bd9b8a86e043b8555663519caac214d1e3e3effbc6bee7f2bcf21e645f77de0ced279d69a8a8b", + "0xa9fc1c2061756b2a1a169c1b149f212ff7f0d2488acd1c5a0197eba793cffa593fc6d1d1b40718aa75ca3ec77eff10e1", + "0xaff64f0fa009c7a6cf0b8d7a22ddb2c8170c3cb3eec082e60d5aadb00b0040443be8936d728d99581e33c22178c41c87", + "0x82e0b181adc5e3b1c87ff8598447260e839d53debfae941ebea38265575546c3a74a14b4325a030833a62ff6c52d9365", + "0xb7ad43cbb22f6f892c2a1548a41dc120ab1f4e1b8dea0cb6272dd9cb02054c542ecabc582f7e16de709d48f5166cae86", + "0x985e0c61094281532c4afb788ecb2dfcba998e974b5d4257a22040a161883908cdd068fe80f8eb49b8953cfd11acf43a", + "0xae46895c6d67ea6d469b6c9c07b9e5d295d9ae73b22e30da4ba2c973ba83a130d7eef39717ec9d0f36e81d56bf742671", + "0x8600177ea1f7e7ef90514b38b219a37dedfc39cb83297e4c7a5b479817ef56479d48cf6314820960c751183f6edf8b0e", + "0xb9208ec1c1d7a1e99b59c62d3e4e61dfb706b0e940d09d3abfc3454c19749083260614d89cfd7e822596c3cdbcc6bb95", + "0xa1e94042c796c2b48bc724352d2e9f3a22291d9a34705993357ddb6adabd76da6fc25dac200a8cb0b5bbd99ecddb7af6", + "0xb29c3adedd0bcad8a930625bc4dfdc3552a9afd5ca6dd9c0d758f978068c7982b50b711aa0eb5b97f2b84ee784637835", + "0xaf0632a238bb1f413c7ea8e9b4c3d68f2827bd2e38cd56024391fba6446ac5d19a780d0cfd4a78fe497d537b766a591a", + "0xaaf6e7f7d54f8ef5e2e45dd59774ecbeecf8683aa70483b2a75be6a6071b5981bbaf1627512a65d212817acdfab2e428", + "0x8c751496065da2e927cf492aa5ca9013b24f861d5e6c24b30bbf52ec5aaf1905f40f9a28175faef283dd4ed4f2182a09", + "0x8952377d8e80a85cf67d6b45499f3bad5fd452ea7bcd99efc1b066c4720d8e5bff1214cea90fd1f972a7f0baac3d29be", + "0xa1946ee543d1a6e21f380453be4d446e4130950c5fc3d075794eb8260f6f52d0a795c1ff91d028a648dc1ce7d9ab6b47", + "0x89f3fefe37af31e0c17533d2ca1ce0884cc1dc97c15cbfab9c331b8debd94781c9396abef4bb2f163d09277a08d6adf0", + "0xa2753f1e6e1a154fb117100a5bd9052137add85961f8158830ac20541ab12227d83887d10acf7fd36dcaf7c2596d8d23", + "0x814955b4198933ee11c3883863b06ff98c7eceb21fc3e09df5f916107827ccf3323141983e74b025f46ae00284c9513b", + "0x8cc5c6bb429073bfef47cae7b3bfccb0ffa076514d91a1862c6bda4d581e0df87db53cc6c130bf8a7826304960f5a34e", + "0x909f22c1f1cdc87f7be7439c831a73484a49acbf8f23d47087d7cf867c64ef61da3bde85dc57d705682b4c3fc710d36e", + "0x8048fee7f276fcd504aed91284f28e73693615e0eb3858fa44bcf79d7285a9001c373b3ef71d9a3054817ba293ebe28c", + "0x94400e5cf5d2700ca608c5fe35ce14623f71cc24959f2bc27ca3684092850f76b67fb1f07ca9e5b2ca3062cf8ad17bd4", + "0x81c2ae7d4d1b17f8b6de6a0430acc0d58260993980fe48dc2129c4948269cdc74f9dbfbf9c26b19360823fd913083d48", + "0x8c41fe765128e63f6889d6a979f6a4342300327c8b245a8cfe3ecfbcac1e09c3da30e2a1045b24b78efc6d6d50c8c6ac", + "0xa5dd4ae51ae48c8be4b218c312ade226cffce671cf121cb77810f6c0990768d6dd767badecb5c69921d5574d5e8433d3", + "0xb7642e325f4ba97ae2a39c1c9d97b35aafd49d53dba36aed3f3cb0ca816480b3394079f46a48252d46596559c90f4d58", + "0xae87375b40f35519e7bd4b1b2f73cd0b329b0c2cb9d616629342a71c6c304338445eda069b78ea0fbe44087f3de91e09", + "0xb08918cb6f736855e11d3daca1ddfbdd61c9589b203b5493143227bf48e2c77c2e8c94b0d1aa2fab2226e0eae83f2681", + "0xac36b84a4ac2ebd4d6591923a449c564e3be8a664c46092c09e875c2998eba16b5d32bfd0882fd3851762868e669f0b1", + "0xa44800a3bb192066fa17a3f29029a23697240467053b5aa49b9839fb9b9b8b12bcdcbfc557f024b61f4f51a9aacdefcb", + "0x9064c688fec23441a274cdf2075e5a449caf5c7363cc5e8a5dc9747183d2e00a0c69f2e6b3f6a7057079c46014c93b3b", + "0xaa367b021469af9f5b764a79bb3afbe2d87fe1e51862221672d1a66f954b165778b7c27a705e0f93841fab4c8468344d", + "0xa1a8bfc593d4ab71f91640bc824de5c1380ab2591cfdafcbc78a14b32de3c0e15f9d1b461d85c504baa3d4232c16bb53", + "0x97df48da1799430f528184d30b6baa90c2a2f88f34cdfb342d715339c5ebd6d019aa693cea7c4993daafc9849063a3aa", + "0xabd923831fbb427e06e0dd335253178a9e5791395c84d0ab1433c07c53c1209161097e9582fb8736f8a60bde62d8693e", + "0x84cd1a43f1a438b43dc60ffc775f646937c4f6871438163905a3cebf1115f814ccd38a6ccb134130bff226306e412f32", + "0x91426065996b0743c5f689eb3ca68a9f7b9e4d01f6c5a2652b57fa9a03d8dc7cd4bdbdab0ca5a891fee1e97a7f00cf02", + "0xa4bee50249db3df7fd75162b28f04e57c678ba142ce4d3def2bc17bcb29e4670284a45f218dad3969af466c62a903757", + "0x83141ebcc94d4681404e8b67a12a46374fded6df92b506aff3490d875919631408b369823a08b271d006d5b93136f317", + "0xa0ea1c8883d58d5a784da3d8c8a880061adea796d7505c1f903d07c287c5467f71e4563fc0faafbc15b5a5538b0a7559", + "0x89d9d480574f201a87269d26fb114278ed2c446328df431dc3556e3500e80e4cd01fcac196a2459d8646361ebda840df", + "0x8bf302978973632dd464bec819bdb91304712a3ec859be071e662040620422c6e75eba6f864f764cffa2799272efec39", + "0x922f666bc0fd58b6d7d815c0ae4f66d193d32fc8382c631037f59eeaeae9a8ca6c72d08e72944cf9e800b8d639094e77", + "0x81ad8714f491cdff7fe4399f2eb20e32650cff2999dd45b9b3d996d54a4aba24cc6c451212e78c9e5550368a1a38fb3f", + "0xb58fcf4659d73edb73175bd9139d18254e94c3e32031b5d4b026f2ed37aa19dca17ec2eb54c14340231615277a9d347e", + "0xb365ac9c2bfe409b710928c646ea2fb15b28557e0f089d39878e365589b9d1c34baf5566d20bb28b33bb60fa133f6eff", + "0x8fcae1d75b53ab470be805f39630d204853ca1629a14158bac2f52632277d77458dec204ff84b7b2d77e641c2045be65", + "0xa03efa6bebe84f4f958a56e2d76b5ba4f95dd9ed7eb479edc7cc5e646c8d4792e5b0dfc66cc86aa4b4afe2f7a4850760", + "0xaf1c823930a3638975fb0cc5c59651771b2719119c3cd08404fbd4ce77a74d708cefbe3c56ea08c48f5f10e6907f338f", + "0x8260c8299b17898032c761c325ac9cabb4c5b7e735de81eacf244f647a45fb385012f4f8df743128888c29aefcaaad16", + "0xab2f37a573c82e96a8d46198691cd694dfa860615625f477e41f91b879bc58a745784fccd8ffa13065834ffd150d881d", + "0x986c746c9b4249352d8e5c629e8d7d05e716b3c7aab5e529ca969dd1e984a14b5be41528baef4c85d2369a42d7209216", + "0xb25e32da1a8adddf2a6080725818b75bc67240728ad1853d90738485d8924ea1e202df0a3034a60ffae6f965ec55cf63", + "0xa266e627afcebcefea6b6b44cbc50f5c508f7187e87d047b0450871c2a030042c9e376f3ede0afcf9d1952f089582f71", + "0x86c3bbca4c0300606071c0a80dbdec21ce1dd4d8d4309648151c420854032dff1241a1677d1cd5de4e4de4385efda986", + "0xb9a21a1fe2d1f3273a8e4a9185abf2ff86448cc98bfa435e3d68306a2b8b4a6a3ea33a155be3cb62a2170a86f77679a5", + "0xb117b1ea381adce87d8b342cba3a15d492ff2d644afa28f22424cb9cbc820d4f7693dfc1a4d1b3697046c300e1c9b4c8", + "0x9004c425a2e68870d6c69b658c344e3aa3a86a8914ee08d72b2f95c2e2d8a4c7bb0c6e7e271460c0e637cec11117bf8e", + "0x86a18aa4783b9ebd9131580c8b17994825f27f4ac427b0929a1e0236907732a1c8139e98112c605488ee95f48bbefbfc", + "0x84042243b955286482ab6f0b5df4c2d73571ada00716d2f737ca05a0d2e88c6349e8ee9e67934cfee4a1775dbf7f4800", + "0x92c2153a4733a62e4e1d5b60369f3c26777c7d01cd3c8679212660d572bd3bac9b8a8a64e1f10f7dbf5eaa7579c4e423", + "0x918454b6bb8e44a2afa144695ba8d48ae08d0cdfef4ad078f67709eddf3bb31191e8b006f04e82ea45a54715ef4d5817", + "0xacf0b54f6bf34cf6ed6c2b39cf43194a40d68de6bcf1e4b82c34c15a1343e9ac3737885e1a30b78d01fa3a5125463db8", + "0xa7d60dbe4b6a7b054f7afe9ee5cbbfeca0d05dc619e6041fa2296b549322529faddb8a11e949562309aecefb842ac380", + "0x91ffb53e6d7e5f11159eaf13e783d6dbdfdb1698ed1e6dbf3413c6ea23492bbb9e0932230a9e2caac8fe899a17682795", + "0xb6e8d7be5076ee3565d5765a710c5ecf17921dd3cf555c375d01e958a365ae087d4a88da492a5fb81838b7b92bf01143", + "0xa8c6b763de2d4b2ed42102ef64eccfef31e2fb2a8a2776241c82912fa50fc9f77f175b6d109a97ede331307c016a4b1a", + "0x99839f86cb700c297c58bc33e28d46b92931961548deac29ba8df91d3e11721b10ea956c8e16984f9e4acf1298a79b37", + "0x8c2e2c338f25ea5c25756b7131cde0d9a2b35abf5d90781180a00fe4b8e64e62590dc63fe10a57fba3a31c76d784eb01", + "0x9687d7df2f41319ca5469d91978fed0565a5f11f829ebadaa83db92b221755f76c6eacd7700735e75c91e257087512e3", + "0x8795fdfb7ff8439c58b9bf58ed53873d2780d3939b902b9ddaaa4c99447224ced9206c3039a23c2c44bcc461e2bb637f", + "0xa803697b744d2d087f4e2307218d48fa88620cf25529db9ce71e2e3bbcc65bac5e8bb9be04777ef7bfb5ed1a5b8e6170", + "0x80f3d3efbbb9346ddd413f0a8e36b269eb5d7ff6809d5525ff9a47c4bcab2c01b70018b117f6fe05253775612ff70c6b", + "0x9050e0e45bcc83930d4c505af35e5e4d7ca01cd8681cba92eb55821aececcebe32bb692ebe1a4daac4e7472975671067", + "0x8d206812aac42742dbaf233e0c080b3d1b30943b54b60283515da005de05ea5caa90f91fedcfcba72e922f64d7040189", + "0xa2d44faaeb2eff7915c83f32b13ca6f31a6847b1c1ce114ea240bac3595eded89f09b2313b7915ad882292e2b586d5b4", + "0x961776c8576030c39f214ea6e0a3e8b3d32f023d2600958c098c95c8a4e374deeb2b9dc522adfbd6bda5949bdc09e2a2", + "0x993fa7d8447407af0fbcd9e6d77f815fa5233ab00674efbcf74a1f51c37481445ae291cc7b76db7c178f9cb0e570e0fc", + "0xabd5b1c78e05f9d7c8cc99bdaef8b0b6a57f2daf0f02bf492bec48ea4a27a8f1e38b5854da96efff11973326ff980f92", + "0x8f15af4764bc275e6ccb892b3a4362cacb4e175b1526a9a99944e692fe6ccb1b4fc19abf312bb2a089cb1f344d91a779", + "0xa09b27ccd71855512aba1d0c30a79ffbe7f6707a55978f3ced50e674b511a79a446dbc6d7946add421ce111135a460af", + "0x94b2f98ce86a9271fbd4153e1fc37de48421fe3490fb3840c00f2d5a4d0ba8810c6a32880b002f6374b59e0a7952518b", + "0x8650ac644f93bbcb88a6a0f49fee2663297fd4bc6fd47b6a89b9d8038d32370438ab3a4775ec9b58cb10aea8a95ef7b6", + "0x95e5c2f2e84eed88c6980bbba5a1c0bb375d5a628bff006f7516d45bb7d723da676add4fdd45956f312e7bab0f052644", + "0xb3278a3fa377ac93af7cfc9453f8cb594aae04269bbc99d2e0e45472ff4b6a2f97a26c4c57bf675b9d86f5e77a5d55d1", + "0xb4bcbe6eb666a206e2ea2f877912c1d3b5bdbd08a989fc4490eb06013e1a69ad1ba08bcdac048bf29192312be399077b", + "0xa76d70b78c99fffcbf9bb9886eab40f1ea4f99a309710b660b64cbf86057cbcb644d243f6e341711bb7ef0fedf0435a7", + "0xb2093c1ee945dca7ac76ad5aed08eae23af31dd5a77c903fd7b6f051f4ab84425d33a03c3d45bf2907bc93c02d1f3ad8", + "0x904b1f7534e053a265b22d20be859912b9c9ccb303af9a8d6f1d8f6ccdc5c53eb4a45a1762b880d8444d9be0cd55e7f9", + "0x8f664a965d65bc730c9ef1ec7467be984d4b8eb46bd9b0d64e38e48f94e6e55dda19aeac82cbcf4e1473440e64c4ca18", + "0x8bcee65c4cc7a7799353d07b114c718a2aae0cd10a3f22b7eead5185d159dafd64852cb63924bf87627d176228878bce", + "0x8c78f2e3675096fef7ebaa898d2615cd50d39ca3d8f02b9bdfb07e67da648ae4be3da64838dffc5935fd72962c4b96c7", + "0x8c40afd3701629421fec1df1aac4e849384ef2e80472c0e28d36cb1327acdf2826f99b357f3d7afdbc58a6347fc40b3c", + "0xa197813b1c65a8ea5754ef782522a57d63433ef752215ecda1e7da76b0412ee619f58d904abd2e07e0c097048b6ae1dd", + "0xa670542629e4333884ad7410f9ea3bd6f988df4a8f8a424ca74b9add2312586900cf9ae8bd50411f9146e82626b4af56", + "0xa19875cc07ab84e569d98b8b67fb1dbbdfb59093c7b748fae008c8904a6fd931a63ca8d03ab5fea9bc8d263568125a9b", + "0xb57e7f68e4eb1bd04aafa917b1db1bdab759a02aa8a9cdb1cba34ba8852b5890f655645c9b4e15d5f19bf37e9f2ffe9f", + "0x8abe4e2a4f6462b6c64b3f10e45db2a53c2b0d3c5d5443d3f00a453e193df771eda635b098b6c8604ace3557514027af", + "0x8459e4fb378189b22b870a6ef20183deb816cefbf66eca1dc7e86d36a2e011537db893729f500dc154f14ce24633ba47", + "0x930851df4bc7913c0d8c0f7bd3b071a83668987ed7c397d3d042fdc0d9765945a39a3bae83da9c88cb6b686ed8aeeb26", + "0x8078c9e5cd05e1a8c932f8a1d835f61a248b6e7133fcbb3de406bf4ffc0e584f6f9f95062740ba6008d98348886cf76b", + "0xaddff62bb29430983fe578e3709b0949cdc0d47a13a29bc3f50371a2cb5c822ce53e2448cfaa01bcb6e0aa850d5a380e", + "0x9433add687b5a1e12066721789b1db2edf9b6558c3bdc0f452ba33b1da67426abe326e9a34d207bfb1c491c18811bde1", + "0x822beda3389963428cccc4a2918fa9a8a51cf0919640350293af70821967108cded5997adae86b33cb917780b097f1ca", + "0xa7a9f52bda45e4148ed56dd176df7bd672e9b5ed18888ccdb405f47920fdb0844355f8565cefb17010b38324edd8315f", + "0xb35c3a872e18e607b2555c51f9696a17fa18da1f924d503b163b4ec9fe22ed0c110925275cb6c93ce2d013e88f173d6a", + "0xadf34b002b2b26ab84fc1bf94e05bd8616a1d06664799ab149363c56a6e0c807fdc473327d25632416e952ea327fcd95", + "0xae4a6b9d22a4a3183fac29e2551e1124a8ce4a561a9a2afa9b23032b58d444e6155bb2b48f85c7b6d70393274e230db7", + "0xa2ea3be4fc17e9b7ce3110284038d46a09e88a247b6971167a7878d9dcf36925d613c382b400cfa4f37a3ebea3699897", + "0x8e5863786b641ce3140fbfe37124d7ad3925472e924f814ebfc45959aaf3f61dc554a597610b5defaecc85b59a99b50f", + "0xaefde3193d0f700d0f515ab2aaa43e2ef1d7831c4f7859f48e52693d57f97fa9e520090f3ed700e1c966f4b76048e57f", + "0x841a50f772956622798e5cd208dc7534d4e39eddee30d8ce133383d66e5f267e389254a0cdae01b770ecd0a9ca421929", + "0x8fbc2bfd28238c7d47d4c03b1b910946c0d94274a199575e5b23242619b1de3497784e646a92aa03e3e24123ae4fcaba", + "0x926999579c8eec1cc47d7330112586bdca20b4149c8b2d066f527c8b9f609e61ce27feb69db67eea382649c6905efcf9", + "0xb09f31f305efcc65589adf5d3690a76cf339efd67cd43a4e3ced7b839507466e4be72dd91f04e89e4bbef629d46e68c0", + "0xb917361f6b95f759642638e0b1d2b3a29c3bdef0b94faa30de562e6078c7e2d25976159df3edbacbf43614635c2640b4", + "0x8e7e8a1253bbda0e134d62bfe003a2669d471b47bd2b5cde0ff60d385d8e62279d54022f5ac12053b1e2d3aaa6910b4c", + "0xb69671a3c64e0a99d90b0ed108ce1912ff8ed983e4bddd75a370e9babde25ee1f5efb59ec707edddd46793207a8b1fe7", + "0x910b2f4ebd37b7ae94108922b233d0920b4aba0bd94202c70f1314418b548d11d8e9caa91f2cd95aff51b9432d122b7f", + "0x82f645c90dfb52d195c1020346287c43a80233d3538954548604d09fbab7421241cde8593dbc4acc4986e0ea39a27dd9", + "0x8fee895f0a140d88104ce442fed3966f58ff9d275e7373483f6b4249d64a25fb5374bbdc6bce6b5ab0270c2847066f83", + "0x84f5bd7aab27b2509397aeb86510dd5ac0a53f2c8f73799bf720f2f87a52277f8d6b0f77f17bc80739c6a7119b7eb062", + "0x9903ceced81099d7e146e661bcf01cbaccab5ba54366b85e2177f07e2d8621e19d9c9c3eee14b9266de6b3f9b6ea75ae", + "0xb9c16ea2a07afa32dd6c7c06df0dec39bca2067a9339e45475c98917f47e2320f6f235da353fd5e15b477de97ddc68dd", + "0x9820a9bbf8b826bec61ebf886de2c4f404c1ebdc8bab82ee1fea816d9de29127ce1852448ff717a3fe8bbfe9e92012e5", + "0x817224d9359f5da6f2158c2c7bf9165501424f063e67ba9859a07ab72ee2ee62eb00ca6da821cfa19065c3282ca72c74", + "0x94b95c465e6cb00da400558a3c60cfec4b79b27e602ca67cbc91aead08de4b6872d8ea096b0dc06dca4525c8992b8547", + "0xa2b539a5bccd43fa347ba9c15f249b417997c6a38c63517ca38394976baa08e20be384a360969ff54e7e721db536b3e5", + "0x96caf707e34f62811ee8d32ccf28d8d6ec579bc33e424d0473529af5315c456fd026aa910c1fed70c91982d51df7d3ca", + "0x8a77b73e890b644c6a142bdbac59b22d6a676f3b63ddafb52d914bb9d395b8bf5aedcbcc90429337df431ebd758a07a6", + "0x8857830a7351025617a08bc44caec28d2fae07ebf5ffc9f01d979ce2a53839a670e61ae2783e138313929129790a51a1", + "0xaa3e420321ed6f0aa326d28d1a10f13facec6f605b6218a6eb9cbc074801f3467bf013a456d1415a5536f12599efa3d3", + "0x824aed0951957b00ea2f3d423e30328a3527bf6714cf9abbae84cf27e58e5c35452ba89ccc011de7c68c75d6e021d8f1", + "0xa2e87cc06bf202e953fb1081933d8b4445527dde20e38ed1a4f440144fd8fa464a2b73e068b140562e9045e0f4bd3144", + "0xae3b8f06ad97d7ae3a5e5ca839efff3e4824dc238c0c03fc1a8d2fc8aa546cdfd165b784a31bb4dec7c77e9305b99a4b", + "0xb30c3e12395b1fb8b776f3ec9f87c70e35763a7b2ddc68f0f60a4982a84017f27c891a98561c830038deb033698ed7fc", + "0x874e507757cd1177d0dff0b0c62ce90130324442a33da3b2c8ee09dbca5d543e3ecfe707e9f1361e7c7db641c72794bb", + "0xb53012dd10b5e7460b57c092eaa06d6502720df9edbbe3e3f61a9998a272bf5baaac4a5a732ad4efe35d6fac6feca744", + "0x85e6509d711515534d394e6cacbed6c81da710074d16ef3f4950bf2f578d662a494d835674f79c4d6315bced4defc5f0", + "0xb6132b2a34b0905dcadc6119fd215419a7971fe545e52f48b768006944b4a9d7db1a74b149e2951ea48c083b752d0804", + "0x989867da6415036d19b4bacc926ce6f4df7a556f50a1ba5f3c48eea9cefbb1c09da81481c8009331ee83f0859185e164", + "0x960a6c36542876174d3fbc1505413e29f053ed87b8d38fef3af180491c7eff25200b45dd5fe5d4d8e63c7e8c9c00f4c8", + "0x9040b59bd739d9cc2e8f6e894683429e4e876a8106238689ff4c22770ae5fdae1f32d962b30301fa0634ee163b524f35", + "0xaf3fcd0a45fe9e8fe256dc7eab242ef7f582dd832d147444483c62787ac820fafc6ca55d639a73f76bfa5e7f5462ab8f", + "0xb934c799d0736953a73d91e761767fdb78454355c4b15c680ce08accb57ccf941b13a1236980001f9e6195801cffd692", + "0x8871e8e741157c2c326b22cf09551e78da3c1ec0fc0543136f581f1550f8bab03b0a7b80525c1e99812cdbf3a9698f96", + "0xa8a977f51473a91d178ee8cfa45ffef8d6fd93ab1d6e428f96a3c79816d9c6a93cd70f94d4deda0125fd6816e30f3bea", + "0xa7688b3b0a4fc1dd16e8ba6dc758d3cfe1b7cf401c31739484c7fa253cce0967df1b290769bcefc9d23d3e0cb19e6218", + "0x8ae84322662a57c6d729e6ff9d2737698cc2da2daeb1f39e506618750ed23442a6740955f299e4a15dda6db3e534d2c6", + "0xa04a961cdccfa4b7ef83ced17ab221d6a043b2c718a0d6cc8e6f798507a31f10bf70361f70a049bc8058303fa7f96864", + "0xb463e39732a7d9daec8a456fb58e54b30a6e160aa522a18b9a9e836488cce3342bcbb2e1deab0f5e6ec0a8796d77197d", + "0xb1434a11c6750f14018a2d3bcf94390e2948f4f187e93bb22070ca3e5393d339dc328cbfc3e48815f51929465ffe7d81", + "0x84ff81d73f3828340623d7e3345553610aa22a5432217ef0ebd193cbf4a24234b190c65ca0873c22d10ea7b63bd1fbed", + "0xb6fe2723f0c47757932c2ddde7a4f8434f665612f7b87b4009c2635d56b6e16b200859a8ade49276de0ef27a2b6c970a", + "0x9742884ed7cd52b4a4a068a43d3faa02551a424136c85a9313f7cb58ea54c04aa83b0728fd741d1fe39621e931e88f8f", + "0xb7d2d65ea4d1ad07a5dee39e40d6c03a61264a56b1585b4d76fc5b2a68d80a93a42a0181d432528582bf08d144c2d6a9", + "0x88c0f66bada89f8a43e5a6ead2915088173d106c76f724f4a97b0f6758aed6ae5c37c373c6b92cdd4aea8f6261f3a374", + "0x81f9c43582cb42db3900747eb49ec94edb2284999a499d1527f03315fd330e5a509afa3bff659853570e9886aab5b28b", + "0x821f9d27d6beb416abf9aa5c79afb65a50ed276dbda6060103bc808bcd34426b82da5f23e38e88a55e172f5c294b4d40", + "0x8ba307b9e7cb63a6c4f3851b321aebfdb6af34a5a4c3bd949ff7d96603e59b27ff4dc4970715d35f7758260ff942c9e9", + "0xb142eb6c5f846de33227d0bda61d445a7c33c98f0a8365fe6ab4c1fabdc130849be597ef734305894a424ea715372d08", + "0xa732730ae4512e86a741c8e4c87fee8a05ee840fec0e23b2e037d58dba8dde8d10a9bc5191d34d00598941becbbe467f", + "0xadce6f7c30fd221f6b10a0413cc76435c4bb36c2d60bca821e5c67409fe9dbb2f4c36ef85eb3d734695e4be4827e9fd3", + "0xa74f00e0f9b23aff7b2527ce69852f8906dab9d6abe62ecd497498ab21e57542e12af9918d4fd610bb09e10b0929c510", + "0xa593b6b0ef26448ce4eb3ab07e84238fc020b3cb10d542ff4b16d4e2be1bcde3797e45c9cf753b8dc3b0ffdb63984232", + "0xaed3913afccf1aa1ac0eb4980eb8426d0baccebd836d44651fd72af00d09fac488a870223c42aca3ceb39752070405ae", + "0xb2c44c66a5ea7fde626548ba4cef8c8710191343d3dadfd3bb653ce715c0e03056a5303a581d47dde66e70ea5a2d2779", + "0x8e5029b2ccf5128a12327b5103f7532db599846e422531869560ceaff392236434d87159f597937dbf4054f810c114f4", + "0x82beed1a2c4477e5eb39fc5b0e773b30cfec77ef2b1bf17eadaf60eb35b6d0dd9d8cf06315c48d3546badb3f21cd0cca", + "0x90077bd6cc0e4be5fff08e5d07a5a158d36cebd1d1363125bc4fae0866ffe825b26f933d4ee5427ba5cd0c33c19a7b06", + "0xa7ec0d8f079970e8e34f0ef3a53d3e0e45428ddcef9cc776ead5e542ef06f3c86981644f61c5a637e4faf001fb8c6b3e", + "0xae6d4add6d1a6f90b22792bc9d40723ee6850c27d0b97eefafd5b7fd98e424aa97868b5287cc41b4fbd7023bca6a322c", + "0x831aa917533d077da07c01417feaa1408846363ba2b8d22c6116bb858a95801547dd88b7d7fa1d2e3f0a02bdeb2e103d", + "0x96511b860b07c8a5ed773f36d4aa9d02fb5e7882753bf56303595bcb57e37ccc60288887eb83bef08c657ec261a021a2", + "0x921d2a3e7e9790f74068623de327443666b634c8443aba80120a45bba450df920b2374d96df1ce3fb1b06dd06f8cf6e3", + "0xaa74451d51fe82b4581ead8e506ec6cd881010f7e7dd51fc388eb9a557db5d3c6721f81c151d08ebd9c2591689fbc13e", + "0xa972bfbcf4033d5742d08716c927c442119bdae336bf5dff914523b285ccf31953da2733759aacaa246a9af9f698342c", + "0xad1fcd0cae0e76840194ce4150cb8a56ebed728ec9272035f52a799d480dfc85840a4d52d994a18b6edb31e79be6e8ad", + "0xa2c69fe1d36f235215432dad48d75887a44c99dfa0d78149acc74087da215a44bdb5f04e6eef88ff7eff80a5a7decc77", + "0xa94ab2af2b6ee1bc6e0d4e689ca45380d9fbd3c5a65b9bd249d266a4d4c07bf5d5f7ef2ae6000623aee64027892bf8fe", + "0x881ec1fc514e926cdc66480ac59e139148ff8a2a7895a49f0dff45910c90cdda97b66441a25f357d6dd2471cddd99bb3", + "0x884e6d3b894a914c8cef946a76d5a0c8351843b2bffa2d1e56c6b5b99c84104381dd1320c451d551c0b966f4086e60f9", + "0x817c6c10ce2677b9fc5223500322e2b880583254d0bb0d247d728f8716f5e05c9ff39f135854342a1afecd9fbdcf7c46", + "0xaaf4a9cb686a14619aa1fc1ac285dd3843ac3dd99f2b2331c711ec87b03491c02f49101046f3c5c538dc9f8dba2a0ac2", + "0x97ecea5ce53ca720b5d845227ae61d70269a2f53540089305c86af35f0898bfd57356e74a8a5e083fa6e1ea70080bd31", + "0xa22d811e1a20a75feac0157c418a4bfe745ccb5d29466ffa854dca03e395b6c3504a734341746b2846d76583a780b32e", + "0x940cbaa0d2b2db94ae96b6b9cf2deefbfd059e3e5745de9aec4a25f0991b9721e5cd37ef71c631575d1a0c280b01cd5b", + "0xae33cb4951191258a11044682de861bf8d92d90ce751b354932dd9f3913f542b6a0f8a4dc228b3cd9244ac32c4582832", + "0xa580df5e58c4274fe0f52ac2da1837e32f5c9db92be16c170187db4c358f43e5cfdda7c5911dcc79d77a5764e32325f5", + "0x81798178cb9d8affa424f8d3be67576ba94d108a28ccc01d330c51d5a63ca45bb8ca63a2f569b5c5fe1303cecd2d777f", + "0x89975b91b94c25c9c3660e4af4047a8bacf964783010820dbc91ff8281509379cb3b24c25080d5a01174dd9a049118d5", + "0xa7327fcb3710ed3273b048650bde40a32732ef40a7e58cf7f2f400979c177944c8bc54117ba6c80d5d4260801dddab79", + "0x92b475dc8cb5be4b90c482f122a51bcb3b6c70593817e7e2459c28ea54a7845c50272af38119406eaadb9bcb993368d0", + "0x9645173e9ecefc4f2eae8363504f7c0b81d85f8949a9f8a6c01f2d49e0a0764f4eacecf3e94016dd407fc14494fce9f9", + "0x9215fd8983d7de6ae94d35e6698226fc1454977ae58d42d294be9aad13ac821562ad37d5e7ee5cdfe6e87031d45cd197", + "0x810360a1c9b88a9e36f520ab5a1eb8bed93f52deefbe1312a69225c0a08edb10f87cc43b794aced9c74220cefcc57e7d", + "0xad7e810efd61ed4684aeda9ed8bb02fb9ae4b4b63fda8217d37012b94ff1b91c0087043bfa4e376f961fff030c729f3b", + "0x8b07c95c6a06db8738d10bb03ec11b89375c08e77f0cab7e672ce70b2685667ca19c7e1c8b092821d31108ea18dfd4c7", + "0x968825d025ded899ff7c57245250535c732836f7565eab1ae23ee7e513201d413c16e1ba3f5166e7ac6cf74de8ceef4f", + "0x908243370c5788200703ade8164943ad5f8c458219186432e74dbc9904a701ea307fd9b94976c866e6c58595fd891c4b", + "0x959969d16680bc535cdc6339e6186355d0d6c0d53d7bbfb411641b9bf4b770fd5f575beef5deec5c4fa4d192d455c350", + "0xad177f4f826a961adeac76da40e2d930748effff731756c797eddc4e5aa23c91f070fb69b19221748130b0961e68a6bb", + "0x82f8462bcc25448ef7e0739425378e9bb8a05e283ce54aae9dbebaf7a3469f57833c9171672ad43a79778366c72a5e37", + "0xa28fb275b1845706c2814d9638573e9bc32ff552ebaed761fe96fdbce70395891ca41c400ae438369264e31a2713b15f", + "0x8a9c613996b5e51dadb587a787253d6081ea446bf5c71096980bf6bd3c4b69905062a8e8a3792de2d2ece3b177a71089", + "0x8d5aefef9f60cb27c1db2c649221204dda48bb9bf8bf48f965741da051340e8e4cab88b9d15c69f3f84f4c854709f48a", + "0x93ebf2ca6ad85ab6deace6de1a458706285b31877b1b4d7dcb9d126b63047efaf8c06d580115ec9acee30c8a7212fa55", + "0xb3ee46ce189956ca298057fa8223b7fd1128cf52f39159a58bca03c71dd25161ac13f1472301f72aef3e1993fe1ab269", + "0xa24d7a8d066504fc3f5027ccb13120e2f22896860e02c45b5eba1dbd512d6a17c28f39155ea581619f9d33db43a96f92", + "0xae9ceacbfe12137db2c1a271e1b34b8f92e4816bad1b3b9b6feecc34df0f8b3b0f7ed0133acdf59c537d43d33fc8d429", + "0x83967e69bf2b361f86361bd705dce0e1ad26df06da6c52b48176fe8dfcbeb03c462c1a4c9e649eff8c654b18c876fdef", + "0x9148e6b814a7d779c19c31e33a068e97b597de1f8100513db3c581190513edc4d544801ce3dd2cf6b19e0cd6daedd28a", + "0x94ccdafc84920d320ed22de1e754adea072935d3c5f8c2d1378ebe53d140ea29853f056fb3fb1e375846061a038cc9bc", + "0xafb43348498c38b0fa5f971b8cdd3a62c844f0eb52bc33daf2f67850af0880fce84ecfb96201b308d9e6168a0d443ae3", + "0x86d5736520a83538d4cd058cc4b4e84213ed00ebd6e7af79ae787adc17a92ba5359e28ba6c91936d967b4b28d24c3070", + "0xb5210c1ff212c5b1e9ef9126e08fe120a41e386bb12c22266f7538c6d69c7fd8774f11c02b81fd4e88f9137b020801fe", + "0xb78cfd19f94d24e529d0f52e18ce6185cb238edc6bd43086270fd51dd99f664f43dd4c7d2fe506762fbd859028e13fcf", + "0xa6e7220598c554abdcc3fdc587b988617b32c7bb0f82c06205467dbedb58276cc07cae317a190f19d19078773f4c2bbb", + "0xb88862809487ee430368dccd85a5d72fa4d163ca4aad15c78800e19c1a95be2192719801e315d86cff7795e0544a77e4", + "0x87ecb13a03921296f8c42ceb252d04716f10e09c93962239fcaa0a7fef93f19ab3f2680bc406170108bc583e9ff2e721", + "0xa810cd473832b6581c36ec4cb403f2849357ba2d0b54df98ef3004b8a530c078032922a81d40158f5fb0043d56477f6e", + "0xa247b45dd85ca7fbb718b328f30a03f03c84aef2c583fbdc9fcc9eb8b52b34529e8c8f535505c10598b1b4dac3d7c647", + "0x96ee0b91313c68bac4aa9e065ce9e1d77e51ca4cff31d6a438718c58264dee87674bd97fc5c6b8008be709521e4fd008", + "0x837567ad073e42266951a9a54750919280a2ac835a73c158407c3a2b1904cf0d17b7195a393c71a18ad029cbd9cf79ee", + "0xa6a469c44b67ebf02196213e7a63ad0423aab9a6e54acc6fcbdbb915bc043586993454dc3cd9e4be8f27d67c1050879b", + "0x8712d380a843b08b7b294f1f06e2f11f4ad6bcc655fdde86a4d8bc739c23916f6fad2b902fe47d6212f03607907e9f0e", + "0x920adfb644b534789943cdae1bdd6e42828dda1696a440af2f54e6b97f4f97470a1c6ea9fa6a2705d8f04911d055acd1", + "0xa161c73adf584a0061e963b062f59d90faac65c9b3a936b837a10d817f02fcabfa748824607be45a183dd40f991fe83f", + "0x874f4ecd408c76e625ea50bc59c53c2d930ee25baf4b4eca2440bfbffb3b8bc294db579caa7c68629f4d9ec24187c1ba", + "0x8bff18087f112be7f4aa654e85c71fef70eee8ae480f61d0383ff6f5ab1a0508f966183bb3fc4d6f29cb7ca234aa50d3", + "0xb03b46a3ca3bc743a173cbc008f92ab1aedd7466b35a6d1ca11e894b9482ea9dc75f8d6db2ddd1add99bfbe7657518b7", + "0x8b4f3691403c3a8ad9e097f02d130769628feddfa8c2b3dfe8cff64e2bed7d6e5d192c1e2ba0ac348b8585e94acd5fa1", + "0xa0d9ca4a212301f97591bf65d5ef2b2664766b427c9dd342e23cb468426e6a56be66b1cb41fea1889ac5d11a8e3c50a5", + "0x8c93ed74188ca23b3df29e5396974b9cc135c91fdefdea6c0df694c8116410e93509559af55533a3776ac11b228d69b1", + "0x82dd331fb3f9e344ebdeeb557769b86a2cc8cc38f6c298d7572a33aea87c261afa9dbd898989139b9fc16bc1e880a099", + "0xa65faedf326bcfd8ef98a51410c78b021d39206704e8291cd1f09e096a66b9b0486be65ff185ca224c45918ac337ddeb", + "0xa188b37d363ac072a766fd5d6fa27df07363feff1342217b19e3c37385e42ffde55e4be8355aceaa2f267b6d66b4ac41", + "0x810fa3ba3e96d843e3bafd3f2995727f223d3567c8ba77d684c993ba1773c66551eb5009897c51b3fe9b37196984f5ec", + "0x87631537541852da323b4353af45a164f68b304d24c01183bf271782e11687f3fcf528394e1566c2a26cb527b3148e64", + "0xb721cb2b37b3c477a48e3cc0044167d51ff568a5fd2fb606e5aec7a267000f1ddc07d3db919926ae12761a8e017c767c", + "0x904dfad4ba2cc1f6e60d1b708438a70b1743b400164cd981f13c064b8328d5973987d4fb9cf894068f29d3deaf624dfb", + "0xa70491538893552c20939fae6be2f07bfa84d97e2534a6bbcc0f1729246b831103505e9f60e97a8fa7d2e6c1c2384579", + "0x8726cf1b26b41f443ff7485adcfddc39ace2e62f4d65dd0bb927d933e262b66f1a9b367ded5fbdd6f3b0932553ac1735", + "0xae8a11cfdf7aa54c08f80cb645e3339187ab3886babe9fae5239ba507bb3dd1c0d161ca474a2df081dcd3d63e8fe445e", + "0x92328719e97ce60e56110f30a00ac5d9c7a2baaf5f8d22355d53c1c77941e3a1fec7d1405e6fbf8959665fe2ba7a8cad", + "0x8d9d6255b65798d0018a8cccb0b6343efd41dc14ff2058d3eed9451ceaad681e4a0fa6af67b0a04318aa628024e5553d", + "0xb70209090055459296006742d946a513f0cba6d83a05249ee8e7a51052b29c0ca9722dc4af5f9816a1b7938a5dac7f79", + "0xaab7b766b9bf91786dfa801fcef6d575dc6f12b77ecc662eb4498f0312e54d0de9ea820e61508fc8aeee5ab5db529349", + "0xa8104b462337748b7f086a135d0c3f87f8e51b7165ca6611264b8fb639d9a2f519926cb311fa2055b5fadf03da70c678", + "0xb0d2460747d5d8b30fc6c6bd0a87cb343ddb05d90a51b465e8f67d499cfc5e3a9e365da05ae233bbee792cdf90ec67d5", + "0xaa55f5bf3815266b4a149f85ed18e451c93de9163575e3ec75dd610381cc0805bb0a4d7c4af5b1f94d10231255436d2c", + "0x8d4c6a1944ff94426151909eb5b99cfd92167b967dabe2bf3aa66bb3c26c449c13097de881b2cfc1bf052862c1ef7b03", + "0x8862296162451b9b6b77f03bf32e6df71325e8d7485cf3335d66fd48b74c2a8334c241db8263033724f26269ad95b395", + "0x901aa96deb26cda5d9321190ae6624d357a41729d72ef1abfd71bebf6139af6d690798daba53b7bc5923462115ff748a", + "0x96c195ec4992728a1eb38cdde42d89a7bce150db43adbc9e61e279ea839e538deec71326b618dd39c50d589f78fc0614", + "0xb6ff8b8aa0837b99a1a8b46fb37f20ad4aecc6a98381b1308697829a59b8442ffc748637a88cb30c9b1f0f28a926c4f6", + "0x8d807e3dca9e7bef277db1d2cfb372408dd587364e8048b304eff00eacde2c723bfc84be9b98553f83cba5c7b3cba248", + "0x8800c96adb0195c4fc5b24511450dee503c32bf47044f5e2e25bd6651f514d79a2dd9b01cd8c09f3c9d3859338490f57", + "0x89fe366096097e38ec28dd1148887112efa5306cc0c3da09562aafa56f4eb000bf46ff79bf0bdd270cbde6bf0e1c8957", + "0xaf409a90c2776e1e7e3760b2042507b8709e943424606e31e791d42f17873a2710797f5baaab4cc4a19998ef648556b0", + "0x8d761863c9b6edbd232d35ab853d944f5c950c2b643f84a1a1327ebb947290800710ff01dcfa26dc8e9828481240e8b1", + "0x90b95e9be1e55c463ed857c4e0617d6dc3674e99b6aa62ed33c8e79d6dfcf7d122f4f4cc2ee3e7c5a49170cb617d2e2e", + "0xb3ff381efefabc4db38cc4727432e0301949ae4f16f8d1dea9b4f4de611cf5a36d84290a0bef160dac4e1955e516b3b0", + "0xa8a84564b56a9003adcadb3565dc512239fc79572762cda7b5901a255bc82656bb9c01212ad33d6bef4fbbce18dacc87", + "0x90a081890364b222eef54bf0075417f85e340d2fec8b7375995f598aeb33f26b44143ebf56fca7d8b4ebb36b5747b0eb", + "0xade6ee49e1293224ddf2d8ab7f14bb5be6bc6284f60fd5b3a1e0cf147b73cff57cf19763b8a36c5083badc79c606b103", + "0xb2fa99806dd2fa3de09320b615a2570c416c9bcdb052e592b0aead748bbe407ec9475a3d932ae48b71c2627eb81986a6", + "0x91f3b7b73c8ccc9392542711c45fe6f236057e6efad587d661ad5cb4d6e88265f86b807bb1151736b1009ab74fd7acb4", + "0x8800e2a46af96696dfbdcbf2ca2918b3dcf28ad970170d2d1783b52b8d945a9167d052beeb55f56c126da7ffa7059baa", + "0x9862267a1311c385956b977c9aa08548c28d758d7ba82d43dbc3d0a0fd1b7a221d39e8399997fea9014ac509ff510ac4", + "0xb7d24f78886fd3e2d283e18d9ad5a25c1a904e7d9b9104bf47da469d74f34162e27e531380dbbe0a9d051e6ffd51d6e7", + "0xb0f445f9d143e28b9df36b0f2c052da87ee2ca374d9d0fbe2eff66ca6fe5fe0d2c1951b428d58f7314b7e74e45d445ea", + "0xb63fc4083eabb8437dafeb6a904120691dcb53ce2938b820bb553da0e1eecd476f72495aacb72600cf9cad18698fd3db", + "0xb9ffd8108eaebd582d665f8690fe8bb207fd85185e6dd9f0b355a09bac1bbff26e0fdb172bc0498df025414e88fe2eda", + "0x967ed453e1f1a4c5b7b6834cc9f75c13f6889edc0cc91dc445727e9f408487bbf05c337103f61397a10011dfbe25d61d", + "0x98ceb673aff36e1987d5521a3984a07079c3c6155974bb8b413e8ae1ce84095fe4f7862fba7aefa14753eb26f2a5805f", + "0x85f01d28603a8fdf6ce6a50cb5c44f8a36b95b91302e3f4cd95c108ce8f4d212e73aec1b8d936520d9226802a2bd9136", + "0x88118e9703200ca07910345fbb789e7a8f92bd80bbc79f0a9e040e8767d33df39f6eded403a9b636eabf9101e588482a", + "0x90833a51eef1b10ed74e8f9bbd6197e29c5292e469c854eed10b0da663e2bceb92539710b1858bbb21887bd538d28d89", + "0xb513b905ec19191167c6193067b5cfdf5a3d3828375360df1c7e2ced5815437dfd37f0c4c8f009d7fb29ff3c8793f560", + "0xb1b6d405d2d18f9554b8a358cc7e2d78a3b34269737d561992c8de83392ac9a2857be4bf15de5a6c74e0c9d0f31f393c", + "0xb828bd3e452b797323b798186607849f85d1fb20c616833c0619360dfd6b3e3aa000fd09dafe4b62d74abc41072ff1a9", + "0x8efde67d0cca56bb2c464731879c9ac46a52e75bac702a63200a5e192b4f81c641f855ca6747752b84fe469cb7113b6c", + "0xb2762ba1c89ac3c9a983c242e4d1c2610ff0528585ed5c0dfc8a2c0253551142af9b59f43158e8915a1da7cc26b9df67", + "0x8a3f1157fb820d1497ef6b25cd70b7e16bb8b961b0063ad340d82a79ee76eb2359ca9e15e6d42987ed7f154f5eeaa2da", + "0xa75e29f29d38f09c879f971c11beb5368affa084313474a5ecafa2896180b9e47ea1995c2733ec46f421e395a1d9cffe", + "0x8e8c3dd3e7196ef0b4996b531ec79e4a1f211db5d5635e48ceb80ff7568b2ff587e845f97ee703bb23a60945ad64314a", + "0x8e7f32f4a3e3c584af5e3d406924a0aa34024c42eca74ef6cc2a358fd3c9efaf25f1c03aa1e66bb94b023a2ee2a1cace", + "0xab7dce05d59c10a84feb524fcb62478906b3fa045135b23afbede3bb32e0c678d8ebe59feabccb5c8f3550ea76cae44b", + "0xb38bb4b44d827f6fd3bd34e31f9186c59e312dbfadd4a7a88e588da10146a78b1f8716c91ad8b806beb8da65cab80c4c", + "0x9490ce9442bbbd05438c7f5c4dea789f74a7e92b1886a730544b55ba377840740a3ae4f2f146ee73f47c9278b0e233bc", + "0x83c003fab22a7178eed1a668e0f65d4fe38ef3900044e9ec63070c23f2827d36a1e73e5c2b883ec6a2afe2450171b3b3", + "0x9982f02405978ddc4fca9063ebbdb152f524c84e79398955e66fe51bc7c1660ec1afc3a86ec49f58d7b7dde03505731c", + "0xab337bd83ccdd2322088ffa8d005f450ced6b35790f37ab4534313315ee84312adc25e99cce052863a8bedee991729ed", + "0x8312ce4bec94366d88f16127a17419ef64285cd5bf9e5eda010319b48085966ed1252ed2f5a9fd3e0259b91bb65f1827", + "0xa60d5a6327c4041b0c00a1aa2f0af056520f83c9ce9d9ccd03a0bd4d9e6a1511f26a422ea86bd858a1f77438adf07e6c", + "0xb84a0a0b030bdad83cf5202aa9afe58c9820e52483ab41f835f8c582c129ee3f34aa096d11c1cd922eda02ea1196a882", + "0x8077d105317f4a8a8f1aadeb05e0722bb55f11abcb490c36c0904401107eb3372875b0ac233144829e734f0c538d8c1d", + "0x9202503bd29a6ec198823a1e4e098f9cfe359ed51eb5174d1ca41368821bfeebcbd49debfd02952c41359d1c7c06d2b1", + "0xabc28c155e09365cb77ffead8dc8f602335ef93b2f44e4ef767ce8fc8ef9dd707400f3a722e92776c2e0b40192c06354", + "0xb0f6d1442533ca45c9399e0a63a11f85ff288d242cea6cb3b68c02e77bd7d158047cae2d25b3bcd9606f8f66d9b32855", + "0xb01c3d56a0db84dc94575f4b6ee2de4beca3230e86bed63e2066beb22768b0a8efb08ebaf8ac3dedb5fe46708b084807", + "0x8c8634b0432159f66feaabb165842d1c8ac378f79565b1b90c381aa8450eb4231c3dad11ec9317b9fc2b155c3a771e32", + "0x8e67f623d69ecd430c9ee0888520b6038f13a2b6140525b056dc0951f0cfed2822e62cf11d952a483107c5c5acac4826", + "0x9590bb1cba816dd6acd5ac5fba5142c0a19d53573e422c74005e0bcf34993a8138c83124cad35a3df65879dba6134edd", + "0x801cd96cde0749021a253027118d3ea135f3fcdbe895db08a6c145641f95ebd368dd6a1568d995e1d0084146aebe224a", + "0x848b5d196427f6fc1f762ee3d36e832b64a76ec1033cfedc8b985dea93932a7892b8ef1035c653fb9dcd9ab2d9a44ac8", + "0xa1017eb83d5c4e2477e7bd2241b2b98c4951a3b391081cae7d75965cadc1acaec755cf350f1f3d29741b0828e36fedea", + "0x8d6d2785e30f3c29aad17bd677914a752f831e96d46caf54446d967cb2432be2c849e26f0d193a60bee161ea5c6fe90a", + "0x935c0ba4290d4595428e034b5c8001cbd400040d89ab00861108e8f8f4af4258e41f34a7e6b93b04bc253d3b9ffc13bf", + "0xaac02257146246998477921cef2e9892228590d323b839f3e64ea893b991b463bc2f47e1e5092ddb47e70b2f5bce7622", + "0xb921fde9412970a5d4c9a908ae8ce65861d06c7679af577cf0ad0d5344c421166986bee471fd6a6cecb7d591f06ec985", + "0x8ef4c37487b139d6756003060600bb6ebac7ea810b9c4364fc978e842f13ac196d1264fbe5af60d76ff6d9203d8e7d3f", + "0x94b65e14022b5cf6a9b95f94be5ace2711957c96f4211c3f7bb36206bd39cfbd0ea82186cab5ad0577a23214a5c86e9e", + "0xa31c166d2a2ca1d5a75a5920fef7532681f62191a50d8555fdaa63ba4581c3391cc94a536fc09aac89f64eafceec3f90", + "0x919a8cc128de01e9e10f5d83b08b52293fdd41bde2b5ae070f3d95842d4a16e5331cf2f3d61c765570c8022403610fa4", + "0xb23d6f8331eef100152d60483cfa14232a85ee712c8538c9b6417a5a7c5b353c2ac401390c6c215cb101f5cee6b5f43e", + "0xab357160c08a18319510a571eafff154298ce1020de8e1dc6138a09fcb0fcbcdd8359f7e9386bda00b7b9cdea745ffdc", + "0xab55079aea34afa5c0bd1124b9cdfe01f325b402fdfa017301bf87812eaa811ea5798c3aaf818074d420d1c782b10ada", + "0xade616010dc5009e7fc4f8d8b00dc716686a5fa0a7816ad9e503e15839d3b909b69d9dd929b7575376434ffec0d2bea8", + "0x863997b97ed46898a8a014599508fa3079f414b1f4a0c4fdc6d74ae8b444afa350f327f8bfc2a85d27f9e2d049c50135", + "0x8d602ff596334efd4925549ed95f2aa762b0629189f0df6dbb162581657cf3ea6863cd2287b4d9c8ad52813d87fcd235", + "0xb70f68c596dcdeed92ad5c6c348578b26862a51eb5364237b1221e840c47a8702f0fbc56eb520a22c0eed99795d3903e", + "0x9628088f8e0853cefadee305a8bf47fa990c50fa96a82511bbe6e5dc81ef4b794e7918a109070f92fc8384d77ace226f", + "0x97e26a46e068b605ce96007197ecd943c9a23881862f4797a12a3e96ba2b8d07806ad9e2a0646796b1889c6b7d75188c", + "0xb1edf467c068cc163e2d6413cc22b16751e78b3312fe47b7ea82b08a1206d64415b2c8f2a677fa89171e82cc49797150", + "0xa44d15ef18745b251429703e3cab188420e2d974de07251501799b016617f9630643fcd06f895634d8ecdd579e1bf000", + "0xabd126df3917ba48c618ee4dbdf87df506193462f792874439043fa1b844466f6f4e0ff2e42516e63b5b23c0892b2695", + "0xa2a67f57c4aa3c2aa1eeddbfd5009a89c26c2ce8fa3c96a64626aba19514beb125f27df8559506f737de3eae0f1fc18f", + "0xa633e0132197e6038197304b296ab171f1d8e0d0f34dcf66fe9146ac385b0239232a8470b9205a4802ab432389f4836d", + "0xa914b3a28509a906c3821463b936455d58ff45dcbe158922f9efb2037f2eb0ce8e92532d29b5d5a3fcd0d23fa773f272", + "0xa0e1412ce4505daf1a2e59ce4f0fc0e0023e335b50d2b204422f57cd65744cc7a8ed35d5ef131a42c70b27111d3115b7", + "0xa2339e2f2b6072e88816224fdd612c04d64e7967a492b9f8829db15367f565745325d361fd0607b0def1be384d010d9e", + "0xa7309fc41203cb99382e8193a1dcf03ac190a7ce04835304eb7e341d78634e83ea47cb15b885601956736d04cdfcaa01", + "0x81f3ccd6c7f5b39e4e873365f8c37b214e8ab122d04a606fbb7339dc3298c427e922ec7418002561d4106505b5c399ee", + "0x92c121cf914ca549130e352eb297872a63200e99b148d88fbc9506ad882bec9d0203d65f280fb5b0ba92e336b7f932e8", + "0xa4b330cf3f064f5b131578626ad7043ce2a433b6f175feb0b52d36134a454ca219373fd30d5e5796410e005b69082e47", + "0x86fe5774112403ad83f9c55d58317eeb17ad8e1176d9f2f69c2afb7ed83bc718ed4e0245ceab4b377f5f062dcd4c00e7", + "0x809d152a7e2654c7fd175b57f7928365a521be92e1ed06c05188a95864ddb25f7cab4c71db7d61bbf4cae46f3a1d96ce", + "0xb82d663e55c2a5ada7e169e9b1a87bc1c0177baf1ec1c96559b4cb1c5214ce1ddf2ab8d345014cab6402f3774235cf5a", + "0x86580af86df1bd2c385adb8f9a079e925981b7184db66fc5fe5b14cddb82e7d836b06eaeef14924ac529487b23dae111", + "0xb5f5f4c5c94944ecc804df6ab8687d64e27d988cbfeae1ba7394e0f6adbf778c5881ead7cd8082dd7d68542b9bb4ecd5", + "0xa6016916146c2685c46e8fdd24186394e2d5496e77e08c0c6a709d4cd7dfa97f1efcef94922b89196819076a91ad37b5", + "0xb778e7367ded3b6eab53d5fc257f7a87e8faf74a593900f2f517220add2125be3f6142022660d8181df8d164ad9441ce", + "0x8581b2d36abe6f553add4d24be761bec1b8efaa2929519114346615380b3c55b59e6ad86990e312f7e234d0203bdf59b", + "0x9917e74fd45c3f71a829ff5498a7f6b5599b48c098dda2339bf04352bfc7f368ccf1a407f5835901240e76452ae807d7", + "0xafd196ce6f9335069138fd2e3d133134da253978b4ce373152c0f26affe77a336505787594022e610f8feb722f7cc1fb", + "0xa477491a1562e329764645e8f24d8e228e5ef28c9f74c6b5b3abc4b6a562c15ffb0f680d372aed04d9e1bf944dece7be", + "0x9767440d58c57d3077319d3a330e5322b9ba16981ec74a5a14d53462eab59ae7fd2b14025bfc63b268862094acb444e6", + "0x80986d921be3513ef69264423f351a61cb48390c1be8673aee0f089076086aaebea7ebe268fd0aa7182695606116f679", + "0xa9554c5c921c07b450ee04e34ec58e054ac1541b26ce2ce5a393367a97348ba0089f53db6660ad76b60278b66fd12e3e", + "0x95097e7d2999b3e84bf052c775581cf361325325f4a50192521d8f4693c830bed667d88f482dc1e3f833aa2bd22d2cbf", + "0x9014c91d0f85aefd28436b5228c12f6353c055a9326c7efbf5e071e089e2ee7c070fcbc84c5fafc336cbb8fa6fec1ca1", + "0x90f57ba36ee1066b55d37384942d8b57ae00f3cf9a3c1d6a3dfee1d1af42d4b5fa9baeb0cd7e46687d1d6d090ddb931d", + "0x8e4b1db12fd760a17214c9e47f1fce6e43c0dbb4589a827a13ac61aaae93759345697bb438a00edab92e0b7b62414683", + "0x8022a959a513cdc0e9c705e0fc04eafd05ff37c867ae0f31f6d01cddd5df86138a426cab2ff0ac8ff03a62e20f7e8f51", + "0x914e9a38829834c7360443b8ed86137e6f936389488eccf05b4b4db7c9425611705076ecb3f27105d24b85c852be7511", + "0x957fb10783e2bd0db1ba66b18e794df710bc3b2b05776be146fa5863c15b1ebdd39747b1a95d9564e1772cdfc4f37b8a", + "0xb6307028444daed8ed785ac9d0de76bc3fe23ff2cc7e48102553613bbfb5afe0ebe45e4212a27021c8eb870721e62a1f", + "0x8f76143597777d940b15a01b39c5e1b045464d146d9a30a6abe8b5d3907250e6c7f858ff2308f8591e8b0a7b3f3c568a", + "0x96163138ac0ce5fd00ae9a289648fd9300a0ca0f63a88481d703ecd281c06a52a3b5178e849e331f9c85ca4ba398f4cc", + "0xa63ef47c3e18245b0482596a09f488a716df3cbd0f9e5cfabed0d742843e65db8961c556f45f49762f3a6ac8b627b3ef", + "0x8cb595466552e7c4d42909f232d4063e0a663a8ef6f6c9b7ce3a0542b2459cde04e0e54c7623d404acb5b82775ac04f6", + "0xb47fe69960eb45f399368807cff16d941a5a4ebad1f5ec46e3dc8a2e4d598a7e6114d8f0ca791e9720fd786070524e2b", + "0x89eb5ff83eea9df490e5beca1a1fbbbbcf7184a37e2c8c91ede7a1e654c81e8cd41eceece4042ea7918a4f4646b67fd6", + "0xa84f5d155ed08b9054eecb15f689ba81e44589e6e7207a99790c598962837ca99ec12344105b16641ca91165672f7153", + "0xa6cc8f25c2d5b2d2f220ec359e6a37a52b95fa6af6e173c65e7cd55299eff4aa9e6d9e6f2769e6459313f1f2aecb0fab", + "0xafcde944411f017a9f7979755294981e941cc41f03df5e10522ef7c7505e5f1babdd67b3bf5258e8623150062eb41d9b", + "0x8fab39f39c0f40182fcd996ade2012643fe7731808afbc53f9b26900b4d4d1f0f5312d9d40b3df8baa4739970a49c732", + "0xae193af9726da0ebe7df1f9ee1c4846a5b2a7621403baf8e66c66b60f523e719c30c6b4f897bb14b27d3ff3da8392eeb", + "0x8ac5adb82d852eba255764029f42e6da92dcdd0e224d387d1ef94174038db9709ac558d90d7e7c57ad4ce7f89bbfc38c", + "0xa2066b3458fdf678ee487a55dd5bfb74fde03b54620cb0e25412a89ee28ad0d685e309a51e3e4694be2fa6f1593a344c", + "0x88d031745dd0ae07d61a15b594be5d4b2e2a29e715d081649ad63605e3404b0c3a5353f0fd9fad9c05c18e93ce674fa1", + "0x8283cfb0ef743a043f2b77ecaeba3005e2ca50435585b5dd24777ee6bce12332f85e21b446b536da38508807f0f07563", + "0xb376de22d5f6b0af0b59f7d9764561f4244cf8ffe22890ecd3dcf2ff1832130c9b821e068c9d8773136f4796721e5963", + "0xae3afc50c764f406353965363840bf28ee85e7064eb9d5f0bb3c31c64ab10f48c853e942ee2c9b51bae59651eaa08c2f", + "0x948b204d103917461a01a6c57a88f2d66b476eae5b00be20ec8c747650e864bc8a83aee0aff59cb7584b7a3387e0ee48", + "0x81ab098a082b07f896c5ffd1e4446cb7fb44804cbbf38d125208b233fc82f8ec9a6a8d8dd1c9a1162dc28ffeec0dde50", + "0xa149c6f1312821ced2969268789a3151bdda213451760b397139a028da609c4134ac083169feb0ee423a0acafd10eceb", + "0xb0ac9e27a5dadaf523010f730b28f0ebac01f460d3bbbe277dc9d44218abb5686f4fac89ae462682fef9edbba663520a", + "0x8d0e0073cca273daaaa61b6fc54bfe5a009bc3e20ae820f6c93ba77b19eca517d457e948a2de5e77678e4241807157cb", + "0xad61d3a2edf7c7533a04964b97499503fd8374ca64286dba80465e68fe932e96749b476f458c6fc57cb1a7ca85764d11", + "0x90eb5e121ae46bc01a30881eaa556f46bd8457a4e80787cf634aab355082de34ac57d7f497446468225f7721e68e2a47", + "0x8cdac557de7c42d1f3780e33dec1b81889f6352279be81c65566cdd4952d4c15d79e656cbd46035ab090b385e90245ef", + "0x82b67e61b88b84f4f4d4f65df37b3e3dcf8ec91ea1b5c008fdccd52da643adbe6468a1cfdb999e87d195afe2883a3b46", + "0x8503b467e8f5d6048a4a9b78496c58493a462852cab54a70594ae3fd064cfd0deb4b8f336a262155d9fedcaa67d2f6fd", + "0x8db56c5ac763a57b6ce6832930c57117058e3e5a81532b7d19346346205e2ec614eb1a2ee836ef621de50a7bc9b7f040", + "0xad344699198f3c6e8c0a3470f92aaffc805b76266734414c298e10b5b3797ca53578de7ccb2f458f5e0448203f55282b", + "0x80602032c43c9e2a09154cc88b83238343b7a139f566d64cb482d87436b288a98f1ea244fd3bff8da3c398686a900c14", + "0xa6385bd50ecd548cfb37174cdbb89e10025b5cadaf3cff164c95d7aef5a33e3d6a9bf0c681b9e11db9ef54ebeee2a0c1", + "0xabf2d95f4aa34b0581eb9257a0cc8462b2213941a5deb8ba014283293e8b36613951b61261cc67bbd09526a54cbbff76", + "0xa3d5de52f48df72c289ff713e445991f142390798cd42bd9d9dbefaee4af4f5faf09042d126b975cf6b98711c3072553", + "0x8e627302ff3d686cff8872a1b7c2a57b35f45bf2fc9aa42b049d8b4d6996a662b8e7cbac6597f0cb79b0cc4e29fbf133", + "0x8510702e101b39a1efbf4e504e6123540c34b5689645e70d0bac1ecc1baf47d86c05cef6c4317a4e99b4edaeb53f2d00", + "0xaa173f0ecbcc6088f878f8726d317748c81ebf501bba461f163b55d66099b191ec7c55f7702f351a9c8eb42cfa3280e2", + "0xb560a697eafab695bcef1416648a0a664a71e311ecbe5823ae903bd0ed2057b9d7574b9a86d3fe22aa3e6ddce38ea513", + "0x8df6304a3d9cf40100f3f687575419c998cd77e5cc27d579cf4f8e98642de3609af384a0337d145dd7c5635172d26a71", + "0x8105c7f3e4d30a29151849673853b457c1885c186c132d0a98e63096c3774bc9deb956cf957367e633d0913680bda307", + "0x95373fc22c0917c3c2044ac688c4f29a63ed858a45c0d6d2d0fe97afd6f532dcb648670594290c1c89010ecc69259bef", + "0x8c2fae9bcadab341f49b55230310df93cac46be42d4caa0d42e45104148a91e527af1b4209c0d972448162aed28fab64", + "0xb05a77baab70683f76209626eaefdda2d36a0b66c780a20142d23c55bd479ddd4ad95b24579384b6cf62c8eb4c92d021", + "0x8e6bc6a7ea2755b4aaa19c1c1dee93811fcde514f03485fdc3252f0ab7f032c315614f6336e57cea25dcfb8fb6084eeb", + "0xb656a27d06aade55eadae2ad2a1059198918ea6cc3fd22c0ed881294d34d5ac7b5e4700cc24350e27d76646263b223aa", + "0xa296469f24f6f56da92d713afcd4dd606e7da1f79dc4e434593c53695847eefc81c7c446486c4b3b8c8d00c90c166f14", + "0x87a326f57713ac2c9dffeb3af44b9f3c613a8f952676fc46343299122b47ee0f8d792abaa4b5db6451ced5dd153aabd0", + "0xb689e554ba9293b9c1f6344a3c8fcb6951d9f9eac4a2e2df13de021aade7c186be27500e81388e5b8bcab4c80f220a31", + "0x87ae0aa0aa48eac53d1ca5a7b93917de12db9e40ceabf8fdb40884ae771cfdf095411deef7c9f821af0b7070454a2608", + "0xa71ffa7eae8ace94e6c3581d4cb2ad25d48cbd27edc9ec45baa2c8eb932a4773c3272b2ffaf077b40f76942a1f3af7f2", + "0x94c218c91a9b73da6b7a495b3728f3028df8ad9133312fc0c03e8c5253b7ccb83ed14688fd4602e2fd41f29a0bc698bd", + "0xae1e77b90ca33728af07a4c03fb2ef71cd92e2618e7bf8ed4d785ce90097fc4866c29999eb84a6cf1819d75285a03af2", + "0xb7a5945b277dab9993cf761e838b0ac6eaa903d7111fca79f9fde3d4285af7a89bf6634a71909d095d7619d913972c9c", + "0x8c43b37be02f39b22029b20aca31bff661abce4471dca88aa3bddefd9c92304a088b2dfc8c4795acc301ca3160656af2", + "0xb32e5d0fba024554bd5fe8a793ebe8003335ddd7f585876df2048dcf759a01285fecb53daae4950ba57f3a282a4d8495", + "0x85ea7fd5e10c7b659df5289b2978b2c89e244f269e061b9a15fcab7983fc1962b63546e82d5731c97ec74b6804be63ef", + "0x96b89f39181141a7e32986ac02d7586088c5a9662cec39843f397f3178714d02f929af70630c12cbaba0268f8ba2d4fa", + "0x929ab1a2a009b1eb37a2817c89696a06426529ebe3f306c586ab717bd34c35a53eca2d7ddcdef36117872db660024af9", + "0xa696dccf439e9ca41511e16bf3042d7ec0e2f86c099e4fc8879d778a5ea79e33aa7ce96b23dc4332b7ba26859d8e674d", + "0xa8fe69a678f9a194b8670a41e941f0460f6e2dbc60470ab4d6ae2679cc9c6ce2c3a39df2303bee486dbfde6844e6b31a", + "0x95f58f5c82de2f2a927ca99bf63c9fc02e9030c7e46d0bf6b67fe83a448d0ae1c99541b59caf0e1ccab8326231af09a5", + "0xa57badb2c56ca2c45953bd569caf22968f76ed46b9bac389163d6fe22a715c83d5e94ae8759b0e6e8c2f27bff7748f3f", + "0x868726fd49963b24acb5333364dffea147e98f33aa19c7919dc9aca0fd26661cfaded74ede7418a5fadbe7f5ae67b67b", + "0xa8d8550dcc64d9f1dd7bcdab236c4122f2b65ea404bb483256d712c7518f08bb028ff8801f1da6aed6cbfc5c7062e33b", + "0x97e25a87dae23155809476232178538d4bc05d4ff0882916eb29ae515f2a62bfce73083466cc0010ca956aca200aeacc", + "0xb4ea26be3f4bd04aa82d7c4b0913b97bcdf5e88b76c57eb1a336cbd0a3eb29de751e1bc47c0e8258adec3f17426d0c71", + "0x99ee555a4d9b3cf2eb420b2af8e3bc99046880536116d0ce7193464ac40685ef14e0e3c442f604e32f8338cb0ef92558", + "0x8c64efa1da63cd08f319103c5c7a761221080e74227bbc58b8fb35d08aa42078810d7af3e60446cbaff160c319535648", + "0x8d9fd88040076c28420e3395cbdfea402e4077a3808a97b7939d49ecbcf1418fe50a0460e1c1b22ac3f6e7771d65169a", + "0xae3c19882d7a9875d439265a0c7003c8d410367627d21575a864b9cb4918de7dbdb58a364af40c5e045f3df40f95d337", + "0xb4f7bfacab7b2cafe393f1322d6dcc6f21ffe69cd31edc8db18c06f1a2b512c27bd0618091fd207ba8df1808e9d45914", + "0x94f134acd0007c623fb7934bcb65ef853313eb283a889a3ffa79a37a5c8f3665f3d5b4876bc66223610c21dc9b919d37", + "0xaa15f74051171daacdc1f1093d3f8e2d13da2833624b80a934afec86fc02208b8f55d24b7d66076444e7633f46375c6a", + "0xa32d6bb47ef9c836d9d2371807bafbbbbb1ae719530c19d6013f1d1f813c49a60e4fa51d83693586cba3a840b23c0404", + "0xb61b3599145ea8680011aa2366dc511a358b7d67672d5b0c5be6db03b0efb8ca5a8294cf220ea7409621f1664e00e631", + "0x859cafc3ee90b7ececa1ed8ef2b2fc17567126ff10ca712d5ffdd16aa411a5a7d8d32c9cab1fbf63e87dce1c6e2f5f53", + "0xa2fef1b0b2874387010e9ae425f3a9676d01a095d017493648bcdf3b31304b087ccddb5cf76abc4e1548b88919663b6b", + "0x939e18c73befc1ba2932a65ede34c70e4b91e74cc2129d57ace43ed2b3af2a9cc22a40fbf50d79a63681b6d98852866d", + "0xb3b4259d37b1b14aee5b676c9a0dd2d7f679ab95c120cb5f09f9fbf10b0a920cb613655ddb7b9e2ba5af4a221f31303c", + "0x997255fe51aaca6e5a9cb3359bcbf25b2bb9e30649bbd53a8a7c556df07e441c4e27328b38934f09c09d9500b5fabf66", + "0xabb91be2a2d860fd662ed4f1c6edeefd4da8dc10e79251cf87f06029906e7f0be9b486462718f0525d5e049472692cb7", + "0xb2398e593bf340a15f7801e1d1fbda69d93f2a32a889ec7c6ae5e8a37567ac3e5227213c1392ee86cfb3b56ec2787839", + "0x8ddf10ccdd72922bed36829a36073a460c2118fc7a56ff9c1ac72581c799b15c762cb56cb78e3d118bb9f6a7e56cb25e", + "0x93e6bc0a4708d16387cacd44cf59363b994dc67d7ada7b6d6dbd831c606d975247541b42b2a309f814c1bfe205681fc6", + "0xb93fc35c05998cffda2978e12e75812122831523041f10d52f810d34ff71944979054b04de0117e81ddf5b0b4b3e13c0", + "0x92221631c44d60d68c6bc7b287509f37ee44cbe5fdb6935cee36b58b17c7325098f98f7910d2c3ca5dc885ad1d6dabc7", + "0xa230124424a57fad3b1671f404a94d7c05f4c67b7a8fbacfccea28887b78d7c1ed40b92a58348e4d61328891cd2f6cee", + "0xa6a230edb8518a0f49d7231bc3e0bceb5c2ac427f045819f8584ba6f3ae3d63ed107a9a62aad543d7e1fcf1f20605706", + "0x845be1fe94223c7f1f97d74c49d682472585d8f772762baad8a9d341d9c3015534cc83d102113c51a9dea2ab10d8d27b", + "0xb44262515e34f2db597c8128c7614d33858740310a49cdbdf9c8677c5343884b42c1292759f55b8b4abc4c86e4728033", + "0x805592e4a3cd07c1844bc23783408310accfdb769cca882ad4d07d608e590a288b7370c2cb327f5336e72b7083a0e30f", + "0x95153e8b1140df34ee864f4ca601cb873cdd3efa634af0c4093fbaede36f51b55571ab271e6a133020cd34db8411241f", + "0x82878c1285cfa5ea1d32175c9401f3cc99f6bb224d622d3fd98cc7b0a27372f13f7ab463ce3a33ec96f9be38dbe2dfe3", + "0xb7588748f55783077c27fc47d33e20c5c0f5a53fc0ac10194c003aa09b9f055d08ec971effa4b7f760553997a56967b3", + "0xb36b4de6d1883b6951f59cfae381581f9c6352fcfcf1524fccdab1571a20f80441d9152dc6b48bcbbf00371337ca0bd5", + "0x89c5523f2574e1c340a955cbed9c2f7b5fbceb260cb1133160dabb7d41c2f613ec3f6e74bbfab3c4a0a6f0626dbe068f", + "0xa52f58cc39f968a9813b1a8ddc4e83f4219e4dd82c7aa1dd083bea7edf967151d635aa9597457f879771759b876774e4", + "0x8300a67c2e2e123f89704abfde095463045dbd97e20d4c1157bab35e9e1d3d18f1f4aaba9cbe6aa2d544e92578eaa1b6", + "0xac6a7f2918768eb6a43df9d3a8a04f8f72ee52f2e91c064c1c7d75cad1a3e83e5aba9fe55bb94f818099ac91ccf2e961", + "0x8d64a2b0991cf164e29835c8ddef6069993a71ec2a7de8157bbfa2e00f6367be646ed74cbaf524f0e9fe13fb09fa15fd", + "0x8b2ffe5a545f9f680b49d0a9797a4a11700a2e2e348c34a7a985fc278f0f12def6e06710f40f9d48e4b7fbb71e072229", + "0x8ab8f71cd337fa19178924e961958653abf7a598e3f022138b55c228440a2bac4176cea3aea393549c03cd38a13eb3fc", + "0x8419d28318c19ea4a179b7abb43669fe96347426ef3ac06b158d79c0acf777a09e8e770c2fb10e14b3a0421705990b23", + "0x8bacdac310e1e49660359d0a7a17fe3d334eb820e61ae25e84cb52f863a2f74cbe89c2e9fc3283745d93a99b79132354", + "0xb57ace3fa2b9f6b2db60c0d861ace7d7e657c5d35d992588aeed588c6ce3a80b6f0d49f8a26607f0b17167ab21b675e4", + "0x83e265cde477f2ecc164f49ddc7fb255bb05ff6adc347408353b7336dc3a14fdedc86d5a7fb23f36b8423248a7a67ed1", + "0xa60ada971f9f2d79d436de5d3d045f5ab05308cae3098acaf5521115134b2a40d664828bb89895840db7f7fb499edbc5", + "0xa63eea12efd89b62d3952bf0542a73890b104dd1d7ff360d4755ebfa148fd62de668edac9eeb20507967ea37fb220202", + "0xa0275767a270289adc991cc4571eff205b58ad6d3e93778ddbf95b75146d82517e8921bd0d0564e5b75fa0ccdab8e624", + "0xb9b03fd3bf07201ba3a039176a965d736b4ef7912dd9e9bf69fe1b57c330a6aa170e5521fe8be62505f3af81b41d7806", + "0xa95f640e26fb1106ced1729d6053e41a16e4896acac54992279ff873e5a969aad1dcfa10311e28b8f409ac1dab7f03bb", + "0xb144778921742418053cb3c70516c63162c187f00db2062193bb2c14031075dbe055d020cde761b26e8c58d0ea6df2c1", + "0x8432fbb799e0435ef428d4fefc309a05dd589bce74d7a87faf659823e8c9ed51d3e42603d878e80f439a38be4321c2fa", + "0xb08ddef14e42d4fd5d8bf39feb7485848f0060d43b51ed5bdda39c05fe154fb111d29719ee61a23c392141358c0cfcff", + "0x8ae3c5329a5e025b86b5370e06f5e61177df4bda075856fade20a17bfef79c92f54ed495f310130021ba94fb7c33632b", + "0x92b6d3c9444100b4d7391febfc1dddaa224651677c3695c47a289a40d7a96d200b83b64e6d9df51f534564f272a2c6c6", + "0xb432bc2a3f93d28b5e506d68527f1efeb2e2570f6be0794576e2a6ef9138926fdad8dd2eabfa979b79ab7266370e86bc", + "0x8bc315eacedbcfc462ece66a29662ca3dcd451f83de5c7626ef8712c196208fb3d8a0faf80b2e80384f0dd9772f61a23", + "0xa72375b797283f0f4266dec188678e2b2c060dfed5880fc6bb0c996b06e91a5343ea2b695adaab0a6fd183b040b46b56", + "0xa43445036fbaa414621918d6a897d3692fdae7b2961d87e2a03741360e45ebb19fcb1703d23f1e15bb1e2babcafc56ac", + "0xb9636b2ffe305e63a1a84bd44fb402442b1799bd5272638287aa87ca548649b23ce8ce7f67be077caed6aa2dbc454b78", + "0x99a30bf0921d854c282b83d438a79f615424f28c2f99d26a05201c93d10378ab2cd94a792b571ddae5d4e0c0013f4006", + "0x8648e3c2f93d70b392443be116b48a863e4b75991bab5db656a4ef3c1e7f645e8d536771dfe4e8d1ceda3be8d32978b0", + "0xab50dc9e6924c1d2e9d2e335b2d679fc7d1a7632e84964d3bac0c9fe57e85aa5906ec2e7b0399d98ddd022e9b19b5904", + "0xab729328d98d295f8f3272afaf5d8345ff54d58ff9884da14f17ecbdb7371857fdf2f3ef58080054e9874cc919b46224", + "0x83fa5da7592bd451cad3ad7702b4006332b3aae23beab4c4cb887fa6348317d234bf62a359e665b28818e5410c278a09", + "0x8bdbff566ae9d368f114858ef1f009439b3e9f4649f73efa946e678d6c781d52c69af195df0a68170f5f191b2eac286b", + "0x91245e59b4425fd4edb2a61d0d47c1ccc83d3ced8180de34887b9655b5dcda033d48cde0bdc3b7de846d246c053a02e8", + "0xa2cb00721e68f1cad8933947456f07144dc69653f96ceed845bd577d599521ba99cdc02421118971d56d7603ed118cbf", + "0xaf8cd66d303e808b22ec57860dd909ca64c27ec2c60e26ffecfdc1179d8762ffd2739d87b43959496e9fee4108df71df", + "0x9954136812dffcd5d3f167a500e7ab339c15cfc9b3398d83f64b0daa3dd5b9a851204f424a3493b4e326d3de81e50a62", + "0x93252254d12511955f1aa464883ad0da793f84d900fea83e1df8bca0f2f4cf5b5f9acbaec06a24160d33f908ab5fea38", + "0x997cb55c26996586ba436a95566bd535e9c22452ca5d2a0ded2bd175376557fa895f9f4def4519241ff386a063f2e526", + "0xa12c78ad451e0ac911260ade2927a768b50cb4125343025d43474e7f465cdc446e9f52a84609c5e7e87ae6c9b3f56cda", + "0xa789d4ca55cbba327086563831b34487d63d0980ba8cf55197c016702ed6da9b102b1f0709ce3da3c53ff925793a3d73", + "0xa5d76acbb76741ce85be0e655b99baa04f7f587347947c0a30d27f8a49ae78cce06e1cde770a8b618d3db402be1c0c4b", + "0x873c0366668c8faddb0eb7c86f485718d65f8c4734020f1a18efd5fa123d3ea8a990977fe13592cd01d17e60809cb5ff", + "0xb659b71fe70f37573ff7c5970cc095a1dc0da3973979778f80a71a347ef25ad5746b2b9608bad4ab9a4a53a4d7df42d7", + "0xa34cbe05888e5e5f024a2db14cb6dcdc401a9cbd13d73d3c37b348f68688f87c24ca790030b8f84fef9e74b4eab5e412", + "0x94ce8010f85875c045b0f014db93ef5ab9f1f6842e9a5743dce9e4cb872c94affd9e77c1f1d1ab8b8660b52345d9acb9", + "0xadefa9b27a62edc0c5b019ddd3ebf45e4de846165256cf6329331def2e088c5232456d3de470fdce3fa758bfdd387512", + "0xa6b83821ba7c1f83cc9e4529cf4903adb93b26108e3d1f20a753070db072ad5a3689643144bdd9c5ea06bb9a7a515cd0", + "0xa3a9ddedc2a1b183eb1d52de26718151744db6050f86f3580790c51d09226bf05f15111691926151ecdbef683baa992c", + "0xa64bac89e7686932cdc5670d07f0b50830e69bfb8c93791c87c7ffa4913f8da881a9d8a8ce8c1a9ce5b6079358c54136", + "0xa77b5a63452cb1320b61ab6c7c2ef9cfbcade5fd4727583751fb2bf3ea330b5ca67757ec1f517bf4d503ec924fe32fbd", + "0x8746fd8d8eb99639d8cd0ca34c0d9c3230ed5a312aab1d3d925953a17973ee5aeb66e68667e93caf9cb817c868ea8f3d", + "0x88a2462a26558fc1fbd6e31aa8abdc706190a17c27fdc4217ffd2297d1b1f3321016e5c4b2384c5454d5717dc732ed03", + "0xb78893a97e93d730c8201af2e0d3b31cb923d38dc594ffa98a714e627c473d42ea82e0c4d2eeb06862ee22a9b2c54588", + "0x920cc8b5f1297cf215a43f6fc843e379146b4229411c44c0231f6749793d40f07b9af7699fd5d21fd69400b97febe027", + "0xa0f0eafce1e098a6b58c7ad8945e297cd93aaf10bc55e32e2e32503f02e59fc1d5776936577d77c0b1162cb93b88518b", + "0x98480ba0064e97a2e7a6c4769b4d8c2a322cfc9a3b2ca2e67e9317e2ce04c6e1108169a20bd97692e1cb1f1423b14908", + "0x83dbbb2fda7e287288011764a00b8357753a6a44794cc8245a2275237f11affdc38977214e463ad67aec032f3dfa37e9", + "0x86442fff37598ce2b12015ff19b01bb8a780b40ad353d143a0f30a06f6d23afd5c2b0a1253716c855dbf445cc5dd6865", + "0xb8a4c60c5171189414887847b9ed9501bff4e4c107240f063e2d254820d2906b69ef70406c585918c4d24f1dd052142b", + "0x919f33a98e84015b2034b57b5ffe9340220926b2c6e45f86fd79ec879dbe06a148ae68b77b73bf7d01bd638a81165617", + "0x95c13e78d89474a47fbc0664f6f806744b75dede95a479bbf844db4a7f4c3ae410ec721cb6ffcd9fa9c323da5740d5ae", + "0xab7151acc41fffd8ec6e90387700bcd7e1cde291ea669567295bea1b9dd3f1df2e0f31f3588cd1a1c08af8120aca4921", + "0x80e74c5c47414bd6eeef24b6793fb1fa2d8fb397467045fcff887c52476741d5bc4ff8b6d3387cb53ad285485630537f", + "0xa296ad23995268276aa351a7764d36df3a5a3cffd7dbeddbcea6b1f77adc112629fdeffa0918b3242b3ccd5e7587e946", + "0x813d2506a28a2b01cb60f49d6bd5e63c9b056aa56946faf2f33bd4f28a8d947569cfead3ae53166fc65285740b210f86", + "0x924b265385e1646287d8c09f6c855b094daaee74b9e64a0dddcf9ad88c6979f8280ba30c8597b911ef58ddb6c67e9fe3", + "0x8d531513c70c2d3566039f7ca47cd2352fd2d55b25675a65250bdb8b06c3843db7b2d29c626eed6391c238fc651cf350", + "0x82b338181b62fdc81ceb558a6843df767b6a6e3ceedc5485664b4ea2f555904b1a45fbb35f6cf5d96f27da10df82a325", + "0x92e62faaedea83a37f314e1d3cb4faaa200178371d917938e59ac35090be1db4b4f4e0edb78b9c991de202efe4f313d8", + "0x99d645e1b642c2dc065bac9aaa0621bc648c9a8351efb6891559c3a41ba737bd155fb32d7731950514e3ecf4d75980e4", + "0xb34a13968b9e414172fb5d5ece9a39cf2eb656128c3f2f6cc7a9f0c69c6bae34f555ecc8f8837dc34b5e470e29055c78", + "0xa2a0bb7f3a0b23a2cbc6585d59f87cd7e56b2bbcb0ae48f828685edd9f7af0f5edb4c8e9718a0aaf6ef04553ba71f3b7", + "0x8e1a94bec053ed378e524b6685152d2b52d428266f2b6eadd4bcb7c4e162ed21ab3e1364879673442ee2162635b7a4d8", + "0x9944adaff14a85eab81c73f38f386701713b52513c4d4b838d58d4ffa1d17260a6d056b02334850ea9a31677c4b078bd", + "0xa450067c7eceb0854b3eca3db6cf38669d72cb7143c3a68787833cbca44f02c0be9bfbe082896f8a57debb13deb2afb1", + "0x8be4ad3ac9ef02f7df09254d569939757101ee2eda8586fefcd8c847adc1efe5bdcb963a0cafa17651befaafb376a531", + "0x90f6de91ea50255f148ac435e08cf2ac00c772a466e38155bd7e8acf9197af55662c7b5227f88589b71abe9dcf7ba343", + "0x86e5a24f0748b106dee2d4d54e14a3b0af45a96cbee69cac811a4196403ebbee17fd24946d7e7e1b962ac7f66dbaf610", + "0xafdd96fbcda7aa73bf9eeb2292e036c25753d249caee3b9c013009cc22e10d3ec29e2aa6ddbb21c4e949b0c0bccaa7f4", + "0xb5a4e7436d5473647c002120a2cb436b9b28e27ad4ebdd7c5f122b91597c507d256d0cbd889d65b3a908531936e53053", + "0xb632414c3da704d80ac2f3e5e0e9f18a3637cdc2ebeb613c29300745582427138819c4e7b0bec3099c1b8739dac1807b", + "0xa28df1464d3372ce9f37ef1db33cc010f752156afae6f76949d98cd799c0cf225c20228ae86a4da592d65f0cffe3951b", + "0x898b93d0a31f7d3f11f253cb7a102db54b669fd150da302d8354d8e02b1739a47cb9bd88015f3baf12b00b879442464e", + "0x96fb88d89a12049091070cb0048a381902965e67a8493e3991eaabe5d3b7ff7eecd5c94493a93b174df3d9b2c9511755", + "0xb899cb2176f59a5cfba3e3d346813da7a82b03417cad6342f19cc8f12f28985b03bf031e856a4743fd7ebe16324805b0", + "0xa60e2d31bc48e0c0579db15516718a03b73f5138f15037491f4dae336c904e312eda82d50862f4debd1622bb0e56d866", + "0x979fc8b987b5cef7d4f4b58b53a2c278bd25a5c0ea6f41c715142ea5ff224c707de38451b0ad3aa5e749aa219256650a", + "0xb2a75bff18e1a6b9cf2a4079572e41205741979f57e7631654a3c0fcec57c876c6df44733c9da3d863db8dff392b44a3", + "0xb7a0f0e811222c91e3df98ff7f286b750bc3b20d2083966d713a84a2281744199e664879401e77470d44e5a90f3e5181", + "0x82b74ba21c9d147fbc338730e8f1f8a6e7fc847c3110944eb17a48bea5e06eecded84595d485506d15a3e675fd0e5e62", + "0xa7f44eef817d5556f0d1abcf420301217d23c69dd2988f44d91ea1f1a16c322263cbacd0f190b9ba22b0f141b9267b4f", + "0xaadb68164ede84fc1cb3334b3194d84ba868d5a88e4c9a27519eef4923bc4abf81aab8114449496c073c2a6a0eb24114", + "0xb5378605fabe9a8c12a5dc55ef2b1de7f51aedb61960735c08767a565793cea1922a603a6983dc25f7cea738d0f7c40d", + "0xa97a4a5cd8d51302e5e670aee78fe6b5723f6cc892902bbb4f131e82ca1dfd5de820731e7e3367fb0c4c1922a02196e3", + "0x8bdfeb15c29244d4a28896f2b2cb211243cd6a1984a3f5e3b0ebe5341c419beeab3304b390a009ffb47588018034b0ea", + "0xa9af3022727f2aa2fca3b096968e97edad3f08edcbd0dbca107b892ae8f746a9c0485e0d6eb5f267999b23a845923ed0", + "0x8e7594034feef412f055590fbb15b6322dc4c6ab7a4baef4685bd13d71a83f7d682b5781bdfa0d1c659489ce9c2b8000", + "0x84977ca6c865ebee021c58106c1a4ad0c745949ecc5332948002fd09bd9b890524878d0c29da96fd11207621136421fe", + "0x8687551a79158e56b2375a271136756313122132a6670fa51f99a1b5c229ed8eea1655a734abae13228b3ebfd2a825dd", + "0xa0227d6708979d99edfc10f7d9d3719fd3fc68b0d815a7185b60307e4c9146ad2f9be2b8b4f242e320d4288ceeb9504c", + "0x89f75583a16735f9dd8b7782a130437805b34280ccea8dac6ecaee4b83fe96947e7b53598b06fecfffdf57ffc12cc445", + "0xa0056c3353227f6dd9cfc8e3399aa5a8f1d71edf25d3d64c982910f50786b1e395c508d3e3727ac360e3e040c64b5298", + "0xb070e61a6d813626144b312ded1788a6d0c7cec650a762b2f8df6e4743941dd82a2511cd956a3f141fc81e15f4e092da", + "0xb4e6db232e028a1f989bb5fc13416711f42d389f63564d60851f009dcffac01acfd54efa307aa6d4c0f932892d4e62b0", + "0x89b5991a67db90024ddd844e5e1a03ef9b943ad54194ae0a97df775dde1addf31561874f4e40fbc37a896630f3bbda58", + "0xad0e8442cb8c77d891df49cdb9efcf2b0d15ac93ec9be1ad5c3b3cca1f4647b675e79c075335c1f681d56f14dc250d76", + "0xb5d55a6ae65bb34dd8306806cb49b5ccb1c83a282ee47085cf26c4e648e19a52d9c422f65c1cd7e03ca63e926c5e92ea", + "0xb749501347e5ec07e13a79f0cb112f1b6534393458b3678a77f02ca89dca973fa7b30e55f0b25d8b92b97f6cb0120056", + "0x94144b4a3ffc5eec6ba35ce9c245c148b39372d19a928e236a60e27d7bc227d18a8cac9983851071935d8ffb64b3a34f", + "0x92bb4f9f85bc8c028a3391306603151c6896673135f8a7aefedd27acb322c04ef5dac982fc47b455d6740023e0dd3ea3", + "0xb9633a4a101461a782fc2aa092e9dbe4e2ad00987578f18cd7cf0021a909951d60fe79654eb7897806795f93c8ff4d1c", + "0x809f0196753024821b48a016eca5dbb449a7c55750f25981bb7a4b4c0e0846c09b8f6128137905055fc43a3f0deb4a74", + "0xa27dc9cdd1e78737a443570194a03d89285576d3d7f3a3cf15cc55b3013e42635d4723e2e8fe1d0b274428604b630db9", + "0x861f60f0462e04cd84924c36a28163def63e777318d00884ab8cb64c8df1df0bce5900342163edb60449296484a6c5bf", + "0xb7bc23fb4e14af4c4704a944253e760adefeca8caee0882b6bbd572c84434042236f39ae07a8f21a560f486b15d82819", + "0xb9a6eb492d6dd448654214bd01d6dc5ff12067a11537ab82023fc16167507ee25eed2c91693912f4155d1c07ed9650b3", + "0x97678af29c68f9a5e213bf0fb85c265303714482cfc4c2c00b4a1e8a76ed08834ee6af52357b143a1ca590fb0265ea5a", + "0x8a15b499e9eca5b6cac3070b5409e8296778222018ad8b53a5d1f6b70ad9bb10c68a015d105c941ed657bf3499299e33", + "0xb487fefede2e8091f2c7bfe85770db2edff1db83d4effe7f7d87bff5ab1ace35e9b823a71adfec6737fede8d67b3c467", + "0x8b51b916402aa2c437fce3bcad6dad3be8301a1a7eab9d163085b322ffb6c62abf28637636fe6114573950117fc92898", + "0xb06a2106d031a45a494adec0881cb2f82275dff9dcdd2bc16807e76f3bec28a6734edd3d54f0be8199799a78cd6228ad", + "0xaf0a185391bbe2315eb97feac98ad6dd2e5d931d012c621abd6e404a31cc188b286fef14871762190acf086482b2b5e2", + "0x8e78ee8206506dd06eb7729e32fceda3bebd8924a64e4d8621c72e36758fda3d0001af42443851d6c0aea58562870b43", + "0xa1ba52a569f0461aaf90b49b92be976c0e73ec4a2c884752ee52ffb62dd137770c985123d405dfb5de70692db454b54a", + "0x8d51b692fa1543c51f6b62b9acb8625ed94b746ef96c944ca02859a4133a5629da2e2ce84e111a7af8d9a5b836401c64", + "0xa7a20d45044cf6492e0531d0b8b26ffbae6232fa05a96ed7f06bdb64c2b0f5ca7ec59d5477038096a02579e633c7a3ff", + "0x84df867b98c53c1fcd4620fef133ee18849c78d3809d6aca0fb6f50ff993a053a455993f216c42ab6090fa5356b8d564", + "0xa7227c439f14c48e2577d5713c97a5205feb69acb0b449152842e278fa71e8046adfab468089c8b2288af1fc51fa945b", + "0x855189b3a105670779997690876dfaa512b4a25a24931a912c2f0f1936971d2882fb4d9f0b3d9daba77eaf660e9d05d5", + "0xb5696bd6706de51c502f40385f87f43040a5abf99df705d6aac74d88c913b8ecf7a99a63d7a37d9bdf3a941b9e432ff5", + "0xab997beb0d6df9c98d5b49864ef0b41a2a2f407e1687dfd6089959757ba30ed02228940b0e841afe6911990c74d536c4", + "0xb36b65f85546ebfdbe98823d5555144f96b4ab39279facd19c0de3b8919f105ba0315a0784dce4344b1bc62d8bb4a5a3", + "0xb8371f0e4450788720ac5e0f6cd3ecc5413d33895083b2c168d961ec2b5c3de411a4cc0712481cbe8df8c2fa1a7af006", + "0x98325d8026b810a8b7a114171ae59a57e8bbc9848e7c3df992efc523621729fd8c9f52114ce01d7730541a1ada6f1df1", + "0x8d0e76dbd37806259486cd9a31bc8b2306c2b95452dc395546a1042d1d17863ef7a74c636b782e214d3aa0e8d717f94a", + "0xa4e15ead76da0214d702c859fb4a8accdcdad75ed08b865842bd203391ec4cba2dcc916455e685f662923b96ee0c023f", + "0x8618190972086ebb0c4c1b4a6c94421a13f378bc961cc8267a301de7390c5e73c3333864b3b7696d81148f9d4843fd02", + "0x85369d6cc7342e1aa15b59141517d8db8baaaeb7ab9670f3ba3905353948d575923d283b7e5a05b13a30e7baf1208a86", + "0x87c51ef42233c24a6da901f28c9a075d9ba3c625687c387ad6757b72ca6b5a8885e6902a3082da7281611728b1e45f26", + "0xaa6348a4f71927a3106ad0ea8b02fc8d8c65531e4ab0bd0a17243e66f35afe252e40ab8eef9f13ae55a72566ffdaff5c", + "0x96a3bc976e9d03765cc3fee275fa05b4a84c94fed6b767e23ca689394501e96f56f7a97cffddc579a6abff632bf153be", + "0x97dbf96c6176379fdb2b888be4e757b2bca54e74124bd068d3fa1dbd82a011bbeb75079da38e0cd22a761fe208ecad9b", + "0xb70cf0a1d14089a4129ec4e295313863a59da8c7e26bf74cc0e704ed7f0ee4d7760090d0ddf7728180f1bf2c5ac64955", + "0x882d664714cc0ffe53cbc9bef21f23f3649824f423c4dbad1f893d22c4687ab29583688699efc4d5101aa08b0c3e267a", + "0x80ecb7cc963e677ccaddbe3320831dd6ee41209acf4ed41b16dc4817121a3d86a1aac9c4db3d8c08a55d28257088af32", + "0xa25ba667d832b145f9ce18c3f9b1bd00737aa36db020e1b99752c8ef7d27c6c448982bd8d352e1b6df266b8d8358a8d5", + "0x83734841c13dee12759d40bdd209b277e743b0d08cc0dd1e0b7afd2d65bfa640400eefcf6be4a52e463e5b3d885eeac6", + "0x848d16505b04804afc773aebabb51b36fd8aacfbb0e09b36c0d5d57df3c0a3b92f33e7d5ad0a7006ec46ebb91df42b8c", + "0x909a8d793f599e33bb9f1dc4792a507a97169c87cd5c087310bc05f30afcd247470b4b56dec59894c0fb1d48d39bb54e", + "0x8e558a8559df84a1ba8b244ece667f858095c50bb33a5381e60fcc6ba586b69693566d8819b4246a27287f16846c1dfa", + "0x84d6b69729f5aaa000cd710c2352087592cfbdf20d5e1166977e195818e593fa1a50d1e04566be23163a2523dc1612f1", + "0x9536d262b7a42125d89f4f32b407d737ba8d9242acfc99d965913ab3e043dcac9f7072a43708553562cac4cba841df30", + "0x9598548923ca119d6a15fd10861596601dd1dedbcccca97bb208cdc1153cf82991ea8cc17686fbaa867921065265970c", + "0xb87f2d4af6d026e4d2836bc3d390a4a18e98a6e386282ce96744603bab74974272e97ac2da281afa21885e2cbb3a8001", + "0x991ece62bf07d1a348dd22191868372904b9f8cf065ae7aa4e44fd24a53faf6d851842e35fb472895963aa1992894918", + "0xa8c53dea4c665b30e51d22ca6bc1bc78aaf172b0a48e64a1d4b93439b053877ec26cb5221c55efd64fa841bbf7d5aff4", + "0x93487ec939ed8e740f15335b58617c3f917f72d07b7a369befd479ae2554d04deb240d4a14394b26192efae4d2f4f35d", + "0xa44793ab4035443f8f2968a40e043b4555960193ffa3358d22112093aadfe2c136587e4139ffd46d91ed4107f61ea5e0", + "0xb13fe033da5f0d227c75927d3dacb06dbaf3e1322f9d5c7c009de75cdcba5e308232838785ab69a70f0bedea755e003f", + "0x970a29b075faccd0700fe60d1f726bdebf82d2cc8252f4a84543ebd3b16f91be42a75c9719a39c4096139f0f31393d58", + "0xa4c3eb1f7160f8216fc176fb244df53008ff32f2892363d85254002e66e2de21ccfe1f3b1047589abee50f29b9d507e3", + "0x8c552885eab04ba40922a8f0c3c38c96089c95ff1405258d3f1efe8d179e39e1295cbf67677894c607ae986e4e6b1fb0", + "0xb3671746fa7f848c4e2ae6946894defadd815230b906b419143523cc0597bc1d6c0a4c1e09d49b66b4a2c11cde3a4de3", + "0x937a249a95813a5e2ef428e355efd202e15a37d73e56cfb7e57ea9f943f2ce5ca8026f2f1fd25bf164ba89d07077d858", + "0x83646bdf6053a04aa9e2f112499769e5bd5d0d10f2e13db3ca89bd45c0b3b7a2d752b7d137fb3909f9c62b78166c9339", + "0xb4eac4b91e763666696811b7ed45e97fd78310377ebea1674b58a2250973f80492ac35110ed1240cd9bb2d17493d708c", + "0x82db43a99bc6573e9d92a3fd6635dbbb249ac66ba53099c3c0c8c8080b121dd8243cd5c6e36ba0a4d2525bae57f5c89c", + "0xa64d6a264a681b49d134c655d5fc7756127f1ee7c93d328820f32bca68869f53115c0d27fef35fe71f7bc4fdaed97348", + "0x8739b7a9e2b4bc1831e7f04517771bc7cde683a5e74e052542517f8375a2f64e53e0d5ac925ef722327e7bb195b4d1d9", + "0x8f337cdd29918a2493515ebb5cf702bbe8ecb23b53c6d18920cc22f519e276ca9b991d3313e2d38ae17ae8bdfa4f8b7e", + "0xb0edeab9850e193a61f138ef2739fc42ceec98f25e7e8403bfd5fa34a7bc956b9d0898250d18a69fa4625a9b3d6129da", + "0xa9920f26fe0a6d51044e623665d998745c9eca5bce12051198b88a77d728c8238f97d4196f26e43b24f8841500b998d0", + "0x86e655d61502b979eeeeb6f9a7e1d0074f936451d0a1b0d2fa4fb3225b439a3770767b649256fe481361f481a8dbc276", + "0x84d3b32fa62096831cc3bf013488a9f3f481dfe293ae209ed19585a03f7db8d961a7a9dd0db82bd7f62d612707575d9c", + "0x81c827826ec9346995ffccf62a241e3b2d32f7357acd1b1f8f7a7dbc97022d3eb51b8a1230e23ce0b401d2e535e8cd78", + "0x94a1e40c151191c5b055b21e86f32e69cbc751dcbdf759a48580951834b96a1eed75914c0d19a38aefd21fb6c8d43d0c", + "0xab890222b44bc21b71f7c75e15b6c6e16bb03371acce4f8d4353ff3b8fcd42a14026589c5ed19555a3e15e4d18bfc3a3", + "0xaccb0be851e93c6c8cc64724cdb86887eea284194b10e7a43c90528ed97e9ec71ca69c6fac13899530593756dd49eab2", + "0xb630220aa9e1829c233331413ee28c5efe94ea8ea08d0c6bfd781955078b43a4f92915257187d8526873e6c919c6a1de", + "0xadd389a4d358c585f1274b73f6c3c45b58ef8df11f9d11221f620e241bf3579fba07427b288c0c682885a700cc1fa28d", + "0xa9fe6ca8bf2961a3386e8b8dcecc29c0567b5c0b3bcf3b0f9169f88e372b80151af883871fc5229815f94f43a6f5b2b0", + "0xad839ae003b92b37ea431fa35998b46a0afc3f9c0dd54c3b3bf7a262467b13ff3c323ada1c1ae02ac7716528bdf39e3e", + "0x9356d3fd0edcbbb65713c0f2a214394f831b26f792124b08c5f26e7f734b8711a87b7c4623408da6a091c9aef1f6af3c", + "0x896b25b083c35ac67f0af3784a6a82435b0e27433d4d74cd6d1eafe11e6827827799490fb1c77c11de25f0d75f14e047", + "0x8bfa019391c9627e8e5f05c213db625f0f1e51ec68816455f876c7e55b8f17a4f13e5aae9e3fb9e1cf920b1402ee2b40", + "0x8ba3a6faa6a860a8f3ce1e884aa8769ceded86380a86520ab177ab83043d380a4f535fe13884346c5e51bee68da6ab41", + "0xa8292d0844084e4e3bb7af92b1989f841a46640288c5b220fecfad063ee94e86e13d3d08038ec2ac82f41c96a3bfe14d", + "0x8229bb030b2fc566e11fd33c7eab7a1bb7b49fed872ea1f815004f7398cb03b85ea14e310ec19e1f23e0bdaf60f8f76c", + "0x8cfbf869ade3ec551562ff7f63c2745cc3a1f4d4dc853a0cd42dd5f6fe54228f86195ea8fe217643b32e9f513f34a545", + "0xac52a3c8d3270ddfe1b5630159da9290a5ccf9ccbdef43b58fc0a191a6c03b8a5974cf6e2bbc7bd98d4a40a3581482d7", + "0xab13decb9e2669e33a7049b8eca3ca327c40dea15ad6e0e7fa63ed506db1d258bc36ac88b35f65cae0984e937eb6575d", + "0xb5e748eb1a7a1e274ff0cc56311c198f2c076fe4b7e73e5f80396fe85358549df906584e6bb2c8195b3e2be7736850a5", + "0xb5cb911325d8f963c41f691a60c37831c7d3bbd92736efa33d1f77a22b3fde7f283127256c2f47e197571e6fe0b46149", + "0x8a01dc6ed1b55f26427a014faa347130738b191a06b800e32042a46c13f60b49534520214359d68eb2e170c31e2b8672", + "0xa72fa874866e19b2efb8e069328362bf7921ec375e3bcd6b1619384c3f7ee980f6cf686f3544e9374ff54b4d17a1629c", + "0x8db21092f7c5f110fba63650b119e82f4b42a997095d65f08f8237b02dd66fdf959f788df2c35124db1dbd330a235671", + "0x8c65d50433d9954fe28a09fa7ba91a70a590fe7ba6b3060f5e4be0f6cef860b9897fa935fb4ebc42133524eb071dd169", + "0xb4614058e8fa21138fc5e4592623e78b8982ed72aa35ee4391b164f00c68d277fa9f9eba2eeefc890b4e86eba5124591", + "0xab2ad3a1bce2fbd55ca6b7c23786171fe1440a97d99d6df4d80d07dd56ac2d7203c294b32fc9e10a6c259381a73f24a1", + "0x812ae3315fdc18774a8da3713a4679e8ed10b9405edc548c00cacbe25a587d32040566676f135e4723c5dc25df5a22e9", + "0xa464b75f95d01e5655b54730334f443c8ff27c3cb79ec7af4b2f9da3c2039c609908cd128572e1fd0552eb597e8cef8d", + "0xa0db3172e93ca5138fe419e1c49a1925140999f6eff7c593e5681951ee0ec1c7e454c851782cbd2b8c9bc90d466e90e0", + "0x806db23ba7d00b87d544eed926b3443f5f9c60da6b41b1c489fba8f73593b6e3b46ebfcab671ee009396cd77d5e68aa1", + "0x8bfdf2c0044cc80260994e1c0374588b6653947b178e8b312be5c2a05e05767e98ea15077278506aee7df4fee1aaf89e", + "0x827f6558c16841b5592ff089c9c31e31eb03097623524394813a2e4093ad2d3f8f845504e2af92195aaa8a1679d8d692", + "0x925c4f8eab2531135cd71a4ec88e7035b5eea34ba9d799c5898856080256b4a15ed1a746e002552e2a86c9c157e22e83", + "0xa9f9a368f0e0b24d00a35b325964c85b69533013f9c2cfad9708be5fb87ff455210f8cb8d2ce3ba58ca3f27495552899", + "0x8ac0d3bebc1cae534024187e7c71f8927ba8fcc6a1926cb61c2b6c8f26bb7831019e635a376146c29872a506784a4aaa", + "0x97c577be2cbbfdb37ad754fae9df2ada5fc5889869efc7e18a13f8e502fbf3f4067a509efbd46fd990ab47ce9a70f5a8", + "0x935e7d82bca19f16614aa43b4a3474e4d20d064e4bfdf1cea2909e5c9ab72cfe3e54dc50030e41ee84f3588cebc524e9", + "0x941aafc08f7c0d94cebfbb1f0aad5202c02e6e37f2c12614f57e727efa275f3926348f567107ee6d8914dd71e6060271", + "0xaf0fbc1ba05b4b5b63399686df3619968be5d40073de0313cbf5f913d3d4b518d4c249cdd2176468ccaa36040a484f58", + "0xa0c414f23f46ca6d69ce74c6f8a00c036cb0edd098af0c1a7d39c802b52cfb2d5dbdf93fb0295453d4646e2af7954d45", + "0x909cf39e11b3875bb63b39687ae1b5d1f5a15445e39bf164a0b14691b4ddb39a8e4363f584ef42213616abc4785b5d66", + "0xa92bac085d1194fbd1c88299f07a061d0bdd3f980b663e81e6254dbb288bf11478c0ee880e28e01560f12c5ccb3c0103", + "0x841705cd5cd76b943e2b7c5e845b9dd3c8defe8ef67e93078d6d5e67ade33ad4b0fd413bc196f93b0a4073c855cd97d4", + "0x8e7eb8364f384a9161e81d3f1d52ceca9b65536ae49cc35b48c3e2236322ba4ae9973e0840802d9fa4f4d82ea833544f", + "0xaed3ab927548bc8bec31467ba80689c71a168e34f50dcb6892f19a33a099f5aa6b3f9cb79f5c0699e837b9a8c7f27efe", + "0xb8fbf7696210a36e20edabd77839f4dfdf50d6d015cdf81d587f90284a9bcef7d2a1ff520728d7cc69a4843d6c20dedd", + "0xa9d533769ce6830211c884ae50a82a7bf259b44ac71f9fb11f0296fdb3981e6b4c1753fe744647b247ebc433a5a61436", + "0x8b4bdf90d33360b7f428c71cde0a49fb733badba8c726876945f58c620ce7768ae0e98fc8c31fa59d8955a4823336bb1", + "0x808d42238e440e6571c59e52a35ae32547d502dc24fd1759d8ea70a7231a95859baf30b490a4ba55fa2f3aaa11204597", + "0x85594701f1d2fee6dc1956bc44c7b31db93bdeec2f3a7d622c1a08b26994760773e3d57521a44cfd7e407ac3fd430429", + "0xa66de045ce7173043a6825e9dc440ac957e2efb6df0a337f4f8003eb0c719d873a52e6eba3cb0d69d977ca37d9187674", + "0x87a1c6a1fdff993fa51efa5c3ba034c079c0928a7d599b906336af7c2dcab9721ceaf3108c646490af9dff9a754f54b3", + "0x926424223e462ceb75aed7c22ade8a7911a903b7e5dd4bc49746ddce8657f4616325cd12667d4393ac52cdd866396d0e", + "0xb5dc96106593b42b30f06f0b0a1e0c1aafc70432e31807252d3674f0b1ea5e58eac8424879d655c9488d85a879a3e572", + "0x997ca0987735cc716507cb0124b1d266d218b40c9d8e0ecbf26a1d65719c82a637ce7e8be4b4815d307df717bde7c72a", + "0x92994d3f57a569b7760324bb5ae4e8e14e1633d175dab06aa57b8e391540e05f662fdc08b8830f489a063f59b689a688", + "0xa8087fcc6aa4642cb998bea11facfe87eb33b90a9aa428ab86a4124ad032fc7d2e57795311a54ec9f55cc120ebe42df1", + "0xa9bd7d1de6c0706052ca0b362e2e70e8c8f70f1f026ea189b4f87a08ce810297ebfe781cc8004430776c54c1a05ae90c", + "0x856d33282e8a8e33a3d237fb0a0cbabaf77ba9edf2fa35a831fdafcadf620561846aa6cbb6bdc5e681118e1245834165", + "0x9524a7aa8e97a31a6958439c5f3339b19370f03e86b89b1d02d87e4887309dbbe9a3a8d2befd3b7ed5143c8da7e0a8ad", + "0x824fdf433e090f8acbd258ac7429b21f36f9f3b337c6d0b71d1416a5c88a767883e255b2888b7c906dd2e9560c4af24c", + "0x88c7fee662ca7844f42ed5527996b35723abffd0d22d4ca203b9452c639a5066031207a5ae763dbc0865b3299d19b1ec", + "0x919dca5c5595082c221d5ab3a5bc230f45da7f6dec4eb389371e142c1b9c6a2c919074842479c2844b72c0d806170c0c", + "0xb939be8175715e55a684578d8be3ceff3087f60fa875fff48e52a6e6e9979c955efef8ff67cfa2b79499ea23778e33b0", + "0x873b6db725e7397d11bc9bed9ac4468e36619135be686790a79bc6ed4249058f1387c9a802ea86499f692cf635851066", + "0xaeae06db3ec47e9e5647323fa02fac44e06e59b885ad8506bf71b184ab3895510c82f78b6b22a5d978e8218e7f761e9f", + "0xb99c0a8359c72ab88448bae45d4bf98797a26bca48b0d4460cd6cf65a4e8c3dd823970ac3eb774ae5d0cea4e7fadf33e", + "0x8f10c8ec41cdfb986a1647463076a533e6b0eec08520c1562401b36bb063ac972aa6b28a0b6ce717254e35940b900e3c", + "0xa106d9be199636d7add43b942290269351578500d8245d4aae4c083954e4f27f64740a3138a66230391f2d0e6043a8de", + "0xa469997908244578e8909ff57cffc070f1dbd86f0098df3cfeb46b7a085cfecc93dc69ee7cad90ff1dc5a34d50fe580c", + "0xa4ef087bea9c20eb0afc0ee4caba7a9d29dfa872137828c721391273e402fb6714afc80c40e98bbd8276d3836bffa080", + "0xb07a013f73cd5b98dae0d0f9c1c0f35bff8a9f019975c4e1499e9bee736ca6fcd504f9bc32df1655ff333062382cff04", + "0xb0a77188673e87cc83348c4cc5db1eecf6b5184e236220c8eeed7585e4b928db849944a76ec60ef7708ef6dac02d5592", + "0xb1284b37e59b529f0084c0dacf0af6c0b91fc0f387bf649a8c74819debf606f7b07fc3e572500016fb145ec2b24e9f17", + "0x97b20b5b4d6b9129da185adfbf0d3d0b0faeba5b9715f10299e48ea0521709a8296a9264ce77c275a59c012b50b6519a", + "0xb9d37e946fae5e4d65c1fbfacc8a62e445a1c9d0f882e60cca649125af303b3b23af53c81d7bac544fb7fcfc7a314665", + "0x8e5acaac379f4bb0127efbef26180f91ff60e4c525bc9b798fc50dfaf4fe8a5aa84f18f3d3cfb8baead7d1e0499af753", + "0xb0c0b8ab1235bf1cda43d4152e71efc1a06c548edb964eb4afceb201c8af24240bf8ab5cae30a08604e77432b0a5faf0", + "0x8cc28d75d5c8d062d649cbc218e31c4d327e067e6dbd737ec0a35c91db44fbbd0d40ec424f5ed79814add16947417572", + "0x95ae6219e9fd47efaa9cb088753df06bc101405ba50a179d7c9f7c85679e182d3033f35b00dbba71fdcd186cd775c52e", + "0xb5d28fa09f186ebc5aa37453c9b4d9474a7997b8ae92748ecb940c14868792292ac7d10ade01e2f8069242b308cf97e5", + "0x8c922a0faa14cc6b7221f302df3342f38fc8521ec6c653f2587890192732c6da289777a6cd310747ea7b7d104af95995", + "0xb9ad5f660b65230de54de535d4c0fcae5bc6b59db21dea5500fdc12eea4470fb8ea003690fdd16d052523418d5e01e8c", + "0xa39a9dd41a0ff78c82979483731f1cd68d3921c3e9965869662c22e02dde3877802e180ba93f06e7346f96d9fa9261d2", + "0x8b32875977ec372c583b24234c27ed73aef00cdff61eb3c3776e073afbdeade548de9497c32ec6d703ff8ad0a5cb7fe4", + "0x9644cbe755a5642fe9d26cfecf170d3164f1848c2c2e271d5b6574a01755f3980b3fc870b98cf8528fef6ecef4210c16", + "0x81ea9d1fdd9dd66d60f40ce0712764b99da9448ae0b300f8324e1c52f154e472a086dda840cb2e0b9813dc8ce8afd4b5", + "0x906aaa4a7a7cdf01909c5cfbc7ded2abc4b869213cbf7c922d4171a4f2e637e56f17020b852ad339d83b8ac92f111666", + "0x939b5f11acbdeff998f2a080393033c9b9d8d5c70912ea651c53815c572d36ee822a98d6dfffb2e339f29201264f2cf4", + "0xaba4898bf1ccea9b9e2df1ff19001e05891581659c1cbbde7ee76c349c7fc7857261d9785823c9463a8aea3f40e86b38", + "0x83ca1a56b8a0be4820bdb5a9346357c68f9772e43f0b887729a50d2eb2a326bbcede676c8bf2e51d7c89bbd8fdb778a6", + "0x94e86e9fe6addfe2c3ee3a547267ed921f4230d877a85bb4442c2d9350c2fa9a9c54e6fe662de82d1a2407e4ab1691c2", + "0xa0cc3bdef671a59d77c6984338b023fa2b431b32e9ed2abe80484d73edc6540979d6f10812ecc06d4d0c5d4eaca7183c", + "0xb5343413c1b5776b55ea3c7cdd1f3af1f6bd802ea95effe3f2b91a523817719d2ecc3f8d5f3cc2623ace7e35f99ca967", + "0x92085d1ed0ed28d8cabe3e7ff1905ed52c7ceb1eac5503760c52fb5ee3a726aba7c90b483c032acc3f166b083d7ec370", + "0x8ec679520455275cd957fca8122724d287db5df7d29f1702a322879b127bff215e5b71d9c191901465d19c86c8d8d404", + "0xb65eb2c63d8a30332eb24ee8a0c70156fc89325ebbb38bacac7cf3f8636ad8a472d81ccca80423772abc00192d886d8a", + "0xa9fe1c060b974bee4d590f2873b28635b61bfcf614e61ff88b1be3eee4320f4874e21e8d666d8ac8c9aba672efc6ecae", + "0xb3fe2a9a389c006a831dea7e777062df84b5c2803f9574d7fbe10b7e1c125817986af8b6454d6be9d931a5ac94cfe963", + "0x95418ad13b734b6f0d33822d9912c4c49b558f68d08c1b34a0127fcfa666bcae8e6fda8832d2c75bb9170794a20e4d7c", + "0xa9a7df761e7f18b79494bf429572140c8c6e9d456c4d4e336184f3f51525a65eb9582bea1e601bdb6ef8150b7ca736a5", + "0xa0de03b1e75edf7998c8c1ac69b4a1544a6fa675a1941950297917366682e5644a4bda9cdeedfaf9473d7fccd9080b0c", + "0xa61838af8d95c95edf32663a68f007d95167bf6e41b0c784a30b22d8300cfdd5703bd6d16e86396638f6db6ae7e42a85", + "0x8866d62084d905c145ff2d41025299d8b702ac1814a7dec4e277412c161bc9a62fed735536789cb43c88693c6b423882", + "0x91da22c378c81497fe363e7f695c0268443abee50f8a6625b8a41e865638a643f07b157ee566de09ba09846934b4e2d7", + "0x941d21dd57c9496aa68f0c0c05507405fdd413acb59bc668ce7e92e1936c68ec4b065c3c30123319884149e88228f0b2", + "0xa77af9b094bc26966ddf2bf9e1520c898194a5ccb694915950dadc204facbe3066d3d89f50972642d76b14884cfbaa21", + "0x8e76162932346869f4618bde744647f7ab52ab498ad654bdf2a4feeb986ac6e51370841e5acbb589e38b6e7142bb3049", + "0xb60979ace17d6937ece72e4f015da4657a443dd01cebc7143ef11c09e42d4aa8855999a65a79e2ea0067f31c9fc2ab0f", + "0xb3e2ffdd5ee6fd110b982fd4fad4b93d0fca65478f986d086eeccb0804960bfaa1919afa743c2239973ea65091fe57d2", + "0x8ce0ce05e7d7160d44574011da687454dbd3c8b8290aa671731b066e2c82f8cf2d63cb8e932d78c6122ec610e44660e6", + "0xab005dd8d297045c39e2f72fb1c48edb501ccf3575d3d04b9817b3afee3f0bb0f3f53f64bda37d1d9cde545aae999bae", + "0x95bd7edb4c4cd60e3cb8a72558845a3cce6bb7032ccdf33d5a49ebb6ddf203bc3c79e7b7e550735d2d75b04c8b2441e8", + "0x889953ee256206284094e4735dbbb17975bafc7c3cb94c9fbfee4c3e653857bfd49e818f64a47567f721b98411a3b454", + "0xb188423e707640ab0e75a061e0b62830cde8afab8e1ad3dae30db69ffae4e2fc005bababbdcbd7213b918ed4f70e0c14", + "0xa97e0fafe011abd70d4f99a0b36638b3d6e7354284588f17a88970ed48f348f88392779e9a038c6cbc9208d998485072", + "0x87db11014a91cb9b63e8dfaa82cdebca98272d89eb445ee1e3ff9dbaf2b3fad1a03b888cffc128e4fe208ed0dddece0f", + "0xaad2e40364edd905d66ea4ac9d51f9640d6fda9a54957d26ba233809851529b32c85660fa401dbee3679ec54fa6dd966", + "0x863e99336ca6edf03a5a259e59a2d0f308206e8a2fb320cfc0be06057366df8e0f94b33a28f574092736b3c5ada84270", + "0xb34bcc56a057589f34939a1adc51de4ff6a9f4fee9c7fa9aa131e28d0cf0759a0c871b640162acdfbf91f3f1b59a3703", + "0x935dd28f2896092995c5eff1618e5b6efe7a40178888d7826da9b0503c2d6e68a28e7fac1a334e166d0205f0695ef614", + "0xb842cd5f8f5de5ca6c68cb4a5c1d7b451984930eb4cc18fd0934d52fdc9c3d2d451b1c395594d73bc3451432bfba653f", + "0x9014537885ce2debad736bc1926b25fdab9f69b216bf024f589c49dc7e6478c71d595c3647c9f65ff980b14f4bb2283b", + "0x8e827ccca1dd4cd21707140d10703177d722be0bbe5cac578db26f1ef8ad2909103af3c601a53795435b27bf95d0c9ed", + "0x8a0b8ad4d466c09d4f1e9167410dbe2edc6e0e6229d4b3036d30f85eb6a333a18b1c968f6ca6d6889bb08fecde017ef4", + "0x9241ee66c0191b06266332dc9161dede384c4bb4e116dbd0890f3c3790ec5566da4568243665c4725b718ac0f6b5c179", + "0xaeb4d5fad81d2b505d47958a08262b6f1b1de9373c2c9ba6362594194dea3e002ab03b8cbb43f867be83065d3d370f19", + "0x8781bc83bb73f7760628629fe19e4714b494dbed444c4e4e4729b7f6a8d12ee347841a199888794c2234f51fa26fc2b9", + "0xb58864f0acd1c2afa29367e637cbde1968d18589245d9936c9a489c6c495f54f0113ecdcbe4680ac085dd3c397c4d0c3", + "0x94a24284afaeead61e70f3e30f87248d76e9726759445ca18cdb9360586c60cc9f0ec1c397f9675083e0b56459784e2e", + "0xaed358853f2b54dcbddf865e1816c2e89be12e940e1abfa661e2ee63ffc24a8c8096be2072fa83556482c0d89e975124", + "0xb95374e6b4fc0765708e370bc881e271abf2e35c08b056a03b847e089831ef4fe3124b9c5849d9c276eb2e35b3daf264", + "0xb834cdbcfb24c8f84bfa4c552e7fadc0028a140952fd69ed13a516e1314a4cd35d4b954a77d51a1b93e1f5d657d0315d", + "0x8fb6d09d23bfa90e7443753d45a918d91d75d8e12ec7d016c0dfe94e5c592ba6aaf483d2f16108d190822d955ad9cdc3", + "0xaa315cd3c60247a6ad4b04f26c5404c2713b95972843e4b87b5a36a89f201667d70f0adf20757ebe1de1b29ae27dda50", + "0xa116862dca409db8beff5b1ccd6301cdd0c92ca29a3d6d20eb8b87f25965f42699ca66974dd1a355200157476b998f3b", + "0xb4c2f5fe173c4dc8311b60d04a65ce1be87f070ac42e13cd19c6559a2931c6ee104859cc2520edebbc66a13dc7d30693", + "0x8d4a02bf99b2260c334e7d81775c5cf582b00b0c982ce7745e5a90624919028278f5e9b098573bad5515ce7fa92a80c8", + "0x8543493bf564ce6d97bd23be9bff1aba08bd5821ca834f311a26c9139c92a48f0c2d9dfe645afa95fec07d675d1fd53b", + "0x9344239d13fde08f98cb48f1f87d34cf6abe8faecd0b682955382a975e6eed64e863fa19043290c0736261622e00045c", + "0xaa49d0518f343005ca72b9e6c7dcaa97225ce6bb8b908ebbe7b1a22884ff8bfb090890364e325a0d414ad180b8f161d1", + "0x907d7fd3e009355ab326847c4a2431f688627faa698c13c03ffdd476ecf988678407f029b8543a475dcb3dafdf2e7a9c", + "0x845f1f10c6c5dad2adc7935f5cd2e2b32f169a99091d4f1b05babe7317b9b1cdce29b5e62f947dc621b9acbfe517a258", + "0x8f3be8e3b380ea6cdf9e9c237f5e88fd5a357e5ded80ea1fc2019810814de82501273b4da38916881125b6fa0cfd4459", + "0xb9c7f487c089bf1d20c822e579628db91ed9c82d6ca652983aa16d98b4270c4da19757f216a71b9c13ddee3e6e43705f", + "0x8ba2d8c88ad2b872db104ea8ddbb006ec2f3749fd0e19298a804bb3a5d94de19285cc7fb19fee58a66f7851d1a66c39f", + "0x9375ecd3ed16786fe161af5d5c908f56eeb467a144d3bbddfc767e90065b7c94fc53431adebecba2b6c9b5821184d36e", + "0xa49e069bfadb1e2e8bff6a4286872e2a9765d62f0eaa4fcb0e5af4bbbed8be3510fb19849125a40a8a81d1e33e81c3eb", + "0x9522cc66757b386aa6b88619525c8ce47a5c346d590bb3647d12f991e6c65c3ab3c0cfc28f0726b6756c892eae1672be", + "0xa9a0f1f51ff877406fa83a807aeb17b92a283879f447b8a2159653db577848cc451cbadd01f70441e351e9ed433c18bc", + "0x8ff7533dcff6be8714df573e33f82cf8e9f2bcaaa43e939c4759d52b754e502717950de4b4252fb904560fc31dce94a4", + "0x959724671e265a28d67c29d95210e97b894b360da55e4cf16e6682e7912491ed8ca14bfaa4dce9c25a25b16af580494f", + "0x92566730c3002f4046c737032487d0833c971e775de59fe02d9835c9858e2e3bc37f157424a69764596c625c482a2219", + "0xa84b47ceff13ed9c3e5e9cdf6739a66d3e7c2bd8a6ba318fefb1a9aecf653bb2981da6733ddb33c4b0a4523acc429d23", + "0xb4ddf571317e44f859386d6140828a42cf94994e2f1dcbcc9777f4eebbfc64fc1e160b49379acc27c4672b8e41835c5d", + "0x8ab95c94072b853d1603fdd0a43b30db617d13c1d1255b99075198e1947bfa5f59aed2b1147548a1b5e986cd9173d15c", + "0x89511f2eab33894fd4b3753d24249f410ff7263052c1fef6166fc63a79816656b0d24c529e45ccce6be28de6e375d916", + "0xa0866160ca63d4f2be1b4ea050dac6b59db554e2ebb4e5b592859d8df339b46fd7cb89aaed0951c3ee540aee982c238a", + "0x8fcc5cbba1b94970f5ff2eb1922322f5b0aa7d918d4b380c9e7abfd57afd8b247c346bff7b87af82efbce3052511cd1b", + "0x99aeb2a5e846b0a2874cca02c66ed40d5569eb65ab2495bc3f964a092e91e1517941f2688e79f8cca49cd3674c4e06dc", + "0xb7a096dc3bad5ca49bee94efd884aa3ff5615cf3825cf95fbe0ce132e35f46581d6482fa82666c7ef5f1643eaee8f1ca", + "0x94393b1da6eaac2ffd186b7725eca582f1ddc8cdd916004657f8a564a7c588175cb443fc6943b39029f5bbe0add3fad8", + "0x884b85fe012ccbcd849cb68c3ad832d83b3ef1c40c3954ffdc97f103b1ed582c801e1a41d9950f6bddc1d11f19d5ec76", + "0xb00061c00131eded8305a7ce76362163deb33596569afb46fe499a7c9d7a0734c084d336b38d168024c2bb42b58e7660", + "0xa439153ac8e6ca037381e3240e7ba08d056c83d7090f16ed538df25901835e09e27de2073646e7d7f3c65056af6e4ce7", + "0x830fc9ca099097d1f38b90e6843dc86f702be9d20bdacc3e52cae659dc41df5b8d2c970effa6f83a5229b0244a86fe22", + "0xb81ea2ffaaff2bb00dd59a9ab825ba5eed4db0d8ac9c8ed1a632ce8f086328a1cddd045fbe1ace289083c1325881b7e7", + "0xb51ea03c58daf2db32c99b9c4789b183365168cb5019c72c4cc91ac30b5fb7311d3db76e6fa41b7cd4a8c81e2f6cdc94", + "0xa4170b2c6d09ca5beb08318730419b6f19215ce6c631c854116f904be3bc30dd85a80c946a8ab054d3e307afaa3f8fbc", + "0x897cc42ff28971ff54d2a55dd6b35cfb8610ac902f3c06e3a5cea0e0a257e870c471236a8e84709211c742a09c5601a6", + "0xa18f2e98d389dace36641621488664ecbb422088ab03b74e67009b8b8acacaaa24fdcf42093935f355207d934adc52a8", + "0x92adcfb678cc2ba19c866f3f2b988fdcb4610567f3ab436cc0cb9acaf5a88414848d71133ebdbec1983e38e6190f1b5f", + "0xa86d43c2ce01b366330d3b36b3ca85f000c3548b8297e48478da1ee7d70d8576d4650cba7852ed125c0d7cb6109aa7f3", + "0x8ed31ceed9445437d7732dce78a762d72ff32a7636bfb3fd7974b7ae15db414d8184a1766915244355deb354fbc5803b", + "0x9268f70032584f416e92225d65af9ea18c466ebc7ae30952d56a4e36fd9ea811dde0a126da9220ba3c596ec54d8a335e", + "0x9433b99ee94f2d3fbdd63b163a2bdf440379334c52308bd24537f7defd807145a062ff255a50d119a7f29f4b85d250e3", + "0x90ce664f5e4628a02278f5cf5060d1a34f123854634b1870906e5723ac9afd044d48289be283b267d45fcbf3f4656aaf", + "0xaaf21c4d59378bb835d42ae5c5e5ab7a3c8c36a59e75997989313197752b79a472d866a23683b329ea69b048b87fa13e", + "0xb83c0589b304cec9ede549fde54f8a7c2a468c6657da8c02169a6351605261202610b2055c639b9ed2d5b8c401fb8f56", + "0x9370f326ea0f170c2c05fe2c5a49189f20aec93b6b18a5572a818cd4c2a6adb359e68975557b349fb54f065d572f4c92", + "0xac3232fa5ce6f03fca238bef1ce902432a90b8afce1c85457a6bee5571c033d4bceefafc863af04d4e85ac72a4d94d51", + "0x80d9ea168ff821b22c30e93e4c7960ce3ad3c1e6deeebedd342a36d01bd942419b187e2f382dbfd8caa34cca08d06a48", + "0xa387a3c61676fb3381eefa2a45d82625635a666e999aba30e3b037ec9e040f414f9e1ad9652abd3bcad63f95d85038db", + "0xa1b229fe32121e0b391b0f6e0180670b9dc89d79f7337de4c77ea7ad0073e9593846f06797c20e923092a08263204416", + "0x92164a9d841a2b828cedf2511213268b698520f8d1285852186644e9a0c97512cafa4bfbe29af892c929ebccd102e998", + "0x82ee2fa56308a67c7db4fd7ef539b5a9f26a1c2cc36da8c3206ba4b08258fbb3cec6fe5cdbd111433fb1ba2a1e275927", + "0x8c77bfe9e191f190a49d46f05600603fa42345592539b82923388d72392404e0b29a493a15e75e8b068dddcd444c2928", + "0x80b927f93ccf79dcf5c5b20bcf5a7d91d7a17bc0401bb7cc9b53a6797feac31026eb114257621f5a64a52876e4474cc1", + "0xb6b68b6501c37804d4833d5a063dd108a46310b1400549074e3cac84acc6d88f73948b7ad48d686de89c1ec043ae8c1a", + "0xab3da00f9bdc13e3f77624f58a3a18fc3728956f84b5b549d62f1033ae4b300538e53896e2d943f160618e05af265117", + "0xb6830e87233b8eace65327fdc764159645b75d2fd4024bf8f313b2dd5f45617d7ecfb4a0b53ccafb5429815a9a1adde6", + "0xb9251cfe32a6dc0440615aadcd98b6b1b46e3f4e44324e8f5142912b597ee3526bea2431e2b0282bb58f71be5b63f65e", + "0xaf8d70711e81cdddfb39e67a1b76643292652584c1ce7ce4feb1641431ad596e75c9120e85f1a341e7a4da920a9cdd94", + "0x98cd4e996594e89495c078bfd52a4586b932c50a449a7c8dfdd16043ca4cda94dafbaa8ad1b44249c99bbcc52152506e", + "0xb9fc6d1c24f48404a4a64fbe3e43342738797905db46e4132aee5f086aaa4c704918ad508aaefa455cfe1b36572e6242", + "0xa365e871d30ba9291cedaba1be7b04e968905d003e9e1af7e3b55c5eb048818ae5b913514fb08b24fb4fbdccbb35d0b8", + "0x93bf99510971ea9af9f1e364f1234c898380677c8e8de9b0dd24432760164e46c787bc9ec42a7ad450500706cf247b2d", + "0xb872f825a5b6e7b9c7a9ddfeded3516f0b1449acc9b4fd29fc6eba162051c17416a31e5be6d3563f424d28e65bab8b8f", + "0xb06b780e5a5e8eb4f4c9dc040f749cf9709c8a4c9ef15e925f442b696e41e5095db0778a6c73bcd329b265f2c6955c8b", + "0x848f1a981f5fc6cd9180cdddb8d032ad32cdfa614fc750d690dbae36cc0cd355cbf1574af9b3ffc8b878f1b2fafb9544", + "0xa03f48cbff3e9e8a3a655578051a5ae37567433093ac500ed0021c6250a51b767afac9bdb194ee1e3eac38a08c0eaf45", + "0xb5be78ce638ff8c4aa84352b536628231d3f7558c5be3bf010b28feac3022e64691fa672f358c8b663904aebe24a54ed", + "0xa9d4da70ff676fa55d1728ba6ab03b471fa38b08854d99e985d88c2d050102d8ccffbe1c90249a5607fa7520b15fe791", + "0x8fe9f7092ffb0b69862c8e972fb1ecf54308c96d41354ed0569638bb0364f1749838d6d32051fff1599112978c6e229c", + "0xae6083e95f37770ecae0df1e010456f165d96cfe9a7278c85c15cffd61034081ce5723e25e2bede719dc9341ec8ed481", + "0xa260891891103089a7afbd9081ea116cfd596fd1015f5b65e10b0961eb37fab7d09c69b7ce4be8bf35e4131848fb3fe4", + "0x8d729fa32f6eb9fd2f6a140bef34e8299a2f3111bffd0fe463aa8622c9d98bfd31a1df3f3e87cd5abc52a595f96b970e", + "0xa30ec6047ae4bc7da4daa7f4c28c93aedb1112cfe240e681d07e1a183782c9ff6783ac077c155af23c69643b712a533f", + "0xac830726544bfe7b5467339e5114c1a75f2a2a8d89453ce86115e6a789387e23551cd64620ead6283dfa4538eb313d86", + "0x8445c135b7a48068d8ed3e011c6d818cfe462b445095e2fbf940301e50ded23f272d799eea47683fc027430ce14613ef", + "0x95785411715c9ae9d8293ce16a693a2aa83e3cb1b4aa9f76333d0da2bf00c55f65e21e42e50e6c5772ce213dd7b4f7a0", + "0xb273b024fa18b7568c0d1c4d2f0c4e79ec509dafac8c5951f14192d63ddbcf2d8a7512c1c1b615cc38fa3e336618e0c5", + "0xa78b9d3ea4b6a90572eb27956f411f1d105fdb577ee2ffeec9f221da9b45db84bfe866af1f29597220c75e0c37a628d8", + "0xa4be2bf058c36699c41513c4d667681ce161a437c09d81383244fc55e1c44e8b1363439d0cce90a3e44581fb31d49493", + "0xb6eef13040f17dd4eba22aaf284d2f988a4a0c4605db44b8d2f4bf9567ac794550b543cc513c5f3e2820242dd704152e", + "0x87eb00489071fa95d008c5244b88e317a3454652dcb1c441213aa16b28cd3ecaa9b22fec0bdd483c1df71c37119100b1", + "0x92d388acdcb49793afca329cd06e645544d2269234e8b0b27d2818c809c21726bc9cf725651b951e358a63c83dedee24", + "0xae27e219277a73030da27ab5603c72c8bd81b6224b7e488d7193806a41343dff2456132274991a4722fdb0ef265d04cd", + "0x97583e08ecb82bbc27c0c8476d710389fa9ffbead5c43001bd36c1b018f29faa98de778644883e51870b69c5ffb558b5", + "0x90a799a8ce73387599babf6b7da12767c0591cadd36c20a7990e7c05ea1aa2b9645654ec65308ee008816623a2757a6a", + "0xa1b47841a0a2b06efd9ab8c111309cc5fc9e1d5896b3e42ed531f6057e5ade8977c29831ce08dbda40348386b1dcc06d", + "0xb92b8ef59bbddb50c9457691bc023d63dfcc54e0fd88bd5d27a09e0d98ac290fc90e6a8f6b88492043bf7c87fac8f3e4", + "0xa9d6240b07d62e22ec8ab9b1f6007c975a77b7320f02504fc7c468b4ee9cfcfd945456ff0128bc0ef2174d9e09333f8d", + "0x8e96534c94693226dc32bca79a595ca6de503af635f802e86442c67e77564829756961d9b701187fe91318da515bf0e6", + "0xb6ba290623cd8dd5c2f50931c0045d1cfb0c30877bc8fe58cbc3ff61ee8da100045a39153916efa1936f4aee0892b473", + "0xb43baa7717fac02d4294f5b3bb5e58a65b3557747e3188b482410388daac7a9c177f762d943fd5dcf871273921213da8", + "0xb9cf00f8fb5e2ef2b836659fece15e735060b2ea39b8e901d3dcbdcf612be8bf82d013833718c04cd46ffaa70b85f42e", + "0x8017d0c57419e414cbba504368723e751ef990cc6f05dad7b3c2de6360adc774ad95512875ab8337d110bf39a42026fa", + "0xae7401048b838c0dcd4b26bb6c56d79d51964a0daba780970b6c97daee4ea45854ea0ac0e4139b3fe60dac189f84df65", + "0x887b237b0cd0f816b749b21db0b40072f9145f7896c36916296973f9e6990ede110f14e5976c906d08987c9836cca57f", + "0xa88c3d5770148aee59930561ca1223aceb2c832fb5417e188dca935905301fc4c6c2c9270bc1dff7add490a125eb81c6", + "0xb6cf9b02c0cd91895ad209e38c54039523f137b5848b9d3ad33ae43af6c20c98434952db375fe378de7866f2d0e8b18a", + "0x84ef3d322ff580c8ad584b1fe4fe346c60866eb6a56e982ba2cf3b021ecb1fdb75ecc6c29747adda86d9264430b3f816", + "0xa0561c27224baf0927ad144cb71e31e54a064c598373fcf0d66aebf98ab7af1d8e2f343f77baefff69a6da750a219e11", + "0xaa5cc43f5b8162b016f5e1b61214c0c9d15b1078911c650b75e6cdfb49b85ee04c6739f5b1687d15908444f691f732de", + "0xad4ac099b935589c7b8fdfdf3db332b7b82bb948e13a5beb121ebd7db81a87d278024a1434bcf0115c54ca5109585c3d", + "0x8a00466abf3f109a1dcd19e643b603d3af23d42794ef8ca2514dd507ecea44a031ac6dbc18bd02f99701168b25c1791e", + "0xb00b5900dfad79645f8bee4e5adc7b84eb22e5b1e67df77ccb505b7fc044a6c08a8ea5faca662414eb945f874f884cea", + "0x950e204e5f17112250b22ea6bb8423baf522fc0af494366f18fe0f949f51d6e6812074a80875cf1ed9c8e7420058d541", + "0x91e5cbf8bb1a1d50c81608c9727b414d0dd2fb467ebc92f100882a3772e54f94979cfdf8e373fdef7c7fcdd60fec9e00", + "0xa093f6a857b8caaff80599c2e89c962b415ecbaa70d8fd973155fa976a284c6b29a855f5f7a3521134d00d2972755188", + "0xb4d55a3551b00da54cc010f80d99ddd2544bde9219a3173dfaadf3848edc7e4056ab532fb75ac26f5f7141e724267663", + "0xa03ea050fc9b011d1b04041b5765d6f6453a93a1819cd9bd6328637d0b428f08526466912895dcc2e3008ee58822e9a7", + "0x99b12b3665e473d01bc6985844f8994fb65cb15745024fb7af518398c4a37ff215da8f054e8fdf3286984ae36a73ca5e", + "0x9972c7e7a7fb12e15f78d55abcaf322c11249cd44a08f62c95288f34f66b51f146302bce750ff4d591707075d9123bd2", + "0xa64b4a6d72354e596d87cda213c4fc2814009461570ccb27d455bbe131f8d948421a71925425b546d8cf63d5458cd64b", + "0x91c215c73b195795ede2228b7ed1f6e37892e0c6b0f4a0b5a16c57aa1100c84df9239054a173b6110d6c2b7f4bf1ce52", + "0x88807198910ec1303480f76a3683870246a995e36adaeadc29c22f0bdba8152fe705bd070b75de657b04934f7d0ccf80", + "0xb37c0026c7b32eb02cacac5b55cb5fe784b8e48b2945c64d3037af83ece556a117f0ff053a5968c2f5fa230e291c1238", + "0x94c768384ce212bc2387e91ce8b45e4ff120987e42472888a317abc9dcdf3563b62e7a61c8e98d7cdcbe272167d91fc6", + "0xa10c2564936e967a390cb14ef6e8f8b04ea9ece5214a38837eda09e79e0c7970b1f83adf017c10efd6faa8b7ffa2c567", + "0xa5085eed3a95f9d4b1269182ea1e0d719b7809bf5009096557a0674bde4201b0ddc1f0f16a908fc468846b3721748ce3", + "0x87468eb620b79a0a455a259a6b4dfbc297d0d53336537b771254dd956b145dc816b195b7002647ea218552e345818a3f", + "0xace2b77ffb87366af0a9cb5d27d6fc4a14323dbbf1643f5f3c4559306330d86461bb008894054394cbfaefeaa0bc2745", + "0xb27f56e840a54fbd793f0b7a7631aa4cee64b5947e4382b2dfb5eb1790270288884c2a19afebe5dc0c6ef335d4531c1c", + "0x876e438633931f7f895062ee16c4b9d10428875f7bc79a8e156a64d379a77a2c45bf5430c5ab94330f03da352f1e9006", + "0xa2512a252587d200d2092b44c914df54e04ff8bcef36bf631f84bde0cf5a732e3dc7f00f662842cfd74b0b0f7f24180e", + "0x827f1bc8f54a35b7a4bd8154f79bcc055e45faed2e74adf7cf21cca95df44d96899e847bd70ead6bb27b9c0ed97bbd8b", + "0xa0c92cf5a9ed843714f3aea9fe7b880f622d0b4a3bf66de291d1b745279accf6ba35097849691370f41732ba64b5966b", + "0xa63f5c1e222775658421c487b1256b52626c6f79cb55a9b7deb2352622cedffb08502042d622eb3b02c97f9c09f9c957", + "0x8cc093d52651e65fb390e186db6cc4de559176af4624d1c44cb9b0e836832419dacac7b8db0627b96288977b738d785d", + "0xaa7b6a17dfcec146134562d32a12f7bd7fe9522e300859202a02939e69dbd345ed7ff164a184296268f9984f9312e8fc", + "0x8ac76721f0d2b679f023d06cbd28c85ae5f4b43c614867ccee88651d4101d4fd352dbdb65bf36bfc3ebc0109e4b0c6f9", + "0x8d350f7c05fc0dcd9a1170748846fb1f5d39453e4cb31e6d1457bed287d96fc393b2ecc53793ca729906a33e59c6834a", + "0xb9913510dfc5056d7ec5309f0b631d1ec53e3a776412ada9aefdaf033c90da9a49fdde6719e7c76340e86599b1f0eec2", + "0x94955626bf4ce87612c5cfffcf73bf1c46a4c11a736602b9ba066328dc52ad6d51e6d4f53453d4ed55a51e0aad810271", + "0xb0fcab384fd4016b2f1e53f1aafd160ae3b1a8865cd6c155d7073ecc1664e05b1d8bca1def39c158c7086c4e1103345e", + "0x827de3f03edfbde08570b72de6662c8bfa499b066a0a27ebad9b481c273097d17a5a0a67f01553da5392ec3f149b2a78", + "0xab7940384c25e9027c55c40df20bd2a0d479a165ced9b1046958353cd69015eeb1e44ed2fd64e407805ba42df10fc7bf", + "0x8ad456f6ff8cd58bd57567d931f923d0c99141978511b17e03cab7390a72b9f62498b2893e1b05c7c22dd274e9a31919", + "0xac75399e999effe564672db426faa17a839e57c5ef735985c70cd559a377adec23928382767b55ed5a52f7b11b54b756", + "0xb17f975a00b817299ac7af5f2024ea820351805df58b43724393bfb3920a8cd747a3bbd4b8286e795521489db3657168", + "0xa2bed800a6d95501674d9ee866e7314063407231491d794f8cf57d5be020452729c1c7cefd8c50dc1540181f5caab248", + "0x9743f5473171271ffdd3cc59a3ae50545901a7b45cd4bc3570db487865f3b73c0595bebabbfe79268809ee1862e86e4a", + "0xb7eab77c2d4687b60d9d7b04e842b3880c7940140012583898d39fcc22d9b9b0a9be2c2e3788b3e6f30319b39c338f09", + "0x8e2b8f797a436a1b661140e9569dcf3e1eea0a77c7ff2bc4ff0f3e49af04ed2de95e255df8765f1d0927fb456a9926b1", + "0x8aefea201d4a1f4ff98ffce94e540bb313f2d4dfe7e9db484a41f13fc316ed02b282e1acc9bc6f56cad2dc2e393a44c9", + "0xb950c17c0e5ca6607d182144aa7556bb0efe24c68f06d79d6413a973b493bfdf04fd147a4f1ab03033a32004cc3ea66f", + "0xb7b8dcbb179a07165f2dc6aa829fad09f582a71b05c3e3ea0396bf9e6fe73076f47035c031c2101e8e38e0d597eadd30", + "0xa9d77ed89c77ec1bf8335d08d41c3c94dcca9fd1c54f22837b4e54506b212aa38d7440126c80648ab7723ff18e65ed72", + "0xa819d6dfd4aef70e52b8402fe5d135f8082d40eb7d3bb5c4d7997395b621e2bb10682a1bad2c9caa33dd818550fc3ec6", + "0x8f6ee34128fac8bbf13ce2d68b2bb363eb4fd65b297075f88e1446ddeac242500eeb4ef0735e105882ff5ba8c44c139b", + "0xb4440e48255c1644bcecf3a1e9958f1ec4901cb5b1122ee5b56ffd02cad1c29c4266999dbb85aa2605c1b125490074d4", + "0xa43304a067bede5f347775d5811cf65a6380a8d552a652a0063580b5c5ef12a0867a39c7912fa219e184f4538eba1251", + "0xa891ad67a790089ffc9f6d53e6a3d63d3556f5f693e0cd8a7d0131db06fd4520e719cfcc3934f0a8f62a95f90840f1d4", + "0xaea6df8e9bb871081aa0fc5a9bafb00be7d54012c5baf653791907d5042a326aeee966fd9012a582cc16695f5baf7042", + "0x8ffa2660dc52ed1cd4eff67d6a84a8404f358a5f713d04328922269bee1e75e9d49afeec0c8ad751620f22352a438e25", + "0x87ec6108e2d63b06abed350f8b363b7489d642486f879a6c3aa90e5b0f335efc2ff2834eef9353951a42136f8e6a1b32", + "0x865619436076c2760d9e87ddc905023c6de0a8d56eef12c98a98c87837f2ca3f27fd26a2ad752252dbcbe2b9f1d5a032", + "0x980437dce55964293cb315c650c5586ffd97e7a944a83f6618af31c9d92c37b53ca7a21bb5bc557c151b9a9e217e7098", + "0x95d128fc369df4ad8316b72aea0ca363cbc7b0620d6d7bb18f7076a8717a6a46956ff140948b0cc4f6d2ce33b5c10054", + "0x8c7212d4a67b9ec70ebbca04358ad2d36494618d2859609163526d7b3acc2fc935ca98519380f55e6550f70a9bc76862", + "0x893a2968819401bf355e85eee0f0ed0406a6d4a7d7f172d0017420f71e00bb0ba984f6020999a3cdf874d3cd8ebcd371", + "0x9103c1af82dece25d87274e89ea0acd7e68c2921c4af3d8d7c82ab0ed9990a5811231b5b06113e7fa43a6bd492b4564f", + "0x99cfd87a94eab7d35466caa4ed7d7bb45e5c932b2ec094258fb14bf205659f83c209b83b2f2c9ccb175974b2a33e7746", + "0x874b6b93e4ee61be3f00c32dd84c897ccd6855c4b6251eb0953b4023634490ed17753cd3223472873cbc6095b2945075", + "0x84a32c0dc4ea60d33aac3e03e70d6d639cc9c4cc435c539eff915017be3b7bdaba33349562a87746291ebe9bc5671f24", + "0xa7057b24208928ad67914e653f5ac1792c417f413d9176ba635502c3f9c688f7e2ee81800d7e3dc0a340c464da2fd9c5", + "0xa03fb9ed8286aacfa69fbd5d953bec591c2ae4153400983d5dbb6cd9ea37fff46ca9e5cceb9d117f73e9992a6c055ad2", + "0x863b2de04e89936c9a4a2b40380f42f20aefbae18d03750fd816c658aee9c4a03df7b12121f795c85d01f415baaeaa59", + "0x8526eb9bd31790fe8292360d7a4c3eed23be23dd6b8b8f01d2309dbfdc0cfd33ad1568ddd7f8a610f3f85a9dfafc6a92", + "0xb46ab8c5091a493d6d4d60490c40aa27950574a338ea5bbc045be3a114af87bdcb160a8c80435a9b7ad815f3cb56a3f3", + "0xaeadc47b41a8d8b4176629557646202f868b1d728b2dda58a347d937e7ffc8303f20d26d6c00b34c851b8aeec547885d", + "0xaebb19fc424d72c1f1822aa7adc744cd0ef7e55727186f8df8771c784925058c248406ebeeaf3c1a9ee005a26e9a10c6", + "0x8ff96e81c1a4a2ab1b4476c21018fae0a67e92129ee36120cae8699f2d7e57e891f5c624902cb1b845b944926a605cc3", + "0x8251b8d2c43fadcaa049a9e7aff838dae4fb32884018d58d46403ac5f3beb5c518bfd45f03b8abb710369186075eb71c", + "0xa8b2a64f865f51a5e5e86a66455c093407933d9d255d6b61e1fd81ffafc9538d73caaf342338a66ba8ee166372a3d105", + "0xaad915f31c6ba7fdc04e2aaac62e84ef434b7ee76a325f07dc430d12c84081999720181067b87d792efd0117d7ee1eab", + "0xa13db3bb60389883fd41d565c54fb5180d9c47ce2fe7a169ae96e01d17495f7f4fa928d7e556e7c74319c4c25d653eb2", + "0xa4491b0198459b3f552855d680a59214eb74e6a4d6c5fa3b309887dc50ebea2ecf6d26c040550f7dc478b452481466fb", + "0x8f017f13d4b1e3f0c087843582b52d5f8d13240912254d826dd11f8703a99a2f3166dfbdfdffd9a3492979d77524276b", + "0x96c3d5dcd032660d50d7cd9db2914f117240a63439966162b10c8f1f3cf74bc83b0f15451a43b31dbd85e4a7ce0e4bb1", + "0xb479ec4bb79573d32e0ec93b92bdd7ec8c26ddb5a2d3865e7d4209d119fd3499eaac527615ffac78c440e60ef3867ae0", + "0xb2c49c4a33aa94b52b6410b599e81ff15490aafa7e43c8031c865a84e4676354a9c81eb4e7b8be6825fdcefd1e317d44", + "0x906dc51d6a90c089b6704b47592805578a6eed106608eeb276832f127e1b8e858b72e448edcbefb497d152447e0e68ff", + "0xb0e81c63b764d7dfbe3f3fddc9905aef50f3633e5d6a4af6b340495124abedcff5700dfd1577bbbed7b6bf97d02719cb", + "0x9304c64701e3b4ed6d146e48a881f7d83a17f58357cca0c073b2bb593afd2d94f6e2a7a1ec511d0a67ad6ff4c3be5937", + "0xb6fdbd12ba05aa598d80b83f70a15ef90e5cba7e6e75fa038540ee741b644cd1f408a6cecfd2a891ef8d902de586c6b5", + "0xb80557871a6521b1b3c74a1ba083ae055b575df607f1f7b04c867ba8c8c181ea68f8d90be6031f4d25002cca27c44da2", + "0xaa7285b8e9712e06b091f64163f1266926a36607f9d624af9996856ed2aaf03a580cb22ce407d1ade436c28b44ca173f", + "0x8148d72b975238b51e6ea389e5486940d22641b48637d7dfadfa603a605bfc6d74a016480023945d0b85935e396aea5d", + "0x8a014933a6aea2684b5762af43dcf4bdbb633cd0428d42d71167a2b6fc563ece5e618bff22f1db2ddb69b845b9a2db19", + "0x990d91740041db770d0e0eb9d9d97d826f09fd354b91c41e0716c29f8420e0e8aac0d575231efba12fe831091ec38d5a", + "0x9454d0d32e7e308ddec57cf2522fb1b67a2706e33fb3895e9e1f18284129ab4f4c0b7e51af25681d248d7832c05eb698", + "0xa5bd434e75bac105cb3e329665a35bce6a12f71dd90c15165777d64d4c13a82bceedb9b48e762bd24034e0fc9fbe45f4", + "0xb09e3b95e41800d4dc29c6ffdaab2cd611a0050347f6414f154a47ee20ee59bf8cf7181454169d479ebce1eb5c777c46", + "0xb193e341d6a047d15eea33766d656d807b89393665a783a316e9ba10518e5515c8e0ade3d6e15641d917a8a172a5a635", + "0xade435ec0671b3621dde69e07ead596014f6e1daa1152707a8c18877a8b067bde2895dd47444ffa69db2bbef1f1d8816", + "0xa7fd3d6d87522dfc56fb47aef9ce781a1597c56a8bbfd796baba907afdc872f753d732bfda1d3402aee6c4e0c189f52d", + "0xa298cb4f4218d0464b2fab393e512bbc477c3225aa449743299b2c3572f065bc3a42d07e29546167ed9e1b6b3b3a3af3", + "0xa9ee57540e1fd9c27f4f0430d194b91401d0c642456c18527127d1f95e2dba41c2c86d1990432eb38a692fda058fafde", + "0x81d6c1a5f93c04e6d8e5a7e0678c1fc89a1c47a5c920bcd36180125c49fcf7c114866b90e90a165823560b19898a7c16", + "0xa4b7a1ec9e93c899b9fd9aaf264c50e42c36c0788d68296a471f7a3447af4dbc81e4fa96070139941564083ec5b5b5a1", + "0xb3364e327d381f46940c0e11e29f9d994efc6978bf37a32586636c0070b03e4e23d00650c1440f448809e1018ef9f6d8", + "0x8056e0913a60155348300e3a62e28b5e30629a90f7dd4fe11289097076708110a1d70f7855601782a3cdc5bdb1ca9626", + "0xb4980fd3ea17bac0ba9ee1c470b17e575bb52e83ebdd7d40c93f4f87bebeaff1c8a679f9d3d09d635f068d37d5bd28bd", + "0x905a9299e7e1853648e398901dfcd437aa575c826551f83520df62984f5679cb5f0ea86aa45ed3e18b67ddc0dfafe809", + "0xab99553bf31a84f2e0264eb34a08e13d8d15e2484aa9352354becf9a15999c76cc568d68274b70a65e49703fc23540d0", + "0xa43681597bc574d2dae8964c9a8dc1a07613d7a1272bdcb818d98c85d44e16d744250c33f3b5e4d552d97396b55e601f", + "0xa54e5a31716fccb50245898c99865644405b8dc920ded7a11f3d19bdc255996054b268e16f2e40273f11480e7145f41e", + "0x8134f3ad5ef2ad4ba12a8a4e4d8508d91394d2bcdc38b7c8c8c0b0a820357ac9f79d286c65220f471eb1adca1d98fc68", + "0x94e2f755e60471578ab2c1adb9e9cea28d4eec9b0e92e0140770bca7002c365fcabfe1e5fb4fe6cfe79a0413712aa3ef", + "0xad48f8d0ce7eb3cc6e2a3086ad96f562e5bed98a360721492ae2e74dc158586e77ec8c35d5fd5927376301b7741bad2b", + "0x8614f0630bdd7fbad3a31f55afd9789f1c605dc85e7dc67e2edfd77f5105f878bb79beded6e9f0b109e38ea7da67e8d5", + "0x9804c284c4c5e77dabb73f655b12181534ca877c3e1e134aa3f47c23b7ec92277db34d2b0a5d38d2b69e5d1c3008a3e3", + "0xa51b99c3088e473afdaa9e0a9f7e75a373530d3b04e44e1148da0726b95e9f5f0c7e571b2da000310817c36f84b19f7f", + "0xac4ff909933b3b76c726b0a382157cdc74ab851a1ac6cef76953c6444441804cc43abb883363f416592e8f6cfbc4550b", + "0xae7d915eb9fc928b65a29d6edbc75682d08584d0014f7bcf17d59118421ae07d26a02137d1e4de6938bcd1ab8ef48fad", + "0x852f7e453b1af89b754df6d11a40d5d41ea057376e8ecacd705aacd2f917457f4a093d6b9a8801837fa0f62986ad7149", + "0x92c6bf5ada5d0c3d4dd8058483de36c215fa98edab9d75242f3eff9db07c734ad67337da6f0eefe23a487bf75a600dee", + "0xa2b42c09d0db615853763552a48d2e704542bbd786aae016eb58acbf6c0226c844f5fb31e428cb6450b9db855f8f2a6f", + "0x880cc07968266dbfdcfbc21815cd69e0eddfee239167ac693fb0413912d816f2578a74f7716eecd6deefa68c6eccd394", + "0xb885b3ace736cd373e8098bf75ba66fa1c6943ca1bc4408cd98ac7074775c4478594f91154b8a743d9c697e1b29f5840", + "0xa51ce78de512bd87bfa0835de819941dffbf18bec23221b61d8096fc9436af64e0693c335b54e7bfc763f287bdca2db6", + "0xa3c76166a3bdb9b06ef696e57603b58871bc72883ee9d45171a30fe6e1d50e30bc9c51b4a0f5a7270e19a77b89733850", + "0xacefc5c6f8a1e7c24d7b41e0fc7f6f3dc0ede6cf3115ffb9a6e54b1d954cbca9bda8ad7a084be9be245a1b8e9770d141", + "0xb420ed079941842510e31cfad117fa11fb6b4f97dfbc6298cb840f27ebaceba23eeaf3f513bcffbf5e4aae946310182d", + "0x95c3bb5ef26c5ed2f035aa5d389c6b3c15a6705b9818a3fefaed28922158b35642b2e8e5a1a620fdad07e75ad4b43af4", + "0x825149f9081ecf07a2a4e3e8b5d21bade86c1a882475d51c55ee909330b70c5a2ac63771c8600c6f38df716af61a3ea1", + "0x873b935aae16d9f08adbc25353cee18af2f1b8d5f26dec6538d6bbddc515f2217ed7d235dcfea59ae61b428798b28637", + "0x9294150843a2bedcedb3bb74c43eb28e759cf9499582c5430bccefb574a8ddd4f11f9929257ff4c153990f9970a2558f", + "0xb619563a811cc531da07f4f04e5c4c6423010ff9f8ed7e6ec9449162e3d501b269fb1c564c09c0429431879b0f45df02", + "0x91b509b87eb09f007d839627514658c7341bc76d468920fe8a740a8cb96a7e7e631e0ea584a7e3dc1172266f641d0f5c", + "0x8b8aceace9a7b9b4317f1f01308c3904d7663856946afbcea141a1c615e21ccad06b71217413e832166e9dd915fbe098", + "0x87b3b36e725833ea0b0f54753c3728c0dbc87c52d44d705ffc709f2d2394414c652d3283bab28dcce09799504996cee0", + "0xb2670aad5691cbf308e4a6a77a075c4422e6cbe86fdba24e9f84a313e90b0696afb6a067eebb42ba2d10340d6a2f6e51", + "0x876784a9aff3d54faa89b2bacd3ff5862f70195d0b2edc58e8d1068b3c9074c0da1cfa23671fe12f35e33b8a329c0ccd", + "0x8b48b9e758e8a8eae182f5cbec96f67d20cca6d3eee80a2d09208eb1d5d872e09ef23d0df8ebbb9b01c7449d0e3e3650", + "0xb79303453100654c04a487bdcadc9e3578bc80930c489a7069a52e8ca1dba36c492c8c899ce025f8364599899baa287d", + "0x961b35a6111da54ece6494f24dacd5ea46181f55775b5f03df0e370c34a5046ac2b4082925855325bb42bc2a2c98381d", + "0xa31feb1be3f5a0247a1f7d487987eb622e34fca817832904c6ee3ee60277e5847945a6f6ea1ac24542c72e47bdf647df", + "0xa12a2aa3e7327e457e1aae30e9612715dd2cfed32892c1cd6dcda4e9a18203af8a44afb46d03b2eed89f6b9c5a2c0c23", + "0xa08265a838e69a2ca2f80fead6ccf16f6366415b920c0b22ee359bcd8d4464ecf156f400a16a7918d52e6d733dd64211", + "0xb723d6344e938d801cca1a00032af200e541d4471fd6cbd38fb9130daa83f6a1dffbbe7e67fc20f9577f884acd7594b2", + "0xa6733d83ec78ba98e72ddd1e7ff79b7adb0e559e256760d0c590a986e742445e8cdf560d44b29439c26d87edd0b07c8c", + "0xa61c2c27d3f7b9ff4695a17afedf63818d4bfba390507e1f4d0d806ce8778d9418784430ce3d4199fd3bdbc2504d2af3", + "0x8332f3b63a6dc985376e8b1b25eeae68be6160fbe40053ba7bcf6f073204f682da72321786e422d3482fd60c9e5aa034", + "0xa280f44877583fbb6b860d500b1a3f572e3ee833ec8f06476b3d8002058e25964062feaa1e5bec1536d734a5cfa09145", + "0xa4026a52d277fcea512440d2204f53047718ebfcae7b48ac57ea7f6bfbc5de9d7304db9a9a6cbb273612281049ddaec5", + "0x95cdf69c831ab2fad6c2535ede9c07e663d2ddccc936b64e0843d2df2a7b1c31f1759c3c20f1e7a57b1c8f0dbb21b540", + "0x95c96cec88806469c277ab567863c5209027cecc06c7012358e5f555689c0d9a5ffb219a464f086b45817e8536b86d2f", + "0xafe38d4684132a0f03d806a4c8df556bf589b25271fbc6fe2e1ed16de7962b341c5003755da758d0959d2e6499b06c68", + "0xa9b77784fda64987f97c3a23c5e8f61b918be0f7c59ba285084116d60465c4a2aaafc8857eb16823282cc83143eb9126", + "0xa830f05881ad3ce532a55685877f529d32a5dbe56cea57ffad52c4128ee0fad0eeaf0da4362b55075e77eda7babe70e5", + "0x992b3ad190d6578033c13ed5abfee4ef49cbc492babb90061e3c51ee4b5790cdd4c8fc1abff1fa2c00183b6b64f0bbbe", + "0xb1015424d9364aeff75de191652dc66484fdbec3e98199a9eb9671ec57bec6a13ff4b38446e28e4d8aedb58dd619cd90", + "0xa745304604075d60c9db36cada4063ac7558e7ec2835d7da8485e58d8422e817457b8da069f56511b02601289fbb8981", + "0xa5ba4330bc5cb3dbe0486ddf995632a7260a46180a08f42ae51a2e47778142132463cc9f10021a9ad36986108fefa1a9", + "0xb419e9fd4babcaf8180d5479db188bb3da232ae77a1c4ed65687c306e6262f8083070a9ac32220cddb3af2ec73114092", + "0xa49e23dc5f3468f3bf3a0bb7e4a114a788b951ff6f23a3396ae9e12cbff0abd1240878a3d1892105413dbc38818e807c", + "0xb7ecc7b4831f650202987e85b86bc0053f40d983f252e9832ef503aea81c51221ce93279da4aa7466c026b2d2070e55d", + "0x96a8c35cb87f84fa84dcd6399cc2a0fd79cc9158ef4bdde4bae31a129616c8a9f2576cd19baa3f497ca34060979aed7d", + "0x8681b2c00aa62c2b519f664a95dcb8faef601a3b961bb4ce5d85a75030f40965e2983871d41ea394aee934e859581548", + "0x85c229a07efa54a713d0790963a392400f55fbb1a43995a535dc6c929f20d6a65cf4efb434e0ad1cb61f689b8011a3bc", + "0x90856f7f3444e5ad44651c28e24cc085a5db4d2ffe79aa53228c26718cf53a6e44615f3c5cda5aa752d5f762c4623c66", + "0x978999b7d8aa3f28a04076f74d11c41ef9c89fdfe514936c4238e0f13c38ec97e51a5c078ebc6409e517bfe7ccb42630", + "0xa099914dd7ed934d8e0d363a648e9038eb7c1ec03fa04dbcaa40f7721c618c3ef947afef7a16b4d7ac8c12aa46637f03", + "0xab2a104fed3c83d16f2cda06878fa5f30c8c9411de71bfb67fd2fc9aa454dcbcf3d299d72f8cc12e919466a50fcf7426", + "0xa4471d111db4418f56915689482f6144efc4664cfb0311727f36c864648d35734351becc48875df96f4abd3cfcf820f9", + "0x83be11727cd30ea94ccc8fa31b09b81c9d6a9a5d3a4686af9da99587332fe78c1f94282f9755854bafd6033549afec91", + "0x88020ff971dc1a01a9e993cd50a5d2131ffdcbb990c1a6aaa54b20d8f23f9546a70918ea57a21530dcc440c1509c24ad", + "0xae24547623465e87905eaffa1fa5d52bb7c453a8dbd89614fa8819a2abcedaf455c2345099b7324ae36eb0ad7c8ef977", + "0xb59b0c60997de1ee00b7c388bc7101d136c9803bf5437b1d589ba57c213f4f835a3e4125b54738e78abbc21b000f2016", + "0xa584c434dfe194546526691b68fa968c831c31da42303a1d735d960901c74011d522246f37f299555416b8cf25c5a548", + "0x80408ce3724f4837d4d52376d255e10f69eb8558399ae5ca6c11b78b98fe67d4b93157d2b9b639f1b5b64198bfe87713", + "0xabb941e8d406c2606e0ddc35c113604fdd9d249eacc51cb64e2991e551b8639ce44d288cc92afa7a1e7fc599cfc84b22", + "0xb223173f560cacb1c21dba0f1713839e348ad02cbfdef0626748604c86f89e0f4c919ed40b583343795bdd519ba952c8", + "0xaf1c70512ec3a19d98b8a1fc3ff7f7f5048a27d17d438d43f561974bbdd116fcd5d5c21040f3447af3f0266848d47a15", + "0x8a44809568ebe50405bede19b4d2607199159b26a1b33e03d180e6840c5cf59d991a4fb150d111443235d75ecad085b7", + "0xb06207cdca46b125a27b3221b5b50cf27af4c527dd7c80e2dbcebbb09778a96df3af67e50f07725239ce3583dad60660", + "0x993352d9278814ec89b26a11c4a7c4941bf8f0e6781ae79559d14749ee5def672259792db4587f85f0100c7bb812f933", + "0x9180b8a718b971fd27bc82c8582d19c4b4f012453e8c0ffeeeffe745581fc6c07875ab28be3af3fa3896d19f0c89ac5b", + "0x8b8e1263eb48d0fe304032dd5ea1f30e73f0121265f7458ba9054d3626894e8a5fef665340abd2ede9653045c2665938", + "0x99a2beee4a10b7941c24b2092192faf52b819afd033e4a2de050fd6c7f56d364d0cf5f99764c3357cf32399e60fc5d74", + "0x946a4aad7f8647ea60bee2c5fcdeb6f9a58fb2cfca70c4d10e458027a04846e13798c66506151be3df9454b1e417893f", + "0xa672a88847652d260b5472d6908d1d57e200f1e492d30dd1cecc441cdfc9b76e016d9bab560efd4d7f3c30801de884a9", + "0x9414e1959c156cde1eb24e628395744db75fc24b9df4595350aaad0bc38e0246c9b4148f6443ef68b8e253a4a6bcf11c", + "0x9316e9e4ec5fab4f80d6540df0e3a4774db52f1d759d2e5b5bcd3d7b53597bb007eb1887cb7dc61f62497d51ffc8d996", + "0x902d6d77bb49492c7a00bc4b70277bc28c8bf9888f4307bb017ac75a962decdedf3a4e2cf6c1ea9f9ba551f4610cbbd7", + "0xb07025a18b0e32dd5e12ec6a85781aa3554329ea12c4cd0d3b2c22e43d777ef6f89876dd90a9c8fb097ddf61cf18adc5", + "0xb355a849ad3227caa4476759137e813505ec523cbc2d4105bc7148a4630f9e81918d110479a2d5f5e4cd9ccec9d9d3e3", + "0xb49532cfdf02ee760109881ad030b89c48ee3bb7f219ccafc13c93aead754d29bdafe345be54c482e9d5672bd4505080", + "0x9477802410e263e4f938d57fa8f2a6cac7754c5d38505b73ee35ea3f057aad958cb9722ba6b7b3cfc4524e9ca93f9cdc", + "0x9148ea83b4436339580f3dbc9ba51509e9ab13c03063587a57e125432dd0915f5d2a8f456a68f8fff57d5f08c8f34d6e", + "0xb00b6b5392b1930b54352c02b1b3b4f6186d20bf21698689bbfc7d13e86538a4397b90e9d5c93fd2054640c4dbe52a4f", + "0x926a9702500441243cd446e7cbf15dde16400259726794694b1d9a40263a9fc9e12f7bcbf12a27cb9aaba9e2d5848ddc", + "0xa0c6155f42686cbe7684a1dc327100962e13bafcf3db97971fc116d9f5c0c8355377e3d70979cdbd58fd3ea52440901c", + "0xa277f899f99edb8791889d0817ea6a96c24a61acfda3ad8c3379e7c62b9d4facc4b965020b588651672fd261a77f1bfc", + "0x8f528cebb866b501f91afa50e995234bef5bf20bff13005de99cb51eaac7b4f0bf38580cfd0470de40f577ead5d9ba0f", + "0x963fc03a44e9d502cc1d23250efef44d299befd03b898d07ce63ca607bb474b5cf7c965a7b9b0f32198b04a8393821f7", + "0xab087438d0a51078c378bf4a93bd48ef933ff0f1fa68d02d4460820df564e6642a663b5e50a5fe509527d55cb510ae04", + "0xb0592e1f2c54746bb076be0fa480e1c4bebc4225e1236bcda3b299aa3853e3afb401233bdbcfc4a007b0523a720fbf62", + "0x851613517966de76c1c55a94dc4595f299398a9808f2d2f0a84330ba657ab1f357701d0895f658c18a44cb00547f6f57", + "0xa2fe9a1dd251e72b0fe4db27be508bb55208f8f1616b13d8be288363ec722826b1a1fd729fc561c3369bf13950bf1fd6", + "0xb896cb2bc2d0c77739853bc59b0f89b2e008ba1f701c9cbe3bef035f499e1baee8f0ff1e794854a48c320586a2dfc81a", + "0xa1b60f98e5e5106785a9b81a85423452ee9ef980fa7fa8464f4366e73f89c50435a0c37b2906052b8e58e212ebd366cf", + "0xa853b0ebd9609656636df2e6acd5d8839c0fda56f7bf9288a943b06f0b67901a32b95e016ca8bc99bd7b5eab31347e72", + "0xb290fa4c1346963bd5225235e6bdf7c542174dab4c908ab483d1745b9b3a6015525e398e1761c90e4b49968d05e30eea", + "0xb0f65a33ad18f154f1351f07879a183ad62e5144ad9f3241c2d06533dad09cbb2253949daff1bb02d24d16a3569f7ef0", + "0xa00db59b8d4218faf5aeafcd39231027324408f208ec1f54d55a1c41228b463b88304d909d16b718cfc784213917b71e", + "0xb8d695dd33dc2c3bc73d98248c535b2770ad7fa31aa726f0aa4b3299efb0295ba9b4a51c71d314a4a1bd5872307534d1", + "0xb848057cca2ca837ee49c42b88422303e58ea7d2fc76535260eb5bd609255e430514e927cc188324faa8e657396d63ec", + "0x92677836061364685c2aaf0313fa32322746074ed5666fd5f142a7e8f87135f45cd10e78a17557a4067a51dfde890371", + "0xa854b22c9056a3a24ab164a53e5c5cf388616c33e67d8ebb4590cb16b2e7d88b54b1393c93760d154208b5ca822dc68f", + "0x86fff174920388bfab841118fb076b2b0cdec3fdb6c3d9a476262f82689fb0ed3f1897f7be9dbf0932bb14d346815c63", + "0x99661cf4c94a74e182752bcc4b98a8c2218a8f2765642025048e12e88ba776f14f7be73a2d79bd21a61def757f47f904", + "0x8a8893144d771dca28760cba0f950a5d634195fd401ec8cf1145146286caffb0b1a6ba0c4c1828d0a5480ce49073c64c", + "0x938a59ae761359ee2688571e7b7d54692848eb5dde57ffc572b473001ea199786886f8c6346a226209484afb61d2e526", + "0x923f68a6aa6616714cf077cf548aeb845bfdd78f2f6851d8148cba9e33a374017f2f3da186c39b82d14785a093313222", + "0xac923a93d7da7013e73ce8b4a2b14b8fd0cc93dc29d5de941a70285bdd19be4740fedfe0c56b046689252a3696e9c5bc", + "0xb49b32c76d4ec1a2c68d4989285a920a805993bc6fcce6dacd3d2ddae73373050a5c44ba8422a3781050682fa0ef6ba2", + "0x8a367941c07c3bdca5712524a1411bad7945c7c48ffc7103b1d4dff2c25751b0624219d1ccde8c3f70c465f954be5445", + "0xb838f029df455efb6c530d0e370bbbf7d87d61a9aea3d2fe5474c5fe0a39cf235ceecf9693c5c6c5820b1ba8f820bd31", + "0xa8983b7c715eaac7f13a001d2abc462dfc1559dab4a6b554119c271aa8fe00ffcf6b6949a1121f324d6d26cb877bcbae", + "0xa2afb24ad95a6f14a6796315fbe0d8d7700d08f0cfaf7a2abe841f5f18d4fecf094406cbd54da7232a159f9c5b6e805e", + "0x87e8e95ad2d62f947b2766ff405a23f7a8afba14e7f718a691d95369c79955cdebe24c54662553c60a3f55e6322c0f6f", + "0x87c2cbcecb754e0cc96128e707e5c5005c9de07ffd899efa3437cadc23362f5a1d3fcdd30a1f5bdc72af3fb594398c2a", + "0x91afd6ee04f0496dc633db88b9370d41c428b04fd991002502da2e9a0ef051bcd7b760e860829a44fbe5539fa65f8525", + "0x8c50e5d1a24515a9dd624fe08b12223a75ca55196f769f24748686315329b337efadca1c63f88bee0ac292dd0a587440", + "0x8a07e8f912a38d94309f317c32068e87f68f51bdfa082d96026f5f5f8a2211621f8a3856dda8069386bf15fb2d28c18f", + "0x94ad1dbe341c44eeaf4dc133eed47d8dbfe752575e836c075745770a6679ff1f0e7883b6aa917462993a7f469d74cab5", + "0x8745f8bd86c2bb30efa7efb7725489f2654f3e1ac4ea95bd7ad0f3cfa223055d06c187a16192d9d7bdaea7b050c6a324", + "0x900d149c8d79418cda5955974c450a70845e02e5a4ecbcc584a3ca64d237df73987c303e3eeb79da1af83bf62d9e579f", + "0x8f652ab565f677fb1a7ba03b08004e3cda06b86c6f1b0b9ab932e0834acf1370abb2914c15b0d08327b5504e5990681c", + "0x9103097d088be1f75ab9d3da879106c2f597e2cc91ec31e73430647bdd5c33bcfd771530d5521e7e14df6acda44f38a6", + "0xb0fec7791cfb0f96e60601e1aeced9a92446b61fedab832539d1d1037558612d78419efa87ff5f6b7aab8fd697d4d9de", + "0xb9d2945bdb188b98958854ba287eb0480ef614199c4235ce5f15fc670b8c5ffe8eeb120c09c53ea8a543a022e6a321ac", + "0xa9461bb7d5490973ebaa51afc0bb4a5e42acdccb80e2f939e88b77ac28a98870e103e1042899750f8667a8cc9123bae9", + "0xa37fdf11d4bcb2aed74b9f460a30aa34afea93386fa4cdb690f0a71bc58f0b8df60bec56e7a24f225978b862626fa00e", + "0xa214420e183e03d531cf91661466ea2187d84b6e814b8b20b3730a9400a7d25cf23181bb85589ebc982cec414f5c2923", + "0xad09a45a698a6beb3e0915f540ef16e9af7087f53328972532d6b5dfe98ce4020555ece65c6cbad8bd6be8a4dfefe6fd", + "0xab6742800b02728c92d806976764cb027413d6f86edd08ad8bb5922a2969ee9836878cd39db70db0bd9a2646862acc4f", + "0x974ca9305bd5ea1dc1755dff3b63e8bfe9f744321046c1395659bcea2a987b528e64d5aa96ac7b015650b2253b37888d", + "0x84eee9d6bce039c52c2ebc4fccc0ad70e20c82f47c558098da4be2f386a493cbc76adc795b5488c8d11b6518c2c4fab8", + "0x875d7bda46efcb63944e1ccf760a20144df3b00d53282b781e95f12bfc8f8316dfe6492c2efbf796f1150e36e436e9df", + "0xb68a2208e0c587b5c31b5f6cb32d3e6058a9642e2d9855da4f85566e1412db528475892060bb932c55b3a80877ad7b4a", + "0xba006368ecab5febb6ab348644d9b63de202293085ed468df8bc24d992ae8ce468470aa37f36a73630c789fb9c819b30", + "0x90a196035150846cd2b482c7b17027471372a8ce7d914c4d82b6ea7fa705d8ed5817bd42d63886242585baf7d1397a1c", + "0xa223b4c85e0daa8434b015fd9170b5561fe676664b67064974a1e9325066ecf88fc81f97ab5011c59fad28cedd04b240", + "0x82e8ec43139cf15c6bbeed484b62e06cded8a39b5ce0389e4cbe9c9e9c02f2f0275d8d8d4e8dfec8f69a191bef220408", + "0x81a3fc07a7b68d92c6ee4b6d28f5653ee9ec85f7e2ee1c51c075c1b130a8c5097dc661cf10c5aff1c7114b1a6a19f11a", + "0x8ed2ef8331546d98819a5dd0e6c9f8cb2630d0847671314a28f277faf68da080b53891dd75c82cbcf7788b255490785d", + "0xacecabf84a6f9bbed6b2fc2e7e4b48f02ef2f15e597538a73aea8f98addc6badda15e4695a67ecdb505c1554e8f345ec", + "0xb8f51019b2aa575f8476e03dcadf86cc8391f007e5f922c2a36b2daa63f5a503646a468990cd5c65148d323942193051", + "0xaaa595a84b403ec65729bc1c8055a94f874bf9adddc6c507b3e1f24f79d3ad359595a672b93aab3394db4e2d4a7d8970", + "0x895144c55fcbd0f64d7dd69e6855cfb956e02b5658eadf0f026a70703f3643037268fdd673b0d21b288578a83c6338dd", + "0xa2e92ae6d0d237d1274259a8f99d4ea4912a299816350b876fba5ebc60b714490e198a916e1c38c6e020a792496fa23c", + "0xa45795fda3b5bb0ad1d3c628f6add5b2a4473a1414c1a232e80e70d1cfffd7f8a8d9861f8df2946999d7dbb56bf60113", + "0xb6659bf7f6f2fef61c39923e8c23b8c70e9c903028d8f62516d16755cd3fba2fe41c285aa9432dc75ab08f8a1d8a81fc", + "0xa735609a6bc5bfd85e58234fc439ff1f58f1ff1dd966c5921d8b649e21f006bf2b8642ad8a75063c159aaf6935789293", + "0xa3c622eb387c9d15e7bda2e3e84d007cb13a6d50d655c3f2f289758e49d3b37b9a35e4535d3cc53d8efd51f407281f19", + "0x8afe147b53ad99220f5ef9d763bfc91f9c20caecbcf823564236fb0e6ede49414c57d71eec4772c8715cc65a81af0047", + "0xb5f0203233cf71913951e9c9c4e10d9243e3e4a1f2cb235bf3f42009120ba96e04aa414c9938ea8873b63148478927e8", + "0x93c52493361b458d196172d7ba982a90a4f79f03aa8008edc322950de3ce6acf4c3977807a2ffa9e924047e02072b229", + "0xb9e72b805c8ac56503f4a86c82720afbd5c73654408a22a2ac0b2e5caccdfb0e20b59807433a6233bc97ae58cf14c70a", + "0xaf0475779b5cee278cca14c82da2a9f9c8ef222eb885e8c50cca2315fea420de6e04146590ed0dd5a29c0e0812964df5", + "0xb430ccab85690db02c2d0eb610f3197884ca12bc5f23c51e282bf3a6aa7e4a79222c3d8761454caf55d6c01a327595f9", + "0x830032937418b26ee6da9b5206f3e24dc76acd98589e37937e963a8333e5430abd6ce3dd93ef4b8997bd41440eed75d6", + "0x8820a6d73180f3fe255199f3f175c5eb770461ad5cfdde2fb11508041ed19b8c4ce66ad6ecebf7d7e836cc2318df47ca", + "0xaef1393e7d97278e77bbf52ef6e1c1d5db721ccf75fe753cf47a881fa034ca61eaa5098ee5a344c156d2b14ff9e284ad", + "0x8a4a26c07218948c1196c45d927ef4d2c42ade5e29fe7a91eaebe34a29900072ce5194cf28d51f746f4c4c649daf4396", + "0x84011dc150b7177abdcb715efbd8c201f9cb39c36e6069af5c50a096021768ba40cef45b659c70915af209f904ede3b6", + "0xb1bd90675411389bb66910b21a4bbb50edce5330850c5ab0b682393950124252766fc81f5ecfc72fb7184387238c402e", + "0x8dfdcd30583b696d2c7744655f79809f451a60c9ad5bf1226dc078b19f4585d7b3ef7fa9d54e1ac09520d95cbfd20928", + "0xb351b4dc6d98f75b8e5a48eb7c6f6e4b78451991c9ba630e5a1b9874c15ac450cd409c1a024713bf2cf82dc400e025ef", + "0xa462b8bc97ac668b97b28b3ae24b9f5de60e098d7b23ecb600d2194cd35827fb79f77c3e50d358f5bd72ee83fef18fa0", + "0xa183753265c5f7890270821880cce5f9b2965b115ba783c6dba9769536f57a04465d7da5049c7cf8b3fcf48146173c18", + "0xa8a771b81ed0d09e0da4d79f990e58eabcd2be3a2680419502dd592783fe52f657fe55125b385c41d0ba3b9b9cf54a83", + "0xa71ec577db46011689d073245e3b1c3222a9b1fe6aa5b83629adec5733dd48617ebea91346f0dd0e6cdaa86e4931b168", + "0xa334b8b244f0d598a02da6ae0f918a7857a54dce928376c4c85df15f3b0f2ba3ac321296b8b7c9dd47d770daf16c8f8c", + "0xa29037f8ef925c417c90c4df4f9fb27fb977d04e2b3dd5e8547d33e92ab72e7a00f5461de21e28835319eae5db145eb7", + "0xb91054108ae78b00e3298d667b913ebc44d8f26e531eae78a8fe26fdfb60271c97efb2dee5f47ef5a3c15c8228138927", + "0x926c13efbe90604f6244be9315a34f72a1f8d1aab7572df431998949c378cddbf2fe393502c930fff614ff06ae98a0ce", + "0x995c758fd5600e6537089b1baa4fbe0376ab274ff3e82a17768b40df6f91c2e443411de9cafa1e65ea88fb8b87d504f4", + "0x9245ba307a7a90847da75fca8d77ec03fdfc812c871e7a2529c56a0a79a6de16084258e7a9ac4ae8a3756f394336e21c", + "0x99e0cfa2bb57a7e624231317044c15e52196ecce020db567c8e8cb960354a0be9862ee0c128c60b44777e65ac315e59f", + "0xad4f6b3d27bbbb744126601053c3dc98c07ff0eb0b38a898bd80dce778372846d67e5ab8fb34fb3ad0ef3f235d77ba7f", + "0xa0f12cae3722bbbca2e539eb9cc7614632a2aefe51410430070a12b5bc5314ecec5857b7ff8f41e9980cac23064f7c56", + "0xb487f1bc59485848c98222fd3bc36c8c9bb3d2912e2911f4ceca32c840a7921477f9b1fe00877e05c96c75d3eecae061", + "0xa6033db53925654e18ecb3ce715715c36165d7035db9397087ac3a0585e587998a53973d011ac6d48af439493029cee6", + "0xa6b4d09cd01c70a3311fd131d3710ccf97bde3e7b80efd5a8c0eaeffeb48cca0f951ced905290267b115b06d46f2693b", + "0xa9dff1df0a8f4f218a98b6f818a693fb0d611fed0fc3143537cbd6578d479af13a653a8155e535548a2a0628ae24fa58", + "0xa58e469f65d366b519f9a394cacb7edaddac214463b7b6d62c2dbc1316e11c6c5184ce45c16de2d77f990dcdd8b55430", + "0x989e71734f8119103586dc9a3c5f5033ddc815a21018b34c1f876cdfc112efa868d5751bf6419323e4e59fa6a03ece1c", + "0xa2da00e05036c884369e04cf55f3de7d659cd5fa3f849092b2519dd263694efe0f051953d9d94b7e121f0aee8b6174d7", + "0x968f3c029f57ee31c4e1adea89a7f92e28483af9a74f30fbdb995dc2d40e8e657dff8f8d340d4a92bf65f54440f2859f", + "0x932778df6f60ac1639c1453ef0cbd2bf67592759dcccb3e96dcc743ff01679e4c7dd0ef2b0833dda548d32cb4eba49e2", + "0xa805a31139f8e0d6dae1ac87d454b23a3dc9fc653d4ca18d4f8ebab30fc189c16e73981c2cb7dd6f8c30454a5208109d", + "0xa9ba0991296caa2aaa4a1ceacfb205544c2a2ec97088eace1d84ee5e2767656a172f75d2f0c4e16a3640a0e0dec316e0", + "0xb1e49055c968dced47ec95ae934cf45023836d180702e20e2df57e0f62fb85d7ac60d657ba3ae13b8560b67210449459", + "0xa94e1da570a38809c71e37571066acabff7bf5632737c9ab6e4a32856924bf6211139ab3cedbf083850ff2d0e0c0fcfc", + "0x88ef1bb322000c5a5515b310c838c9af4c1cdbb32eab1c83ac3b2283191cd40e9573747d663763a28dad0d64adc13840", + "0xa987ce205f923100df0fbd5a85f22c9b99b9b9cbe6ddfa8dfda1b8fe95b4f71ff01d6c5b64ca02eb24edb2b255a14ef0", + "0x84fe8221a9e95d9178359918a108de4763ebfa7a6487facb9c963406882a08a9a93f492f8e77cf9e7ea41ae079c45993", + "0xaa1cf3dc7c5dcfa15bbbc811a4bb6dbac4fba4f97fb1ed344ab60264d7051f6eef19ea9773441d89929ee942ed089319", + "0x8f6a7d610d59d9f54689bbe6a41f92d9f6096cde919c1ab94c3c7fcecf0851423bc191e5612349e10f855121c0570f56", + "0xb5af1fa7894428a53ea520f260f3dc3726da245026b6d5d240625380bfb9c7c186df0204bb604efac5e613a70af5106e", + "0xa5bce6055ff812e72ce105f147147c7d48d7a2313884dd1f488b1240ee320f13e8a33f5441953a8e7a3209f65b673ce1", + "0xb9b55b4a1422677d95821e1d042ab81bbf0bf087496504021ec2e17e238c2ca6b44fb3b635a5c9eac0871a724b8d47c3", + "0x941c38e533ce4a673a3830845b56786585e5fe49c427f2e5c279fc6db08530c8f91db3e6c7822ec6bb4f956940052d18", + "0xa38e191d66c625f975313c7007bbe7431b5a06ed2da1290a7d5d0f2ec73770d476efd07b8e632de64597d47df175cbb0", + "0x94ba76b667abf055621db4c4145d18743a368d951565632ed4e743dd50dd3333507c0c34f286a5c5fdbf38191a2255cd", + "0xa5ca38c60be5602f2bfa6e00c687ac96ac36d517145018ddbee6f12eb0faa63dd57909b9eeed26085fe5ac44e55d10ab", + "0xb00fea3b825e60c1ed1c5deb4b551aa65a340e5af36b17d5262c9cd2c508711e4dc50dc2521a2c16c7c901902266e64a", + "0x971b86fc4033485e235ccb0997a236206ba25c6859075edbcdf3c943116a5030b7f75ebca9753d863a522ba21a215a90", + "0xb3b31f52370de246ee215400975b674f6da39b2f32514fe6bd54e747752eedca22bb840493b44a67df42a3639c5f901f", + "0xaffbbfac9c1ba7cbfa1839d2ae271dd6149869b75790bf103230637da41857fc326ef3552ff31c15bda0694080198143", + "0xa95d42aa7ef1962520845aa3688f2752d291926f7b0d73ea2ee24f0612c03b43f2b0fe3c9a9a99620ffc8d487b981bc2", + "0x914a266065caf64985e8c5b1cb2e3f4e3fe94d7d085a1881b1fefa435afef4e1b39a98551d096a62e4f5cc1a7f0fdc2e", + "0x81a0b4a96e2b75bc1bf2dbd165d58d55cfd259000a35504d1ffb18bc346a3e6f07602c683723864ffb980f840836fd8d", + "0x91c1556631cddd4c00b65b67962b39e4a33429029d311c8acf73a18600e362304fb68bccb56fde40f49e95b7829e0b87", + "0x8befbacc19e57f7c885d1b7a6028359eb3d80792fe13b92a8400df21ce48deb0bb60f2ddb50e3d74f39f85d7eab23adc", + "0x92f9458d674df6e990789690ec9ca73dacb67fc9255b58c417c555a8cc1208ace56e8e538f86ba0f3615573a0fbac00d", + "0xb4b1b3062512d6ae7417850c08c13f707d5838e43d48eb98dd4621baf62eee9e82348f80fe9b888a12874bfa538771f8", + "0xa13c4a3ac642ede37d9c883f5319e748d2b938f708c9d779714108a449b343f7b71a6e3ef4080fee125b416762920273", + "0xaf44983d5fc8cceee0551ef934e6e653f2d3efa385e5c8a27a272463a6f333e290378cc307c2b664eb923c78994e706e", + "0xa389fd6c59fe2b4031cc244e22d3991e541bd203dd5b5e73a6159e72df1ab41d49994961500dcde7989e945213184778", + "0x8d2141e4a17836c548de9598d7b298b03f0e6c73b7364979a411c464e0628e21cff6ac3d6decdba5d1c4909eff479761", + "0x980b22ef53b7bdf188a3f14bc51b0dbfdf9c758826daa3cbc1e3986022406a8aa9a6a79e400567120b88c67faa35ce5f", + "0xa28882f0a055f96df3711de5d0aa69473e71245f4f3e9aa944e9d1fb166e02caa50832e46da6d3a03b4801735fd01b29", + "0x8db106a37d7b88f5d995c126abb563934dd8de516af48e85695d02b1aea07f79217e3cdd03c6f5ca57421830186c772b", + "0xb5a7e50da0559a675c472f7dfaee456caab6695ab7870541b2be8c2b118c63752427184aad81f0e1afc61aef1f28c46f", + "0x9962118780e20fe291d10b64f28d09442a8e1b5cffd0f3dd68d980d0614050a626c616b44e9807fbee7accecae00686a", + "0xb38ddf33745e8d2ad6a991aefaf656a33c5f8cbe5d5b6b6fd03bd962153d8fd0e01b5f8f96d80ae53ab28d593ab1d4e7", + "0x857dc12c0544ff2c0c703761d901aba636415dee45618aba2e3454ff9cbc634a85c8b05565e88520ff9be2d097c8b2b1", + "0xa80d465c3f8cc63af6d74a6a5086b626c1cb4a8c0fee425964c3bd203d9d7094e299f81ce96d58afc20c8c9a029d9dae", + "0x89e1c8fbde8563763be483123a3ed702efac189c6d8ab4d16c85e74bbaf856048cc42d5d6e138633a38572ba5ec3f594", + "0x893a594cf495535f6d216508f8d03c317dcf03446668cba688da90f52d0111ac83d76ad09bf5ea47056846585ee5c791", + "0xaadbd8be0ae452f7f9450c7d2957598a20cbf10139a4023a78b4438172d62b18b0de39754dd2f8862dbd50a3a0815e53", + "0xae7d39670ecca3eb6db2095da2517a581b0e8853bdfef619b1fad9aacd443e7e6a40f18209fadd44038a55085c5fe8b2", + "0x866ef241520eacb6331593cfcb206f7409d2f33d04542e6e52cba5447934e02d44c471f6c9a45963f9307e9809ab91d9", + "0xb1a09911ad3864678f7be79a9c3c3eb5c84a0a45f8dcb52c67148f43439aeaaa9fd3ed3471276b7e588b49d6ebe3033a", + "0xadd07b7f0dbb34049cd8feeb3c18da5944bf706871cfd9f14ff72f6c59ad217ebb1f0258b13b167851929387e4e34cfe", + "0xae048892d5c328eefbdd4fba67d95901e3c14d974bfc0a1fc68155ca9f0d59e61d7ba17c6c9948b120cf35fd26e6fee9", + "0x9185b4f3b7da0ddb4e0d0f09b8a9e0d6943a4611e43f13c3e2a767ed8592d31e0ba3ebe1914026a3627680274291f6e5", + "0xa9c022d4e37b0802284ce3b7ee9258628ab4044f0db4de53d1c3efba9de19d15d65cc5e608dbe149c21c2af47d0b07b5", + "0xb24dbd5852f8f24921a4e27013b6c3fa8885b973266cb839b9c388efad95821d5d746348179dcc07542bd0d0aefad1ce", + "0xb5fb4f279300876a539a27a441348764908bc0051ebd66dc51739807305e73db3d2f6f0f294ffb91b508ab150eaf8527", + "0xace50841e718265b290c3483ed4b0fdd1175338c5f1f7530ae9a0e75d5f80216f4de37536adcbc8d8c95982e88808cd0", + "0xb19cadcde0f63bd1a9c24bd9c2806f53c14c0b9735bf351601498408ba503ddbd2037c891041cbba47f58b8c483f3b21", + "0xb6061e63558d312eb891b97b39aa552fa218568d79ee26fe6dd5b864aea9e3216d8f2e2f3b093503be274766dac41426", + "0x89730fdb2876ab6f0fe780d695f6e12090259027e789b819956d786e977518057e5d1d7f5ab24a3ae3d5d4c97773bd2b", + "0xb6fa841e81f9f2cad0163a02a63ae96dc341f7ae803b616efc6e1da2fbea551c1b96b11ad02c4afbdf6d0cc9f23da172", + "0x8fb66187182629c861ddb6896d7ed3caf2ad050c3dba8ab8eb0d7a2c924c3d44c48d1a148f9e33fb1f061b86972f8d21", + "0x86022ac339c1f84a7fa9e05358c1a5b316b4fc0b83dbe9c8c7225dc514f709d66490b539359b084ce776e301024345fa", + "0xb50b9c321468da950f01480bb62b6edafd42f83c0001d6e97f2bd523a1c49a0e8574fb66380ea28d23a7c4d54784f9f0", + "0xa31c05f7032f30d1dac06678be64d0250a071fd655e557400e4a7f4c152be4d5c7aa32529baf3e5be7c4bd49820054f6", + "0xb95ac0848cd322684772119f5b682d90a66bbf9dac411d9d86d2c34844bbd944dbaf8e47aa41380455abd51687931a78", + "0xae4a6a5ce9553b65a05f7935e61e496a4a0f6fd8203367a2c627394c9ce1e280750297b74cdc48fd1d9a31e93f97bef4", + "0xa22daf35f6e9b05e52e0b07f7bd1dbbebd2c263033fb0e1b2c804e2d964e2f11bc0ece6aca6af079dd3a9939c9c80674", + "0x902150e0cb1f16b9b59690db35281e28998ce275acb313900da8b2d8dfd29fa1795f8ca3ff820c31d0697de29df347c1", + "0xb17b5104a5dc665cdd7d47e476153d715eb78c6e5199303e4b5445c21a7fa7cf85fe7cfd08d7570f4e84e579b005428c", + "0xa03f49b81c15433f121680aa02d734bb9e363af2156654a62bcb5b2ba2218398ccb0ff61104ea5d7df5b16ea18623b1e", + "0x802101abd5d3c88876e75a27ffc2f9ddcce75e6b24f23dba03e5201281a7bd5cc7530b6a003be92d225093ca17d3c3bb", + "0xa4d183f63c1b4521a6b52226fc19106158fc8ea402461a5cccdaa35fee93669df6a8661f45c1750cd01308149b7bf08e", + "0x8d17c22e0c8403b69736364d460b3014775c591032604413d20a5096a94d4030d7c50b9fe3240e31d0311efcf9816a47", + "0x947225acfcce5992eab96276f668c3cbe5f298b90a59f2bb213be9997d8850919e8f496f182689b5cbd54084a7332482", + "0x8df6f4ed216fc8d1905e06163ba1c90d336ab991a18564b0169623eb39b84e627fa267397da15d3ed754d1f3423bff07", + "0x83480007a88f1a36dea464c32b849a3a999316044f12281e2e1c25f07d495f9b1710b4ba0d88e9560e72433addd50bc2", + "0xb3019d6e591cf5b33eb972e49e06c6d0a82a73a75d78d383dd6f6a4269838289e6e07c245f54fed67f5c9bb0fd5e1c5f", + "0x92e8ce05e94927a9fb02debadb99cf30a26172b2705003a2c0c47b3d8002bf1060edb0f6a5750aad827c98a656b19199", + "0xac2aff801448dbbfc13cca7d603fd9c69e82100d997faf11f465323b97255504f10c0c77401e4d1890339d8b224f5803", + "0xb0453d9903d08f508ee27e577445dc098baed6cde0ac984b42e0f0efed62760bd58d5816cf1e109d204607b7b175e30c", + "0xae68dc4ba5067e825d46d2c7c67f1009ceb49d68e8d3e4c57f4bcd299eb2de3575d42ea45e8722f8f28497a6e14a1cfe", + "0xb22486c2f5b51d72335ce819bbafb7fa25eb1c28a378a658f13f9fc79cd20083a7e573248d911231b45a5cf23b561ca7", + "0x89d1201d1dbd6921867341471488b4d2fd0fc773ae1d4d074c78ae2eb779a59b64c00452c2a0255826fca6b3d03be2b1", + "0xa2998977c91c7a53dc6104f5bc0a5b675e5350f835e2f0af69825db8af4aeb68435bdbcc795f3dd1f55e1dd50bc0507f", + "0xb0be4937a925b3c05056ed621910d535ccabf5ab99fd3b9335080b0e51d9607d0fd36cb5781ff340018f6acfca4a9736", + "0xaea145a0f6e0ba9df8e52e84bb9c9de2c2dc822f70d2724029b153eb68ee9c17de7d35063dcd6a39c37c59fdd12138f7", + "0x91cb4545d7165ee8ffbc74c874baceca11fdebbc7387908d1a25877ca3c57f2c5def424dab24148826832f1e880bede0", + "0xb3b579cb77573f19c571ad5eeeb21f65548d7dff9d298b8d7418c11f3e8cd3727c5b467f013cb87d6861cfaceee0d2e3", + "0xb98a1eeec2b19fecc8378c876d73645aa52fb99e4819903735b2c7a885b242787a30d1269a04bfb8573d72d9bbc5f0f0", + "0x940c1f01ed362bd588b950c27f8cc1d52276c71bb153d47f07ec85b038c11d9a8424b7904f424423e714454d5e80d1cd", + "0xaa343a8ecf09ce11599b8cf22f7279cf80f06dbf9f6d62cb05308dbbb39c46fd0a4a1240b032665fbb488a767379b91b", + "0x87c3ac72084aca5974599d3232e11d416348719e08443acaba2b328923af945031f86432e170dcdd103774ec92e988c9", + "0x91d6486eb5e61d2b9a9e742c20ec974a47627c6096b3da56209c2b4e4757f007e793ebb63b2b246857c9839b64dc0233", + "0xaebcd3257d295747dd6fc4ff910d839dd80c51c173ae59b8b2ec937747c2072fa85e3017f9060aa509af88dfc7529481", + "0xb3075ba6668ca04eff19efbfa3356b92f0ab12632dcda99cf8c655f35b7928c304218e0f9799d68ef9f809a1492ff7db", + "0x93ba7468bb325639ec2abd4d55179c69fd04eaaf39fc5340709227bbaa4ad0a54ea8b480a1a3c8d44684e3be0f8d1980", + "0xa6aef86c8c0d92839f38544d91b767c582568b391071228ff5a5a6b859c87bf4f81a7d926094a4ada1993ddbd677a920", + "0x91dcd6d14207aa569194aa224d1e5037b999b69ade52843315ca61ba26abe9a76412c9e88259bc5cf5d7b95b97d9c3bc", + "0xb3b483d31c88f78d49bd065893bc1e3d2aa637e27dedb46d9a7d60be7660ce7a10aaaa7deead362284a52e6d14021178", + "0x8e5730070acf8371461ef301cc4523e8e672aa0e3d945d438a0e0aa6bdf8cb9c685dcf38df429037b0c8aff3955c6f5b", + "0xb8c6d769890a8ee18dc4f9e917993315877c97549549b34785a92543cbeec96a08ae3a28d6e809c4aacd69de356c0012", + "0x95ca86cd384eaceaa7c077c5615736ca31f36824bd6451a16142a1edc129fa42b50724aeed7c738f08d7b157f78b569e", + "0x94df609c6d71e8eee7ab74226e371ccc77e01738fe0ef1a6424435b4570fe1e5d15797b66ed0f64eb88d4a3a37631f0e", + "0x89057b9783212add6a0690d6bb99097b182738deff2bd9e147d7fd7d6c8eacb4c219923633e6309ad993c24572289901", + "0x83a0f9f5f265c5a0e54defa87128240235e24498f20965009fef664f505a360b6fb4020f2742565dfc7746eb185bcec0", + "0x91170da5306128931349bc3ed50d7df0e48a68b8cc8420975170723ac79d8773e4fa13c5f14dc6e3fafcad78379050b1", + "0xb7178484d1b55f7e56a4cc250b6b2ec6040437d96bdfddfa7b35ed27435860f3855c2eb86c636f2911b012eb83b00db8", + "0xac0b00c4322d1e4208e09cd977b4e54d221133ff09551f75b32b0b55d0e2be80941dda26257b0e288c162e63c7e9cf68", + "0x9690ed9e7e53ed37ff362930e4096b878b12234c332fd19d5d064824084245952eda9f979e0098110d6963e468cf513e", + "0xb6fa547bb0bb83e5c5be0ed462a8783fba119041c136a250045c09d0d2af330c604331e7de960df976ff76d67f8000cd", + "0x814603907c21463bcf4e59cfb43066dfe1a50344ae04ef03c87c0f61b30836c3f4dea0851d6fa358c620045b7f9214c8", + "0x9495639e3939fad2a3df00a88603a5a180f3c3a0fe4d424c35060e2043e0921788003689887b1ed5be424d9a89bb18bb", + "0xaba4c02d8d57f2c92d5bc765885849e9ff8393d6554f5e5f3e907e5bfac041193a0d8716d7861104a4295d5a03c36b03", + "0x8ead0b56c1ca49723f94a998ba113b9058059321da72d9e395a667e6a63d5a9dac0f5717cec343f021695e8ced1f72af", + "0xb43037f7e3852c34ed918c5854cd74e9d5799eeddfe457d4f93bb494801a064735e326a76e1f5e50a339844a2f4a8ec9", + "0x99db8422bb7302199eb0ff3c3d08821f8c32f53a600c5b6fb43e41205d96adae72be5b460773d1280ad1acb806af9be8", + "0x8a9be08eae0086c0f020838925984df345c5512ff32e37120b644512b1d9d4fecf0fd30639ca90fc6cf334a86770d536", + "0x81b43614f1c28aa3713a309a88a782fb2bdfc4261dd52ddc204687791a40cf5fd6a263a8179388596582cccf0162efc2", + "0xa9f3a8b76912deb61d966c75daf5ddb868702ebec91bd4033471c8e533183df548742a81a2671de5be63a502d827437d", + "0x902e2415077f063e638207dc7e14109652e42ab47caccd6204e2870115791c9defac5425fd360b37ac0f7bd8fe7011f8", + "0xaa18e4fdc1381b59c18503ae6f6f2d6943445bd00dd7d4a2ad7e5adad7027f2263832690be30d456e6d772ad76f22350", + "0xa348b40ba3ba7d81c5d4631f038186ebd5e5f314f1ea737259151b07c3cc8cf0c6ed4201e71bcc1c22fefda81a20cde6", + "0xaa1306f7ac1acbfc47dc6f7a0cb6d03786cec8c8dc8060388ccda777bca24bdc634d03e53512c23dba79709ff64f8620", + "0x818ccfe46e700567b7f3eb400e5a35f6a5e39b3db3aa8bc07f58ace35d9ae5a242faf8dbccd08d9a9175bbce15612155", + "0xb7e3da2282b65dc8333592bb345a473f03bd6df69170055fec60222de9897184536bf22b9388b08160321144d0940279", + "0xa4d976be0f0568f4e57de1460a1729129252b44c552a69fceec44e5b97c96c711763360d11f9e5bf6d86b4976bf40d69", + "0x85d185f0397c24c2b875b09b6328a23b87982b84ee880f2677a22ff4c9a1ba9f0fea000bb3f7f66375a00d98ebafce17", + "0xb4ccbb8c3a2606bd9b87ce022704663af71d418351575f3b350d294f4efc68c26f9a2ce49ff81e6ff29c3b63d746294e", + "0x93ffd3265fddb63724dfde261d1f9e22f15ecf39df28e4d89e9fea03221e8e88b5dd9b77628bacaa783c6f91802d47cc", + "0xb1fd0f8d7a01378e693da98d03a2d2fda6b099d03454b6f2b1fa6472ff6bb092751ce6290059826b74ac0361eab00e1e", + "0xa89f440c71c561641589796994dd2769616b9088766e983c873fae0716b95c386c8483ab8a4f367b6a68b72b7456dd32", + "0xaf4fe92b01d42d03dd5d1e7fa55e96d4bbcb7bf7d4c8c197acd16b3e0f3455807199f683dcd263d74547ef9c244b35cc", + "0xa8227f6e0a344dfe76bfbe7a1861be32c4f4bed587ccce09f9ce2cf481b2dda8ae4f566154bc663d15f962f2d41761bd", + "0xa7b361663f7495939ed7f518ba45ea9ff576c4e628995b7aea026480c17a71d63fc2c922319f0502eb7ef8f14a406882", + "0x8ddcf382a9f39f75777160967c07012cfa89e67b19714a7191f0c68eaf263935e5504e1104aaabd0899348c972a8d3c6", + "0x98c95b9f6f5c91f805fb185eedd06c6fc4457d37dd248d0be45a6a168a70031715165ea20606245cbdf8815dc0ac697f", + "0x805b44f96e001e5909834f70c09be3efcd3b43632bcac5b6b66b6d227a03a758e4b1768ce2a723045681a1d34562aaeb", + "0xb0e81b07cdc45b3dca60882676d9badb99f25c461b7efe56e3043b80100bb62d29e1873ae25eb83087273160ece72a55", + "0xb0c53f0abe78ee86c7b78c82ae1f7c070bb0b9c45c563a8b3baa2c515d482d7507bb80771e60b38ac13f78b8af92b4a9", + "0xa7838ef6696a9e4d2e5dfd581f6c8d6a700467e8fd4e85adabb5f7a56f514785dd4ab64f6f1b48366f7d94728359441b", + "0x88c76f7700a1d23c30366a1d8612a796da57b2500f97f88fdf2d76b045a9d24e7426a8ffa2f4e86d3046937a841dad58", + "0xad8964baf98c1f02e088d1d9fcb3af6b1dfa44cdfe0ed2eae684e7187c33d3a3c28c38e8f4e015f9c04d451ed6f85ff6", + "0x90e9d00a098317ececaa9574da91fc149eda5b772dedb3e5a39636da6603aa007804fa86358550cfeff9be5a2cb7845e", + "0xa56ff4ddd73d9a6f5ab23bb77efa25977917df63571b269f6a999e1ad6681a88387fcc4ca3b26d57badf91b236503a29", + "0x97ad839a6302c410a47e245df84c01fb9c4dfef86751af3f9340e86ff8fc3cd52fa5ff0b9a0bd1d9f453e02ca80658a6", + "0xa4c8c44cbffa804129e123474854645107d1f0f463c45c30fd168848ebea94880f7c0c5a45183e9eb837f346270bdb35", + "0xa72e53d0a1586d736e86427a93569f52edd2f42b01e78aee7e1961c2b63522423877ae3ac1227a2cf1e69f8e1ff15bc3", + "0x8559f88a7ef13b4f09ac82ae458bbae6ab25671cfbf52dae7eac7280d6565dd3f0c3286aec1a56a8a16dc3b61d78ce47", + "0x8221503f4cdbed550876c5dc118a3f2f17800c04e8be000266633c83777b039a432d576f3a36c8a01e8fd18289ebc10b", + "0x99bfbe5f3e46d4d898a578ba86ed26de7ed23914bd3bcdf3c791c0bcd49398a52419077354a5ab75cea63b6c871c6e96", + "0xaa134416d8ff46f2acd866c1074af67566cfcf4e8be8d97329dfa0f603e1ff208488831ce5948ac8d75bfcba058ddcaa", + "0xb02609d65ebfe1fe8e52f21224a022ea4b5ea8c1bd6e7b9792eed8975fc387cdf9e3b419b8dd5bcce80703ab3a12a45f", + "0xa4f14798508698fa3852e5cac42a9db9797ecee7672a54988aa74037d334819aa7b2ac7b14efea6b81c509134a6b7ad2", + "0x884f01afecbcb987cb3e7c489c43155c416ed41340f61ecb651d8cba884fb9274f6d9e7e4a46dd220253ae561614e44c", + "0xa05523c9e71dce1fe5307cc71bd721feb3e1a0f57a7d17c7d1c9fb080d44527b7dbaa1f817b1af1c0b4322e37bc4bb1e", + "0x8560aec176a4242b39f39433dd5a02d554248c9e49d3179530815f5031fee78ba9c71a35ceeb2b9d1f04c3617c13d8f0", + "0x996aefd402748d8472477cae76d5a2b92e3f092fc834d5222ae50194dd884c9fb8b6ed8e5ccf8f6ed483ddbb4e80c747", + "0x8fd09900320000cbabc40e16893e2fcf08815d288ec19345ad7b6bb22f7d78a52b6575a3ca1ca2f8bc252d2eafc928ec", + "0x939e51f73022bc5dc6862a0adf8fb8a3246b7bfb9943cbb4b27c73743926cc20f615a036c7e5b90c80840e7f1bfee0e7", + "0xa0a6258700cadbb9e241f50766573bf9bdb7ad380b1079dc3afb4054363d838e177b869cad000314186936e40359b1f2", + "0x972699a4131c8ed27a2d0e2104d54a65a7ff1c450ad9da3a325c662ab26869c21b0a84d0700b98c8b5f6ce3b746873d7", + "0xa454c7fe870cb8aa6491eafbfb5f7872d6e696033f92e4991d057b59d70671f2acdabef533e229878b60c7fff8f748b1", + "0xa167969477214201f09c79027b10221e4707662e0c0fde81a0f628249f2f8a859ce3d30a7dcc03b8ecca8f7828ad85c7", + "0x8ff6b7265175beb8a63e1dbf18c9153fb2578c207c781282374f51b40d57a84fd2ef2ea2b9c6df4a54646788a62fd17f", + "0xa3d7ebeccde69d73d8b3e76af0da1a30884bb59729503ff0fb0c3bccf9221651b974a6e72ea33b7956fc3ae758226495", + "0xb71ef144c9a98ce5935620cb86c1590bd4f48e5a2815d25c0cdb008fde628cf628c31450d3d4f67abbfeb16178a74cfd", + "0xb5e0a16d115134f4e2503990e3f2035ed66b9ccf767063fe6747870d97d73b10bc76ed668550cb82eedc9a2ca6f75524", + "0xb30ffaaf94ee8cbc42aa2c413175b68afdb207dbf351fb20be3852cb7961b635c22838da97eaf43b103aff37e9e725cc", + "0x98aa7d52284f6c1f22e272fbddd8c8698cf8f5fbb702d5de96452141fafb559622815981e50b87a72c2b1190f59a7deb", + "0x81fbacda3905cfaf7780bb4850730c44166ed26a7c8d07197a5d4dcd969c09e94a0461638431476c16397dd7bdc449f9", + "0x95e47021c1726eac2e5853f570d6225332c6e48e04c9738690d53e07c6b979283ebae31e2af1fc9c9b3e59f87e5195b1", + "0xac024a661ba568426bb8fce21780406537f518075c066276197300841e811860696f7588188bc01d90bace7bc73d56e3", + "0xa4ebcaf668a888dd404988ab978594dee193dad2d0aec5cdc0ccaf4ec9a7a8228aa663db1da8ddc52ec8472178e40c32", + "0xa20421b8eaf2199d93b083f2aff37fb662670bd18689d046ae976d1db1fedd2c2ff897985ecc6277b396db7da68bcb27", + "0x8bc33d4b40197fd4d49d1de47489d10b90d9b346828f53a82256f3e9212b0cbc6930b895e879da9cec9fedf026aadb3e", + "0xaaafdd1bec8b757f55a0433eddc0a39f818591954fd4e982003437fcceb317423ad7ee74dbf17a2960380e7067a6b4e2", + "0xaad34277ebaed81a6ec154d16736866f95832803af28aa5625bf0461a71d02b1faba02d9d9e002be51c8356425a56867", + "0x976e9c8b150d08706079945bd0e84ab09a648ecc6f64ded9eb5329e57213149ae409ae93e8fbd8eda5b5c69f5212b883", + "0x8097fae1653247d2aed4111533bc378171d6b2c6d09cbc7baa9b52f188d150d645941f46d19f7f5e27b7f073c1ebd079", + "0x83905f93b250d3184eaba8ea7d727c4464b6bdb027e5cbe4f597d8b9dc741dcbea709630bd4fd59ce24023bec32fc0f3", + "0x8095030b7045cff28f34271386e4752f9a9a0312f8df75de4f424366d78534be2b8e1720a19cb1f9a2d21105d790a225", + "0xa7b7b73a6ae2ed1009c49960374b0790f93c74ee03b917642f33420498c188a169724945a975e5adec0a1e83e07fb1b2", + "0x856a41c54df393b6660b7f6354572a4e71c8bfca9cabaffb3d4ef2632c015e7ee2bc10056f3eccb3dbed1ad17d939178", + "0xa8f7a55cf04b38cd4e330394ee6589da3a07dc9673f74804fdf67b364e0b233f14aec42e783200a2e4666f7c5ff62490", + "0x82c529f4e543c6bca60016dc93232c115b359eaee2798a9cf669a654b800aafe6ab4ba58ea8b9cdda2b371c8d62fa845", + "0x8caab020c1baddce77a6794113ef1dfeafc5f5000f48e97f4351b588bf02f1f208101745463c480d37f588d5887e6d8c", + "0x8fa91b3cc400f48b77b6fd77f3b3fbfb3f10cdff408e1fd22d38f77e087b7683adad258804409ba099f1235b4b4d6fea", + "0x8aa02787663d6be9a35677d9d8188b725d5fcd770e61b11b64e3def8808ea5c71c0a9afd7f6630c48634546088fcd8e2", + "0xb5635b7b972e195cab878b97dea62237c7f77eb57298538582a330b1082f6207a359f2923864630136d8b1f27c41b9aa", + "0x8257bb14583551a65975946980c714ecd6e5b629672bb950b9caacd886fbd22704bc9e3ba7d30778adab65dc74f0203a", + "0xab5fe1cd12634bfa4e5c60d946e2005cbd38f1063ec9a5668994a2463c02449a0a185ef331bd86b68b6e23a8780cb3ba", + "0xa7d3487da56cda93570cc70215d438204f6a2709bfb5fda6c5df1e77e2efc80f4235c787e57fbf2c74aaff8cbb510a14", + "0xb61cff7b4c49d010e133319fb828eb900f8a7e55114fc86b39c261a339c74f630e1a7d7e1350244ada566a0ff3d46c4b", + "0x8d4d1d55d321d278db7a85522ccceca09510374ca81d4d73e3bb5249ace7674b73900c35a531ec4fa6448fabf7ad00dc", + "0x966492248aee24f0f56c8cfca3c8ec6ba3b19abb69ae642041d4c3be8523d22c65c4dafcab4c58989ccc4e0bd2f77919", + "0xb20c320a90cb220b86e1af651cdc1e21315cd215da69f6787e28157172f93fc8285dcd59b039c626ed8ca4633cba1a47", + "0xaae9e6b22f018ceb5c0950210bb8182cb8cb61014b7e14581a09d36ebd1bbfebdb2b82afb7fdb0cf75e58a293d9c456d", + "0x875547fb67951ad37b02466b79f0c9b985ccbc500cfb431b17823457dc79fb9597ec42cd9f198e15523fcd88652e63a4", + "0x92afce49773cb2e20fb21e4f86f18e0959ebb9c33361547ddb30454ee8e36b1e234019cbdca0e964cb292f7f77df6b90", + "0x8af85343dfe1821464c76ba11c216cbef697b5afc69c4d821342e55afdac047081ec2e3f7b09fc14b518d9a23b78c003", + "0xb7de4a1648fd63f3a918096ea669502af5357438e69dac77cb8102b6e6c15c76e033cfaa80dafc806e535ede5c1a20aa", + "0xac80e9b545e8bd762951d96c9ce87f629d01ffcde07efc2ef7879ca011f1d0d8a745abf26c9d452541008871304fac00", + "0xa4cf0f7ed724e481368016c38ea5816698a5f68eb21af4d3c422d2ba55f96a33e427c2aa40de1b56a7cfac7f7cf43ab0", + "0x899b0a678bb2db2cae1b44e75a661284844ebcdd87abf308fedeb2e4dbe5c5920c07db4db7284a7af806a2382e8b111a", + "0xaf0588a2a4afce2b1b13c1230816f59e8264177e774e4a341b289a101dcf6af813638fed14fb4d09cb45f35d5d032609", + "0xa4b8df79e2be76e9f5fc5845f06fe745a724cf37c82fcdb72719b77bdebea3c0e763f37909373e3a94480cc5e875cba0", + "0x83e42c46d88930c8f386b19fd999288f142d325e2ebc86a74907d6d77112cb0d449bc511c95422cc810574031a8cbba9", + "0xb5e39534070de1e5f6e27efbdd3dc917d966c2a9b8cf2d893f964256e95e954330f2442027dc148c776d63a95bcde955", + "0x958607569dc28c075e658cd4ae3927055c6bc456eef6212a6fea8205e48ed8777a8064f584cda38fe5639c371e2e7fba", + "0x812adf409fa63575113662966f5078a903212ffb65c9b0bbe62da0f13a133443a7062cb8fd70f5e5dd5559a32c26d2c8", + "0xa679f673e5ce6a3cce7fa31f22ee3785e96bcb55e5a776e2dd3467bef7440e3555d1a9b87cb215e86ee9ed13a090344b", + "0xafedbb34508b159eb25eb2248d7fe328f86ef8c7d84c62d5b5607d74aae27cc2cc45ee148eb22153b09898a835c58df4", + "0xb75505d4f6b67d31e665cfaf5e4acdb5838ae069166b7fbcd48937c0608a59e40a25302fcc1873d2e81c1782808c70f0", + "0xb62515d539ec21a155d94fc00ea3c6b7e5f6636937bce18ed5b618c12257fb82571886287fd5d1da495296c663ebc512", + "0xab8e1a9446bbdd588d1690243b1549d230e6149c28f59662b66a8391a138d37ab594df38e7720fae53217e5c3573b5be", + "0xb31e8abf4212e03c3287bb2c0a153065a7290a16764a0bac8f112a72e632185a654bb4e88fdd6053e6c7515d9719fadb", + "0xb55165477fe15b6abd2d0f4fddaa9c411710dcc4dd712daba3d30e303c9a3ee5415c256f9dc917ecf18c725b4dbab059", + "0xa0939d4f57cacaae549b78e87cc234de4ff6a35dc0d9cd5d7410abc30ebcd34c135e008651c756e5a9d2ca79c40ef42b", + "0x8cf10e50769f3443340844aad4d56ec790850fed5a41fcbd739abac4c3015f0a085a038fbe7fae9f5ad899cce5069f6b", + "0x924055e804d82a99ea4bb160041ea4dc14b568abf379010bc1922fde5d664718c31d103b8b807e3a1ae809390e708c73", + "0x8ec0f9d26f71b0f2e60a179e4fd1778452e2ffb129d50815e5d7c7cb9415fa69ae5890578086e8ef6bfde35ad2a74661", + "0x98c7f12b15ec4426b59f737f73bf5faea4572340f4550b7590dfb7f7ffedb2372e3e555977c63946d579544c53210ad0", + "0x8a935f7a955c78f69d66f18eee0092e5e833fa621781c9581058e219af4d7ceee48b84e472e159dda6199715fb2f9acf", + "0xb78d4219f95a2dbfaa7d0c8a610c57c358754f4f43c2af312ab0fe8f10a5f0177e475332fb8fd23604e474fc2abeb051", + "0x8d086a14803392b7318c28f1039a17e3cfdcece8abcaca3657ec3d0ac330842098a85c0212f889fabb296dfb133ce9aa", + "0xa53249f417aac82f2c2a50c244ce21d3e08a5e5a8bd33bec2a5ab0d6cd17793e34a17edfa3690899244ce201e2fb9986", + "0x8619b0264f9182867a1425be514dc4f1ababc1093138a728a28bd7e4ecc99b9faaff68c23792264bc6e4dce5f52a5c52", + "0x8c171edbbbde551ec19e31b2091eb6956107dd9b1f853e1df23bff3c10a3469ac77a58335eee2b79112502e8e163f3de", + "0xa9d19ec40f0ca07c238e9337c6d6a319190bdba2db76fb63902f3fb459aeeb50a1ac30db5b25ee1b4201f3ca7164a7f4", + "0xb9c6ec14b1581a03520b8d2c1fbbc31fb8ceaef2c0f1a0d0080b6b96e18442f1734bea7ef7b635d787c691de4765d469", + "0x8cb437beb4cfa013096f40ccc169a713dc17afee6daa229a398e45fd5c0645a9ad2795c3f0cd439531a7151945d7064d", + "0xa6e8740cc509126e146775157c2eb278003e5bb6c48465c160ed27888ca803fa12eee1f6a8dd7f444f571664ed87fdc1", + "0xb75c1fecc85b2732e96b3f23aefb491dbd0206a21d682aee0225838dc057d7ed3b576176353e8e90ae55663f79e986e4", + "0xad8d249b0aea9597b08358bce6c77c1fd552ef3fbc197d6a1cfe44e5e6f89b628b12a6fb04d5dcfcbacc51f46e4ae7bb", + "0xb998b2269932cbd58d04b8e898d373ac4bb1a62e8567484f4f83e224061bc0f212459f1daae95abdbc63816ae6486a55", + "0x827988ef6c1101cddc96b98f4a30365ff08eea2471dd949d2c0a9b35c3bbfa8c07054ad1f4c88c8fbf829b20bb5a9a4f", + "0x8692e638dd60babf7d9f2f2d2ce58e0ac689e1326d88311416357298c6a2bffbfebf55d5253563e7b3fbbf5072264146", + "0xa685d75b91aea04dbc14ab3c1b1588e6de96dae414c8e37b8388766029631b28dd860688079b12d09cd27f2c5af11adf", + "0xb57eced93eec3371c56679c259b34ac0992286be4f4ff9489d81cf9712403509932e47404ddd86f89d7c1c3b6391b28c", + "0xa1c8b4e42ebcbd8927669a97f1b72e236fb19249325659e72be7ddaaa1d9e81ca2abb643295d41a8c04a2c01f9c0efd7", + "0x877c33de20d4ed31674a671ba3e8f01a316581e32503136a70c9c15bf0b7cb7b1cba6cd4eb641fad165fb3c3c6c235fd", + "0xa2a469d84ec478da40838f775d11ad38f6596eb41caa139cc190d6a10b5108c09febae34ffdafac92271d2e73c143693", + "0x972f817caedb254055d52e963ed28c206848b6c4cfdb69dbc961c891f8458eaf582a6d4403ce1177d87bc2ea410ef60a", + "0xaccbd739e138007422f28536381decc54bb6bd71d93edf3890e54f9ef339f83d2821697d1a4ac1f5a98175f9a9ecb9b5", + "0x8940f8772e05389f823b62b3adc3ed541f91647f0318d7a0d3f293aeeb421013de0d0a3664ea53dd24e5fbe02d7efef6", + "0x8ecce20f3ef6212edef07ec4d6183fda8e0e8cad2c6ccd0b325e75c425ee1faba00b5c26b4d95204238931598d78f49d", + "0x97cc72c36335bd008afbed34a3b0c7225933faba87f7916d0a6d2161e6f82e0cdcda7959573a366f638ca75d30e9dab1", + "0x9105f5de8699b5bdb6bd3bb6cc1992d1eac23929c29837985f83b22efdda92af64d9c574aa9640475087201bbbe5fd73", + "0x8ffb33c4f6d05c413b9647eb6933526a350ed2e4278ca2ecc06b0e8026d8dbe829c476a40e45a6df63a633090a3f82ef", + "0x8bfc6421fdc9c2d2aaa68d2a69b1a2728c25b84944cc3e6a57ff0c94bfd210d1cbf4ff3f06702d2a8257024d8be7de63", + "0xa80e1dc1dddfb41a70220939b96dc6935e00b32fb8be5dff4eed1f1c650002ff95e4af481c43292e3827363b7ec4768a", + "0x96f714ebd54617198bd636ba7f7a7f8995a61db20962f2165078d9ed8ee764d5946ef3cbdc7ebf8435bb8d5dd4c1deac", + "0x8cdb0890e33144d66391d2ae73f5c71f5a861f72bc93bff6cc399fc25dd1f9e17d8772592b44593429718784802ac377", + "0x8ccf9a7f80800ee770b92add734ed45a73ecc31e2af0e04364eefc6056a8223834c7c0dc9dfc52495bdec6e74ce69994", + "0xaa0875f423bd68b5f10ba978ddb79d3b96ec093bfbac9ff366323193e339ed7c4578760fb60f60e93598bdf1e5cc4995", + "0xa9214f523957b59c7a4cb61a40251ad72aba0b57573163b0dc0f33e41d2df483fb9a1b85a5e7c080e9376c866790f8cb", + "0xb6224b605028c6673a536cc8ff9aeb94e7a22e686fda82cf16068d326469172f511219b68b2b3affb7933af0c1f80d07", + "0xb6d58968d8a017c6a34e24c2c09852f736515a2c50f37232ac6b43a38f8faa7572cc31dade543b594b61b5761c4781d0", + "0x8a97cefe5120020c38deeb861d394404e6c993c6cbd5989b6c9ebffe24f46ad11b4ba6348e2991cbf3949c28cfc3c99d", + "0x95bf046f8c3a9c0ce2634be4de3713024daec3fc4083e808903b25ce3ac971145af90686b451efcc72f6b22df0216667", + "0xa6a4e2f71b8fa28801f553231eff2794c0f10d12e7e414276995e21195abc9c2983a8997e41af41e78d19ff6fbb2680b", + "0x8e5e62a7ca9c2f58ebaab63db2ff1fb1ff0877ae94b7f5e2897f273f684ae639dff44cc65718f78a9c894787602ab26a", + "0x8542784383eec4f565fcb8b9fc2ad8d7a644267d8d7612a0f476fc8df3aff458897a38003d506d24142ad18f93554f2b", + "0xb7db68ba4616ea072b37925ec4fb39096358c2832cc6d35169e032326b2d6614479f765ae98913c267105b84afcb9bf2", + "0x8b31dbb9457d23d416c47542c786e07a489af35c4a87dadb8ee91bea5ac4a5315e65625d78dad2cf8f9561af31b45390", + "0xa8545a1d91ac17257732033d89e6b7111db8242e9c6ebb0213a88906d5ef407a2c6fdb444e29504b06368b6efb4f4839", + "0xb1bd85d29ebb28ccfb05779aad8674906b267c2bf8cdb1f9a0591dd621b53a4ee9f2942687ee3476740c0b4a7621a3ae", + "0xa2b54534e152e46c50d91fff03ae9cd019ff7cd9f4168b2fe7ac08ef8c3bbc134cadd3f9d6bd33d20ae476c2a8596c8a", + "0xb19b571ff4ae3e9f5d95acda133c455e72c9ea9973cae360732859836c0341c4c29ab039224dc5bc3deb824e031675d8", + "0x940b5f80478648bac025a30f3efeb47023ce20ee98be833948a248bca6979f206bb28fc0f17b90acf3bb4abd3d14d731", + "0x8f106b40588586ac11629b96d57808ad2808915d89539409c97414aded90b4ff23286a692608230a52bff696055ba5d6", + "0xae6bda03aa10da3d2abbc66d764ca6c8d0993e7304a1bdd413eb9622f3ca1913baa6da1e9f4f9e6cf847f14f44d6924d", + "0xa18e7796054a340ef826c4d6b5a117b80927afaf2ebd547794c400204ae2caf277692e2eabb55bc2f620763c9e9da66d", + "0x8d2d25180dc2c65a4844d3e66819ccfcf48858f0cc89e1c77553b463ec0f7feb9a4002ce26bc618d1142549b9850f232", + "0x863f413a394de42cc8166c1c75d513b91d545fff1de6b359037a742c70b008d34bf8e587afa2d62c844d0c6f0ea753e7", + "0x83cd0cf62d63475e7fcad18a2e74108499cdbf28af2113cfe005e3b5887794422da450b1944d0a986eb7e1f4c3b18f25", + "0xb4f8b350a6d88fea5ab2e44715a292efb12eb52df738c9b2393da3f1ddee68d0a75b476733ccf93642154bceb208f2b8", + "0xb3f52aaa4cd4221cb9fc45936cc67fd3864bf6d26bf3dd86aa85aa55ecfc05f5e392ecce5e7cf9406b4b1c4fce0398c8", + "0xb33137084422fb643123f40a6df2b498065e65230fc65dc31791c330e898c51c3a65ff738930f32c63d78f3c9315f85b", + "0x91452bfa75019363976bb7337fe3a73f1c10f01637428c135536b0cdc7da5ce558dae3dfc792aa55022292600814a8ef", + "0xad6ba94c787cd4361ca642c20793ea44f1f127d4de0bb4a77c7fbfebae0fcadbf28e2cb6f0c12c12a07324ec8c19761d", + "0x890aa6248b17f1501b0f869c556be7bf2b1d31a176f9978bb97ab7a6bd4138eed32467951c5ef1871944b7f620542f43", + "0x82111db2052194ee7dd22ff1eafffac0443cf969d3762cceae046c9a11561c0fdce9c0711f88ac01d1bed165f8a7cee3", + "0xb1527b71df2b42b55832f72e772a466e0fa05743aacc7814f4414e4bcc8d42a4010c9e0fd940e6f254cafedff3cd6543", + "0x922370fa49903679fc565f09c16a5917f8125e72acfeb060fcdbadbd1644eb9f4016229756019c93c6d609cda5d5d174", + "0xaa4c7d98a96cab138d2a53d4aee8ebff6ef903e3b629a92519608d88b3bbd94de5522291a1097e6acf830270e64c8ee1", + "0xb3dc21608a389a72d3a752883a382baaafc61ecc44083b832610a237f6a2363f24195acce529eb4aed4ef0e27a12b66e", + "0x94619f5de05e07b32291e1d7ab1d8b7337a2235e49d4fb5f3055f090a65e932e829efa95db886b32b153bdd05a53ec8c", + "0xade1e92722c2ffa85865d2426fb3d1654a16477d3abf580cfc45ea4b92d5668afc9d09275d3b79283e13e6b39e47424d", + "0xb7201589de7bed094911dd62fcd25c459a8e327ac447b69f541cdba30233063e5ddffad0b67e9c3e34adcffedfd0e13d", + "0x809d325310f862d6549e7cb40f7e5fc9b7544bd751dd28c4f363c724a0378c0e2adcb5e42ec8f912f5f49f18f3365c07", + "0xa79c20aa533de7a5d671c99eb9eb454803ba54dd4f2efa3c8fec1a38f8308e9905c71e9282955225f686146388506ff6", + "0xa85eeacb5e8fc9f3ed06a3fe2dc3108ab9f8c5877b148c73cf26e4e979bf5795edbe2e63a8d452565fd1176ed40402b2", + "0x97ef55662f8a1ec0842b22ee21391227540adf7708f491436044f3a2eb18c471525e78e1e14fa292507c99d74d7437c6", + "0x93110d64ed5886f3d16ce83b11425576a3a7a9bb831cd0de3f9a0b0f2270a730d68136b4ef7ff035ede004358f419b5c", + "0xac9ed0a071517f0ae4f61ce95916a90ba9a77a3f84b0ec50ef7298acdcd44d1b94525d191c39d6bd1bb68f4471428760", + "0x98abd6a02c7690f5a339adf292b8c9368dfc12e0f8069cf26a5e0ce54b4441638f5c66ea735142f3c28e00a0024267e6", + "0xb51efb73ba6d44146f047d69b19c0722227a7748b0e8f644d0fc9551324cf034c041a2378c56ce8b58d06038fb8a78de", + "0x8f115af274ef75c1662b588b0896b97d71f8d67986ae846792702c4742ab855952865ce236b27e2321967ce36ff93357", + "0xb3c4548f14d58b3ab03c222da09e4381a0afe47a72d18d50a94e0008797f78e39e99990e5b4757be62310d400746e35a", + "0xa9b1883bd5f31f909b8b1b6dcb48c1c60ed20aa7374b3ffa7f5b2ed036599b5bef33289d23c80a5e6420d191723b92f7", + "0x85d38dffd99487ae5bb41ab4a44d80a46157bbbe8ef9497e68f061721f74e4da513ccc3422936b059575975f6787c936", + "0xadf870fcb96e972c033ab7a35d28ae79ee795f82bc49c3bd69138f0e338103118d5529c53f2d72a9c0d947bf7d312af2", + "0xab4c7a44e2d9446c6ff303eb49aef0e367a58b22cc3bb27b4e69b55d1d9ee639c9234148d2ee95f9ca8079b1457d5a75", + "0xa386420b738aba2d7145eb4cba6d643d96bda3f2ca55bb11980b318d43b289d55a108f4bc23a9606fb0bccdeb3b3bb30", + "0x847020e0a440d9c4109773ecca5d8268b44d523389993b1f5e60e541187f7c597d79ebd6e318871815e26c96b4a4dbb1", + "0xa530aa7e5ca86fcd1bec4b072b55cc793781f38a666c2033b510a69e110eeabb54c7d8cbcb9c61fee531a6f635ffa972", + "0x87364a5ea1d270632a44269d686b2402da737948dac27f51b7a97af80b66728b0256547a5103d2227005541ca4b7ed04", + "0x8816fc6e16ea277de93a6d793d0eb5c15e9e93eb958c5ef30adaf8241805adeb4da8ce19c3c2167f971f61e0b361077d", + "0x8836a72d301c42510367181bb091e4be377777aed57b73c29ef2ce1d475feedd7e0f31676284d9a94f6db01cc4de81a2", + "0xb0d9d8b7116156d9dde138d28aa05a33e61f8a85839c1e9071ccd517b46a5b4b53acb32c2edd7150c15bc1b4bd8db9e3", + "0xae931b6eaeda790ba7f1cd674e53dc87f6306ff44951fa0df88d506316a5da240df9794ccbd7215a6470e6b31c5ea193", + "0x8c6d5bdf87bd7f645419d7c6444e244fe054d437ed1ba0c122fde7800603a5fadc061e5b836cb22a6cfb2b466f20f013", + "0x90d530c6d0cb654999fa771b8d11d723f54b8a8233d1052dc1e839ea6e314fbed3697084601f3e9bbb71d2b4eaa596df", + "0xb0d341a1422588c983f767b1ed36c18b141774f67ef6a43cff8e18b73a009da10fc12120938b8bba27f225bdfd3138f9", + "0xa131b56f9537f460d304e9a1dd75702ace8abd68cb45419695cb8dee76998139058336c87b7afd6239dc20d7f8f940cc", + "0xaa6c51fa28975f709329adee1bbd35d49c6b878041841a94465e8218338e4371f5cb6c17f44a63ac93644bf28f15d20f", + "0x88440fb584a99ebd7f9ea04aaf622f6e44e2b43bbb49fb5de548d24a238dc8f26c8da2ccf03dd43102bda9f16623f609", + "0x9777b8695b790e702159a4a750d5e7ff865425b95fa0a3c15495af385b91c90c00a6bd01d1b77bffe8c47d01baae846f", + "0x8b9d764ece7799079e63c7f01690c8eff00896a26a0d095773dea7a35967a8c40db7a6a74692f0118bf0460c26739af4", + "0x85808c65c485520609c9e61fa1bb67b28f4611d3608a9f7a5030ee61c3aa3c7e7dc17fff48af76b4aecee2cb0dbd22ac", + "0xad2783a76f5b3db008ef5f7e67391fda4e7e36abde6b3b089fc4835b5c339370287935af6bd53998bed4e399eda1136d", + "0x96f18ec03ae47c205cc4242ca58e2eff185c9dca86d5158817e2e5dc2207ab84aadda78725f8dc080a231efdc093b940", + "0x97de1ab6c6cc646ae60cf7b86df73b9cf56cc0cd1f31b966951ebf79fc153531af55ca643b20b773daa7cab784b832f7", + "0x870ba266a9bfa86ef644b1ef025a0f1b7609a60de170fe9508de8fd53170c0b48adb37f19397ee8019b041ce29a16576", + "0xad990e888d279ac4e8db90619d663d5ae027f994a3992c2fbc7d262b5990ae8a243e19157f3565671d1cb0de17fe6e55", + "0x8d9d5adcdd94c5ba3be4d9a7428133b42e485f040a28d16ee2384758e87d35528f7f9868de9bd23d1a42a594ce50a567", + "0x85a33ed75d514ece6ad78440e42f7fcdb59b6f4cff821188236d20edae9050b3a042ce9bc7d2054296e133d033e45022", + "0x92afd2f49a124aaba90de59be85ff269457f982b54c91b06650c1b8055f9b4b0640fd378df02a00e4fc91f7d226ab980", + "0x8c0ee09ec64bd831e544785e3d65418fe83ed9c920d9bb4d0bf6dd162c1264eb9d6652d2def0722e223915615931581c", + "0x8369bedfa17b24e9ad48ebd9c5afea4b66b3296d5770e09b00446c5b0a8a373d39d300780c01dcc1c6752792bccf5fd0", + "0x8b9e960782576a59b2eb2250d346030daa50bbbec114e95cdb9e4b1ba18c3d34525ae388f859708131984976ca439d94", + "0xb682bface862008fea2b5a07812ca6a28a58fd151a1d54c708fc2f8572916e0d678a9cb8dc1c10c0470025c8a605249e", + "0xa38d5e189bea540a824b36815fc41e3750760a52be0862c4cac68214febdc1a754fb194a7415a8fb7f96f6836196d82a", + "0xb9e7fbda650f18c7eb8b40e42cc42273a7298e65e8be524292369581861075c55299ce69309710e5b843cb884de171bd", + "0xb6657e5e31b3193874a1bace08f42faccbd3c502fb73ad87d15d18a1b6c2a146f1baa929e6f517db390a5a47b66c0acf", + "0xae15487312f84ed6265e4c28327d24a8a0f4d2d17d4a5b7c29b974139cf93223435aaebe3af918f5b4bb20911799715f", + "0x8bb4608beb06bc394e1a70739b872ce5a2a3ffc98c7547bf2698c893ca399d6c13686f6663f483894bccaabc3b9c56ad", + "0xb58ac36bc6847077584308d952c5f3663e3001af5ecf2e19cb162e1c58bd6c49510205d453cffc876ca1dc6b8e04a578", + "0x924f65ced61266a79a671ffb49b300f0ea44c50a0b4e3b02064faa99fcc3e4f6061ea8f38168ab118c5d47bd7804590e", + "0x8d67d43b8a06b0ff4fafd7f0483fa9ed1a9e3e658a03fb49d9d9b74e2e24858dc1bed065c12392037b467f255d4e5643", + "0xb4d4f87813125a6b355e4519a81657fa97c43a6115817b819a6caf4823f1d6a1169683fd68f8d025cdfa40ebf3069acb", + "0xa7fd4d2c8e7b59b8eed3d4332ae94b77a89a2616347402f880bc81bde072220131e6dbec8a605be3a1c760b775375879", + "0x8d4a7d8fa6f55a30df37bcf74952e2fa4fd6676a2e4606185cf154bdd84643fd01619f8fb8813a564f72e3f574f8ce30", + "0x8086fb88e6260e9a9c42e9560fde76315ff5e5680ec7140f2a18438f15bc2cc7d7d43bfb5880b180b738c20a834e6134", + "0x916c4c54721de03934fee6f43de50bb04c81f6f8dd4f6781e159e71c40c60408aa54251d457369d133d4ba3ed7c12cb4", + "0x902e5bf468f11ed9954e2a4a595c27e34abe512f1d6dc08bbca1c2441063f9af3dc5a8075ab910a10ff6c05c1c644a35", + "0xa1302953015e164bf4c15f7d4d35e3633425a78294406b861675667eec77765ff88472306531e5d3a4ec0a2ff0dd6a9e", + "0x87874461df3c9aa6c0fa91325576c0590f367075f2f0ecfeb34afe162c04c14f8ce9d608c37ac1adc8b9985bc036e366", + "0x84b50a8a61d3cc609bfb0417348133e698fe09a6d37357ce3358de189efcf35773d78c57635c2d26c3542b13cc371752", + "0xacaed2cff8633d12c1d12bb7270c54d65b0b0733ab084fd47f81d0a6e1e9b6f300e615e79538239e6160c566d8bb8d29", + "0x889e6a0e136372ca4bac90d1ab220d4e1cad425a710e8cdd48b400b73bb8137291ceb36a39440fa84305783b1d42c72f", + "0x90952e5becec45b2b73719c228429a2c364991cf1d5a9d6845ae5b38018c2626f4308daa322cab1c72e0f6c621bb2b35", + "0x8f5a97a801b6e9dcd66ccb80d337562c96f7914e7169e8ff0fda71534054c64bf2a9493bb830623d612cfe998789be65", + "0x84f3df8b9847dcf1d63ca470dc623154898f83c25a6983e9b78c6d2d90a97bf5e622445be835f32c1e55e6a0a562ea78", + "0x91d12095cd7a88e7f57f254f02fdb1a1ab18984871dead2f107404bcf8069fe68258c4e6f6ebd2477bddf738135400bb", + "0xb771a28bc04baef68604d4723791d3712f82b5e4fe316d7adc2fc01b935d8e644c06d59b83bcb542afc40ebafbee0683", + "0x872f6341476e387604a7e93ae6d6117e72d164e38ebc2b825bc6df4fcce815004d7516423c190c1575946b5de438c08d", + "0x90d6b4aa7d40a020cdcd04e8b016d041795961a8e532a0e1f4041252131089114a251791bf57794cadb7d636342f5d1c", + "0x899023ba6096a181448d927fed7a0fe858be4eac4082a42e30b3050ee065278d72fa9b9d5ce3bc1372d4cbd30a2f2976", + "0xa28f176571e1a9124f95973f414d5bdbf5794d41c3839d8b917100902ac4e2171eb940431236cec93928a60a77ede793", + "0x838dbe5bcd29c4e465d02350270fa0036cd46f8730b13d91e77afb7f5ed16525d0021d3b2ae173a76c378516a903e0cb", + "0x8e105d012dd3f5d20f0f1c4a7e7f09f0fdd74ce554c3032e48da8cce0a77260d7d47a454851387770f5c256fa29bcb88", + "0x8f4df0f9feeb7a487e1d138d13ea961459a6402fd8f8cabb226a92249a0d04ded5971f3242b9f90d08da5ff66da28af6", + "0xad1cfda4f2122a20935aa32fb17c536a3653a18617a65c6836700b5537122af5a8206befe9eaea781c1244c43778e7f1", + "0x832c6f01d6571964ea383292efc8c8fa11e61c0634a25fa180737cc7ab57bc77f25e614aac9a2a03d98f27b3c1c29de2", + "0x903f89cc13ec6685ac7728521898781fecb300e9094ef913d530bf875c18bcc3ceed7ed51e7b482d45619ab4b025c2e9", + "0xa03c474bb915aad94f171e8d96f46abb2a19c9470601f4c915512ec8b9e743c3938450a2a5b077b4618b9df8809e1dc1", + "0x83536c8456f306045a5f38ae4be2e350878fa7e164ea408d467f8c3bc4c2ee396bd5868008c089183868e4dfad7aa50b", + "0x88f26b4ea1b236cb326cd7ad7e2517ec8c4919598691474fe15d09cabcfc37a8d8b1b818f4d112432ee3a716b0f37871", + "0xa44324e3fe96e9c12b40ded4f0f3397c8c7ee8ff5e96441118d8a6bfad712d3ac990b2a6a23231a8f691491ac1fd480f", + "0xb0de4693b4b9f932191a21ee88629964878680152a82996c0019ffc39f8d9369bbe2fe5844b68d6d9589ace54af947e4", + "0x8e5d8ba948aea5fd26035351a960e87f0d23efddd8e13236cc8e4545a3dda2e9a85e6521efb8577e03772d3637d213d9", + "0x93efc82d2017e9c57834a1246463e64774e56183bb247c8fc9dd98c56817e878d97b05f5c8d900acf1fbbbca6f146556", + "0x8731176363ad7658a2862426ee47a5dce9434216cef60e6045fa57c40bb3ce1e78dac4510ae40f1f31db5967022ced32", + "0xb10c9a96745722c85bdb1a693100104d560433d45b9ac4add54c7646a7310d8e9b3ca9abd1039d473ae768a18e489845", + "0xa2ac374dfbb464bf850b4a2caf15b112634a6428e8395f9c9243baefd2452b4b4c61b0cb2836d8eae2d57d4900bf407e", + "0xb69fe3ded0c4f5d44a09a0e0f398221b6d1bf5dbb8bc4e338b93c64f1a3cac1e4b5f73c2b8117158030ec03787f4b452", + "0x8852cdbaf7d0447a8c6f211b4830711b3b5c105c0f316e3a6a18dcfbb9be08bd6f4e5c8ae0c3692da08a2dfa532f9d5c", + "0x93bbf6d7432a7d98ade3f94b57bf9f4da9bc221a180a370b113066dd42601bb9e09edd79e2e6e04e00423399339eebda", + "0xa80941c391f1eeafc1451c59e4775d6a383946ff22997aeaadf806542ba451d3b0f0c6864eeba954174a296efe2c1550", + "0xa045fe2bb011c2a2f71a0181a8f457a3078470fb74c628eab8b59aef69ffd0d649723bf74d6885af3f028bc5a104fb39", + "0xb9d8c35911009c4c8cad64692139bf3fc16b78f5a19980790cb6a7aea650a25df4231a4437ae0c351676a7e42c16134f", + "0x94c79501ded0cfcbab99e1841abe4a00a0252b3870e20774c3da16c982d74c501916ec28304e71194845be6e3113c7ab", + "0x900a66418b082a24c6348d8644ddb1817df5b25cb33044a519ef47cc8e1f7f1e38d2465b7b96d32ed472d2d17f8414c6", + "0xb26f45d393b8b2fcb29bdbb16323dc7f4b81c09618519ab3a39f8ee5bd148d0d9f3c0b5dfab55b5ce14a1cb9206d777b", + "0xaa1a87735fc493a80a96a9a57ca40a6d9c32702bfcaa9869ce1a116ae65d69cefe2f3e79a12454b4590353e96f8912b4", + "0xa922b188d3d0b69b4e4ea2a2aa076566962844637da12c0832105d7b31dea4a309eee15d12b7a336be3ea36fcbd3e3b7", + "0x8f3841fcf4105131d8c4d9885e6e11a46c448226401cf99356c291fadb864da9fa9d30f3a73c327f23f9fd99a11d633e", + "0x9791d1183fae270e226379af6c497e7da803ea854bb20afa74b253239b744c15f670ee808f708ede873e78d79a626c9a", + "0xa4cad52e3369491ada61bf28ada9e85de4516d21c882e5f1cd845bea9c06e0b2887b0c5527fcff6fc28acd3c04f0a796", + "0xb9ac86a900899603452bd11a7892a9bfed8054970bfcbeaa8c9d1930db891169e38d6977f5258c25734f96c8462eee3b", + "0xa3a154c28e5580656a859f4efc2f5ebfa7eaa84ca40e3f134fa7865e8581586db74992dbfa4036aa252fba103773ddde", + "0x95cc2a0c1885a029e094f5d737e3ecf4d26b99036453a8773c77e360101f9f98676ee246f6f732a377a996702d55691f", + "0x842651bbe99720438d8d4b0218feb60481280c05beb17750e9ca0d8c0599a60f873b7fbdcc7d8835ba9a6d57b16eec03", + "0x81ee54699da98f5620307893dcea8f64670609fa20e5622265d66283adeac122d458b3308c5898e6c57c298db2c8b24f", + "0xb97868b0b2bc98032d68352a535a1b341b9ff3c7af4e3a7f3ebc82d3419daa1b5859d6aedc39994939623c7cd878bd9b", + "0xb60325cd5d36461d07ef253d826f37f9ee6474a760f2fff80f9873d01fd2b57711543cdc8d7afa1c350aa753c2e33dea", + "0x8c205326c11d25a46717b780c639d89714c7736c974ae71287e3f4b02e6605ac2d9b4928967b1684f12be040b7bf2dd3", + "0x95a392d82db51e26ade6c2ccd3396d7e40aff68fa570b5951466580d6e56dda51775dce5cf3a74a7f28c3cb2eb551c4d", + "0x8f2cc8071eb56dffb70bda6dd433b556221dc8bba21c53353c865f00e7d4d86c9e39f119ea9a8a12ef583e9a55d9a6b6", + "0x9449a71af9672aaf8856896d7e3d788b22991a7103f75b08c0abbcc2bfe60fda4ed8ce502cea4511ff0ea52a93e81222", + "0x857090ab9fdb7d59632d068f3cc8cf27e61f0d8322d30e6b38e780a1f05227199b4cd746aac1311c36c659ef20931f28", + "0x98a891f4973e7d9aaf9ac70854608d4f7493dffc7e0987d7be9dd6029f6ea5636d24ef3a83205615ca1ff403750058e1", + "0xa486e1365bbc278dd66a2a25d258dc82f46b911103cb16aab3945b9c95ae87b386313a12b566df5b22322ede0afe25ad", + "0xa9a1eb399ed95d396dccd8d1ac718043446f8b979ec62bdce51c617c97a312f01376ab7fb87d27034e5f5570797b3c33", + "0xb7abc3858d7a74bb446218d2f5a037e0fae11871ed9caf44b29b69c500c1fa1dcfad64c9cdccc9d80d5e584f06213deb", + "0x8cfb09fe2e202faa4cebad932b1d35f5ca204e1c2a0c740a57812ac9a6792130d1312aabd9e9d4c58ca168bfebd4c177", + "0xa90a305c2cd0f184787c6be596fa67f436afd1f9b93f30e875f817ac2aae8bdd2e6e656f6be809467e6b3ad84adb86b1", + "0x80a9ef993c2b009ae172cc8f7ec036f5734cf4f4dfa06a7db4d54725e7fbfae5e3bc6f22687bdbb6961939d6f0c87537", + "0x848ade1901931e72b955d7db1893f07003e1708ff5d93174bac5930b9a732640f0578839203e9b77eb27965c700032d3", + "0x93fdf4697609c5ae9c33b9ca2f5f1af44abeb2b98dc4fdf732cf7388de086f410730dc384d9b7a7f447bb009653c8381", + "0x89ce3fb805aea618b5715c0d22a9f46da696b6fa86794f56fdf1d44155a33d42daf1920bcbe36cbacf3cf4c92df9cbc7", + "0x829ce2c342cf82aa469c65f724f308f7a750bd1494adc264609cd790c8718b8b25b5cab5858cf4ee2f8f651d569eea67", + "0xaf2f0cee7bf413204be8b9df59b9e4991bc9009e0d6dbe6815181df0ec2ca93ab8f4f3135b1c14d8f53d74bff0bd6f27", + "0xb87998cecf7b88cde93d1779f10a521edd5574a2fbd240102978639ec57433ba08cdb53849038a329cebbe74657268d2", + "0xa64542a1261a6ed3d720c2c3a802303aad8c4c110c95d0f12e05c1065e66f42da494792b6bfc5b9272363f3b1d457f58", + "0x86a6fd042e4f282fadf07a4bfee03fc96a3aea49f7a00f52bf249a20f1ec892326855410e61f37fbb27d9305eb2fc713", + "0x967ea5bc403b6db269682f7fd0df90659350d7e1aa66bc4fab4c9dfcd75ed0bba4b52f1cebc5f34dc8ba810793727629", + "0xa52990f9f3b8616ce3cdc2c74cd195029e6a969753dcf2d1630438700e7d6ebde36538532b3525ac516f5f2ce9dd27a3", + "0xa64f7ff870bab4a8bf0d4ef6f5c744e9bf1021ed08b4c80903c7ad318e80ba1817c3180cc45cb5a1cae1170f0241655f", + "0xb00f706fa4de1f663f021e8ad3d155e84ce6084a409374b6e6cd0f924a0a0b51bebaaaf1d228c77233a73b0a5a0df0e9", + "0x8b882cc3bff3e42babdb96df95fb780faded84887a0a9bab896bef371cdcf169d909f5658649e93006aa3c6e1146d62e", + "0x9332663ef1d1dcf805c3d0e4ce7a07d9863fb1731172e766b3cde030bf81682cc011e26b773fb9c68e0477b4ae2cfb79", + "0xa8aa8151348dbd4ef40aaeb699b71b4c4bfd3218560c120d85036d14f678f6736f0ec68e80ce1459d3d35feccc575164", + "0xa16cd8b729768f51881c213434aa28301fa78fcb554ddd5f9012ee1e4eae7b5cb3dd88d269d53146dea92d10790faf0b", + "0x86844f0ef9d37142faf3b1e196e44fbe280a3ba4189aa05c356778cb9e3b388a2bff95eed305ada8769935c9974e4c57", + "0xae2eec6b328fccf3b47bcdac32901ac2744a51beb410b04c81dea34dee4912b619466a4f5e2780d87ecefaebbe77b46d", + "0x915df4c38d301c8a4eb2dc5b1ba0ffaad67cbb177e0a80095614e9c711f4ef24a4cef133f9d982a63d2a943ba6c8669d", + "0xae6a2a4dedfc2d1811711a8946991fede972fdf2a389b282471280737536ffc0ac3a6d885b1f8bda0366eb0b229b9979", + "0xa9b628c63d08b8aba6b1317f6e91c34b2382a6c85376e8ef2410a463c6796740ae936fc4e9e0737cb9455d1daa287bd8", + "0x848e30bf7edf2546670b390d5cf9ab71f98fcb6add3c0b582cb34996c26a446dee5d1bde4fdcde4fc80c10936e117b29", + "0x907d6096c7c8c087d1808dd995d5d2b9169b3768c3f433475b50c2e2bd4b082f4d543afd8b0b0ddffa9c66222a72d51d", + "0xa59970a2493b07339124d763ac9d793c60a03354539ecbcf6035bc43d1ea6e35718202ae6d7060b7d388f483d971573c", + "0xb9cfef2af9681b2318f119d8611ff6d9485a68d8044581b1959ab1840cbca576dbb53eec17863d2149966e9feb21122f", + "0xad47271806161f61d3afa45cdfe2babceef5e90031a21779f83dc8562e6076680525b4970b2f11fe9b2b23c382768323", + "0x8e425a99b71677b04fe044625d338811fbb8ee32368a424f6ab2381c52e86ee7a6cecedf777dc97181519d41c351bc22", + "0x86b55b54d7adefc12954a9252ee23ae83efe8b5b4b9a7dc307904413e5d69868c7087a818b2833f9b004213d629be8ad", + "0xa14fda6b93923dd11e564ae4457a66f397741527166e0b16a8eb91c6701c244fd1c4b63f9dd3515193ec88fa6c266b35", + "0xa9b17c36ae6cd85a0ed7f6cabc5b47dc8f80ced605db327c47826476dc1fb8f8669aa7a7dc679fbd4ee3d8e8b4bd6a6f", + "0x82a0829469c1458d959c821148f15dacae9ea94bf56c59a6ab2d4dd8b3d16d73e313b5a3912a6c1f131d73a8f06730c4", + "0xb22d56d549a53eaef549595924bdb621ff807aa4513feedf3fdcbf7ba8b6b9cfa4481c2f67fc642db397a6b794a8b63a", + "0x974c59c24392e2cb9294006cbe3c52163e255f3bd0c2b457bdc68a6338e6d5b6f87f716854492f8d880a6b896ccf757c", + "0xb70d247ba7cad97c50b57f526c2ba915786e926a94e8f8c3eebc2e1be6f4255411b9670e382060049c8f4184302c40b2", + "0xad80201fe75ef21c3ddbd98cf23591e0d7a3ba1036dfe77785c32f44755a212c31f0ceb0a0b6f5ee9b6dc81f358d30c3", + "0x8c656e841f9bb90b9a42d425251f3fdbc022a604d75f5845f479ed4be23e02aaf9e6e56cde351dd7449c50574818a199", + "0x8b88dd3fa209d3063b7c5b058f7249ee9900fbc2287d16da61a0704a0a1d71e45d9c96e1cda7fdf9654534ec44558b22", + "0x961da00cc8750bd84d253c08f011970ae1b1158ad6778e8ed943d547bceaf52d6d5a212a7de3bf2706688c4389b827d2", + "0xa5dd379922549a956033e3d51a986a4b1508e575042b8eaa1df007aa77cf0b8c2ab23212f9c075702788fa9c53696133", + "0xac8fcfde3a349d1e93fc8cf450814e842005c545c4844c0401bc80e6b96cdb77f29285a14455e167c191d4f312e866cd", + "0xac63d79c799783a8466617030c59dd5a8f92ee6c5204676fd8d881ce5f7f8663bdbeb0379e480ea9b6340ab0dc88e574", + "0x805874fde19ce359041ae2bd52a39e2841acabfd31f965792f2737d7137f36d4e4722ede8340d8c95afa6af278af8acb", + "0x8d2f323a228aa8ba7b7dc1399138f9e6b41df1a16a7069003ab8104b8b68506a45141bc5fe66acf430e23e13a545190b", + "0xa1610c721a2d9af882bb6b39bea97cff1527a3aea041d25934de080214ae77c959e79957164440686d15ab301e897d4d", + "0xaba16d29a47fc36f12b654fde513896723e2c700c4190f11b26aa4011da57737ad717daa02794aa3246e4ae5f0b0cc3a", + "0xa406db2f15fdd135f346cc4846623c47edd195e80ba8c7cb447332095314d565e4040694ca924696bb5ee7f8996ea0ba", + "0x8b30e2cd9b47d75ba57b83630e40f832249af6c058d4f490416562af451993eec46f3e1f90bc4d389e4c06abd1b32a46", + "0xaacf9eb7036e248e209adbfc3dd7ce386569ea9b312caa4b240726549db3c68c4f1c8cbf8ed5ea9ea60c7e57c9df3b8e", + "0xb20fcac63bf6f5ee638a42d7f89be847f348c085ddcbec3fa318f4323592d136c230495f188ef2022aa355cc2b0da6f9", + "0x811eff750456a79ec1b1249d76d7c1547065b839d8d4aaad860f6d4528eb5b669473dcceeeea676cddbc3980b68461b7", + "0xb52d14ae33f4ab422f953392ae76a19c618cc31afc96290bd3fe2fb44c954b5c92c4789f3f16e8793f2c0c1691ade444", + "0xa7826dafeeba0db5b66c4dfcf2b17fd7b40507a5a53ac2e42942633a2cb30b95ba1739a6e9f3b7a0e0f1ec729bf274e2", + "0x8acfd83ddf7c60dd7c8b20c706a3b972c65d336b8f9b3d907bdd8926ced271430479448100050b1ef17578a49c8fa616", + "0xaf0c69f65184bb06868029ad46f8465d75c36814c621ac20a5c0b06a900d59305584f5a6709683d9c0e4b6cd08d650a6", + "0xb6cc8588191e00680ee6c3339bd0f0a17ad8fd7f4be57d5d7075bede0ea593a19e67f3d7c1a20114894ee5bfcab71063", + "0xa82fd4f58635129dbb6cc3eb9391cf2d28400018b105fc41500fbbd12bd890b918f97d3d359c29dd3b4c4e34391dfab0", + "0x92fc544ed65b4a3625cf03c41ddff7c039bc22d22c0d59dcc00efd5438401f2606adb125a1d5de294cca216ec8ac35a3", + "0x906f67e4a32582b71f15940523c0c7ce370336935e2646bdaea16a06995256d25e99df57297e39d6c39535e180456407", + "0x97510337ea5bbd5977287339197db55c60533b2ec35c94d0a460a416ae9f60e85cee39be82abeeacd5813cf54df05862", + "0x87e6894643815c0ea48cb96c607266c5ee4f1f82ba5fe352fb77f9b6ed14bfc2b8e09e80a99ac9047dfcf62b2ae26795", + "0xb6fd55dd156622ad7d5d51b7dde75e47bd052d4e542dd6449e72411f68275775c846dde301e84613312be8c7bce58b07", + "0xb98461ac71f554b2f03a94e429b255af89eec917e208a8e60edf5fc43b65f1d17a20de3f31d2ce9f0cb573c25f2f4d98", + "0x96f0dea40ca61cefbee41c4e1fe9a7d81fbe1f49bb153d083ab70f5d0488a1f717fd28cedcf6aa18d07cce2c62801898", + "0x8d7c3ab310184f7dc34b6ce4684e4d29a31e77b09940448ea4daac730b7eb308063125d4dd229046cf11bfd521b771e0", + "0x96f0564898fe96687918bbf0a6adead99cf72e3a35ea3347e124af9d006221f8e82e5a9d2fe80094d5e8d48e610f415e", + "0xad50fcb92c2675a398cf07d4c40a579e44bf8d35f27cc330b57e54d5ea59f7d898af0f75dccfe3726e5471133d70f92b", + "0x828beed62020361689ae7481dd8f116902b522fb0c6c122678e7f949fdef70ead011e0e6bffd25678e388744e17cdb69", + "0x8349decac1ca16599eee2efc95bcaabf67631107da1d34a2f917884bd70dfec9b4b08ab7bc4379d6c73b19c0b6e54fb8", + "0xb2a6a2e50230c05613ace9e58bb2e98d94127f196f02d9dddc53c43fc68c184549ca12d713cb1b025d8260a41e947155", + "0x94ff52181aadae832aed52fc3b7794536e2a31a21fc8be3ea312ca5c695750d37f08002f286b33f4023dba1e3253ecfa", + "0xa21d56153c7e5972ee9a319501be4faff199fdf09bb821ea9ce64aa815289676c00f105e6f00311b3a5b627091b0d0fc", + "0xa27a60d219f1f0c971db73a7f563b371b5c9fc3ed1f72883b2eac8a0df6698400c9954f4ca17d7e94e44bd4f95532afb", + "0xa2fc56fae99b1f18ba5e4fe838402164ce82f8a7f3193d0bbd360c2bac07c46f9330c4c7681ffb47074c6f81ee6e7ac6", + "0xb748e530cd3afb96d879b83e89c9f1a444f54e55372ab1dcd46a0872f95ce8f49cf2363fc61be82259e04f555937ed16", + "0x8bf8993e81080c7cbba1e14a798504af1e4950b2f186ab3335b771d6acaee4ffe92131ae9c53d74379d957cb6344d9cd", + "0x96774d0ef730d22d7ab6d9fb7f90b9ead44285219d076584a901960542756700a2a1603cdf72be4708b267200f6c36a9", + "0xb47703c2ab17be1e823cc7bf3460db1d6760c0e33862c90ca058845b2ff234b0f9834ddba2efb2ee1770eb261e7d8ffd", + "0x84319e67c37a9581f8b09b5e4d4ae88d0a7fb4cbb6908971ab5be28070c3830f040b1de83ee663c573e0f2f6198640e4", + "0x96811875fa83133e0b3c0e0290f9e0e28bca6178b77fdf5350eb19344d453dbd0d71e55a0ef749025a5a2ca0ad251e81", + "0x81a423423e9438343879f2bfd7ee9f1c74ebebe7ce3cfffc8a11da6f040cc4145c3b527bd3cf63f9137e714dbcb474ef", + "0xb8c3535701ddbeec2db08e17a4fa99ba6752d32ece5331a0b8743676f421fcb14798afc7c783815484f14693d2f70db8", + "0x81aee980c876949bf40782835eec8817d535f6f3f7e00bf402ddd61101fdcd60173961ae90a1cf7c5d060339a18c959d", + "0x87e67b928d97b62c49dac321ce6cb680233f3a394d4c9a899ac2e8db8ccd8e00418e66cdfd68691aa3cb8559723b580c", + "0x8eac204208d99a2b738648df96353bbb1b1065e33ee4f6bba174b540bbbd37d205855e1f1e69a6b7ff043ca377651126", + "0x848e6e7a54ad64d18009300b93ea6f459ce855971dddb419b101f5ac4c159215626fadc20cc3b9ab1701d8f6dfaddd8b", + "0x88aa123d9e0cf309d46dddb6acf634b1ade3b090a2826d6e5e78669fa1220d6df9a6697d7778cd9b627db17eea846126", + "0x9200c2a629b9144d88a61151b661b6c4256cc5dadfd1e59a8ce17a013c2d8f7e754aabe61663c3b30f1bc47784c1f8cf", + "0xb6e1a2827c3bdda91715b0e1b1f10dd363cef337e7c80cac1f34165fc0dea7c8b69747e310563db5818390146ce3e231", + "0x92c333e694f89f0d306d54105b2a5dcc912dbe7654d9e733edab12e8537350815be472b063e56cfde5286df8922fdecb", + "0xa6fac04b6d86091158ebb286586ccfec2a95c9786e14d91a9c743f5f05546073e5e3cc717635a0c602cad8334e922346", + "0xa581b4af77feebc1fb897d49b5b507c6ad513d8f09b273328efbb24ef0d91eb740d01b4d398f2738125dacfe550330cd", + "0x81c4860cccf76a34f8a2bc3f464b7bfd3e909e975cce0d28979f457738a56e60a4af8e68a3992cf273b5946e8d7f76e2", + "0x8d1eaa09a3180d8af1cbaee673db5223363cc7229a69565f592fa38ba0f9d582cedf91e15dabd06ebbf2862fc0feba54", + "0x9832f49b0147f4552402e54593cfa51f99540bffada12759b71fcb86734be8e500eea2d8b3d036710bdf04c901432de9", + "0x8bdb0e8ec93b11e5718e8c13cb4f5de545d24829fd76161216340108098dfe5148ed25e3b57a89a516f09fa79043734d", + "0xab96f06c4b9b0b2c0571740b24fca758e6976315053a7ecb20119150a9fa416db2d3a2e0f8168b390bb063f0c1caf785", + "0xab777f5c52acd62ecf4d1f168b9cc8e1a9b45d4ec6a8ff52c583e867c2239aba98d7d3af977289b367edce03d9c2dfb1", + "0xa09d3ce5e748da84802436951acc3d3ea5d8ec1d6933505ed724d6b4b0d69973ab0930daec9c6606960f6e541e4a3ce2", + "0x8ef94f7be4d85d5ad3d779a5cf4d7b2fc3e65c52fb8e1c3c112509a4af77a0b5be994f251e5e40fabeeb1f7d5615c22b", + "0xa7406a5bf5708d9e10922d3c5c45c03ef891b8d0d74ec9f28328a72be4cdc05b4f2703fa99366426659dfca25d007535", + "0xb7f52709669bf92a2e070bfe740f422f0b7127392c5589c7f0af71bb5a8428697c762d3c0d74532899da24ea7d8695c2", + "0xb9dfb0c8df84104dbf9239ccefa4672ef95ddabb8801b74997935d1b81a78a6a5669a3c553767ec19a1281f6e570f4ff", + "0xae4d5c872156061ce9195ac640190d8d71dd406055ee43ffa6f9893eb24b870075b74c94d65bc1d5a07a6573282b5520", + "0xafe6bd3eb72266d333f1807164900dcfa02a7eb5b1744bb3c86b34b3ee91e3f05e38fa52a50dc64eeb4bdb1dd62874b8", + "0x948043cf1bc2ef3c01105f6a78dc06487f57548a3e6ef30e6ebc51c94b71e4bf3ff6d0058c72b6f3ecc37efd7c7fa8c0", + "0xa22fd17c2f7ffe552bb0f23fa135584e8d2d8d75e3f742d94d04aded2a79e22a00dfe7acbb57d44e1cdb962fb22ae170", + "0x8cd0f4e9e4fb4a37c02c1bde0f69359c43ab012eb662d346487be0c3758293f1ca560122b059b091fddce626383c3a8f", + "0x90499e45f5b9c81426f3d735a52a564cafbed72711d9279fdd88de8038e953bc48c57b58cba85c3b2e4ce56f1ddb0e11", + "0x8c30e4c034c02958384564cac4f85022ef36ab5697a3d2feaf6bf105049675bbf23d01b4b6814711d3d9271abff04cac", + "0x81f7999e7eeea30f3e1075e6780bbf054f2fb6f27628a2afa4d41872a385b4216dd5f549da7ce6cf39049b2251f27fb7", + "0xb36a7191f82fc39c283ffe53fc1f5a9a00b4c64eee7792a8443475da9a4d226cf257f226ea9d66e329af15d8f04984ec", + "0xaad4da528fdbb4db504f3041c747455baff5fcd459a2efd78f15bdf3aea0bdb808343e49df88fe7a7c8620009b7964a3", + "0x99ebd8c6dd5dd299517fb6381cfc2a7f443e6e04a351440260dd7c2aee3f1d8ef06eb6c18820b394366ecdfd2a3ce264", + "0x8873725b81871db72e4ec3643084b1cdce3cbf80b40b834b092767728605825c19b6847ad3dcf328438607e8f88b4410", + "0xb008ee2f895daa6abd35bd39b6f7901ae4611a11a3271194e19da1cdcc7f1e1ea008fe5c5440e50d2c273784541ad9c5", + "0x9036feafb4218d1f576ef89d0e99124e45dacaa6d816988e34d80f454d10e96809791d5b78f7fd65f569e90d4d7238c5", + "0x92073c1d11b168e4fa50988b0288638b4868e48bbc668c5a6dddf5499875d53be23a285acb5e4bad60114f6cf6c556e9", + "0x88c87dfcb8ba6cbfe7e1be081ccfadbd589301db2cb7c99f9ee5d7db90aa297ed1538d5a867678a763f2deede5fd219a", + "0xb42a562805c661a50f5dea63108002c0f27c0da113da6a9864c9feb5552225417c0356c4209e8e012d9bcc9d182c7611", + "0x8e6317d00a504e3b79cd47feb4c60f9df186467fe9ca0f35b55c0364db30528f5ff071109dabb2fc80bb9cd4949f0c24", + "0xb7b1ea6a88694f8d2f539e52a47466695e39e43a5eb9c6f23bca15305fe52939d8755cc3ac9d6725e60f82f994a3772f", + "0xa3cd55161befe795af93a38d33290fb642b8d80da8b786c6e6fb02d393ea308fbe87f486994039cbd7c7b390414594b6", + "0xb416d2d45b44ead3b1424e92c73c2cf510801897b05d1724ff31cbd741920cd858282fb5d6040fe1f0aa97a65bc49424", + "0x950ee01291754feace97c2e933e4681e7ddfbc4fcd079eb6ff830b0e481d929c93d0c7fb479c9939c28ca1945c40da09", + "0x869bd916aee8d86efe362a49010382674825d49195b413b4b4018e88ce43fe091b475d0b863ff0ba2259400f280c2b23", + "0x9782f38cd9c9d3385ec286ebbc7cba5b718d2e65a5890b0a5906b10a89dc8ed80d417d71d7c213bf52f2af1a1f513ea7", + "0x91cd33bc2628d096269b23faf47ee15e14cb7fdc6a8e3a98b55e1031ea0b68d10ba30d97e660f7e967d24436d40fad73", + "0x8becc978129cc96737034c577ae7225372dd855da8811ae4e46328e020c803833b5bdbc4a20a93270e2b8bd1a2feae52", + "0xa36b1d8076783a9522476ce17f799d78008967728ce920531fdaf88303321bcaf97ecaa08e0c01f77bc32e53c5f09525", + "0xb4720e744943f70467983aa34499e76de6d59aa6fadf86f6b787fdce32a2f5b535b55db38fe2da95825c51002cfe142d", + "0x91ad21fc502eda3945f6de874d1b6bf9a9a7711f4d61354f9e5634fc73f9c06ada848de15ab0a75811d3250be862827d", + "0x84f78e2ebf5fc077d78635f981712daf17e2475e14c2a96d187913006ad69e234746184a51a06ef510c9455b38acb0d7", + "0x960aa7906e9a2f11db64a26b5892ac45f20d2ccb5480f4888d89973beb6fa0dfdc06d68d241ff5ffc7f1b82b1aac242d", + "0xa99365dcd1a00c66c9db6924b97c920f5c723380e823b250db85c07631b320ec4e92e586f7319e67a522a0578f7b6d6c", + "0xa25d92d7f70cf6a88ff317cfec071e13774516da664f5fac0d4ecaa65b8bf4eb87a64a4d5ef2bd97dfae98d388dbf5cc", + "0xa7af47cd0041295798f9779020a44653007444e8b4ef0712982b06d0dcdd434ec4e1f7c5f7a049326602cb605c9105b7", + "0xaefe172eac5568369a05980931cc476bebd9dea573ba276d59b9d8c4420784299df5a910033b7e324a6c2dfc62e3ef05", + "0xb69bc9d22ffa645baa55e3e02522e9892bb2daa7fff7c15846f13517d0799766883ee09ae0869df4139150c5b843ca8a", + "0x95a10856140e493354fdd12722c7fdded21b6a2ffbc78aa2697104af8ad0c8e2206f44b0bfee077ef3949d46bbf7c16b", + "0x891f2fcd2c47cbea36b7fa715968540c233313f05333f09d29aba23c193f462ed490dd4d00969656e89c53155fdfe710", + "0xa6c33e18115e64e385c843dde34e8a228222795c7ca90bc2cc085705d609025f3351d9be61822c69035a49fb3e48f2d5", + "0xb87fb12f12c0533b005adad0487f03393ff682e13575e3cb57280c3873b2c38ba96a63c49eef7a442753d26b7005230b", + "0xb905c02ba451bfd411c135036d92c27af3b0b1c9c2f1309d6948544a264b125f39dd41afeff4666b12146c545adc168a", + "0x8b29c513f43a78951cf742231cf5457a6d9d55edf45df5481a0f299a418d94effef561b15d2c1a01d1b8067e7153fda9", + "0xb9941cccd51dc645920d2781c81a317e5a33cb7cf76427b60396735912cb6d2ca9292bb4d36b6392467d390d2c58d9f3", + "0xa8546b627c76b6ef5c93c6a98538d8593dbe21cb7673fd383d5401b0c935eea0bdeeefeb1af6ad41bad8464fb87bbc48", + "0xaa286b27de2812de63108a1aec29d171775b69538dc6198640ac1e96767c2b83a50391f49259195957d457b493b667c9", + "0xa932fb229f641e9abbd8eb2bd874015d97b6658ab6d29769fc23b7db9e41dd4f850382d4c1f08af8f156c5937d524473", + "0xa1412840fcc86e2aeec175526f2fb36e8b3b8d21a78412b7266daf81e51b3f68584ed8bd42a66a43afdd8c297b320520", + "0x89c78be9efb624c97ebca4fe04c7704fa52311d183ffd87737f76b7dadc187c12c982bd8e9ed7cd8beb48cdaafd2fd01", + "0xa3f5ddec412a5bec0ce15e3bcb41c6214c2b05d4e9135a0d33c8e50a78eaba71e0a5a6ea8b45854dec5c2ed300971fc2", + "0x9721f9cec7a68b7758e3887548790de49fa6a442d0396739efa20c2f50352a7f91d300867556d11a703866def2d5f7b5", + "0xa23764e140a87e5991573521af039630dd28128bf56eed2edbed130fd4278e090b60cf5a1dca9de2910603d44b9f6d45", + "0xa1a6494a994215e48ab55c70efa8ffdddce6e92403c38ae7e8dd2f8288cad460c6c7db526bbdf578e96ca04d9fe12797", + "0xb1705ea4cb7e074efe0405fc7b8ee2ec789af0426142f3ec81241cacd4f7edcd88e39435e4e4d8e7b1df64f3880d6613", + "0x85595d061d677116089a6064418b93eb44ff79e68d12bd9625078d3bbc440a60d0b02944eff6054433ee34710ae6fbb4", + "0x9978d5e30bedb7526734f9a1febd973a70bfa20890490e7cc6f2f9328feab1e24f991285dbc3711d892514e2d7d005ad", + "0xaf30243c66ea43b9f87a061f947f7bce745f09194f6e95f379c7582b9fead920e5d6957eaf05c12ae1282ada4670652f", + "0xa1930efb473f88001e47aa0b2b2a7566848cccf295792e4544096ecd14ee5d7927c173a8576b405bfa2eec551cd67eb5", + "0xb0446d1c590ee5a45f7e22d269c044f3848c97aec1d226b44bfd0e94d9729c28a38bccddc3a1006cc5fe4e3c24f001f2", + "0xb8a8380172df3d84b06176df916cf557966d4f2f716d3e9437e415d75b646810f79f2b2b71d857181b7fc944018883a3", + "0xa563afec25b7817bfa26e19dc9908bc00aa8fc3d19be7d6de23648701659009d10e3e4486c28e9c6b13d48231ae29ac5", + "0xa5a8e80579de886fb7d6408f542791876885947b27ad6fa99a8a26e381f052598d7b4e647b0115d4b5c64297e00ce28e", + "0x8f87afcc7ad33c51ac719bade3cd92da671a37a82c14446b0a2073f4a0a23085e2c8d31913ed2d0be928f053297de8f6", + "0xa43c455ce377e0bc434386c53c752880687e017b2f5ae7f8a15c044895b242dffde4c92fb8f8bb50b18470b17351b156", + "0x8368f8b12a5bceb1dba25adb3a2e9c7dc9b1a77a1f328e5a693f5aec195cd1e06b0fe9476b554c1c25dac6c4a5b640a3", + "0x919878b27f3671fc78396f11531c032f3e2bd132d04cc234fa4858676b15fb1db3051c0b1db9b4fc49038216f11321ce", + "0xb48cd67fb7f1242696c1f877da4bdf188eac676cd0e561fbac1a537f7b8229aff5a043922441d603a26aae56a15faee4", + "0xa3e0fdfd4d29ea996517a16f0370b54787fefe543c2fe73bfc6f9e560c1fd30dad8409859e2d7fa2d44316f24746c712", + "0x8bb156ade8faf149df7bea02c140c7e392a4742ae6d0394d880a849127943e6f26312033336d3b9fdc0092d71b5efe87", + "0x8845e5d5cc555ca3e0523244300f2c8d7e4d02aaebcb5bd749d791208856c209a6f84dd99fd55968c9f0ab5f82916707", + "0xa3e90bb5c97b07789c2f32dff1aec61d0a2220928202f5ad5355ae71f8249237799d6c8a22602e32e572cb12eabe0c17", + "0xb150bcc391884c996149dc3779ce71f15dda63a759ee9cc05871f5a8379dcb62b047098922c0f26c7bd04deb394c33f9", + "0x95cd4ad88d51f0f2efcfd0c2df802fe252bb9704d1afbf9c26a248df22d55da87bdfaf41d7bc6e5df38bd848f0b13f42", + "0xa05a49a31e91dff6a52ac8b9c2cfdd646a43f0d488253f9e3cfbce52f26667166bbb9b608fc358763a65cbf066cd6d05", + "0xa59c3c1227fdd7c2e81f5e11ef5c406da44662987bac33caed72314081e2eed66055d38137e01b2268e58ec85dd986c0", + "0xb7020ec3bd73a99861f0f1d88cf5a19abab1cbe14b7de77c9868398c84bb8e18dbbe9831838a96b6d6ca06e82451c67b", + "0x98d1ff2525e9718ee59a21d8900621636fcd873d9a564b8dceb4be80a194a0148daf1232742730b3341514b2e5a5436c", + "0x886d97b635975fc638c1b6afc493e5998ca139edba131b75b65cfe5a8e814f11bb678e0eeee5e6e5cd913ad3f2fefdfc", + "0x8fb9fd928d38d5d813b671c924edd56601dd7163b686c13f158645c2f869d9250f3859aa5463a39258c90fef0f41190a", + "0xaac35e1cd655c94dec3580bb3800bd9c2946c4a9856f7d725af15fbea6a2d8ca51c8ad2772abed60ee0e3fb9cb24046b", + "0xb8d71fa0fa05ac9e443c9b4929df9e7f09a919be679692682e614d24227e04894bfc14a5c73a62fb927fedff4a0e4aa7", + "0xa45a19f11fbbb531a704badbb813ed8088ab827c884ee4e4ebf363fa1132ff7cfa9d28be9c85b143e4f7cdbc94e7cf1a", + "0x82b54703a4f295f5471b255ab59dce00f0fe90c9fb6e06b9ee48b15c91d43f4e2ef4a96c3118aeb03b08767be58181bb", + "0x8283264c8e6d2a36558f0d145c18576b6600ff45ff99cc93eca54b6c6422993cf392668633e5df396b9331e873d457e5", + "0x8c549c03131ead601bc30eb6b9537b5d3beb7472f5bb1bcbbfd1e9f3704477f7840ab3ab7f7dc13bbbbcdff886a462d4", + "0xafbb0c520ac1b5486513587700ad53e314cb74bfbc12e0b5fbdcfdaac36d342e8b59856196a0d84a25cff6e6e1d17e76", + "0x89e4c22ffb51f2829061b3c7c1983c5c750cad158e3a825d46f7cf875677da5d63f653d8a297022b5db5845c9271b32b", + "0xafb27a86c4c2373088c96b9adf4433f2ebfc78ac5c526e9f0510670b6e4e5e0057c0a4f75b185e1a30331b9e805c1c15", + "0xa18e16b57445f88730fc5d3567bf5a176861dc14c7a08ed2996fe80eed27a0e7628501bcb78a1727c5e9ac55f29c12c4", + "0x93d61bf88b192d6825cf4e1120af1c17aa0f994d158b405e25437eaeefae049f7b721a206e7cc8a04fdc29d3c42580a1", + "0xa99f2995a2e3ed2fd1228d64166112038de2f516410aa439f4c507044e2017ea388604e2d0f7121256fadf7fbe7023d1", + "0x914fd91cffc23c32f1c6d0e98bf660925090d873367d543034654389916f65f552e445b0300b71b61b721a72e9a5983c", + "0xb42a578a7787b71f924e7def425d849c1c777156b1d4170a8ee7709a4a914e816935131afd9a0412c4cb952957b20828", + "0x82fb30590e84b9e45db1ec475a39971cf554dc01bcc7050bc89265740725c02e2be5a972168c5170c86ae83e5b0ad2c0", + "0xb14f8d8e1e93a84976289e0cf0dfa6f3a1809e98da16ee5c4932d0e1ed6bf8a07697fdd4dd86a3df84fb0003353cdcc0", + "0x85d7a2f4bda31aa2cb208b771fe03291a4ebdaf6f1dc944c27775af5caec412584c1f45bc741fca2a6a85acb3f26ad7d", + "0xaf02e56ce886ff2253bc0a68faad76f25ead84b2144e5364f3fb9b648f03a50ee9dc0b2c33ebacf7c61e9e43201ef9ef", + "0x87e025558c8a0b0abd06dfc350016847ea5ced7af2d135a5c9eec9324a4858c4b21510fb0992ec52a73447f24945058e", + "0x80fff0bafcd058118f5e7a4d4f1ae0912efeb281d2cbe4d34ba8945cc3dbe5d8baf47fb077343b90b8d895c90b297aca", + "0xb6edcf3a40e7b1c3c0148f47a263cd819e585a51ef31c2e35a29ce6f04c53e413f743034c0d998d9c00a08ba00166f31", + "0xabb87ed86098c0c70a76e557262a494ff51a30fb193f1c1a32f8e35eafa34a43fcc07aa93a3b7a077d9e35afa07b1a3d", + "0xa280214cd3bb0fb7ecd2d8bcf518cbd9078417f2b91d2533ec2717563f090fb84f2a5fcfdbbeb2a2a1f8a71cc5aa5941", + "0xa63083ca7238ea2b57d15a475963cf1d4f550d8cd76db290014a0461b90351f1f26a67d674c837b0b773b330c7c3d534", + "0xa8fa39064cb585ece5263e2f42f430206476bf261bd50f18d2b694889bd79d04d56410664cecad62690e5c5a20b3f6ff", + "0x85ba52ce9d700a5dcf6c5b00559acbe599d671ce5512467ff4b6179d7fad550567ce2a9c126a50964e3096458ea87920", + "0xb913501e1008f076e5eac6d883105174f88b248e1c9801e568fefaffa1558e4909364fc6d9512aa4d125cbd7cc895f05", + "0x8eb33b5266c8f2ed4725a6ad147a322e44c9264cf261c933cbbe230a43d47fca0f29ec39756b20561dabafadd5796494", + "0x850ebc8b661a04318c9db5a0515066e6454fa73865aa4908767a837857ecd717387f614acb614a88e075d4edc53a2f5a", + "0xa08d6b92d866270f29f4ce23a3f5d99b36b1e241a01271ede02817c8ec3f552a5c562db400766c07b104a331835c0c64", + "0x8131804c89bb3e74e9718bfc4afa547c1005ff676bd4db9604335032b203390cfa54478d45c6c78d1fe31a436ed4be9f", + "0x9106d94f23cc1eacec8316f16d6f0a1cc160967c886f51981fdb9f3f12ee1182407d2bb24e5b873de58cb1a3ee915a6b", + "0xa13806bfc3eae7a7000c9d9f1bd25e10218d4e67f59ae798b145b098bca3edad2b1040e3fc1e6310e612fb8818f459ac", + "0x8c69fbca502046cb5f6db99900a47b34117aef3f4b241690cdb3b84ca2a2fc7833e149361995dc41fa78892525bce746", + "0x852c473150c91912d58ecb05769222fa18312800c3f56605ad29eec9e2d8667b0b81c379048d3d29100ed2773bb1f3c5", + "0xb1767f6074426a00e01095dbb1795beb4e4050c6411792cbad6537bc444c3165d1058bafd1487451f9c5ddd209e0ae7e", + "0x80c600a5fe99354ce59ff0f84c760923dc8ff66a30bf47dc0a086181785ceb01f9b951c4e66df800ea6d705e8bc47055", + "0xb5cf19002fbc88a0764865b82afcb4d64a50196ea361e5c71dff7de084f4dcbbc34ec94a45cc9e0247bd51da565981aa", + "0x93e67a254ea8ce25e112d93cc927fadaa814152a2c4ec7d9a56eaa1ed47aec99b7e9916b02e64452cc724a6641729bbb", + "0xace70b32491bda18eee4a4d041c3bc9effae9340fe7e6c2f5ad975ee0874c17f1a7da7c96bd85fccff9312c518fac6e9", + "0xab4cfa02065017dd7f1aadc66f2c92f78f0f11b8597c03a5d69d82cb2eaf95a4476a836ac102908f137662472c8d914b", + "0xa40b8cd8deb8ae503d20364d64cab7c2801b7728a9646ed19c65edea6a842756a2f636283494299584ad57f4bb12cd0b", + "0x8594e11d5fc2396bcd9dbf5509ce4816dbb2b7305168021c426171fb444d111da5a152d6835ad8034542277011c26c0e", + "0x8024de98c26b4c994a66628dc304bb737f4b6859c86ded552c5abb81fd4c6c2e19d5a30beed398a694b9b2fdea1dd06a", + "0x8843f5872f33f54df8d0e06166c1857d733995f67bc54abb8dfa94ad92407cf0179bc91b0a50bbb56cdc2b350d950329", + "0xb8bab44c7dd53ef9edf497dcb228e2a41282c90f00ba052fc52d57e87b5c8ab132d227af1fcdff9a12713d1f980bcaae", + "0x982b4d7b29aff22d527fd82d2a52601d95549bfb000429bb20789ed45e5abf1f4b7416c7b7c4b79431eb3574b29be658", + "0x8eb1f571b6a1878e11e8c1c757e0bc084bab5e82e897ca9be9b7f4b47b91679a8190bf0fc8f799d9b487da5442415857", + "0xa6e74b588e5af935c8b243e888582ef7718f8714569dd4992920740227518305eb35fab674d21a5551cca44b3e511ef2", + "0xa30fc2f3a4cb4f50566e82307de73cd7bd8fe2c1184e9293c136a9b9e926a018d57c6e4f308c95b9eb8299e94d90a2a1", + "0xa50c5869ca5d2b40722c056a32f918d47e0b65ca9d7863ca7d2fb4a7b64fe523fe9365cf0573733ceaadebf20b48fff8", + "0x83bbdd32c04d17581418cf360749c7a169b55d54f2427390defd9f751f100897b2d800ce6636c5bbc046c47508d60c8c", + "0xa82904bdf614de5d8deaff688c8a5e7ac5b3431687acbcda8fa53960b7c417a39c8b2e462d7af91ce6d79260f412db8e", + "0xa4362e31ff4b05d278b033cf5eebea20de01714ae16d4115d04c1da4754269873afc8171a6f56c5104bfd7b0db93c3e7", + "0xb5b8daa63a3735581e74a021b684a1038cea77168fdb7fdf83c670c2cfabcfc3ab2fc7359069b5f9048188351aef26b5", + "0xb48d723894b7782d96ac8433c48faca1bdfa5238019c451a7f47d958097cce3ae599b876cf274269236b9d6ff8b6d7ca", + "0x98ffff6a61a3a6205c7820a91ca2e7176fab5dba02bc194c4d14942ac421cb254183c705506ab279e4f8db066f941c6c", + "0xae7db24731da2eaa6efc4f7fcba2ecc26940ddd68038dce43acf2cee15b72dc4ef42a7bfdd32946d1ed78786dd7696b3", + "0xa656db14f1de9a7eb84f6301b4acb2fbf78bfe867f48a270e416c974ab92821eb4df1cb881b2d600cfed0034ac784641", + "0xaa315f8ecba85a5535e9a49e558b15f39520fce5d4bf43131bfbf2e2c9dfccc829074f9083e8d49f405fb221d0bc4c3c", + "0x90bffba5d9ff40a62f6c8e9fc402d5b95f6077ed58d030c93e321b8081b77d6b8dac3f63a92a7ddc01585cf2c127d66c", + "0xabdd733a36e0e0f05a570d0504e73801bf9b5a25ff2c78786f8b805704997acb2e6069af342538c581144d53149fa6d3", + "0xb4a723bb19e8c18a01bd449b1bb3440ddb2017f10bb153da27deb7a6a60e9bb37619d6d5435fbb1ba617687838e01dd0", + "0x870016b4678bab3375516db0187a2108b2e840bae4d264b9f4f27dbbc7cc9cac1d7dc582d7a04d6fd1ed588238e5e513", + "0x80d33d2e20e8fc170aa3cb4f69fffb72aeafb3b5bb4ea0bc79ab55da14142ca19b2d8b617a6b24d537366e3b49cb67c3", + "0xa7ee76aec273aaae03b3b87015789289551969fb175c11557da3ab77e39ab49d24634726f92affae9f4d24003050d974", + "0x8415ea4ab69d779ebd42d0fe0c6aef531d6a465a5739e429b1fcf433ec45aa8296c527e965a20f0ec9f340c9273ea3cf", + "0x8c7662520794e8b4405d0b33b5cac839784bc86a5868766c06cbc1fa306dbe334978177417b31baf90ce7b0052a29c56", + "0x902b2abecc053a3dbdea9897ee21e74821f3a1b98b2d560a514a35799f4680322550fd3a728d4f6d64e1de98033c32b8", + "0xa05e84ed9ecab8d508d670c39f2db61ad6e08d2795ec32a3c9d0d3737ef3801618f4fc2a95f90ec2f068606131e076c5", + "0x8b9208ff4d5af0c2e3f53c9375da666773ac57197dfabb0d25b1c8d0588ba7f3c15ee9661bb001297f322ea2fbf6928b", + "0xa3c827741b34a03254d4451b5ab74a96f2b9f7fb069e2f5adaf54fd97cc7a4d516d378db5ca07da87d8566d6eef13726", + "0x8509d8a3f4a0ed378e0a1e28ea02f6bf1d7f6c819c6c2f5297c7df54c895b848f841653e32ba2a2c22c2ff739571acb8", + "0xa0ce988b7d3c40b4e496aa83a09e4b5472a2d98679622f32bea23e6d607bc7de1a5374fb162bce0549a67dad948519be", + "0xaa8a3dd12bd60e3d2e05f9c683cdcb8eab17fc59134815f8d197681b1bcf65108cba63ac5c58ee632b1e5ed6bba5d474", + "0x8b955f1d894b3aefd883fb4b65f14cd37fc2b9db77db79273f1700bef9973bf3fd123897ea2b7989f50003733f8f7f21", + "0xac79c00ddac47f5daf8d9418d798d8af89fc6f1682e7e451f71ea3a405b0d36af35388dd2a332af790bc83ca7b819328", + "0xa0d44dd2a4438b809522b130d0938c3fe7c5c46379365dbd1810a170a9aa5818e1c783470dd5d0b6d4ac7edbb7330910", + "0xa30b69e39ad43dd540a43c521f05b51b5f1b9c4eed54b8162374ae11eac25da4f5756e7b70ce9f3c92c2eeceee7431ed", + "0xac43220b762c299c7951222ea19761ab938bf38e4972deef58ed84f4f9c68c230647cf7506d7cbfc08562fcca55f0485", + "0xb28233b46a8fb424cfa386a845a3b5399d8489ceb83c8f3e05c22c934798d639c93718b7b68ab3ce24c5358339e41cbb", + "0xac30d50ee8ce59a10d4b37a3a35e62cdb2273e5e52232e202ca7d7b8d09d28958ee667fae41a7bb6cdc6fe8f6e6c9c85", + "0xb199842d9141ad169f35cc7ff782b274cbaa645fdb727761e0a89edbf0d781a15f8218b4bf4eead326f2903dd88a9cc1", + "0x85e018c7ddcad34bb8285a737c578bf741ccd547e68c734bdb3808380e12c5d4ef60fc896b497a87d443ff9abd063b38", + "0x8c856e6ba4a815bdb891e1276f93545b7072f6cb1a9aa6aa5cf240976f29f4dee01878638500a6bf1daf677b96b54343", + "0xb8a47555fa8710534150e1a3f13eab33666017be6b41005397afa647ea49708565f2b86b77ad4964d140d9ced6b4d585", + "0x8cd1f1db1b2f4c85a3f46211599caf512d5439e2d8e184663d7d50166fd3008f0e9253272f898d81007988435f715881", + "0xb1f34b14612c973a3eceb716dc102b82ab18afef9de7630172c2780776679a7706a4874e1df3eaadf541fb009731807f", + "0xb25464af9cff883b55be2ff8daf610052c02df9a5e147a2cf4df6ce63edcdee6dc535c533590084cc177da85c5dc0baa", + "0x91c3c4b658b42d8d3448ae1415d4541d02379a40dc51e36a59bd6e7b9ba3ea51533f480c7c6e8405250ee9b96a466c29", + "0x86dc027b95deb74c36a58a1333a03e63cb5ae22d3b29d114cfd2271badb05268c9d0c819a977f5e0c6014b00c1512e3a", + "0xae0e6ff58eb5fa35da5107ebeacf222ab8f52a22bb1e13504247c1dfa65320f40d97b0e6b201cb6613476687cb2f0681", + "0x8f13415d960b9d7a1d93ef28afc2223e926639b63bdefce0f85e945dfc81670a55df288893a0d8b3abe13c5708f82f91", + "0x956f67ca49ad27c1e3a68c1faad5e7baf0160c459094bf6b7baf36b112de935fdfd79fa4a9ea87ea8de0ac07272969f4", + "0x835e45e4a67df9fb51b645d37840b3a15c171d571a10b03a406dd69d3c2f22df3aa9c5cbe1e73f8d767ce01c4914ea9a", + "0x919b938e56d4b32e2667469d0bdccb95d9dda3341aa907683ee70a14bbbe623035014511c261f4f59b318b610ac90aa3", + "0x96b48182121ccd9d689bf1dfdc228175564cd68dc904a99c808a7f0053a6f636c9d953e12198bdf2ea49ea92772f2e18", + "0xac5e5a941d567fa38fdbcfa8cf7f85bb304e3401c52d88752bcd516d1fa9bac4572534ea2205e38423c1df065990790f", + "0xac0bd594fb85a8d4fc26d6df0fa81f11919401f1ecf9168b891ec7f061a2d9368af99f7fd8d9b43b2ce361e7b8482159", + "0x83d92c69ca540d298fe80d8162a1c7af3fa9b49dfb69e85c1d136a3ec39fe419c9fa78e0bb6d96878771fbd37fe92e40", + "0xb35443ae8aa66c763c2db9273f908552fe458e96696b90e41dd509c17a5c04ee178e3490d9c6ba2dc0b8f793c433c134", + "0x923b2d25aa45b2e580ffd94cbb37dc8110f340f0f011217ee1bd81afb0714c0b1d5fb4db86006cdd2457563276f59c59", + "0x96c9125d38fca1a61ac21257b696f8ac3dae78def50285e44d90ea293d591d1c58f703540a7e4e99e070afe4646bbe15", + "0xb57946b2332077fbcdcb406b811779aefd54473b5559a163cd65cb8310679b7e2028aa55c12a1401fdcfcac0e6fae29a", + "0x845daedc5cf972883835d7e13c937b63753c2200324a3b8082a6c4abb4be06c5f7c629d4abe4bfaf1d80a1f073eb6ce6", + "0x91a55dfd0efefcd03dc6dacc64ec93b8d296cb83c0ee72400a36f27246e7f2a60e73b7b70ba65819e9cfb73edb7bd297", + "0x8874606b93266455fe8fdd25df9f8d2994e927460af06f2e97dd4d2d90db1e6b06d441b72c2e76504d753badca87fb37", + "0x8ee99e6d231274ff9252c0f4e84549da173041299ad1230929c3e3d32399731c4f20a502b4a307642cac9306ccd49d3c", + "0x8836497714a525118e20849d6933bb8535fb6f72b96337d49e3133d936999c90a398a740f42e772353b5f1c63581df6d", + "0xa6916945e10628f7497a6cdc5e2de113d25f7ade3e41e74d3de48ccd4fce9f2fa9ab69645275002e6f49399b798c40af", + "0x9597706983107eb23883e0812e1a2c58af7f3499d50c6e29b455946cb9812fde1aa323d9ed30d1c0ffd455abe32303cd", + "0xa24ee89f7f515cc33bdbdb822e7d5c1877d337f3b2162303cfc2dae028011c3a267c5cb4194afa63a4856a6e1c213448", + "0x8cd25315e4318801c2776824ae6e7d543cb85ed3bc2498ba5752df2e8142b37653cf9e60104d674be3aeb0a66912e97a", + "0xb5085ecbe793180b40dbeb879f4c976eaaccaca3a5246807dced5890e0ed24d35f3f86955e2460e14fb44ff5081c07ba", + "0x960188cc0b4f908633a6840963a6fa2205fc42c511c6c309685234911c5304ef4c304e3ae9c9c69daa2fb6a73560c256", + "0xa32d0a70bf15d569b4cda5aebe3e41e03c28bf99cdd34ffa6c5d58a097f322772acca904b3a47addb6c7492a7126ebac", + "0x977f72d06ad72d4aa4765e0f1f9f4a3231d9f030501f320fe7714cc5d329d08112789fa918c60dd7fdb5837d56bb7fc6", + "0x99fa038bb0470d45852bb871620d8d88520adb701712fcb1f278fed2882722b9e729e6cdce44c82caafad95e37d0e6f7", + "0xb855e8f4fc7634ada07e83b6c719a1e37acb06394bc8c7dcab7747a8c54e5df3943915f021364bd019fdea103864e55f", + "0x88bc2cd7458532e98c596ef59ea2cf640d7cc31b4c33cef9ed065c078d1d4eb49677a67de8e6229cc17ea48bace8ee5a", + "0xaaa78a3feaa836d944d987d813f9b9741afb076e6aca1ffa42682ab06d46d66e0c07b8f40b9dbd63e75e81efa1ef7b08", + "0xb7b080420cc4d808723b98b2a5b7b59c81e624ab568ecdfdeb8bf3aa151a581b6f56e983ef1b6f909661e25db40b0c69", + "0xabee85c462ac9a2c58e54f06c91b3e5cd8c5f9ab5b5deb602b53763c54826ed6deb0d6db315a8d7ad88733407e8d35e2", + "0x994d075c1527407547590df53e9d72dd31f037c763848d1662eebd4cefec93a24328c986802efa80e038cb760a5300f5", + "0xab8777640116dfb6678e8c7d5b36d01265dfb16321abbfc277da71556a34bb3be04bc4ae90124ed9c55386d2bfb3bda0", + "0x967e3a828bc59409144463bcf883a3a276b5f24bf3cbfdd7a42343348cba91e00b46ac285835a9b91eef171202974204", + "0x875a9f0c4ffe5bb1d8da5e3c8e41d0397aa6248422a628bd60bfae536a651417d4e8a7d2fb98e13f2dad3680f7bd86d3", + "0xacaa330c3e8f95d46b1880126572b238dbb6d04484d2cd4f257ab9642d8c9fc7b212188b9c7ac9e0fd135c520d46b1bf", + "0xaceb762edbb0f0c43dfcdb01ea7a1ac5918ca3882b1e7ebc4373521742f1ed5250d8966b498c00b2b0f4d13212e6dd0b", + "0x81d072b4ad258b3646f52f399bced97c613b22e7ad76373453d80b1650c0ca87edb291a041f8253b649b6e5429bb4cff", + "0x980a47d27416ac39c7c3a0ebe50c492f8c776ea1de44d5159ac7d889b6d554357f0a77f0e5d9d0ff41aae4369eba1fc2", + "0x8b4dfd5ef5573db1476d5e43aacfb5941e45d6297794508f29c454fe50ea622e6f068b28b3debe8635cf6036007de2e3", + "0xa60831559d6305839515b68f8c3bc7abbd8212cc4083502e19dd682d56ca37c9780fc3ce4ec2eae81ab23b221452dc57", + "0x951f6b2c1848ced9e8a2339c65918e00d3d22d3e59a0a660b1eca667d18f8430d737884e9805865ef3ed0fe1638a22d9", + "0xb02e38fe790b492aa5e89257c4986c9033a8b67010fa2add9787de857d53759170fdd67715ca658220b4e14b0ca48124", + "0xa51007e4346060746e6b0e4797fc08ef17f04a34fe24f307f6b6817edbb8ce2b176f40771d4ae8a60d6152cbebe62653", + "0xa510005b05c0b305075b27b243c9d64bcdce85146b6ed0e75a3178b5ff9608213f08c8c9246f2ca6035a0c3e31619860", + "0xaaff4ef27a7a23be3419d22197e13676d6e3810ceb06a9e920d38125745dc68a930f1741c9c2d9d5c875968e30f34ab5", + "0x864522a9af9857de9814e61383bebad1ba9a881696925a0ea6bfc6eff520d42c506bbe5685a9946ed710e889765be4a0", + "0xb63258c080d13f3b7d5b9f3ca9929f8982a6960bdb1b0f8676f4dca823971601672f15e653917bf5d3746bb220504913", + "0xb51ce0cb10869121ae310c7159ee1f3e3a9f8ad498827f72c3d56864808c1f21fa2881788f19ece884d3f705cd7bd0c5", + "0x95d9cecfc018c6ed510e441cf84c712d9909c778c16734706c93222257f64dcd2a9f1bd0b400ca271e22c9c487014274", + "0x8beff4d7d0140b86380ff4842a9bda94c2d2be638e20ac68a4912cb47dbe01a261857536375208040c0554929ced1ddc", + "0x891ff49258749e2b57c1e9b8e04b12c77d79c3308b1fb615a081f2aacdfb4b39e32d53e069ed136fdbd43c53b87418fa", + "0x9625cad224e163d387738825982d1e40eeff35fe816d10d7541d15fdc4d3eee48009090f3faef4024b249205b0b28f72", + "0x8f3947433d9bd01aa335895484b540a9025a19481a1c40b4f72dd676bfcf332713714fd4010bde936eaf9470fd239ed0", + "0xa00ec2d67789a7054b53f0e858a8a232706ccc29a9f3e389df7455f1a51a2e75801fd78469a13dbc25d28399ae4c6182", + "0xa3f65884506d4a62b8775a0ea0e3d78f5f46bc07910a93cd604022154eabdf1d73591e304d61edc869e91462951975e1", + "0xa14eef4fd5dfac311713f0faa9a60415e3d30b95a4590cbf95f2033dffb4d16c02e7ceff3dcd42148a4e3bc49cce2dd4", + "0x8afa11c0eef3c540e1e3460bc759bb2b6ea90743623f88e62950c94e370fe4fd01c22b6729beba4dcd4d581198d9358f", + "0xafb05548a69f0845ffcc5f5dc63e3cdb93cd270f5655173b9a950394b0583663f2b7164ba6df8d60c2e775c1d9f120af", + "0x97f179e01a947a906e1cbeafa083960bc9f1bade45742a3afee488dfb6011c1c6e2db09a355d77f5228a42ccaa7bdf8e", + "0x8447fca4d35f74b3efcbd96774f41874ca376bf85b79b6e66c92fa3f14bdd6e743a051f12a7fbfd87f319d1c6a5ce217", + "0xa57ca39c23617cd2cf32ff93b02161bd7baf52c4effb4679d9d5166406e103bc8f3c6b5209e17c37dbb02deb8bc72ddd", + "0x9667c7300ff80f0140be002b0e36caab07aaee7cce72679197c64d355e20d96196acaf54e06e1382167d081fe6f739c1", + "0x828126bb0559ce748809b622677267ca896fa2ee76360fd2c02990e6477e06a667241379ca7e65d61a5b64b96d7867de", + "0x8b8835dea6ba8cf61c91f01a4b3d2f8150b687a4ee09b45f2e5fc8f80f208ae5d142d8e3a18153f0722b90214e60c5a7", + "0xa98e8ff02049b4da386e3ee93db23bbb13dfeb72f1cfde72587c7e6d962780b7671c63e8ac3fbaeb1a6605e8d79e2f29", + "0x87a4892a0026d7e39ef3af632172b88337cb03669dea564bcdb70653b52d744730ebb5d642e20cb627acc9dbb547a26b", + "0x877352a22fc8052878a57effc159dac4d75fe08c84d3d5324c0bab6d564cdf868f33ceee515eee747e5856b62cfa0cc7", + "0x8b801ba8e2ff019ee62f64b8cb8a5f601fc35423eb0f9494b401050103e1307dc584e4e4b21249cd2c686e32475e96c3", + "0xa9e7338d6d4d9bfec91b2af28a8ed13b09415f57a3a00e5e777c93d768fdb3f8e4456ae48a2c6626b264226e911a0e28", + "0x99c05fedf40ac4726ed585d7c1544c6e79619a0d3fb6bda75a08c7f3c0008e8d5e19ed4da48de3216135f34a15eba17c", + "0xa61cce8a1a8b13a4a650fdbec0eeea8297c352a8238fb7cac95a0df18ed16ee02a3daa2de108fa122aca733bd8ad7855", + "0xb97f37da9005b440b4cb05870dd881bf8491fe735844f2d5c8281818583b38e02286e653d9f2e7fa5e74c3c3eb616540", + "0xa72164a8554da8e103f692ac5ebb4aece55d5194302b9f74b6f2a05335b6e39beede0bf7bf8c5bfd4d324a784c5fb08c", + "0xb87e8221c5341cd9cc8bb99c10fe730bc105550f25ed4b96c0d45e6142193a1b2e72f1b3857373a659b8c09be17b3d91", + "0xa41fb1f327ef91dcb7ac0787918376584890dd9a9675c297c45796e32d6e5985b12f9b80be47fc3a8596c245f419d395", + "0x90dafa3592bdbb3465c92e2a54c2531822ba0459d45d3e7a7092fa6b823f55af28357cb51896d4ec2d66029c82f08e26", + "0xa0a9adc872ebc396557f484f1dd21954d4f4a21c4aa5eec543f5fa386fe590839735c01f236574f7ff95407cd12de103", + "0xb8c5c940d58be7538acf8672852b5da3af34f82405ef2ce8e4c923f1362f97fc50921568d0fd2fe846edfb0823e62979", + "0x85aaf06a8b2d0dac89dafd00c28533f35dbd074978c2aaa5bef75db44a7b12aeb222e724f395513b9a535809a275e30b", + "0x81f3cbe82fbc7028c26a6c1808c604c63ba023a30c9f78a4c581340008dbda5ec07497ee849a2183fcd9124f7936af32", + "0xa11ac738de75fd60f15a34209d3825d5e23385796a4c7fc5931822f3f380af977dd0f7b59fbd58eed7777a071e21b680", + "0x85a279c493de03db6fa6c3e3c1b1b29adc9a8c4effc12400ae1128da8421954fa8b75ad19e5388fe4543b76fb0812813", + "0x83a217b395d59ab20db6c4adb1e9713fc9267f5f31a6c936042fe051ce8b541f579442f3dcf0fa16b9e6de9fd3518191", + "0x83a0b86e7d4ed8f9ccdc6dfc8ff1484509a6378fa6f09ed908e6ab9d1073f03011dc497e14304e4e3d181b57de06a5ab", + "0xa63ad69c9d25704ce1cc8e74f67818e5ed985f8f851afa8412248b2df5f833f83b95b27180e9e7273833ed0d07113d3b", + "0x99b1bc2021e63b561fe44ddd0af81fcc8627a91bfeecbbc989b642bc859abc0c8d636399701aad7bbaf6a385d5f27d61", + "0xb53434adb66f4a807a6ad917c6e856321753e559b1add70824e5c1e88191bf6993fccb9b8b911fc0f473fb11743acacd", + "0x97ed3b9e6fb99bf5f945d4a41f198161294866aa23f2327818cdd55cb5dc4c1a8eff29dd8b8d04902d6cd43a71835c82", + "0xb1e808260e368a18d9d10bdea5d60223ba1713b948c782285a27a99ae50cc5fc2c53d407de07155ecc16fb8a36d744a0", + "0xa3eb4665f18f71833fec43802730e56b3ee5a357ea30a888ad482725b169d6f1f6ade6e208ee081b2e2633079b82ba7d", + "0xab8beb2c8353fc9f571c18fdd02bdb977fc883313469e1277b0372fbbb33b80dcff354ca41de436d98d2ed710faa467e", + "0xaa9071cfa971e4a335a91ad634c98f2be51544cb21f040f2471d01bb97e1df2277ae1646e1ea8f55b7ba9f5c8c599b39", + "0x80b7dbfdcaf40f0678012acc634eba44ea51181475180d9deb2050dc4f2de395289edd0223018c81057ec79b04b04c49", + "0x89623d7f6cb17aa877af14de842c2d4ab7fd576d61ddd7518b5878620a01ded40b6010de0da3cdf31d837eecf30e9847", + "0xa773bb024ae74dd24761f266d4fb27d6fd366a8634febe8235376b1ae9065c2fe12c769f1d0407867dfbe9f5272c352f", + "0x8455a561c3aaa6ba64c881a5e13921c592b3a02e968f4fb24a2243c36202795d0366d9cc1a24e916f84d6e158b7aeac7", + "0x81d8bfc4b283cf702a40b87a2b96b275bdbf0def17e67d04842598610b67ea08c804d400c3e69fa09ea001eaf345b276", + "0xb8f8f82cb11fea1c99467013d7e167ff03deb0c65a677fab76ded58826d1ba29aa7cf9fcd7763615735ea3ad38e28719", + "0x89a6a04baf9cccc1db55179e1650b1a195dd91fb0aebc197a25143f0f393524d2589975e3fbfc2547126f0bced7fd6f2", + "0xb81b2162df045390f04df07cbd0962e6b6ca94275a63edded58001a2f28b2ae2af2c7a6cba4ecd753869684e77e7e799", + "0xa3757f722776e50de45c62d9c4a2ee0f5655a512344c4cbec542d8045332806568dd626a719ef21a4eb06792ca70f204", + "0x8c5590df96ec22179a4e8786de41beb44f987a1dcc508eb341eecbc0b39236fdfad47f108f852e87179ccf4e10091e59", + "0x87502f026ed4e10167419130b88c3737635c5b9074c364e1dd247cef5ef0fc064b4ae99b187e33301e438bbd2fe7d032", + "0xaf925a2165e980ced620ff12289129fe17670a90ae0f4db9d4b39bd887ccb1f5d2514ac9ecf910f6390a8fc66bd5be17", + "0x857fca899828cf5c65d26e3e8a6e658542782fc72762b3b9c73514919f83259e0f849a9d4838b40dc905fe43024d0d23", + "0x87ffebdbfb69a9e1007ebac4ffcb4090ff13705967b73937063719aa97908986effcb7262fdadc1ae0f95c3690e3245d", + "0xa9ff6c347ac6f4c6ab993b748802e96982eaf489dc69032269568412fc9a79e7c2850dfc991b28211b3522ee4454344b", + "0xa65b3159df4ec48bebb67cb3663cd744027ad98d970d620e05bf6c48f230fa45bf17527fe726fdf705419bb7a1bb913e", + "0x84b97b1e6408b6791831997b03cd91f027e7660fd492a93d95daafe61f02427371c0e237c75706412f442991dfdff989", + "0xab761c26527439b209af0ae6afccd9340bbed5fbe098734c3145b76c5d2cd7115d9227b2eb523882b7317fbb09180498", + "0xa0479a8da06d7a69c0b0fee60df4e691c19c551f5e7da286dab430bfbcabf31726508e20d26ea48c53365a7f00a3ad34", + "0xa732dfc9baa0f4f40b5756d2e8d8937742999623477458e0bc81431a7b633eefc6f53b3b7939fe0a020018549c954054", + "0x901502436a1169ba51dc479a5abe7c8d84e0943b16bc3c6a627b49b92cd46263c0005bc324c67509edd693f28e612af1", + "0xb627aee83474e7f84d1bab9b7f6b605e33b26297ac6bbf52d110d38ba10749032bd551641e73a383a303882367af429b", + "0x95108866745760baef4a46ef56f82da6de7e81c58b10126ebd2ba2cd13d339f91303bf2fb4dd104a6956aa3b13739503", + "0x899ed2ade37236cec90056f3569bc50f984f2247792defafcceb49ad0ca5f6f8a2f06573705300e07f0de0c759289ff5", + "0xa9f5eee196d608efe4bcef9bf71c646d27feb615e21252cf839a44a49fd89da8d26a758419e0085a05b1d59600e2dc42", + "0xb36c6f68fed6e6c85f1f4a162485f24817f2843ec5cbee45a1ebfa367d44892e464949c6669f7972dc7167af08d55d25", + "0xaaaede243a9a1b6162afbc8f571a52671a5a4519b4062e3f26777664e245ba873ed13b0492c5dbf0258c788c397a0e9e", + "0x972b4fb39c31cbe127bf9a32a5cc10d621ebdd9411df5e5da3d457f03b2ab2cd1f6372d8284a4a9400f0b06ecdbfd38e", + "0x8f6ca1e110e959a4b1d9a5ce5f212893cec21db40d64d5ac4d524f352d72198f923416a850bf845bc5a22a79c0ea2619", + "0xa0f3c93b22134f66f04b2553a53b738644d1665ceb196b8494b315a4c28236fb492017e4a0de4224827c78e42f9908b7", + "0x807fb5ee74f6c8735b0b5ca07e28506214fe4047dbeb00045d7c24f7849e98706aea79771241224939cb749cf1366c7d", + "0x915eb1ff034224c0b645442cdb7d669303fdc00ca464f91aaf0b6fde0b220a3a74ff0cb043c26c9f3a5667b3fdaa9420", + "0x8fda6cef56ed33fefffa9e6ac8e6f76b1af379f89761945c63dd448801f7bb8ca970504a7105fac2f74f652ccff32327", + "0x87380cffdcffb1d0820fa36b63cc081e72187f86d487315177d4d04da4533eb19a0e2ff6115ceab528887819c44a5164", + "0x8cd89e03411a18e7f16f968b89fb500c36d47d229f6487b99e62403a980058db5925ce249206743333538adfad168330", + "0x974451b1df33522ce7056de9f03e10c70bf302c44b0741a59df3d6877d53d61a7394dcee1dd46e013d7cb9d73419c092", + "0x98c35ddf645940260c490f384a49496a7352bb8e3f686feed815b1d38f59ded17b1ad6e84a209e773ed08f7b8ff1e4c2", + "0x963f386cf944bb9b2ddebb97171b64253ea0a2894ac40049bdd86cda392292315f3a3d490ca5d9628c890cfb669f0acb", + "0x8d507712152babd6d142ee682638da8495a6f3838136088df9424ef50d5ec28d815a198c9a4963610b22e49b4cdf95e9", + "0x83d4bc6b0be87c8a4f1e9c53f257719de0c73d85b490a41f7420e777311640937320557ff2f1d9bafd1daaa54f932356", + "0x82f5381c965b7a0718441131c4d13999f4cdce637698989a17ed97c8ea2e5bdb5d07719c5f7be8688edb081b23ede0f4", + "0xa6ebecab0b72a49dfd01d69fa37a7f74d34fb1d4fef0aa10e3d6fceb9eccd671225c230af89f6eb514250e41a5f91f52", + "0x846d185bdad6e11e604df7f753b7a08a28b643674221f0e750ebdb6b86ec584a29c869e131bca868972a507e61403f6a", + "0x85a98332292acb744bd1c0fd6fdcf1f889a78a2c9624d79413ffa194cc8dfa7821a4b60cde8081d4b5f71f51168dd67f", + "0x8f7d97c3b4597880d73200d074eb813d95432306e82dafc70b580b8e08cb8098b70f2d07b4b3ac6a4d77e92d57035031", + "0x8185439c8751e595825d7053518cbe121f191846a38d4dbcb558c3f9d7a3104f3153401adaaaf27843bbe2edb504bfe3", + "0xb3c00d8ece1518fca6b1215a139b0a0e26d9cba1b3a424f7ee59f30ce800a5db967279ed60958dd1f3ee69cf4dd1b204", + "0xa2e6cb6978e883f9719c3c0d44cfe8de0cc6f644b98f98858433bea8bbe7b612c8aca5952fccce4f195f9d54f9722dc2", + "0x99663087e3d5000abbec0fbda4e7342ec38846cc6a1505191fb3f1a337cb369455b7f8531a6eb8b0f7b2c4baf83cbe2b", + "0xab0836c6377a4dbc7ca6a4d6cf021d4cd60013877314dd05f351706b128d4af6337711ed3443cb6ca976f40d74070a9a", + "0x87abfd5126152fd3bac3c56230579b489436755ea89e0566aa349490b36a5d7b85028e9fb0710907042bcde6a6f5d7e3", + "0x974ba1033f75f60e0cf7c718a57ae1da3721cf9d0fb925714c46f027632bdd84cd9e6de4cf4d00bc55465b1c5ebb7384", + "0xa607b49d73689ac64f25cec71221d30d53e781e1100d19a2114a21da6507a60166166369d860bd314acb226596525670", + "0xa7c2b0b915d7beba94954f2aa7dd08ec075813661e2a3ecca5d28a0733e59583247fed9528eb28aba55b972cdbaf06eb", + "0xb8b3123e44128cc8efbe3270f2f94e50ca214a4294c71c3b851f8cbb70cb67fe9536cf07d04bf7fe380e5e3a29dd3c15", + "0xa59a07e343b62ad6445a0859a32b58c21a593f9ddbfe52049650f59628c93715aa1f4e1f45b109321756d0eeec8a5429", + "0x94f51f8a4ed18a6030d0aaa8899056744bd0e9dc9ac68f62b00355cddab11da5da16798db75f0bfbce0e5bdfe750c0b6", + "0x97460a97ca1e1fa5ce243b81425edc0ec19b7448e93f0b55bc9785eedeeafe194a3c8b33a61a5c72990edf375f122777", + "0x8fa859a089bc17d698a7ee381f37ce9beadf4e5b44fce5f6f29762bc04f96faff5d58c48c73631290325f05e9a1ecf49", + "0xabdf38f3b20fc95eff31de5aa9ef1031abfa48f1305ee57e4d507594570401503476d3bcc493838fc24d6967a3082c7f", + "0xb8914bfb82815abb86da35c64d39ab838581bc0bf08967192697d9663877825f2b9d6fbdcf9b410463482b3731361aef", + "0xa8187f9d22b193a5f578999954d6ec9aa9b32338ccadb8a3e1ce5bad5ea361d69016e1cdfac44e9d6c54e49dd88561b9", + "0xaac262cb7cba7fd62c14daa7b39677cabc1ef0947dd06dd89cac8570006a200f90d5f0353e84f5ff03179e3bebe14231", + "0xa630ef5ece9733b8c46c0a2df14a0f37647a85e69c63148e79ffdcc145707053f9f9d305c3f1cf3c7915cb46d33abd07", + "0xb102c237cb2e254588b6d53350dfda6901bd99493a3fbddb4121d45e0b475cf2663a40d7b9a75325eda83e4ba1e68cb3", + "0x86a930dd1ddcc16d1dfa00aa292cb6c2607d42c367e470aa920964b7c17ab6232a7108d1c2c11fc40fb7496547d0bbf8", + "0xa832fdc4500683e72a96cce61e62ac9ee812c37fe03527ad4cf893915ca1962cee80e72d4f82b20c8fc0b764376635a1", + "0x88ad985f448dabb04f8808efd90f273f11f5e6d0468b5489a1a6a3d77de342992a73eb842d419034968d733f101ff683", + "0x98a8538145f0d86f7fbf9a81c9140f6095c5bdd8960b1c6f3a1716428cd9cca1bf8322e6d0af24e6169abcf7df2b0ff6", + "0x9048c6eba5e062519011e177e955a200b2c00b3a0b8615bdecdebc217559d41058d3315f6d05617be531ef0f6aef0e51", + "0x833bf225ab6fc68cdcacf1ec1b50f9d05f5410e6cdcd8d56a3081dc2be8a8d07b81534d1ec93a25c2e270313dfb99e3b", + "0xa84bcd24c3da5e537e64a811b93c91bfc84d7729b9ead7f79078989a6eb76717d620c1fad17466a0519208651e92f5ff", + "0xb7cdd0a3fbd79aed93e1b5a44ca44a94e7af5ed911e4492f332e3a5ed146c7286bde01b52276a2fcc02780d2109874dd", + "0x8a19a09854e627cb95750d83c20c67442b66b35896a476358f993ba9ac114d32c59c1b3d0b8787ee3224cf3888b56c64", + "0xa9abd5afb8659ee52ada8fa5d57e7dd355f0a7350276f6160bec5fbf70d5f99234dd179eb221c913e22a49ec6d267846", + "0x8c13c4274c0d30d184e73eaf812200094bbbd57293780bdadbceb262e34dee5b453991e7f37c7333a654fc71c69d6445", + "0xa4320d73296ff8176ce0127ca1921c450e2a9c06eff936681ebaffb5a0b05b17fded24e548454de89aca2dcf6d7a9de4", + "0xb2b8b3e15c1f645f07783e5628aba614e60157889db41d8161d977606788842b67f83f361eae91815dc0abd84e09abd5", + "0xad26c3aa35ddfddc15719b8bb6c264aaec7065e88ac29ba820eb61f220fef451609a7bb037f3722d022e6c86e4f1dc88", + "0xb8615bf43e13ae5d7b8dd903ce37190800cd490f441c09b22aa29d7a29ed2c0417b7a08ead417868f1de2589deaadd80", + "0x8d3425e1482cd1e76750a76239d33c06b3554c3c3c87c15cb7ab58b1cee86a4c5c4178b44e23f36928365a1b484bde02", + "0x806893a62e38c941a7dd6f249c83af16596f69877cc737d8f73f6b8cd93cbc01177a7a276b2b8c6b0e5f2ad864db5994", + "0x86618f17fa4b0d65496b661bbb5ba3bc3a87129d30a4b7d4f515b904f4206ca5253a41f49fd52095861e5e065ec54f21", + "0x9551915da1304051e55717f4c31db761dcdcf3a1366c89a4af800a9e99aca93a357bf928307f098e62b44a02cb689a46", + "0x8f79c4ec0ec1146cb2a523b52fe33def90d7b5652a0cb9c2d1c8808a32293e00aec6969f5b1538e3a94cd1efa3937f86", + "0xa0c03e329a707300081780f1e310671315b4c6a4cedcb29697aedfabb07a9d5df83f27b20e9c44cf6b16e39d9ded5b98", + "0x86a7cfa7c8e7ce2c01dd0baec2139e97e8e090ad4e7b5f51518f83d564765003c65968f85481bbb97cb18f005ccc7d9f", + "0xa33811770c6dfda3f7f74e6ad0107a187fe622d61b444bbd84fd7ef6e03302e693b093df76f6ab39bb4e02afd84a575a", + "0x85480f5c10d4162a8e6702b5e04f801874d572a62a130be94b0c02b58c3c59bdcd48cd05f0a1c2839f88f06b6e3cd337", + "0x8e181011564b17f7d787fe0e7f3c87f6b62da9083c54c74fd6c357a1f464c123c1d3d8ade3cf72475000b464b14e2be3", + "0x8ee178937294b8c991337e0621ab37e9ffa4ca2bdb3284065c5e9c08aad6785d50cf156270ff9daf9a9127289710f55b", + "0x8bd1e8e2d37379d4b172f1aec96f2e41a6e1393158d7a3dbd9a95c8dd4f8e0b05336a42efc11a732e5f22b47fc5c271d", + "0x8f3da353cd487c13136a85677de8cedf306faae0edec733cf4f0046f82fa4639db4745b0095ff33a9766aba50de0cbcf", + "0x8d187c1e97638df0e4792b78e8c23967dac43d98ea268ca4aabea4e0fa06cb93183fd92d4c9df74118d7cc27bf54415e", + "0xa4c992f08c2f8bac0b74b3702fb0c75c9838d2ce90b28812019553d47613c14d8ce514d15443159d700b218c5a312c49", + "0xa6fd1874034a34c3ea962a316c018d9493d2b3719bb0ec4edbc7c56b240802b2228ab49bee6f04c8a3e9f6f24a48c1c2", + "0xb2efed8e799f8a15999020900dc2c58ece5a3641c90811b86a5198e593d7318b9d53b167818ccdfbe7df2414c9c34011", + "0x995ff7de6181ddf95e3ead746089c6148da3508e4e7a2323c81785718b754d356789b902e7e78e2edc6b0cbd4ff22c78", + "0x944073d24750a9068cbd020b834afc72d2dde87efac04482b3287b40678ad07588519a4176b10f2172a2c463d063a5cd", + "0x99db4b1bb76475a6fd75289986ef40367960279524378cc917525fb6ba02a145a218c1e9caeb99332332ab486a125ac0", + "0x89fce4ecd420f8e477af4353b16faabb39e063f3f3c98fde2858b1f2d1ef6eed46f0975a7c08f233b97899bf60ccd60a", + "0x8c09a4f07a02b80654798bc63aada39fd638d3e3c4236ccd8a5ca280350c31e4a89e5f4c9aafb34116e71da18c1226b8", + "0x85325cfa7ded346cc51a2894257eab56e7488dbff504f10f99f4cd2b630d913003761a50f175ed167e8073f1b6b63fb0", + "0xb678b4fbec09a8cc794dcbca185f133578f29e354e99c05f6d07ac323be20aecb11f781d12898168e86f2e0f09aca15e", + "0xa249cfcbca4d9ba0a13b5f6aac72bf9b899adf582f9746bb2ad043742b28915607467eb794fca3704278f9136f7642be", + "0x9438e036c836a990c5e17af3d78367a75b23c37f807228362b4d13e3ddcb9e431348a7b552d09d11a2e9680704a4514f", + "0x925ab70450af28c21a488bfb5d38ac994f784cf249d7fd9ad251bb7fd897a23e23d2528308c03415074d43330dc37ef4", + "0xa290563904d5a8c0058fc8330120365bdd2ba1fdbaef7a14bc65d4961bb4217acfaed11ab82669e359531f8bf589b8db", + "0xa7e07a7801b871fc9b981a71e195a3b4ba6b6313bc132b04796a125157e78fe5c11a3a46cf731a255ac2d78a4ae78cd0", + "0xb26cd2501ee72718b0eebab6fb24d955a71f363f36e0f6dff0ab1d2d7836dab88474c0cef43a2cc32701fca7e82f7df3", + "0xa1dc3b6c968f3de00f11275092290afab65b2200afbcfa8ddc70e751fa19dbbc300445d6d479a81bda3880729007e496", + "0xa9bc213e28b630889476a095947d323b9ac6461dea726f2dc9084473ae8e196d66fb792a21905ad4ec52a6d757863e7d", + "0xb25d178df8c2df8051e7c888e9fa677fde5922e602a95e966db9e4a3d6b23ce043d7dc48a5b375c6b7c78e966893e8c3", + "0xa1c8d88d72303692eaa7adf68ea41de4febec40cc14ae551bb4012afd786d7b6444a3196b5d9d5040655a3366d96b7cd", + "0xb22bd44f9235a47118a9bbe2ba5a2ba9ec62476061be2e8e57806c1a17a02f9a51403e849e2e589520b759abd0117683", + "0xb8add766050c0d69fe81d8d9ea73e1ed05f0135d093ff01debd7247e42dbb86ad950aceb3b50b9af6cdc14ab443b238f", + "0xaf2cf95f30ef478f018cf81d70d47d742120b09193d8bb77f0d41a5d2e1a80bfb467793d9e2471b4e0ad0cb2c3b42271", + "0x8af5ef2107ad284e246bb56e20fef2a255954f72de791cbdfd3be09f825298d8466064f3c98a50496c7277af32b5c0bc", + "0x85dc19558572844c2849e729395a0c125096476388bd1b14fa7f54a7c38008fc93e578da3aac6a52ff1504d6ca82db05", + "0xae8c9b43c49572e2e166d704caf5b4b621a3b47827bb2a3bcd71cdc599bba90396fd9a405261b13e831bb5d44c0827d7", + "0xa7ba7efede25f02e88f6f4cbf70643e76784a03d97e0fbd5d9437c2485283ad7ca3abb638a5f826cd9f6193e5dec0b6c", + "0x94a9d122f2f06ef709fd8016fd4b712d88052245a65a301f5f177ce22992f74ad05552b1f1af4e70d1eac62cef309752", + "0x82d999b3e7cf563833b8bc028ff63a6b26eb357dfdb3fd5f10e33a1f80a9b2cfa7814d871b32a7ebfbaa09e753e37c02", + "0xaec6edcde234df502a3268dd2c26f4a36a2e0db730afa83173f9c78fcb2b2f75510a02b80194327b792811caefda2725", + "0x94c0bfa66c9f91d462e9194144fdd12d96f9bbe745737e73bab8130607ee6ea9d740e2cfcbbd00a195746edb6369ee61", + "0xab7573dab8c9d46d339e3f491cb2826cabe8b49f85f1ede78d845fc3995537d1b4ab85140b7d0238d9c24daf0e5e2a7e", + "0x87e8b16832843251fe952dadfd01d41890ed4bb4b8fa0254550d92c8cced44368225eca83a6c3ad47a7f81ff8a80c984", + "0x9189d2d9a7c64791b19c0773ad4f0564ce6bea94aa275a917f78ad987f150fdb3e5e26e7fef9982ac184897ecc04683f", + "0xb3661bf19e2da41415396ae4dd051a9272e8a2580b06f1a1118f57b901fa237616a9f8075af1129af4eabfefedbe2f1c", + "0xaf43c86661fb15daf5d910a4e06837225e100fb5680bd3e4b10f79a2144c6ec48b1f8d6e6b98e067d36609a5d038889a", + "0x82ac0c7acaa83ddc86c5b4249aae12f28155989c7c6b91e5137a4ce05113c6cbc16f6c44948b0efd8665362d3162f16a", + "0x8f268d1195ab465beeeb112cd7ffd5d5548559a8bc01261106d3555533fc1971081b25558d884d552df0db1cddda89d8", + "0x8ef7caa5521f3e037586ce8ac872a4182ee20c7921c0065ed9986c047e3dda08294da1165f385d008b40d500f07d895f", + "0x8c2f98f6880550573fad46075d3eba26634b5b025ce25a0b4d6e0193352c8a1f0661064027a70fe8190b522405f9f4e3", + "0xb7653f353564feb164f0f89ec7949da475b8dad4a4d396d252fc2a884f6932d027b7eb2dc4d280702c74569319ed701a", + "0xa026904f4066333befd9b87a8fad791d014096af60cdd668ef919c24dbe295ff31f7a790e1e721ba40cf5105abca67f4", + "0x988f982004ada07a22dd345f2412a228d7a96b9cae2c487de42e392afe1e35c2655f829ce07a14629148ce7079a1f142", + "0x9616add009067ed135295fb74d5b223b006b312bf14663e547a0d306694ff3a8a7bb9cfc466986707192a26c0bce599f", + "0xad4c425de9855f6968a17ee9ae5b15e0a5b596411388cf976df62ecc6c847a6e2ddb2cea792a5f6e9113c2445dba3e5c", + "0xb698ac9d86afa3dc69ff8375061f88e3b0cff92ff6dfe747cebaf142e813c011851e7a2830c10993b715e7fd594604a9", + "0xa386fa189847bb3b798efca917461e38ead61a08b101948def0f82cd258b945ed4d45b53774b400af500670149e601b7", + "0x905c95abda2c68a6559d8a39b6db081c68cef1e1b4be63498004e1b2f408409be9350b5b5d86a30fd443e2b3e445640a", + "0x9116dade969e7ce8954afcdd43e5cab64dc15f6c1b8da9d2d69de3f02ba79e6c4f6c7f54d6bf586d30256ae405cd1e41", + "0xa3084d173eacd08c9b5084a196719b57e47a0179826fda73466758235d7ecdb87cbcf097bd6b510517d163a85a7c7edd", + "0x85bb00415ad3c9be99ff9ba83672cc59fdd24356b661ab93713a3c8eab34e125d8867f628a3c3891b8dc056e69cd0e83", + "0x8d58541f9f39ed2ee4478acce5d58d124031338ec11b0d55551f00a5a9a6351faa903a5d7c132dc5e4bb026e9cbd18e4", + "0xa622adf72dc250e54f672e14e128c700166168dbe0474cecb340da175346e89917c400677b1bc1c11fcc4cc26591d9db", + "0xb3f865014754b688ca8372e8448114fff87bf3ca99856ab9168894d0c4679782c1ced703f5b74e851b370630f5e6ee86", + "0xa7e490b2c40c2446fcd91861c020da9742c326a81180e38110558bb5d9f2341f1c1885e79b364e6419023d1cbdc47380", + "0xb3748d472b1062e54572badbb8e87ac36534407f74932e7fc5b8392d008e8e89758f1671d1e4d30ab0fa40551b13bb5e", + "0x89898a5c5ec4313aabc607b0049fd1ebad0e0c074920cf503c9275b564d91916c2c446d3096491c950b7af3ac5e4b0ed", + "0x8eb8c83fef2c9dd30ea44e286e9599ec5c20aba983f702e5438afe2e5b921884327ad8d1566c72395587efac79ca7d56", + "0xb92479599e806516ce21fb0bd422a1d1d925335ebe2b4a0a7e044dd275f30985a72b97292477053ac5f00e081430da80", + "0xa34ae450a324fe8a3c25a4d653a654f9580ed56bbea213b8096987bbad0f5701d809a17076435e18017fea4d69f414bc", + "0x81381afe6433d62faf62ea488f39675e0091835892ecc238e02acf1662669c6d3962a71a3db652f6fe3bc5f42a0e5dc5", + "0xa430d475bf8580c59111103316fe1aa79c523ea12f1d47a976bbfae76894717c20220e31cf259f08e84a693da6688d70", + "0xb842814c359754ece614deb7d184d679d05d16f18a14b288a401cef5dad2cf0d5ee90bad487b80923fc5573779d4e4e8", + "0x971d9a2627ff2a6d0dcf2af3d895dfbafca28b1c09610c466e4e2bff2746f8369de7f40d65b70aed135fe1d72564aa88", + "0x8f4ce1c59e22b1ce7a0664caaa7e53735b154cfba8d2c5cc4159f2385843de82ab58ed901be876c6f7fce69cb4130950", + "0x86cc9dc321b6264297987000d344fa297ef45bcc2a4df04e458fe2d907ad304c0ea2318e32c3179af639a9a56f3263cf", + "0x8229e0876dfe8f665c3fb19b250bd89d40f039bbf1b331468b403655be7be2e104c2fd07b9983580c742d5462ca39a43", + "0x99299d73066e8eb128f698e56a9f8506dfe4bd014931e86b6b487d6195d2198c6c5bf15cccb40ccf1f8ddb57e9da44a2", + "0xa3a3be37ac554c574b393b2f33d0a32a116c1a7cfeaf88c54299a4da2267149a5ecca71f94e6c0ef6e2f472b802f5189", + "0xa91700d1a00387502cdba98c90f75fbc4066fefe7cc221c8f0e660994c936badd7d2695893fde2260c8c11d5bdcdd951", + "0x8e03cae725b7f9562c5c5ab6361644b976a68bada3d7ca508abca8dfc80a469975689af1fba1abcf21bc2a190dab397d", + "0xb01461ad23b2a8fa8a6d241e1675855d23bc977dbf4714add8c4b4b7469ccf2375cec20e80cedfe49361d1a30414ac5b", + "0xa2673bf9bc621e3892c3d7dd4f1a9497f369add8cbaa3472409f4f86bd21ac67cfac357604828adfee6ada1835365029", + "0xa042dff4bf0dfc33c178ba1b335e798e6308915128de91b12e5dbbab7c4ac8d60a01f6aea028c3a6d87b9b01e4e74c01", + "0x86339e8a75293e4b3ae66b5630d375736b6e6b6b05c5cda5e73fbf7b2f2bd34c18a1d6cefede08625ce3046e77905cb8", + "0xaf2ebe1b7d073d03e3d98bc61af83bf26f7a8c130fd607aa92b75db22d14d016481b8aa231e2c9757695f55b7224a27f", + "0xa00ee882c9685e978041fd74a2c465f06e2a42ffd3db659053519925be5b454d6f401e3c12c746e49d910e4c5c9c5e8c", + "0x978a781c0e4e264e0dad57e438f1097d447d891a1e2aa0d5928f79a9d5c3faae6f258bc94fdc530b7b2fa6a9932bb193", + "0xaa4b7ce2e0c2c9e9655bf21e3e5651c8503bce27483017b0bf476be743ba06db10228b3a4c721219c0779747f11ca282", + "0xb003d1c459dacbcf1a715551311e45d7dbca83a185a65748ac74d1800bbeaba37765d9f5a1a221805c571910b34ebca8", + "0x95b6e531b38648049f0d19de09b881baa1f7ea3b2130816b006ad5703901a05da57467d1a3d9d2e7c73fb3f2e409363c", + "0xa6cf9c06593432d8eba23a4f131bb7f72b9bd51ab6b4b772a749fe03ed72b5ced835a349c6d9920dba2a39669cb7c684", + "0xaa3d59f6e2e96fbb66195bc58c8704e139fa76cd15e4d61035470bd6e305db9f98bcbf61ac1b95e95b69ba330454c1b3", + "0xb57f97959c208361de6d7e86dff2b873068adb0f158066e646f42ae90e650079798f165b5cd713141cd3a2a90a961d9a", + "0xa76ee8ed9052f6a7a8c69774bb2597be182942f08115baba03bf8faaeaee526feba86120039fe8ca7b9354c3b6e0a8e6", + "0x95689d78c867724823f564627d22d25010f278674c6d2d0cdb10329169a47580818995d1d727ce46c38a1e47943ebb89", + "0xab676d2256c6288a88e044b3d9ffd43eb9d5aaee00e8fc60ac921395fb835044c71a26ca948e557fed770f52d711e057", + "0x96351c72785c32e5d004b6f4a1259fb8153d631f0c93fed172f18e8ba438fbc5585c1618deeabd0d6d0b82173c2e6170", + "0x93dd8d3db576418e22536eba45ab7f56967c6c97c64260d6cddf38fb19c88f2ec5cd0e0156f50e70855eee8a2b879ffd", + "0xad6ff16f40f6de3d7a737f8e6cebd8416920c4ff89dbdcd75eabab414af9a6087f83ceb9aff7680aa86bff98bd09c8cc", + "0x84de53b11671abc9c38710e19540c5c403817562aeb22a88404cdaff792c1180f717dbdfe8f54940c062c4d032897429", + "0x872231b9efa1cdd447b312099a5c164c560440a9441d904e70f5abfc3b2a0d16be9a01aca5e0a2599a61e19407587e3d", + "0x88f44ac27094a2aa14e9dc40b099ee6d68f97385950f303969d889ee93d4635e34dff9239103bdf66a4b7cbba3e7eb7a", + "0xa59afebadf0260e832f6f44468443562f53fbaf7bcb5e46e1462d3f328ac437ce56edbca617659ac9883f9e13261fad7", + "0xb1990e42743a88de4deeacfd55fafeab3bc380cb95de43ed623d021a4f2353530bcab9594389c1844b1c5ea6634c4555", + "0x85051e841149a10e83f56764e042182208591396d0ce78c762c4a413e6836906df67f38c69793e158d64fef111407ba3", + "0x9778172bbd9b1f2ec6bbdd61829d7b39a7df494a818e31c654bf7f6a30139899c4822c1bf418dd4f923243067759ce63", + "0x9355005b4878c87804fc966e7d24f3e4b02bed35b4a77369d01f25a3dcbff7621b08306b1ac85b76fe7b4a3eb5f839b1", + "0x8f9dc6a54fac052e236f8f0e1f571ac4b5308a43acbe4cc8183bce26262ddaf7994e41cf3034a4cbeca2c505a151e3b1", + "0x8cc59c17307111723fe313046a09e0e32ea0cce62c13814ab7c6408c142d6a0311d801be4af53fc9240523f12045f9ef", + "0x8e6057975ed40a1932e47dd3ac778f72ee2a868d8540271301b1aa6858de1a5450f596466494a3e0488be4fbeb41c840", + "0x812145efbd6559ae13325d56a15940ca4253b17e72a9728986b563bb5acc13ec86453796506ac1a8f12bd6f9e4a288c3", + "0x911da0a6d6489eb3dab2ec4a16e36127e8a291ae68a6c2c9de33e97f3a9b1f00da57a94e270a0de79ecc5ecb45d19e83", + "0xb72ea85973f4b2a7e6e71962b0502024e979a73c18a9111130e158541fa47bbaaf53940c8f846913a517dc69982ba9e1", + "0xa7a56ad1dbdc55f177a7ad1d0af78447dc2673291e34e8ab74b26e2e2e7d8c5fe5dc89e7ef60f04a9508847b5b3a8188", + "0xb52503f6e5411db5d1e70f5fb72ccd6463fa0f197b3e51ca79c7b5a8ab2e894f0030476ada72534fa4eb4e06c3880f90", + "0xb51c7957a3d18c4e38f6358f2237b3904618d58b1de5dec53387d25a63772e675a5b714ad35a38185409931157d4b529", + "0xb86b4266e719d29c043d7ec091547aa6f65bbf2d8d831d1515957c5c06513b72aa82113e9645ad38a7bc3f5383504fa6", + "0xb95b547357e6601667b0f5f61f261800a44c2879cf94e879def6a105b1ad2bbf1795c3b98a90d588388e81789bd02681", + "0xa58fd4c5ae4673fa350da6777e13313d5d37ed1dafeeb8f4f171549765b84c895875d9d3ae6a9741f3d51006ef81d962", + "0x9398dc348d078a604aadc154e6eef2c0be1a93bb93ba7fe8976edc2840a3a318941338cc4d5f743310e539d9b46613d2", + "0x902c9f0095014c4a2f0dccaaab543debba6f4cc82c345a10aaf4e72511725dbed7a34cd393a5f4e48a3e5142b7be84ed", + "0xa7c0447849bb44d04a0393a680f6cd390093484a79a147dd238f5d878030d1c26646d88211108e59fe08b58ad20c6fbd", + "0x80db045535d6e67a422519f5c89699e37098449d249698a7cc173a26ccd06f60238ae6cc7242eb780a340705c906790c", + "0x8e52b451a299f30124505de2e74d5341e1b5597bdd13301cc39b05536c96e4380e7f1b5c7ef076f5b3005a868657f17c", + "0x824499e89701036037571761e977654d2760b8ce21f184f2879fda55d3cda1e7a95306b8abacf1caa79d3cc075b9d27f", + "0x9049b956b77f8453d2070607610b79db795588c0cec12943a0f5fe76f358dea81e4f57a4692112afda0e2c05c142b26f", + "0x81911647d818a4b5f4990bfd4bc13bf7be7b0059afcf1b6839333e8569cdb0172fd2945410d88879349f677abaed5eb3", + "0xad4048f19b8194ed45b6317d9492b71a89a66928353072659f5ce6c816d8f21e69b9d1817d793effe49ca1874daa1096", + "0x8d22f7b2ddb31458661abd34b65819a374a1f68c01fc6c9887edeba8b80c65bceadb8f57a3eb686374004b836261ef67", + "0x92637280c259bc6842884db3d6e32602a62252811ae9b019b3c1df664e8809ffe86db88cfdeb8af9f46435c9ee790267", + "0xa2f416379e52e3f5edc21641ea73dc76c99f7e29ea75b487e18bd233856f4c0183429f378d2bfc6cd736d29d6cadfa49", + "0x882cb6b76dbdc188615dcf1a8439eba05ffca637dd25197508156e03c930b17b9fed2938506fdd7b77567cb488f96222", + "0xb68b621bb198a763fb0634eddb93ed4b5156e59b96c88ca2246fd1aea3e6b77ed651e112ac41b30cd361fadc011d385e", + "0xa3cb22f6b675a29b2d1f827cacd30df14d463c93c3502ef965166f20d046af7f9ab7b2586a9c64f4eae4fad2d808a164", + "0x8302d9ce4403f48ca217079762ce42cee8bc30168686bb8d3a945fbd5acd53b39f028dce757b825eb63af2d5ae41169d", + "0xb2eef1fbd1a176f1f4cd10f2988c7329abe4eb16c7405099fb92baa724ab397bc98734ef7d4b24c0f53dd90f57520d04", + "0xa1bbef0bd684a3f0364a66bde9b29326bac7aa3dde4caed67f14fb84fed3de45c55e406702f1495a3e2864d4ee975030", + "0x976acdb0efb73e3a3b65633197692dedc2adaed674291ae3df76b827fc866d214e9cac9ca46baefc4405ff13f953d936", + "0xb9fbf71cc7b6690f601f0b1c74a19b7d14254183a2daaafec7dc3830cba5ae173d854bbfebeca985d1d908abe5ef0cda", + "0x90591d7b483598c94e38969c4dbb92710a1a894bcf147807f1bcbd8aa3ac210b9f2be65519aa829f8e1ccdc83ad9b8cf", + "0xa30568577c91866b9c40f0719d46b7b3b2e0b4a95e56196ac80898a2d89cc67880e1229933f2cd28ee3286f8d03414d7", + "0x97589a88c3850556b359ec5e891f0937f922a751ac7c95949d3bbc7058c172c387611c0f4cb06351ef02e5178b3dd9e4", + "0x98e7bbe27a1711f4545df742f17e3233fbcc63659d7419e1ca633f104cb02a32c84f2fac23ca2b84145c2672f68077ab", + "0xa7ddb91636e4506d8b7e92aa9f4720491bb71a72dadc47c7f4410e15f93e43d07d2b371951a0e6a18d1bd087aa96a5c4", + "0xa7c006692227a06db40bceac3d5b1daae60b5692dd9b54772bedb5fea0bcc91cbcdb530cac31900ffc70c5b3ffadc969", + "0x8d3ec6032778420dfa8be52066ba0e623467df33e4e1901dbadd586c5d750f4ccde499b5197e26b9ea43931214060f69", + "0x8d9a8410518ea64f89df319bfd1fc97a0971cdb9ad9b11d1f8fe834042ea7f8dce4db56eeaf179ff8dda93b6db93e5ce", + "0xa3c533e9b3aa04df20b9ff635cb1154ce303e045278fcf3f10f609064a5445552a1f93989c52ce852fd0bbd6e2b6c22e", + "0x81934f3a7f8c1ae60ec6e4f212986bcc316118c760a74155d06ce0a8c00a9b9669ec4e143ca214e1b995e41271774fd9", + "0xab8e2d01a71192093ef8fafa7485e795567cc9db95a93fb7cc4cf63a391ef89af5e2bfad4b827fffe02b89271300407f", + "0x83064a1eaa937a84e392226f1a60b7cfad4efaa802f66de5df7498962f7b2649924f63cd9962d47906380b97b9fe80e1", + "0xb4f5e64a15c6672e4b55417ee5dc292dcf93d7ea99965a888b1cc4f5474a11e5b6520eacbcf066840b343f4ceeb6bf33", + "0xa63d278b842456ef15c278b37a6ea0f27c7b3ffffefca77c7a66d2ea06c33c4631eb242bbb064d730e70a8262a7b848a", + "0x83a41a83dbcdf0d22dc049de082296204e848c453c5ab1ba75aa4067984e053acf6f8b6909a2e1f0009ed051a828a73b", + "0x819485b036b7958508f15f3c19436da069cbe635b0318ebe8c014cf1ef9ab2df038c81161b7027475bcfa6fff8dd9faf", + "0xaa40e38172806e1e045e167f3d1677ef12d5dcdc89b43639a170f68054bd196c4fae34c675c1644d198907a03f76ba57", + "0x969bae484883a9ed1fbed53b26b3d4ee4b0e39a6c93ece5b3a49daa01444a1c25727dabe62518546f36b047b311b177c", + "0x80a9e73a65da99664988b238096a090d313a0ee8e4235bc102fa79bb337b51bb08c4507814eb5baec22103ec512eaab0", + "0x86604379aec5bddda6cbe3ef99c0ac3a3c285b0b1a15b50451c7242cd42ae6b6c8acb717dcca7917838432df93a28502", + "0xa23407ee02a495bed06aa7e15f94cfb05c83e6d6fba64456a9bbabfa76b2b68c5c47de00ba169e710681f6a29bb41a22", + "0x98cff5ecc73b366c6a01b34ac9066cb34f7eeaf4f38a5429bad2d07e84a237047e2a065c7e8a0a6581017dadb4695deb", + "0x8de9f68a938f441f3b7ab84bb1f473c5f9e5c9e139e42b7ccee1d254bd57d0e99c2ccda0f3198f1fc5737f6023dd204e", + "0xb0ce48d815c2768fb472a315cad86aa033d0e9ca506f146656e2941829e0acb735590b4fbc713c2d18d3676db0a954ac", + "0x82f485cdefd5642a6af58ac6817991c49fac9c10ace60f90b27f1788cc026c2fe8afc83cf499b3444118f9f0103598a8", + "0x82c24550ed512a0d53fc56f64cc36b553823ae8766d75d772dacf038c460f16f108f87a39ceef7c66389790f799dbab3", + "0x859ffcf1fe9166388316149b9acc35694c0ea534d43f09dae9b86f4aa00a23b27144dda6a352e74b9516e8c8d6fc809c", + "0xb8f7f353eec45da77fb27742405e5ad08d95ec0f5b6842025be9def3d9892f85eb5dd0921b41e6eff373618dba215bca", + "0x8ccca4436f9017e426229290f5cd05eac3f16571a4713141a7461acfe8ae99cd5a95bf5b6df129148693c533966145da", + "0xa2c67ecc19c0178b2994846fea4c34c327a5d786ac4b09d1d13549d5be5996d8a89021d63d65cb814923388f47cc3a03", + "0xaa0ff87d676b418ec08f5cbf577ac7e744d1d0e9ebd14615b550eb86931eafd2a36d4732cc5d6fab1713fd7ab2f6f7c0", + "0x8aef4730bb65e44efd6bb9441c0ae897363a2f3054867590a2c2ecf4f0224e578c7a67f10b40f8453d9f492ac15a9b2d", + "0x86a187e13d8fba5addcfdd5b0410cedd352016c930f913addd769ee09faa6be5ca3e4b1bdb417a965c643a99bd92be42", + "0xa0a4e9632a7a094b14b29b78cd9c894218cdf6783e61671e0203865dc2a835350f465fbaf86168f28af7c478ca17bc89", + "0xa8c7b02d8deff2cd657d8447689a9c5e2cd74ef57c1314ac4d69084ac24a7471954d9ff43fe0907d875dcb65fd0d3ce5", + "0x97ded38760aa7be6b6960b5b50e83b618fe413cbf2bcc1da64c05140bcc32f5e0e709cd05bf8007949953fac5716bad9", + "0xb0d293835a24d64c2ae48ce26e550b71a8c94a0883103757fb6b07e30747f1a871707d23389ba2b2065fa6bafe220095", + "0x8f9e291bf849feaa575592e28e3c8d4b7283f733d41827262367ea1c40f298c7bcc16505255a906b62bf15d9f1ba85fb", + "0x998f4e2d12708b4fd85a61597ca2eddd750f73c9e0c9b3cf0825d8f8e01f1628fd19797dcaed3b16dc50331fc6b8b821", + "0xb30d1f8c115d0e63bf48f595dd10908416774c78b3bbb3194192995154d80ea042d2e94d858de5f8aa0261b093c401fd", + "0xb5d9c75bb41f964cbff3f00e96d9f1480c91df8913f139f0d385d27a19f57a820f838eb728e46823cbff00e21c660996", + "0xa6edec90b5d25350e2f5f0518777634f9e661ec9d30674cf5b156c4801746d62517751d90074830ac0f4b09911c262f1", + "0x82f98da1264b6b75b8fbeb6a4d96d6a05b25c24db0d57ba3a38efe3a82d0d4e331b9fc4237d6494ccfe4727206457519", + "0xb89511843453cf4ecd24669572d6371b1e529c8e284300c43e0d5bb6b3aaf35aeb634b3cb5c0a2868f0d5e959c1d0772", + "0xa82bf065676583e5c1d3b81987aaae5542f522ba39538263a944bb33ea5b514c649344a96c0205a3b197a3f930fcda6c", + "0xa37b47ea527b7e06c460776aa662d9a49ff4149d3993f1a974b0dd165f7171770d189b0e2ea54fd5fccb6a14b116e68a", + "0xa1017677f97dda818274d47556d09d0e4ccacb23a252f82a6cfe78c630ad46fb9806307445a59fb61262182de3a2b29c", + "0xb01e9fcac239ba270e6877b79273ddd768bf8a51d2ed8a051b1c11e18eff3de5920e2fcbfbd26f06d381eddd3b1f1e1b", + "0x82fcd53d803b1c8e4ed76adc339b7f3a5962d37042b9683aabac7513ac68775d4a566a9460183926a6a95dbe7d551a1f", + "0xa763e78995d55cd21cdb7ef75d9642d6e1c72453945e346ab6690c20a4e1eeec61bb848ef830ae4b56182535e3c71d8f", + "0xb769f4db602251d4b0a1186782799bdcef66de33c110999a5775c50b349666ffd83d4c89714c4e376f2efe021a5cfdb2", + "0xa59cbd1b785efcfa6e83fc3b1d8cf638820bc0c119726b5368f3fba9dce8e3414204fb1f1a88f6c1ff52e87961252f97", + "0x95c8c458fd01aa23ecf120481a9c6332ebec2e8bb70a308d0576926a858457021c277958cf79017ddd86a56cacc2d7db", + "0x82eb41390800287ae56e77f2e87709de5b871c8bdb67c10a80fc65f3acb9f7c29e8fa43047436e8933f27449ea61d94d", + "0xb3ec25e3545eb83aed2a1f3558d1a31c7edde4be145ecc13b33802654b77dc049b4f0065069dd9047b051e52ab11dcdd", + "0xb78a0c715738f56f0dc459ab99e252e3b579b208142836b3c416b704ca1de640ca082f29ebbcee648c8c127df06f6b1e", + "0xa4083149432eaaf9520188ebf4607d09cf664acd1f471d4fb654476e77a9eaae2251424ffda78d09b6cb880df35c1219", + "0x8c52857d68d6e9672df3db2df2dbf46b516a21a0e8a18eec09a6ae13c1ef8f369d03233320dd1c2c0bbe00abfc1ea18b", + "0x8c856089488803066bff3f8d8e09afb9baf20cecc33c8823c1c0836c3d45498c3de37e87c016b705207f60d2b00f8609", + "0x831a3df39be959047b2aead06b4dcd3012d7b29417f642b83c9e8ce8de24a3dbbd29c6fdf55e2db3f7ea04636c94e403", + "0xaed84d009f66544addabe404bf6d65af7779ce140dc561ff0c86a4078557b96b2053b7b8a43432ffb18cd814f143b9da", + "0x93282e4d72b0aa85212a77b336007d8ba071eea17492da19860f1ad16c1ea8867ccc27ef5c37c74b052465cc11ea4f52", + "0xa7b78b8c8d057194e8d68767f1488363f77c77bddd56c3da2bc70b6354c7aa76247c86d51f7371aa38a4aa7f7e3c0bb7", + "0xb1c77283d01dcd1bde649b5b044eac26befc98ff57cbee379fb5b8e420134a88f2fc7f0bf04d15e1fbd45d29e7590fe6", + "0xa4aa8de70330a73b2c6458f20a1067eed4b3474829b36970a8df125d53bbdda4f4a2c60063b7cccb0c80fc155527652f", + "0x948a6c79ba1b8ad7e0bed2fae2f0481c4e41b4d9bbdd9b58164e28e9065700e83f210c8d5351d0212e0b0b68b345b3a5", + "0x86a48c31dcbbf7b082c92d28e1f613a2378a910677d7db3a349dc089e4a1e24b12eee8e8206777a3a8c64748840b7387", + "0x976adb1af21e0fc34148917cf43d933d7bfd3fd12ed6c37039dcd5a4520e3c6cf5868539ba5bf082326430deb8a4458d", + "0xb93e1a4476f2c51864bb4037e7145f0635eb2827ab91732b98d49b6c07f6ac443111aa1f1da76d1888665cb897c3834e", + "0x8afd46fb23bf869999fa19784b18a432a1f252d09506b8dbb756af900518d3f5f244989b3d7c823d9029218c655d3dc6", + "0x83f1e59e3abeed18cdc632921672673f1cb6e330326e11c4e600e13e0d5bc11bdc970ae12952e15103a706fe720bf4d6", + "0x90ce4cc660714b0b673d48010641c09c00fc92a2c596208f65c46073d7f349dd8e6e077ba7dcef9403084971c3295b76", + "0x8b09b0f431a7c796561ecf1549b85048564de428dac0474522e9558b6065fede231886bc108539c104ce88ebd9b5d1b0", + "0x85d6e742e2fb16a7b0ba0df64bc2c0dbff9549be691f46a6669bca05e89c884af16822b85faefefb604ec48c8705a309", + "0xa87989ee231e468a712c66513746fcf03c14f103aadca0eac28e9732487deb56d7532e407953ab87a4bf8961588ef7b0", + "0xb00da10efe1c29ee03c9d37d5918e391ae30e48304e294696b81b434f65cf8c8b95b9d1758c64c25e534d045ba28696f", + "0x91c0e1fb49afe46c7056400baa06dbb5f6e479db78ee37e2d76c1f4e88994357e257b83b78624c4ef6091a6c0eb8254d", + "0x883fb797c498297ccbf9411a3e727c3614af4eccde41619b773dc7f3259950835ee79453debf178e11dec4d3ada687a0", + "0xa14703347e44eb5059070b2759297fcfcfc60e6893c0373eea069388eba3950aa06f1c57cd2c30984a2d6f9e9c92c79e", + "0xafebc7585b304ceba9a769634adff35940e89cd32682c78002822aab25eec3edc29342b7f5a42a56a1fec67821172ad5", + "0xaea3ff3822d09dba1425084ca95fd359718d856f6c133c5fabe2b2eed8303b6e0ba0d8698b48b93136a673baac174fd9", + "0xaf2456a09aa777d9e67aa6c7c49a1845ea5cdda2e39f4c935c34a5f8280d69d4eec570446998cbbe31ede69a91e90b06", + "0x82cada19fed16b891ef3442bafd49e1f07c00c2f57b2492dd4ee36af2bd6fd877d6cb41188a4d6ce9ec8d48e8133d697", + "0x82a21034c832287f616619a37c122cee265cc34ae75e881fcaea4ea7f689f3c2bc8150bbf7dbcfd123522bfb7f7b1d68", + "0x86877217105f5d0ec3eeff0289fc2a70d505c9fdf7862e8159553ef60908fb1a27bdaf899381356a4ef4649072a9796c", + "0x82b196e49c6e861089a427c0b4671d464e9d15555ffb90954cd0d630d7ae02eb3d98ceb529d00719c2526cd96481355a", + "0xa29b41d0d43d26ce76d4358e0db2b77df11f56e389f3b084d8af70a636218bd3ac86b36a9fe46ec9058c26a490f887f7", + "0xa4311c4c20c4d7dd943765099c50f2fd423e203ccfe98ff00087d205467a7873762510cac5fdce7a308913ed07991ed7", + "0xb1f040fc5cc51550cb2c25cf1fd418ecdd961635a11f365515f0cb4ffb31da71f48128c233e9cc7c0cf3978d757ec84e", + "0xa9ebae46f86d3bd543c5f207ed0d1aed94b8375dc991161d7a271f01592912072e083e2daf30c146430894e37325a1b9", + "0x826418c8e17ad902b5fe88736323a47e0ca7a44bce4cbe27846ec8fe81de1e8942455dda6d30e192cdcc73e11df31256", + "0x85199db563427c5edcbac21f3d39fec2357be91fb571982ddcdc4646b446ad5ced84410de008cb47b3477ee0d532daf8", + "0xb7eed9cd400b2ca12bf1d9ae008214b8561fb09c8ad9ff959e626ffde00fee5ff2f5b6612e231f2a1a9b1646fcc575e3", + "0x8b40bf12501dcbac78f5a314941326bfcddf7907c83d8d887d0bb149207f85d80cd4dfbd7935439ea7b14ea39a3fded7", + "0x83e3041af302485399ba6cd5120e17af61043977083887e8d26b15feec4a6b11171ac5c06e6ad0971d4b58a81ff12af3", + "0x8f5b9a0eecc589dbf8c35a65d5e996a659277ef6ea509739c0cb7b3e2da9895e8c8012de662e5b23c5fa85d4a8f48904", + "0x835d71ed5e919d89d8e6455f234f3ff215462c4e3720c371ac8c75e83b19dfe3ae15a81547e4dc1138e5f5997f413cc9", + "0x8b7d2e4614716b1db18e9370176ea483e6abe8acdcc3dcdf5fb1f4d22ca55d652feebdccc171c6de38398d9f7bfdec7a", + "0x93eace72036fe57d019676a02acf3d224cf376f166658c1bf705db4f24295881d477d6fdd7916efcfceff8c7a063deda", + "0xb1ac460b3d516879a84bc886c54f020a9d799e7c49af3e4d7de5bf0d2793c852254c5d8fe5616147e6659512e5ccb012", + "0xacd0947a35cb167a48bcd9667620464b54ac0e78f9316b4aa92dcaab5422d7a732087e52e1c827faa847c6b2fe6e7766", + "0x94ac33d21c3d12ff762d32557860e911cd94d666609ddcc42161b9c16f28d24a526e8b10bb03137257a92cec25ae637d", + "0x832e02058b6b994eadd8702921486241f9a19e68ed1406dad545e000a491ae510f525ccf9d10a4bba91c68f2c53a0f58", + "0x9471035d14f78ff8f463b9901dd476b587bb07225c351161915c2e9c6114c3c78a501379ab6fb4eb03194c457cbd22bf", + "0xab64593e034c6241d357fcbc32d8ea5593445a5e7c24cac81ad12bd2ef01843d477a36dc1ba21dbe63b440750d72096a", + "0x9850f3b30045e927ad3ec4123a32ed2eb4c911f572b6abb79121873f91016f0d80268de8b12e2093a4904f6e6cab7642", + "0x987212c36b4722fe2e54fa30c52b1e54474439f9f35ca6ad33c5130cd305b8b54b532dd80ffd2c274105f20ce6d79f6e", + "0x8b4d0c6abcb239b5ed47bef63bc17efe558a27462c8208fa652b056e9eae9665787cd1aee34fbb55beb045c8bfdb882b", + "0xa9f3483c6fee2fe41312d89dd4355d5b2193ac413258993805c5cbbf0a59221f879386d3e7a28e73014f10e65dd503d9", + "0xa2225da3119b9b7c83d514b9f3aeb9a6d9e32d9cbf9309cbb971fd53c4b2c001d10d880a8ad8a7c281b21d85ceca0b7c", + "0xa050be52e54e676c151f7a54453bbb707232f849beab4f3bf504b4d620f59ed214409d7c2bd3000f3ff13184ccda1c35", + "0xadbccf681e15b3edb6455a68d292b0a1d0f5a4cb135613f5e6db9943f02181341d5755875db6ee474e19ace1c0634a28", + "0x8b6eff675632a6fad0111ec72aacc61c7387380eb87933fd1d098856387d418bd38e77d897e65d6fe35951d0627c550b", + "0xaabe2328ddf90989b15e409b91ef055cb02757d34987849ae6d60bef2c902bf8251ed21ab30acf39e500d1d511e90845", + "0x92ba4eb1f796bc3d8b03515f65c045b66e2734c2da3fc507fdd9d6b5d1e19ab3893726816a32141db7a31099ca817d96", + "0x8a98b3cf353138a1810beb60e946183803ef1d39ac4ea92f5a1e03060d35a4774a6e52b14ead54f6794d5f4022b8685c", + "0x909f8a5c13ec4a59b649ed3bee9f5d13b21d7f3e2636fd2bb3413c0646573fdf9243d63083356f12f5147545339fcd55", + "0x9359d914d1267633141328ed0790d81c695fea3ddd2d406c0df3d81d0c64931cf316fe4d92f4353c99ff63e2aefc4e34", + "0xb88302031681b54415fe8fbfa161c032ea345c6af63d2fb8ad97615103fd4d4281c5a9cae5b0794c4657b97571a81d3b", + "0x992c80192a519038082446b1fb947323005b275e25f2c14c33cc7269e0ec038581cc43705894f94bad62ae33a8b7f965", + "0xa78253e3e3eece124bef84a0a8807ce76573509f6861d0b6f70d0aa35a30a123a9da5e01e84969708c40b0669eb70aa6", + "0x8d5724de45270ca91c94792e8584e676547d7ac1ac816a6bb9982ee854eb5df071d20545cdfd3771cd40f90e5ba04c8e", + "0x825a6f586726c68d45f00ad0f5a4436523317939a47713f78fd4fe81cd74236fdac1b04ecd97c2d0267d6f4981d7beb1" + ], + "g2_monomial": [ + "0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8", + "0xb5bfd7dd8cdeb128843bc287230af38926187075cbfbefa81009a2ce615ac53d2914e5870cb452d2afaaab24f3499f72185cbfee53492714734429b7b38608e23926c911cceceac9a36851477ba4c60b087041de621000edc98edada20c1def2", + "0xb5337ba0ce5d37224290916e268e2060e5c14f3f9fc9e1ec3af5a958e7a0303122500ce18f1a4640bf66525bd10e763501fe986d86649d8d45143c08c3209db3411802c226e9fe9a55716ac4a0c14f9dcef9e70b2bb309553880dc5025eab3cc", + "0xb3c1dcdc1f62046c786f0b82242ef283e7ed8f5626f72542aa2c7a40f14d9094dd1ebdbd7457ffdcdac45fd7da7e16c51200b06d791e5e43e257e45efdf0bd5b06cd2333beca2a3a84354eb48662d83aef5ecf4e67658c851c10b13d8d87c874", + "0x954d91c7688983382609fca9e211e461f488a5971fd4e40d7e2892037268eacdfd495cfa0a7ed6eb0eb11ac3ae6f651716757e7526abe1e06c64649d80996fd3105c20c4c94bc2b22d97045356fe9d791f21ea6428ac48db6f9e68e30d875280", + "0x88a6b6bb26c51cf9812260795523973bb90ce80f6820b6c9048ab366f0fb96e48437a7f7cb62aedf64b11eb4dfefebb0147608793133d32003cb1f2dc47b13b5ff45f1bb1b2408ea45770a08dbfaec60961acb8119c47b139a13b8641e2c9487", + "0x85cd7be9728bd925d12f47fb04b32d9fad7cab88788b559f053e69ca18e463113ecc8bbb6dbfb024835f901b3a957d3108d6770fb26d4c8be0a9a619f6e3a4bf15cbfd48e61593490885f6cee30e4300c5f9cf5e1c08e60a2d5b023ee94fcad0", + "0x80477dba360f04399821a48ca388c0fa81102dd15687fea792ee8c1114e00d1bc4839ad37ac58900a118d863723acfbe08126ea883be87f50e4eabe3b5e72f5d9e041db8d9b186409fd4df4a7dde38c0e0a3b1ae29b098e5697e7f110b6b27e4", + "0xb7a6aec08715a9f8672a2b8c367e407be37e59514ac19dd4f0942a68007bba3923df22da48702c63c0d6b3efd3c2d04e0fe042d8b5a54d562f9f33afc4865dcbcc16e99029e25925580e87920c399e710d438ac1ce3a6dc9b0d76c064a01f6f7", + "0xac1b001edcea02c8258aeffbf9203114c1c874ad88dae1184fadd7d94cd09053649efd0ca413400e6e9b5fa4eac33261000af88b6bd0d2abf877a4f0355d2fb4d6007adb181695201c5432e50b850b51b3969f893bddf82126c5a71b042b7686", + "0x90043fda4de53fb364fab2c04be5296c215599105ecff0c12e4917c549257125775c29f2507124d15f56e30447f367db0596c33237242c02d83dfd058735f1e3c1ff99069af55773b6d51d32a68bf75763f59ec4ee7267932ae426522b8aaab6", + "0xa8660ce853e9dc08271bf882e29cd53397d63b739584dda5263da4c7cc1878d0cf6f3e403557885f557e184700575fee016ee8542dec22c97befe1d10f414d22e84560741cdb3e74c30dda9b42eeaaf53e27822de2ee06e24e912bf764a9a533", + "0x8fe3921a96d0d065e8aa8fce9aa42c8e1461ca0470688c137be89396dd05103606dab6cdd2a4591efd6addf72026c12e065da7be276dee27a7e30afa2bd81c18f1516e7f068f324d0bad9570b95f6bd02c727cd2343e26db0887c3e4e26dceda", + "0x8ae1ad97dcb9c192c9a3933541b40447d1dc4eebf380151440bbaae1e120cc5cdf1bcea55180b128d8e180e3af623815191d063cc0d7a47d55fb7687b9d87040bf7bc1a7546b07c61db5ccf1841372d7c2fe4a5431ffff829f3c2eb590b0b710", + "0x8c2fa96870a88150f7876c931e2d3cc2adeaaaf5c73ef5fa1cf9dfa0991ae4819f9321af7e916e5057d87338e630a2f21242c29d76963cf26035b548d2a63d8ad7bd6efefa01c1df502cbdfdfe0334fb21ceb9f686887440f713bf17a89b8081", + "0xb9aa98e2f02bb616e22ee5dd74c7d1049321ac9214d093a738159850a1dbcc7138cb8d26ce09d8296368fd5b291d74fa17ac7cc1b80840fdd4ee35e111501e3fa8485b508baecda7c1ab7bd703872b7d64a2a40b3210b6a70e8a6ffe0e5127e3", + "0x9292db67f8771cdc86854a3f614a73805bf3012b48f1541e704ea4015d2b6b9c9aaed36419769c87c49f9e3165f03edb159c23b3a49c4390951f78e1d9b0ad997129b17cdb57ea1a6638794c0cca7d239f229e589c5ae4f9fe6979f7f8cba1d7", + "0x91cd9e86550f230d128664f7312591fee6a84c34f5fc7aed557bcf986a409a6de722c4330453a305f06911d2728626e611acfdf81284f77f60a3a1595053a9479964fd713117e27c0222cc679674b03bc8001501aaf9b506196c56de29429b46", + "0xa9516b73f605cc31b89c68b7675dc451e6364595243d235339437f556cf22d745d4250c1376182273be2d99e02c10eee047410a43eff634d051aeb784e76cb3605d8e079b9eb6ad1957dfdf77e1cd32ce4a573c9dfcc207ca65af6eb187f6c3d", + "0xa9667271f7d191935cc8ad59ef3ec50229945faea85bfdfb0d582090f524436b348aaa0183b16a6231c00332fdac2826125b8c857a2ed9ec66821cfe02b3a2279be2412441bc2e369b255eb98614e4be8490799c4df22f18d47d24ec70bba5f7", + "0xa4371144d2aa44d70d3cb9789096d3aa411149a6f800cb46f506461ee8363c8724667974252f28aea61b6030c05930ac039c1ee64bb4bd56532a685cae182bf2ab935eee34718cffcb46cae214c77aaca11dbb1320faf23c47247db1da04d8dc", + "0x89a7eb441892260b7e81168c386899cd84ffc4a2c5cad2eae0d1ab9e8b5524662e6f660fe3f8bfe4c92f60b060811bc605b14c5631d16709266886d7885a5eb5930097127ec6fb2ebbaf2df65909cf48f253b3d5e22ae48d3e9a2fd2b01f447e", + "0x9648c42ca97665b5eccb49580d8532df05eb5a68db07f391a2340769b55119eaf4c52fe4f650c09250fa78a76c3a1e271799b8333cc2628e3d4b4a6a3e03da1f771ecf6516dd63236574a7864ff07e319a6f11f153406280d63af9e2b5713283", + "0x9663bf6dd446ea7a90658ee458578d4196dc0b175ef7fcfa75f44d41670850774c2e46c5a6be132a2c072a3c0180a24f0305d1acac49d2d79878e5cda80c57feda3d01a6af12e78b5874e2a4b3717f11c97503b41a4474e2e95b179113726199", + "0xb212aeb4814e0915b432711b317923ed2b09e076aaf558c3ae8ef83f9e15a83f9ea3f47805b2750ab9e8106cb4dc6ad003522c84b03dc02829978a097899c773f6fb31f7fe6b8f2d836d96580f216fec20158f1590c3e0d7850622e15194db05", + "0x925f005059bf07e9ceccbe66c711b048e236ade775720d0fe479aebe6e23e8af281225ad18e62458dc1b03b42ad4ca290d4aa176260604a7aad0d9791337006fbdebe23746f8060d42876f45e4c83c3643931392fde1cd13ff8bddf8111ef974", + "0x9553edb22b4330c568e156a59ef03b26f5c326424f830fe3e8c0b602f08c124730ffc40bc745bec1a22417adb22a1a960243a10565c2be3066bfdb841d1cd14c624cd06e0008f4beb83f972ce6182a303bee3fcbcabc6cfe48ec5ae4b7941bfc", + "0x935f5a404f0a78bdcce709899eda0631169b366a669e9b58eacbbd86d7b5016d044b8dfc59ce7ed8de743ae16c2343b50e2f925e88ba6319e33c3fc76b314043abad7813677b4615c8a97eb83cc79de4fedf6ccbcfa4d4cbf759a5a84e4d9742", + "0xa5b014ab936eb4be113204490e8b61cd38d71da0dec7215125bcd131bf3ab22d0a32ce645bca93e7b3637cf0c2db3d6601a0ddd330dc46f9fae82abe864ffc12d656c88eb50c20782e5bb6f75d18760666f43943abb644b881639083e122f557", + "0x935b7298ae52862fa22bf03bfc1795b34c70b181679ae27de08a9f5b4b884f824ef1b276b7600efa0d2f1d79e4a470d51692fd565c5cf8343dd80e5d3336968fc21c09ba9348590f6206d4424eb229e767547daefa98bc3aa9f421158dee3f2a", + "0x9830f92446e708a8f6b091cc3c38b653505414f8b6507504010a96ffda3bcf763d5331eb749301e2a1437f00e2415efb01b799ad4c03f4b02de077569626255ac1165f96ea408915d4cf7955047620da573e5c439671d1fa5c833fb11de7afe6", + "0x840dcc44f673fff3e387af2bb41e89640f2a70bcd2b92544876daa92143f67c7512faf5f90a04b7191de01f3e2b1bde00622a20dc62ca23bbbfaa6ad220613deff43908382642d4d6a86999f662efd64b1df448b68c847cfa87630a3ffd2ec76", + "0x92950c895ed54f7f876b2fda17ecc9c41b7accfbdd42c210cc5b475e0737a7279f558148531b5c916e310604a1de25a80940c94fe5389ae5d6a5e9c371be67bceea1877f5401725a6595bcf77ece60905151b6dfcb68b75ed2e708c73632f4fd", + "0x8010246bf8e94c25fd029b346b5fbadb404ef6f44a58fd9dd75acf62433d8cc6db66974f139a76e0c26dddc1f329a88214dbb63276516cf325c7869e855d07e0852d622c332ac55609ba1ec9258c45746a2aeb1af0800141ee011da80af175d4", + "0xb0f1bad257ebd187bdc3f37b23f33c6a5d6a8e1f2de586080d6ada19087b0e2bf23b79c1b6da1ee82271323f5bdf3e1b018586b54a5b92ab6a1a16bb3315190a3584a05e6c37d5ca1e05d702b9869e27f513472bcdd00f4d0502a107773097da", + "0x9636d24f1ede773ce919f309448dd7ce023f424afd6b4b69cb98c2a988d849a283646dc3e469879daa1b1edae91ae41f009887518e7eb5578f88469321117303cd3ac2d7aee4d9cb5f82ab9ae3458e796dfe7c24284b05815acfcaa270ff22e2", + "0xb373feb5d7012fd60578d7d00834c5c81df2a23d42794fed91aa9535a4771fde0341c4da882261785e0caca40bf83405143085e7f17e55b64f6c5c809680c20b050409bf3702c574769127c854d27388b144b05624a0e24a1cbcc4d08467005b", + "0xb15680648949ce69f82526e9b67d9b55ce5c537dc6ab7f3089091a9a19a6b90df7656794f6edc87fb387d21573ffc847062623685931c2790a508cbc8c6b231dd2c34f4d37d4706237b1407673605a604bcf6a50cc0b1a2db20485e22b02c17e", + "0x8817e46672d40c8f748081567b038a3165f87994788ec77ee8daea8587f5540df3422f9e120e94339be67f186f50952504cb44f61e30a5241f1827e501b2de53c4c64473bcc79ab887dd277f282fbfe47997a930dd140ac08b03efac88d81075", + "0xa6e4ef6c1d1098f95aae119905f87eb49b909d17f9c41bcfe51127aa25fee20782ea884a7fdf7d5e9c245b5a5b32230b07e0dbf7c6743bf52ee20e2acc0b269422bd6cf3c07115df4aa85b11b2c16630a07c974492d9cdd0ec325a3fabd95044", + "0x8634aa7c3d00e7f17150009698ce440d8e1b0f13042b624a722ace68ead870c3d2212fbee549a2c190e384d7d6ac37ce14ab962c299ea1218ef1b1489c98906c91323b94c587f1d205a6edd5e9d05b42d591c26494a6f6a029a2aadb5f8b6f67", + "0x821a58092900bdb73decf48e13e7a5012a3f88b06288a97b855ef51306406e7d867d613d9ec738ebacfa6db344b677d21509d93f3b55c2ebf3a2f2a6356f875150554c6fff52e62e3e46f7859be971bf7dd9d5b3e1d799749c8a97c2e04325df", + "0x8dba356577a3a388f782e90edb1a7f3619759f4de314ad5d95c7cc6e197211446819c4955f99c5fc67f79450d2934e3c09adefc91b724887e005c5190362245eec48ce117d0a94d6fa6db12eda4ba8dde608fbbd0051f54dcf3bb057adfb2493", + "0xa32a690dc95c23ed9fb46443d9b7d4c2e27053a7fcc216d2b0020a8cf279729c46114d2cda5772fd60a97016a07d6c5a0a7eb085a18307d34194596f5b541cdf01b2ceb31d62d6b55515acfd2b9eec92b27d082fbc4dc59fc63b551eccdb8468", + "0xa040f7f4be67eaf0a1d658a3175d65df21a7dbde99bfa893469b9b43b9d150fc2e333148b1cb88cfd0447d88fa1a501d126987e9fdccb2852ecf1ba907c2ca3d6f97b055e354a9789854a64ecc8c2e928382cf09dda9abde42bbdf92280cdd96", + "0x864baff97fa60164f91f334e0c9be00a152a416556b462f96d7c43b59fe1ebaff42f0471d0bf264976f8aa6431176eb905bd875024cf4f76c13a70bede51dc3e47e10b9d5652d30d2663b3af3f08d5d11b9709a0321aba371d2ef13174dcfcaf", + "0x95a46f32c994133ecc22db49bad2c36a281d6b574c83cfee6680b8c8100466ca034b815cfaedfbf54f4e75188e661df901abd089524e1e0eb0bf48d48caa9dd97482d2e8c1253e7e8ac250a32fd066d5b5cb08a8641bdd64ecfa48289dca83a3", + "0xa2cce2be4d12144138cb91066e0cd0542c80b478bf467867ebef9ddaf3bd64e918294043500bf5a9f45ee089a8d6ace917108d9ce9e4f41e7e860cbce19ac52e791db3b6dde1c4b0367377b581f999f340e1d6814d724edc94cb07f9c4730774", + "0xb145f203eee1ac0a1a1731113ffa7a8b0b694ef2312dabc4d431660f5e0645ef5838e3e624cfe1228cfa248d48b5760501f93e6ab13d3159fc241427116c4b90359599a4cb0a86d0bb9190aa7fabff482c812db966fd2ce0a1b48cb8ac8b3bca", + "0xadabe5d215c608696e03861cbd5f7401869c756b3a5aadc55f41745ad9478145d44393fec8bb6dfc4ad9236dc62b9ada0f7ca57fe2bae1b71565dbf9536d33a68b8e2090b233422313cc96afc7f1f7e0907dc7787806671541d6de8ce47c4cd0", + "0xae7845fa6b06db53201c1080e01e629781817f421f28956589c6df3091ec33754f8a4bd4647a6bb1c141ac22731e3c1014865d13f3ed538dcb0f7b7576435133d9d03be655f8fbb4c9f7d83e06d1210aedd45128c2b0c9bab45a9ddde1c862a5", + "0x9159eaa826a24adfa7adf6e8d2832120ebb6eccbeb3d0459ffdc338548813a2d239d22b26451fda98cc0c204d8e1ac69150b5498e0be3045300e789bcb4e210d5cd431da4bdd915a21f407ea296c20c96608ded0b70d07188e96e6c1a7b9b86b", + "0xa9fc6281e2d54b46458ef564ffaed6944bff71e389d0acc11fa35d3fcd8e10c1066e0dde5b9b6516f691bb478e81c6b20865281104dcb640e29dc116daae2e884f1fe6730d639dbe0e19a532be4fb337bf52ae8408446deb393d224eee7cfa50", + "0x84291a42f991bfb36358eedead3699d9176a38f6f63757742fdbb7f631f2c70178b1aedef4912fed7b6cf27e88ddc7eb0e2a6aa4b999f3eb4b662b93f386c8d78e9ac9929e21f4c5e63b12991fcde93aa64a735b75b535e730ff8dd2abb16e04", + "0xa1b7fcacae181495d91765dfddf26581e8e39421579c9cbd0dd27a40ea4c54af3444a36bf85a11dda2114246eaddbdd619397424bb1eb41b5a15004b902a590ede5742cd850cf312555be24d2df8becf48f5afba5a8cd087cb7be0a521728386", + "0x92feaaf540dbd84719a4889a87cdd125b7e995a6782911931fef26da9afcfbe6f86aaf5328fe1f77631491ce6239c5470f44c7791506c6ef1626803a5794e76d2be0af92f7052c29ac6264b7b9b51f267ad820afc6f881460521428496c6a5f1", + "0xa525c925bfae1b89320a5054acc1fa11820f73d0cf28d273092b305467b2831fab53b6daf75fb926f332782d50e2522a19edcd85be5eb72f1497193c952d8cd0bcc5d43b39363b206eae4cb1e61668bde28a3fb2fc1e0d3d113f6dfadb799717", + "0x98752bb6f5a44213f40eda6aa4ff124057c1b13b6529ab42fe575b9afa66e59b9c0ed563fb20dff62130c436c3e905ee17dd8433ba02c445b1d67182ab6504a90bbe12c26a754bbf734665c622f76c62fe2e11dd43ce04fd2b91a8463679058b", + "0xa9aa9a84729f7c44219ff9e00e651e50ddea3735ef2a73fdf8ed8cd271961d8ed7af5cd724b713a89a097a3fe65a3c0202f69458a8b4c157c62a85668b12fc0d3957774bc9b35f86c184dd03bfefd5c325da717d74192cc9751c2073fe9d170e", + "0xb221c1fd335a4362eff504cd95145f122bf93ea02ae162a3fb39c75583fc13a932d26050e164da97cff3e91f9a7f6ff80302c19dd1916f24acf6b93b62f36e9665a8785413b0c7d930c7f1668549910f849bca319b00e59dd01e5dec8d2edacc", + "0xa71e2b1e0b16d754b848f05eda90f67bedab37709550171551050c94efba0bfc282f72aeaaa1f0330041461f5e6aa4d11537237e955e1609a469d38ed17f5c2a35a1752f546db89bfeff9eab78ec944266f1cb94c1db3334ab48df716ce408ef", + "0xb990ae72768779ba0b2e66df4dd29b3dbd00f901c23b2b4a53419226ef9232acedeb498b0d0687c463e3f1eead58b20b09efcefa566fbfdfe1c6e48d32367936142d0a734143e5e63cdf86be7457723535b787a9cfcfa32fe1d61ad5a2617220", + "0x8d27e7fbff77d5b9b9bbc864d5231fecf817238a6433db668d5a62a2c1ee1e5694fdd90c3293c06cc0cb15f7cbeab44d0d42be632cb9ff41fc3f6628b4b62897797d7b56126d65b694dcf3e298e3561ac8813fbd7296593ced33850426df42db", + "0xa92039a08b5502d5b211a7744099c9f93fa8c90cedcb1d05e92f01886219dd464eb5fb0337496ad96ed09c987da4e5f019035c5b01cc09b2a18b8a8dd419bc5895388a07e26958f6bd26751929c25f89b8eb4a299d822e2d26fec9ef350e0d3c", + "0x92dcc5a1c8c3e1b28b1524e3dd6dbecd63017c9201da9dbe077f1b82adc08c50169f56fc7b5a3b28ec6b89254de3e2fd12838a761053437883c3e01ba616670cea843754548ef84bcc397de2369adcca2ab54cd73c55dc68d87aec3fc2fe4f10" + ] +} \ No newline at end of file diff --git a/arbitrator/prover/src/kzg.rs b/arbitrator/prover/src/kzg.rs new file mode 100644 index 000000000..7ab21e5ee --- /dev/null +++ b/arbitrator/prover/src/kzg.rs @@ -0,0 +1,59 @@ +// Copyright 2022-2024, Offchain Labs, Inc. +// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE + +use c_kzg::{KzgSettings, BYTES_PER_G1_POINT, BYTES_PER_G2_POINT}; +use num::BigUint; +use serde::{de::Error as _, Deserialize}; + +struct HexBytes; + +impl<'de, const N: usize> serde_with::DeserializeAs<'de, [u8; N]> for HexBytes { + fn deserialize_as(deserializer: D) -> Result<[u8; N], D::Error> + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + let mut s = s.as_str(); + if s.starts_with("0x") { + s = &s[2..]; + } + let mut bytes = [0; N]; + match hex::decode_to_slice(s, &mut bytes) { + Ok(()) => Ok(bytes), + Err(err) => Err(D::Error::custom(err.to_string())), + } + } +} + +#[derive(Deserialize)] +struct TrustedSetup { + #[serde(with = "serde_with::As::>")] + g1_lagrange: Vec<[u8; BYTES_PER_G1_POINT]>, + #[serde(with = "serde_with::As::>")] + g2_monomial: Vec<[u8; BYTES_PER_G2_POINT]>, +} + +const FIELD_ELEMENTS_PER_BLOB: usize = 4096; + +lazy_static::lazy_static! { + pub static ref ETHEREUM_KZG_SETTINGS: KzgSettings = { + let trusted_setup = serde_json::from_str::(include_str!("kzg-trusted-setup.json")) + .expect("Failed to deserialize Ethereum trusted setup"); + KzgSettings::load_trusted_setup(&trusted_setup.g1_lagrange, &trusted_setup.g2_monomial) + .expect("Failed to load Ethereum trusted setup") + }; + + pub static ref BLS_MODULUS: BigUint = "52435875175126190479447740508185965837690552500527637822603658699938581184513".parse().unwrap(); + pub static ref ROOT_OF_UNITY: BigUint = { + // order 2^32 + let root: BigUint = "10238227357739495823651030575849232062558860180284477541189508159991286009131".parse().unwrap(); + let exponent = (1_u64 << 32) / (FIELD_ELEMENTS_PER_BLOB as u64); + root.modpow(&BigUint::from(exponent), &*BLS_MODULUS) + }; +} + +#[cfg(test)] +#[test] +fn load_trusted_setup() { + let _: &KzgSettings = &*ETHEREUM_KZG_SETTINGS; +} diff --git a/arbitrator/prover/src/lib.rs b/arbitrator/prover/src/lib.rs index e4ea7a06c..8285c011d 100644 --- a/arbitrator/prover/src/lib.rs +++ b/arbitrator/prover/src/lib.rs @@ -5,6 +5,7 @@ pub mod binary; mod host; +mod kzg; pub mod machine; /// cbindgen:ignore mod memory; diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index 0849312f3..23ab7bbfc 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -4,6 +4,7 @@ use crate::{ binary::{parse, FloatInstruction, Local, NameCustomSection, WasmBinary}, host, + kzg::{BLS_MODULUS, ETHEREUM_KZG_SETTINGS, ROOT_OF_UNITY}, memory::Memory, merkle::{Merkle, MerkleType}, reinterpret::{ReinterpretAsSigned, ReinterpretAsUnsigned}, @@ -15,13 +16,15 @@ use crate::{ }, }; use arbutil::{Color, PreimageType}; +use c_kzg::FIELD_ELEMENTS_PER_BLOB; use digest::Digest; use eyre::{bail, ensure, eyre, Result, WrapErr}; use fnv::FnvHashMap as HashMap; -use num::{traits::PrimInt, Zero}; +use num::{traits::PrimInt, BigUint, Zero}; use rayon::prelude::*; use serde::{Deserialize, Serialize}; use serde_with::serde_as; +use sha2::Sha256; use sha3::Keccak256; use smallvec::SmallVec; use std::{ @@ -1865,10 +1868,24 @@ impl Machine { let offset = self.value_stack.pop().unwrap().assume_u32(); let ptr = self.value_stack.pop().unwrap().assume_u32(); let preimage_ty = PreimageType::try_from(u8::try_from(inst.argument_data)?)?; + // Preimage reads must be word aligned + if offset % 32 != 0 { + error!(); + } if let Some(hash) = module.memory.load_32_byte_aligned(ptr.into()) { if let Some(preimage) = self.preimage_resolver.get(self.context, preimage_ty, hash) { + if preimage_ty == PreimageType::EthVersionedHash + && preimage.len() != 32 * FIELD_ELEMENTS_PER_BLOB + { + bail!( + "kzg hash {} preimage should be {} bytes long but is instead {}", + hash, + 32 * FIELD_ELEMENTS_PER_BLOB, + preimage.len(), + ); + } let offset = usize::try_from(offset).unwrap(); let len = std::cmp::min(32, preimage.len().saturating_sub(offset)); let read = preimage.get(offset..(offset + len)).unwrap_or_default(); @@ -2269,6 +2286,11 @@ impl Machine { next_inst.opcode, Opcode::ReadPreImage | Opcode::ReadInboxMessage, ) { + let offset = self + .value_stack + .get(self.value_stack.len() - 1) + .unwrap() + .assume_u32(); let ptr = self .value_stack .get(self.value_stack.len() - 2) @@ -2296,7 +2318,70 @@ impl Machine { None => panic!("Missing requested preimage for hash {}", hash), }; data.push(0); // preimage proof type - data.extend(preimage); + match preimage_ty { + PreimageType::Keccak256 | PreimageType::Sha2_256 => { + // The proofs for these preimage types are just the raw preimages. + data.extend(preimage); + } + PreimageType::EthVersionedHash => { + let blob = c_kzg::Blob::from_bytes(&preimage) + .expect("Failed to generate KZG blob from preimage"); + let commitment = c_kzg::KzgCommitment::blob_to_kzg_commitment( + &blob, + ÐEREUM_KZG_SETTINGS, + ) + .expect("Failed to generate KZG commitment from blob"); + let mut expected_hash: Bytes32 = + Sha256::digest(&*commitment).into(); + expected_hash[0] = 1; + if hash != expected_hash { + panic!( + "Trying to prove versioned hash {} preimage but recomputed hash {}", + hash, + expected_hash, + ); + } + if offset % 32 != 0 { + panic!( + "Cannot prove blob preimage at unaligned offset {}", + offset, + ); + } + let offset_usize = usize::try_from(offset).unwrap(); + let mut proving_offset = offset; + let proving_past_end = offset_usize >= preimage.len(); + if proving_past_end { + // Proving any offset proves the length which is all we need here, + // because we're past the end of the preimage. + proving_offset = 0; + } + let exp = (proving_offset / 32).reverse_bits() + >> (u32::BITS - FIELD_ELEMENTS_PER_BLOB.trailing_zeros()); + let z = ROOT_OF_UNITY.modpow(&BigUint::from(exp), &BLS_MODULUS); + let z_bytes = z.to_bytes_be(); + let mut padded_z_bytes = [0u8; 32]; + padded_z_bytes[32 - z_bytes.len()..].copy_from_slice(&z_bytes); + let z_bytes = c_kzg::Bytes32::from(padded_z_bytes); + let (kzg_proof, proven_y) = c_kzg::KzgProof::compute_kzg_proof( + &blob, + &z_bytes, + ÐEREUM_KZG_SETTINGS, + ) + .expect("Failed to generate KZG proof from blob and z"); + if !proving_past_end { + assert_eq!( + &*proven_y, + &preimage[offset_usize..offset_usize + 32], + "KZG proof produced wrong preimage", + ); + } + data.extend(hash); + data.extend(*z_bytes); + data.extend(*proven_y); + data.extend(*commitment); + data.extend(kzg_proof.to_bytes().as_slice()); + } + } } else if next_inst.opcode == Opcode::ReadInboxMessage { let msg_idx = self .value_stack diff --git a/arbitrator/prover/src/main.rs b/arbitrator/prover/src/main.rs index 2c72d0b57..089111da1 100644 --- a/arbitrator/prover/src/main.rs +++ b/arbitrator/prover/src/main.rs @@ -6,7 +6,7 @@ use eyre::{Context, Result}; use fnv::{FnvHashMap as HashMap, FnvHashSet as HashSet}; use prover::{ machine::{GlobalState, InboxIdentifier, Machine, MachineStatus, PreimageResolver, ProofInfo}, - utils::{Bytes32, CBytes}, + utils::{hash_preimage, Bytes32, CBytes}, wavm::Opcode, }; use std::sync::Arc; @@ -159,7 +159,7 @@ fn main() -> Result<()> { let mut buf = vec![0u8; size]; file.read_exact(&mut buf)?; - let hash = preimage_ty.hash(&buf); + let hash = hash_preimage(&buf, preimage_ty)?; preimages .entry(preimage_ty) .or_default() @@ -206,7 +206,7 @@ fn main() -> Result<()> { let mut proofs: Vec = Vec::new(); let mut seen_states = HashSet::default(); - let mut opcode_counts: HashMap = HashMap::default(); + let mut proving_backoff: HashMap<(Opcode, u64), usize> = HashMap::default(); let mut opcode_profile: HashMap = HashMap::default(); let mut func_profile: HashMap<(usize, usize), SimpleProfile> = HashMap::default(); let mut func_stack: Vec<(usize, usize, SimpleProfile)> = Vec::default(); @@ -237,7 +237,13 @@ fn main() -> Result<()> { let next_opcode = next_inst.opcode; if opts.proving_backoff { - let count_entry = opcode_counts.entry(next_opcode).or_insert(0); + let mut extra_data = 0; + if matches!(next_opcode, Opcode::ReadInboxMessage | Opcode::ReadPreImage) { + extra_data = next_inst.argument_data; + } + let count_entry = proving_backoff + .entry((next_opcode, extra_data)) + .or_insert(0); *count_entry += 1; let count = *count_entry; // Apply an exponential backoff to how often to prove an instruction; diff --git a/arbitrator/prover/src/utils.rs b/arbitrator/prover/src/utils.rs index e86ea9676..3929dbc2a 100644 --- a/arbitrator/prover/src/utils.rs +++ b/arbitrator/prover/src/utils.rs @@ -1,8 +1,14 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE +use crate::kzg::ETHEREUM_KZG_SETTINGS; +use arbutil::PreimageType; +use c_kzg::{Blob, KzgCommitment}; +use digest::Digest; use eyre::{eyre, Result}; use serde::{Deserialize, Serialize}; +use sha2::Sha256; +use sha3::Keccak256; use std::{ borrow::Borrow, convert::TryInto, @@ -261,3 +267,19 @@ pub fn split_import(qualified: &str) -> Result<(&str, &str)> { let [module, name]: [&str; 2] = parts; Ok((module, name)) } + +pub fn hash_preimage(preimage: &[u8], ty: PreimageType) -> Result<[u8; 32]> { + match ty { + PreimageType::Keccak256 => Ok(Keccak256::digest(preimage).into()), + PreimageType::Sha2_256 => Ok(Sha256::digest(preimage).into()), + PreimageType::EthVersionedHash => { + // TODO: really we should also accept what version it is, + // but right now only one version is supported by this hash format anyways. + let blob = Box::new(Blob::from_bytes(preimage)?); + let commitment = KzgCommitment::blob_to_kzg_commitment(&blob, ÐEREUM_KZG_SETTINGS)?; + let mut commitment_hash: [u8; 32] = Sha256::digest(&*commitment.to_bytes()).into(); + commitment_hash[0] = 1; + Ok(commitment_hash) + } + } +} diff --git a/arbitrator/prover/test-cases/go/main.go b/arbitrator/prover/test-cases/go/main.go index afed870fe..549a83f15 100644 --- a/arbitrator/prover/test-cases/go/main.go +++ b/arbitrator/prover/test-cases/go/main.go @@ -5,13 +5,16 @@ package main import ( "bytes" + "crypto/sha512" "encoding/hex" "fmt" + "math/big" "os" "runtime" "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" merkletree "github.com/wealdtech/go-merkletree" "github.com/offchainlabs/nitro/arbcompress" @@ -59,6 +62,11 @@ func testCompression(data []byte) { } } +const FIELD_ELEMENTS_PER_BLOB = 4096 +const BYTES_PER_FIELD_ELEMENT = 32 + +var BLS_MODULUS, _ = new(big.Int).SetString("52435875175126190479447740508185965837690552500527637822603658699938581184513", 10) + func main() { fmt.Printf("starting executable with %v arg(s): %v\n", len(os.Args), os.Args) runtime.GC() @@ -113,5 +121,24 @@ func main() { checkPreimage(arbutil.Keccak256PreimageType, common.HexToHash("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad")) checkPreimage(arbutil.Sha2_256PreimageType, common.HexToHash("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9")) + kzgPreimage, err := wavmio.ResolveTypedPreimage(arbutil.EthVersionedHashPreimageType, common.HexToHash("01c277af4074155da57fd0f1065fc8b2e1d475e6639371b7300a2f1fb46296fa")) + if err != nil { + panic(fmt.Sprintf("failed to resolve eth versioned hash preimage: %v", err)) + } + blobLength := FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT + if len(kzgPreimage) != blobLength { + panic(fmt.Sprintf("expected blob length to be %v but got %v", blobLength, len(kzgPreimage))) + } + for i := 0; i < FIELD_ELEMENTS_PER_BLOB; i++ { + hash := sha512.Sum512([]byte(fmt.Sprintf("%v", i))) + scalar := new(big.Int).SetBytes(hash[:]) + scalar.Mod(scalar, BLS_MODULUS) + expectedElement := math.U256Bytes(scalar) + gotElement := kzgPreimage[i*BYTES_PER_FIELD_ELEMENT : (i+1)*BYTES_PER_FIELD_ELEMENT] + if !bytes.Equal(gotElement, expectedElement) { + panic(fmt.Sprintf("expected blob element %v to be %v but got %v", i, hex.EncodeToString(expectedElement), hex.EncodeToString(gotElement))) + } + } + println("verified preimage resolution!\n") } diff --git a/arbitrator/prover/test-cases/rust/Cargo.lock b/arbitrator/prover/test-cases/rust/Cargo.lock index d90ed9bb8..b4bc9de58 100644 --- a/arbitrator/prover/test-cases/rust/Cargo.lock +++ b/arbitrator/prover/test-cases/rust/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "block-buffer" version = "0.9.0" @@ -18,6 +24,21 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpufeatures" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +dependencies = [ + "libc", +] + [[package]] name = "digest" version = "0.9.0" @@ -49,12 +70,61 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +[[package]] +name = "libc" +version = "0.2.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + [[package]] name = "opaque-debug" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + [[package]] name = "sha3" version = "0.9.1" @@ -73,6 +143,8 @@ version = "0.1.0" dependencies = [ "digest", "hex-literal", + "num-bigint", + "sha2", "sha3", ] diff --git a/arbitrator/prover/test-cases/rust/Cargo.toml b/arbitrator/prover/test-cases/rust/Cargo.toml index 9e1ded68a..7dd479687 100644 --- a/arbitrator/prover/test-cases/rust/Cargo.toml +++ b/arbitrator/prover/test-cases/rust/Cargo.toml @@ -7,6 +7,8 @@ publish = false [dependencies] digest = { version = "0.9.0", default-features = false } hex-literal = "0.3.4" +num-bigint = { version = "0.4.4", default-features = false } +sha2 = { version = "0.9.9", default-features = false } sha3 = { version = "0.9.1", default-features = false } [workspace] diff --git a/arbitrator/prover/test-cases/rust/data/preimages.bin b/arbitrator/prover/test-cases/rust/data/preimages.bin deleted file mode 100644 index 34ef5a4292ec9998940525f0bf323d2219048896..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40 ZcmZSJW`KZ<)SR4rh4TEOoD@bZVgQZm2+#lk diff --git a/arbitrator/prover/test-cases/rust/src/bin/host-io.rs b/arbitrator/prover/test-cases/rust/src/bin/host-io.rs index 19ddabddc..d16f60ff5 100644 --- a/arbitrator/prover/test-cases/rust/src/bin/host-io.rs +++ b/arbitrator/prover/test-cases/rust/src/bin/host-io.rs @@ -1,8 +1,11 @@ use hex_literal::hex; +use num_bigint::BigUint; +use sha2::{Digest, Sha512}; extern "C" { pub fn wavm_read_keccak_256_preimage(ptr: *mut u8, offset: usize) -> usize; pub fn wavm_read_sha2_256_preimage(ptr: *mut u8, offset: usize) -> usize; + pub fn wavm_read_eth_versioned_hash_preimage(ptr: *mut u8, offset: usize) -> usize; pub fn wavm_read_inbox_message(msg_num: u64, ptr: *mut u8, offset: usize) -> usize; pub fn wavm_read_delayed_inbox_message(seq_num: u64, ptr: *mut u8, offset: usize) -> usize; pub fn wavm_halt_and_set_finished(); @@ -13,9 +16,15 @@ struct Bytes32([u8; 32]); const INBOX_HEADER_LEN: usize = 40; // also in src/main.rs & contracts's OneStepProverHostIo.sol const DELAYED_HEADER_LEN: usize = 112; // also in src/main.rs & contracts's OneStepProverHostIo.sol +const FIELD_ELEMENTS_PER_BLOB: usize = 4096; +const BYTES_PER_FIELD_ELEMENT: usize = 32; fn main() { println!("hello!"); + let bls_modulus: BigUint = + "52435875175126190479447740508185965837690552500527637822603658699938581184513" + .parse() + .expect("Failed to parse BLS_MODULUS"); unsafe { let mut bytebuffer = Bytes32([0x0; 32]); // in delayed inbox - we're skipping the "kind" byte @@ -39,6 +48,7 @@ fn main() { for j in 0..32 { assert_eq!(bytebuffer.0[j], (j as u8) + 1); } + let keccak_hash = hex!("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"); bytebuffer = Bytes32(keccak_hash); println!("keccak preimage"); @@ -46,12 +56,47 @@ fn main() { let len = wavm_read_keccak_256_preimage(bytebuffer.0.as_mut_ptr(), 0); assert_eq!(len, expected_preimage.len()); assert_eq!(&bytebuffer.0[..len], expected_preimage); + println!("sha2 preimage"); let sha2_hash = hex!("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"); bytebuffer = Bytes32(sha2_hash); let len = wavm_read_sha2_256_preimage(bytebuffer.0.as_mut_ptr(), 0); assert_eq!(len, expected_preimage.len()); assert_eq!(&bytebuffer.0[..len], expected_preimage); + + println!("kzg preimage"); + let eth_versioned_hash = + hex!("01c277af4074155da57fd0f1065fc8b2e1d475e6639371b7300a2f1fb46296fa"); + + bytebuffer = Bytes32(eth_versioned_hash); + let len = wavm_read_eth_versioned_hash_preimage( + bytebuffer.0.as_mut_ptr(), + FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT, + ); + assert_eq!(len, 0); + let len = wavm_read_eth_versioned_hash_preimage( + bytebuffer.0.as_mut_ptr(), + (FIELD_ELEMENTS_PER_BLOB + 1) * BYTES_PER_FIELD_ELEMENT, + ); + assert_eq!(len, 0); + + for i in 0..FIELD_ELEMENTS_PER_BLOB { + bytebuffer = Bytes32(eth_versioned_hash); + let len = wavm_read_eth_versioned_hash_preimage( + bytebuffer.0.as_mut_ptr(), + i * BYTES_PER_FIELD_ELEMENT, + ); + assert_eq!(len, BYTES_PER_FIELD_ELEMENT); + + let sha_input = i.to_string(); + let sha512 = Sha512::digest(sha_input.as_bytes()); + let mut scalar = BigUint::from_bytes_be(sha512.as_slice()); + scalar %= &bls_modulus; + let scalar_bytes = scalar.to_bytes_be(); + let mut expected_hash = [0u8; 32]; + expected_hash[32-scalar_bytes.len()..].copy_from_slice(&scalar_bytes); + assert_eq!(bytebuffer.0, expected_hash); + } } println!("Done!"); } diff --git a/arbitrator/wasm-libraries/Cargo.lock b/arbitrator/wasm-libraries/Cargo.lock index 3b545fcc4..b50aebb95 100644 --- a/arbitrator/wasm-libraries/Cargo.lock +++ b/arbitrator/wasm-libraries/Cargo.lock @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.147" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "memchr" @@ -246,9 +246,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.28" +version = "2.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" dependencies = [ "proc-macro2", "quote", diff --git a/arbitrator/wasm-libraries/host-io/src/lib.rs b/arbitrator/wasm-libraries/host-io/src/lib.rs index e8f59994a..733d14335 100644 --- a/arbitrator/wasm-libraries/host-io/src/lib.rs +++ b/arbitrator/wasm-libraries/host-io/src/lib.rs @@ -9,6 +9,7 @@ extern "C" { pub fn wavm_set_globalstate_u64(idx: u32, val: u64); pub fn wavm_read_keccak_256_preimage(ptr: *mut u8, offset: usize) -> usize; pub fn wavm_read_sha2_256_preimage(ptr: *mut u8, offset: usize) -> usize; + pub fn wavm_read_eth_versioned_hash_preimage(ptr: *mut u8, offset: usize) -> usize; pub fn wavm_read_inbox_message(msg_num: u64, ptr: *mut u8, offset: usize) -> usize; pub fn wavm_read_delayed_inbox_message(seq_num: u64, ptr: *mut u8, offset: usize) -> usize; } @@ -150,6 +151,7 @@ pub unsafe extern "C" fn go__github_com_offchainlabs_nitro_wavmio_resolveTypedPr let preimage_reader = match preimage_type { PreimageType::Keccak256 => wavm_read_keccak_256_preimage, PreimageType::Sha2_256 => wavm_read_sha2_256_preimage, + PreimageType::EthVersionedHash => wavm_read_eth_versioned_hash_preimage, }; let read = preimage_reader(our_ptr, offset as usize); assert!(read <= 32); diff --git a/arbutil/preimage_type.go b/arbutil/preimage_type.go index 7eaf60c01..72a39431b 100644 --- a/arbutil/preimage_type.go +++ b/arbutil/preimage_type.go @@ -10,4 +10,5 @@ type PreimageType uint8 const ( Keccak256PreimageType PreimageType = iota Sha2_256PreimageType + EthVersionedHashPreimageType ) diff --git a/contracts b/contracts index 0a149d2af..b0158487c 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 0a149d2af9aee566c4abf493479ec15e5fc32d98 +Subproject commit b0158487cea5d5533837e37e46be1f79303921ba diff --git a/scripts/create-test-preimages.py b/scripts/create-test-preimages.py new file mode 100644 index 000000000..c7ecb36e0 --- /dev/null +++ b/scripts/create-test-preimages.py @@ -0,0 +1,39 @@ +import sys +import struct +import hashlib + +BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 +BYTES_PER_FIELD_ELEMENT = 32 +FIELD_ELEMENTS_PER_BLOB = 4096 +KZG_ENDIANNESS='big' + +def write_data_to_file(filename, preimages): + with open(filename, 'wb') as file: + for preimage in preimages: + preimage_type, data = preimage + file.write(struct.pack('B', preimage_type)) + file.write(struct.pack('") + sys.exit(1) + +filename = sys.argv[1] + +preimages = [ + (0, b'hello world'), + (1, b'hello world'), + (2, kzg_test_data()), +] + +write_data_to_file(filename, preimages) From 5fb9a0ed381170a4b75c5cbdc495be7606cebc68 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 2 Jan 2024 16:47:45 -0600 Subject: [PATCH 580/775] Bump rust to 1.70 to make deps happy --- Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index b62e56925..f1c17cf09 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,8 +41,8 @@ RUN apt-get update && apt-get install -y curl build-essential=12.9 FROM wasm-base as wasm-libs-builder # clang / lld used by soft-float wasm RUN apt-get install -y clang=1:11.0-51+nmu5 lld=1:11.0-51+nmu5 - # pinned rust 1.65.0 -RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.68.2 --target x86_64-unknown-linux-gnu wasm32-unknown-unknown wasm32-wasi + # pinned rust 1.70.0 +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.70.0 --target x86_64-unknown-linux-gnu wasm32-unknown-unknown wasm32-wasi COPY ./Makefile ./ COPY arbitrator/arbutil arbitrator/arbutil COPY arbitrator/wasm-libraries arbitrator/wasm-libraries @@ -81,7 +81,7 @@ COPY --from=contracts-builder workspace/contracts/node_modules/@offchainlabs/upg COPY --from=contracts-builder workspace/.make/ .make/ RUN PATH="$PATH:/usr/local/go/bin" NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-wasm-bin -FROM rust:1.68-slim-bullseye as prover-header-builder +FROM rust:1.70-slim-bullseye as prover-header-builder WORKDIR /workspace RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && \ @@ -97,7 +97,7 @@ RUN NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-prover-header FROM scratch as prover-header-export COPY --from=prover-header-builder /workspace/target/ / -FROM rust:1.68-slim-bullseye as prover-builder +FROM rust:1.70-slim-bullseye as prover-builder WORKDIR /workspace RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && \ From 206fdc548312bcb04edb66121a7bd7c27a3e81ae Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 2 Jan 2024 16:48:02 -0600 Subject: [PATCH 581/775] Fix clippy --- arbitrator/jit/src/syscall.rs | 6 +++--- arbitrator/prover/src/kzg.rs | 2 +- arbitrator/prover/src/machine.rs | 8 ++------ 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/arbitrator/jit/src/syscall.rs b/arbitrator/jit/src/syscall.rs index c81641a7f..4f657eeef 100644 --- a/arbitrator/jit/src/syscall.rs +++ b/arbitrator/jit/src/syscall.rs @@ -337,7 +337,7 @@ pub fn js_value_call(mut env: WasmEnvMut, sp: u32) -> MaybeEscape { let value = match (object, method_name.as_slice()) { (Ref(GO_ID), b"_makeFuncWrapper") => { - let arg = match args.get(0) { + let arg = match args.first() { Some(arg) => arg, None => fail!( "Go trying to call Go._makeFuncWrapper with bad args {:?}", @@ -415,7 +415,7 @@ pub fn js_value_call(mut env: WasmEnvMut, sp: u32) -> MaybeEscape { (Ref(CRYPTO_ID), b"getRandomValues") => { let name = "crypto.getRandomValues"; - let id = match args.get(0) { + let id = match args.first() { Some(Ref(x)) => x, _ => fail!("Go trying to call {name} with bad args {:?}", args), }; @@ -456,7 +456,7 @@ pub fn js_value_new(mut env: WasmEnvMut, sp: u32) { let args_len = sp.read_u64(2); let args = sp.read_value_slice(args_ptr, args_len); match class { - UINT8_ARRAY_ID => match args.get(0) { + UINT8_ARRAY_ID => match args.first() { Some(JsValue::Number(size)) => { let id = pool.insert(DynamicObject::Uint8Array(vec![0; *size as usize])); sp.write_u64(4, GoValue::Object(id).encode()); diff --git a/arbitrator/prover/src/kzg.rs b/arbitrator/prover/src/kzg.rs index 7ab21e5ee..f80536ff0 100644 --- a/arbitrator/prover/src/kzg.rs +++ b/arbitrator/prover/src/kzg.rs @@ -48,7 +48,7 @@ lazy_static::lazy_static! { // order 2^32 let root: BigUint = "10238227357739495823651030575849232062558860180284477541189508159991286009131".parse().unwrap(); let exponent = (1_u64 << 32) / (FIELD_ELEMENTS_PER_BLOB as u64); - root.modpow(&BigUint::from(exponent), &*BLS_MODULUS) + root.modpow(&BigUint::from(exponent), &BLS_MODULUS) }; } diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index 23ab7bbfc..b4ec83f1c 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -365,7 +365,7 @@ impl Module { bin.memories.len() <= 1, "Multiple memories are not supported" ); - if let Some(limits) = bin.memories.get(0) { + if let Some(limits) = bin.memories.first() { let page_size = Memory::PAGE_SIZE; let initial = limits.initial; // validate() checks this is less than max::u32 let allowed = u32::MAX as u64 / Memory::PAGE_SIZE - 1; // we require the size remain *below* 2^32 @@ -2286,11 +2286,7 @@ impl Machine { next_inst.opcode, Opcode::ReadPreImage | Opcode::ReadInboxMessage, ) { - let offset = self - .value_stack - .get(self.value_stack.len() - 1) - .unwrap() - .assume_u32(); + let offset = self.value_stack.last().unwrap().assume_u32(); let ptr = self .value_stack .get(self.value_stack.len() - 2) From 22ced3c681ce7b361faf6c2889f9ad6352954677 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 2 Jan 2024 17:45:40 -0600 Subject: [PATCH 582/775] Fix docker build --- Dockerfile | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index f1c17cf09..03baf0872 100644 --- a/Dockerfile +++ b/Dockerfile @@ -85,7 +85,7 @@ FROM rust:1.70-slim-bullseye as prover-header-builder WORKDIR /workspace RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && \ - apt-get install -y make && \ + apt-get install -y make clang && \ cargo install --force cbindgen COPY arbitrator/Cargo.* arbitrator/cbindgen.toml arbitrator/ COPY ./Makefile ./ @@ -97,15 +97,12 @@ RUN NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-prover-header FROM scratch as prover-header-export COPY --from=prover-header-builder /workspace/target/ / -FROM rust:1.70-slim-bullseye as prover-builder +FROM rust:1.75-slim-bookworm as prover-builder WORKDIR /workspace RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && \ - apt-get install -y make wget gpg software-properties-common zlib1g-dev libstdc++-10-dev wabt -RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - && \ - add-apt-repository 'deb http://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-12 main' && \ - apt-get update && \ - apt-get install -y llvm-12-dev libclang-common-12-dev + apt-get install -y make wget gpg software-properties-common zlib1g-dev \ + libstdc++-11-dev wabt clang llvm-dev libclang-common-14-dev libpolly-14-dev COPY arbitrator/Cargo.* arbitrator/ COPY arbitrator/arbutil arbitrator/arbutil COPY arbitrator/prover/Cargo.toml arbitrator/prover/ From d359644a41d0c3dd0fe0cd63fa2b69400ca914a7 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 2 Jan 2024 18:10:09 -0600 Subject: [PATCH 583/775] Update all docker images to bookworm --- Dockerfile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 03baf0872..e236b149e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:bullseye-slim as brotli-wasm-builder +FROM debian:bookworm-slim as brotli-wasm-builder WORKDIR /workspace RUN apt-get update && \ apt-get install -y cmake make git lbzip2 python3 xz-utils && \ @@ -13,7 +13,7 @@ RUN cd emsdk && . ./emsdk_env.sh && cd .. && ./scripts/build-brotli.sh -w -t /wo FROM scratch as brotli-wasm-export COPY --from=brotli-wasm-builder /workspace/install/ / -FROM debian:bullseye-slim as brotli-library-builder +FROM debian:bookworm-slim as brotli-library-builder WORKDIR /workspace COPY scripts/build-brotli.sh scripts/ COPY brotli brotli @@ -24,7 +24,7 @@ RUN apt-get update && \ FROM scratch as brotli-library-export COPY --from=brotli-library-builder /workspace/install/ / -FROM node:16-bullseye-slim as contracts-builder +FROM node:16-bookworm-slim as contracts-builder RUN apt-get update && \ apt-get install -y git python3 make g++ WORKDIR /workspace @@ -34,7 +34,7 @@ COPY contracts contracts/ COPY Makefile . RUN NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-solidity -FROM debian:bullseye-20211220 as wasm-base +FROM debian:bookworm-20211220 as wasm-base WORKDIR /workspace RUN apt-get update && apt-get install -y curl build-essential=12.9 @@ -81,7 +81,7 @@ COPY --from=contracts-builder workspace/contracts/node_modules/@offchainlabs/upg COPY --from=contracts-builder workspace/.make/ .make/ RUN PATH="$PATH:/usr/local/go/bin" NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-wasm-bin -FROM rust:1.70-slim-bullseye as prover-header-builder +FROM rust:1.70-slim-bookworm as prover-header-builder WORKDIR /workspace RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && \ @@ -124,7 +124,7 @@ RUN NITRO_BUILD_IGNORE_TIMESTAMPS=1 make CARGOFLAGS="--features=llvm" build-jit FROM scratch as prover-export COPY --from=prover-builder /workspace/target/ / -FROM debian:bullseye-slim as module-root-calc +FROM debian:bookworm-slim as module-root-calc WORKDIR /workspace RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && \ @@ -141,7 +141,7 @@ COPY ./solgen ./solgen COPY ./contracts ./contracts RUN NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-replay-env -FROM debian:bullseye-slim as machine-versions +FROM debian:bookworm-slim as machine-versions RUN apt-get update && apt-get install -y unzip wget curl WORKDIR /workspace/machines # Download WAVM machines @@ -163,7 +163,7 @@ RUN ./download-machine.sh consensus-v10.2 0x0754e09320c381566cc0449904c377a52bd3 RUN ./download-machine.sh consensus-v10.3 0xf559b6d4fa869472dabce70fe1c15221bdda837533dfd891916836975b434dec RUN ./download-machine.sh consensus-v11 0xf4389b835497a910d7ba3ebfb77aa93da985634f3c052de1290360635be40c4a -FROM golang:1.20-bullseye as node-builder +FROM golang:1.20-bookworm as node-builder WORKDIR /workspace ARG version="" ARG datetime="" @@ -193,13 +193,13 @@ FROM node-builder as fuzz-builder RUN mkdir fuzzers/ RUN ./scripts/fuzz.bash --build --binary-path /workspace/fuzzers/ -FROM debian:bullseye-slim as nitro-fuzzer +FROM debian:bookworm-slim as nitro-fuzzer COPY --from=fuzz-builder /workspace/fuzzers/*.fuzz /usr/local/bin/ COPY ./scripts/fuzz.bash /usr/local/bin RUN mkdir /fuzzcache ENTRYPOINT [ "/usr/local/bin/fuzz.bash", "--binary-path", "/usr/local/bin/", "--fuzzcache-path", "/fuzzcache" ] -FROM debian:bullseye-slim as nitro-node-slim +FROM debian:bookworm-slim as nitro-node-slim WORKDIR /home/user COPY --from=node-builder /workspace/target/bin/nitro /usr/local/bin/ COPY --from=node-builder /workspace/target/bin/relay /usr/local/bin/ From e8ec476514ba6b9286380eb2d8190296c628767a Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Thu, 4 Jan 2024 17:55:21 -0700 Subject: [PATCH 584/775] Make clippy happy --- arbitrator/prover/src/machine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index 0849312f3..6ca552d83 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -362,7 +362,7 @@ impl Module { bin.memories.len() <= 1, "Multiple memories are not supported" ); - if let Some(limits) = bin.memories.get(0) { + if let Some(limits) = bin.memories.first() { let page_size = Memory::PAGE_SIZE; let initial = limits.initial; // validate() checks this is less than max::u32 let allowed = u32::MAX as u64 / Memory::PAGE_SIZE - 1; // we require the size remain *below* 2^32 From b9e9bcfecc6f857e20bb9b46d18847927af57a35 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Thu, 4 Jan 2024 18:22:06 -0700 Subject: [PATCH 585/775] Make clippy happy --- arbitrator/jit/src/syscall.rs | 6 +++--- arbitrator/wasm-libraries/go-stub/src/lib.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arbitrator/jit/src/syscall.rs b/arbitrator/jit/src/syscall.rs index c81641a7f..4f657eeef 100644 --- a/arbitrator/jit/src/syscall.rs +++ b/arbitrator/jit/src/syscall.rs @@ -337,7 +337,7 @@ pub fn js_value_call(mut env: WasmEnvMut, sp: u32) -> MaybeEscape { let value = match (object, method_name.as_slice()) { (Ref(GO_ID), b"_makeFuncWrapper") => { - let arg = match args.get(0) { + let arg = match args.first() { Some(arg) => arg, None => fail!( "Go trying to call Go._makeFuncWrapper with bad args {:?}", @@ -415,7 +415,7 @@ pub fn js_value_call(mut env: WasmEnvMut, sp: u32) -> MaybeEscape { (Ref(CRYPTO_ID), b"getRandomValues") => { let name = "crypto.getRandomValues"; - let id = match args.get(0) { + let id = match args.first() { Some(Ref(x)) => x, _ => fail!("Go trying to call {name} with bad args {:?}", args), }; @@ -456,7 +456,7 @@ pub fn js_value_new(mut env: WasmEnvMut, sp: u32) { let args_len = sp.read_u64(2); let args = sp.read_value_slice(args_ptr, args_len); match class { - UINT8_ARRAY_ID => match args.get(0) { + UINT8_ARRAY_ID => match args.first() { Some(JsValue::Number(size)) => { let id = pool.insert(DynamicObject::Uint8Array(vec![0; *size as usize])); sp.write_u64(4, GoValue::Object(id).encode()); diff --git a/arbitrator/wasm-libraries/go-stub/src/lib.rs b/arbitrator/wasm-libraries/go-stub/src/lib.rs index df77893fc..1a5d1963c 100644 --- a/arbitrator/wasm-libraries/go-stub/src/lib.rs +++ b/arbitrator/wasm-libraries/go-stub/src/lib.rs @@ -218,7 +218,7 @@ pub unsafe extern "C" fn go__syscall_js_valueNew(sp: GoStack) { let args_len = sp.read_u64(2); let args = read_value_slice(args_ptr, args_len); if class == UINT8_ARRAY_ID { - if let Some(InterpValue::Number(size)) = args.get(0) { + if let Some(InterpValue::Number(size)) = args.first() { let id = DynamicObjectPool::singleton() .insert(DynamicObject::Uint8Array(vec![0; *size as usize])); sp.write_u64(4, GoValue::Object(id).encode()); @@ -321,7 +321,7 @@ unsafe fn value_call_impl(sp: &mut GoStack) -> Result { let args_len = sp.read_u64(4); let args = read_value_slice(args_ptr, args_len); if object == InterpValue::Ref(GO_ID) && &method_name == b"_makeFuncWrapper" { - let id = args.get(0).ok_or_else(|| { + let id = args.first().ok_or_else(|| { format!( "Go attempting to call Go._makeFuncWrapper with bad args {:?}", args, @@ -405,7 +405,7 @@ unsafe fn value_call_impl(sp: &mut GoStack) -> Result { )) } } else if object == InterpValue::Ref(CRYPTO_ID) && &method_name == b"getRandomValues" { - let id = match args.get(0) { + let id = match args.first() { Some(InterpValue::Ref(x)) => *x, _ => { return Err(format!( From c02e8401caec041e2d8b856ecc8189f910a21475 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Fri, 5 Jan 2024 10:23:33 +0530 Subject: [PATCH 586/775] address PR comments --- staker/block_validator.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/staker/block_validator.go b/staker/block_validator.go index e649b112b..352335a5d 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -98,11 +98,6 @@ type BlockValidatorConfig struct { func (c *BlockValidatorConfig) Validate() error { if c.MemoryFreeLimit == "default" { c.memoryFreeLimit = 1073741824 // 1GB - _, err := resourcemanager.NewCgroupsMemoryLimitCheckerIfSupported(c.memoryFreeLimit) - if err != nil { - log.Warn("Cgroups V1 or V2 is unsupported, memory-free-limit feature inside block-validator is disabled") - c.MemoryFreeLimit = "" - } } else if c.MemoryFreeLimit != "" { limit, err := resourcemanager.ParseMemLimit(c.MemoryFreeLimit) if err != nil { @@ -241,9 +236,14 @@ func NewBlockValidator( if config().MemoryFreeLimit != "" { limtchecker, err := resourcemanager.NewCgroupsMemoryLimitCheckerIfSupported(config().memoryFreeLimit) if err != nil { - return nil, fmt.Errorf("failed to create MemoryFreeLimitChecker, Cgroups V1 or V2 is unsupported") + if config().MemoryFreeLimit == "default" { + log.Warn("Cgroups V1 or V2 is unsupported, memory-free-limit feature inside block-validator is disabled") + } else { + return nil, fmt.Errorf("failed to create MemoryFreeLimitChecker, Cgroups V1 or V2 is unsupported") + } + } else { + ret.MemoryFreeLimitChecker = limtchecker } - ret.MemoryFreeLimitChecker = limtchecker } return ret, nil } From cc89883f629d5b43efc06c27b71cfac774b7259f Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Fri, 5 Jan 2024 10:28:25 +0530 Subject: [PATCH 587/775] address PR comments --- broadcaster/backlog/backlog.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 265f6b5af..d2f7c66be 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -19,8 +19,8 @@ var ( errOutOfBounds = errors.New("message not found in backlog") confirmedSequenceNumberGauge = metrics.NewRegisteredGauge("arb/sequencenumber/confirmed", nil) - backlogSizeInBytesGauge = metrics.NewRegisteredGauge("arb/feed/backlog/sizeinbytes", nil) - backlogSizeGauge = metrics.NewRegisteredGauge("arb/feed/backlog/size", nil) + backlogSizeInBytesGauge = metrics.NewRegisteredGauge("arb/feed/backlog/bytes", nil) + backlogSizeGauge = metrics.NewRegisteredGauge("arb/feed/backlog/messages", nil) ) // Backlog defines the interface for backlog. From 1fbc42591a5a5ac0ab46eed3814cc7d81203068b Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 5 Jan 2024 12:41:02 -0600 Subject: [PATCH 588/775] Update docker wasm-libs-builder deps --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index e236b149e..0c811a0cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,13 +34,13 @@ COPY contracts contracts/ COPY Makefile . RUN NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-solidity -FROM debian:bookworm-20211220 as wasm-base +FROM debian:bookworm-20231218 as wasm-base WORKDIR /workspace RUN apt-get update && apt-get install -y curl build-essential=12.9 FROM wasm-base as wasm-libs-builder # clang / lld used by soft-float wasm -RUN apt-get install -y clang=1:11.0-51+nmu5 lld=1:11.0-51+nmu5 +RUN apt-get install -y clang=1:14.0-55.7~deb12u1 lld=1:14.0-55.7~deb12u1 # pinned rust 1.70.0 RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.70.0 --target x86_64-unknown-linux-gnu wasm32-unknown-unknown wasm32-wasi COPY ./Makefile ./ From 97c04cedb3b3924d2a432f83276d8290be51518a Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 7 Jan 2024 16:01:00 -0600 Subject: [PATCH 589/775] Disable coverage in arbitrator CI --- .github/workflows/arbitrator-ci.yml | 29 +----------------------- .github/workflows/arbitrator-skip-ci.yml | 2 +- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index 8c491a421..9796e599e 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -20,7 +20,7 @@ env: WABT_VERSION: 1.0.32 jobs: - coverage: + arbitrator: name: Run Arbitrator tests runs-on: ubuntu-8 steps: @@ -54,14 +54,6 @@ jobs: components: 'llvm-tools-preview, rustfmt, clippy' targets: 'wasm32-wasi, wasm32-unknown-unknown' - - name: Install grcov - uses: jaxxstorm/action-install-gh-release@v1.10.0 - with: - repo: mozilla/grcov - tag: v0.8.18 - extension: "\\.bz2" - cache: enable - - name: Cache Rust intermediate build products uses: actions/cache@v3 with: @@ -135,13 +127,6 @@ jobs: - name: Make arbitrator libraries run: make -j wasm-ci-build - - name: Enable rust instrumentation - run: | - echo LLVM_PROFILE_FILE="your_name-%p-%m.profraw" >> $GITHUB_ENV - echo "CARGO_INCREMENTAL=0" >> $GITHUB_ENV - echo RUSTFLAGS="-Cinstrument-coverage" >> $GITHUB_ENV - echo RUSTDOCFLAGS="-Cpanic=abort" >> $GITHUB_ENV - - name: Clippy check run: cargo clippy --all --manifest-path arbitrator/Cargo.toml -- -D warnings @@ -154,18 +139,6 @@ jobs: - name: Make proofs from test cases run: make -j test-gen-proofs - - name: Create code-coverage files - run: | - grcov . --binary-path arbitrator/target/release/ -s . -t lcov --branch --ignore-not-existing --ignore "/*" -o lcov.info - - - name: Upload to codecov.io - uses: codecov/codecov-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: ./lcov.info - fail_ci_if_error: true - verbose: false - - name: Start geth server run: | geth --dev --http --http.port 8545 & diff --git a/.github/workflows/arbitrator-skip-ci.yml b/.github/workflows/arbitrator-skip-ci.yml index 75fb47d0a..10c9bf9c1 100644 --- a/.github/workflows/arbitrator-skip-ci.yml +++ b/.github/workflows/arbitrator-skip-ci.yml @@ -13,7 +13,7 @@ on: - 'Makefile' jobs: - coverage: + arbitrator: name: Run Arbitrator tests runs-on: ubuntu-latest steps: From 3b306093abef54de7fbdb2dcbd9bce2daa5eddbb Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 7 Jan 2024 17:03:51 -0600 Subject: [PATCH 590/775] Build custom geth with KZG precompile --- .github/workflows/arbitrator-ci.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index 9796e599e..46da77500 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -31,9 +31,8 @@ jobs: - name: Install Ubuntu dependencies run: | - sudo add-apt-repository -y ppa:ethereum/ethereum sudo apt-get update && sudo apt-get install -y \ - build-essential cmake ethereum lld-14 libudev-dev + build-essential cmake lld-14 libudev-dev sudo ln -s /usr/bin/wasm-ld-14 /usr/local/bin/wasm-ld - name: Install go @@ -41,6 +40,15 @@ jobs: with: go-version: 1.20.x + - name: Install custom go-ethereum + run: | + cd /tmp + git clone --branch v1.13.8 --depth 1 https://github.com/ethereum/go-ethereum.git + cd go-ethereum + # Enable KZG point evaluation precompile early + sed -i 's#var PrecompiledContractsBerlin = map\[common.Address\]PrecompiledContract{#\0 common.BytesToAddress([]byte{0x0a}): \&kzgPointEvaluation{},#g' core/vm/contracts.go + go build -o /usr/local/bin/geth ./cmd/geth + - name: Setup nodejs uses: actions/setup-node@v3 with: From f081ffdec031589d5f8ea10c324f89028fb6d896 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 7 Jan 2024 18:09:22 -0600 Subject: [PATCH 591/775] Pull out prove_kzg_preimage into separate function --- arbitrator/prover/src/kzg.rs | 61 +++++++++++++++++++++++++++++++ arbitrator/prover/src/machine.rs | 63 ++------------------------------ 2 files changed, 65 insertions(+), 59 deletions(-) diff --git a/arbitrator/prover/src/kzg.rs b/arbitrator/prover/src/kzg.rs index f80536ff0..9eff9747e 100644 --- a/arbitrator/prover/src/kzg.rs +++ b/arbitrator/prover/src/kzg.rs @@ -1,9 +1,13 @@ // Copyright 2022-2024, Offchain Labs, Inc. // For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE +use crate::utils::Bytes32; use c_kzg::{KzgSettings, BYTES_PER_G1_POINT, BYTES_PER_G2_POINT}; +use eyre::{ensure, Result, WrapErr}; use num::BigUint; use serde::{de::Error as _, Deserialize}; +use sha2::{Digest, Sha256}; +use std::{convert::TryFrom, io::Write}; struct HexBytes; @@ -52,6 +56,63 @@ lazy_static::lazy_static! { }; } +/// Creates a KZG preimage proof consumable by the point evaluation precompile. +pub fn prove_kzg_preimage( + hash: Bytes32, + preimage: &[u8], + offset: u32, + out: &mut impl Write, +) -> Result<()> { + let blob = + c_kzg::Blob::from_bytes(preimage).wrap_err("Failed to generate KZG blob from preimage")?; + let commitment = c_kzg::KzgCommitment::blob_to_kzg_commitment(&blob, ÐEREUM_KZG_SETTINGS) + .wrap_err("Failed to generate KZG commitment from blob")?; + let mut expected_hash: Bytes32 = Sha256::digest(&*commitment).into(); + expected_hash[0] = 1; + ensure!( + hash == expected_hash, + "Trying to prove versioned hash {} preimage but recomputed hash {}", + hash, + expected_hash, + ); + ensure!( + offset % 32 == 0, + "Cannot prove blob preimage at unaligned offset {}", + offset, + ); + let offset_usize = usize::try_from(offset)?; + let mut proving_offset = offset; + let proving_past_end = offset_usize >= preimage.len(); + if proving_past_end { + // Proving any offset proves the length which is all we need here, + // because we're past the end of the preimage. + proving_offset = 0; + } + let exp = (proving_offset / 32).reverse_bits() + >> (u32::BITS - FIELD_ELEMENTS_PER_BLOB.trailing_zeros()); + let z = ROOT_OF_UNITY.modpow(&BigUint::from(exp), &BLS_MODULUS); + let z_bytes = z.to_bytes_be(); + let mut padded_z_bytes = [0u8; 32]; + padded_z_bytes[32 - z_bytes.len()..].copy_from_slice(&z_bytes); + let z_bytes = c_kzg::Bytes32::from(padded_z_bytes); + let (kzg_proof, proven_y) = + c_kzg::KzgProof::compute_kzg_proof(&blob, &z_bytes, ÐEREUM_KZG_SETTINGS) + .wrap_err("Failed to generate KZG proof from blob and z")?; + if !proving_past_end { + ensure!( + *proven_y == preimage[offset_usize..offset_usize + 32], + "KZG proof produced wrong preimage for offset {}", + offset, + ); + } + out.write_all(&*hash)?; + out.write_all(&*z_bytes)?; + out.write_all(&*proven_y)?; + out.write_all(&*commitment)?; + out.write_all(kzg_proof.to_bytes().as_slice())?; + Ok(()) +} + #[cfg(test)] #[test] fn load_trusted_setup() { diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index b4ec83f1c..f66a10dc1 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -4,7 +4,7 @@ use crate::{ binary::{parse, FloatInstruction, Local, NameCustomSection, WasmBinary}, host, - kzg::{BLS_MODULUS, ETHEREUM_KZG_SETTINGS, ROOT_OF_UNITY}, + kzg::prove_kzg_preimage, memory::Memory, merkle::{Merkle, MerkleType}, reinterpret::{ReinterpretAsSigned, ReinterpretAsUnsigned}, @@ -20,11 +20,10 @@ use c_kzg::FIELD_ELEMENTS_PER_BLOB; use digest::Digest; use eyre::{bail, ensure, eyre, Result, WrapErr}; use fnv::FnvHashMap as HashMap; -use num::{traits::PrimInt, BigUint, Zero}; +use num::{traits::PrimInt, Zero}; use rayon::prelude::*; use serde::{Deserialize, Serialize}; use serde_with::serde_as; -use sha2::Sha256; use sha3::Keccak256; use smallvec::SmallVec; use std::{ @@ -2320,62 +2319,8 @@ impl Machine { data.extend(preimage); } PreimageType::EthVersionedHash => { - let blob = c_kzg::Blob::from_bytes(&preimage) - .expect("Failed to generate KZG blob from preimage"); - let commitment = c_kzg::KzgCommitment::blob_to_kzg_commitment( - &blob, - ÐEREUM_KZG_SETTINGS, - ) - .expect("Failed to generate KZG commitment from blob"); - let mut expected_hash: Bytes32 = - Sha256::digest(&*commitment).into(); - expected_hash[0] = 1; - if hash != expected_hash { - panic!( - "Trying to prove versioned hash {} preimage but recomputed hash {}", - hash, - expected_hash, - ); - } - if offset % 32 != 0 { - panic!( - "Cannot prove blob preimage at unaligned offset {}", - offset, - ); - } - let offset_usize = usize::try_from(offset).unwrap(); - let mut proving_offset = offset; - let proving_past_end = offset_usize >= preimage.len(); - if proving_past_end { - // Proving any offset proves the length which is all we need here, - // because we're past the end of the preimage. - proving_offset = 0; - } - let exp = (proving_offset / 32).reverse_bits() - >> (u32::BITS - FIELD_ELEMENTS_PER_BLOB.trailing_zeros()); - let z = ROOT_OF_UNITY.modpow(&BigUint::from(exp), &BLS_MODULUS); - let z_bytes = z.to_bytes_be(); - let mut padded_z_bytes = [0u8; 32]; - padded_z_bytes[32 - z_bytes.len()..].copy_from_slice(&z_bytes); - let z_bytes = c_kzg::Bytes32::from(padded_z_bytes); - let (kzg_proof, proven_y) = c_kzg::KzgProof::compute_kzg_proof( - &blob, - &z_bytes, - ÐEREUM_KZG_SETTINGS, - ) - .expect("Failed to generate KZG proof from blob and z"); - if !proving_past_end { - assert_eq!( - &*proven_y, - &preimage[offset_usize..offset_usize + 32], - "KZG proof produced wrong preimage", - ); - } - data.extend(hash); - data.extend(*z_bytes); - data.extend(*proven_y); - data.extend(*commitment); - data.extend(kzg_proof.to_bytes().as_slice()); + prove_kzg_preimage(hash, &preimage, offset, &mut data) + .expect("Failed to generate KZG preimage proof"); } } } else if next_inst.opcode == Opcode::ReadInboxMessage { From 8dc996ccc0a83c7a4be78113baf6bcfac0caa1b4 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Mon, 8 Jan 2024 19:00:22 +0530 Subject: [PATCH 592/775] Handle long sequencer URLs and fix fetching the list of live sequencers --- .../seq-coordinator-manager.go | 21 +++++++++++++++---- util/redisutil/redis_coordinator.go | 16 ++++++++++---- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/cmd/seq-coordinator-manager/seq-coordinator-manager.go b/cmd/seq-coordinator-manager/seq-coordinator-manager.go index 07bc26af2..daafe1e5e 100644 --- a/cmd/seq-coordinator-manager/seq-coordinator-manager.go +++ b/cmd/seq-coordinator-manager/seq-coordinator-manager.go @@ -34,6 +34,7 @@ type manager struct { livelinessSet map[string]bool priorityList []string nonPriorityList []string + maxURLSize int } func main() { @@ -57,6 +58,9 @@ func main() { }, prioritiesSet: make(map[string]bool), livelinessSet: make(map[string]bool), + // maxURLSize dictates the allowed max length for sequencer urls + // urls exceeding this size will be truncated with an ellipsis + maxURLSize: 100, } seqManager.refreshAllLists(ctx) @@ -160,11 +164,11 @@ func main() { flex.SetDirection(tview.FlexRow). AddItem(priorityHeading, 0, 1, false). AddItem(tview.NewFlex(). - AddItem(prioritySeqList, 0, 2, true). + AddItem(prioritySeqList, seqManager.maxURLSize+20, 0, true). AddItem(priorityForm, 0, 3, true), 0, 12, true). AddItem(nonPriorityHeading, 0, 1, false). AddItem(tview.NewFlex(). - AddItem(nonPrioritySeqList, 0, 2, true). + AddItem(nonPrioritySeqList, seqManager.maxURLSize+20, 0, true). AddItem(nonPriorityForm, 0, 3, true), 0, 12, true). AddItem(instructions, 0, 3, false).SetBorder(true) @@ -243,13 +247,22 @@ func (sm *manager) populateLists(ctx context.Context) { if _, ok := sm.livelinessSet[seqURL]; ok { status = fmt.Sprintf("(%d) %v ", index, emoji.GreenCircle) } - prioritySeqList.AddItem(status+seqURL+sec, "", rune(0), nil).SetSecondaryTextColor(tcell.ColorPurple) + url := seqURL + if len(seqURL) > sm.maxURLSize { + url = seqURL[:sm.maxURLSize] + "..." + } + prioritySeqList.AddItem(status+url+sec, "", rune(0), nil).SetSecondaryTextColor(tcell.ColorPurple) + } nonPrioritySeqList.Clear() status := fmt.Sprintf("(-) %v ", emoji.GreenCircle) for _, seqURL := range sm.nonPriorityList { - nonPrioritySeqList.AddItem(status+seqURL, "", rune(0), nil) + url := seqURL + if len(seqURL) > sm.maxURLSize { + url = seqURL[:sm.maxURLSize] + "..." + } + nonPrioritySeqList.AddItem(status+url, "", rune(0), nil) } } diff --git a/util/redisutil/redis_coordinator.go b/util/redisutil/redis_coordinator.go index 357dfb2e9..6af141c66 100644 --- a/util/redisutil/redis_coordinator.go +++ b/util/redisutil/redis_coordinator.go @@ -89,11 +89,19 @@ func (rc *RedisCoordinator) GetPriorities(ctx context.Context) ([]string, error) return prioritiesList, nil } -// GetLiveliness returns a map whose keys are sequencers that have their liveliness set to OK +// GetLiveliness returns a list of sequencers that have their liveliness set to OK func (rc *RedisCoordinator) GetLiveliness(ctx context.Context) ([]string, error) { - livelinessList, _, err := rc.Client.Scan(ctx, 0, WANTS_LOCKOUT_KEY_PREFIX+"*", 0).Result() - if err != nil { - return []string{}, err + var livelinessList []string + cursor := uint64(0) + for { + keySlice, cursor, err := rc.Client.Scan(ctx, cursor, WANTS_LOCKOUT_KEY_PREFIX+"*", 0).Result() + if err != nil { + return []string{}, err + } + livelinessList = append(livelinessList, keySlice...) + if cursor == 0 { + break + } } for i, elem := range livelinessList { url := strings.TrimPrefix(elem, WANTS_LOCKOUT_KEY_PREFIX) From d9e6e9a25333ee774ff223f665b3c7c378452533 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 8 Jan 2024 10:37:26 -0600 Subject: [PATCH 593/775] Update contracts pin --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index b0158487c..c1ca7ce29 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit b0158487cea5d5533837e37e46be1f79303921ba +Subproject commit c1ca7ce29b8442b0d8dbbde3c75a8ab551ec0ac8 From 552939ff3bf92579f9a93d1d961e366b69b9dd00 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 8 Jan 2024 11:33:49 -0600 Subject: [PATCH 594/775] Fix getL1Confirmations on L3s --- nodeInterface/NodeInterface.go | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/nodeInterface/NodeInterface.go b/nodeInterface/NodeInterface.go index 3b377bc5a..bdcfb569f 100644 --- a/nodeInterface/NodeInterface.go +++ b/nodeInterface/NodeInterface.go @@ -10,6 +10,7 @@ import ( "math/big" "sort" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -17,6 +18,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos" @@ -24,6 +26,7 @@ import ( "github.com/offchainlabs/nitro/arbos/retryables" "github.com/offchainlabs/nitro/arbos/util" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/solgen/go/node_interfacegen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/merkletree" @@ -94,14 +97,37 @@ func (n NodeInterface) GetL1Confirmations(c ctx, evm mech, blockHash bytes32) (u return 0, err } } - latestL1Block, latestBatchCount := node.InboxReader.GetLastReadBlockAndBatchCount() - if latestBatchCount <= batch { - return 0, nil // batch was reorg'd out? - } meta, err := node.InboxTracker.GetBatchMetadata(batch) if err != nil { return 0, err } + if node.L1Reader.IsParentChainArbitrum() { + parentChainClient := node.L1Reader.Client() + parentNodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, parentChainClient) + if err != nil { + return 0, err + } + parentChainBlock, err := parentChainClient.BlockByNumber(n.context, new(big.Int).SetUint64(meta.ParentChainBlock)) + if err != nil { + // Hide the parent chain RPC error from the client in case it contains sensitive information. + // Likely though, this error is just "not found" because the block got reorg'd. + return 0, fmt.Errorf("failed to get parent chain block %v containing batch", meta.ParentChainBlock) + } + confs, err := parentNodeInterface.GetL1Confirmations(&bind.CallOpts{Context: n.context}, parentChainBlock.Hash()) + if err != nil { + log.Warn( + "Failed to get L1 confirmations from parent chain", + "blockNumber", meta.ParentChainBlock, + "blockHash", parentChainBlock.Hash(), "err", err, + ) + return 0, fmt.Errorf("failed to get L1 confirmations from parent chain for block %v", parentChainBlock.Hash()) + } + return confs, nil + } + latestL1Block, latestBatchCount := node.InboxReader.GetLastReadBlockAndBatchCount() + if latestBatchCount <= batch { + return 0, nil // batch was reorg'd out? + } if latestL1Block < meta.ParentChainBlock || arbutil.BlockNumberToMessageCount(blockNum, genesis) > meta.MessageCount { return 0, nil } From a211e2b7c11ed356c663f0aae4e7593f0153c161 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 8 Jan 2024 12:47:31 -0600 Subject: [PATCH 595/775] Fix test hitting panic if len(msgs)==0 --- wsbroadcastserver/clientconnection.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 82b9603a0..6f5bf54e4 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -140,6 +140,9 @@ func (cc *ClientConnection) writeBacklog(ctx context.Context, segment backlog.Ba msgs = msgs[requestedIdx:] } } + if len(msgs) == 0 { + break + } isFirstSegment = false bm := &m.BroadcastMessage{ Version: m.V1, From efed0abe84aad9969774d5d7b6479e735e1238eb Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 9 Jan 2024 11:41:24 -0600 Subject: [PATCH 596/775] Bump contracts submodule pin --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index c1ca7ce29..7f4dffcf6 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit c1ca7ce29b8442b0d8dbbde3c75a8ab551ec0ac8 +Subproject commit 7f4dffcf6964697664cc9fb4afa7e4a14814fea3 From 859c29a1a149d3ca024b0a8c344c43d59cd830d2 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 9 Jan 2024 21:19:35 -0600 Subject: [PATCH 597/775] Bump contracts submodule --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 7f4dffcf6..154e95bf5 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 7f4dffcf6964697664cc9fb4afa7e4a14814fea3 +Subproject commit 154e95bf5e805b433af5265987e5752c05fee9b4 From 7b387ccca1edac92dddff0aa06424aabd959a791 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Wed, 10 Jan 2024 19:05:51 +0530 Subject: [PATCH 598/775] Add an option to support multiple block validation RPCs --- arbnode/node.go | 7 +- cmd/nitro/nitro.go | 2 +- staker/block_validator.go | 100 ++++++++++++++++++---------- staker/stateless_block_validator.go | 10 ++- system_tests/common_test.go | 7 +- util/rpcclient/rpcclient.go | 16 ++--- 6 files changed, 89 insertions(+), 53 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index eaefb8ecb..f107d59b6 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -42,6 +42,7 @@ import ( "github.com/offchainlabs/nitro/util/contracts" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/redisutil" + "github.com/offchainlabs/nitro/util/rpcclient" "github.com/offchainlabs/nitro/util/signature" "github.com/offchainlabs/nitro/wsbroadcastserver" ) @@ -188,7 +189,7 @@ func ConfigDefaultL1NonSequencerTest() *Config { config.BlockValidator = staker.TestBlockValidatorConfig config.Staker = staker.TestL1ValidatorConfig config.Staker.Enable = false - config.BlockValidator.ValidationServer.URL = "" + config.BlockValidator.ValidationServerConfigs = []rpcclient.ClientConfig{{URL: ""}} return &config } @@ -203,7 +204,7 @@ func ConfigDefaultL2Test() *Config { config.SeqCoordinator.Signer.ECDSA.Dangerous.AcceptMissing = true config.Staker = staker.TestL1ValidatorConfig config.Staker.Enable = false - config.BlockValidator.ValidationServer.URL = "" + config.BlockValidator.ValidationServerConfigs = []rpcclient.ClientConfig{{URL: ""}} config.TransactionStreamer = DefaultTransactionStreamerConfig return &config @@ -520,7 +521,7 @@ func createNodeImpl( txStreamer.SetInboxReaders(inboxReader, delayedBridge) var statelessBlockValidator *staker.StatelessBlockValidator - if config.BlockValidator.ValidationServer.URL != "" { + if config.BlockValidator.ValidationServerConfigs[0].URL != "" { statelessBlockValidator, err = staker.NewStatelessBlockValidator( inboxReader, inboxTracker, diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 55c8d7704..2fc6bea9c 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -389,7 +389,7 @@ func mainImpl() int { } var sameProcessValidationNodeEnabled bool - if nodeConfig.Node.BlockValidator.Enable && (nodeConfig.Node.BlockValidator.ValidationServer.URL == "self" || nodeConfig.Node.BlockValidator.ValidationServer.URL == "self-auth") { + if nodeConfig.Node.BlockValidator.Enable && (nodeConfig.Node.BlockValidator.ValidationServerConfigs[0].URL == "self" || nodeConfig.Node.BlockValidator.ValidationServerConfigs[0].URL == "self-auth") { sameProcessValidationNodeEnabled = true valnode.EnsureValidationExposedViaAuthRPC(&stackConf) } diff --git a/staker/block_validator.go b/staker/block_validator.go index 352335a5d..96810b866 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -5,6 +5,7 @@ package staker import ( "context" + "encoding/json" "errors" "fmt" "runtime" @@ -81,16 +82,18 @@ type BlockValidator struct { } type BlockValidatorConfig struct { - Enable bool `koanf:"enable"` - ValidationServer rpcclient.ClientConfig `koanf:"validation-server" reload:"hot"` - ValidationPoll time.Duration `koanf:"validation-poll" reload:"hot"` - PrerecordedBlocks uint64 `koanf:"prerecorded-blocks" reload:"hot"` - ForwardBlocks uint64 `koanf:"forward-blocks" reload:"hot"` - CurrentModuleRoot string `koanf:"current-module-root"` // TODO(magic) requires reinitialization on hot reload - PendingUpgradeModuleRoot string `koanf:"pending-upgrade-module-root"` // TODO(magic) requires StatelessBlockValidator recreation on hot reload - FailureIsFatal bool `koanf:"failure-is-fatal" reload:"hot"` - Dangerous BlockValidatorDangerousConfig `koanf:"dangerous"` - MemoryFreeLimit string `koanf:"memory-free-limit" reload:"hot"` + Enable bool `koanf:"enable"` + ValidationServer rpcclient.ClientConfig `koanf:"validation-server" reload:"hot"` + ValidationServerConfigs []rpcclient.ClientConfig `koanf:"validation-server-configs" reload:"hot"` + ValidationPoll time.Duration `koanf:"validation-poll" reload:"hot"` + PrerecordedBlocks uint64 `koanf:"prerecorded-blocks" reload:"hot"` + ForwardBlocks uint64 `koanf:"forward-blocks" reload:"hot"` + CurrentModuleRoot string `koanf:"current-module-root"` // TODO(magic) requires reinitialization on hot reload + PendingUpgradeModuleRoot string `koanf:"pending-upgrade-module-root"` // TODO(magic) requires StatelessBlockValidator recreation on hot reload + FailureIsFatal bool `koanf:"failure-is-fatal" reload:"hot"` + Dangerous BlockValidatorDangerousConfig `koanf:"dangerous"` + MemoryFreeLimit string `koanf:"memory-free-limit" reload:"hot"` + ValidationServerConfigsList string `koanf:"validation-server-configs-list" reload:"hot"` memoryFreeLimit int } @@ -105,7 +108,26 @@ func (c *BlockValidatorConfig) Validate() error { } c.memoryFreeLimit = limit } - return c.ValidationServer.Validate() + if c.ValidationServerConfigs == nil { + if c.ValidationServerConfigsList == "default" { + c.ValidationServerConfigs = []rpcclient.ClientConfig{c.ValidationServer} + } else { + var validationServersConfigs []rpcclient.ClientConfig + if err := json.Unmarshal([]byte(c.ValidationServerConfigsList), &validationServersConfigs); err != nil { + return fmt.Errorf("failed to parse block-validator validation-server-configs-list string: %w", err) + } + c.ValidationServerConfigs = validationServersConfigs + } + } + if len(c.ValidationServerConfigs) == 0 { + return fmt.Errorf("block-validator validation-server-configs is empty, need at least one validation server config") + } + for _, serverConfig := range c.ValidationServerConfigs { + if err := serverConfig.Validate(); err != nil { + return fmt.Errorf("failed to validate one of the block-validator validation-server-configs. url: %s, err: %w", serverConfig.URL, err) + } + } + return nil } type BlockValidatorDangerousConfig struct { @@ -117,6 +139,7 @@ type BlockValidatorConfigFetcher func() *BlockValidatorConfig func BlockValidatorConfigAddOptions(prefix string, f *flag.FlagSet) { f.Bool(prefix+".enable", DefaultBlockValidatorConfig.Enable, "enable block-by-block validation") rpcclient.RPCClientAddOptions(prefix+".validation-server", f, &DefaultBlockValidatorConfig.ValidationServer) + f.String(prefix+".validation-server-configs-list", DefaultBlockValidatorConfig.ValidationServerConfigsList, "array of validation rpc configs given as a json string. time duration should be supplied in number indicating nanoseconds") f.Duration(prefix+".validation-poll", DefaultBlockValidatorConfig.ValidationPoll, "poll time to check validations") f.Uint64(prefix+".forward-blocks", DefaultBlockValidatorConfig.ForwardBlocks, "prepare entries for up to that many blocks ahead of validation (small footprint)") f.Uint64(prefix+".prerecorded-blocks", DefaultBlockValidatorConfig.PrerecordedBlocks, "record that many blocks ahead of validation (larger footprint)") @@ -132,21 +155,23 @@ func BlockValidatorDangerousConfigAddOptions(prefix string, f *flag.FlagSet) { } var DefaultBlockValidatorConfig = BlockValidatorConfig{ - Enable: false, - ValidationServer: rpcclient.DefaultClientConfig, - ValidationPoll: time.Second, - ForwardBlocks: 1024, - PrerecordedBlocks: uint64(2 * runtime.NumCPU()), - CurrentModuleRoot: "current", - PendingUpgradeModuleRoot: "latest", - FailureIsFatal: true, - Dangerous: DefaultBlockValidatorDangerousConfig, - MemoryFreeLimit: "default", + Enable: false, + ValidationServerConfigsList: "default", + ValidationServer: rpcclient.DefaultClientConfig, + ValidationPoll: time.Second, + ForwardBlocks: 1024, + PrerecordedBlocks: uint64(2 * runtime.NumCPU()), + CurrentModuleRoot: "current", + PendingUpgradeModuleRoot: "latest", + FailureIsFatal: true, + Dangerous: DefaultBlockValidatorDangerousConfig, + MemoryFreeLimit: "default", } var TestBlockValidatorConfig = BlockValidatorConfig{ Enable: false, ValidationServer: rpcclient.TestClientConfig, + ValidationServerConfigs: []rpcclient.ClientConfig{rpcclient.TestClientConfig}, ValidationPoll: 100 * time.Millisecond, ForwardBlocks: 128, PrerecordedBlocks: uint64(2 * runtime.NumCPU()), @@ -665,14 +690,12 @@ func (v *BlockValidator) advanceValidations(ctx context.Context) (*arbutil.Messa defer v.reorgMutex.RUnlock() wasmRoots := v.GetModuleRootsToValidate() - room := 100 // even if there is more room then that it's fine - for _, spawner := range v.validationSpawners { + rooms := make([]int, len(v.validationSpawners)) + currentSpawnerIndex := 0 + for i, spawner := range v.validationSpawners { here := spawner.Room() / len(wasmRoots) - if here <= 0 { - room = 0 - } - if here < room { - room = here + if here > 0 { + rooms[i] = here } } pos := v.validated() - 1 // to reverse the first +1 in the loop @@ -743,7 +766,13 @@ validationsLoop: log.Trace("result validated", "count", v.validated(), "blockHash", v.lastValidGS.BlockHash) continue } - if room == 0 { + for currentSpawnerIndex < len(rooms) { + if rooms[currentSpawnerIndex] > 0 { + break + } + currentSpawnerIndex++ + } + if currentSpawnerIndex == len(rooms) { log.Trace("advanceValidations: no more room", "pos", pos) return nil, nil } @@ -770,11 +799,9 @@ validationsLoop: defer validatorPendingValidationsGauge.Dec(1) var runs []validator.ValidationRun for _, moduleRoot := range wasmRoots { - for i, spawner := range v.validationSpawners { - run := spawner.Launch(input, moduleRoot) - log.Trace("advanceValidations: launched", "pos", validationStatus.Entry.Pos, "moduleRoot", moduleRoot, "spawner", i) - runs = append(runs, run) - } + run := v.validationSpawners[currentSpawnerIndex].Launch(input, moduleRoot) + log.Trace("advanceValidations: launched", "pos", validationStatus.Entry.Pos, "moduleRoot", moduleRoot, "spawner", currentSpawnerIndex) + runs = append(runs, run) } validationCtx, cancel := context.WithCancel(ctx) validationStatus.Runs = runs @@ -796,7 +823,10 @@ validationsLoop: } nonBlockingTrigger(v.progressValidationsChan) }) - room-- + rooms[currentSpawnerIndex]-- + if rooms[currentSpawnerIndex] == 0 { + currentSpawnerIndex++ + } } } } diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index acd86f862..9aae34115 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -222,14 +222,18 @@ func NewStatelessBlockValidator( config func() *BlockValidatorConfig, stack *node.Node, ) (*StatelessBlockValidator, error) { - valConfFetcher := func() *rpcclient.ClientConfig { return &config().ValidationServer } - valClient := server_api.NewValidationClient(valConfFetcher, stack) + validationSpawners := make([]validator.ValidationSpawner, len(config().ValidationServerConfigs)) + for i, serverConfig := range config().ValidationServerConfigs { + valConfFetcher := func() *rpcclient.ClientConfig { return &serverConfig } + validationSpawners[i] = server_api.NewValidationClient(valConfFetcher, stack) + } + valConfFetcher := func() *rpcclient.ClientConfig { return &config().ValidationServerConfigs[0] } execClient := server_api.NewExecutionClient(valConfFetcher, stack) validator := &StatelessBlockValidator{ config: config(), execSpawner: execClient, recorder: recorder, - validationSpawners: []validator.ValidationSpawner{valClient}, + validationSpawners: validationSpawners, inboxReader: inboxReader, inboxTracker: inbox, streamer: streamer, diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 937b8980f..dd125bdef 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -537,15 +537,15 @@ func StaticFetcherFrom[T any](t *testing.T, config *T) func() *T { } func configByValidationNode(t *testing.T, clientConfig *arbnode.Config, valStack *node.Node) { - clientConfig.BlockValidator.ValidationServer.URL = valStack.WSEndpoint() - clientConfig.BlockValidator.ValidationServer.JWTSecret = "" + clientConfig.BlockValidator.ValidationServerConfigs[0].URL = valStack.WSEndpoint() + clientConfig.BlockValidator.ValidationServerConfigs[0].JWTSecret = "" } func AddDefaultValNode(t *testing.T, ctx context.Context, nodeConfig *arbnode.Config, useJit bool) { if !nodeConfig.ValidatorRequired() { return } - if nodeConfig.BlockValidator.ValidationServer.URL != "" { + if nodeConfig.BlockValidator.ValidationServerConfigs[0].URL != "" { return } conf := valnode.TestValidationConfig @@ -921,6 +921,7 @@ func Create2ndNodeWithConfig( AddDefaultValNode(t, ctx, nodeConfig, true) Require(t, execConfig.Validate()) + Require(t, nodeConfig.Validate()) configFetcher := func() *gethexec.Config { return execConfig } currentExec, err := gethexec.CreateExecutionNode(ctx, l2stack, l2chainDb, l2blockchain, l1client, configFetcher) Require(t, err) diff --git a/util/rpcclient/rpcclient.go b/util/rpcclient/rpcclient.go index dee6e9252..00b39c62f 100644 --- a/util/rpcclient/rpcclient.go +++ b/util/rpcclient/rpcclient.go @@ -21,14 +21,14 @@ import ( ) type ClientConfig struct { - URL string `koanf:"url"` - JWTSecret string `koanf:"jwtsecret"` - Timeout time.Duration `koanf:"timeout" reload:"hot"` - Retries uint `koanf:"retries" reload:"hot"` - ConnectionWait time.Duration `koanf:"connection-wait"` - ArgLogLimit uint `koanf:"arg-log-limit" reload:"hot"` - RetryErrors string `koanf:"retry-errors" reload:"hot"` - RetryDelay time.Duration `koanf:"retry-delay"` + URL string `json:"url,omitempty" koanf:"url"` + JWTSecret string `json:"jwtsecret,omitempty" koanf:"jwtsecret"` + Timeout time.Duration `json:"timeout,omitempty" koanf:"timeout" reload:"hot"` + Retries uint `json:"retries,omitempty" koanf:"retries" reload:"hot"` + ConnectionWait time.Duration `json:"connection-wait,omitempty" koanf:"connection-wait"` + ArgLogLimit uint `json:"arg-log-limit,omitempty" koanf:"arg-log-limit" reload:"hot"` + RetryErrors string `json:"retry-errors,omitempty" koanf:"retry-errors" reload:"hot"` + RetryDelay time.Duration `json:"retry-delay,omitempty" koanf:"retry-delay"` retryErrors *regexp.Regexp } From 5169b84ecff1d8254b5e8372bb2f1cb5a30a9740 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Wed, 10 Jan 2024 17:14:12 +0100 Subject: [PATCH 599/775] Pass parent chain id to createNode instead of making chainID call using l1 client --- arbnode/node.go | 9 +++------ cmd/nitro/nitro.go | 1 + go-ethereum | 2 +- system_tests/common_test.go | 7 +++---- system_tests/das_test.go | 9 ++++----- system_tests/full_challenge_impl_test.go | 5 +++-- system_tests/recreatestate_rpc_test.go | 5 +++-- 7 files changed, 18 insertions(+), 20 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index ae350de02..f92dcefe7 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -348,6 +348,7 @@ func createNodeImpl( txOptsBatchPoster *bind.TransactOpts, dataSigner signature.DataSignerFunc, fatalErrChan chan error, + parentChainID *big.Int, ) (*Node, error) { config := configFetcher.Get() @@ -561,11 +562,6 @@ func createNodeImpl( var stakerObj *staker.Staker var messagePruner *MessagePruner - parentChainID, err := l1client.ChainID(ctx) - if err != nil { - return nil, fmt.Errorf("getting parent chain id: %w", err) - } - if config.Staker.Enable { dp, err := StakerDataposter( ctx, @@ -709,8 +705,9 @@ func CreateNode( txOptsBatchPoster *bind.TransactOpts, dataSigner signature.DataSignerFunc, fatalErrChan chan error, + parentChainID *big.Int, ) (*Node, error) { - currentNode, err := createNodeImpl(ctx, stack, exec, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan) + currentNode, err := createNodeImpl(ctx, stack, exec, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID) if err != nil { return nil, err } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 55c8d7704..45f539488 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -536,6 +536,7 @@ func mainImpl() int { l1TransactionOptsBatchPoster, dataSigner, fatalErrChan, + big.NewInt(int64(nodeConfig.ParentChain.ID)), ) if err != nil { log.Error("failed to create node", "err", err) diff --git a/go-ethereum b/go-ethereum index 1e2855b24..b1622e6ac 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 1e2855b24d6555c8cfaf471bd9e2c3d19ab5c32c +Subproject commit b1622e6ac4bf3762aebde92a585de2889d90823f diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 937b8980f..2e17a50ed 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -782,10 +782,9 @@ func createTestNodeWithL1( execConfigFetcher := func() *gethexec.Config { return execConfig } execNode, err := gethexec.CreateExecutionNode(ctx, l2stack, l2chainDb, l2blockchain, l1client, execConfigFetcher) Require(t, err) - currentNode, err = arbnode.CreateNode( ctx, l2stack, execNode, l2arbDb, NewFetcherFromConfig(nodeConfig), l2blockchain.Config(), l1client, - addresses, sequencerTxOptsPtr, sequencerTxOptsPtr, dataSigner, fatalErrChan, + addresses, sequencerTxOptsPtr, sequencerTxOptsPtr, dataSigner, fatalErrChan, big.NewInt(1337), ) Require(t, err) @@ -821,7 +820,7 @@ func createTestNode( execNode, err := gethexec.CreateExecutionNode(ctx, stack, chainDb, blockchain, nil, execConfigFetcher) Require(t, err) - currentNode, err := arbnode.CreateNode(ctx, stack, execNode, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), nil, nil, nil, nil, nil, feedErrChan) + currentNode, err := arbnode.CreateNode(ctx, stack, execNode, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), nil, nil, nil, nil, nil, feedErrChan, big.NewInt(1337)) Require(t, err) // Give the node an init message @@ -925,7 +924,7 @@ func Create2ndNodeWithConfig( currentExec, err := gethexec.CreateExecutionNode(ctx, l2stack, l2chainDb, l2blockchain, l1client, configFetcher) Require(t, err) - currentNode, err := arbnode.CreateNode(ctx, l2stack, currentExec, l2arbDb, NewFetcherFromConfig(nodeConfig), l2blockchain.Config(), l1client, first.DeployInfo, &txOpts, &txOpts, dataSigner, feedErrChan) + currentNode, err := arbnode.CreateNode(ctx, l2stack, currentExec, l2arbDb, NewFetcherFromConfig(nodeConfig), l2blockchain.Config(), l1client, first.DeployInfo, &txOpts, &txOpts, dataSigner, feedErrChan, big.NewInt(13)) Require(t, err) err = currentNode.Start(ctx) diff --git a/system_tests/das_test.go b/system_tests/das_test.go index 6db339521..96de52e19 100644 --- a/system_tests/das_test.go +++ b/system_tests/das_test.go @@ -123,7 +123,7 @@ func TestDASRekey(t *testing.T) { l1NodeConfigB := arbnode.ConfigDefaultL1NonSequencerTest() sequencerTxOpts := l1info.GetDefaultTransactOpts("Sequencer", ctx) sequencerTxOptsPtr := &sequencerTxOpts - + parentChainID := big.NewInt(1337) { authorizeDASKeyset(t, ctx, pubkeyA, l1info, l1client) @@ -141,8 +141,7 @@ func TestDASRekey(t *testing.T) { l1NodeConfigA.DataAvailability.ParentChainNodeURL = "none" execA, err := gethexec.CreateExecutionNode(ctx, l2stackA, l2chainDb, l2blockchain, l1client, gethexec.ConfigDefaultTest) Require(t, err) - - nodeA, err := arbnode.CreateNode(ctx, l2stackA, execA, l2arbDb, NewFetcherFromConfig(l1NodeConfigA), l2blockchain.Config(), l1client, addresses, sequencerTxOptsPtr, sequencerTxOptsPtr, nil, feedErrChan) + nodeA, err := arbnode.CreateNode(ctx, l2stackA, execA, l2arbDb, NewFetcherFromConfig(l1NodeConfigA), l2blockchain.Config(), l1client, addresses, sequencerTxOptsPtr, sequencerTxOptsPtr, nil, feedErrChan, parentChainID) Require(t, err) Require(t, nodeA.Start(ctx)) l2clientA := ClientForStack(t, l2stackA) @@ -189,7 +188,7 @@ func TestDASRekey(t *testing.T) { Require(t, err) l1NodeConfigA.DataAvailability.RPCAggregator = aggConfigForBackend(t, backendConfigB) - nodeA, err := arbnode.CreateNode(ctx, l2stackA, execA, l2arbDb, NewFetcherFromConfig(l1NodeConfigA), l2blockchain.Config(), l1client, addresses, sequencerTxOptsPtr, sequencerTxOptsPtr, nil, feedErrChan) + nodeA, err := arbnode.CreateNode(ctx, l2stackA, execA, l2arbDb, NewFetcherFromConfig(l1NodeConfigA), l2blockchain.Config(), l1client, addresses, sequencerTxOptsPtr, sequencerTxOptsPtr, nil, feedErrChan, parentChainID) Require(t, err) Require(t, nodeA.Start(ctx)) l2clientA := ClientForStack(t, l2stackA) @@ -322,7 +321,7 @@ func TestDASComplexConfigAndRestMirror(t *testing.T) { sequencerTxOpts := l1info.GetDefaultTransactOpts("Sequencer", ctx) sequencerTxOptsPtr := &sequencerTxOpts - nodeA, err := arbnode.CreateNode(ctx, l2stackA, execA, l2arbDb, NewFetcherFromConfig(l1NodeConfigA), l2blockchain.Config(), l1client, addresses, sequencerTxOptsPtr, sequencerTxOptsPtr, dataSigner, feedErrChan) + nodeA, err := arbnode.CreateNode(ctx, l2stackA, execA, l2arbDb, NewFetcherFromConfig(l1NodeConfigA), l2blockchain.Config(), l1client, addresses, sequencerTxOptsPtr, sequencerTxOptsPtr, dataSigner, feedErrChan, big.NewInt(1337)) Require(t, err) Require(t, nodeA.Start(ctx)) l2clientA := ClientForStack(t, l2stackA) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index 43ba6a056..118d17ec8 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -278,7 +278,8 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall asserterRollupAddresses.SequencerInbox = asserterSeqInboxAddr asserterExec, err := gethexec.CreateExecutionNode(ctx, asserterL2Stack, asserterL2ChainDb, asserterL2Blockchain, l1Backend, gethexec.ConfigDefaultTest) Require(t, err) - asserterL2, err := arbnode.CreateNode(ctx, asserterL2Stack, asserterExec, asserterL2ArbDb, NewFetcherFromConfig(conf), chainConfig, l1Backend, asserterRollupAddresses, nil, nil, nil, fatalErrChan) + parentChainID := big.NewInt(1337) + asserterL2, err := arbnode.CreateNode(ctx, asserterL2Stack, asserterExec, asserterL2ArbDb, NewFetcherFromConfig(conf), chainConfig, l1Backend, asserterRollupAddresses, nil, nil, nil, fatalErrChan, parentChainID) Require(t, err) err = asserterL2.Start(ctx) Require(t, err) @@ -289,7 +290,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall challengerRollupAddresses.SequencerInbox = challengerSeqInboxAddr challengerExec, err := gethexec.CreateExecutionNode(ctx, challengerL2Stack, challengerL2ChainDb, challengerL2Blockchain, l1Backend, gethexec.ConfigDefaultTest) Require(t, err) - challengerL2, err := arbnode.CreateNode(ctx, challengerL2Stack, challengerExec, challengerL2ArbDb, NewFetcherFromConfig(conf), chainConfig, l1Backend, &challengerRollupAddresses, nil, nil, nil, fatalErrChan) + challengerL2, err := arbnode.CreateNode(ctx, challengerL2Stack, challengerExec, challengerL2ArbDb, NewFetcherFromConfig(conf), chainConfig, l1Backend, &challengerRollupAddresses, nil, nil, nil, fatalErrChan, parentChainID) Require(t, err) err = challengerL2.Start(ctx) Require(t, err) diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index 9429155d7..f5bdca097 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -334,7 +334,8 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig execNode, err := gethexec.CreateExecutionNode(ctx1, stack, chainDb, blockchain, nil, execConfigFetcher) Require(t, err) - node, err := arbnode.CreateNode(ctx1, stack, execNode, arbDb, NewFetcherFromConfig(arbnode.ConfigDefaultL2Test()), blockchain.Config(), nil, nil, nil, nil, nil, feedErrChan) + parentChainID := big.NewInt(1337) + node, err := arbnode.CreateNode(ctx1, stack, execNode, arbDb, NewFetcherFromConfig(arbnode.ConfigDefaultL2Test()), blockchain.Config(), nil, nil, nil, nil, nil, feedErrChan, parentChainID) Require(t, err) err = node.TxStreamer.AddFakeInitMessage() Require(t, err) @@ -375,7 +376,7 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig execNode, err = gethexec.CreateExecutionNode(ctx1, stack, chainDb, blockchain, nil, execConfigFetcher) Require(t, err) - node, err = arbnode.CreateNode(ctx, stack, execNode, arbDb, NewFetcherFromConfig(arbnode.ConfigDefaultL2Test()), blockchain.Config(), nil, node.DeployInfo, nil, nil, nil, feedErrChan) + node, err = arbnode.CreateNode(ctx, stack, execNode, arbDb, NewFetcherFromConfig(arbnode.ConfigDefaultL2Test()), blockchain.Config(), nil, node.DeployInfo, nil, nil, nil, feedErrChan, parentChainID) Require(t, err) Require(t, node.Start(ctx)) client = ClientForStack(t, stack) From bc3186f9e6a820ec906d74941248ecb1869cff19 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 11 Jan 2024 09:51:49 +0100 Subject: [PATCH 600/775] Update go-ethereum pin --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index b1622e6ac..1e2855b24 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit b1622e6ac4bf3762aebde92a585de2889d90823f +Subproject commit 1e2855b24d6555c8cfaf471bd9e2c3d19ab5c32c From bbb8cf7c88151c8e9d0eca03e1179629370d8b7e Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Thu, 11 Jan 2024 14:39:15 +0530 Subject: [PATCH 601/775] optimize impl and address PR comments --- broadcaster/backlog/backlog.go | 27 +++++++++++++++++++++------ broadcaster/message/message.go | 6 +++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index d2f7c66be..366092999 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -56,24 +56,30 @@ func (b *backlog) Head() BacklogSegment { return b.head.Load() } -func (b *backlog) backlogSizeInBytes() uint64 { +func (b *backlog) backlogSizeInBytes() (uint64, error) { if b.head.Load() == nil || b.tail.Load() == nil { - return 0 + return 0, errors.New("the head or tail segment of feed backlog is nil") } headSeg := b.head.Load() headSeg.messagesLock.RLock() + if len(headSeg.messages) == 0 { + return 0, errors.New("head segment of the feed backlog is empty") + } headMsg := headSeg.messages[0] headSeg.messagesLock.RUnlock() tailSeg := b.tail.Load() tailSeg.messagesLock.RLock() + if len(tailSeg.messages) == 0 { + return 0, errors.New("tail segment of the feed backlog is empty") + } tailMsg := tailSeg.messages[len(tailSeg.messages)-1] size := tailMsg.CumulativeSumMsgSize tailSeg.messagesLock.RUnlock() size -= headMsg.CumulativeSumMsgSize - size += uint64(len(headMsg.Signature) + len(headMsg.Message.Message.L2msg) + 160) - return size + size += headMsg.Size() + return size, nil } // Append will add the given messages to the backlogSegment at head until @@ -83,6 +89,12 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { if bm.ConfirmedSequenceNumberMessage != nil { b.delete(uint64(bm.ConfirmedSequenceNumberMessage.SequenceNumber)) + size, err := b.backlogSizeInBytes() + if err != nil { + log.Warn("error calculating backlogSizeInBytes", "err", err) + } else { + backlogSizeInBytesGauge.Update(int64(size)) + } } lookupByIndex := b.lookupByIndex.Load() @@ -98,7 +110,9 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { prevMsgIdx := segment.End() if segment.count() >= b.config().SegmentLimit { segment.messagesLock.RLock() - msg.CumulativeSumMsgSize = segment.messages[len(segment.messages)-1].CumulativeSumMsgSize + if len(segment.messages) > 0 { + msg.CumulativeSumMsgSize = segment.messages[len(segment.messages)-1].CumulativeSumMsgSize + } segment.messagesLock.RUnlock() nextSegment := newBacklogSegment() @@ -115,6 +129,7 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { b.head.Store(segment) b.tail.Store(segment) b.messageCount.Store(0) + backlogSizeInBytesGauge.Update(0) log.Warn(err.Error()) } else if errors.Is(err, errSequenceNumberSeen) { log.Info("ignoring message sequence number, already in backlog", "message sequence number", msg.SequenceNumber) @@ -124,9 +139,9 @@ func (b *backlog) Append(bm *m.BroadcastMessage) error { } lookupByIndex.Store(uint64(msg.SequenceNumber), segment) b.messageCount.Add(1) + backlogSizeInBytesGauge.Inc(int64(msg.Size())) } - backlogSizeInBytesGauge.Update(int64(b.backlogSizeInBytes())) backlogSizeGauge.Update(int64(b.Count())) return nil } diff --git a/broadcaster/message/message.go b/broadcaster/message/message.go index 076eb9642..a575ae5cd 100644 --- a/broadcaster/message/message.go +++ b/broadcaster/message/message.go @@ -39,8 +39,12 @@ type BroadcastFeedMessage struct { CumulativeSumMsgSize uint64 `json:"-"` } +func (m *BroadcastFeedMessage) Size() uint64 { + return uint64(len(m.Signature) + len(m.Message.Message.L2msg) + 160) +} + func (m *BroadcastFeedMessage) UpdateCumulativeSumMsgSize(val uint64) { - m.CumulativeSumMsgSize += val + uint64(len(m.Signature)+len(m.Message.Message.L2msg)+160) + m.CumulativeSumMsgSize += val + m.Size() } func (m *BroadcastFeedMessage) Hash(chainId uint64) (common.Hash, error) { From 9dd855619bbf393baa06cdef322248cb35a1a3ec Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Thu, 11 Jan 2024 16:01:51 +0530 Subject: [PATCH 602/775] address PR comments --- cmd/seq-coordinator-manager/seq-coordinator-manager.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/seq-coordinator-manager/seq-coordinator-manager.go b/cmd/seq-coordinator-manager/seq-coordinator-manager.go index daafe1e5e..43d90441e 100644 --- a/cmd/seq-coordinator-manager/seq-coordinator-manager.go +++ b/cmd/seq-coordinator-manager/seq-coordinator-manager.go @@ -164,6 +164,7 @@ func main() { flex.SetDirection(tview.FlexRow). AddItem(priorityHeading, 0, 1, false). AddItem(tview.NewFlex(). + // fixedSize is maxURLSize plus 20 characters to accomodate ellipsis, statuses and emojis AddItem(prioritySeqList, seqManager.maxURLSize+20, 0, true). AddItem(priorityForm, 0, 3, true), 0, 12, true). AddItem(nonPriorityHeading, 0, 1, false). From 8b86e0e5016f01323ab870fa10971154d242965e Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 11 Jan 2024 16:17:37 +0000 Subject: [PATCH 603/775] fix starting second node in pruning system test, add more checks --- system_tests/pruning_test.go | 96 +++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 34 deletions(-) diff --git a/system_tests/pruning_test.go b/system_tests/pruning_test.go index ef82c0466..bdb6be6a3 100644 --- a/system_tests/pruning_test.go +++ b/system_tests/pruning_test.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/trie" "github.com/offchainlabs/nitro/cmd/conf" "github.com/offchainlabs/nitro/cmd/pruning" "github.com/offchainlabs/nitro/execution/gethexec" @@ -32,35 +33,34 @@ func TestPruning(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - var dataDir string - - func() { - builder := NewNodeBuilder(ctx).DefaultConfig(t, true) - _ = builder.Build(t) - dataDir = builder.dataDir - l2cleanupDone := false - defer func() { - if !l2cleanupDone { - builder.L2.cleanup() - } - builder.L1.cleanup() - }() - builder.L2Info.GenerateAccount("User2") - var txs []*types.Transaction - for i := uint64(0); i < 200; i++ { - tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) - txs = append(txs, tx) - err := builder.L2.Client.SendTransaction(ctx, tx) - Require(t, err) - } - for _, tx := range txs { - _, err := builder.L2.EnsureTxSucceeded(tx) - Require(t, err) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + _ = builder.Build(t) + l2cleanupDone := false + defer func() { + if !l2cleanupDone { + builder.L2.cleanup() } - l2cleanupDone = true - builder.L2.cleanup() - t.Log("stopped l2 node") + builder.L1.cleanup() + }() + builder.L2Info.GenerateAccount("User2") + var txs []*types.Transaction + for i := uint64(0); i < 200; i++ { + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) + txs = append(txs, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) + Require(t, err) + } + for _, tx := range txs { + _, err := builder.L2.EnsureTxSucceeded(tx) + Require(t, err) + } + lastBlock, err := builder.L2.Client.BlockNumber(ctx) + Require(t, err) + l2cleanupDone = true + builder.L2.cleanup() + t.Log("stopped l2 node") + func() { stack, err := node.New(builder.l2StackConfig) Require(t, err) defer stack.Close() @@ -105,15 +105,43 @@ func TestPruning(t *testing.T) { Fatal(t, "The db doesn't have less entries after pruning then before. Before:", chainDbEntriesBeforePruning, "After:", chainDbEntriesAfterPruning) } }() - builder := NewNodeBuilder(ctx).DefaultConfig(t, true) - builder.dataDir = dataDir - cancel = builder.Build(t) - defer cancel() - builder.L2Info.GenerateAccount("User2") + testClient, cleanup := builder.Build2ndNode(t, &SecondNodeParams{stackConfig: builder.l2StackConfig}) + defer cleanup() + + currentBlock := uint64(0) + // wait for the chain to catch up + for currentBlock < lastBlock { + currentBlock, err = testClient.Client.BlockNumber(ctx) + Require(t, err) + } + + currentBlock, err = testClient.Client.BlockNumber(ctx) + Require(t, err) + bc := testClient.ExecNode.Backend.ArbInterface().BlockChain() + triedb := bc.StateCache().TrieDB() + var start uint64 + if currentBlock+1 >= builder.execConfig.Caching.BlockCount { + start = currentBlock + 1 - builder.execConfig.Caching.BlockCount + } else { + start = 0 + } + for i := start; i <= currentBlock; i++ { + header := bc.GetHeaderByNumber(i) + _, err := bc.StateAt(header.Root) + Require(t, err) + tr, err := trie.New(trie.TrieID(header.Root), triedb) + Require(t, err) + it, err := tr.NodeIterator(nil) + Require(t, err) + for it.Next(true) { + } + Require(t, it.Error()) + } + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) - err := builder.L2.Client.SendTransaction(ctx, tx) + err = testClient.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = builder.L2.EnsureTxSucceeded(tx) + _, err = testClient.EnsureTxSucceeded(tx) Require(t, err) } From d6e4f734982a59b76bd2c58a6214e6387432a5d4 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Thu, 11 Jan 2024 23:00:57 +0530 Subject: [PATCH 604/775] address PR comments --- broadcaster/backlog/backlog.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 366092999..67df9e6bb 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -57,10 +57,15 @@ func (b *backlog) Head() BacklogSegment { } func (b *backlog) backlogSizeInBytes() (uint64, error) { - if b.head.Load() == nil || b.tail.Load() == nil { + headSeg := b.head.Load() + tailSeg := b.tail.Load() + if headSeg == nil || tailSeg == nil { + if headSeg == tailSeg { + return 0, nil + } return 0, errors.New("the head or tail segment of feed backlog is nil") } - headSeg := b.head.Load() + headSeg.messagesLock.RLock() if len(headSeg.messages) == 0 { return 0, errors.New("head segment of the feed backlog is empty") @@ -68,7 +73,6 @@ func (b *backlog) backlogSizeInBytes() (uint64, error) { headMsg := headSeg.messages[0] headSeg.messagesLock.RUnlock() - tailSeg := b.tail.Load() tailSeg.messagesLock.RLock() if len(tailSeg.messages) == 0 { return 0, errors.New("tail segment of the feed backlog is empty") From 1e743ca226a46917b7c5fbe12238939f45b080d6 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Thu, 11 Jan 2024 23:29:14 +0530 Subject: [PATCH 605/775] fix failing custom lint --- broadcaster/backlog/backlog.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/broadcaster/backlog/backlog.go b/broadcaster/backlog/backlog.go index 67df9e6bb..f6501105c 100644 --- a/broadcaster/backlog/backlog.go +++ b/broadcaster/backlog/backlog.go @@ -60,7 +60,7 @@ func (b *backlog) backlogSizeInBytes() (uint64, error) { headSeg := b.head.Load() tailSeg := b.tail.Load() if headSeg == nil || tailSeg == nil { - if headSeg == tailSeg { + if headSeg == nil && tailSeg == nil { return 0, nil } return 0, errors.New("the head or tail segment of feed backlog is nil") From 199fa1ff17ea0b2e19e4e0d98ae5c6ea7f8ab7cb Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 12 Jan 2024 17:47:36 -0600 Subject: [PATCH 606/775] Add option to disable batch poster access lists --- arbnode/batch_poster.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 4bd0e2490..a75e7b524 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -122,6 +122,7 @@ type BatchPosterConfig struct { ParentChainWallet genericconf.WalletConfig `koanf:"parent-chain-wallet"` L1BlockBound string `koanf:"l1-block-bound" reload:"hot"` L1BlockBoundBypass time.Duration `koanf:"l1-block-bound-bypass" reload:"hot"` + UseAccessLists bool `koanf:"use-access-lists" reload:"hot"` gasRefunder common.Address l1BlockBound l1BlockBound @@ -168,6 +169,7 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".redis-url", DefaultBatchPosterConfig.RedisUrl, "if non-empty, the Redis URL to store queued transactions in") f.String(prefix+".l1-block-bound", DefaultBatchPosterConfig.L1BlockBound, "only post messages to batches when they're within the max future block/timestamp as of this L1 block tag (\"safe\", \"finalized\", \"latest\", or \"ignore\" to ignore this check)") f.Duration(prefix+".l1-block-bound-bypass", DefaultBatchPosterConfig.L1BlockBoundBypass, "post batches even if not within the layer 1 future bounds if we're within this margin of the max delay") + f.Bool(prefix+".use-access-lists", DefaultBatchPosterConfig.UseAccessLists, "post batches with access lists to reduce gas usage (disabled for L3s)") redislock.AddConfigOptions(prefix+".redis-lock", f) dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f, dataposter.DefaultDataPosterConfig) genericconf.WalletConfigAddOptions(prefix+".parent-chain-wallet", f, DefaultBatchPosterConfig.ParentChainWallet.Pathname) @@ -190,6 +192,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ ParentChainWallet: DefaultBatchPosterL1WalletConfig, L1BlockBound: "", L1BlockBoundBypass: time.Hour, + UseAccessLists: true, RedisLock: redislock.DefaultCfg, } @@ -216,6 +219,7 @@ var TestBatchPosterConfig = BatchPosterConfig{ ParentChainWallet: DefaultBatchPosterL1WalletConfig, L1BlockBound: "", L1BlockBoundBypass: time.Hour, + UseAccessLists: true, } type BatchPosterOpts struct { @@ -298,7 +302,7 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e // Dataposter sender may be external signer address, so we should initialize // access list after initializing dataposter. b.accessList = func(SequencerInboxAccs, AfterDelayedMessagesRead int) types.AccessList { - if opts.L1Reader.IsParentChainArbitrum() { + if !b.config().UseAccessLists || opts.L1Reader.IsParentChainArbitrum() { // Access lists cost gas instead of saving gas when posting to L2s, // because data is expensive in comparison to computation. return nil From 3424519b0521a7e47d5b06ce06e3d4eb64c5bcd9 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Sat, 13 Jan 2024 00:36:58 +0000 Subject: [PATCH 607/775] add delay while polling block number in pruning test --- system_tests/pruning_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system_tests/pruning_test.go b/system_tests/pruning_test.go index bdb6be6a3..e9e99dffc 100644 --- a/system_tests/pruning_test.go +++ b/system_tests/pruning_test.go @@ -3,6 +3,7 @@ package arbtest import ( "context" "testing" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" @@ -114,6 +115,7 @@ func TestPruning(t *testing.T) { for currentBlock < lastBlock { currentBlock, err = testClient.Client.BlockNumber(ctx) Require(t, err) + time.Sleep(20 * time.Millisecond) } currentBlock, err = testClient.Client.BlockNumber(ctx) From 44319b73ee718288d08a4408f018a486a56db3cf Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 16 Jan 2024 12:02:23 -0700 Subject: [PATCH 608/775] Add a check that the database chain id matches the config --- cmd/nitro/init.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index ada195b5c..4cf5dcda0 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -37,6 +37,7 @@ import ( "github.com/offchainlabs/nitro/cmd/util" "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/statetransfer" + "github.com/offchainlabs/nitro/util/arbmath" ) func downloadInit(ctx context.Context, initConfig *conf.InitConfig) (string, error) { @@ -163,6 +164,9 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if readOnlyDb, err := stack.OpenDatabaseWithFreezer("l2chaindata", 0, 0, "", "", true); err == nil { if chainConfig := gethexec.TryReadStoredChainConfig(readOnlyDb); chainConfig != nil { readOnlyDb.Close() + if !arbmath.BigEquals(chainConfig.ChainID, chainId) { + return nil, nil, fmt.Errorf("database has chain ID %v but config has chain ID %v (are you sure this database is for the right chain?)", chainConfig.ChainID, chainId) + } chainDb, err := stack.OpenDatabaseWithFreezer("l2chaindata", config.Execution.Caching.DatabaseCache, config.Persistent.Handles, config.Persistent.Ancient, "", false) if err != nil { return chainDb, nil, err From b8afe5192d7c7670812af84847b11d885fdd8473 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 16 Jan 2024 18:40:02 -0700 Subject: [PATCH 609/775] Fix trusted setup JSON as per ethereum/consensus-specs#3583 --- arbitrator/prover/src/kzg-trusted-setup.json | 4098 ++++++++++++++++++ 1 file changed, 4098 insertions(+) diff --git a/arbitrator/prover/src/kzg-trusted-setup.json b/arbitrator/prover/src/kzg-trusted-setup.json index c6d724efa..6793490e2 100644 --- a/arbitrator/prover/src/kzg-trusted-setup.json +++ b/arbitrator/prover/src/kzg-trusted-setup.json @@ -1,4 +1,4102 @@ { + "g1_monomial": [ + "0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb", + "0xad3eb50121139aa34db1d545093ac9374ab7bca2c0f3bf28e27c8dcd8fc7cb42d25926fc0c97b336e9f0fb35e5a04c81", + "0x8029c8ce0d2dce761a7f29c2df2290850c85bdfaec2955626d7acc8864aeb01fe16c9e156863dc63b6c22553910e27c1", + "0xb1386c995d3101d10639e49b9e5d39b9a280dcf0f135c2e6c6928bb3ab8309a9da7178f33925768c324f11c3762cfdd5", + "0x9596d929610e6d2ed3502b1bb0f1ea010f6b6605c95d4859f5e53e09fa68dc71dfd5874905447b5ec6cd156a76d6b6e8", + "0x851e3c3d4b5b7cdbba25d72abf9812cf3d7c5a9dbdec42b6635e2add706cbeea18f985afe5247459f6c908620322f434", + "0xb10f4cf8ec6e02491bbe6d9084d88c16306fdaf399fef3cd1453f58a4f7633f80dc60b100f9236c3103eaf727468374f", + "0xade11ec630127e04d17e70db0237d55f2ff2a2094881a483797e8cddb98b622245e1f608e5dcd1172b9870e733b4a32f", + "0xaf58c8a2f58f904ce20db81005331bf2d251e227e7d1bef575d691bdca842e6233eb2e26c2e116a61a78594772b38d25", + "0xb3c1313c31ec82da5a7a09e9cf6656ca598c243345fe8d4828e520ade91787ffb8b9867db789b34ad67cef47b26ff86d", + "0xa8ed8a235355948e0b04be080b7b3e145293accefb4704d1da9050796b2f6870516c1ebf77ae6a65359edcfd016c0f36", + "0x80e792d5ba24b8058f6d7291a2ec5cb68aab1e16e96d793128e86815631baf42c56b6205c19e25ce9727bd1fd6f9defb", + "0x816288c5d726b094e3fdf95cb8882f442c4d9d1101b92c7938a7dfd49bc50636d73ea1b05f75eb731c908c8fd8dee717", + "0xae009128d128ba2e1519bfa7a0c01ed494a7d461c3aba60f8a301701fed61fe4e31d6c79ce189542ae51df91e73ce1b3", + "0x96a866d60a9007d05825c332476a83e869e15b11d7257172a67690ea9bd3efea44bf9c8d42191454eb04fcf110b16396", + "0x8b250a2a06419adb9b611e89f7f8f2990aa301949b533ad3bf17c4a61ab5f5be0b1d5e2b571864d13f1bb75805c7795d", + "0x8450f49facf2e620fa45ee90e1801178842d927a2a25fc6ed7ba99a4eec7ae40eebfee41028eaa84f107f4a777694976", + "0x91049080cf659c0985a22d1366e59191bb89663f922e8168b9b7d85c8a73d74a6d9dceefd855d3d858b493670c750581", + "0xa1e167aeb2008087f3195926f1985c0a459d6ec57237255b1473a96de4e2c1cf766127c862c7dc853a6909e67cb06cf7", + "0xb667c0d4e26e20698b07567358625d5f003839c92de8088e12dbd74a6f6a3156b4ea8d252c9ad62af5f6c4fec1cf6cc7", + "0x8e4b5e304c0b1b161ae3e4b68b5e3ac66c42acd7c1ee2458044f6527c508a93995e50894d72d57c1350f91afe72775ff", + "0x8c642640aa7915421cdc21fd639f88a42052b1cfa358ff7702e60793a92b7b5926dae15a0c8f8f59cd3013f01c159ba3", + "0xa356f35e713cfc283056bf539de54a21731e61efb4c47319f20de4a4b723d76a33b65f4a67d298b9ec5c2a1579418657", + "0x93ce204146ce95f484dc79c27919a16c9e3fc14a9111c6c63d44491158d5838117d20851cc3227a5e8ba6ccf79e77f39", + "0xb585664cbb9a84b52f89114e1cf0cf1171bea78a136dc1404ac88a11210b2debc3b7a55e702da93ff629095c134a295e", + "0xb6dfd444ec7fdceb14c6328f26ca12c3f9fc4327d8d8c68948e92e7e61262b82d833a65a9e3af6353ffa832b6da25705", + "0xb4d4b8eb9ecfffe3f0d48fb4149c7b31aec1da7041ec03bd0750c52a2a7cbc3a7cfbf09d5bfdc56e3860826a62d0bb91", + "0xa4e248e3d61db52da9683fef188579c470d65e2df9064726847b1599fc774049ffdc6ef2ae578d5ed7874f1298ecdf69", + "0xa68a0fffc2e37d3183feb01b42234c0f4e510f9dc29d09c571e6da00fecad9da224cd0f31550070148667e226c4ca413", + "0x86adda2ffecb77236c18005051f31f9657a0d50fef2a1175dfda32e74d5d53df825c10f289eb0ad39df0c64fc9bc7729", + "0x998266d5c9c3764ed97d66fa9ed176af043999652bae19f0657c8328629d30af453230e3681c5a38e2f01e389ed8d825", + "0xa05261554d3c620af0c914cf27ab98f5d3593c33ab313c198e0c40d6c72022eb5943778cd4f73e9fe8383392a7004976", + "0xad243fb3631bf90fedb9d679fd71fc0cf06bda028591ded2bd4c634ea7b3c2bd22eca2ab318fcdaa6c2cda1e63e1c57b", + "0x89b9859a04f903c95e97fb2951f01cc6418a2505eee0b5bc7266b4d33e01b69b9fe7dc56fa9ebb5856095be0925a422d", + "0xa68d118343a5bbfbbab95ff9bfe53aeb7fdbaf16db983e6f4456366df2aa01fbdb6ee9901cb102fc7d2bd099be2f1f3e", + "0xb49301f25d5a9dd2ec60ddb0b4b477291958487efea9e54dc0e4ef388f03b8bbadd13259d191f7a0b7513876767d8282", + "0x8b93df7fb4513f67749905fd43db78f7026589b704ebb9ea3255d0ad6415437799f40f02e07efccda1e6fd5e8cd0a721", + "0xad88769ace96455da37c3c9019a9f523c694643be3f6b37b1e9dcc5053d1fe8e463abebdb1b3ef2f2fb801528a01c47c", + "0x80f0eb5dcbfaaf421bf59a8b9bd5245c4823c94510093e23e0b0534647fb5525a25ea3aeea0a927a1ee20c057f2c9234", + "0xb10ad82ea6a5aeabe345d00eb17910d6942b6862f7f3773c7d321194e67c9cced0b3310425662606634dcd7f8b976c04", + "0x82f6fd91f87822f6cc977808eeac77889f4a32fb0d618e784b2331263d0ffa820b3f70b069d32e0319c9e033ab75d3b4", + "0x9436d3dc6b5e25b1f695f8c6c1c553dab312ccace4dac3afddc141d3506467cd50cb04a49ea96ea7f5a8a7b0fc65ef37", + "0x8e0a9491651d52be8ebf4315fbbb410272f9a74b965d33b79ff1b9e1be3be59e43d9566773560e43280549c348e48f01", + "0x8809137e5d3a22400d6e645a9bd84e21c492371736c7e62c51cef50fee3aa7f2405724367a83fd051ff702d971167f67", + "0xb536a24f31a346de7f9863fc351fa602158404d2f94747eebe43abf1f21bf8f95a64146c02a4bec27b503f546789a388", + "0xb5cdf5a04fc12a0e0ef7545830061dff7fd8abea46e48fbe6235109e6c36ee6bffcb9529e2f3d0d701cf58bbfb6a4197", + "0xab15377525753467d042b7931f66f862cbbb77464212c9aa72d4e5c04375ef55f619b3a446091c1ba1a3b5d9f05e538f", + "0x905a75b943ad017ff78ea6ddd1d28a45c7273ee1c2e5e3353685813793ead3370c09cabd903fcab9d8b1c6961372d486", + "0x8147df4324faddc02fb0896367a7647b719b6499a361aecfdd3a34296fa6768ad31c34f9e873fd1e683386c44651883e", + "0xac91d08570dd91f89d2e01dca67cdc83b640e20f073ea9f0734759c92182bb66c5d645f15ebd91ed705b66486ed2088d", + "0xac6295ef2513bbea7ef4cdcf37d280300c34e63c4b9704663d55891a61bf5c91b04cc1d202a3a0a7c4520c30edc277c7", + "0xb604be776a012095c0d4ebc77797dd8dec62a54c0559fb2185d7bac6b50d4e5fd471ac2d7f4523206d5d8178eabd9a87", + "0x80ead68def272ce3f57951145e71ed6dc26da98e5825ef439af577c0c5de766d4e39207f205d5d21db903d89f37bbb02", + "0x9950b4a830388c897158c7fe3921e2fe24beedc7c84e2024e8b92b9775f8f99593b54a86b8870ec5087734295ba06032", + "0xb89ba714adabf94e658a7d14ac8fc197376a416841c2a80e1a6dde4f438d5f747d1fb90b39e8ea435c59d6ecda13dea1", + "0xb0c78e7cc60bd05be46d48fbb0421a678c7f14b8d93730deb66fbe1647613b2c62b5075126d917047820c57fc3509cb9", + "0xa860c4acc5444e9ae987e8c93cb9a5f17d954d63c060cc616f724e26bc73d2c54cd36e0492d1fde173847278e55942ba", + "0x8fb8269c9d5c15428e8d45da1251e4c4a4b600d47da0caea29fef246854d8fb6acae86a8e6440d0c429d8dd9c2dfee0c", + "0x96c5d8eb6fd5c525b348ee4335d200139e437e4be83690af0f35b7f336a7cda8c6d2958647988b84da9f2dd7bbb7710b", + "0xa7f62141c4346cc14e9823dc38ac7d587b0427022afc1498d12ee2c43f6ac3a82167057e670dd524b74137f8c3ceb56d", + "0x956aac50d06b46a3e94397f163f593f5010d366aa2d816c2205c7d0f47f90cf0f36c169e964f9bcf698d49182d47d91f", + "0xb812899bcdc0e70d79ca729cb01104bf60e1357b9085a10f64f3ba9865d57e9abd0a505a502d4de07afb46f4d266be2f", + "0xabce02c7e1372e25d40944dc9ece2904a8f59c8854c5f2875fe63ace8ce37d97881f4f9ab4f7bad070ec8e0daee58d3f", + "0x8fb13c515b2d6abb4e14ed753fad5cc36c3631dfe21a23d0f603aad719423dd5423157eefcbd9a9c6074e155b79eb38d", + "0xa9ef67304dc297ab5af778cf8afa849eeac27db4b6978963e97b95ef7a8d3264d0d07775f728c298a2b6daed2ecf5053", + "0xa9b975520adb066e2ff2a4cde53284c23bc84261a22dc43b1634d99eff8e7892e46bb6e6da7319c9e72788aa9ea7a1ea", + "0xa6eaea4ab4206294474d9b956d9d3188d558a5633de2bd05df0d3bac03dbcbe4ed85406349c1d2e660b77c6da1f5bf8c", + "0xaf4a19f77290dddee762e1e0d4bc9945aacea3f75756ae46cd3e58a8f74d1b5db73e4834687946b0f39191e32f2fed0c", + "0xaafa6523f58f1a4cabc924c86d842816d606afeea21fa4b2b8b9573425810fdcc41c98888318e868f9c05e2be12178a3", + "0x8ef38fba0a3fa4ebe985239c8b759c22aaef0c57e6f39050a651c869487803b0d1e389c3d958fb5a7f37740f050ac69e", + "0xb07dfc9f85913c608ca7596a2e361f05e4853fad00e796fd492d247de6414892ce160f627669b1ba933b6ad726415d4e", + "0x94da679ad1d78b2bff5283c938f17b2a7d6e9cbcdf59d340e6dfb652951c7a9e852ac0590f99cfee9631b9410f6f00ea", + "0x98a907c9c021a5b034d3720197c160a82c4b7146cb73d48efeed99b9d0c6b831812cf80ac7e19e85a676a8cd3ead72de", + "0xadb746595466a12929019d0048cea33236b05c1229d2eba73b259a18a786f2bc3f05fc0598d8ce253cecb80bdf679aaf", + "0xa2fbac016996d68f9027a157b0a3f6a336144a798d6113adfcda3a5d05b62c31f108f112aa915906aef22b7f83b9228b", + "0x81841dea1904406d1b6fa49b4b3f7f6cb40b7646cf44d36c9fa07e3dee29f8e47324b40d8356ddf653109673c3374e9b", + "0xa3edbb8aac5e60c775775cbdb19067341b2e2530de48738e84c2c07151241ee31f0d8333bf20c2bc9dcb7b2e638a6b5e", + "0xb8aa6890e22964828787ce86460d3a32f12a655bb5c28de500f2fcf6b61e3334640ec6ba96029a4912af0d18df4b4139", + "0x8ca43169f04243ad0fdb0152de17c60d9e31ee0ab520970fccd98590e05508821a183b4b367967e60d53c2c826ec5dbd", + "0xb179fffd9df8c00486c5a8b9327d599f5a11745ef564f06e126849b06fe2f99273c81f65bc941efb0debaadfecbfec1c", + "0xacf068f1c2b1926279cc82750ce21b0d6b0bfd0406f0d8bbfa959bd83935932957c7f6b8de318315bf0b75f6ee41a0f2", + "0xb97831da260919c856e9f71a41687f5979bc16f8a53b1037285b4a2f9ce93af5cfe70bf0ad484744827fb55c847b58eb", + "0xaff50b0bd907383b0c241727af364fe084d021221bfb1b09fb6c1a7752eeba45d662493d590f1f182764b90b25f17906", + "0xaeeef044c14e3ad41e1235c9e816e1eb49087fd3abe877b89b3bade74459186126e160bb569bcd77779e701b19b5f71a", + "0x8483deb2b7001ca7c438fcdca8ca6aba96c9cbc4becfd9b16a6062705eae270011bcaedcae69bb54630d8c78129e57c7", + "0xaeee8d24be4ac0d9784c029e239fb5e64316ce29b88f47394cfaaa8bb966a72061bff72f99d02dc51c9705854686e77f", + "0x90ae09525a16bb2422169e15d6831c87968a14ebc0d1d27e11a759839c73c655b9d33ee5b12f275d6f440688146fbd2f", + "0xa3a41fc7fefef101422465e506bea7f3ff23c26fe35f5732b86f5f2471fb93b37ebc339f84c6be1e8d22abc812c2e212", + "0x86f4b5293e8aea4af1f1fb05dcf99714cb3aff1cfc849b1bb73524061c921c9da9ad92579a852e1889da29d952f02fe5", + "0x8932ef39d4050a1e9dc0fd8afeaf159472d71c5c27f458c69d2730836606ea56e19c8c4febf2535f930d3260e9bc7637", + "0x86307b9f3696bb21c20e4558e30310389e7367803c353d437e9b696039a0ff054d9a4953b75237ab1d1dd6f71118c189", + "0x96e57730e683ef5b550c91de18b19ac73879f3e26234297db68d28747ed0953beb0f3913cfb720c602720bf9330685d8", + "0xb04a19ee70123782e47b238abde55baf60ac0c66292a998af0d14afc8bbeb1134e557b94cd17a020084631c09a0d3c02", + "0x829abc8718be8139569fcb2c398962f38f4201114d30e2b2fb23566f8a27a5c380f5605cec543415202a12ed859e33f6", + "0xa0744fa488c8fa92a722c5fc4ef5a47dfe824eccd87d26c8bab9c174cbb151d44b1b29082c48652f03d3177e5ec86001", + "0x81d4035ae9fd28bdcd78b135cb54955d3b685a527319df6ee7e904b8e6d796f5f5a5f5035ee1de750c4cb6050e452b9e", + "0xb205e8c2ec24d7104fa0106c09ad34b5a912c1adef553fb718838dd627355993c2ec01055c11d00b2c75b68e9516d44b", + "0xb12d09da7968fa7394e449624fc7174d1d76c069ccb03e140d4d87a2d3f6d1f7b9cfc930f0c80becc673406ebe63f08e", + "0xb23752c158695da85048fdf38b395681cc0e8998630af8a9ed41efbda08c9964c2dc8ae6e53377264be4467d702c0de4", + "0xb0d84582fd73628d96b8c1ec96197697c41a963542451a2ade0890af0d33c7161d0f18e1a1ce2c168ca2dc1e9119d55e", + "0x8b877e618b469aa187632e410b125d2999d5738fd66d482000706b51fd904a0c7e7daa8c9b729fa33817bbc4154cba2a", + "0xb1cfc8a7551b601723b937d497d01dec3ee7614c2bf13d430b1058d5ebc1406045009ff02c2ac15bf8cf16f860193d1e", + "0xb6d9da84f97b21e13175bbb0b5cc8e79e88b470c87a3e115726c1bd98e0288526c58f3faaa8aa170ace0cd6a60852525", + "0xad2e773c2d527671ca5fab7085dde4da31cd35f45d4315dd95d8893ff5fb900494dca08eccfc1a2fc7bf7c7fd2fcab97", + "0x8d5a79b34aeb761d4a0c73f09f02e9548e6d382c33ee6887a759ab05762b490b8a549ef2933c7e3a46415c154c0221c0", + "0xb6f2cbe81bd0a7298403be392f8456bed30aed7ef30216959357698f789affd2942ae5fbaf3f48ecebeb7c273b20cb57", + "0xb5b6c45d99cea7ce6a1dc134aff4a8f630f299b42bd59592a7592345f8cd35bcbee944e61b0723de732fcad6e4425b63", + "0x8077d64dfcb2418974e956ea6dbf8a4c05b25d2a025333ad7e2a379f1976dc036771403383a51bfa3476c9c619ef8bef", + "0xad2e0a9d479c77a5fb73b3613a177fdaad50dcb50fed50e756ba18164c153af30b07fb2565e80ff7469f1b0338b7b5de", + "0x81017d1d80a6b6df4e99d0d7f85a8180b5523e8fa2ea2672fddff604933f8a113cab27fce098dcb454d7d1f7ed266e04", + "0x852355479d68e76c7febf6dfe2ef8e80d575c0d3bd52c983803592021cfa898c571c0b884412c21e66f0dbfe03167b53", + "0x98e1bf8ad48421467c93b9f72b47dded7c41b4fcd36ea55ca43ab24b0d0b876f5a731f422579b7167c7138fad2121266", + "0x803369314abd5422019ed4b0ef652b4dbe97ef5a87b0ea373eec9628b64a12120b2c3d4eb53db405131ff786d14c7ac6", + "0xadf2613fc34f73e1160975c140e925ed84d254e03cc3bc7fc1d19957b499c9ba9d9e4c1639981b594a7095c0a52c6757", + "0xa2f6a68efdff6e4173c00692abcfdfcdaf6f8b62369afad3dafaae4f2f38c4860780b4624d185e20e4f4498b75b5fe94", + "0x8b1658aa0e119fb8401d486ed08d60240d26a8623ef9788e3b45ad09ae31259395b021bd16be395139cbb7149714e764", + "0xa7dd8bf21121285e00672ee8bb84e0cb39b2496fb53a26e35dfbca7f2b04e9a9ff9db15f53fe63fcbeafeb2deeaf2ca4", + "0xb6d8d709e44bc18f3b41d69608edce60c02bcba48d3b7e2fd420842657f0665a7343246dea149a25e8f3416284abae66", + "0xaaf744ca5e9bcb63e3e2939b7a1e96e4a93c88c76bec0cf4294dd7db95cdd3f6a7d92196e352d08680e2328bc4592899", + "0x84434b015a7c398d35f1ec71fce455d62ba4ed4f62da042ec31bb2b4db47073314354cd50bc322297a1cfe35138bf490", + "0x8d70b3a3cd9d5dfefdacfa418c0b775a112a47ce538d33a560a519660009c3f141fd6221c18539129e9c0acdaceeeb80", + "0xb8c6903412a800ec78a4c15f31c24385a267b0c0ece32fd31bbbb557fd70c3b2d60d8fc0f90fbd70f43baa1928ea30ba", + "0x8e391dd445ea06cabb433f057853f8159511b2f9bef41aed9ccd14e0a6fcd912bbaebd38fd5fb736cfde0fa34b7a4874", + "0xa40cd988f70613df32babbd1bbc2f1b29ff1ab0147b01161555a81d56c9621657999bcdb1df38485f687afc51d5d0f23", + "0xb6a008b4426b3d7b28ae04eee4698fc8ef6a35d89008ef5394da39ce582ce1a45dcfae9a33b90f6fa4237f3667803873", + "0x8987280debfb175c3b44a2f152ea82548e4f680966f1fcbee9bf7d714e31bf8080c33f52705ef3aeee70544b22516aba", + "0xa78a51a2c11eea7680a5a0ae417a2981f8c69c396e06da621eadd7510a3664ade49d065617bec67b3de779548a4f4509", + "0xa4d9163f0a1bc048385e94d5e0bcafeee1b18f28eb23505623b9e8ef16f3df76408254dfbe790e45f2884198060d388d", + "0x83dcae2568a0c518793c0f6e38b42f9ceb50673d100b556a17ec8bd9faeec84afe50b8d72422c6b2356959667bb8e2de", + "0x874731941be4474b4576226e5906b5dee89fc9b56a9870dcc7289c1a7d494d345ba6aba31f7546a16f9963283c05f744", + "0x82c1cfab1f501189ac20147fc4631075dbf1abf9125b7d42fcb4f31cf73f3d6461b1bd08fdf6e45cc54bc08a7d5d51d1", + "0xb978228286f5d4a10ce027b6bea3021affcaa805340ca4b5192c69e8c56db59f48e4a14a284ec015f53baf97389f62b2", + "0xaf125f4fdccd1c1b64fdffecb5ec7cf8c7392bbe476e1b89a5b5329c5ba4a526e58c11e72ab9de8a38d60af648d75adc", + "0x8411a41ec14295acab0d36389013535a80dfff6e024bffeb32fb3070762f61256419e8c51b2ad6de9dbe4f1e8e286912", + "0x8ea67a91112a41f9c65515cd496f4b0cdefa1400fc06568eef000c9eae6dc250fb7622eb3f2deca10b37287cd96fa463", + "0x8da99b6c55c31dee6a49aabb54da249d348a31d4416201a10c45a3b04b11e99d4ae9813632f0ee36c523b5cca62f6f49", + "0x8b44656341e039e2bd83a19c3bb9a88f6209482e274f8cd4f8557b728e5948dd80b5745f621b96f4562928689314e8c2", + "0xa02d424a615ba0dce8ed91f477e79852215a3a39d025059826fa278e7eebef19824b2a2844f5b3865a0f471b609a23f5", + "0xa1f115cebc3fff3bcf233da27cef19eae791660f155d088003460f75567a550bef0722885010ddc384acdeac635939dc", + "0xb61a55ce9d143c17876776e064b58a10baf0ba13553c785c1e47f57b5f94c0cda8bc89d43d73386e57816c15b61a8ec8", + "0xb4073f47041e20a8e548c7fb00e07ba3b9056c34eb4ab63bb0e7b48f8e338e8b56a17611a1b5f4c03b352450b86f1d69", + "0xa7b1a07b213205b682fc5b6acb7e76fdf97b280c26621d8f3b76b7c1deb3511957da33a4e358c8e8f3d98b2a8855d67e", + "0xb797e67c2670fbd9844e8a68c585f404b035dc14bd4ec75c3f95f932c777f9db5d5f5df7629164af488fc1213035cc5f", + "0x99618200797b945f595794d6468e5c618649554ad9ba896330f1cc844090eb956ae9fc23132912f9047085c5f0c3bf7b", + "0x81194aa1319abf534cb3927af9adfb178a99d0e3e8c99ab1105f1d3b4fed40ec2971caf1d6647acb0c8d681eca53097b", + "0x80673f18e4978dbc226a6cd4b128a1259d9a7f833879c6e2fbe24d69fef2c3c23a51a4f3e8d88fa4533434bbb0723661", + "0x8125bf6c7dbb2fb63aaa3f53283559f172c788223674adbeb6d5bd17cfe888e6b87a79aec774917f20ce911c1f85f8e7", + "0x884bcdb1878b14fc38adc9fb8b4dd0b3afde404fbeb664f26ddfebc81736018551f23e75ce4cfe4865f610bcd454fbd7", + "0xaec65c8d4be8316e98aa54888af01bc6703a0c5d04b69756ff39a0a947b66817ec59d76afe9f61a25749b5e890f03e02", + "0xaa457aaa1b014a4c5a8992847a187a23321bb43452c98745987d038e3b04046102ae859b7a8e980eea978a39d76a88ef", + "0xa9832ee63b08e19123f719bfe2fe742125f32463efa966c7709a98ebfc65277670e9ea1fa2d2d78b96bdc7523b0c4c3e", + "0xa87b6b1b7858f96d55064274f29fbde56067064962cf3c3e2ba3110b22ea633bc037a74d23543ce3307a46208855d74f", + "0x897cbe4ab68a753020fec732dfcc052c7ed9905342b5a6fe0aa25c631f9ad9b659e0ee75d46f0df6507b6720675ee28c", + "0x97c3b5f0d54c1fc45e79445c3ff30458959e406a069f5bbf7979d684195b4fa0406b87c1c008f4075bc9e602ed863152", + "0x921e65d582ea9322ddfad1c855331c3cac81f53c700b96db5305a643c084eb6793094e07944bfd41dc02c3b3cf671530", + "0x8f23ef1aca02a260a3b65d25b110f28d3bafca44727448c8f2d03c5e77eda620c1721b06681bd816ee6027664d76352a", + "0x946a89b132ec0795aea9ff9dde7b77e7feafffe6e4a2f093042a7e6c71cd6ab87ce0ca914a1b5fabad4e1f96a795f163", + "0xa01e2de9db33df6511172123ad6f7c64074237471df646b32dd9aff8c15278e2723108e4facaedca97e9f49503f8c792", + "0x99dcdcde45b2ea3f15279936feede5f7d3b63ca4972f335b0559c2fa6f9faabd8127aa892a36deb114357ca906553ed8", + "0xa3f8af37bfcf66b04d1896a4bd5d343f4733d4c3305369ac7e75a08f20f2004c10c642d2c7577f4e5c4d1f2cd851ac3b", + "0xb7294d15a3d674a56099f97a1adc9e82c15e90832eaf1722df110fc2abc8634c51515e5ad8522015498a3753b1fa8c49", + "0xb4f27f5062ba7a04ea0048b3025b5e3d5b5d319a9e80310c808a5fb4e8e77b38c10a0f3172cb805cadbcc8bc66d36ec7", + "0xaefe5decee0ae2dc372cc6cf4217daf97c4c908d145f100f0daf1ccdfdf641c78432c2e473e7e4b77dcdf2d4c2bb05f0", + "0xacc84af7648a535ffd218c0cc95c8f7b092418c548815f1bafc286b1fe14f6ccb51b2044db3bff864d0bb70e88604084", + "0x84d8e3dac0df6a22beb03742e1d4af684f139f07e2ea0f7fb27fc2d7d4f1e89b5e89f71af32ff115ed5e6092133535f0", + "0x8ada001e1a03a823c4c056f636e77adc0f9dc08689d28de0d99e0feecab5db13abf37b41ec268dbdb42c75419a046c68", + "0x87dac6c798d1744dff81d8bc3e0e04f3c9bf260e811685ddb9a9a8d6eda73927439b344f9a818d2103fad633de5a4a17", + "0xad9929a7d8a7d5d5954e48281a87e5c84f67e19110d73296b9989a09c76767a57a8115629239ffb4d99dfdf9c52ef6d9", + "0x81ac7cbeef8ec35a5c3b61cc887080c29e6cd3e08af37e45830d17400dbacfb374dd07bf370b979828c3875b2027d5c6", + "0x97f92c9182953b7e10f7a1bbb6b5b5c40b8275eb5a6eec1e29874c4712814749aa8c409651380216e1ff01d7b8511041", + "0xa09794d0bbe7db013045d3fd857c1544fe6231d21afa3495fa300371f6301a3a0f4b8ea175b281503dd06078ff371ae4", + "0x839bb58d320aa08116dd387a57a2b9bd9efc89c4cdfd82d0e47a00cabe644631d09be5436bd485df3b61b75ddf81a3ef", + "0xb1cdaa344f783757e8b9c1f84421da3c5be4c69f019a8fd4c1aa5bf1a63e8970c99e35c22cf3b48a0e6738bc6ba7ce8d", + "0x92af68e3216c78998208fb24b5ba0e645d0d3f5e28222b805668d7e9cdd6c033d3b22fd6df4c2d745d7f910d133cd226", + "0x87640a4ea4e605e2204e5232b29a6c1c31152d83547eef14122cb76a0da52b8653801af48455a3ed713b9dcfee7b1ef1", + "0x8147e5bf0c8f4731155ca0517ef3fae5a32b4d5d2d98ed0007b23893d8dbb7f8a1199c50c1750c2fa7c9cebe594b1bb0", + "0xa76b4473c63c3ab6103c729afd2482822e4150f3155af39983b0ff0766c71cb622455ce6304e23853661eaa322219d18", + "0xb3e2f05ca551bc3adec0067e4034aaffd72e0b64ac18ae25452c996927976c6727966e26d213b032521889be2170800d", + "0xa8414cd14cb3be658e9e0004ce511ef7063439b1cbc3166a11de030613fde4b59caad4e91d426927863c55382afbf476", + "0xb2f0f8ab99f4d0ea785ac84fdbc00b20217b1df59b30b51d9d209d489d53b69dd5d82cdacc16fd1dd15c3a4001595f50", + "0x8b2025d5fd658c9bbed619f3e3f6ac8efe7aeff8aa9401bd66a7ceb0062c44b353608ca073f95be99204f0a913bb77eb", + "0x94a46bc5a87291b42024b2137e623c70115b9c6b196604106bfbfa20f3f56ac7779763f56b580190d3cb2f1c648cada1", + "0xaca9355545118d0769cacf69c4b23d6d68d229cd8f68f1bc0c847c05569c5af6bbbd8c4dceb637b4a6b3b5c83841bf5e", + "0xb0731992cab87c7116406b283a84707a34838bfa3284b0f6082dfabeaf41c5ac2b0ddc1b420547a1b0955aee92de2dc0", + "0xb671f77588c0f69f6830a5b28e7d07ed161b81fa9791bb3a24aae6638e3aa5e186df74978a82549c370c18ebee04d4f0", + "0xb5621ed841780f3e6681d880a76cf519cdd20d35197b112eeaa686764d57b5dfa78ffe1a294b6bc76b6e3949cd2a2369", + "0xafeba2524659d00caecf089645611553187a6ed7102050f6dd20f5a19bed08ac7065912d88371ee06242897d58d652a4", + "0xb78bfb83d44ced14a20135804aba3f00128c3ce1f302e95567ce4097b0d973414153fb305b9f156882a5a0554bf25973", + "0x98510aede95d26b1adf214053eae051ffaf24894e2fa37961a91d0ff5392dd09388196648d95b73e90bd88f2587cc4bf", + "0xb35c682d49c295946b9f120fbc47b95abd9ee86d294abb003a92139fb825b509209562575015856a270eb3eea86397a7", + "0xb9641bf685571dd9c478dd2033a1f1b11cd3a662b26502c78595863b8e536a189674a9a85f7a253453ebfd1b99fbd841", + "0xb2ad37036a59b1c9b8457972665720a6868422ed8157b6810a9c0783006103be34ab732d7aeb8629653edd18fd0f1717", + "0xaf0920cff05179a3896ea6ea322c39adf91ada5bc40fe3f6fb1b1b4e121e907c904bbaa8ca00468b3749f3da144d71f3", + "0x8e269672818ef1e2f9e0c8aa65c84442fcd9151d74bb8e870cee8c0e3fe24526e1a5388b430cef47b67f79b4e4056bcc", + "0xaa29a16fe00ea3d143b1032b1dd26b8ce638f37f95c085c7e777e8e2784bd724bd5c38b1583c61a6ec7c451dd78fd3fb", + "0x87452b7435911cc5f513b0c81b15aa04972ecbe3d7bbd0a5d676c96a8a311301c0e07fac925c53a350b46fbd3d4d0fc1", + "0x869a81c351096f47748e41566ae7b77a454b1cdfaa41d34a5742f80df38fbf5cbb08924b6fdff58e3b18f05c62bbbbb1", + "0x8b7bc1b0486300981147a40a449ada9a41afc06d735cce8bf0fab3ee94ba2e2ea57b1397e3cd31bc295352beb8334ef7", + "0x93e93fc41adb2df279d95654921b4c2edf0d293dab58d0afefb221f777349ef88d0985b3447e3b935954a81f1580a92c", + "0x970fa7cdca8324faf3e62348bb50d78f580b4f43f2e1c11bd8382d48d0074a3c55c6407203a0c9cb1c5f2163ba421ef4", + "0x924983929e608d27e4a36d4ed919297869e3c64de51aca794d32d6e90aea546bf898d98ceca28a0b2187734821b78504", + "0x8d395332529c703d943d68415d443332b5c1342ca9d9a59bfa8bd4ab63e93358c4b0dde6ce1f2e8ea9dc8f52ad7ebd95", + "0x80200dda853e588256599e7f905add5d5ee7c74272780317694fbae39318ae9be05d5bcd7b20cf460069743f3d4ef240", + "0xa287d51d6359c9ef7c7ac1b20e479ce7d0146dba5606397bd04b7a622cec642508d5b45d51b31de71f9763595b6ac88e", + "0xa320396c075175d6599225cf2e1de8c7cab549f6316c07feb0f6eaa21f06b2dd29ab14fbdf2af4543b4890ec0fd08a4d", + "0xb1e9fe230418d20368691058adcbbe30011bab3000422f0371015ff8bd09c60fb5fa85d18550d35b1c900977ca48f58b", + "0x9718fc26a51783b971744933f20490e9b5cd9162f86b84788c4c5217f5409e37b5a39d628b18e5b35a757acf67596321", + "0xa0cf81fdb161f4f1b419c5e4caa36d4bdca2325f0cd25b119a30178016f171bd6fb88403e4e3aec026c4089f180d540e", + "0x8ab1e36bd04625ee794ef04c4dcb8e004d61aceb2b62438377f49ad95dcf025ba25eb799280004941e555bf7172af6fe", + "0x9257b9e3d14d37fc7efae49b0c68d36eaac546035f4a2654d566b3ce1b2c4564cbb03dc8ec66efceb768559a8a507a18", + "0x945d1123b839637ab5154a1972c3c83a0ff34a3b1a3465de6ef0416b1950f649869a3ef88d7f1036648ee385265ce2df", + "0x81449639d708860fc0229c94f754f7262e8a3c7f67960ff12dfd15df95f57a9ffcee2013e81978b7703dd42bd5d0816f", + "0xa865481deaae5a690fd53892791e5fa729db283b75a525a11cdfee1ce17e8e7f0b449d25f20b3c1b43da128dbdf98a8b", + "0x98766812a65fcd25b853546e3bba618a3edc9fd61510e4f8ab60c038a7fa50d197abeec8776109df0f2119be9445ad00", + "0xb1b8dd5379d903dc41d74e999b1ab693607a0d2905692f4fb96adf08f738e5d31f9d00df28ccb8b5856145ca552c3e3c", + "0x99d20be7b511bec78a8ed03c207aa4aa9097ba39d85e18f1b8d52f65431ab7e9a773c7b9ac3e8d8b25458bc91bd00703", + "0xb1b7c3563fe8cb33c7d3e0b89d00bdd13e86452ff507c2e69db7b3af06f247f139155396e9b0278753310dc63940a10b", + "0xb3dc9c08451b1de7c9969b1e47574bffff50490f4a16c51e12390195d9e9c72f794790caf7b0a835d64e01fec995d3ac", + "0xaaaa4761a00022ede0809d7063d3532b7bfae90ff16f45e17a340ad4ebaa2fbac40728ccc5fbe36a67ab0e707566c5dc", + "0x8319a1903314eab01f5442d2aee6ae9c3f6edfda0d9a88b416d0f874d7d1d05d08bb482102f8ca70a4fa34836d0840c1", + "0x932949a6e9edfec344932a74d4f81eec3667ece1e8b8ca840ce07ffd4b5d6d8f01657c764d64ac1b9190f876b136490e", + "0x904db1568128487e312fe629dd8bb920cecafd3bb9cad8b63e269ae0129f2f5c80cd82f0d81e7feca9835c3945a72d28", + "0xa17280693d30dcd43c85de8f6b02d5f30cb9097274ad680cede1ef105c903615b4c40f3c6aaca478642de324972514e0", + "0x8d5f76e093aee71d0cdeb017fdfcb13bd068039746de90690ce150a0bfdbe7ddc4d539df0f82c2d2890a40b191900594", + "0x96fa1f2196a3883cdd73c66d28403cbbb58f6a939a3697ee0d308d8a076393cbb4be86255af986869230ee410c01bcfa", + "0xa8b74438dc5cabd70a91bf25601af915c4418d074327a9b01e0190c27d3922c89bb9b41e0b366e82e313edda8f21983d", + "0xac9fdc1a9b2e3ff379eb2370979372e13c4177bf4574f1490fadf05a7073e6d61e703e2d8eed9ce984aba317d411e219", + "0xa45a6c9b958169f2f8df70143e6ac3e2f6f969a4eed6fd9f1c620711bc2454739bb69f0094079464790c5429c0d8aedd", + "0x8901cbdd1009864386577842c1e3d37835fddf834064d9613b4559ea9aef3084204e1f863c4306f874141f4374f449ff", + "0xb6c582161691e3635536686825be9c4d7399d668a7675738417e0363e064dfd28acdbd8dbc9e34c1dab8a1990f1f0eba", + "0x89e89ddaf3cacc78428f3168549c161283ca8337345750667c98212717b21e7d994eae4e45bbddacc832a18df1d79276", + "0x84be275627eed8e1a73c7af8a20cee1ef5cc568cfeea7ec323d7f91b44e9653e9aeed47c1896a8240b99dde545f0e1fa", + "0xa779a54ab4f40228f6e2539595fb8d509b70aab7c19e1928c1be69ec1dc19285c3898cf15e5f8b8bc725e13af177fe17", + "0x92e2a49d2b9b36349d442283b17d46f8f9bf5932c34223015ce62d2f285e7363b2c12232be4a838b5b6cf08e694c094c", + "0x8b4e28c6f3f36caa2cfb82ba88066c830f8017bd35608b077143dff236f3181230166f5a5c02fa0e5272297331726aed", + "0x85fd77d46162ffac4b8adb25baff0eb0512a53a3d01638b3a376ea34702279ce21c8e7d8884308c03e00c9bcc1a9fd29", + "0xaad5e46916ff1be29009b595d1d8fa160cc7aa01c7fbf3a68f445c87615790dcab1fcdbdceda533d182b6541f09f2f73", + "0x948df7654726250dae393325addd3c0a20431c81f00470962190335ea4b6d9f7463d6f308cda46b92084c1f24390b1da", + "0x8f577474dea132676504376c5542b730b6604fe3d965eaa194659fd11c52233bd0b11ab62e198c0f442327ff1c00e501", + "0xae2f1001546db3e0c19700adad997cd9f765fe7a51a502cbcd9a2a07a3a5db79c8f603e05cf96d80b688cb6c9b6cd3ae", + "0x953b68e5d9561088dd20406ea7fb6894cba33868a38ace38fc30b5813140cb15dd6dd2171befae5b4df2e4a9658889d8", + "0x86c52901655ff11419b084a04da8fc3596eae59d81d3461601c0baff59ba59e3d1dd0b7ce719e741a3e97c013e898579", + "0xb9a72dd5eff73f9912a28b55de073568efb3eb0241a10b77a2bfd4f30c2aa4fbfe0c89eb345c9f07fb725660873cb515", + "0x8e7353f5f2932e4ffd95811caf46c9bd1a53643c27eb41a4ebd211f230955cd71a8b27e17cfe8aa708d8514c0de67a66", + "0xa096b8e66312a92fb10839ebe60189a8d1bd34dff55f7dfae85e4d2f53a1a4a88211c19fc84494f066358ddce82be131", + "0x931c5cd82719d76596832b007969b5f75d65cffabb41b9dac7910300db677c1309abe77eeb9837a68c760bb72013b73a", + "0x8ba10f5118d778085122065b55dd1918fddb650cce7854d15a8f0da747da44d7b12d44fc29ad7dc38f174be803db74c6", + "0x8c971deec679372a328587d91fd24ab91043e936ca709c333453d7afd43ee256d08c71cb89f0ab0e89ae119831df6d86", + "0xa2ac28a58034fbd8fd518f409221bad0efec52670880f202e09c0530e2aabc2171ed95e99891790596ffad163d86c110", + "0xb3354e3dfa8068aba4f3741152b9204baa4e342c1cc77e6dd1419cbaf8da1d118be605846b8609e997d6a62a11f3423a", + "0xa12ab65a213c9d95c24865fddc2dffe0cf9fc527dd6bcdacc1bd7271e79929a4ab3427a231f4f49d0530474e6cbc88f9", + "0x90afd65b7e6973f8aafbe74da0f42441840d3c93bd69bc1bec8fa56824e7ca97ad1b427c8a85da7d588469bd4ccc50c3", + "0xa09175940c59489bac3d3da3a4091270d9118948cbbdd57f2bcc63fbf45b8010651c801d3e58dccf42733ce1d6b446a3", + "0xa843bbf286e3cecc1fe370ff1bcf5f1001bc2e95b34246625ff50d48ee62343e82fba2d25b8a4bd5f7b5ffe90920efa2", + "0xa3c4d1003219157fdbee2707ce07afa6c2a64ae8e450182c307ed7f070024071f30b12c4b0032960ff913c74e73a9976", + "0xb24af3f68d66f825d06fc3ff94fcccebe28b1a0d4ba29c48d3a3c953b9bf7ae6707f193fef25e2dcbd2b74e483c774f0", + "0xb0f657f7723184ef7d7e4381143f1ac8020d8c6c6f2dcbebb0eaf9870d61a81f2d452596503311e46d1b38f625d4756b", + "0xb90091004fc8f6205c51bec68547ac82dba0f5525631e7632cf6efe54eecd9020729fbee6105d1b8012402d3b79c54aa", + "0x8e3fa187713c60eb0a416d6900a894cdf81e6b6b69dae0bb64f6287f3c3f030cfa85c665f7aace1eab4937f380b8f728", + "0x879bf0784ccf6725c9cd1ea8c49fde31c91c605de1ea664a33c2ce24c277ee45d20b66309f98d989acb2ff3b77e13101", + "0xaf3f3a3ddc4e11abd627d5aef8adffa91c25df5f0c68b4d2b5d51e7d9af3395ba4f6f7ae2325a6672847e1ecc6cad628", + "0x973e667289e796d3a40f072e6fea575a9b371a9997cf8961677f8dd934619ddc47c1a3efe91bae9ef95acb11a8fe6d09", + "0xafa81c5606de82f46b93f4bb6db3fc0670f4e0d1091388b138a66b3827322d95a56168c951c30831d59eeadc227500bd", + "0xb83eff77db5b4c18574662942eb36f6261c59f655f8a9c3d3731412d0f257c8e80aacc995c4b2303058a1ba32522a434", + "0x912e5ac9234b9445be8260393ff08e4859a7a385e800b74d1534eeb971f58f74cfb518dfdb89f8705d89fbf721439129", + "0xab27c8ece4a51d23e22c2e22efa43487c941139b37ea1182e96efb54ca4809d8245eae0ebe8ba94f0ed4457896fe11b1", + "0xa6630585d104a745bc79dba266d9292bbdad346449c8ee8140a5e6e8a6194411df9cdbf3d3ef83468a536d4f052e9335", + "0x8b8c128244da48e7fec641a882d0005a2d05c7138d86a293e6a0a97c76bf632b44767d0ce44663c975e7f9f9679e25e3", + "0x87dbcaca67351a4e7d2297d7cdba4796d12f58857e7ee4abd0645563577ff33544a44cd84e50b3a3b420d6998de9b57c", + "0xb859ba43df259d7f8e7fac70bfd7aae546d57a5dc90e107b174a95bf7fd3cf00f740c4434848e69b2a7e6061f66c1ef1", + "0x99d6e20978fefc40c6d310187eb2ad3a39296f189ee122ed64d74f81033c3069d44f7a9d3988a1df635b609603a17272", + "0x99a5ddf3420cc0c92b21f71a805245608d4995ead447d8f73a670d26d33e26920d5f07bfe1f6230bd5f15978055b4253", + "0xb936ac0944d3c5e4b494f48f158000abb37b80b5c763f77fe856398c664b0f1ddbcc0a9a2a672db9278f08b4bafbe2ec", + "0xb4af85fbf4040e35a686dd016adec037c99b47cc2e4dfccaf7870ee9e8c97bff30f3035992def2a9d4af323c0b3af8ae", + "0xa5ee32b8bd5f8fa9000da4da0bf00565659a43285393d37080b555d0166bde64d87317b2eab2d48a0e7b287caa989be2", + "0x894d4ad58ecb1c9ebc4f5a97407082e56cb7358d7a881ba7da72321c5027498454f2c7fa2bd5f67a4b11d38c7f14344a", + "0x965be9eeaa0d450dacc1b1cc2fbf0d5d4b0dd188f2c89aaa9260e7307a2a1eb22db6092fccb662269e9a1abfc547cabb", + "0x805893c424aec206260c1c2d2509d2cb9e67ee528bd5179a8417a667aa216a3f318ed118b50d28da18e36c01f0805e3f", + "0x972d7040d4963b35260ef0cc37cd01746f1a2a87cedc0dc7b0ee7e838c9e4573784ea743f563b5267eb3905d4fa961ba", + "0x8c7156991d4c2e561888feaecf501f721b4174e7d14109e9deeac5a9d748301c07e11fb2b04b09799f0d34ff42cb77d1", + "0x894722ac35af3d507e81d737d21e16c5ba04686f8f004aa75934aae5e17acd3e065b96e229eb011c2f34096f4c62048b", + "0x81237937c247c88e8e31e2c72412189fe59c1daf65c5513489d86cf29ee922c0bb08e5f7890f09f4ada7e5262083d266", + "0x8cf62cda2fe0d9a6b42aa2a1c483f4ad26378c7cc2c2d1510a76df7560b07dba8528b33aaacb15f7f20b9d4c7c9f61f6", + "0xaaf0921fb3e1920eee5d0acb59dcc268b42f4b435d60d25d30357edd7dd758d035919691bd15311d85489dfa2e5ee696", + "0x92cec07be2247ef42002ebcaf65ec855611b8e893a5675796f2225f55412201b0bf9f4761924d0c8377b9f131e09e39f", + "0x8e514a62ac1e91773d99588415426c97ad63e917c10d762fe06ace5277a5c3bf3730e4b9e5d116f8493b9ab8687b70e3", + "0x83932df2d923a5052468a3ea87f7b55c6a80ede3594046ee4fe233046570921822bc16555b92ba6aeabaef9b1dc0805a", + "0xa2b5bfb249de3472113fd3f35bfabf3c21d5609da62a27ea6aab5f309c9068d94bc58ba03efb4ec11be06306d59e60e8", + "0x8106cf3ebe6f0507be8c6e8d137987315fe3689ecb75bb27980f36ba5efac504baccea0e7603549b6d126beccc278804", + "0xa73ee70b6fe8c082443972102c453fc0e386852476cf22224fc0bfe554735c12f96037fbf10922795f4502c4f052b5f4", + "0x932b27e175440169958504f3ed6400e7d6dcd5e716c19dcd0f15c56c04503ed133d5a993e111c016f141e32d68b29886", + "0x96f7ce4595318e0b4a6b368f788ff82226aac676aed4ace343867f751de414453a9aaaabef6e6224ce5aedc3d5cf77c4", + "0xa950c1e3bc9a14484997013d44d876374b939af437ae7c821c131fb886063ee9fe7214a25a0c7084f0b07b99412eff75", + "0xa9dba3886ed6855303106a1bdd26010f294218684e1c178afcfea3f37a2f04fd01724a31d82de3449046617e3507a115", + "0x87a2f776b32a6b550cf3ceeaf78db02819be74968d228b1d14e0d74a1cdf994bb500b7abef6619455e98d728701fac5c", + "0x8cd887b07e335edc0b27e6a660cebb64d210741395be431d79d570139687b056557159407459799a8197b6079644f666", + "0xb81a61fce00588909c13a90c1caa150f15788786af443ff60ce654b57147601f7e70b95659e01f470334a220b547611b", + "0x8aebc51141544c5f3d3b99422250424b9800031a8fdfbf22c430907a3a446fecaa2392105d66d64b1c8e847240da4a6a", + "0x90db7dc12baa02f3f86d3edadf9434e2b9318d4f6f0eca08276b765dbb38d8eb0d08be2fe70adf2bf16ceda5db08d3ca", + "0xaa1839894152d548cc6ad963de20fb6fcc843bc9af2a2bf967c63626b8ad19e900894d6106265f38f3afccca317c22f0", + "0x848e27b741496988a582515c0c8847b2bfc6a001259396cdeea1e1b1d2828ca3a626693a1bf4adf3a3d7f8b1fa3d75fe", + "0xa0aa11754d4ee136ac3ca609b17bcae77758763b2016544ca7921dddedd8aafcc7ad5f2b337c8bf53084eb8e43ea41fb", + "0xb8713b7aa1c112178195fdcc9b7024f46e6bc04c4e76c41abe620aa265287809200d98eaed6c9703fa97e81d6964f0ec", + "0x8605b5b33309e9ea6823542b85383c496794b8481c577497aaf99ba90496e794dce405be615bf92c7b6361460e6b82e3", + "0x826fa34faa7f83e063a7bf172addfc07badabada59cfc6604fdf481d29085251c0a67a1355b2cbd374e2975934b84cb6", + "0xb45d131082dc16fa53af010d43eefb79200dc23d2f3ee26af95ac6a5cebc49c84a9ed293e534ed16ff3ef9a4a25456ec", + "0x91bd6ce3c5396a7a0de489e49f0cdf6dce1cd2d0be7a410326423c3185bd1125ce1e610768be7f15f4e44b62f8834fc3", + "0x903ffbe3d33fbf106c01c727dc3a385201a67ded70d4df623934882f69a3a96c909b027a124f3d70cb072b0046a149e8", + "0xb405359db9d9ef4821a181b440ef2918c240595141d861d19a85867a5afa74d2972d22c988775eab441e734700bae4a3", + "0x8abb756d027233c83751910a832b0ef4d28d100077f1c5d656720c94906f91d85dd0ea94b1cc0ed95b692efee14c786e", + "0xa78ee77ab476a41a3454160ba7ca4085d8b1f7057c63e76db8b07cf20afdeddd2250cd00771a6329133bb4ad48ccc20a", + "0xa41810271d8c37197aa9b3dfcefe3498e42f5978d3f3d59defff4676d6402d8575b40683834f184f143b6cfbfc859b3a", + "0x90c24a0750242660bcc6d487358a3cc015730538a0a8beb00ad5ac2ef33cb8ca8a62121e50bec8f3d2f43900f8e3134a", + "0x8b96c39695d864ef5796941754978a1fd612b369f6b77fe5ae6587beac936ee28190af8f0a3822b63060af35e49a5c8b", + "0xacde2548883d0e63c0fc257bb9dadd919aba60a985b69ebcfa1bca78acca42fc1322ec30bcc8e7c188818f858d04ad33", + "0x895c86ae9ff8d95f2707d4838a3bc8ddb05b2611f0476f014b9c150d0e8332bc73285037a747426f09ac8179ba4e19fc", + "0x821761fe406e18bd86fa9ca9db99d382cd3b5c70c456f471fa3706d57763d147706304c75d54f51ce8f3115aa26e59d9", + "0xa803a80e3e8f47dc3c59ea23eafdec017458eac648b360cd42cbd075e0dde6f6f450b48c7646fb1e178c04f82ae51a12", + "0x91f40e1b6f588bd592829ce937996452c40be0fd6c43793c607866701ac6a8c7227e0891d45c6e7b1599382b0a3fbdbb", + "0x9408246d996a634a58689337f2526dfb3ba9ffef1d3ff91c32aa8cbbed900861ef25d6477308b67d76491edfcc70d65e", + "0xa492325a427f3df1c9c690c5b553daa8ac41f62f5ae55f425539222bacf959e2f67afabbba1732e120d3e7a6dcdf7049", + "0x8fd0c3e15477cae228613a171b6e9ec29ddc63ef74854d99b638adeffe39f89f34346a42851e8445e855a9f2bbef0f57", + "0xb735ed01fafa051004dbaad5e8c9e2faca8f6049ef9b590f256ea4d75b04594af12764ad4e6031735eae36f83179db93", + "0xa7d35f43fca06c86b3425dcb68a87186834ba9740664fd657915771beca4cdc0fa2fc9b4c2e9d9bdad8ec33543ddfa59", + "0xa1156e71e2db1b17df5da28747c88e091bd687bfee59d89096437ab4dc9a543fe5c5272d5023d72adbaab397a6fc94d1", + "0xab06a58bd81b33a411bade8d8c5232d38fadc2e38507159edea6e2e104b8ebd65ca02b05335118f691d44197b847a4dd", + "0x848b67a10f1e6ff8f5c228f226ef2ffeb67fb8f50925fc94cbb588d61896d9dc79726959e649898fd3354fe3ff7b7ee3", + "0xaa933397361f32b388edcf832f0db172a38e756b34d5f7a4a050fa7325058006c22cede26ee27917e8f1b0f301792bd7", + "0x89e49e7f02cfaae4a4b9c4180c9f6559d76e3a45774955859d4147970b1470dac37bdc9aedca1c32a20b045049161590", + "0xadc1825d5ab94fc719f25d8c9773f4d518134ed88eb13ac33cb910b2be3523ef9ef88d9e4aea2418b806e20108317bf6", + "0x96c4b444c8a023da644f3a343ebeeed19a8392d2ce175992461451c318a54273b76c3574d8f2dceda2947ddd34d1a674", + "0x8aa7e97e87c8c5b29bbd51a6d30396a6be1fb82b716ef83800f2c36d5b85467ade7e0f59d2db82c310fa92a9265f0b03", + "0x9146c32d99f02c3a6f764dcd9b4807f1585f528ac69dc4f84e4380f6fda4f9d5057c375671d51e7aca2b2b4140e83da0", + "0xa10760a533d9bc57536bcaf65f080302086aa50225437efd64e176841544711828c23a15c49c0dd1f357d3f10722ab72", + "0xacb0811777e17f7ae7aaba5f6fce81b759c067a4908730916195a2505c7450d0e6e2194c2ef0f241090597d58e70de47", + "0xb24f161e9bcdbad56665e2490b5e4c7768390d4668cd69a04ed74739062dbe832636dd33cda89e9b0afa8c77e93fc641", + "0x96b4d01106b831868a88ef016500ef2fa42d0ce87a37ca8ca4194a92a22c113edfe04eb2ca037329f3c1acc635148f55", + "0xaebbb95fb4f7adcc8e7a217aeb73f9e037cbb873d08c1cd9d68c6c6834511adf1af8b44567fee84327599bdcb734dedb", + "0xa9bd8b17300532fb94d028659bcafbe7bbdf32f8945baf5db4cfaa1bac09e57c94cad0ba046b4514044b8fe81ea8596d", + "0xa5557cbda599857c512533e7cadcf27bf8444daa0602aa7499cafc1cf1cf21f9d16429915db7485f0e9a1b5046cf01c5", + "0x8810307c40bc661c478a9747ebf2a30e5a5ead942d1ac0418db36ba5db0709c476f7d19685cabe6959e33ec1f3bff914", + "0x8829b741f41f2c32e10b252d9338deb486dba2f23996a44cf1dd888ad967a589d51329be34d764139f372a1043f6c2e5", + "0xa6b4728d18857c5fa082fa67bfb3b1d801e76b251b1e211a19c87cea5fe7ce757f943c85071f7a03a718388cd5690e95", + "0x86da7f397e2533cd487f962ae58e87bea2cd50af70ef2df9ea0f29f70b5843cde664d30ec207ab84fc817f3851277e02", + "0x8085776ef4ac6d42ab85b9d9135ecc6380720efd274f966544eeedf4684028197de76ecab919fa5414302597e1962bca", + "0xb05a065c733033d223ba13d16baa7a97bd8c8b8b1f0e59a9bdd36ee17e9922d48eb39bd180c168b122088a77f0bf321a", + "0xa89343fe44a93023dcc7ef71bd3bcb6786f68e1885ad260edc56a52445d34757f476395ba7ad35437f89bc573c7618dc", + "0xa114a9cd6105b524f3969c69faa2e09afe21753a93361a296f9e0e3b4e3e63726ddf2e6bfd3ddc046043e50bd44e539e", + "0x8a5611fec539cf681c05636bb580f29acc06f628bb012649ffa41ea6c1521194a5643d5dd843f09b6eb2c3bdb4d41acd", + "0xade247c4011ec73ec90b72f35afa59a999e64ba5a7e664a4b30874fea53ba6a14a76a41b58a5f891a20d019e5f091bdb", + "0x905b5d96df388160ade1ffe210d0c6d1979081bc3de3b8d93ac0d677cc2fc2dc1ef6dcd49d3947055514292a3fa2932e", + "0xa9520796ca9fccd11b7524d866507f731f0f88976f0de04286e68d7cf6dbd192d0d269f0cd60fd3d34011a9fe9e144c2", + "0x989a1edf4d7dae811eb57a865c8e64297837ffeeaae6ee6ac3af0f1044f023f1ca552bf00f1642491f0f0f20e820632e", + "0x879c8e63713f4935ed6e020559e140ea3073ced79d3096c152c430141272117b4fd9a9fc3eef012e81262df02ea14bd7", + "0x95074738ac1540c0312274333acd1ecad9c5509fee883c4d9295fa8d8200f6e637c363de395f9fa612f05c0dc58fae88", + "0xa770e4fc595269eb806b113ab3187ea75c8f96b57bf9fcfaf535f3eedc1d4d7e6285a20990575de0ff09f62d06ed0692", + "0x81283e5dfb6423439ff513eca1cc316941d196df8da2d1069d2d0b63f5289e630af2fd4119bc0144c002d33313372dab", + "0xabd1b108e743887b78f698f2aba9d5492f87a22868d1351d705d93a1084fd45be67170c68a6e18b07f400d9a01cda8c2", + "0x8509c3f67b92908cea8144f4e2a71631a66a61ac3547601c788907e52e380e5fe8ae4110aed95d13c67d3bcdd5b55a61", + "0x8fa5a790ec5cce6d4114128c295390120869aac5490a82feebd3c37a167120df2e7fdfaf2a4050a7dfebf48fb093212f", + "0x944753e1ea7d8bc727d46a7702077dc01dc0c6574e8263a16579b57ee155ca5901f71bb347a01a9a922b329d3ff75135", + "0xb46bc1fd4590b7a6275e20036d247c5909fc549c78e95b64ae7ed96e3b05bb044840f19f7650ebfe7008ba09fa83c3c9", + "0xb1e47e4d88e59a06c465348c6cc4181d40f45b91e5e883966d370c26622c328415c6144aa2f61ddb88ec752482c550ca", + "0x8bd4f8e293e3f1815c7e67167618fb3b0ea76424bc0985908957cfcede36109378e41b4d89555b8c2541b4c447e00461", + "0xa70589a867b2bfb63d0106083d58475d506637148549ed35c83f14e5c8de996e1b1f3447ecc80cf5cd134ef4db9d2fb6", + "0x8048b80ba6131d07370162724127b0f7cb17fa7f71855e55e5a75bd0a9e4fd71b0d0ea2d16ec98858e458528df8d06b5", + "0x97326cb94bae7530f4ec3235770c5a7ba042759e789d91c31fedbd979e3c0e6a2c69e2af3c1979c6fe0094274dbd53ce", + "0xa18e9c1d3eabd62af4e31a4b8e08494f4167fd4598c95d0123f39c46c53f9e93f76615900246e81a286c782ac37c569f", + "0x80309c59d4522b15aba617cd3c6238663e8b1c7ad84456346082c8f281140fc0edf9caa19de411c7e7fb809ca4fa3f4d", + "0x8e450c0990e2f65923f252311623038899eeff7b5c2da85b3a224e0ef7132588b291b782d53c477ecb70f34501466178", + "0x87843f96f41484e254e754c681a65681b9ae5c96c292140368743df9e60f7e2ada58ca2bb95fa39abe064b2ebf21eeba", + "0x858e8d5bf2a1cf26d8af5036b28b831d450a446026f58a1734b696c18f1f41482796b91cab0e5b443dd2f0b9cffa52b4", + "0x99627dd6bad8c05c5904cd23aa667d664da846496dbbb8452705c4ec01e1480e9c7295504a5a8529e4a0c842306b038d", + "0xb64b33256c18b2c886a837a0c0730fdfe73befb0e2796207c4dc592c5a33cd51f8c2ef47c584dd5773abf9ce9c1b0082", + "0x944f6da2a1546f0bfc4d98c3e73c79e935e33d208b6be26b0b5f8df6d0e3b74a5bda649853b99281bd3a3ec799a7dd04", + "0xa266d165435784d4e884640155e35b2a911b3f89e1e715986de419b166a36a341ba724877d80583fa3da566f6a828971", + "0xadff2698409d0756e78c534032ee926560c13d578cb178d5073172d049ebbce32a92692f7e2033ec781b9b0d894ddce0", + "0xa91933f110756c699c28bf9e24fd405bf432002a28c4349e0ca995528e56a5a2d101b8d78afa90a178ff1a9bf2ba515c", + "0x8e77839c0eb4da2d01e4053912cd823eddffbdc6b9c42199fba707ca6ab49fc324288b57be959fbfb11d59085d49324a", + "0xaa124517c76692036c737e987f27c2660514e12a953e63ff4bcb269dd18fc44dae95e282de8444bed09639ef6577af88", + "0xb285deae99688f1bd80f338772472fa2b35e68887c7eb52c4ef30fc733812444c5cd110050275ad999d5a9b57f782911", + "0x8877b0fa85b44ef31f50bdb70b879fa6df5eb1940e2b304fd0c8f08abb65f3118fa3d97ff93919038c1e452fb1160334", + "0x8a89f3b50dcbca655024542ca7d93df17deff5c7d01c7da2bdb69e76b3e0b4490d85c800fb3debb4b0b4d20c9527f7ad", + "0xb7e5dbe36e985354ac2f4ab7730fea01b850af00767a6c4d8ee72e884d0fe539bb81f2e34638fcf5d07b7c8d605f4c06", + "0xa85a1d78f6d4f9d5d83ec0f2a426708342d4e4a5d15625554e8452f6a843d9aa4db0c7e68caebdaf767c5b3a6a6b2124", + "0xa518078a9dac63c5bf511b21ed8e50d1ccede27ebfe9d240937be813f5ee56aef93dc3bf7c08606be1e6172f13f352ce", + "0x91144eedebda4d1ad801654ef4ecd46683489b177ba1de7259f7dd8242c8c1700e15938e06c5d29aa69f4660564209a0", + "0xa16c4657bc29d1d3271f507847b5a4f6401cee4ad35583ad6b7a68e6c2b9b462d77b5dd359fd88ea91ce93bb99130173", + "0x85b855778f4b506880a2833b8468871c700440a87112fa6a83fd3ddb7e294b3a232d045dc37dfc7100b36f910d93c2ae", + "0x8d86bb149d31bfbf1fabcae1b8183d19087fd601c3826a72a95d2f9cedb8bb0203d1136a754aa2dd61f84b7f515acfa9", + "0xacfe7264eee24e14e9f95251cbcfdd7e7f7112955a1972058444df3c2d2a1070627baefada3574ebd39600f7f2ea7595", + "0x906bd14ecca20ac4ae44bff77cc94eb5a4ecc61eba130de9838e066e8766ed3b58705f32c650e1e222b3100691b3806b", + "0x8f2cbc7b8593c4be941dd01b80dc406fe9dfdf813ef87df911763f644f6309d659ea9e3830ff9155e21b195fc3c01c57", + "0xa68eb15ed78fae0060c6d20852db78f31bebb59d4ddc3c5bdd9a38dbe4efa99141b311473033ff8f8ea23af219bc8125", + "0xa95cb76c9d23fc478c7e8a73161f2ff409c1e28a2624c7d5e026e3cee9e488f22225a0c5907264545a73e83260e3a4ec", + "0xb76f90e55fa37c9e2732fd6eba890dd9f1958c1a3e990bd0ce26055e22fe422d6f0bcc57a8a9890585717f0479180905", + "0xb80cc95f365fabd9602ec370ca67aa4fb1219a46e44adf039d63c432e786835bb6b80756b38f80d0864ecb80e4acb453", + "0xb753c86c82d98a5b04e89de8d005f513f5ea5ea5cf281a561d881ed9ad9d9a4be5febb6438e0dba3d377a7509d839df0", + "0xa664733f3b902fac4d1a65ea0d479bb2b54a4f0e2140ed258570da2e5907746e2ac173ace9120d8de4a5e29657ae6e05", + "0x9479722da1a53446e2559bb0e70c4e5bf3f86c0ce478eede6f686db23be97fcd496f00a9e174ceb89ab27f80621f9b80", + "0xb707fd21b75a8d244d8d578f3302d1b32bb2d09f2bd5247dff638d8b8b678c87d4feab83fe275c5553720a059d403836", + "0x93214c16831c6e1d6e5a1266f09f435bbed5030c3c4c96794b38d4a70871782002e558d960778e4465b1ff296ffedad8", + "0x8648f84e18eb63dad624e5fa0e7a28af2ee6d47c28f191be0918c412bf24b5460c04bf2b7a127c472914a0741843f78b", + "0xb67f61e75d6b773a6b58b847d87084b94f3cdac3daa7bef75c2238903a84250355a986b158ff96ba276ca13a6035fdd6", + "0xae9b094b7b5359ee4239d0858d3755a51aba19fce8ad82b0936cca48017523319c3309409ea6e9883a41bece2077e4d8", + "0x8d1d8e1fba8cebd7a0e1effea785a35e16b1a10842f43e2b161d75add11eccf8f942d2ae91c20eef6c1a0c813731ea9a", + "0xb82bd387458e3603782d5e2dec32ae03890a3fc156d7138d953f98eff4200de27c224f626e3648e80cd3dfc684c4790f", + "0xa6dd02a89ad1c84e25e91176c26355e21a01b126c1df4d22546159dab9d502dbc69bc0d793a017c1456516e4aa5fa53f", + "0xa9ab74a5c5459b8500beb0ad13e9cfe2656e966dc9b4f3f98bec7588023b4ddebf74e4fc722d30423f639f4ee1b2587f", + "0xb03e5f33ab7ecec12cbc547038d3fa4f7ea0437e571891c39660c38d148212d191be29e04eb2dc001b674219b7a15a9c", + "0x925df4fc6e898ca55090ad1a8f756cc5014167a042affda5b24896eeb6aac408545134920586a8e1a2b997de9758b78a", + "0x98c8580fb56ed329fad9665bdf5b1676934ddfb701a339cc52c2c051e006f8202e1b2b0f5de01127c2cacf3b84deb384", + "0xafc3765d374c60fac209abd976fe2c6f03ce5cc5c392f664bb8fac01be6d5a6e6251ac5fb54cfcd73e3b2db6af587cbb", + "0x8e7e98fb5a0b5b50d1a64a411f216c6738baaca97e06d1eba1c561e5c52809b9dab1da9f378b5f7d56a01af077e4f8cf", + "0xb724bf90309651afb2c5babaa62dc6eac2b8a565701520fe0508cee937f4f7b6f483fc164b15d4be4e29414ce5d3c7d4", + "0x9665160e7bf73c94f956ecb8ba8c46fe43ae55c354ce36da40ccc7594beae21d48d9c34d1af15228c42d062a84353a0c", + "0x8600ab3aa86b408ee6e477c55572573ed8cfb23689bbdadf9fccb00161b921ec66427d9988763a7009b823fa79f8a187", + "0xb0d8d19fd1022e7bc628d456b9bd1a2584dce504eb0bf0802bdb1abd7a069abbeeccdb97ce688f3f84a229342dbc1c33", + "0x8f447d5e5a65bb4b717d6939cbd06485b1d9870fe43d12f2da93ca3bb636133a96e49f46d2658b6c59f0436d4eede857", + "0xb94e327d408d8553a54e263f6daa5f150f9067364ded7406dcb5c32db3c2dffd81d466ee65378db78d1c90bc20b08ab3", + "0xb58c02781b74ef6f57f9d0714a96161d6bfa04aa758473fb4d67cc02094cd0c0f29d0527c37679a62b98771420cf638b", + "0x8cfa0a687ea51561713e928271c43324b938aa11bb90f7ffaa0e4a779b3e98899f2af59364ce67b73a46a88748c76efa", + "0x95d6d39c814c5362df69116558d81ce6f1c65fb400fc62de037f670d85f23f392c1451d43341c59bc342bc31842c8582", + "0xaf888b384c52d9e04e4db6c4e507c2037eb5857e9bcc33acf84fc3a02d93cbde8cce32141fce9f5fec715b5f24d56356", + "0xa7822bbc3c236fd58bd978f0fc15fe0b60933a0c953db6436a233441219418090ae0c07c490a6548e319029771cdaba7", + "0x8c53729f750922e5eb461774be8851a3f40fe42eed170881cc8024d590bf0a161d861f5c967144d15cdcdc3dc6b5cf88", + "0xa052a25a4aeab0d5bb79bc92a6ae14b5ad07d1baca73f4f6684ccecfc7ea69bc21eadeb9510452fdba116c0502dd698f", + "0x923946b83d37f60555dbac99f141f5a232728c6eb819a37e568c8c6e4d9e97a4229fb75d1de7e9d81f3356f69e6d36f1", + "0x8cab82cf7e415b64a63bd272fe514d8b1fa03ba29852ec8ef04e9c73d02a2b0d12092a8937756fdec02d27c8080fb125", + "0xb1123314852495e8d2789260e7b3c6f3e38cb068a47bdf54ed05f963258d8bcabaa36ccbea095ba008e07a2678ec85a7", + "0xa685b779514961e2652155af805996ceb15fb45c7af89c5896f161cac18e07b78c9776047c95b196362c9ad5430bcb22", + "0xb734dd88f6cc6329c1cb0316c08ade03369a11dc33191086c6a177cf24540c7ceee8199b7afa86c344d78d513f828e81", + "0xb0bf492fb136ecdb602c37636ed4deef44560ab752c0af5080a79c9f76a1f954eba60a0bf6ba8bd7b8cac21848c29741", + "0xa5c74682323e85ac20f912ab9c1d6e1b9246c4c829dca40c8a7d58ec07ea0ad3524be30623f351269552f49b65a1245c", + "0x837403b9cf830fb33ecc11a7c8433e07745973c36acdeb3fc9ea8f7d8d690d462e1250b7410f79f2f4180fe8f3962a4f", + "0xb03d64b944d49c83608f2c5b9c14070c025f7568c4c33d4eeb1da31d07f0bc5897e498b35b50d557ee129f0c3c68e254", + "0x827272aab8bf757e2483156e00fbebe1093a58070dd3af9855bbf946c7abfb9c8a850a6a8acda8c620902f391f968b8f", + "0x84c4eb863a865282d321302d06b362f8bd11c2bb0090f90ebffedd3eb3e7af704cff00d39a6d48cbea4262942e95200b", + "0xb044eb91653dc55dce75c8d636308a5a0dae1298de4382d318e934140a21ca90e8a210e06fdf93aadbbeab1c2ef3904a", + "0xa8c08955a4378522e09a351ecb21b54025a90f2936b974068e80862803e7da2b5380c4b83b4b4aad0409df8d6c8cc0cb", + "0xa763a5fb32bd6cb7d7c6199041f429782deacac22b6a8467077fab68824dd69343ebca63a11004c637b9cb3129dbf493", + "0x8c44c8afa9a623f05c2e2aba12e381abdb6753bb494da81f238452f24c758c0a0d517982f3999d2537b7279d381625ed", + "0x8613f47fda577cd3bda7c99b80cf4b2dd40699edfd3df78acb5e456dd41fd0773bc8da6c5e8cbf726a519b9fb7646ccc", + "0xb21a30d49d7e1c52068482b837a4475568d0923d38e813cea429c1000b5f79b8905b08f6db237e2eccf7ef3e29848162", + "0xb9bdf4915f3fbb8d84cdfd0deedf2c9dc5b14f52bf299ef5dca2f816988e66322df078da2c54b934b69728fd3bef40b5", + "0x993b45f389f55eba8e5ba1042d9a87242c383a066cbf19bc871b090abe04de9ff6c1438cb091875d21b8c10fac51db58", + "0xa85a95d14633d52d499727f3939979a498c154fd7ebb444b08f637b32c1caf5cca5e933a2f5d94f26851ae162707b77d", + "0xb9874c7c4be1c88a9646e0c2f467cd76bc21765b5ab85d551305f5ec0b4419e39d90703d4ac1bb01feb3b160517e97b7", + "0xad6771177fc78812904c90594712956357de1533a07fec3082ba707f19c5866596d624efc3e11773b3100547d8f6c202", + "0xa79f31921134f7197f79c43a4b5d5b86736a8d3ad5af1bdf4ad8789c2bfe1c905199c5e9f21e9f446247224f82b334f8", + "0xa7f1b6c45321222a350a86543162c6e4e3d2a7c2dce41aeb94c42c02418f0892dbd70c31700245d78c4d125163b2cd5e", + "0x92abafe3ec9dbe55c193fb69042500067eb8f776e9bf0f1cb5ab8eb12e3d34986d1204136856fb115c12784c3b8dea6e", + "0x89bc761238a4d989006ca5af5303c910c584fe7e6f22aa9f65f0718a1bc171e452c43695e9f5a591725e870770c0eceb", + "0xaa0e44c2b006a27d35e8087779411ba2f9f1966a0f5646ff6871bcf63a8b1a4a7638751b94c9b9798ccd491c940bc53f", + "0x8736fe82862b8106e7fdab7b5a964d87ec291a74b8eb1cb5a6c046a648c1b686064ef3d52297043b8940bfe870c712f8", + "0x956a3def1942f05144d8e9c3a82fd2d3610064b53b9eefde3d5594a8f705bf8f6849eb2c22181796beffeba43cc74ee4", + "0xaf27416d00cf97d5a1f4a1b6b51c010884cceca294f1151c3b684a3f83c3c8a3c30771df1166d833cbddf6c873c400c3", + "0xaac3b8dca2336fc4ffc63c362df461289e4bbd3418c621bde6c581d3ecedf66e2b3e523d4db39e3d8ba014577bf85efd", + "0x94c3a8167f62074e5b28c2bffe4b6ce645439a9a0c5da3ca1b3ee956590a465d6f84a8a4dbbe9070ffbd6bbc734e4d62", + "0x95e23ba6986d25ed4451215da05bd72c5491528271726d79a94c8cb16aef1c85b190d6c5b8a3a1191c7cafbab1dccf0c", + "0x953e3dadb5ad68f7de31ac09692948655d174fe16d88b96930ef35b331da7f1dbc4c17863cd07b4ec3135b5205891a27", + "0x915d018f18b5d63cb3301c2bb5c6e85e75a88ba80663c964d06575b6bacbbe59139d030b218ce0998271d5b28c00b26d", + "0x8c871ba3dd138a908b2f7effeea0e71df096b23e0dd47cab10b9762b250abfd1221da94a8ee884e05bdf02271fb85a04", + "0x96bad5c6ebc3080ecbe337409ae398bbeada651221c42a43ea3b7c08c21841ddbcfde544c9b8d4772de6f2ce92c0b963", + "0xb5dbcd0b1c44c62108841558ec0a48df4b327a741e208c38b1c052321eda6e6ad01af71d49dfcdd445ab6fa6f0c34e6d", + "0x97dba59219b69e8aef2659d1f10bbea98d74aefff1f6451de3f41be39acbac0122b8ff58b02e90554469e88911ec3547", + "0xb7e5682ec306478be4858296f5d03364a61f3260636a4242f984d351a02e8723378496beb30c4ca22def9c9ca193ea70", + "0x9656a7a3df4d11df3d8bc35930dff70a5e78a488ca57bba20bb06814fc390fc6c7cb3f39b22134992aad196cced577de", + "0x8b269695aa63eb56d0324ba984279dc4c88e565321f1d61d553622bd4f1910d5eff68393d3a830eb924472bd478c2aa3", + "0x9177bcd04b28c87bc0440268b4c8995c6790cad6039594971b2c177f0e197055231e776927d3fa30d98fb897a2ba401f", + "0xae0e943973482001c4f214b9da82e1c27e38aa254d0555e016095c537c835d3702bc2de5c67b234ab151e02b3b7a43a6", + "0x82fc719a7d38bf4787fe1888019ad89fbf29beb951d2fece8686d2beb9119d0c8c6d13bc598748c72c70d73d488140ca", + "0xb716dc66f87eb16b95df8066877353962d91bf98cf7346a7f27056c2a4956fb65e55cb512af278783887ab269e91cd76", + "0x81d58cd8bc6657362d724b966321cd29a1b5cdc4601a49fa06e07e1ad13b05e9f387ca4f053ed42396c508cd065c5219", + "0xb32ad0280df6651c27bb6ddbdc61d5eb8246722140a2e29c02b8b52127de57a970e1ded5c2a67f9491ae9667349f4c46", + "0xb68a2eb64cc43f423be8985b1a068e3814b0d6217837fb8fbfd9c786db9cca91885c86899c50a1242040b53bf304ced9", + "0x85887515d4e371eabb81194cbc070e0c422179e01dbda050b359bd5870449c7950e6b3947b7a4a0eb68199341cc89fc3", + "0xac5fff3c27dfbab78eb8aad37ac31cc747a82401ebf3644a4f4f5aa98d37b8bf3b3f4bd8a3428b32a127c25c9e19d239", + "0x86fceaa6fbf8913553a9e1e907fcb1f1986d5e401a7eafd353beefd1899d571454fea96ff5b2a21254d9fb693ec94951", + "0xb6778bb296d3f0de2531b67d36fdbfa21475be0ca48b9dfcc38f396c41b557823735ed0b583e525a2bae1fe06e04058c", + "0x898088babeb5b9866537d6489f7514524c118704abd66b54210dc40a1c1ddb0a1edf7fe0b6e0db53b836f1828ecf939e", + "0xb27854364b97274765f0fb8d1f80d3660d469785d1b68da05e2bd1e4b8cbbe04304804d4c8aabb44cf030eba6c496510", + "0x8c55bbf3603dc11cb78b6395ccbc01e08afcef13611f7c52956b7a65ccf9c70551bff3ae274367200be9fc2d5cb26506", + "0x947726f73cd6281cd448d94f21d3b91b96de7ad3ff039f9153befbb5f172db9f53cacb4f88c80a3db26e6a0f7a846eb0", + "0xa7b733a05e97528812d71cecb4f638a90d51acf6b8fcbc054787d6deb7e2595b7b8d1cbe1aa09d78375b5e684a2019bc", + "0x8d5ca6d161341461544c533314fe0a6655cde032c2d96f0e4ea7e41098b8b39fa075d38e2d8c74e2d0308f250d6cf353", + "0xb960e9f081393e2260b41f988935285586a26657a3d00b0692ea85420373b9f279b2f1bb2da2caae72dd2e314045f1bd", + "0x852a49c7388c10821b387c6d51617add97ba72485f52be95d347bac44c638c92e9c6a44ba0d32afc4d59178a497d944a", + "0x8412162a65147e1334ad5af512982b2b48eef565682b3f3e0bbe93fbc5e1103db9375a0c486bdb1b2c57e4cb3a8e7851", + "0x8f52c3eb5d4f1e1e82cfd2b291d4910195427603b796f6c311deb35ef14a01a57a9e6cad39619ad108f3e86f384f9e1c", + "0x88d221088f2bf0103c53e44d0d96cd7881ec2b0a965db9121a47481771a8b796edd5ac23c4f9c208a171dab301f7d3bb", + "0xb49c3235e8b3617ed08a1891b9e2bcb33dbdacceb94ca96330555b7e00904fe6a749ced9312b8634f88bcb4e76f91cb1", + "0xa85834215e32f284d6dfb0cbfd97f6cffc7b9d354e8f8126d54598bb42d7f858a2b914cf84fa664069632db2ff89a332", + "0xaa3d48eb483c6120c27d9b3e3d0178c1c942632ff54b69f5b3cfbc6ad4ff5b2b9ce6eb771fd1eea8edf4a74c97027265", + "0xa446cfded353cdd9487783b45846402b973cdeddf87e2bf10cf4661610fff35743cc25e8d3b5771dcedfb46b018a5d18", + "0x80998377b3b393ef3073f1a655ad9d1e34980750e9a5cfb95f53a221b053ddb4d6985747217e9c920735b0c851d7551f", + "0xa35ac469790fac6b8b07b486f36d0c02421a5f74ea2f0a20ffc5da8b622ac45dfccabfb737efa6e1689b4bd908234536", + "0x8fb1f6d8e9c463b16ac1d0f36e04544320d5a482dd6ffaec90ea0f02b4611aaca984828bf67f84dcc3506b69af0a00a1", + "0xb6e818d61aea62c5ed39c0a22ccbb327178feebdabda0c9927aa1549d2c5bb0637785c4aed2a6d9a7b4989fa8634c64a", + "0xb4e7208d16018bf67caafe996d436113eac619732e3f529a6efb7e6f094d8ebea55b7be0e122be075770f5957b6ea6f0", + "0xb691d38b552befac61f6d367287c38d01fec73b7f2efdb6713ca30314a37fb7c177eb111fe6bee657f2681014e07630a", + "0x9817587e418e6e7e8e97ae27067f17b55d25dfb14e98f63f530620c855d9a348c9fa571c8508e2741f902f8b9fdc0c5c", + "0xb6a6e5ca779ba140bf1d84cd5394ede8262f7479637ec0087a4b152243a1774ba916d8115ce759a3bebd1b409de5f2fc", + "0xb53d1c84ad766ff794bf497db3228efd2cc8ed5fc1958d89c1126efdff361610ecb45ea8e329b39035ab00a66c1259c7", + "0xadc31333c507c8e0f4aa2934fcdca57fd9c786722a50dbd5404e129541f7ac182cc7373bf14e1e4e06e6cf94b31b90eb", + "0xa82b7fde4642d982d95cec669efee140ad797a2442c7f6620580527d163accbf021b893446cbb8038ea82fe25b15d029", + "0x91f7acf8a8903979afa281646fdecb54aa4d2ed905748e156e92f0910de268fa29d67107d40863935d677d1de8039be2", + "0x86fea71c6d43a7d93216a92fc24dfce8521fd4534a9558b33762d002081247867a6eff54cad7116023277fb4049403ad", + "0x8ae5369a7f9f4c91f3be44b98089efd9c97c08f5bb4cd8b3150c115ecd86288fa0865a046a489c782973a111eb93966e", + "0xb6fb9e829aa2c81c2d9eac72bb2fd7f3a08e0cd763532c2ce3287444d33cf48b3621f205e9603ec58525934b61a795a9", + "0x83e35ca808d84e41fc92115e9f6e283e928c3a614e6dfc48fe78c33b6411262e7bfa731eadb1e1937bc03cff60032e1d", + "0x832fca5196c95098ad47b7d24ba2f9d042e1c73ad2273edd1c2ce36386796ccc26e8567847697f3fcc2a0536a2a2087a", + "0x8fdb7038bc8f462ab2b76bf7053362f9c030019f1b6105cf42219a4e620ecc961e3eacb16a8e581a562a97f1418b0128", + "0x8d3a5a404b51b1ad8ce3b23970e0d5cc57b573922341008e3a952a1dd24a135e19e55b79d86a70cfd82e1c0e9630f874", + "0xba00c025c1c21c57c03cdfc0bfd094b35422281ff0a64b68b240617aa58c6b18800af5f2047d3ff9068bbe987d6c7980", + "0xb468f0dd51964b3806b0aa04f3fe28a035e8f5567fc7d27555be33d02701a838b8dbfe1348b6422c4eac46d2c75c40c7", + "0x8a73a18c97da9958903c38584b08d0e7e26993a5d9b068a5e0e1ee0d8a873942745cf795f94f7a3d3ba88790a9fbb2f6", + "0x953a0a40c2c8102723736854d13b228698c14a02d85c8d2e61db1a768019ac305faf0d5db62ac976430ce087a5b20f1e", + "0x8998219da6b34f657cb8a621c890a52cb98c2bc0f26f26e2af666eebeadadc5e8bdf4f830a91d04aca8ce186190152c8", + "0x8941e08c3155ad432236ed05460420a05dd0aaab30477493ffb364b14c00ea5b9183d30d3442b6321d2d20c36e4f5c7e", + "0x93f293ff7fb56cf5b03aee6f3ad2ad78444398ed5b3be56d7bf5b56b5aa5a2b980d13895dd57a5726d1b067c20cc55e2", + "0x84a16f313e3f75e31824f58d19ab24c6611fb4c75140a7cadc3c166f68819547c1d0ff7f7d13f5d8ae30dff1d80e2aa4", + "0xb6e3e830b15039d3e28b08f5465bb089eade11ee3bd80afe39e010df7db1fcf0c56d698717677a41ddbc91eeaf6544d3", + "0x95e928e6dfff51351281568ae72da7d1edeb6e9fe01f30af0499e7505ba35a22b5bb919d41bb809a432dce83f3977663", + "0xaabeeb60ca46f9b0232ff82ea7766dcab8cc5aaf9d23539f30174f9486640bc9312868ca493b59b314519fc399973e47", + "0xb393a11e957d0bbb3ecf617b075b5906a3450b348e62916c04791b366f0a7397cccd6648440ac544bc30526e1f95aad8", + "0xabb5bfc3964a6d246da60bd809d0ea6daf4f8222efdc12ceb6730194e85f413ee7eb03bae300abf7ea900dbbc3d08971", + "0x96c1bd1d1d216a4bfbcf000c123f296c0d31e1684e9e3884c14df23bf528c8d599f82bb98fcea491716b617216a8e0be", + "0x92d1e570a56f1741fd9f3d9f488cc336421c6256c14a08d340a63720be49b0029e3780e3e193a2e22bf66cc652fa22a3", + "0x8769c08551e3a730e46f8e5d0db9cf38e565a001dfb50db3c30fa7fa0e98b19438edc23c6e03c8c144581b720d7b33a4", + "0xb850bd67fdf5d77d9288680b2f6b3bc0f210580447fb6c404eb01139a43fccb7ed20051999ae2323ea5a58de9676bfb4", + "0x80285da7a0aaf72c4528a137182d89a4db22a446e6c4a488cf3411937f4e83f7b00ec7549b0b4417682e283f91225dfe", + "0x80520368a80b97d80feb09dbc6908096c40ff7120f415702c1614d7112b0b57f6729581c71f4a3ce794ac959a46494ff", + "0x9817b4c27a490b1cd5a6337e7bc7e8005fa075dd980c6bf075ddfa46cd51cc307ad1d9f24e613b762a20fc6c877eab41", + "0xad66bda1a3034ec5e420b78107896ecf36126ce3ef9705163db259072dfa438c6107717a33572272062b9f60cb89557c", + "0x876114ef078c2915288e29c9abe6b0ad6a756b5ee2930ba1b8a17257f3f0557602d1225e8aa41ce8606af71ada2a971b", + "0xaa3d6cde4c3b9d3d5d0c77a33e67f182a3e1cf89b0921423b2024236171955b34afc52b1f25b1dad9da9b001371771d7", + "0x984d3e3a72412d290e3459339757af7520d1739c7af0cbcf659c71999328db44f407d92e8a69fea11625612c49eac927", + "0xae890d0faf5bd3280dcad20a5f90e23a206661be8842375fea2ab22aadc500849ffbc52fe743b376d46bb926cedae6a6", + "0xb1f231f3f4d710c3fe80099faeb56dac67c1baf53b8fe67a9920fe4f90e52cb9a4bf19211249a6456613b28efe337f18", + "0x8caa54b418ba609d16520af3dff2e96d5f2eeb162c065a1763beb926547b2cfb3ae41d738db2c5681a9bc8bc9e6b9a1a", + "0x932157ff56c5ac29cf6cf44f450c882b3acfbb9f43d12d118da3d6256bde4e6eb3183aea304ab6967f37baa718ffec99", + "0x9360bed8fc5b6aac36aa69473040689bfc30411d20ffb7275ef39b9ff5789f9055d149383ce9f0f7709a1f9d683adbfe", + "0x98b5b33209068335da72782179d0c7aeeabe94b5560a19d72088fe8323e56db7ce65debe37a97536b6b8a0ca3b840b61", + "0x89a385c11be40064160b030a1bb28c3921fc8078522618a238c7ea0f86f34717ed9af9b4e2e20f5128e5f7fc66ad841e", + "0xb615703cbc64b4192990cc7e4903b74aed6a0076ce113b59ef7719197ffa46fb29eb78ca56b49873487432d0625c0faa", + "0x90f0d77abae9d3ad73a218e5ccec505ad108ea098451461567ae8ef9661606ca8e78df53b5d628b20b7037bd24622330", + "0x92e0e7cc4dfadc5fa0ee6da0c8de0493030db6e54ba0317f52f232a6708b732068b6077bd13a17eb7eb40b88368085b5", + "0xa24dad20094985bfccc6df1343506ed3bf9dcbdf4b2085a87627a5d71f7568db067304e465f8f380c5c88e8a27291a01", + "0x8629a45a10619354c84bdc2f6c42f540eab5a46f53f2ae11970433d7a2aef007897590bf31dfba1c921614c6d6fe1687", + "0x84ac64040d4206f82b08c771f375da4b7d752e41d2aa0da20ce845f6bc1b880a855d3ee966bca19b8ec327b4b43e7f0e", + "0x9608e6050c25996c052509f43f24a85cdf184135f46eaac520a9a6e78e0d44a6cee50ebc054048c708aefde8cd6651c2", + "0xa32032b0e0d7cc35e480c328f315327f9385adb102a708c9ba637878deb74582ae26bb6d6e5f8c9e3a839b0e0154b82a", + "0xb7e3c78d63acc6564a49e9f00b0a820b56d4f37a2374af1f7f1d016268011df9e7af0670ed2b0eee961f15aa948328dd", + "0x8b88bfdd353acc91ad0d308a43e5fb40da22c228f2fe093c6d6904d70f69c6203f56636ed898b05df51d33f1095ef609", + "0xb1d7a430c51fc857af55047683fc18c453b013527196c5e1bf776819a3dffca802217e9249ae03f084e2ea03ad67fcc2", + "0x80558e28a819ddb5e72e97c54be0f57c173ccf78038d360d190b7f1350a19577b8e3f43fa2f7bf113a228cd3b965b2e4", + "0xb4b2ec44e746c00dfc5661ba2514930934fc805cdc29adc531c02d28ce3cc754414b0485d4ee593232cd1175f357ad66", + "0xb57cee5d32835f76572330f61ccd25a203f0e4a7e5053d32965db283aad92f287645533e8e615137208383ec51b1fd99", + "0x930256086b419a8a6581c52590d0dbd9f8a3564c79424198fca3866b786df2f6098a18c50dc4abd20853a7184b1ce15d", + "0x8e75fd01181cffcd618a983492390f486e8c889972a46c1f34a4e1b38f384e8e4efc7e3c18533aa2057da9f9623e2238", + "0xb375d927dd988429f9e2764e5943916131092c394fce13b311baa10f34b023dd3571da02553176091a0738cc23771b9a", + "0xb9e28e4c0d0477518034d000e32464852e6951c8db6f64ccdb1d2566f5094716213fbf2fc0e29ac88d0e79f725e3c926", + "0x963981e99392afbd2b8318d5a6b2b0cc69c7f2f2f13f4b38dddbfedb2b0eaf0584aecfcbda20a4c60789c15d77970a58", + "0xa7804e1977aa77c263c7c001afa6cf568032dea940e350d6a58ce4614f1a91c13ae1c78bfea740c229dce2444556976a", + "0x8787204177da3cde6d35cd3497fa8774d244f9faa9f4bd91b636a613a32ce2ea0326378cf9c4cf475e73ef751b355c4b", + "0x895aeef46a07152a04ec812f1aa1fd431389fa0ef6c6e96a5b833e70ea14073bc9984757a8ee456dbec9788e74e6f0ca", + "0x8d17f0e5826783440d1f0ec868003510a4d9952bfe4a638e44a36d94482ac18ba70ef7ff773bdf7a3b62d714dcf0fcba", + "0x810d5e36b31310b2e054a666d3b3f7ed16dfcb1765532d87ca2a3920316f0187303c27dd113db145d47e8961062a6c03", + "0xb4e2fb48ae04cf8580bb6a28095076c9b95e5f13122b917328f334d4ac8a8648ce442919e28319a40148987350ab5303", + "0xb85549a313544fa1eb3ceb78473b7d3d717fc85b808de7b79db7dbd0af838ebb020622a7503f1cbacab688dddb648f84", + "0x80665adee057088eae827a5fe904ec3ad77d8843cdce0322d535e0659b4abc74a4d7ddd8a94c27f2def5c34ac2c038ee", + "0xad72fc19c2ce99b5b717e35528fe7d3ac8add340b02ebeb4889d9a94c32f312a0b45ea84d21c54f84cc40ee4958b72e1", + "0x99d530c843dff89a47a5ee8c87303ab18f8a82b0d5b808fca050354b35da5c5a5594d55921c6362d6cc917d75bdc18dc", + "0x99c7286c293e1be21c5b2a669dfdfcd5aa587105d2886fc5a8eaf8984da4e907f7d7b8c2362d64a4f1621b077a2a08a0", + "0xb4a39e1a9ed5d80c9563c3ca3fadf76f5478c63a98f4346a61b930c9c733e002f3ff02bc16abfdb53d776184cc3f87ba", + "0x9378ea71b941979404c92d01fb70b33fa68d085bf15d60eb1c9fc2b5fcdee6379f5583389a3660a756a50019a2f19a69", + "0xb68e17344a2bc45b8e2e19466b86dc139afefbf9bad2e2e28276a725099ebac7f5763f3cb52002261e3abe45ef51eb1a", + "0x819e64dc412b2d194d693b9b3157c1070a226af35c629837df145ea12ad52fa8eabd65b025a63c1fb0726207a58cdde8", + "0xa5e8ff8748419466ff6df5d389125f3d46aedacf44eaf12cbfe2f68d218c7d5ab6de4a8279d13aecc25f3b1d98230894", + "0x91560d54a9715cfda9cf7133ae51c432d0bf7fcbaeb468004994e6838bfc5ddcfa30e4e780667d0c4c0376780b083017", + "0xae8adb3309cc89d79a55ff74f129bb311fe4f5351a8b87600a87e0c3ba60825f71fccf67eadcf7e4b243c619417540fd", + "0x8d92cc1a6baa7bfa96fbce9940e7187b3d142f1888bdcb09bb5c8abf63355e9fb942ac4b4819d9be0e0e822d3e8e2e08", + "0xa6e8b79fdd90c34735bb8fbef02165ccbe55ea726dc203b15e7a015bf311c9cac56efd84d221cc55eaa710ee749dbdfe", + "0xa409b151de37bddf39ce5f8aa3def60ee91d6f03ddd533fce9bf7bdbeac618cc982c4f1ffbf6e302b8353d8f28f8c479", + "0xb9693975ef82171b3b9fc318ca296e4fe6110b26cbdfd653418f7754563fa7b6e22d64f8025ee4243483fa321572bfe4", + "0xa039ebe0d9ee4a03ade08e2104ffd7169975b224061924cca2aae71464d250851e9f5f6f6cb288b5bf15df9e252712a6", + "0xb27834db422395bd330e53736a001341ce02c9b148c277dabac67dc422741bfa983c28d47c27e8214cd861f2bad8c6f6", + "0xa2bafaf4e2daf629fd27d7d5ac09fb5efc930ff2ae610f37519808683aa583fe1c6f37207daf73de1d8a164f79a0c981", + "0xb856cee1cfcf5e50db9af4ab0aed3db2f43c936eaea369b5bba65582f61f383c285efbda97b1c068c5d230cbe94f7722", + "0xa61ab205554c0550fa267e46a3d454cd1b0a631646b3df140623ff1bfffaa118e9abe6b62814968cc2a506e9c03ea9a0", + "0x8c78edcd106377b9cbdfa2abd5278724aed0d9e4ae5869b5d2b568fdabb7804c953bae96294fcc70ef3cd52ba2cbe4ed", + "0x8570869a9bbf6cc84966545a36586a60be4d694839f367b73dfc40b5f623fc4e246b39b9a3090694aa2e17e652d07fd1", + "0xa905b82c4da8d866a894da72315a95dc98faa3c7b3d809aef18f3b2be4801e736a1b79a406179e8cac8f74d27e71ac52", + "0xa8eb8679ff1a64908515f6720ff69434cb33d63aeb22d565fde506618908b1d37585e3bd4d044fd0838b55787af06b42", + "0xaf4d86b2fbd1684a657dffe4210321a71e6ae560c144d44668d1f324dc9630e98348c3d444622a689327c1a59cc169dd", + "0x80359c6eab16954559ab0e6a1fee9a0526c45d3cae1a371159a2e3aa9b893afdc3a785c9559a5fd9cd8cd774234bf819", + "0x8d4e5ff81eb5d17bbe8ae6416538ca51a9427ce142b311f5cbb14febbbbb9c1ffc6489fd625b9266264c366c12a9d997", + "0x92e181c66489c5fa063ba2a1a354b6fd3439b8b4365a8c90e42e169bfaa1fb5766bf3e0fe804399d18bc8fbcafb5c3b1", + "0xa9ddf229360a095393885083716cb69c819b2d7cfb100e459c2e6beb999ff04446d1e4a0534832ae3b178cbe29f4f1d3", + "0x8e085ef7d919302a1cc797857b75cff194bdbc1c5216434fa808c3dea0cf666f39d9b00f6d12b409693d7a9bd50a912c", + "0x916dc4dc89e5e6acf69e4485a09fc66968f9b292eac61a146df1b750aa3da2425a0743d492179f90a543a0d4cd72c980", + "0xb9cbf17e32c43d7863150d4811b974882da338cf0ed1313765b431b89457021dd1e421eeaa52840ef00551bb630962dc", + "0xa6fb875786daec1a91484481787093d8d691dd07e15c9c0c6ae0404bf9dc26083ed15d03c6d3fe03e29f28e20da21269", + "0xa870fcb54b9a029e8086de9b08da8782c64ad2cc2e7fdf955b913d294038bb8136193256b85267e75a4ca205808a76b4", + "0x99883f057e09b88bf0e316f9814c091837fd5c26eeb16fec108c9fed4b7a2bd1c783dac0e4242b5a906621ab606c1e50", + "0x85d89069ca3190577dab39bbec43c16bf6dbca439ad3eebd8f5e9f507d84c3c43e77fd6323224582566a3aa2c8018951", + "0x9363ba219e0003f6e8a9d8937b9e1449e4b2c5cd57194563b758bea39deab88778e8f8e4f7816970a617fb077e1e1d42", + "0x820622f25553c035326145c1d2d537dc9cfd064c2f5bdf6d4ec97814de5fe9a0fbd443345fa2ea0a9d40d81d3936aa56", + "0x87e31110aaf447e70c3316459250e4f7f8c24420c97828f9eb33b22107542c5535bdb48b0e58682dd842edea2886ff08", + "0x95bf80cac6f42029d843d1246588acb40a74802f9e94b2bf69b1833936767e701ef7b0e099e22ab9f20f8c0c4a794b6c", + "0xa46ecf612b2763d099b27fb814bd8fdbaee51d6b9ac277ad6f28350b843ce91d701371adfaaf4509400dc11628089b58", + "0x8604decf299fb17e073969708be5befeb1090ab688ad9f3f97a0847a40ea9a11bbcfc7a91e8dc27bc67a155123f3bd02", + "0x8eb765c8dc509061825f3688cb2d78b6fef90cf44db33783d256f09be284bc7282205279725b78882688a514247c4976", + "0xb5c30b2244fa109d66b3a5270b178960fdec47d31e63db0b374b80d2b626409eb76d2e8d1ebf47ef96c166743032fc5e", + "0xaab01e76290a7e936989530221646160bf8f64e61e79282e980c8c5dcaaa805ff096efd01d075a2c75917a3f4bf15041", + "0xb9d79671debd0b83d0c7c7c3e64c0fb1274300564b262771f839b49218501e7f38ef80cae1f7e5a3c34acdc74c89dab6", + "0x92c0eaceadf036b3b9dfd2712013aba3dd7c30b7760f501f52141618265baa31840fe77850a7014dc528f71f8cf39ce6", + "0xb3cdd098059980455dd5b1c04182df1bd12fa844a866f02a9f8a86aab95b59945baa9af99f687410bffc5b07153cb23c", + "0xb361b73a62f71256b7f6ea8e0f6615e14fc5a06ee98b928ab3c9dd3eef9d9d30070e9855c82b7facb639cacb3401e01f", + "0xb9c85fc0f25a3271cf28b1ca900078eaaa66cbab0a3e677606e898ac32781a2dfce4d9cbd07404599e2c3c02fa161c9d", + "0xac5b4fdac2a0b2e6430d9fc72bde4249d72183b197fc7347bb1546ae6f544426686bbe0caec3ee973b6836da5e831c44", + "0xb675aebf24b92e398e166f171a6df442b3f5919b6bee192f31675a5e8eeb77d34c6590a6f0c0857417e0f78cfb085db8", + "0xa9bef942044d8d62e6a40169f7dc7b49e40cd0d77f8678dd7c7bae6f46c46786f9b1e319a3fa408f22a54fd2a4d70804", + "0xa20d19cd917d5102ae9ca0cf532127d2b953aa3303310e8a8c4b3da025dded993a47e3a28e6b02acfadb6d65dc2d41a3", + "0xa47fdb04059b83b2afb86a47b2368bbd7247c337a36d3333b6e5ef2cc9476a92c4907e4c58a845c9ef9b497621e0b714", + "0x94a9e9ffc14b411e11a4ffa59878d59460263589003dc7b6915247c549f67feede279bf3645fdd92379022fb21e3caeb", + "0xb92e1177dd9ecdaf1370c71b14954219cf0851f309bc216d5907a4e2e84e0df3457018224150c142cc6bf86644bb4b73", + "0x8bc57fadd68a265b7df9b42227a9c0968db7b1bb50dc12f7d755505779f1ff2c408672b3091e903366acc9ce15d19fb6", + "0xb6b5efbe1ac4e1bd2e8447c45000d09397b772ca5496acc447b881022608a41c4f60388814607a01890190105bee7be3", + "0x95f7c85fd614df968f8ccf8d086579c9e1cec4644ecf06da26e3511cb39635a7326b3cec47bd51cf5646f1c660425e9c", + "0xb81765fb319bcdc74b4d608383ccb4af7dd84413b23af637be12e2827a75f7e4bcd14441cf979ed9038ae366fbb6f022", + "0xa120ea76cda8c6c50c97035078f6648afe6537809bdba26e7c9e61de8f3070d2347160f9d34010effbf2ec7e94f5749f", + "0x92c1b8631953b40d3cc77eee2c72a064b999c09a9b92c11d8fa7b4072966273901c9dba25f9f79f384d9f11a56f3fc7a", + "0xa4b00dc0ab67b2300abc9c516e34daf444d6497b066a90cfe3381ed2812304ed37b14f3b948990443dc6c1cf1bed460c", + "0xa9e9f7e13c9f031bc7b9e6f1417c7abcc38894fe7d3f54869ee277afd2efa3e6fb50757dd36c8c94d591e0abdea322cc", + "0x84f3e98f831792b5ad14bcfe62a4c9f296476c6087c4c1ec7767fc642fbca141ff6a3deeb8b4d4106a9cda5a9937eea0", + "0x8eb1a7931bbea9a714226fd74b0100ab88355287d9b0a349c095e9b5809b98f237ffd706bce7d67a770da355fb9cec7b", + "0x9738ef8739e1742c1f26b51a1621be0b89d37406a370c531e236f635c7064c661818817bb3858908986aa687b28b21be", + "0xa9cf3ce8501b003ccaf57552a4c4ec31081e44526d3aa3791d3dc4a7e438a357c0956f93c500356186d8fd4588ffac5e", + "0xa7af6a219cca59225839a9de5b19263cb23d75557d448bc7d677b62591a2e068c45e5f4457cceb3e9efa01d0601fc18a", + "0x972a24ece5eda7692cbb6fb727f92740451bc1281835e2a02931b2b05824a16b01dbe5edd03a0ed5b441ff25a5cc0188", + "0xb21d1ec7597ce95a42f759c9a8d79c8275d7e29047a22e08150f0f65014702f10b7edce8c03f6e7ab578ce8c3b0ec665", + "0xa13a1c7df341bd689e1f8116b7afc149c1ef39161e778aa7903e3df2569356ad31834fa58ceb191485585ce5ef6835c3", + "0xa57bdb08119dc3bc089b5b2b5383455c4de0c2fcdac2dcfa21c7ac5071a61635ff83eceb7412f53fab42d1a01991de32", + "0xb2968748fa4a6921ee752d97aa225d289f599a7db7a222450e69706533573ded450380c87f8cdd4a8b8c8db1b42b5c97", + "0x8718ec04e0d5f38e3034ecd2f13dfde840add500f43a5e13457a1c73db0d18138f938690c8c315b5bcbeb51e8b9a2781", + "0x82094789e26c4a04f2f30bdb97b9aecca9b756cbd28d22ab3c8bed8afc5b2963340ddfc5a5f505e679bf058cbc5dcbb8", + "0xa35b8a566dd6ab67eddc2467906bffc76c345d508e52e9e4bb407b4f2b2c5f39b31d5a4bf5022f87bf7181dc6be2fe41", + "0xa8c93b1e893d4777c0e3a1b4bef3be90c215781501407c4011457fc3240e13524b4d2bea64a6d0a3efe3f3b0dae9b8ab", + "0x877095ad18b1e5870818f7a606127ba1736a0b55b0dbcd281ec307c84b08afc0c9117e3a880fe48bfc225fbf37671a97", + "0x84405ee0421ed2db1add3593df8426a9c1fcc8063e875f5311a917febc193748678dd63171d0c21665fb68b6d786c378", + "0xa52cdc8209c3c310bed15a5db260c4f4d4857f19c10e4c4a4cfe9dfc324dfac851421bb801509cf8147f65068d21603c", + "0x8f8a028a70dda7285b664722387666274db92230b09b0672f1ead0d778cee79aae60688c3dfd3a8ed1efdeda5784c9d4", + "0xa0be42fecc86f245a45a8ed132d6efc4a0c4e404e1880d14601f5dce3f1c087d8480bad850d18b61629cf0d7b98e0ae0", + "0x83d157445fc45cb963b063f11085746e93ab40ece64648d3d05e33e686770c035022c14fdf3024b32b321abf498689ad", + "0x8a72bbf5a732e2d4f02e05f311027c509f228aef3561fc5edac3ef4f93313845d3a9f43c69f42e36f508efcc64a20be0", + "0xb9ca29b0ec8e41c6a02f54d8c16aebf377982488cbe2ed1753090f2db4f804f6269af03e015d647a82ef06ffaa8cba6c", + "0xb4df3858d61bbb5ded1cf0be22a79df65ae956e961fbb56c883e1881c4c21fe642e3f5a0c108a882e553ac59595e3241", + "0x86457d8890ac8858d7bab180ef66851247c2bf5e52bf69a4051d1d015252c389684fcc30bb4b664d42fbf670574ab3a3", + "0x86d5576ea6dfa06d9ebce4cd885450f270c88a283e1e0d29cab27851c14ed2f00355e167b52e1539f1218ad11d8f13dd", + "0x883ad1364dc2a92388bfafaa9bc943c55b2f813525831e817a6208c666829a40455dde494eba054b2495a95f7ce69e8a", + "0x8942371e6925231c2c603b5f5a882d8404d39f0c7c4232557c2610b21c2c07f145466da798ea78b7932da2b774aa3128", + "0xa799eb71496783cc7faf12c9d9804bf6180699a004b2f07fc5cc36840f63ce7eee7dde9275819a9aa3f8d92dc0d47557", + "0x8eb3fb5c769548ee38c7882f51b959c5d5a42b5935269ccf987d6ddbb25a206e80c6000bcc328af149e0727c0b7c02c0", + "0x8f3910d64e421a8f2d8db4c7b352ba5b3fc519d5663973fea5962efe4364fb74448770df944ef37ffe0382648fb56946", + "0xb41413e0c26ff124cf334dab0dc8e538293d8d519d11cc2d10895a96b2064ac60c7da39f08589b38726cffa4c3f0bfef", + "0xb46ef2eb10abae0f35fa4c9c7ee2665e8044b8d9f91988a241da40fd5bbc63166925582151941b400006e28bbc5ba22a", + "0xb8baa8b4c420bb572a3b6b85479b67d994c49a7ebfe1274687d946a0d0b36dfed7630cfb897350fa166f5e2eff8f9809", + "0x964b46d359c687e0dcfbdab0c2797fc2bd1042af79b7418795b43d32ffca4de89358cee97b9b30401392ff54c7834f9f", + "0x8410d0203d382ebf07f200fd02c89b80676957b31d561b76563e4412bebce42ca7cafe795039f46baf5e701171360a85", + "0xb1a8d5d473c1a912ed88ea5cfa37c2aea5c459967546d8f2f5177e04e0813b8d875b525a79c29cb3009c20e7e7292626", + "0xafaab9a1637429251d075e0ba883380043eaf668e001f16d36737028fded6faa6eeed6b5bb340f710961cee1f8801c41", + "0xaef17650003b5185d28d1e2306b2f304279da50925f2704a6a3a68312f29fe5c2f2939f14e08b0ba9dee06ea950ad001", + "0x97bcc442f370804aa4c48c2f8318d6f3452da8389af9335e187482d2e2b83b9382e5c297dce1a0f02935e227b74e09a3", + "0x8a67a27b199f0bcd02d52a3e32f9b76a486b830ec481a49a4e11807e98408b7052b48581b5dd9f0b3e93052ec45dfb68", + "0xb113bf15f430923c9805a5df2709082ab92dcdf686431bbad8c5888ca71cc749290fa4d4388a955c6d6ee3a3b9bc3c53", + "0x8629ca24440740ce86c212afed406026f4ea077e7aa369c4151b6fa57bca7f33f9d026900e5e6e681ae669fd2bd6c186", + "0x933a528371dcecc1ec6ded66b1c7b516bd691b3b8f127c13f948bfbcda3f2c774c7e4a8fbee72139c152064232103bdf", + "0x8568ddd01f81a4df34e5fa69c7f4bb8c3c04274147498156aec2e3bd98ea3e57c8a23503925de8fa3de4184563a2b79e", + "0x8160874ec030f30fda8f55bcf62613994ff7ed831e4901c7560eac647182b4a9b43bfaff74b916602b9d6ae3bfcaf929", + "0xae71c48d48cf9459800cdf9f8e96bc22e2d4e37259e5c92a2b24fbe2c6ca42675e312288603c81762f6ceb15400bc4c9", + "0xb05f39bb83fda73e0559db1fd4a71423938a87ad9f060d616d4f4a6c64bf99472a2cbfb95f88b9257c9630fc21a0b81f", + "0x80c8479a640ed7a39e67f2db5ad8dfd28979f5443e8e6c23da8087fc24134d4b9e7c94320ffa4154163270f621188c27", + "0x9969ba20ee29c64cb3285a3433a7e56a0fe4ddc6f3d93e147f49fe021bed4a9315266ebb2fb0eb3036bb02001ae015e6", + "0xa198c89fef2ab88e498703b9021becc940a80e32eb897563d65db57cc714eaa0e79092b09dd3a84cfab199250186edcc", + "0x8df14a3db8fe558a54d6120bad87405ba9415a92b08c498812c20416c291b09fed33d1e2fcf698eb14471f451e396089", + "0x81e245ef2649b8a5c8d4b27188dd7e985ef6639090bdc03462c081396cf7fc86ed7d01bfe7e649d2b399255e842bdc21", + "0x8659f622c7ab7b40061bcf7a10144b51ad3ab5348567195924f2944e8c4ce137a37f1ba328e4716c10806f3fb7271689", + "0xa575d610fc8fe09334ca619ecdadf02d468ca71dd158a5a913252ca55ea8d8f9ce4548937c239b9cb8ab752a4d5af24a", + "0x94744549cd9f29d99f4c8c663997bdfa90e975b31f1086214245de9c87b0c32209f515a0de64d72d5ef49c09b0a031fa", + "0x80a8677862b056df59e350c967a27436c671b65d58854e100115bac9824ba177e94c2a1bfcaa191a071b9cefdbee3989", + "0x91be9a5504ec99922440f92a43fe97ddce2f21b9d94cd3a94c085a89b70c903696cec203bbab6d0a70693ba4e558fb01", + "0x8c5a0087bcd370734d12d9b3ab7bc19e9a336d4b49fc42825b2bfedcd73bb85eb47bf8bb8552b9097cc0790e8134d08c", + "0x933aa9e6bd86df5d043e0577a48e17eea3352e23befdbb7d7dcac33b5703d5ace230443ac0a40e23bf95da4cc2313478", + "0x984b7ee4bd081ee06c484db6114c2ce0ba356988efb90f4c46ff85ed2865fb37f56a730166c29ef0ae3345a39cdeae7a", + "0xae830f908ea60276c6c949fb8813e2386cf8d1df26dcf8206aa8c849e4467243e074471380ed433465dc8925c138ea4c", + "0x874c1df98d45b510b4f22feff46a7e8ed22cfc3fad2ac4094b53b9e6477c8dfc604976ca3cee16c07906dece471aa6c6", + "0xa603eb60d4c0fb90fa000d2913689126849c0261e6a8649218270e22a994902965a4e7f8c9462447259495fe17296093", + "0xa7c73d759a8ad5e3a64c6d050740d444e8d6b6c9ade6fb31cb660fa93dc4a79091230baccb51c888da05c28cb26f6f3f", + "0xa4411b79b6a85c79ea173bd9c23d49d19e736475f3d7d53213c5349ebb94a266d510d12ba52b2ac7a62deaaaec7339b8", + "0x943b84f8bbcee53b06266b5c4cd24d649d972593837fe82b0bf5d5e1bbc1a2bf148e1426c366d7c39ab566b10224cadc", + "0x8300012096a8b4cefecc080054bf3ceb0918162ba263c6848860423407796b5eb517170c0bad8e4905ac69a383055a21", + "0x8244a1e3ad41908c6f037e2f8db052e81f281646141334829f36c707f307448b9ab79a7f382a1e8d86f877c90b59271c", + "0x8eca1b74687802ecc36a5d39e4516a9dee3de61a2047252d9ed737b49e0090c386e9d792ac004c96337681c7f29a16ad", + "0xb70fa47535f0524835039a20036c61e77f66146ad79d3d339214d8744742db41ceeb577c829d000011aeafbb12e09579", + "0x84b3abbce48689f3adbb99889c7fd1f3e15ab455d477e34f5151c5c1c358ed77a5b6a581879f7e0f1f34106e0792e547", + "0xab45ecb58c0ef0dbce3d16afc6ac281e0d90ec48741ea96a141152647e98fcc87f3a3ff07ba81f3179118453ce123156", + "0x90d231a145ba36a59087e259bbfc019fa369201fcfeaa4347d5fd0a22cd8a716e5a797f3cc357f2779edb08f3b666169", + "0xa4f6074d23c6c97e00130bc05f25213ca4fa76c69ca1ace9dece904a2bdd9d987661f5d55023b50028c444af47ff7a08", + "0x933af884939ad0241f3f1f8e8be65f91d77ac0fb234e1134d92713b7cfb927f1933f164aec39177daa13b39c1370fac8", + "0x80d1db6933ce72091332ae47dc691acb2a9038f1239327b26d08ea9d40aa8f2e44410bbda64f2842a398cbe8f74f770f", + "0xa7a08605be2241ccc00151b00b3196d9c0717c4150909a2e9cd05538781231762b6cc6994bebbd4cddae7164d048e7b2", + "0x96db0d839765a8fdbbac03430fa800519e11e06c9b402039e9ae8b6503840c7ecac44123df37e3d220ac03e77612f4e4", + "0x96d70f8e9acd5a3151a8a9100ad94f16c289a31d61df681c23b17f21749c9062622d0a90f6d12c52397b609c6e997f76", + "0x8cf8e22273f7459396ff674749ab7e24c94fe8ab36d45d8235e83be98d556f2b8668ba3a4ec1cb98fac3c0925335c295", + "0x97b7e796a822262abc1a1f5a54cb72a1ea12c6c5824ac34cd1310be02d858a3c3aa56a80f340439b60d100e59c25097d", + "0xa48208328b08769737aa1a30482563a4a052aea736539eceab148fa6653a80cb6a80542e8b453f1f92a33d0480c20961", + "0xb612184941413fd6c85ff6aa517b58303b9938958aa85a85911e53ed308778624d77eadb27ccf970573e25d3dfd83df7", + "0xb3717068011648c7d03bbd1e2fc9521a86d2c3ae69113d732c2468880a3b932ebec93596957026477b02842ed71a331b", + "0xa0ad363e1352dcf035b03830fef4e27d5fd6481d29d5e8c9d51e851e3862d63cdcbaf8e330d61c1b90886921dac2c6fd", + "0x8db409fdacfa4bfdaf01cc87c8e97b53ca3a6e3a526d794eaad1c2023f3df4b888f1bf19fee9a990fe6d5c7c3063f30c", + "0xb34d6975310ab15938b75ef15020a165fc849949065d32d912554b51ffa1d3f428a6d1a396cb9329367670391de33842", + "0x9117285e9e6762853fc074b8a92b3923864de2c88c13cea7bab574aaf8cdd324843455d2c3f83c00f91f27c7ecc5592a", + "0xb4b2e8f190ea0b60819894710c866bf8578dd1b231ae701d430797cc7ede6e216e8ca6a304f3af9484061563645bf2ab", + "0x8c493c6853ab135d96a464815dd06cad8b3e8b163849cdefc23d1f20211685753b3d3e147be43e61e92e35d35a0a0697", + "0x9864d7880f778c42d33cf102c425e380d999d55a975a29c2774cad920dfddb80087a446c4f32ed9a6ab5f22ec6f82af0", + "0x90f67fe26f11ca13e0c72b2c2798c0d0569ed6bc4ce5bbaf517c096e7296d5dd5685a25012f6c6d579af5b4f5d400b37", + "0xa228872348966f26e28a962af32e8fa7388d04bc07cfc0224a12be10757ac7ab16a3387c0b8318fcb0c67384b0e8c1a4", + "0xa9d9d64bba3c03b51acf70aeb746a2712ddafe3b3667ae3c25622df377c2b5504e7ab598263bec835ab972283c9a168b", + "0x932128971c9d333f32939a1b46c4f7cf7e9d8417bd08dc5bd4573ccbd6ec5b460ac8880fb7f142f7ef8a40eef76d0c6d", + "0x964115e7838f2f197d6f09c06fbb2301d6e27c0ecdf208350cf3b36c748436dac50f47f9f9ac651c09ab7ad7221c7e43", + "0xa5941f619e5f55a9cf6e7f1499b1f1bcddcc7cf5e274efedaaad73a75bc71b1fc5c29cd903f6c69dc9a366a6933ca9d1", + "0xa154bf5eaec096029e5fe7c8bf6c695ae51ace356bb1ad234747776c7e1b406dee2d58864c3f4af84ed69f310974125e", + "0xb504e6209d48b0338ab1e4bdab663bac343bb6e0433466b70e49dc4464c1ec05f4a98111fd4450393607510ae467c915", + "0x813411918ea79bdde295393284dc378b9bdc6cfcb34678b9733ea8c041ac9a32c1e7906e814887469f2c1e39287e80f8", + "0x8be0369f94e4d72c561e6edb891755368660208853988647c55a8eed60275f2dd6ee27db976de6ecf54ac5c66aaf0ae6", + "0xa7e2701e55b1e7ea9294994c8ad1c080db06a6fc8710cd0c9f804195dce2a97661c566089c80652f27b39018f774f85e", + "0x956b537703133b6ddf620d873eac67af058805a8cc4beb70f9c16c6787bf3cc9765e430d57a84a4c3c9fbdd11a007257", + "0x835ae5b3bb3ee5e52e048626e3ddaa49e28a65cb94b7ecdc2e272ff603b7058f1f90b4c75b4b9558f23851f1a5547a35", + "0x85d67c371d1bf6dc72cca7887fa7c886ce988b5d77dc176d767be3205e80f6af2204d6530f7060b1f65d360a0eaeff30", + "0xa84a6647a10fcef8353769ef5f55a701c53870054691a6e9d7e748cbe417b3b41dbb881bae67adc12cb6596c0d8be376", + "0x87ffe271fc0964cb225551c7a61008d8bcb8b3d3942970dbcc2b9f4f9045a767971880368ea254e2038a3a0b94ecf236", + "0x964bb721c51d43ee7dd67c1a2b7dd2cc672ce8fad78c22dcddb43e6aab48d9a4a7dc595d702aa54a6fb0ffabf01f2780", + "0xa89b3f84bb7dcbe3741749776f5b78a269f6b1bebb8e95d3cc80b834fd2177c6be058d16cacfd0d5e1e35e85cde8b811", + "0xb4314538e003a1587b5592ff07355ea03239f17e75c49d51f32babe8e048b90b046a73357bcb9ce382d3e8fbe2f8e68b", + "0x86daf4bf201ae5537b5d4f4d734ed2934b9cf74de30513e3280402078f1787871b6973aa60f75858bdf696f19935a0e2", + "0xb1adf5d4f83f089dc4f5dae9dbd215322fa98c964e2eaa409bf8ca3fa5c627880a014ed209492c3894b3df1c117236c4", + "0xb508d52382c5bac5749bc8c89f70c650bb2ed3ef9dc99619468c387c1b6c9ff530a906dfa393f78f34c4f2f31478508a", + "0xa8349a5865cb1f191bebb845dfbc25c747681d769dbffd40d8cedf9c9a62fa2cbc14b64bb6121120dab4e24bef8e6b37", + "0xaf0500d4af99c83db8890a25f0be1de267a382ec5e9835e2f3503e1bac9412acf9ff83a7b9385708ef8187a38a37bc77", + "0xb76d57a1c1f85b8a8e1722a47057b4c572800957a6b48882d1fc21309c2e45f648a8db0fcff760d1dbc7732cf37c009b", + "0xb93c996cec0d3714667b5a5a5f7c05a7dc00bbc9f95ac8e310626b9e41ae4cc5707fac3e5bd86e1e1f2f6d9627b0da94", + "0x93216fdb864217b4c761090a0921cf8d42649ab7c4da1e009ec5450432564cb5a06cb6e8678579202d3985bd9e941cef", + "0x8b8be41105186a339987ae3a5f075fbc91f34b9984d222dfed0f0f85d2f684b56a56ab5dc812a411570491743d6c8b18", + "0x959b72782a6b2469e77fe4d492674cc51db148119b0671bd5d1765715f49fa8a87e907646671161586e84979ef16d631", + "0x86b7fc72fb7e7904ea71d5e66ba0d5d898ace7850985c8cc4a1c4902c5bf94351d23ce62eed45e24321fb02adfa49fc8", + "0xa2f244e7c9aa272cb0d067d81d25e5a3045b80b5a520b49fd5996ece267a7f1bea42e53147bbf153d9af215ea605fc9e", + "0x81aa2efa5520eebc894ce909ba5ce3250f2d96baa5f4f186a0637a1eea0080dd3a96c2f9fadf92262c1c5566ddb79bab", + "0xb607dd110cfe510d087bcff9a18480ba2912662256d0ab7b1d8120b22db4ad036b2266f46152754664c4e08d0fc583f6", + "0x8f588d5f4837e41312744caac5eee9ddc3ad7085871041694f0b5813edf83dc13af7970f7c9b6d234a886e07fa676a04", + "0x924921b903207783b31016cbec4e6c99e70f5244e775755c90d03a8b769738be3ba61577aca70f706a9c2b80040c9485", + "0xae0a42a222f1a71cd0d3c69ffb2f04c13e1940cce8efabe032629f650be3ceed6abb79651dbb81cb39a33286eb517639", + "0xa07d7d76460f31f5f0e32e40a5ea908d9d2aebf111ac4fadee67ef6540b916733c35a777dcdc05f6417726ca1f2d57dd", + "0x88d7f8a31f8c99794291847d28745e5d0b5d3b9684ca4170b686ffbb5bb521a3ef6746c3c8db22e4250a0cdff7939d96", + "0x849573071fd98c020dc9a8622a9eff221cb9f889bde259e7127a8886b73bef7ad430b87750915658918dcfb6b7b4d8d3", + "0xb12d59f732fa47fad175d6263734da8db89230fd340a46ad1cdee51e577041a5c80bf24cd195593e637daf1a66ef5a98", + "0xabbcfb8a4a6d5e269ee1ac5e277df84416c73ca55ec88317f73608201af25af0cb65b943c54684a5651df3a26e3daca2", + "0xab157f589bdbaf067a6a7ba7513df0492933855d39f3a081196cf2352e0ddc0162d476c433320366e3df601e0556278d", + "0xa86c0619b92e5ae4f7daa876a2abc5ba189156afc2fa05eef464dfa342ba37fc670d0dc308ad3822fcb461ab001bac30", + "0xa3f292946476cfe8d5e544a5325439a00e0165a5f9bf3bb6a53f477baeac7697cc0377745536681aa116f326ce911390", + "0x8aecbbfd442a6a0f01c1c09db5d9d50213eb6f1ff6fab674cde3da06a4edff3ed317e804f78300c22ef70c336123e05d", + "0x834ed4b58211fcd647d7bf7c0a3ba9085184c5c856b085e8a0fcd5215c661ef43d36f3f0f6329a9f1370501b4e73b6e4", + "0xa114ea5ad2b402a0de6105e5730907f2f1e458d28ae35144cf49836e0ad21325fe3e755cfb67984ae0a32e65402aad1e", + "0xa005f12bed97d71cee288b59afe9affb4d256888727343944a99913980df2c963fe02f218e6ea992f88db693a4498066", + "0xa010f286ab06b966e3b91ff8f1bdbe2fe9ab41a27bc392d5787aa02a46e5080e58c62c7d907818caae9f6a8b8123e381", + "0x857bd6df2ddef04dbc7c4f923e0b1696d3016c8bfed07fdfa28a3a3bd62d89b0f9df49aae81cbb6883d5e7b4fadae280", + "0xb3927030da445bc4756ac7230a5d87412a4f7510581fb422212ce2e8cf49689aca7ba71678743af06d4de4914c5aa4a0", + "0xb86403182c98fcce558d995f86752af316b3b2d53ba32075f71c7da2596747b7284c34a1a87de604fcc71e7e117a8add", + "0x98dd19b5527733041689b2a4568edaf6aa0fe1a3dd800c290cda157b171e053648a5772c5d3d4c80e5a795bc49adf12e", + "0x88a3c227bb7c9bff383f9ad3f7762245939a718ab85ae6e5e13180b12bf724d42054d3852b421c1cd1b3670baddecb63", + "0xb3cfd9ad66b52bbe57b5fff0fad723434d23761409b92c4893124a574acc1e6b1e14b4ec507661551cbbe05e16db362e", + "0x923e1bb482cf421dd77801f9780f49c3672b88508a389b94015fd907888dc647ee9ea8ec8d97131d235d066daf1f42b7", + "0x8d5e16240f04f92aa948181d421006bdbc7b215648fb6554193224d00cf337ebbb958f7548cf01b4d828acffb9fbc452", + "0x8b2b8f18ad0559746f6cda3acca294a1467fb1a3bc6b6371bc3a61a3bfe59418934fa8706f78b56005d85d9cb7f90454", + "0xa9316e2a94d6e31426d2ae7312878ba6baaac40f43e2b8a2fa3ab5a774c6918551554b2dbb23dc82f70ba3e0f60b5b0d", + "0x9593116d92cf06b8cd6905a2ce569ee6e69a506c897911f43ae80fc66c4914da209fc9347962034eebbc6e3e0fe59517", + "0x887d89d2b2d3c82b30e8f0acf15f0335532bd598b1861755498610cb2dd41ff5376b2a0bb757cb477add0ce8cfe7a9fc", + "0xb514cfe17875ecb790ad055271cc240ea4bda39b6cfa6a212908849c0875cb10c3a07826550b24c4b94ea68c6bb9e614", + "0xa563d5187966d1257d2ed71d53c945308f709bcc98e3b13a2a07a1933dc17bcb34b30796bd68c156d91811fbd49da2cb", + "0xa7195ccc53b58e65d1088868aeeb9ee208103e8197ad4c317235bb2d0ad3dc56cb7d9a7186416e0b23c226078095d44c", + "0xa838e7a368e75b73b5c50fbfedde3481d82c977c3d5a95892ac1b1a3ea6234b3344ad9d9544b5a532ccdef166e861011", + "0x9468ed6942e6b117d76d12d3a36138f5e5fb46e3b87cf6bb830c9b67d73e8176a1511780f55570f52d8cdb51dcf38e8c", + "0x8d2fc1899bc3483a77298de0e033085b195caf0e91c8be209fd4f27b60029cbe1f9a801fbd0458b4a686609762108560", + "0x8f4e44f8ca752a56aa96f3602e9234ad905ad9582111daf96a8c4d6f203bf3948f7ce467c555360ad58376ee8effd2ba", + "0x8fb88640b656e8f1c7c966c729eb2ba5ccf780c49873f8b873c6971840db7d986bdf1332ba80f8a0bb4b4ee7401468fa", + "0xb72aa3235868186913fb5f1d324e748cd3ce1a17d3d6e6ea7639a5076430fe0b08841c95feb19bb94181fe59c483a9eb", + "0xb8b102690ebb94fc4148742e7e3fd00f807b745b02cbe92cd92992c9143b6db7bb23a70da64a8b2233e4a6e572fc2054", + "0x8c9ae291f6cd744e2c6afe0719a7fc3e18d79307f781921fb848a0bf222e233879c1eca8236b4b1be217f9440859b6ce", + "0xa658ede47e14b3aad789e07f5374402f60e9cacb56b1b57a7c6044ca2418b82c98874e5c8c461898ebd69e38fecd5770", + "0x89c0cb423580e333923eb66bda690f5aca6ec6cba2f92850e54afd882ba608465a7dbb5aa077cd0ca65d9d00909348ab", + "0xaed8e28d98d5508bd3818804cf20d296fe050b023db2ed32306f19a7a3f51c7aaafed9d0847a3d2cd5ba5b4dabbc5401", + "0x96a0fcd6235f87568d24fb57269a94402c23d4aa5602572ad361f3f915a5f01be4e6945d576d51be0d37c24b8b0f3d72", + "0x935d0c69edd5dfa8ed07c49661b3e725b50588f814eb38ea31bcc1d36b262fae40d038a90feff42329930f8310348a50", + "0x900518288aa8ea824c7042f76710f2ea358c8bb7657f518a6e13de9123be891fa847c61569035df64605a459dad2ecc8", + "0x947d743a570e84831b4fb5e786024bd752630429d0673bf12028eb4642beb452e133214aff1cfa578a8856c5ebcb1758", + "0xa787266f34d48c13a01b44e02f34a0369c36f7ec0aae3ec92d27a5f4a15b3f7be9b30b8d9dd1217d4eeedff5fd71b2e5", + "0xa24b797214707ccc9e7a7153e94521900c01a1acd7359d4c74b343bfa11ea2cdf96f149802f4669312cd58d5ab159c93", + "0x97f5ee9c743b6845f15c7f0951221468b40e1edaef06328653a0882793f91e8146c26ac76dd613038c5fdcf5448e2948", + "0x80abd843693aed1949b4ea93e0188e281334163a1de150c080e56ca1f655c53eb4e5d65a67bc3fc546ed4445a3c71d00", + "0x908e499eb3d44836808dacff2f6815f883aeced9460913cf8f2fbbb8fe8f5428c6fc9875f60b9996445a032fd514c70f", + "0xae1828ef674730066dc83da8d4dd5fa76fc6eb6fa2f9d91e3a6d03a9e61d7c3a74619f4483fe14cddf31941e5f65420a", + "0xa9f4dbe658cd213d77642e4d11385a8f432245b098fccd23587d7b168dbeebe1cca4f37ee8d1725adb0d60af85f8c12f", + "0x93e20ee8a314b7772b2439be9d15d0bf30cd612719b64aa2b4c3db48e6df46cea0a22db08ca65a36299a48d547e826a7", + "0xa8746a3e24b08dffa57ae78e53825a9ddbbe12af6e675269d48bff4720babdc24f907fde5f1880a6b31c5d5a51fbb00e", + "0xb5e94dfab3c2f5d3aea74a098546aa6a465aa1e3f5989377d0759d1899babf543ad688bb84811d3e891c8713c45886c5", + "0xa3929bada828bd0a72cda8417b0d057ecb2ddd8454086de235540a756e8032f2f47f52001eb1d7b1355339a128f0a53b", + "0xb684231711a1612866af1f0b7a9a185a3f8a9dac8bde75c101f3a1022947ceddc472beb95db9d9d42d9f6ccef315edbc", + "0xaf7809309edbb8eb61ef9e4b62f02a474c04c7c1ffa89543d8c6bf2e4c3d3e5ecbd39ec2fc1a4943a3949b8a09d315a6", + "0xb6f6e224247d9528ef0da4ad9700bee6e040bbf63e4d4c4b5989d0b29a0c17f7b003c60f74332fefa3c8ddbd83cd95c1", + "0xadbcec190a6ac2ddd7c59c6933e5b4e8507ce5fd4e230effc0bd0892fc00e6ac1369a2115f3398dfc074987b3b005c77", + "0x8a735b1bd7f2246d3fa1b729aecf2b1df8e8c3f86220a3a265c23444bdf540d9d6fe9b18ed8e6211fad2e1f25d23dd57", + "0x96b1bf31f46766738c0c687af3893d098d4b798237524cb2c867ed3671775651d5852da6803d0ea7356a6546aa9b33f2", + "0x8036e4c2b4576c9dcf98b810b5739051de4b5dde1e3e734a8e84ab52bc043e2e246a7f6046b07a9a95d8523ec5f7b851", + "0x8a4f4c32ee2203618af3bb603bf10245be0f57f1cfec71037d327fa11c1283b833819cb83b6b522252c39de3ce599fa5", + "0xad06ed0742c9838e3abaaffdb0ac0a64bad85b058b5be150e4d97d0346ed64fd6e761018d51d4498599669e25a6e3148", + "0x8d91cb427db262b6f912c693db3d0939b5df16bf7d2ab6a7e1bc47f5384371747db89c161b78ff9587259fdb3a49ad91", + "0xae0a3f84b5acb54729bcd7ef0fbfdcf9ed52da595636777897268d66db3de3f16a9cf237c9f8f6028412d37f73f2dfad", + "0x8f774109272dc387de0ca26f434e26bc5584754e71413e35fa4d517ee0f6e845b83d4f503f777fe31c9ec05796b3b4bc", + "0xa8670e0db2c537ad387cf8d75c6e42724fae0f16eca8b34018a59a6d539d3c0581e1066053a2ec8a5280ffabad2ca51f", + "0xac4929ed4ecad8124f2a2a482ec72e0ef86d6a4c64ac330dab25d61d1a71e1ee1009d196586ce46293355146086cabba", + "0x845d222cb018207976cc2975a9aa3543e46c861486136d57952494eb18029a1ebb0d08b6d7c67c0f37ee82a5c754f26f", + "0xb99fa4a29090eac44299f0e4b5a1582eb89b26ed2d4988b36338b9f073851d024b4201cd39a2b176d324f12903c38bee", + "0x9138823bc45640b8f77a6464c171af2fe1700bdc2b7b88f4d66b1370b3eafe12f5fbb7b528a7e1d55d9a70ca2f9fc8e6", + "0x8ac387dc4cf52bc48a240f2965ab2531ae3b518d4d1f99c0f520a3d6eb3d5123a35ef96bed8fa71ee2f46793fa5b33b3", + "0x864adec6339d4c2ba2525621fceabd4c455902f6f690f31a26e55413e0722e5711c509dc47ce0bcc27bbdc7651768d2d", + "0xa0a52edb72268a15201a968dabc26a22909620bda824bd548fb8c26cc848f704166ed730d958f0173bd3b0a672f367bd", + "0x949e445b0459983abd399571a1a7150aab3dd79f4b52a1cd5d733e436c71c1d4b74287c6b0ce6cc90c6711ba4c541586", + "0x858966355dac11369e3b6552f2b381665181693d5a32e596984da3314021710b25a37d8c548b08700eea13d86cb22f21", + "0x974bcbb8d38c5e6518745cc03ad436e585b61f31d705e7e2e5085da9655d768ac4d800904f892c3dab65d6223e3f1fd6", + "0x8092b6506b01308bf6187fde5ebd4fa7448c9a640961ba231be22ac5fa2c7635ef01e8b357722c7695d09b723101ea2a", + "0xa5b8ef360bf28533ee17d8cd131fff661d265f609db49599085c0c7d83b0af409a1b5c28e3a5e5d7f8459a368aa121e8", + "0xb031b6d5e3ceab0f0c93314b3b675f55cf18cbc86f70444af266fe39cb22fd7dad75d8c84e07f1c1bfa2cb8283e1361a", + "0x93ad489e4f74658320c1cceed0137c023d3001a2c930ed87e6a21dbf02f2eb6ad1c1d8bcb3739c85dcfbecb040928707", + "0xb15e4ec2cdab0d34aec8d6c50338812eb6ecd588cf123a3e9d22a7ca23b5a98662af18289f09e6cdd85a39a2863c945c", + "0xb304f71a9717cf40c22073f942618b44bf27cd5e2ed4a386ad45d75b0fcb5a8dafd35158211eaf639495c6f1a651cedb", + "0xb82d78d3eaaa7c5101b7a5aae02bd4f002cd5802d18c3abcda0dd53b036661c6d3c8b79e0abe591eab90b6fdc5fef5e3", + "0xabbd1884243a35578b80914a5084449c237ee4e4660c279d1073a4d4217d1b55c6b7e9c087dfd08d94ac1416273d8d07", + "0x92f4b61c62502745e3e198ec29bca2e18696c69dcb914d1f3a73f4998d012b90caf99df46e9bb59942e43cce377fe8fd", + "0x906e79df98185820c8208844e1ba6bd86cb96965814b01310bd62f22cbec9b5d379b2ef16772d6fc45a421b60cfd68fe", + "0xa0eae2784ef596e2eb270dd40c48d6c508e4394c7d6d08d4cc1b56fde42b604d10ba752b3a80f2c4a737e080ef51b44f", + "0x94c084985e276dc249b09029e49a4ef8a369cd1737b51c1772fbb458d61e3fe120d0f517976eba8ffa5711ba93e46976", + "0x83619a0157eff3f480ab91d1d6225fead74c96a6fd685333f1e8e4d746f6273e226bad14232f1d1168a274e889f202f1", + "0xa724fe6a83d05dbbf9bb3f626e96db2c10d6d5c650c0a909415fbda9b5711c8b26e377201fb9ce82e94fa2ab0bf99351", + "0xa8a10c1b91a3a1fa2d7fd1f78a141191987270b13004600601d0f1f357042891010717319489f681aa8a1da79f7f00d5", + "0xa398a2e95b944940b1f8a8e5d697c50e7aa03994a8a640dfad4ea65cfb199a4d97861a3ec62d1c7b2b8d6e26488ca909", + "0xa2eedfe5452513b2a938fffd560798ef81379c5a5032d5b0da7b3bb812addbaad51f564c15d9acbbfc59bb7eddd0b798", + "0xab31c572f6f145a53e13b962f11320a1f4d411739c86c88989f8f21ab629639905b3eedb0628067942b0dc1814b678ca", + "0xad032736dd0e25652d3566f6763b48b34ea1507922ed162890cd050b1125ec03b6d41d34fccba36ec90336f7cdf788ed", + "0x83028a558a5847293147c483b74173eca28578186137df220df747fccd7d769528d7277336ea03c5d9cdd0bc5ae3d666", + "0xab5d182cd1181de8e14d3ef615580217c165e470b7a094a276b78a3003089123db75c6e1650bf57d23e587c587cd7472", + "0xa4793e089fbdb1597654f43b4f7e02d843d4ab99ee54099c3d9f0bd5c0c5657c90bb076379a055b00c01b12843415251", + "0x98bdc52ee062035356fb2b5c3b41673198ddc60b2d1e546cb44e3bb36094ef3c9cf2e12bbc890feb7d9b15925439d1ea", + "0xa4f90cca6f48024a0341bd231797b03693b34e23d3e5b712eb24aba37a27827319b2c16188f97c0636a0c115381dc659", + "0x8888e6c2e4a574d04ba5f4264e77abc24ccc195f1a7e3194169b8a2ceded493740c52db4f9833b3dbf4d67a3c5b252cb", + "0x83dc4e302b8b0a76dc0292366520b7d246d73c6aebe1bdd16a02f645c082197bcff24a4369deda60336172cefbcf09af", + "0xa4eb2741699febfeb793914da3054337cc05c6fa00d740e5f97cb749ae16802c6256c9d4f0f7297dcdbb8b9f22fc0afa", + "0x8b65557d5be273d1cb992a25cfce40d460c3f288d5cb0a54bdef25cbd17cdea5c32ec966e493addf5a74fd8e95b23e63", + "0x97c6577e76c73837bcb398b947cb4d3323d511141e0ddd0b456f59fbb1e8f920a5c20d7827a24309145efddee786140f", + "0xabcc0849ffe2a6a72157de907907b0a52deece04cf8317bee6fe1d999444b96e461eac95b6afde3d4fe530344086a625", + "0x9385c0115cb826a49df1917556efa47b5b5e4022b6a0d2082053d498ec9681da904ecf375368bb4e385833116ea61414", + "0x8b868c1841f0cdc175c90a81e610b0652c181db06731f5c8e72f8fafa0191620742e61a00db8215a991d60567b6a81ca", + "0xa8df15406f31b8fcf81f8ff98c01f3df73bf9ec84544ddec396bdf7fafa6fe084b3237bf7ef08ad43b26517de8c3cd26", + "0xa9943d21e35464ce54d4cc8b135731265a5d82f9ccf66133effa460ffdb443cdb694a25320506923eede88d972241bf2", + "0xa1378ee107dd7a3abcf269fd828887c288363e9b9ca2711377f2e96d2ed5e7c5ec8d3f1da995a3dcbedf1752d9c088fc", + "0x8a230856f9227b834c75bdebc1a57c7298a8351874bf39805c3e0255d6fd0e846f7ad49709b65ec1fd1a309331a83935", + "0x877bcf42549d42610e1780e721f5800972b51ba3b45c95c12b34cb35eeaf7eac8fa752edd7b342411820cf9093fea003", + "0x84c7a0b63842e50905624f1d2662506b16d1f3ea201877dfc76c79181c338b498eceb7cad24c2142c08919120e62f915", + "0x8e18b1bd04b1d65f6ed349b5d33a26fe349219043ead0e350b50ae7a65d6ff5f985dd9d318d3b807d29faa1a7de4fe42", + "0x8ea7b5a7503e1f0b3c3cd01f8e50207044b0a9c50ed1697794048bbe8efd6659e65134d172fb22f95439e1644f662e23", + "0xb1954a2818cad1dad6d343a7b23afa9aa8ad4463edc4eb51e26e087c2010927535020d045d97d44086d76acdb5818cbf", + "0xa5271ea85d0d21fa1ff59b027cf88847c0f999bbf578599083ff789a9b5228bc161e1c81deb97e74db1a82a0afd61c50", + "0xaa2fa4c05af3387e2c799315781d1910f69977ec1cfea57a25f1a37c63c4daaa3f0ecd400884a1673e17dd5300853bcf", + "0xb1cd2a74ca0b8e6090da29787aef9b037b03b96607983a308b790133bd21297b21ca4e2edec890874096dbf54e9d04c3", + "0x801931607ec66a81272feaa984f0b949ad12d75ecf324ba96627bd4dc5ddead8ebf088f78e836b6587c2b6c0b3366b6c", + "0x95d79504710bdf0ad9b9c3da79068c30665818c2f0cdbba02cc0a5e46e29d596032ac984441b429bd62e34535c8d55b0", + "0x9857d41e25e67876510ff8dadf0162019590f902da1897da0ef6fc8556e3c98961edb1eb3a3a5c000f6c494413ded15e", + "0x8740c9ffe6bd179c19a400137c3bd3a593b85bd4c264e26b4dfb9e2e17ac73e5b52dfacc1dcb4033cfc0cd04785f4363", + "0x977f98f29d948b4097a4abdf9345f4c1fb0aa94ba0c6bf6faa13b76f3a3efc8f688e1fe96099b71b3e1c05041118c8d1", + "0xa364422b1239126e3e8d7b84953ce2181f9856319b0a29fcab81e17ac27d35798088859c1cfc9fc12b2dbbf54d4f70b3", + "0xa0f6ba637f0db7a48e07439bb92ddb20d590ce9e2ed5bab08d73aa22d82c32a9a370fe934cbe9c08aeb84b11adcf2e0e", + "0xa2c548641bd5b677c7748327cca598a98a03a031945276be6d5c4357b6d04f8f40dd1c942ee6ec8499d56a1290ac134d", + "0x9863e9cc5fbcdbd105a41d9778d7c402686bfd2d81d9ed107b4fda15e728871c38647529693306855bee33a00d257a7e", + "0xa54173bf47b976290c88fd41f99300135de222f1f76293757a438450880e6f13dbde3d5fe7afc687bdfbcfc4fbc1fc47", + "0xb8db413917c60907b73a997b5ab42939abd05552c56a13525e3253eb72b83f0d5cc52b695968a10005c2e2fe13290e61", + "0xa1f8388ef21697c94ba90b1a1c157f0dc138e502379e6fc5dc47890d284563e5db7716266e1b91927e5adf3cde4c0a72", + "0x9949013a59d890eb358eab12e623b2b5edb1acbee238dfad8b7253102abc6173922e188d5b89ec405aa377be8be5f16d", + "0xa00fdb7710db992041f6ddb3c00099e1ce311dea43c252c58f560c0d499983a89de67803a8e57baa01ee9d0ee6fa1e44", + "0xa8b1bcbed1951c9cdb974b61078412881b830b48cd6b384db0c00fa68bcc3f4312f8e56c892ea99d3511857ef79d3db9", + "0x8f3ee78404edc08af23b1a28c2012cee0bdf3599a6cb4ea689fc47df4a765ef519191819a72562b91a0fbcdb896a937e", + "0x8155bbb7fa8d386848b0a87caae4da3dec1f3dade95c750a64a8e3555166ccc8799f638bd80ed116c74e3a995541587a", + "0xabfe30adbc0a6f1fd95c630ed5dac891b85384fa9331e86b83217f29dff0bd7cad19d328485715a7e3df9a19069d4d2f", + "0x89d0783e496ee8dbb695764b87fb04cee14d4e96c4ba613a19736971c577d312079048142c12ce5b32b21e4d491d281b", + "0x856b8dbc9c5d8f56b6bb7d909f339ca6da9a8787bba91f09130a025ab6d29b64dbf728ba6ed26e160a23c1cdb9bc037b", + "0x8a30dd2ea24491141047a7dfe1a4af217661c693edf70b534d52ca547625c7397a0d721e568d5b8398595856e80e9730", + "0xae7e1412feb68c5721922ed9279fb05549b7ef6812a4fd33dbbbd7effab756ab74634f195d0c072143c9f1fd0e1ee483", + "0xb7ce970e06fa9832b82eef572f2902c263fda29fdce9676f575860aae20863046243558ede2c92343616be5184944844", + "0x85ed0531f0e5c1a5d0bfe819d1aa29d6d5ff7f64ad8a0555560f84b72dee78e66931a594c72e1c01b36a877d48e017ca", + "0xb8595be631dc5b7ea55b7eb8f2982c74544b1e5befc4984803b1c69727eac0079558182f109e755df3fd64bee00fcaa5", + "0x99e15a66e5b32468ef8813e106271df4f8ba43a57629162832835b8b89402eb32169f3d2c8de1eb40201ce10e346a025", + "0x844c6f5070a8c73fdfb3ed78d1eddca1be31192797ad53d47f98b10b74cc47a325d2bc07f6ee46f05e26cf46a6433efb", + "0x974059da7f13da3694ad33f95829eb1e95f3f3bfc35ef5ef0247547d3d8ee919926c3bd473ab8b877ff4faa07fcc8580", + "0xb6f025aecc5698f6243cc531782b760f946efebe0c79b9a09fe99de1da9986d94fa0057003d0f3631c39783e6d84c7d5", + "0xb0c5358bc9c6dfe181c5fdf853b16149536fbb70f82c3b00db8d854aefe4db26f87332c6117f017386af8b40288d08f9", + "0xa3106be5e52b63119040b167ff9874e2670bd059b924b9817c78199317deb5905ae7bff24a8ff170de54a02c34ff40a4", + "0xad846eb8953a41c37bcd80ad543955942a47953cbc8fb4d766eac5307892d34e17e5549dc14467724205255bc14e9b39", + "0xb16607e7f0f9d3636e659e907af4a086ad4731488f5703f0917c4ce71a696072a14a067db71a3d103530920e1ec50c16", + "0x8ed820e27116e60c412c608582e9bb262eaaf197197c9b7df6d62b21a28b26d49ea6c8bb77dfde821869d9b58025f939", + "0x97bc25201d98cde389dd5c0c223a6f844393b08f75d3b63326343073e467ac23aacef630ddc68545ea874299ba4a3b4f", + "0xb73c9695ad2eefd6cc989a251c433fab7d431f5e19f11d415a901762717d1004bb61e0cc4497af5a8abf2d567e59fef4", + "0xadaabe331eea932533a7cc0cf642e2a5e9d60bbc92dd2924d9b429571cbf0d62d32c207b346607a40643c6909b8727e2", + "0xa7b1bbfe2a5e9e8950c7cb4daab44a40c3ffab01dc012ed7fe445f4af47fa56d774a618fafe332ab99cac4dfb5cf4794", + "0xb4a3c454dcd5af850212e8b9ba5fe5c0d958d6b1cabbf6c6cfe3ccbc4d4c943309c18b047256867daf359006a23f3667", + "0xa5c0b32f6cef993834c1381ec57ad1b6f26ae7a8190dd26af0116e73dadc53bb0eeb1911419d609b79ce98b51fdc33bc", + "0xac2f52de3ecf4c437c06c91f35f7ac7d171121d0b16d294a317897918679f3b9db1cef3dd0f43adb6b89fe3030728415", + "0x94722ae6d328b1f8feaf6f0f78804e9b0219de85d6f14e8626c2845681841b2261d3e6a2c5b124086b7931bf89e26b46", + "0xa841a0602385d17afabca3a1bb6039167d75e5ec870fea60cfcaec4863039b4d745f1a008b40ec07bca4e42cb73f0d21", + "0x8c355f0a1886ffced584b4a002607e58ff3f130e9de827e36d38e57cb618c0cb0b2d2dea2966c461cb3a3887ede9aef1", + "0xa6a9817b0fc2fd1786f5ba1a7b3d8595310987fb8d62f50a752c6bb0b2a95b67d03a4adfd13e10aa6190a280b7ee9a67", + "0xa1d2e552581ecbafeaef08e389eaa0b600a139d446e7d0648ac5db8bbbf3c438d59497e3a2874fc692b4924b87ff2f83", + "0xa1b271c55389f25639fe043e831e2c33a8ba045e07683d1468c6edd81fedb91684e4869becfb164330451cfe699c31a8", + "0x8c263426e7f7e52f299d57d047a09b5eeb893644b86f4d149535a5046afd655a36d9e3fdb35f3201c2ccac2323a9582e", + "0xb41c242a7f7880c714241a97d56cce658ee6bcb795aec057a7b7c358d65f809eb901e0d51256826727dc0dc1d1887045", + "0x93001b9445813c82f692f94c0dc1e55298f609936b743cf7aae5ebfa86204f38833d3a73f7b67314be67c06a1de5682d", + "0x82087536dc5e78422ad631af6c64c8d44f981c195ddea07d5af9bb0e014cdc949c6fa6e42fce823e0087fdb329d50a34", + "0x8e071861ceba2737792741c031f57e0294c4892684506b7c4a0fc8b2f9a0a6b0a5635de3d1e8716c34df0194d789ae86", + "0xb471c997e1e11774bd053f15609d58838a74073a6c089a7a32c37dd3f933badf98c7e5833263f3e77bc0d156a62dd750", + "0x8d2d8686fb065b61714414bb6878fff3f9e1e303c8e02350fd79e2a7f0555ded05557628152c00166ce71c62c4d2feaa", + "0xae4c75274d21c02380730e91de2056c0262ffcecf0cbdb519f0bdb0b5a10ae2d4996b3dc4b3e16dbaea7f0c63d497fef", + "0x97140d819e8ca6330e589c6debdee77041c5a9cedb9b8cbd9c541a49207eeb7f6e6b1c7e736ec8ba6b3ab10f7fcd443a", + "0xaf6659f31f820291a160be452e64d1293aa68b5074b4c066dac169b8d01d0179139504df867dc56e2a6120354fc1f5be", + "0xa5e5d8088a368024617bfde6b731bf9eee35fc362bed3f5dfdd399e23a2495f97f17728fec99ca945b3282d1858aa338", + "0xa59cfc79d15dbdde51ab8e5129c97d3baba5a0a09272e6d2f3862370fdbaf90994e522e8bd99d6b14b3bb2e9e5545c6f", + "0xa30499b068083b28d6c7ddcc22f6b39b5ec84c8ee31c5630822c50ea736bb9dca41c265cffc6239f1c9ef2fd21476286", + "0x88ffe103eca84bbe7d1e39a1aa599a5c7c9d5533204d5c4e085402a51441bb8efb8971efe936efbbfa05e5cb0d4b8017", + "0xb202356fbf95a4d699154639e8cb03d02112c3e0128aab54d604645d8510a9ba98936028349b661672c3a4b36b9cb45d", + "0x8b89bb6574bf3524473cff1ff743abcf1406bd11fb0a72070ccd7d8fce9493b0069fb0c6655252a5164aee9e446ea772", + "0x93247b1038fa7e26667ee6446561d4882dc808d1015daafb705935ddc3598bb1433182c756465960480f7b2de391649e", + "0xb027f94d3358cbb8b6c8c227300293a0dee57bf2fee190a456ad82ecfb6c32f8090afa783e2ab16f8139805e1fb69534", + "0xa18bb1849b2f06c1d2214371031d41c76ffa803ee3aa60920d29dbf3db5fbfac2b7383d5d0080ba29ce25c7baa7c306b", + "0x827bf9fd647e238d5ac961c661e5bbf694b4c80b3af8079f94a2484cb8fba2c8cf60e472ebcd0b0024d98ae80ad2ff5a", + "0x838e891218c626a7f39b8fd546b013587408e8e366ecc636b54f97fa76f0a758bc1effa1d0f9b6b3bc1a7fcc505970a0", + "0x836523b5e8902d6e430c6a12cff01e417d2bd7b402e03904034e3b39755dee540d382778c1abe851d840d318ebedce7f", + "0x850a77dda9ac6c217e2ef00bf386a1adec18b7f462f52801c4f541215690502a77ef7519b690e22fdf54dc2109e0ca38", + "0xa8265c6ae7b29fc2bda6a2f99ced0c1945dd514b1c6ca19da84b5269514f48a4f7b2ccbab65c9107cfd5b30b26e5462f", + "0xab3d02ee1f1267e8d9d8f27cc388e218f3af728f1de811242b10e01de83471a1c8f623e282da5a284d77884d9b8cde0e", + "0x831edaf4397e22871ea5ddee1e7036bab9cc72f8d955c7d8a97f5e783f40532edbbb444d0520fefcffeab75677864644", + "0x80484487977e4877738744d67b9a35b6c96be579a9faa4a263e692295bb6e01f6e5a059181f3dd0278e2c3c24d10a451", + "0xaae65a18f28c8812617c11ecf30ad525421f31fb389b8b52d7892415e805a133f46d1feca89923f8f5b8234bd233486a", + "0xb3a36fd78979e94288b4cefed82f043a7e24a4a8025479cc7eb39591e34603048a41ee606ee03c0b5781ebe26a424399", + "0xb748b3fc0d1e12e876d626a1ba8ad6ad0c1f41ea89c3948e9f7d2666e90173eb9438027fadcd741d3ae0696bd13840f1", + "0xacdd252d7c216c470683a140a808e011c4d5f1b4e91aeb947f099c717b6a3bad6651142cde988330827eb7d19d5fb25c", + "0xb9a25556a6ca35db1ed59a1ec6f23343eab207a3146e4fc3324136e411c8dba77efd567938c63a39c2f1c676b07d8cdb", + "0xa8db6aef8f5680d2bdb415d7bcaae11de1458678dcb8c90c441d5986c44f83a9e5855662d0c1aace999172d8628d8fe1", + "0xaf58147108e9909c3a9710cc186eab598682dca4bfd22481e040b8c000593ecb22c4ede4253ac9504e964dfa95a9b150", + "0x8dd8bb70f1c9aec0fcc9478f24dfc9c3c36c0bf5ff7a67c017fa4dab2ec633fbd7bc9d8aa41ea63e2696971ed7e375f5", + "0xaa98d600b22aff993a4d7a3ccabd314e1825b200cb598f6b797d7e4d6a76d89e34a4d156c06bddfc62f2ef9b4c809d1d", + "0x8a8fc960d6c51294b8205d1dabe430bef59bda69824fa5c3c3105bef22ac77c36d2d0f38ffc95ce63731de5544ccbeff", + "0xb6d1020efe01dc8032bd1b35e622325d7b9af9dcd5c9c87c48d7d6ebc58644454294c59b7f4b209204b5b1f899f473bf", + "0x8a750dc9fe4891f2dfe5759fb985939810e4cdc0b4e243ff324b6143f87676d8cb4bcb9dfb01b550801cedcaaa5349e2", + "0x98c13142d3a9c5f8d452245c40c6dae4327dd958e0fda85255ea0f87e0bcbaa42a3a0bd50407ed2b23f9f6317a8a4bc5", + "0x99f2b83d9ec4fc46085a6d2a70fd0345df10f4a724c1ba4dee082a1fde9e642e3091992ebf5f90a731abcb6ec11f6d9b", + "0xb218546ab2db565b2489ea4205b79daa19ef2acbf772ccaaa5e40150e67ea466090d07198444b48e7109939aa2319148", + "0x84f9d1d868e4b55e535f1016558f1789df0daa0ead2d13153e02f715fe8049b1ce79f5bc1b0bbbb0b7e4dd3c04783f3f", + "0x80d870d212fbddfdda943e90d35a5a8aa0509a7a1e7f8909f2fcb09c51c3026be47cc7a22620a3063406872105b4f81a", + "0xb5b15138ff6551fac535d4bbce2ea6adc516b6b7734b4601c66ec029da2615e3119dc9ad6a937344acfd7b50e4a1a2ae", + "0x95d2f97652086e7ceb54e1d32692b1c867ffba23c4325740c7f10d369283d1b389e8afa0df967831ade55696931e7934", + "0x8a5b580403e1a99cd208f707e8ce0d3f658c8280417683f69008d09cc74d835a85f7380f391b36ead9ac66d9eedd1cbe", + "0xa8b0c90bff34c86720637b5a2081f0f144cfe2205c1176cacd87d348609bc67af68aed72414dc9aa6f44a82c92c2a890", + "0x865abbdd96c496892c165a8de0f9e73348bf24fce361d7a9048710178a3625881afb0006e9f5ee39124866b87904c904", + "0xace67bb994adef4b6f841cdf349195608030044562780a7e9b00b58a4ff117268a03ff01e5a3a9d9d7eff1dd01f5f4bf", + "0xb9371d59185b3d2d320d3fefeadb06ba2aa7d164352fb8dc37571509509fa214d736d244ac625a09a033a10d51611e2e", + "0xa8ef992771422dcf2d6d84386fde9fe5dba88bfded3dfcd14074ca04331b4fd53a7f316615cdfaf10ed932cbb424a153", + "0x868cbc75f8f789ea45eded2768a1dac0763347e0d8e8028d316a21005f17be179d26d5965903e51b037f2f57fe41765d", + "0xb607111bcdfd05fa144aa0281b13ee736079ebbbf384d938a60e5e3579639ed8ef8eb9ca184868cdb220a8e130d4a952", + "0xaca55702af5cae4cae65576769effd98858307a71b011841c563b97c2aa5aeb5c4f8645d254f631ed1582df3dbbf17da", + "0xb9b5cbace76246e80c20dfcc6f1e2c757a22ab53f7fd9ff8a1d309538b55174e55e557a13bf68f095ff6a4fa637ef21a", + "0x8571b0a96871f254e2397c9be495c76379faf347801cb946b94e63212d6a0da61c80e5d7bebbabcd6eaa7f1029172fe5", + "0x902540326281e6dc9c20d9c4deaaf6fbbbcc3d1869bd0cf7f081c0525bea33df5cfa24ead61430fda47fb964fcc7994b", + "0x841af09279d3536a666fa072278950fabf27c59fc15f79bd52acb078675f8087f657929c97b4bc761cbade0ecb955541", + "0xa1f958b147ddf80ab2c0746ba11685c4bae37eb25bfa0442e7e1078a00d5311d25499da30f6d168cb9302ea1f2e35091", + "0x863d939381db37d5a5866964be3392a70be460f0353af799d6b3ed6307176972686bd378f8ad457435a4094d27e8dfb7", + "0x835cd4d7f36eff553d17483eb6c041b14280beb82c7c69bca115929658455a1931212976c619bafb8179aed9940a8cc6", + "0x8d0770e3cb8225e39c454a1fc76954118491b59d97193c72c174ecc7613051e5aed48a534016a8cf0795c524f771a010", + "0x91aa4edb82f6f40db2b7bd4789cc08786f6996ebed3cb6f06248e4884bc949793f04a4c5ea6eefe77984b1cc2a45d699", + "0x8fb494ca2449f659ff4838833507a55500a016be9293e76598bbae0a7cb5687e4693757c2b6d76e62bd6c7f19ed080bb", + "0xb59b104449a880a282c1dd6a3d8debb1d8814ef35aab5673c1e500ee4cb0e840fb23e05fa5a0af92509c26b97f098f90", + "0xaca908e3bad65e854ae6be6c5db441a06bcd47f5abafdfa8f5a83c8cd3c6e08c33cab139c45887887a478338e19ceb9f", + "0x806f5d802040313a31964fc3eb0ee18ac91b348685bed93c13440984ee46f3d2da7194af18c63dea4196549129660a4e", + "0xae4b2dca75c28d8f23b3ab760b19d839f39ff5a3112e33cb44cff22492604a63c382b88ec67be4b0266924dd438c3183", + "0x99d1c29c6bd8bf384e79cd46e30b8f79f9cbc7d3bf980e9d6ffba048f0fc487cac45c364a8a44bb6027ad90721475482", + "0xa16e861c1af76d35528c25bf804bfc41c4e1e91b2927d07d8e96bffe3a781b4934e9d131ecf173be9399800b8269efac", + "0xa253303234fb74f5829060cdcef1d98652441ab6db7344b1e470d195a95722675988048d840201c3b98e794b1e8b037c", + "0x905ac8a0ea9ce0eb373fb0f83dd4cbe20afb45b9d21ae307846fd4757d4d891b26a6711924e081e2b8151e14a496da18", + "0xb485315791e775b9856cc5a820b10f1fa5028d5b92c2f0e003ba55134e1eddb3eb25f985f2611a2257acf3e7cfdfab5e", + "0xb6189c0458b9a043ebc500abc4d88083a3487b7ac47ed5e13ab2a41e0a1bee50d54a406063f92bc96959f19e822a89a7", + "0xa30e15f995fd099a223fc6dc30dad4b8d40bee00caa2bc3223ba6d53cd717c4968a3e90c4618c711ed37cc4cd4c56cf3", + "0xa1b1ed07fcc350bb12a09cd343768d208fc51a6b3486f0ece8f5a52f8a5810b4bc7ab75582ec0bc2770aed52f68eace5", + "0x88aa739fbae4bece147ba51a863e45d5f7203dbc3138975dc5aef1c32656feb35f014d626e0d5b3d8b1a2bda6f547509", + "0xab570f3c8eabfca325b3a2ea775ef6b0c6e6138c39d53c2310329e8fb162869fde22b0e55688de9eb63d65c37598fca3", + "0x89d274762c02158e27cb37052e296a78f2b643eb7f9ae409f8dac5c587d8b4d82be4ef7c79344a08ebec16ac4a895714", + "0x99c411d2ad531e64f06e604d44c71c7c384424498ecd0a567d31ec380727fb605af76643d0d5513dd0a8d018076dd087", + "0x80d0777fa9f79f4a0f0f937d6de277eec22b3507e2e398f44b16e11e40edf5feff55b3b07a69e95e7e3a1621add5ed58", + "0xb2430a460783f44feb6e4e342106571ef81ad36e3ddd908ec719febeb7acaf4b833de34998f83a1dab8f0137a3744c11", + "0xb8f38ccfc7279e1e30ad7cefc3ea146b0e2dff62430c50a5c72649a4f38f2bac2996124b03af2079d942b47b078cc4f8", + "0xa178a450a62f30ec2832ac13bbc48789549c64fc9d607b766f6d7998558a0e2fad007ae0148fc5747189b713f654e6ba", + "0x98c5ede296f3016f6597f7ccc5f82c88fd38ed6dc3d6da3e4a916bfd7c4c95928722a1d02534fe89387c201d70aa6fd2", + "0xa8cc5e98573705d396576e022b2ba2c3e7c7ece45cd8605cb534b511763682582299e91b4bb4100c967019d9f15bbfaf", + "0x848480ea7b7d9536e469da721236d932870b7bbee31ccf7ae31b4d98d91413f59b94a1e0d1786ee7342295aa3734969c", + "0xb88ea38f9ee432f49e09e4e013b19dff5a50b65453e17caf612155fff6622198f3cba43b2ea493a87e160935aaaf20a9", + "0x949376934a61e0ef8894339c8913b5f3b228fa0ae5c532ad99b8d783b9e4451e4588541f223d87273c0e96c0020d5372", + "0x96f90bb65ca6b476527d32c415814b9e09061648d34993f72f28fae7dc9c197e04ef979f804076d107bb218dfd9cb299", + "0xa4402da95d9942c8f26617e02a7cef0ebc4b757fac72f222a7958e554c82cc216444de93f659e4a1d643b3e55a95d526", + "0x81179cbc26a33f6d339b05ea3e1d6b9e1190bd44e94161ae36357b9cdf1e37d745d45c61735feed64371fe5384102366", + "0xad4dc22bdbd60e147fdac57d98166de37c727f090059cfc33e5ee6cf85e23c2643996b75cf1b37c63f3dc9d3c57ffa18", + "0x8a9b1b93dc56e078ce3bb61c2b0088fd6c3e303ba6b943231cc79d4a8e8572f4109bbde5f5aa7333aae3287909cb0fe2", + "0x8876ef583bc1513322457a4807d03381ba1f4d13e179260eaa3bddfede8df677b02b176c6c9f74c8e6eab0e5edee6de6", + "0xb6c67e228bf190fbaeb2b7ec34d4717ce710829c3e4964f56ebb7e64dc85058c30be08030fa87cc94f1734c5206aef5f", + "0xa00cb53b804ee9e85ce12c0103f12450d977bc54a41195819973c8a06dcb3f46f2bf83c3102db62c92c57ab4dd1e9218", + "0xa7675a64772eefddf8e94636fb7d1d28f277074327c02eea8fae88989de0c5f2dc1efed010f4992d57b5f59a0ab40d69", + "0x8d42bb915e0bf6a62bcdf2d9330eca9b64f9ec36c21ae14bf1d9b0805e5e0228b8a5872be61be8133ad06f11cb77c363", + "0xa5b134de0d76df71af3001f70e65c6d78bed571bc06bfddf40d0baad7ea2767608b1777b7ef4c836a8445949877eeb34", + "0xaeadbc771eaa5de3a353229d33ed8c66e85efbd498e5be467709cb7ff70d3f1a7640002568b0940e3abd7b2da81d2821", + "0x8c28da8e57a388007bd2620106f6226b011ee716a795c5d9f041c810edf9cf7345b2e2e7d06d8a6b6afa1ee01a5badc1", + "0x8ed070626a4d39ffd952ddb177bc68fd35b325312e7c11694c99b691f92a8ea7734aeb96cf9cc73e05b3c1b1dcad6978", + "0xada83e18e4842f3d8871881d5dbc81aed88a1328298bfdc9e28275094bd88d71b02e7b8501c380fa8d93096cbc62f4fb", + "0x8befc3bec82dcf000a94603b4a35c1950ba5d00d4bed12661e4237afa75062aa5dcef8eac0b9803136c76d2dd424a689", + "0x97c6f36c91ca5ca9230bfcbf109d813728b965a29b62e5f54c8e602d14a52ac38fa1270de8bfe1ab365426f3fc3654c7", + "0xb01d192af3d8dbce2fe2fece231449e70eb9ac194ec98e758da11ca53294a0fa8c29b1d23a5d9064b938b259ea3b4fb5", + "0x819a2c20646178f2f02865340db1c3c6ebc18f4e6559dd93aa604388796a34bd9fed28ad3ccc8afc57a5b60bb5c4e4ec", + "0xa9ffc877470afc169fecf9ec2dc33253b677371938b0c4ffa10f77bb80089afa2b4488437be90bb1bcf7586a6f4286e3", + "0xb533051c7ce7107176bcb34ad49fdb41fac32d145854d2fe0a561c200dcf242da484156177e2c8f411c3fdf1559ecf83", + "0x8fe2caff2e4241d353110a3618832f1443f7afe171fd14607009a4a0aa18509a4f1367b67913e1235ac19de15e732eb1", + "0x84705c6370619403b9f498059f9869fdf5f188d9d9231a0cb67b1da2e8c906ead51b934286497293698bba269c48aa59", + "0x899dddf312a37e3b10bdaaacc1789d71d710994b6ee2928ac982ad3fd8a4f6167672bc8bf3419412711c591afe801c28", + "0xb2f7916d946b903ded57b9d57025386143410a41a139b183b70aeca09cf43f5089ead1450fce4e6eb4fba2c8f5c5bbe5", + "0x8d5f742fe27a41623b5820914c5ca59f82246010fa974304204839880e5d0db8bc45ebab2ad19287f0de4ac6af25c09e", + "0xb93d4a1f6f73ac34da5ffbd2a4199cf1d51888bc930dc3e481b78806f454fcb700b4021af7525b108d49ebbbaa936309", + "0x8606f8d9121512e0217a70249937e5c7f35fbfe019f02248b035fa3a87d607bc23ae66d0443e26a4324f1f8e57fd6a25", + "0xb21312cdec9c2c30dd7e06e9d3151f3c1aceeb0c2f47cf9800cce41521b9d835cb501f98b410dc1d49a310fdda9bc250", + "0xa56420b64286bdddda1e212bba268e9d1ba6bdb7132484bf7f0b9e38099b94a540884079b07c501c519b0813c184f6b4", + "0x80b2cf0e010118cb2260f9c793cef136f8fa7b5e2711703735524e71d43bce2d296c093be41f2f59118cac71f1c5a2ff", + "0xadcb12d65163804d2f66b53f313f97152841c3625dbbda765e889b9937195c6fcd55d45cc48ebffabb56a5e5fe041611", + "0x8b8a42e50dc6b08ab2f69fc0f6d45e1ea3f11ba0c1008ee48448d79d1897356599e84f7f9d8a100329ed384d6787cfc4", + "0xaaa9c74afa2dec7eccfbd8bb0fc6f24ed04e74c9e2566c0755a00afdfdf3c4c7c59e2a037ec89c2f20af3fae1dd83b46", + "0xaa9f6e8fd59187171c6083ae433627d702eb78084f59010ff07aff8f821f7022ef5fbbe23d76814d811b720a8bfa6cc3", + "0xa56a3ded501659ad006d679af3287080b7ee8449e579406c2cae9706ef8bf19c1fc2eb2a6f9eaf2d3c7582cded73e477", + "0x81971e077c1da25845840222b4191e65f6d242b264af4e86800f80072d97d2a27a6adc87c3a1cb1b0dd63d233fbafa81", + "0xa6fa5453c4aaad2947969ee856616bf6448224f7c5bf578f440bcfc85a55beb40bef79df8096c4db59d1bd8ef33293ea", + "0x87c545adbfaaf71e0ab4bac9ae4e1419718f52b0060e8bb16b33db6d71b7248ae259d8dd4795b36a4bbb17f8fae9fd86", + "0xb4c7a9bc0910e905713291d549cec5309e2d6c9b5ea96954489b1dff2e490a6c8b1fa1e392232575f0a424ba94202f61", + "0x802350b761bcaba21b7afe82c8c6d36ee892b4524ab67e2161a91bbfa1d8e92e7e771efb1f22c14126218dd2cb583957", + "0xb4e7ddb9143d4d78ea8ea54f1c908879877d3c96ee8b5e1cb738949dcfceb3012a464506d8ae97aa99ea1de2abf34e3d", + "0xa49a214065c512ad5b7cc45154657a206ef3979aa753b352f8b334411f096d28fd42bca17e57d4baaafb014ac798fc10", + "0x8a80c70a06792678a97fe307520c0bf8ed3669f2617308752a2ab3c76fdf3726b014335a9b4c9cbcfc1df3b9e983c56f", + "0xa34721d9e2a0e4d08995a9d986dc9c266c766296d8d85e7b954651ad2ca07e55abb1b215898ee300da9b67114b036e0d", + "0x8cfce4564a526d7dca31e013e0531a9510b63845bbbd868d5783875ed45f92c1c369ce4a01d9d541f55f83c2c0a94f03", + "0xab3f5f03a5afc727778eb3edf70e4249061810eba06dc3b96b718e194c89429c5bfbec4b06f8bce8a2118a2fdce67b59", + "0xaa80c2529fc19d428342c894d4a30cb876169b1a2df81a723ab313a071cba28321de3511a4de7846207e916b395abcc9", + "0x82b7828249bf535ef24547d6618164b3f72691c17ca1268a5ee9052dba0db2fdd9987c8e083307a54399eab11b0f76b1", + "0x8fbcb56b687adad8655a6cf43364a18a434bf635e60512fad2c435cf046f914228fb314f7d8d24d7e5e774fb5ffb1735", + "0xa3010a61a2642f5ebbce7b4bc5d6ecb3df98722a49eb1655fe43c1d4b08f11dfad4bcec3e3f162d4cc7af6a504f4d47c", + "0xb3dcc0fdf531478e7c9ef53190aa5607fd053a7d2af6c24a15d74c279dbb47e3c803a1c6517d7e45d6534bb59e3527f5", + "0x8648f6316c898baaca534dff577c38e046b8dfa8f5a14ee7c7bc95d93ae42aa7794ba0f95688a13b554eeb58aeedf9ba", + "0x89fca6fc50407695e9315483b24f8b4e75936edf1475bcf609eed1c4370819abac0e6a7c3c44f669560367d805d9ba63", + "0xa367a17db374f34cd50f66fb31ba5b7de9dbe040f23db2dcc1d6811c0e863606f6c51850af203956f3399000f284d05f", + "0x91030f9ca0fff3e2dbd5947dcf2eba95eb3dbca92ee2df0ed83a1f73dbf274611af7daf1bb0c5c2ee46893ab87013771", + "0x84d56181f304ce94015ea575afeef1f84ea0c5dbb5d29fb41f25c7f26077b1a495aff74bd713b83bce48c62d7c36e42d", + "0x8fe2f84f178739c3e2a2f7dcac5351c52cbed5fa30255c29b9ae603ffd0c1a181da7fb5da40a4a39eec6ce971c328fcf", + "0xa6f9b77b2fdf0b9ee98cb6ff61073260b134eb7a428e14154b3aa34f57628e8980c03664c20f65becfe50d2bdd2751d4", + "0x8c6760865445b9327c34d2a1247583694fbeb876055a6a0a9e5cb460e35d0b2c419e7b14768f1cc388a6468c94fd0a0f", + "0xaf0350672488a96fe0089d633311ac308978a2b891b6dbb40a73882f1bda7381a1a24a03e115ead2937bf9dcd80572ad", + "0xa8e528ec2ee78389dd31d8280e07c3fdd84d49556a0969d9d5c134d9a55cd79e1d65463367b9512389f125ed956bc36a", + "0x942c66589b24f93e81fe3a3be3db0cd4d15a93fb75260b1f7419f58d66afaa57c8d2d8e6571536790e2b415eec348fd9", + "0x83fe4184b4b277d8bf65fb747b3c944170824b5832751057e43465526560f60da6e5bbee2f183cb20b896a20197168c7", + "0x88a71aada494e22c48db673d9e203eef7a4e551d25063b126017066c7c241ee82bedaa35741de4bd78a3dd8e21a8af44", + "0x8c642a3186ca264aac16ee5e27bd8da7e40e9c67ae159b5d32daa87b7de394bf2d7e80e7efb1a5506c53bfd6edd8c2c3", + "0x81855d6de9a59cef51bef12c72f07f1e0e8fe324fcc7ec3f850a532e96dcd434c247130610aaee413956f56b31cbb0dc", + "0xa01e61390dcd56a58ad2fcdb3275704ddfbedef3ba8b7c5fce4814a6cdd03d19d985dba6fd3383d4db089444ea9b9b4d", + "0x96494e89cbf3f9b69488a875434302000c2c49b5d07e5ff048a5b4a8147c98291ae222529b61bb66f1903b2e988e5425", + "0xb9689b3e8dddc6ec9d5c42ba9877f02c1779b2c912bba5183778dc2f022b49aed21c61c8ec7e3c02d74fe3f020a15986", + "0xa2a85e213b80b0511395da318cbb9935c87b82c305f717a264155a28a2ea204e9e726bae04ce6f012e331bd6730cbb9d", + "0x91b70f44c7d8c5980ce77e9033a34b05781cbe773854d3f49d2905cc711a3d87c20d5d496801ad6fd82438874ce732b8", + "0x884596417ff741bb4d11925d73852ffeea7161c7f232be3bdce9e6bbe7884c3a784f8f1807356ae49d336b7b53a2b495", + "0xae2aed8ab6951d8d768789f5bc5d638838d290d33ccc152edfb123e88ba04c6272b44294b0c460880451ad7b3868cc6a", + "0x89d8ebfb9beebc77189d27de31c55f823da87798a50bca21622cbf871e5d9f1d3182cf32ee9b90f157e6ce298e9efccf", + "0xafd00a4db4c2ed93cf047378c9402914b6b3255779f3bb47ded4ab206acb7eaebba0fd7762928e681b1aebcfee994adc", + "0xa2e49b6cd32e95d141ebc29f8c0b398bb5e1a04945f09e7e30a4062142111cd7aa712ac0e3e6394cfb73dd854f41ad77", + "0xae8e714ab6e01812a4de5828d84060f626358bb2b955f6fb99ae887b0d5ce4f67ebc079ab9e27d189bf1d3f24f7c2014", + "0xa3100c1eebf46d604e75ebf78569c25acf938d112b29ccbe1a91582f6bd8ef5548ae3961c808d3fb73936ac244e28dbc", + "0xa9a02dcff0e93d47ead9cdddc4759971c2d848580bf50e117eb100cafca6afeaa7b87208513d5f96b1e1440ffc1b0212", + "0x894ab01462137e1b0db7b84920a3b677fbb46c52b6f4c15320ef64f985e0fc05cec84cd48f389ce039779d5376966ea3", + "0xb1e40e8399ee793e5f501c9c43bde23538e3ce473c20a9f914f4a64f5b565748d13ab2406efe40a048965ee4476113e4", + "0xa5a7d97a19e636238968670a916d007bf2ce6ae8e352345d274101d0bbe3ac9b898f5b85814a7e4c433dd22ac2e000ff", + "0xb6394c43b82923231d93fd0aa8124b757163ba62df369898b9481f0118cb85375d0caac979a198ece432dbb4eb7cc357", + "0x82d522ae3ff4fe2c607b34b42af6f39c0cf96fcfe1f5b1812fca21c8d20cece78376da86dcbd6cdb140e23c93ae0bcb2", + "0xb6e0d986383bc4955508d35af92f2993e7e89db745f4525948c5274cfd500880cb5a9d58a5b13d96f6368bb266a4433e", + "0xb0b4325772ec156571d740c404e1add233fb693579f653b0fae0042b03157d3b904838f05c321d2d30f2dbd27c4d08ad", + "0xac41367250263a2099006ef80c30bac1d2f25731d4874be623b6e315c45b0dc9a65f530fce82fb3dc25bd0610008c760", + "0xb6c0b1ed7df53da04a6f3e796d3bfa186f9551c523bc67898bc0ecfc6b4a4a22f8c4d3bfc740ebf7b9fa5b0ea9431808", + "0x8e78fca17346601219d01e5cd6a4837161a7c8f86fe2a8d93574d8006da5f06ae7c48eea7d2b70992c2a69184619663c", + "0xa21f91f47e04fafbfafacf3185b6863766a2d0c324ccac2c3853a4748af5897dbbe31d91473b480f646121339c9bae2d", + "0xa464d68786ab1fc64bd8734fce0be6fbe8dc021d3e771ff492ada76eedff466577c25e282b7c8ab4c1fd95ef5ff3631e", + "0x829a24badc7714081e03509ccfb00818ce40430682c1c0e4a399cd10b690bda1f921aabcbf1edfb1d8a2e98e6c0cedd6", + "0x87ccf7e4bbcb818ef525435e7a7f039ecbb9c6670b0af163173da38cbdb07f18bc0b40b7e0c771a74e5a4bc8f12dfe2c", + "0x94087bd2af9dbeb449eb7f014cfbf3ee4348c0f47cde7dc0ad401a3c18481a8a33b89322227dee0822244965ae5a2abb", + "0x896b83ed78724dac8a3d5a75a99de8e056a083690152c303326aa833618b93ef9ec19ab8c6ef0efe9da2dbcccac54431", + "0x821e6a0d7ccf3c7bd6a6cc67cde6c5b92fb96542cb6b4e65a44bbc90bbc40c51ff9e04702cb69dd2452f39a2ff562898", + "0xb35b2096cda729090663a49cb09656c019fef1fc69a88496028d3a258ad2b3fd6d91ab832163eaa0077989f647e85e7e", + "0xb7857ef62c56d8bce62476cdb2ab965eddff24d932e20fc992bd820598686defe6cc0a7232d2be342696c2990d80721a", + "0xb343d974dfda3f6589043acd25d53aecf7c34b1e980ae135a55cda554ff55e531bc7c2dfe89b0d2c30e523c7b065dad1", + "0x8d139e16a73cd892b75f3f4e445a10d55d1118f8eeafc75b259d098338419e72e950df6ca49cb45677a3c4e16fb19cdc", + "0x817b8535bd759da392b2c5760c51b3952ecf663662a137c997f595c533cd561ed7e655673c11144242160e41d1f2dd71", + "0x817ee0f0819b0ccb794df17982d5b4332abff5fec5e23b69579db2767855642156d9b9acccf6ceab43332ccc8d2744dc", + "0x9835d2b652aec9b0eba0c8e3b6169567e257a6a3f274ec705dbc250ee63f0f8e4b342e47b9e0c280c778208483d47af8", + "0xb78c40177f54f0e6d03083a4f50d8e56b5aafdb90f1b047bb504777d6e27be5a58170330aee12fbaa5f1e9d4f944acfc", + "0xab8eebacf3806fac7ab951f6a9f3695545e2e3b839ca399a4ef360a73e77f089bb53d3d31dbd84ddfde55e5f013626e0", + "0x96c411fc6aecca39d07d2aff44d94b40814d8cfc4ee5a192fd23b54589b2801694d820a0dd217e44863ccff31dda891b", + "0x8249c424a0caf87d4f7ff255950bbc64064d4d1b093324bfe99583e8457c1f50e6996e3517bf281aa9b252c2a7c5a83a", + "0xacf6ed86121821a3dd63f3875b185c5ebe024bdb37878c8a8d558943d36db0616545a60db90789c0925295f45d021225", + "0xa37f155621a789f774dd13e57016b8e91b3a2512b5c75377ec8871b22a66db99655d101f57acaecd93115297caabfc21", + "0x92e60ee245bd4d349f1c656e034b1a7f0c6415a39ac4c54d383112734305488b3b90b0145024255735e0a32f38dba656", + "0xacec614e562ccfc93366309cfdc78c7d7ee0a23e3a7782a4fc4807b8803e6ebfb894a489d03e9a3c817ff2ec14813eba", + "0xb912f9dd26ed552cb14b007b893e6ed2494d12517e5761dbeb88521270144f8c3eb9571a0ad444b30a8a65e80bd95996", + "0x8375408dae79c547a29e9a9e5d4ec8241b36b82e45e4ca3b0c36d2227c02d17bb171528d3778eac3bbdc75d6c4e8a367", + "0x8c2d0e6e4406836da112edbbb63996408bb3cda4a2712fd245e4bb29a0100fdc89a2746d859b84a94565bc1cfa681813", + "0xa7431bf59e111c072d28c97626cd54fcdf018421d053a787d2aef454b91251ee8ff9d3702d06b088f92b9ad2bbebff15", + "0x8f3659b0fbeb90b7f30b7a49233325e806551a32911a654dca86e290b314483bbb33fe6482387bc48c35d85c1dd0441c", + "0x8dca5ba23f0bb76f7dacabf12886053552ba829a72827b472a2f01e19a893155cdce65f1fb670000f43e8c75ba015a31", + "0x8c1514c083c77624eeb5d995d60994a2866192e15c4474d0be4189fae0e9dbd62494ebb4c02fbc176b53be548abbc5a1", + "0x80498d2ed153381baf3b0f81da839ed0eea6af5796c422b8e59be805dba48c4395bb97824ac308170bb4f14f319c5ddf", + "0x84f5ebc3bf96362457993e9fa31493c31c4283075e2403f63d581b6b0db8a3df294b2085643f2007f4de38cb5d627776", + "0x958e6e38774da518193a98397978dbc73d1c3827b4996ec00b4183da2c305a187a0ada9aa306242814b229a395be83c9", + "0xab8b8fbf73845615e7fab3e09e96cc181159eab09f36b4c1239b3c03313c9aeb4bbb51e16316fe338b2319ed2571b810", + "0x977e4e33b33bd53394e591eba4f9a183e13704c61e467d74b28f4ad0b69aa51501a5221cb1e0e42bcb548ca518caa619", + "0xa9bb7ecb9846cc30d04aad56d253c3df7004cebb272f6adf7b40a84adef9f57291e0d08d64c961b9fc406cdb198aab9b", + "0x8d2b72dc36406a545a9da44e1fddfb953d4894710ca026d6421a4ac91e02d0373a599f2acfe41d8258bc9679cf6f43d3", + "0x904192fc8fe250f61ecb8a36abbbccae85f592bbf00c10039c30b5a1c733d752a04e4fd8a1000c6578616f8a16aa83a3", + "0x87f5fdfe20bbbf931b529ec9be77bbfcc398cad9d932d29f62c846e08a91d2f47ae56ad5345122d62a56f629f9a76c4d", + "0x84cc3a53b2e7b7e03015f796b6cb7c32d6ded95c5b49c233ac27fafa792994b43c93cda6e618b66fce381f3db69838ba", + "0xaab58da10d7bbe091788988d43d66a335644f3d0897bbc98df27dcc0c0fcee0ac72e24f1abdd77e25196a1d0d0728e98", + "0xa10ea8677c2b7da563d84aa91a314a54cab27bb417c257826ebdd3b045d2a0f12729fe630bbbf785d04874f99f26bee8", + "0xacc4970ef2a4435937a9b8a5a5a311226ca188d8f26af1adfcd6efb2376a59155b9a9ff1cff591bde4b684887d5da6e5", + "0x8dc7cf6fcca483c44eb55e7fb924bf3f76cf79b411ae4b01c6c968910877ac9c166b71350f4d935f19bdffb056477961", + "0xac2dd1182ded2054c2f4dbf27b71a0b517fb57193733a4e4e56aca8a069cff5078ffd3fd033683d076c1c639a4de63c7", + "0x932ec87c450cd0dc678daf8c63cd1bf46124fa472934e517fbbfb78199f288ff7f354b36e0cc6c8739d3f496cfe0913b", + "0xb0d631ced213e8492be60ea334dbe3b7799b86d85d5e8e70d02beef3ae87b1d76e1df3bdb5f7ba8a41904c96f6a64455", + "0x929d7239ead7575867e26b536b8badf2e11ca37840034d0e5c77039f8cce122eff5a1bf6e0bcadde6b3858e9f483d475", + "0xaaae5d372d02ee25b14de585af6fbc48f2c7cd2a6af4f08352951b45aa469599eff41e820df642ca1a0f881120e89dbe", + "0xb23c411741a6b059f04fa4f5fd9dd10e2a64915f2de6ea31e39c32f2f347a776a953320e5f7613fcb1167efe502f5c5c", + "0xa4581b0ae633fe29c6f09928e5efb16db019eeac57f79fef2fa1d3c9bee42ce0e852bc60b9d0133265373747e52a67a4", + "0x81b33afffd7b2575d4a9a1c5dd6eee675c084f82e06b9b3a52a3c9f76e087f12dca6e0ffddc42fb81ce1adb559d47a38", + "0x89cc890f06b424591556aabdfdbb36d7a23700425e90c9cfed7d3da226b4debe414ac5bdf175273828ce6c5355712514", + "0xa4399438be75cfae2bf825496704da5ed9001bed8538d8ac346c8cf0d4407808e9ee67573eb95fe1c6872ac21f639aaa", + "0xad537f7ce74a1ca9a46fc06f15c1c8a6c32363bd6ac78a3c579ed8f84252e38a914cac16709fe65360e822ef47896de4", + "0x8e53b69f5e3e86b86299452e20ea8068b49565d0d0ab5d50ce00158a18403ae44e1b078a3cfd3f919aa81eb049a30c6e", + "0xa59f2542c67a430fd3526215c60c02353ee18af2ff87cb6231a2564fe59b8efec421f18d8b8cc7f084675ecf57b3fd05", + "0xb8d9bac93ef56cb4026dd1c731d92260a608fd55b8321e39166678e1dab834d0efddb717685da87786caeb1aaf258089", + "0xaa2df56f4c6fe9e0f899116c37302675f796a1608338700f05a13e779eb7cf278e01947864a8c2c74cc9d9a763804446", + "0xb0108ff2e327dcb6982961232bf7a9a0356d4297902f4b38d380ff1b954bfbcae0093df0f133dd9e84d5966c7b1aada7", + "0xb06b813b01fe7f8cf05b79dc95006f0c01d73101583d456278d71cd78638df2b1115897072b20947943fa263ddab0cd6", + "0xaa41e6c4d50da8abf0ea3c3901412fe9c9dff885383e2c0c0c50ed2f770ada888a27ea08bbb5342b5ff402e7b1230f12", + "0xa48635dbb7debac10cb93d422c2910e5358ba0c584b73f9845028af4a763fd20da8f928b54b27782b27ca47e631ebf38", + "0x80a574c208e994799e4fa9ef895163f33153bc6487491d817c4049e376054c641c4717bda8efbeb09152fa421a7268a7", + "0xb592bfd78ae228afc219c186589b9b0b5c571e314976d1ed5c1642db9159d577679a73c049cfc3dcfefcd5a4f174eeea", + "0xaa1f08af3918c61eadf567a5b1a3cdcdfb1b925f23f1f9e3c47889762f4d979d64686ce1ce990055ef8c1030d98daa3b", + "0x857df4cfd56d41c6d0c7fcc1c657e83c888253bae58d33b86e0803a37461be5a57140a77fb4b61108d1d8565091ada1c", + "0x8fae66a72361df509d253012a94160d84d0b2260822c788927d32fd3c89500500908c8f850ef70df68ddaeb077fd0820", + "0xaa1dbefc9aef1e7b896ff7303837053c63cfb5c8a3d8204680d3228ac16c23636748fe59286468c99699ae668e769a0c", + "0xb64b1cb2ba28665ed10bad1dddc42f3f97383c39bad463c6615b527302e2aaf93eb6062946d2150bd41c329697d101be", + "0xb6d35e3b524186e9065cee73ea17c082feff1811b5ab5519dd7991cdff2f397e3a79655969755309bd08c7d5a66f5d78", + "0xa4dae7f584270743bbba8bb633bdb8bc4dcc43580e53d3e9e509ff6c327e384f14104b5bdfe5c662dc6568806950da37", + "0xaae84d3d9ad4e237b07c199813a42ed2af3bf641339c342d9abf7ebec29b5bd06249c4488ce5c9277d87f7b71b3ddd37", + "0xb82a463cf643821618a058bddf9f2acb34ac86a8de42a0fa18c9626e51c20351d27a9575398a31227e21e291b0da183e", + "0x8b6c921e8707aded3ea693f490322971b1a7f64786ef071bc9826c73a06bd8ae6bf21bc980425769627b529d30b253ce", + "0x80724937b27fc50f033c11c50835c632369f0905f413b1713a2b0a2274bec5d7a30438e94193d479ba6679dbe09a65ef", + "0xa1d9b259a2ca9cff8af6678b3af0a290c2f51e9cf26d5fe3c6a4fa3d28cbf33cb709b7f78b4f61cb9419427983c61925", + "0x96a3e69a5ed7a98ce59c4481f2ffb75be9542122ad0eb4952c84d4536760df217854d4ec561ce2f4a79d3793c22fa4f4", + "0x990c4d9a4a22d63a8976d34833cafc35936b165f04aed3504e9b435f0de1be4c83b097bbaa062483cf3dee3833b4f5b6", + "0xb9bf5e4b270aec4a0dc219457b5fed984b548892c4b700482525ba1a7df19284464f841dab94abfabcaa9a7b7a757484", + "0xacaecf49cb4786d17cf867d7a93bd4ffee0781766e11b5c1b29089ae0024c859d11b45828fbff5330b888543264d74a9", + "0xb0e1a0865b1e6f9e4a0e31d0c885526ac06678acc526fda5124742a2c303bd0e8871a0cb7951ec8ed9540fc247c8d844", + "0x82b3d327b3d1a631758451e12870816956cd0cef91fcf313a90dd533d5291193a0ff3cc447054564ce68c9b027a7ffd7", + "0xa2843602abb98f0f83e000f3415039788da1e9a096bfe8fed6b99bab96df948c814560424ffebe755cb72f40436fb590", + "0xab1c7b43cf838798d1e314bc26e04fc021e99a7bfbfc8ffde62fa8d7f92139de86a377289d5177021154229de01ede15", + "0x95e5cf5dd87ae3aed41b03c6c55f9dfad38dc126b17e7e587c156f7745c8da0bd1d60acb718fc1a03b61344f01e3de4d", + "0x86f021a3762bb47167f80d4ef1b1c873a91fe83409f9704f192efeebbc3ece0729cd2f92f63419907ea38ae47bc907d2", + "0xaaa1445dafbbcd645d4332d9806225e9346ee5ac6b22ad45e8922134fe12f3d433f567a6a4c19efdd9d5775a7de1e92f", + "0x8fd7e15688eef75df7b8bca3d61bc9fca4f56e047cdb6d0b864e7d1c4966eac27d6094b0c8482b49739f83ec51050198", + "0x80aab8b4d394eb011d4ec6a4c2815617308c9b847c6fa6a3d7e6af1c79420ef6ff2a13934a398581c40ee4cf1cac02ac", + "0x8970b97ac076a1d8a321ce00eada0edf974a46bf3cc26f6854e4218cdfc8d2b0c32199d9658f254b4fbae5a2c5535f41", + "0xa1aa2ec5b03df0a630e73dd048680ed6d3032c324941423f45cd1f16038789e5e75b876a13948732e9079a422f66a9fc", + "0xb5fe5f5e2f2ae2beeb8e95859a02fc45f01f9fb0ebb2bd8ec9ec976b3e806228821a9775096d341d662bc536c4d89452", + "0xa2bc1f170b62d0d5788b02391337b2ab157c38e725694e80aeead7383e05599be0e2f0fa27ef05db007061809356e147", + "0xa8a69701d4a8d0d972390e9f831fd8e9f424b2c2ef069e56bd763e9e835b3ce5f7cf5de5e5c297c06ace4aa74df1067c", + "0xb43d551af4ff3873557efe3f3fb98e5ede9008492f181f4796dd1a6bcda8b9445c155e8146966baa812afae1abe06b48", + "0xb4b1dae44fd596813f30602ab20e9b1fb20cb1bd650daacc97b7e054e5c0178b8131d439a9e5b142ca483cc012a362b3", + "0xb95b8a94c30a831eaaebea98c65cc5d0228c78afd6603d4aa426d8186aecc951f1a11c33951f51df04c7e6fa43ffb5ae", + "0xb100059624cf9db371bec80013a57a8f296d006c139a8766308f1ea821c7eccc26cad65bc640ab3f6cef9062653bf17d", + "0x8e5a2cb76716e0000d13bce5ef87acac307362a6096f090f5f64e5c5c71a10fddfdee8435e7166ba8c3ad8c3f540f3e4", + "0x93d2c43e21588c1e83c4255c52604b4ac3f40e656352d1827e95dd5222a45aebff9674e34fbbe7ed21eca77bd9b8dcbc", + "0x8aeaed611546bb9073b07512a9a1f38a7f436ab45e11775a0f9754baaf63e9bcc7bb59b47546a5ded5e4ba2f698e3b5f", + "0xaf9e6792e74a1163fe27612f999a2f3cfa9048914c5bef69e3b2a75162bb0ce6ece81af699ad7f0c5278a8df0ba000d2", + "0x850bf2d5d34791c371a36404036ad6fdcd8fb62d1bb17a57e88bda7a78ea322397ce24d1abf4d0c89b9cf0b4cc42feb3", + "0x87f7e2a1625e2b7861b11d593aaac933ed08a7c768aebd00a45d893ed295bbb6ed865037b152bb574d70be006ddc1791", + "0x8dcce8f4ad163b29a2348ea15431c2c6ea1189ece88d2790e9f46b9125bd790b22503ec391bc2dee8f35419863b2c50c", + "0xb4bf5266c37f12421dd684b29517982d5e4b65dfdfba5fc7bd7479fd854aabf250627498f1e1188a51c0a88d848ec951", + "0x8651623c690247f747af8fdffdc3e5f73d0662bc3279fa2423a3c654af9b6433b9e5e0155f1ce53857e67388e7e3401d", + "0xb155120f196d52760129dde2e2b1990039b99484cdc948fa98095cd23da87679850f522e5955eae34ac267d2144160d3", + "0xaec8115e8d7b6601fbceeccf92e35845a06706d46acd188452c9f7d49abef14c6b3a9a9369a8bab2fd4eb9288e2aaca5", + "0x998a8ca4dc0f145f67a8c456f1d6a7323c4836fe036dcbb0f27eb1c596d121eb97369638a9908cfaf218c7706f266245", + "0xb235fbafac62802742ee3d26b1f4e887f7d2da4d711ba7f9bb6ca024de7beec1de66bb830ce96d69538f7dcb93c51b26", + "0x9258d2ddc21ab4e3edcde7eb7f6a382a29f1b626003cc6fdd8858be90f4ad13240072d8a8d44ef8de51ca4f477fa6c45", + "0x99d038487821c948142c678acd8c792960993dd8cb5e02cb229153a1ee9f88249f4ad9007f08e5d82e2a71fb96bb5f32", + "0xa88ee9dbc73d3d8e0f447b76fdb3a27936bde479a58d5799176885583dc93830ac58bca9087075950ea75100cf51af23", + "0x88b9b15816e5a0387153c1f4b90f613beb3ea4596037da01a81fdd2bcbd0baf5598db99f77e7694e5a0d35e822758108", + "0x907ae4b637d06b15846ee27d08c9c9af42df261c5bdd10cf5bc71f8e5ca34b33ac2405307023c50bdb8dc7b98a2cd5fe", + "0x9393d6900e1d2d1a1e42412fefd99578d9ac1d855c90a3e7930a739085496448609d674ca9b34016ad91f22d1cac538e", + "0xa28ac56b216730b7dcdb5ab3fc22d424c21a677db99a9897a89ed253ea83acfd9d83125133f5be6d9cd92298df110af8", + "0xb027590ee8766f1e352f831fda732adbaf77152485223ad5489ef3b0ce2d2e9f98d547c111fe133847ebb738987fb928", + "0xa9cc08fbd5c3fee8f77cf6eb996a5cafa195df5134dab000e4d0312f970a5577942ee89794e618074f49841f1f933a42", + "0xa8b3535c3df0b1a409d3fc740527ee7dd5ac21756115cde6f87f98cc7623f50cfcf16790689cab113ee7c35a5bd4879f", + "0xb61420227b97e5603ae8a716c6759b619f02b8fdc48acbf854352aa6519dad74b97bacc1723ca564cbf3ca48539ed773", + "0x853762498de80eebf955a6c8ddd259af463e4e25f0b6ba7b6a27b19bdbf4c585de55760a16e2d9345cdba6b2a02610f3", + "0xa711c1b13fc6c30745203c5d06390e6c82bd7c50f61734aa8d99c626faba30119bc910be63ec916c91ba53f8483c05a8", + "0xb488c0a793f4481f46b5875d96eecd73e46209a91677769f0890c5e002ecd7d4b1c9f4ba68c47fbed40e3857b1d8717a", + "0xa651c5e812ae65b1c66d92c607e80be330737ea49c1dcfe019c0ecea0f41a320406935bb09206a4abff0d1c24599b9ad", + "0x85e34e7d96e4b97db98a43247b6c244383b11ca10bf4777364acf509a6faa618bc973e2136a4693fbc8ab597e308fd5a", + "0x99837214102b394fffa7f3883759554c6bb7a070f5c809303595a44195e02b9a169460dc6bbffb62bdc0e7ced5f0a5c1", + "0xa952f89c0afb4bdae8c62b89cc3cfb60d0576ba4fe01a5d99534792f38d8848d919b3fc7577435d8443a044d2ee0bcfa", + "0xa1ac1f81acb29798acdfc493854663519e2d1b0e9d23d286ce33882c34b4c1c0bb43dd9638166d8026315a44d9ec92a8", + "0xac9c58aa38219ae659d23007cc7b97fd25b7b610b2d81a8f9f94ddb089efc49c049a8ea4c56e6eaf7b6498f422a97b3c", + "0x87e61d501c242b484fb9a937ef21d485f6678d75257fc8fe831b528979068cadbe7e12b49c34058ec96d70a9d179ab14", + "0xaa45f6852f35cc8b65a4a8b5380641d2602a4fa4e3a035db9664df3ac2e170b1280c4a8b7b55161430063e54de4158a6", + "0xa46975614ddde6d134753c8d82c381966f87203d6e5a5fb99a93b0d43aa461466b37f07b8d0973a1abd6ee2b40f24348", + "0x8d35f97297773422351f4d99564c1359ef1a10cfb60aa0e6c8985a78f39b4268486312c8ebf9dd2ef50a771aa03158eb", + "0x8497c6242102d21e8b3ade9a9896c96308ab39171ab74cbd94e304c47598e2c2a7b0a0822492ac5c076ba91d4176481d", + "0x973f8fcb5f26915b3a3ef6fe58cc44bc7f4e115cd0ad9727d8d1b8113e126ae2e253a19922c5433be4ab2311a839c214", + "0xae3ee9f1d765a9baf54b4617a289c3b24930aa8d57658a6b0b113bbf9b000c4a78499296c6f428bbb64755dfd4f795d2", + "0xa5be7a8e522ef3dcf9d2951220faf22bb865d050f4af2880b8483222ff7aad7c0866219fcc573df9d829c6efbb517f98", + "0xa5f3c7fabd7853a57695c5ad6d5b99167d08b5414e35ed1068ae386e0cb1ee2afbbe4d2b9024379b6fc3b10c39024d36", + "0x978d5592d4798c9e6baceff095413589461267d6a5b56cd558ec85011342da16f4365d879b905168256f61d36d891b1f", + "0xb7b6eaffa095ecbd76d6e1e88ceebabaf674d9ef7e331e875c6d9b9faa1762c800ff1ea597c214c28080f67a50a96c1e", + "0x8a1ab53ae5ceaa42e06e58dd8faf6c215fc09ba111ca9eeb800612334d30d5971448be90fec62ed194328aadd8c8eecc", + "0xa9ca532cac8ace9a9e845382f8a7840bf40cb426f2fcad8a2f40aadbb400b3a74021627cc9351b0966b841b30284962e", + "0x8dddeda8854c8e7ddc52676dd1d0fed1da610ed5415ddd7d25b835bd8420a6f83d7b67ec682270c9648b2e2186343591", + "0x888906aac64fd41d5c518a832d4e044fdc430cfe142fd431caf4676cafc58853ce576f098910d729011be0a9d50d67b5", + "0x96a3f886a2824e750b1e2ea5c587132f52a0c5e3ff192260d8783c666206bd8ebd539933816d7cdd97e4bc374e0b1edf", + "0xa150a29ffb2632cc7ec560983d9804cd6da3596c0c25956d27eb04776508eae809659fc883834269437871735de5f9ed", + "0x81f7ad4d2959d9d4009d1dfbc6fee38f930f163eb5eac11e98dc38bd2f7f224e3f5c767583f8e52d58d34f3417a6cf90", + "0x97ccac905ea7d9c6349132dd0397b6a2de9e57fd2d70f55e50860e019de15c20171a50b28a5c00ef90d43b838253b3d1", + "0x95694f00c21e8a205d6cbda09956b5b6ec9242ec8c799a91f515b07dcc7de3b6f573e2c0ba149f5a83700cda2d1df0f5", + "0x82bbc3c4a3b3997584903db30fffd182a266c7d1df3e913f908d5a53122fa12cf5acd11d915d85d5bd110fcc43cee736", + "0x8d3f24b4949aa1b4162c28dfbb9f813dd1d8b330f71325448dc45ea34d59b69ca95059402aae011e1b5aba6e536bc6ec", + "0x92c734c19752d24782331e74c9af97a8399ddfdd32954e91cda7363dba876aca4f730b451c50a8913950420682da8121", + "0x8653d2c79f77b8c7dcdf7e8dee42433998aeedf1b583abfca686d47a854de1b75e9a4351580c96d1a2a9532659203361", + "0x886f0e414cb558c1a534a1916d3531320a9b6024639712ffe18164ce6313993a553e2b9aafe9c0716318f81a5d0bb1da", + "0xb31b5efaba5a5020c3bcea0f54860e0688c2c3f27b9b0e44b45d745158f484e474d5d3b1a0044dd6753c7fb4bf8ace34", + "0xb2d615bbdfdc042d6f67a6170127392d99f0e77ae17b0e1be6786ff2f281795f1bf11f83f2e0f8723b5cdd1db1856e09", + "0xa6e014cca531e6ac2922239b5bee39d69d9ba6d0fa96a4b812217dd342657d35606f0b9c5a317efd423cdb1047815e3d", + "0xa8921736b69c9fbb29f443715174bac753e908251804620c542fad6cfbfda7bdfe287f2902f30b043a8a4b4818cfdeef", + "0x8d73a9949a042ec2dcefa476e454cd9877eee543b1a6b3b96a78ffcff87421e8b26dd54d5b3192ac32073cb36497acc3", + "0xb936a71ee8df0e48867f3790adf55dc8efc6585024128de2495f8873bd00fd9fa0984472125e801ed9c3cdce6698f160", + "0x82f69c06209c28f64874e850601dda56af44ffc864f42efa8f9c6a0758207bf0a00f583840982dec0a517ab899a98e5b", + "0xb7a0a14411101473406f30e82f14b13e6efc9699e7193c0be04bb43d1b49e8c54812ce0f9b39131a20379c4c39d3bbe3", + "0x81159c969f38107af3b858d7582b22925a7ccced02fae3698482d7e9cdc6c568e959651991c6cf16c53a997442054b61", + "0x8bf1116a206e0ce9199fcab6ed2b44a9e46e8143bff3ed3f1431f8d55508fe2728b8902670cfd8d9b316f575f288ed9d", + "0xa279b2149824b64144eb92f5a36b22036d34a52bd5a66e5da4b61fbc95af6eda8e485c7914f448abd8674fc14d268d9d", + "0x8b98279b5f3588d1a2f8589d2756458690a502728800f8d94b28e00df842a101c96ab9c5aee87c5bbe65552c0c383b80", + "0xb4a27a351ec54420f94e0a0a79d7c7a7337940399646631baca93eeab5fd429d7fb39428be77dcbce64a13eaa3c8ca1d", + "0x90c08baa29ec8338ffce381eae3d23ce3f6ba54e5242dec21dc3caaed69cac13f2ab5e8d9d719bc95720fa182eee399c", + "0x85156d65bb4fef69ffd539ab918b3286105ca6f1c36a74351ab3310b339727483433e8f8784791f47b4ba35ca933c379", + "0x923005013c27209d07c06a6b92b0cbb248a69c5e15c600bbcc643e8dcd2402adebd94dd4cafb44ec422a127e9780aaec", + "0x863b23eb5463a6ef5a12039edc2f8e18e3c97b244841bc50af02459b1bcc558367edf2f6e4fe69f45f37887469dd536d", + "0x87a4a7708a112724ff9b69ebb25d623b5cae362ae0946daed2ec80e917800dbfcd69f999c253542533242e7b9a5cc959", + "0x8bf4347ceea7f94b53564f26b1a4749a16f13bf71a9e03a546f906f7c423089820ff217066159b0637d9d6824e9c101c", + "0xab07eef925d264145971628a39e4dd93ff849767f68ed06065802cf22756fc6bf384cf6d9ab174bfc1a87bcc37b037aa", + "0x8e3f10a42fad43887d522dc76b1480063267991c2457c39f1e790e0c16c03e38a4c8e79a0b7622892464957bf517ebd8", + "0xa8722fc7b1acf0be18f6ddf3ee97a5a9b02a98da5bc1126a8b7bf10d18ee415be9a85668eb604ef5a1f48659bc447eb5", + "0x878d6b2a9c0aca8e2bc2a5eb7dd8d842aa839bbd7754860c396a641d5794eab88a55f8448de7dbddf9e201cbc54fe481", + "0xada881c167d39d368c1e9b283cf50491c6bfc66072815608ba23ab468cfbd31ca1bd7f140e158e0d9e4d7ebfa670bc2d", + "0xa2b48578fa899d77a7ee1b9cb1e228b40c20b303b3d403fd6612649c81e7db5a7313ba9702adc89627b5fd7439f8b754", + "0x8e051280e10551558dcb5522120ac9216281c29071c0371aaa9bde52961fe26b21d78de3f98cb8cd63e65cff86d1b25c", + "0xa7c5022047930c958e499e8051056c5244ae03beb60d4ba9fe666ab77a913a067324dfb6debcb4da4694645145716c9d", + "0x95cff6ec03e38c5ab0f6f8dccde252d91856093d8429b7494efc7772996e7985d2d6965307c7fdfa484559c129cca9f9", + "0x993eb550d5e8661791f63e2fa259ab1f78a0e3edad467eb419b076a70923fede2e00ddc48a961d20001aaae89fad11e8", + "0xabb2826e4d4b381d64787a09934b9c4fe1d5f5742f90858228e484f3c546e16ee8a2a0b0a952d834a93154a8b18f3d16", + "0xa922ca9f2061996e65ef38a7c5c7755e59d8d5ce27d577abcdd8165b23b4877398d735f9cb470a771335fc7d99ecb7fc", + "0x90f22862216f6bc1bbf5437740a47605d1ff5147b1f06f7b13fec446e4c5a4a4a84792cb244a1905f3478a36f8d7065b", + "0x87f3d9a86afef5b79ea1ca690ee1ee4bb9754b66f7c50a42ad6b99af7c222c853ca161f440a0a2a60b3b5a54e3493240", + "0x80a9ca9a2d33b9cf61976b3860d79f5d00de89a06ef043d2a52931809018aeb4ce70423cbef375b29c2c750c2c8704c2", + "0xb4e798ef1d615896108dae37ac50c1e859216ab6dbac11653e44d06ce5209057b4b0dd6d31dcfcda87664a23c8ef1cbd", + "0xaaed6d1e7c5b1db06f80dae6c24857daadfb0268f20e48a98fba4b76de1ebf65fb84c3be95fd6a418b498f8285ec63bd", + "0xaeceaa316c6369492c939f94809bc80e0857abac86c0d85be8066bbf61afbaaec67e28c572437a8d35c49dd596b3134f", + "0xb791c3d53ed34a7d1c8aa89b7953e3684c3cd529230824dc529739a5fbe74b58b87f01e56e7a169f61c508237ef67160", + "0x9351f8c80634386c45c0050d2f813193f9d839173be941e2092d729be5403632a2f18dffdc323d69eb0dc31fa31c5866", + "0x97693184d5c0056ae244dfb6709cafa23a795dc22d497a307a7f9cf442d7452024023c54a8d6bda5d90a355ba2c84f3a", + "0x85362daa003d23511ca174a8caafe83d52b6436dc4e43c4c049e5388d9211b5cbef3885896914d86d39be0dd1f910511", + "0xa2511b5fa34b24eeb0e1bcbcf872a569d1ff5570fe7b0fb48f5542f7fe57bad808d34b50afa87580866a6cb0eba02f27", + "0xb382e3327eb1401f2d378dbb56ac7250adde0961bd718575a64d264ffd44772c20752d4035c3ba60eb435e160b375e20", + "0xafad8a5d40b536c0720556845a6b257ed42165c14fb4b4a874717d107752f49ed9380c5b048df3aca67287bb8fc411a8", + "0x8fad0c98434ca5373c2d767868f679b76b4a8d04bca8240ea3f388558262c2d61b73b16fc1160932652b5688c25fffcf", + "0x83898008b5cbb6f08f8ef3ec179427869682bb4e8d38f6e6a687a214d4a307436afc64ee67d70a5a8ba9730bf839aecc", + "0xb85232e79913785fd82b06890706972b4ad7a309489930ae23390d51aa5189731f8a2df24800409a8c36b3dd6fc91275", + "0xa24ff26ec792f3701da4c5638c1fca4fa4dae95b01827d6200d583c4caf17ea3171393ba2a8c23d1ee8b88402916f176", + "0xadc5c7a7ff6b41d6cc386b7fc69d7bb04179bdf267864f9aa577f0f6a88438191fa81ebaf13055c2f2d7290be6421ace", + "0xa05e835abd502d31454d40a019010ff90b6b0b1f993075a35c9907aeab7a342ac0ba6144dc9379aada6119157970e9b2", + "0x85ff07ba58463e7f153fc83f11302e9061e648a5cbd272bb0545030b20e11facd8b3ff90c9ac8c280a704fbda5c9d1b0", + "0xa6c735ada8f4587da8cdad7ea3ada01650b5a3ecab8d81daa7a5f5de51ef4a6592b524692584306f06be3f6701f2870c", + "0xb138deee4e53ae8d677fae104f713ef1b8babfecec16b6a85785a66a72784eb09d44c3b63567222ade714e98f7d1604e", + "0xae79c1a49dafcdd972acd95d8ad0a35c02adc7fd736d4c44c3cd13df5789d339b5ea16bddbbd43e486a061ab31baa5c0", + "0xab3cf2371a1d7dcd0ffe3869a0178230964b06694bf258b2073ea66a2afccd845b38485da83d02e1d607d4c5c36b78a8", + "0xab9609f28a325fd01cb39540e3a714506c44e52ef28ee640f361deb5760aadbb23e804663b0fa20a66e239c33f8d8bb8", + "0x8ed95ea8e76e1b42823d7915a6aae77d93746f846bf602841dfce0e47543a36efb9ee7e5b42c73c3209d911225cc471b", + "0xa80b6162036d43811482323f0ce59eb18740e33a63d7c7bbbf3be206985919e5342d53a69df537d43e8b7d7f51e8892f", + "0x93c03d0a5083408ba00c125a8a9385213d4c860072f0297857b1235045819b904e07f2425c13a661d0a01d2e53347f4b", + "0xa6581200f00f96c461621e1d26b14a23687dd97eb9f7df4ba641a84340ee7306dc1796248fba4804f185947ad13b4385", + "0x8be174018fa40f7e0cedc5ae68f38969eb7695f2205e9c573641e533d56f68c20abf38a23d2f0dcac371e60b21b18615", + "0x857ad4ee3218c647c58f09b8ab22bcc8976f00a768ab1f708618e868e6143474be846422ce2710a0ed39b5155b6f13a1", + "0xa490bec40f322d599f26bcefcdddd8f2ef6576aa737d5ce7e8d5d422741abe749e3e6a48489aed8c560633f72857e3c2", + "0xa9c0ee339621f1c4a2410f9b4d2f03f1b558dae2973807b8bccd920e8feb7f65dfde3e79986b72ad21fcc4567240381d", + "0x8592251568e750a430f7d2c6ddbb3ec82a4dd9fd83efe389e69aa177fd97ac2c96c59a6e86db20d8e6f125d65b46c4d3", + "0xa4e2f4aa6a682913b423b097c4069c4e46a1f3af9556b1bfd0580d0fc01e3991488458049e0735b2a629684a79271c8f", + "0x8c4f6a3e738cf74112b08b1680be08158013ef8a515a81215d8a36c9b756786d1b4cb4563923463f3329292f4b48bf6d", + "0x8bace547353c02ea00dd547eeda7259aa354d4772dd5e0c486c723cf88627b7112e196b879c3c92a9561b674d9fc486d", + "0x8d372f4901e25e8db64fa098148d4a4e709b0e9dcb756d0f90dad99dea393054193ae1a33d292a3dd772ff7ba05e4b71", + "0xa8c7ea6a6a031ed23d65639f01f5423190775558f479700597df7ae7e338a6ae5e9b32f470aff20787ac8b7eec84df6c", + "0xb6e9dcba240fdbbf66033410a79a2dd3e9e1ffdf2eae949b3a9ed720e939d92339991dc3e70a5ac7d5253f317daf0b7d", + "0x974dec4cd61af75721071752c664d9c2a5121f06ff1515c56139a177a3ca825f763b69d431d4607e393fa74dcc91cc58", + "0x958863e6ad583a9d370a6db3639066982e44766904e7afa849b132f6666b7d08ab931131b3bec7a506d6583e93d56767", + "0x8b93a33b5da9b3300c20a96d80b894e3789c77041183c2cb21751579c8c96857f60cfc2f075201b64e95a78985c5b321", + "0xb726cb9f7ef34ddbc2fad82b3b0af0b30cc913e26c5a614ae5c19cc9c55c8e6dae069db5315a8dcb6d987415bb550ca8", + "0xa730f515398a71bddd66cab2ff996659d4e47dfbb08ce7958a41021f76d269b91c7498b708cd14b183a8ef469c772803", + "0xa4eb3b18132eb0f5337f14e01d63ca0bec0db6a43870f800e5491db756c2f5fce519d8dba5528b4bcef550d06b33699c", + "0xb1ab6621eec1ee6784e632e214693f39a14f3715991996b883d66200963e065c86fa0667f7bc36b93b40b5d90ff708c2", + "0x80486a26c3532ad6e19f76d8c9344e2626c07363fd495264927cb5935fa9565ece670dc98767afb04af6a9a5c9231075", + "0x8ee20e0df3c84a1c6b0e21bcc325cf99235b747ffe47f17fdfba548a358ca75cbcc331dd50db2311b400ae882256a608", + "0xaef4268959e5541e7ec69c921a1e81a8374d7e44bf1bb2debf4101cf3cd6b7d6ca7f441758b388de96b3e0edb5b97be9", + "0x8793629bd29d689ec94b016de8886cac6e2ca6638911babb22db4a787661422da0639a4e4089ebeb689d173abfe75950", + "0xb487b3551c20a29e9a5abbda8c50ff594826283e443c09e3ae09b914e46060b3f9abf70434444ce1487e2a74e562616b", + "0x8f11531cfc5997dd04b997cb87ba1831aa7041d5434fe72de66304e3f165d882fac891391fbb1eb955c65319e65293b6", + "0xb195136875fd02a75676c33cb3e60504d5964f7a9e81f4c8c8fd38af62e2145c55f765b3158664566191188ac678f381", + "0xb374174b0b3eb04fa49eb4ece45173f0db5d829eac370a20a62309566e0f98b18f72f3633626893c053b7be6bfbd2366", + "0xb2a2f6b0cf652775679b2d677048f2ed8c31a3269e6cddcc7a10e3e6fee89e486b50d9d55fbe452b79c4157c0270fb77", + "0x892177c364dc59032594e7a6fd032286ffdf4fa0b9e3baeb37ec839faebfd2fd46c57b2c9bfe9977b59c93a9cc0ead1d", + "0x8ab7c0038a7dbb2ef200dbbe9acbc875829ecad4883792d5c6ce283de67ccd9aa935a9cc7b30b2bd9de7fca7bf2a9a05", + "0x83745cfc78ca709835aa6c6a233c2b86fb31e3f9f6a8becf63e501f2841c4366fb7d131b746c9d3291afda714ff05579", + "0xa723dcb67925ef007e8339dc578d2622d9bb77cfda87cca0088854a59414c02338752c56116a6c1281917842e8467c38", + "0x8a098142da0af2254c425fdbbd0d1b1a17b2bd781391ab37f181775524b8563c64ab8a1602aee2ac6c0a82ba11a8b1d1", + "0xb13bd7529a9b351c5d395c794c28bcb0a3167f1c992e8c062eef47be9be27895945231d249c73a0b6949daa295e14944", + "0xa20dcd2fc2222eaae467d9f5db861040f58bcb991a26e5663ac3aa5e1ff13d0010657c5af586cc4621757add2b905073", + "0xb818f660c3cc4e9f273c25ceeabe562c8afa8ff88529c26f2cf45ae6b2813cca5f350e3cbd56f6257c4df41722dabd25", + "0xb225d5987108b24411bc389276f12509a45e86d5ad6b6d929af5274df0be11109c0fed329669a0acafdf3b0beaa8f2ec", + "0x91fcb6d04576d3c6bae947bb7843b430e5fb0592ae49b0a65dfa5791f4eaa4bf2c7f436c8de7360f217001c2b4e5c67a", + "0x8821f7a1424ca3fdc5d4a5606ad10dfaba6094cf36669fa9f84cf7617e50425405d14980780e1e18a1ecea7913cda896", + "0x990dcb7f38f56521a70cb71bf4522649fcd46ac052c7feabb0748dfcac9f9c0f95d29e070d32af3cd0adbf869535e17b", + "0xb0fac1029fe2c1100f24e2f4bf10c7672199fce53513c7dde2e8d9b00702edf0143e0e1dc7ceae7dcc6994edc2422b6f", + "0xa514ebb1a33451b4915c05114db0b10168393613744df848b24e43e09f0bda23baefd9d731075198aace586615ac7911", + "0x8b77f7953c2e67049fdca3653b8d8cf3f799677f79b954da02bdad8cc4d6c855c1c7c16b4f6f9ba35f46426ec28b2d84", + "0x875520cfbda16ec5b1d1d00f578a910d0fc052f17870ba093e22e310bb07648d34817cc2b8811b6f52de535f7046a0d0", + "0xb8c77b4be0b430851c4ff69e91cb770db1935d848198601393810ef395efab52deb9d5c6525472bab720273d5e0e7a79", + "0xb6d4d437146671bdea62fb6545395ea3df39f1cdef21b8476b68e7a25aa7354f847740576d6c9f187bbae9941f0ae450", + "0x95c642f1bccdb62cd6a2212dcdd6ff8d49aee426ca08b7cf3a9d15249d24a9eed5533f92a70c84498c0797f8a57efa27", + "0xb617978047ed0f748c305aa7f30c2dacd0db00baa67fe0c5ce346ef0e6991dc7e05f18dcb2702467421f8390f27aa815", + "0x86411c7a00b3e8b43bf22fb061b1f54ad9bbf632cd74395a478218389c0f544668acf3dd7726532d080ca7da9a5f8608", + "0x97bf684a8849626c4710a6992f6c11f6b5406fd4dfe9e6aa502425aaafe9827e2c435aaf9a5d3d2ba3a4c0e8aec79ba4", + "0x8b178e2a125b461d3180906ffba0af3dce614c64058501fdd35243ababf892d6fcdea4834ce42c25d5569452b782a709", + "0x8ebed2c8a25c61da6a6a8cb0d8f5ea179e28869753eacc728f2c076f7aed8598cd3aa0981f120f9e7ea55b3a689ae882", + "0xa6f235b8e655ca3d634740b53d8c0a757ecc75d2b8838b7948997c1985473d01943d935f687b86cee56cd47c8e773443", + "0xa7959c465a9646908b9d8032a589e41a7dd999f2ffc54bb42f22e5f8a4d8c493a31bcc7ea2cac6c8dbcc59acace7181b", + "0x96d0532df2e12da20a57cadb6cf5f6c4ee1aa4775629358c25f1d51677a3e96d1fe3b232532324b4f02f941952d4cc68", + "0x90f493473d686b639a30d1ddc9c72eae6e983f1236e162e58e967a477c0654973ea2e1bdf4ba1a44d7247bc1befc2cab", + "0x8b2d87876d9c4085102a07ebb41c565ba69acab99ffc03efc18f20e48d3f3bbe4fc6ddab9c78fe479d9ada80504d85ba", + "0x829a0fb3200a28e09cacd6c5346000e7786116ddfd898f37dfd17bef454a8abc0fe939ed8735c00769f7f2f33cd4f906", + "0x86194ec9e88ddb7150e8b03e7a535b6e99863fc6762835601efd03615aa97aaeb413cb210e86035086ed852b39c9d019", + "0xb02efd116a7189cb317ceae392bc301ae55470f0489fa89934e182aeb8c67e280299b975786fe9a470bff46827defb9b", + "0x87d7c3903bd22b12d815506f150373f518d47dfc6e5fd74347d88b518124c9923d1e4c98defeb3a45d53d50b423e2175", + "0xa1a430406b28254a7d6348bc98e697e9bab43839aa05d53faee97546f84541ea0b559162619b2045182938f69bf61cae", + "0x99d243c226c61c6697fb3d2594f3533fa5dfd7cfc87107908cacde337d7a077fa5a9dc702d26081b065edb1227498e65", + "0x800ee5006ab6217161f42db0cfc552a81728bb4fbd7af6e4620ea099a65ef6664184af3f65a07fcec7e965529c5b49bf", + "0x91bfd307579cadc8f81009558605be3edbcb8dbba271475803484017f40130b2b216aef4f620d960193be681877d3a53", + "0x96a060459dec458d19a6f8af6e49dc6c7c58c55dd18915c5fce5e0f4b4a422fce3b9632f6059388fe760289abf70f173", + "0x9921a37f3e657222c7fda3588418a9071409711d9f1fccede7494429f02a45fbc52d79fbb64e9ccd518f60d06d0520d3", + "0x81052b0d15773cb75975ca9230ebb2579700e489c7e3f07cd9cde206fef38b8139bd4976d2b4a7840495fc645f96df03", + "0x88ac37ba66d1de5e23878c992e4d54023729e97e77351f50dc5918d738b5a73faf1dc6feec7e85784761836ba1c6f778", + "0xae1e6072c13060775f6086d1ae1f88b627ffcb810fc0e0e97deea1f3a15ef0aaa52a6dce2563e4beedadc131af2a8281", + "0x8b60a340f5e4f90badf83001b495ac9f13974c3d2054ddcb3e6b8ca99dec5cd63a263e05c282454191ab2e087d5a2911", + "0x832e2d56ba69dbf817b2b9dbd25c1538d5b8dbf5d9bc05e6be85054a423ebb66a71b157e166e0b9444ac171b34b7ccc9", + "0x8586036fc7dde1e7e3ecb61663130c4529866ae9f5f5095b9fccd24a4c70eea899aae5f10ea1ba66d1665b2d83be35b0", + "0xa77969453b5c083a207913272b5b69d4ccbd8718bdf54be8fbe11b4bd0a2168aae3ba8f9362afa69c0ffa28d7e5a2340", + "0xb7fe9568c214baad0ac5f83745611b481f744ec1c4fa78a549b180dcf79633e5ba75dc20055012a13d849eb7a9be57d3", + "0xb01cad1d2a6c51c0ce88243d1f52f95fb5ee315a905079688027511f0c4ecd0563a3a81846709d272fa5ccb9665e8043", + "0x8eae0a21adfc569aa57237654021c2bdb2c6f0f52ccc90a126682c21a1f9413c63d285f92b2b2f8649150a9284bf70b7", + "0x942acc947192b5f3cf60e92383e5d35f79e7a5904e8e9fd1c8a351676c83ad29b0afb6578d555457cf909f8f4d27adfd", + "0xa74e092f8628fba9abcabc27e2e9f3d5a9a941dfe50a2dfde2ad179aabc73afd196676925c2d98643ab8b3d02bdb66ad", + "0x896159daa2afd757cf3f9d34af248ad68bb3c62e4c9ac49919422727479cf669098f270b9e645607a7d11adad4c889b2", + "0xa428d8370813d78e7a2a24eebd36e9da2f8bb3605e5a39b5fcda939b531c35a8ebaaa642ba556250a37bddeec90326fb", + "0xa5fa04eb60a1d5ee9820e78f42f7be15e1c02757b539aead995768c6209684d6c183c71d282e0c12a4c15c03f9a89d4d", + "0x93c77d5d220e40affa7269a6915c076c9aef4db552c643ae5d560a79c955b491c6346ca4cf11cbb7fe1894e28d47b065", + "0x802e605d2de745eef6981d88e7a57ef4046a2062725e8080995374cea2b3273c27f35b7774d0dcba014710d8d6c501f2", + "0x82f7169e6ec9b3e2bd450f35ea2e66d06bcf900acf5b73139677b48e078ce2e16599103027b2326770c99c0a690f2015", + "0xb0c8581879439f9b997551233fe2de71aa03604f9cec37a7b18c5854342d9b67be468f3cac4bf6f64fe8a0066248c498", + "0xa3f626848a4db6e9fb01cac90d3362ec521e969ebd5228af694ea3671061476149f13d652942ac1e39f65591fed740f9", + "0x88a8e759b9cbe16a7c16e43f4afa2de6100d2eafa4dee75ccd653ec38c919013d0a6b35c1ee1eaee7c1985b58bcc9e92", + "0xa3d5fc7aaea072798490616552d947e95f49cf02a420314307aafb555287ec607d75589ba24b009cd68299dc6f7942fa", + "0xa809cceeb84f9bcf3c3ddafde3041e7bc3b1d14df8830ab849002176a0725e6f16f70774d8962cb0b8ac0dc43c4ac66f", + "0xb8f2e46c031cc8fa160a08c2ebdfa85345ed14771b06daa9636b0e7792b7fddbc501dfc85cc626a01104a43a7d3230c3", + "0xb5367e2a521c318b802ce16ceac80c4b8139f73ddb10ddf38433397cda70a86ea1f051cc55626a4e99d27f30f3975ff5", + "0x96d963660121c1441cd13141279cd371a6a0aa18b6a20761b18df60aa9c14e13489afd83695a0921d5232efe72045f07", + "0x80818d492fd85d666bd91aaf6257b86527fdd796773c793407df1d4a0f91d74649a6bab4d15155c36ed4c6e0a32c5636", + "0x931e22918905fd6c230d3d867ea42861f3074d320d14e1929031924c8ac209a5c552b679b24563bb12f9749b4ee983bd", + "0xa4de2c333e74ed9bfa3c0bf6a0beb90427abd9aa4221294cda74331646b58ef46ed57cccc8798ba2b9309894b17cfd69", + "0x883881554c1d88c0ed8d3b6dec3d200f6fea69a77ace3e4d6f86b41506a23724b4394ec8384075f9c75c3868ba8a8e8e", + "0xaa0539ecf6ec9bf06f24443027f8f24b6b3d8c5b2084248eecd4bcad3c9a69716e1a0d01057f09a65bff1006ac5e157a", + "0x856d74d44c943c9e809b42dc493dff20eca03cb0cf5ed45108c69b1f90d8592a53ae8100e99380a274fafad23e74cdfc", + "0x9188257446661c88da093b7c5ce998135913f63842d7c1586065377b169ee35b062d925367fb9b909ca971f1188667b1", + "0x8d3aa57cdafbe998938787479f5d590c1484c6dbe94e6c487e57a746ef5252be0eaa5976d6270de7db64b6b92e57a0f7", + "0xb8f4d6997240f9eda5aca0c43323a828d1563c491b3db2087f60ac4120a3fcd06075fb42bb19d0339ab5ee3fb7db25d2", + "0xad247ea94b8ae1e81eae4c9fd7b39e6601b53cff47b2547ff90a3cca87192eae28408082774a1fd14bf9ab459b7a4f1f", + "0x9598598070f8bdbcc49056c40971e673726cd8c1bc4baa0b5124dfb5fb750e7baa7a7df18eae2bd91955ddcb1ec67955", + "0xb874131ab1608667fa60ea29092d090859eed1812e90c609afff96d79e82c5ba546f617f4c96fc32c9bba97431c1e9af", + "0xb00750a9cdc75c2a54f0d3cc99b0fe02300754f25166f7ac85ff41ab5e9cfcca33a29be76a480f12a2d410c7cd5032e5", + "0x84b5bd1c90bb6c66755b28ba4af493ca1b0c3a4df9f436aac67d2e07289053f925cf6a149a84e74e1027dc8758150179", + "0x99caf64bd9d193ff306e8ab5da3f1bb2a190a60c3a82099b8d03d17fa810dc53d176c21379f479e828f60d25beb3ffd0", + "0xa8fd9de502f1c261d5733430e5a18d8b7892a98c9529a016fc2ee53892ae965dcd9c75850bcda4c7edb980b8d88e60ea", + "0x848c02cac636e047028a3fe8c1bf4066fb7591b96b0340f8fbd476ff01b35fa3e37d309333771a134f24800e5f3f9289", + "0xa1eab1a06dcca3439f0166441e7e7f2f5b56f5f8aa9f45e411c561f556e0fb71c514c06c26ac53b49a576caca5faac3d", + "0xaa603f970dcbe953e700e61c151182c8d32cbbb53ceef572ac93383db33a4b098b5c7b267e42d514ca66b740c0925efe", + "0xb55fd5301bd700ddb0b4f72fabe9a91ad49759506101fa802ed1677e9553595aa4d2c66f7574e78d21ce882ce0120ae7", + "0x829137bc4da7b4886d3d04d2c39cbf4b1dc40c813ac1adb425c7b9abf9142b516314cab79c68454df5d71994ce416144", + "0xb83a3a22735001f783dd48a01c4fb3598a51ff3987e842b8045c71c035b9e43645a55254ca5911a5676ef4a8af12d056", + "0x8ca8d463deb13f9eef5e533bc39efaeb0c15631282c5c0deee1673b0053a7cccd514af09801dd6c158caa159fe9351ac", + "0xa9ffb1427828f3c456b9c8cc50782de1ab0029b9233a0fd998bad0fd014d27e15c4a32d1e16ad41bff748378b5abdf49", + "0x9627e29f725ddd86456aff813976bbc4a836f4deabf5ad9f73d1a260ceb30948824df9c8841e6b3c529652202be181b3", + "0xb52c988647fe3d9276eed3c262e1044f57fbb116c64cf4f207235c205b3fda0f3d789bf90f5217401b468d85fdfda404", + "0x833bbd6e2924f5c4446cb76b881d1434a5badce9eb9b003f85d076e297ad7ef45b822069fe54d17427a348c3263fb838", + "0xa067a36352db6f82a116cb87d3db5f60b18576852409e2076cbbfc7843af78866313a4969385a40271051dd195d51116", + "0x902b99545971f9a103f99d7399acc347ac46fe156166e51deefc0e92aebf5893460c69aeeae11f5af9f49418e289ce6c", + "0x9206a0e9ce9b9880f29ef0417c96931985f5d83bb17cebdbba4ff2af81a3d37155b04649426f698aed372e4f669599e6", + "0xb54a5d7c976e45c0b1d44433595eae9d1ae9aeabfd58cd5ecb0c5804756a7b01c9a517754423b4714a3695533a3114c8", + "0x91b612131e84580ece228b81ace83da0269b53f94d3c02a1a0879ebbd81bdc252064b3d03a7e140b43a90f237d9a45a0", + "0xa6cead3b8607eaeafe37135bd6de8fbd16f806c131eb71c8d36bfbe295d45b070255e50dabf076e2c3f6b8699be71d6a", + "0x931da21e67b11ba6ce438546a24d063bcd51aebe39b4220a78d9c0aab88b2d37969b5ef3502d835507f9c8d6d006714c", + "0x8fda408caa9daf01122a2308b7b9d328f52e1e2f138a8bec30492488f4d710e5e52524a6455a3a2ae2818ec8a610b650", + "0xad8ad5c189644352d90c462731c46145410e5adf38682bb80f95495dd64d9d13782537d68690847bbb06c6be7175dbc7", + "0x87bb5cc466ade60feb0961421c3fabdc8a7e20f11df8437bfff63d3f8bd25305002a396c9d0fa4fb9a9986d4717f12c4", + "0x827cff72870ba00c29064a7d2b4973f322d6b6de7924c93d8bf8825e7a0e8478c7748f90f5c716bf83c55b2795d315d8", + "0xa225895a8e94229776ceb51b05356291f2dce748be17a60d5aeb33ef8507c368bafe5d1d6eea927f28b9d1422b661b9a", + "0x8e011323ce670ff51c964241a6b72e0e0ffbb3ff9bb2762492323fc3a4abf4718091be0945287c7329850e4f74462cde", + "0xa2c03c2e5f4e9d3ef361f68b188451994ad1b24de9f323370559c8abfcdc7bffd289d92e78a5f6b104b0a12c84dab2ef", + "0xa22b4771116ce22276fab1fec6826610707ce8a342f9f60b079c4e0259dac3cc41c96c560dfd0ada6edd2828f7c0e8d6", + "0x97c17441d0af9be83b42097aa8b7cec84a253b9a2b957214b8fa93c26d2add46144faffa7b8a55312059b10690f711f1", + "0x94bdf348849f31a2737cbae5e5848aee711067bac85c11c2e68b44c398cfafbf3493a3226cd1ddf7a916e7613fc7b6f6", + "0x838f59c6e8469a8ec6fd40b978a3607439aaebe1e50ff707eec72c0b8278af05b477bf12a384b56d03e3d4eb91e56f67", + "0xa1940f0db58185e2b3aedd2b0bc2b73b4a65c68e09b046f38e9dcd4e13c94f5406bea92635190bf315e48ec64eceef2f", + "0xb2f4e0ae44e1f1210a91d8f280f17091fa994034ba8c991583f8182a323e9b3001a712e3584fc2d64ecbf2d319d076b2", + "0x9342b89c721338d02c7854cd7466fb24d93d7313b6114ea591e6607439c8ddb911d1cf35f01898e9c557982bdff8f9b6", + "0x8583fcab15be1dd14d5a415f4b14d706c8c62f058500f1344b37730c8be6741779691f87ded3cbcf6516468b373cafb0", + "0x8fa9587c7989646571ad9032f34cedd353caee14f5be5cde1e9e0a1710f90c08faf6fa96a60e1f150f761c9c8ae7417d", + "0x8d9ff904cc08141f5a9879f5f77dc600e6edbe859082231a4d819953890199bcc5f940b730ea688332f07e5279d49e1c", + "0xb5f82b46e5ef9a2df8d144202d6e2e4f3bdae8e2048d2af5ea7deb3f722fbe6d370401954e74ff0d8cb1010ffb1f38d5", + "0xa3b5b57d435b06ed70530e060002a8fea71746ad07d969ca23f22b5e52624527595b6a6d54b4e953fb7b7596bac378f0", + "0xb90f89390df6d4b7879b915aa3c29b8d779d035033f8873bb7ac54a14ec98f0d08c0e3bf696e2ffa7b5730d736f571f8", + "0x8e81e371b92887e43d95c0dbdcc9575282b26ccebdc8cbf46587e4f2a83b61e9bc0c6d7d1f114b9d21e04fd6c180b12a", + "0x8d682947c51dffc6e0fe0a486293c9ed121f441805168236393087cf62f2a429cca60bf0e472564844347d32c6bea27e", + "0xa8341ec7dd189fa7168759240224192c58209b53fc961c18082deba217928c399bde08ceae42bffd37c1135b4d14a845", + "0xa94bb076dcc5ee5ec82fac57c5b384c690df12631882bd1b960e1eb8c04f787bc22b7bac315b9dc5a8a098f17f051a0b", + "0xab64e1c6f01b87706c88a3bd974454a438722768de7340b834ccf93ea9880c14ee7c2181432acf51f980d56de73832ee", + "0xb7b0058bb724d879e5ad7aed6230297c54cb599ef659e86bf2cc84c38225899fb388391df9b2e6fdf063171937fd8c72", + "0xae856f4fb74c27cc98b67429186e7df4feb01278cd57bfd3170af6e52e0a23b9e926bf9565a890cfb4ae8f2d590b2cd5", + "0x804b9c6702f0596d328f92fc1ed5a30a7ba17b9204524135001b569233fc4937035031d079f52fd04968f37c24013898", + "0x84274ed1af6bd6a968583995622b4d18c6a2bc703ce0d0edce45bb736529b4836343dcd11911a94a134dca7877e6cab8", + "0x88808098463f7505034c3b6328c8a08186b33f7a981c08376e429dd64b79b97753170531ed078dd265ded4ec0a1ed8d5", + "0x92823bfb23a4eb84d3759e7d717f0c8641ece0927cd2ba8c728c26bb35df2629a838002f353c8d3d75eb19520aab5f25", + "0x8db36bae4d960cdb9c51f419d7ddc81f372e56be605bc96a9d4072b829f05527c37c8f255cc6115300a2a0d2e6568d89", + "0xa8fcdbd7f3b4d7ff04149a209feb75e97149e7efceaa42d66a6b8e432590fe7bd01f1a77fa8b47108f670b612e33fee9", + "0xa9f4c53c62db7e5dbdea6918862d3c6d24b5bd8732a218edf0ba61e9d1861182323d8ecd7bef8f895b42970b492f6e40", + "0x8b95bc7f07818f4d7b409aff8da0b2c2ae136cde386f53a71565cae9fd14c73c13cc1cfd79c0f97cd77839fb738c5b9a", + "0xadbd1d11adc756b51a571ddbcbf4392415231ddad93da09acfafee03a9e4f9e1ce3826110619e5271feadfaffce3e793", + "0x95d327c8bb195cdf25fd79c98f9406a6b0316214b1630ebcce95bdaeffafa36fc1accc6882e0e5d13a8db5c0f3c0e61c", + "0x8cb2f1e2fb25558869afdacc7bb866544cfdd566cefcd048b48d458a886130bd086ecb7600a960a7f2563c61cb326510", + "0xb3aa8c4bf5b933d89cd74ca7f7176d6624d562d7d58b041328b49d7562a30b489cb606abb3c49e85baf04c28e9cd1f44", + "0x97f9053a85250c420599827297453c2cfde087065b823d9e43139e6a9cac3a2ec40a1b6e2f0726bdc870fff215462f0b", + "0x878d5dbe6b881389c2ca126ff66d87127c9aaa3f62f0d2c1ec0ea2b279ac95f8a06710dce166415db227655e2345a04d", + "0xb2c33a6b4203e3ca5247f0890e475518317ffc44cfbb1da9a1ba02114e8b752bea618050b876de5cf3b1906140a64471", + "0xa56170c8313d2b5541a795bea9934d4425b185b5c409f0484df6f44f0e4bcbf50b860ff46b7245cd99c1cfa8fc1965b7", + "0x96e2b658e2876a14147385fc423d2702a3cb76962b6b437222cf9cea39ebf4bdc03bbf434b747866d4bf72b4ceefa639", + "0x89c4a74fa2f067e7ae49c84ef782c331bcc9245db7e941804e2e99d12e987b4d25cb827778ad4c3566c4fc68018650b6", + "0xa01d30cea7d01c80ff26650020fab02e78fc3842e2398a81b44b21d58d4e9816166ff4ed2418831fa995a28ff35cb6f1", + "0xb960c80b55a8845bbf24bc3f23b0110ca701f9544ab6a5bb7929330213cb471321e55c390ceca3e24bff69bdb0d331c0", + "0x802c5b13f22be7be0e5db11eb3be0f0ea7f9182c932265060ba05fba20ea093dd2810d3b969ee3e387e60fe6ee834e8d", + "0x92478f88ef7435d15e39a97916c736abb28ea318394b88678fddbbaab3eaf31776110936abad116a8ff6ca632dd12043", + "0xa6d3da0370c303001d5ed99d1db8bce1f26b0e442f0f042e36db9674e92dcd6e80465e772f1e669f99221caee3392fe9", + "0x938f04f70a8f947d6df2f0c0e9af3cce0c06edbb3c131970dd60884fc0b0a0959c504a2a36c3ff76dfe919905671626a", + "0xa7117e55224230822e9983df2132347eb7208cb6798f291df926ab51e04b1a1f78d5568c9a8924ee6f57426134360f20", + "0xb91074c77ad93fe48dc2b10c0c5a62ca3ab7d98345b919c52d84a9dc419b59fc1b267e1c2d4b2e120016ef84bbdb0cbe", + "0xaa175c6b6edf02fe8778762c9575581c0ee6efc9dbf99c291a41444a23a056b893be6c45333d907d0bbe9fb0eef84d08", + "0xad36dcb4e2ab425aa339ae464b038d550cb11186741dcf257f1b8b80ed4f32ffabbece45e2dc1525d4c3eeed819ea04f", + "0x91cb35c1ffa9cd5aebef523edb8325078da3eb5cf9e95c675a76446fc7692aaee6f949de064ca2f3e0f082cc3fa93e20", + "0x82622f9410c143a86bc4d756b3c7b324dc295231ce865de020d61cc0868f2c150a473cea3a5b756b36771ce1032415a5", + "0xa5c29996ad3a53468ece9356a5b4ccb68971ea1c89cf39644f1da2d4a477c2ea99bf791ef902b87c225d8c53d67c4c92", + "0x92893eceed1af34fa92b23dcbab175b6a0188a27dbac9ad3317c4e39955a763cb383ab13fb1c519cde311d8a4d12e8b3", + "0x8a093cb191b94b0200e38d31955f9d240e2be1edcd6810a2396a061f17c3ddc9c4f4d56766ddff4e121be7110e03b869", + "0x93981473df0cb1f4b47c7d9b64e3123dcf1593845b401e619f5d7c70b5dbea375d1ca43fca65845fcf0a6b2e0af43791", + "0xa6beb6b0697070f9562910add88d9ba91992f8da127b27be81868b1596d1012f09ea7ed601b4a6474c921a1a1a6d866c", + "0x92026b1ee30f2ed61c9f30337c3356844217926aabdff383c19ca3c21e0bc49811ca5b308012bee4ef250cfae1615800", + "0xac0ebaea6d35f84dac4ce648af096305ba68a7a0aea0a11ab2fbe3162075444a158433c98141bc92ef3b3400d6deb46a", + "0x83046f482dee24ac3ca83373f0d1b82ac1c4beda0f229a9011a81ec659ff5fc1fb105e219975b5c744308c77a24f71e4", + "0xaa5a312c47ff7248dcb9c6ffbe5a0628ccd565c07365c4413734d415cd4fb35772622ed833862dddff520a67c509c6a5", + "0xa02fb88805c34018ac33582e19ed0a7e4616acc3dd0867e5f21914c2031c05c6dca30b8b35b57c2b137750f3878a6f8c", + "0xa60528f1f14bf0c496491d46a0fbbd6c343e4eb3f1631e92f96a3c5e5c684091aabe5801df7a67f7c6dfd1b0d35269d4", + "0xa1fd8e7fad8ca05a340c05a051bb0eb4197eed345f4104629a9e38e234b09d789cc5537024615feb4a6177d32d39e39e", + "0x8e70e36c1aa070815440e19443f1f04aae23b1b59fdbcba43b47b94a026c82c8f66c5dfe54f826f4d95ee1930cdb8008", + "0x8234c1969fa7e9079661e4ca309b71b1aaa10f4372be0b963205c23a81f5a3d52ec08ba9ff65b37f832b52d631580d61", + "0xa18cb4134127fb37c4abca328cd0047378a2e1423490af2bd3eba9ffcc99ca81a3c22404c0886f21f65c7b93c41d7981", + "0xb46fa45fe538816de776eec086e040005706cb3eca097e290abfb6864e745c879868aac8361894f3c3564373ef9ad55c", + "0xb96ca43b96c59e95439f75d1e726a35a9362f0dbd34963b156e103e080a8126a8dc3501f9fd541ff3bcf4677f5c4a86b", + "0xa8e8c87c7301613818d57387009e601a7ab5cbdc2890f63d985c30c74f9cea2d0584c116baf0d9cd5594386ee93fc661", + "0xb47e4f1b9153ef0981f813948150f283b47a7346fd9921d51fe8e4daedaef78ddeb4fd467c2ccb7cebd9816243da1c6e", + "0xa370c202a99c8441ffe96fad0f801086d4d7cc7b960f6e98cca29ceedf492afddfd0f351c9c4d29ac008bc255ec1a2a8", + "0x8f5e6ce1655d1c059b006174e3f5a55c88e1821c97f9702ad8e8455d46c2a83ae4482f2d43edda74a835686ec45a8a15", + "0xa30421e694930a3b65d397b2720d5f8e1eec2b6e2bb5a28d3f9b0a84db9aabd83850268bae64c2b10e313cccf120151b", + "0x8abe87163046f7a9b18e2a3c0b66e258facc1b31431420e0b70354b7a60ebd250a784634a76692e7d6f4330b62114945", + "0x894f033cf077d4eb312e3258d9dca414356271abce1d6094ecce6d018c5fadb1c15d8d69451574ad0701a2876db191c5", + "0xb0923d64f88ffc872654e1a294bb1af8681689c21cf08f39afe51448a68e60a9a0a74ccce9969276a932a52c07d095a3", + "0xb9ca23b5be8725fae7fa710eefd45522889c50c29c26384e00b78a962384f0aeff9d15cb5910e9565da12a577eb7e5ba", + "0xb242ccf292757197a9f470f2d80ccddc48c7f1235ba026bc68a93be2738bc968e8a200aff3e2f4807216442eb3fc50dc", + "0xadc2c3b375b308524b79a024ff87d122055440643fea6fc0a651bdb312c7cbe6a456afa9d342bc76446d77d8daf08bc2", + "0xab645955356c2ebf2f3df9da275e01daf0b44a52afc309277d6d9ad1b05484e5ae0d9d41ad485fe481e5e362826a86ae", + "0x8de96ac587a4449fcc8b7fd0a51b4b5185d9c2eb3434f94cbadd092de1e26b0f6b3f7b15a37e8424b1429121ddca0ecd", + "0x94c70ad4e9b871566f3da98170b665a09788d421818299857cde0853789fb943cbcf7d4b2c95246ea7b72edc56a8e36c", + "0xb2574be63497843340700b701d5cc8be6d23125bd62058802ee67cce1f3b5f5602b27c93fea5611f27dc695ac563f042", + "0x869ec89da7850cedd88bcb3a50a15cece233119b31b64a61bf6b2310892ce42d8b473b584b11e61db29ed24ce8033f83", + "0x8fbaa269da8e28e9adf4c1b08f109da786dbe9cba871c32eecbfb10619b7a5d65a26f9bb33e201a8ed20b3de94003fbb", + "0x8bf7a059c37242caf7f821a6314e4e4adf799e0dd86b37892a7172598892c07272acebd05b534755c57b51556b2d610f", + "0xb4e72645fca459898cdd9214892ed08b5c99f82049c0a30d72bac0b9717caa9c6cc16c3dc7aa6ea4d42dcd2a6c175df6", + "0xa39170da87a3495da55bbb9701c5461f3403447174ed6a4af75712f7ba4ac35f51a4234bc4b94da888a0959ee109c0c7", + "0xb45675b2774ea7696089dbf7a0afe6c22e85fd0e4ef3db508fbaf96c9d07f700c991789206da9309fd291be696357c5f", + "0xb52899e3e3f6341eefcbe1291db6664bf3b6e8021d32fb9c3e37b6258a35c1da927747b2ce990937d6f4c6c3e7d020d2", + "0x84e5bdb3dfe19700d79dd3fabb0159ccfa084f7288db836c855b827613ce8071067c8d7ac5cc2b4e88ed7f84b690f6e1", + "0x801477d200b6d12fc6e0a9bab1c8211193ab06e44551e037a9b4c36fc2d4f67760b9ff4eba9a3bc7b6e177e891f64ff6", + "0xb6b71a5116d3c22af26a7530f535e9b7851f25a84e562a8f17a125d55b9b3fc1bd8cfe65bdcbeeb328409521e802051c", + "0x8687e21c34d7804c12489d30680d131ce2133e2981bfa993afd8a8eeda958ebd5e6881d342d725338659882d9f21cf98", + "0xa024e97a7c4de32b6383c34431994abc533ecdbd6be9bff836ec1af022f5a86773bf345c6f33273797a61fb70a8fd5d6", + "0x83f784f095da20ce5b31f54d6cb14b32a8a12675f0029289c9cd036b7c87a8077be2d04a62618685720e6ee69c875e97", + "0xb4e9dfe7cb9d9efd3fe00d99ae5e48769d4af4bf43d4e05c0b54c9cfd8bc854de96b8d3ebf4dcc06b9dac66b7471a0de", + "0xa08b79f9d4673afcf7f38b57f484f88feb7c908f597663a2417f92c348150c2be6b5603f914eba0d9d5bdd4e5c5572c1", + "0xb0eaf919589988798cb01ba0610cd1b7fa3c08715675ece8ecd5f9ef6d5d7b2c4c8ae1ea7dfd202237171aa3e6f9de74", + "0xabff99a98baae4dd0954052503ce81827781694a5ea8c1149f96a3adde75dc2d630e138598cd2ae7fdc7a654aa17df8f", + "0x83e369b8680d8b9d995222b033b4f4f3e3b20e782113c941325c7fa9c742feef8747e4a212d9aa23285a259cc4faef8d", + "0xb16d5855dd2716613697eba36e2fae0872aaea6999e91cf6552f93f9a0b85ed4f6ff922a91b50816bd6cf8e7a4513fc9", + "0x848373db600e32e741aa1d37726bbb28956783f89ce2d781e95fb1ee1adf4359968a141678af268077eae4c25503204e", + "0x93a0dd0fdac18a31875564505b4e28f9e8bb2915faae666538597731ac56cd77f23f2456461e2f672983fb24ad91f6e0", + "0xab1ebbe49fa56524b564bc2e43784147073e6ea5d27a9540fbf2e04d0f87c645ed2fd28b3e4982cc4c0af1734ee47a6f", + "0xb3ee30b733839edab6f61f0738e3f4afaeccf700d8dc7415684f193b36d70d07acd5780cf539f12e0fbf8d4683be773a", + "0x88388f2cbdec47a6b3ae460b69eb0d2130ac14de950c22fd86de03e40d02292bb93cebe62432da39d509c1289f785fef", + "0x9370c41a54b68ff486b4cc6329c3a851716ebf1d088d77a6c56dec93a18b8a77b596cde74cc17d2adb2b2f411a2e4bbb", + "0xb9083b60dc16531f77b05a955b51a237a8f8c0173d72c352c5ca441b55abbc890b14937e457aaec4be5cbbf80cae0099", + "0xaafff8f6c6ebaad952c65054dfc7c829453ec735331bf8135e06406b7a9f740c9a200dc48bb2175516b41f77dc160121", + "0xb43d31fbbaf10526809e9e5bd8bb47a76e0fabd7852ee7744404559ab89f0f215ff518f3271a6aa972a459cab82ac558", + "0xb581ede48c6ef34e678f91dc4b89507413e00e70712e3e8c32a80eed770ec8d8b98caee9702d068aeaca6f704be57bd8", + "0x8cb0a137e68b001a5ccac61de27cac9fb78d4af7b2f5a00b8d95d33ac19cc50c69e760c5e0330a85c0ded1edce0fe6f9", + "0xb947fca07c7aa6c2bf13048275402b00b77b28f1d0ba4b589fbcede13f93b5b931c588560ab8ceba23bb8e748031b55d", + "0x81753cced5ff819901740a9a584334e355b497cb699f0be5a52cd555a4c9f149535c7bb355b54407f7f0ec27de6c2e19", + "0xb3d59273951ce97838c4853ec329782a255b5fc7c848e7992ded1be28a5ada7fa3254123afe32607b9991ec6e0659b08", + "0x86b253de246f82be1cb0cef01e87c3d022ca1829d2cc7e6a160a5afbd3ca6b94d75739b122e3bb16f8bde28a8f3223ba", + "0xb728b659fa2d8487e061a37f7d14a4c2d70cc37497a8715695d8d332cb274deee2ce23b9b5f6a7408516c02c3d526a49", + "0x81277b46d98848a45abfbe39842495659dcbb80dee985a4fc91d77d52b815487aa8bb455f411fcce4c3879c7a075a93f", + "0xb05b6f1fb4a6e654f0ee6b83e08b58b57059bb0b7c490405bc8d963c4a2d6be39c558917977e554e1e9e3169961cbf3e", + "0x88f75fa7d016fb6442551ec071cc1e2beeb3ccd213d16d744f573a82f5d70f41dd1b18af71d5f9e73d87f2f6b7dbe889", + "0x81a46434f1bbd65a661a0ff45a0295b8fd8a42a7969c5953721bc98698b64bddee3f806876d1e9983063fdd0c11f99df", + "0x8b4f6d33c510a4c9c7d623d9ae0c9aa631fcb987704726b2a4d8519372123bce3c439202f25b5b47045ec14ce39a21a8", + "0x8d5112b330fb63cf6ef3d2164b404c14ff9907d685015701399a260951912b19b8f270f869df317e9050a127763d7980", + "0xaadab394e84dfb82db15ecd2427f39b62352c3e1647c3bcd14fb24ae830ad0116f0fed87ddb63963b424a4741961386e", + "0x81ca4e5600d00a3bda24cbdea7a532a4cbbd893c10e7ff10667c15ffa8138b91667abe5466b31a3dcdd60155c48538c1", + "0xad943af1b8a5fcfcf309ed8f2f916339f254cd555c71a407a47365a139306286a05a8314e1c70e20a65fccd75d36fa12", + "0xb16597a0b437060a390467bbfab94c0bdd695ae898894f4689f939e30cc2119cc08ecb594546304adf876f4e275ebcd9", + "0xa44a4e0a6693be356065891c27eefa040a1a79475be53d54d5fdcea7e0668ff9b35f850974000ed119f6865aa6faa721", + "0xadef27d1b6e6921f4eaf69c79e2e01f5174f7033eaafdd33edcfa5119af23f3a834ffe1bdf19576581b797abd1865b34", + "0x90c1e9202f3ffe28f8e1f58e9650dc4ff4dbc158005b6f2296ec36147e524b4f2f87f8aafc39db5b006fe0c491c92f45", + "0xac817cd54288b6f7fe6338415344fc9e7b669414051631ab2f27851c052c044be06bf7235d668e194bef695923256368", + "0xab14944ef653a14456d4ebc12e3196df3f1b4707c4e50b317b5ccc8ca3a0720f0330609f0e7e71793f6ca01583f38c70", + "0xad5353f2f380837e5ffdf079350b3d42935a0517861d03af98db5ed3ea8501abd68885c8c65f5a66e944b1874826a450", + "0x8b5583863f84af8443ce8970b02e26cc5d959e47efbf8a66a54106ab165f1f76b36423aee74c7b5402fd1c4d7c1adfe6", + "0xb3b46037eed9fc30e4f8f0da8bdbdcc40a38e22e876ce9fde981883017854aba82c18eb00887d92ad847d30082fe7271", + "0x98a2b6fc90b7ad172e4368c1e54675b75c8bf2096d91c9f2b60b3397d3be3b705aed5389845dbd68f0f84438cd0f7687", + "0xb155e800852a5f90a2eac69cc4483428da1dc2c31588a13c924e60a7616ce9baeb7d4b829c772b260277cadd8ed84719", + "0xb8b92c520a1302b0cf7d993a52e1dacd7f27bda9868d59c55687d995ae676b7070af4c0792a9bc1c2635d44a4fee01bb", + "0x96dfe9bde526b8fc829eda825f55168b88e8f4e43d4d708cc3060df03437b46e12a8ac70d7788aa75760f6294d3e84d8", + "0xa3fa66c54e2fa084ced3bd838614c6c33042f492a5745d167a723c60d5e7d6020ffd1747981a23f8b68df21ad8f0fa77", + "0xb573ca10cc41fc04a642f6f62c355a4fda69b94b8e95dbb02fd1ccce4bce1191356e1fd66d372159944eb36a7071f005", + "0xacd0a1c9abddfd0ea223eda1722aaada362d34234455bd1c6be115d41e535b16f12ca428da7820a757fa4c98884a385d", + "0x96f242eee99c4db383b8754fa7987c0c159652e1866faec905a8d3f010e0a1ad05bd77b9ea8dfd653738959180f58430", + "0x9215a9b672a5d6e435e0e0a45156e0e20f75cbbdf1d14940fed3ddb63d433bef643796c7a4fff881829ebb2b2eba9460", + "0xb8ad9bfceaf08dc5a874387219ddd1170bc3a5e25ed72d321d59ae713be5ddf9fdfbd3aa7ab163be28dfa0dd14614e19", + "0xa19a1050590bc500b32c502f393e407abc3d8e683d6f6b978873aff3e3299b18b1f6b59e2b0fe237d819dbdfcfdc98ca", + "0xa6870fb11d4429686e52e1f44c8dcfc7ea24a020df9570c021578dbc1f9bdc8cf797cb3a72d7fc52805dba35d59f2cd0", + "0xa7be733b64d5c06c127bd1c87250e42bfe30ca91ed8ce51e0b6e377f454e8f6fef7f99bff650695df2fd10c375da349b", + "0xa1b97145dab30330eea2cdc8739b2446a3704b64505fcea3dd8a9b4a72edf222e98d967d6fd7f76794acfd97aa091065", + "0xb2127049907d2a3b654d1c940b740bfba3dbaf660f86ea79c2f909af7c9fe2a07a1caeb1be12370aeffaf8faa50f1582", + "0x8a207701214bb28e99b0784e9228b1c34afa701966267fe7110f6f29f5bb41eaae6cdb98844d0400787978fabd224de8", + "0x9925147a383b6f5f814520220ffdbf20b214225882c3ef49b1a1ca677709176ec82466fb9c4be2dfbe5640afb63b014a", + "0x8416ad93871623fb555b5390b80de99edaaf317350cc0c1ae9d54d59517074d40061f315cce8ba2026d9c1e6f6a1009f", + "0xa315f943deebbf0a2cdbcf3f8323e215a406e9cbfbcc3f6288714cb3a6befb1bf71b2a21ff7a2ec4731c65044c45b6b5", + "0x8213e0c2539c24efd186ffa8b6dd401ad2233bc19166a0623b26dd1e93614bbf792823f5599ac116231e2efde9885709", + "0x8e5cafd2f34a127a4a896f05e4d929eef06972a1826b3566446942198df26d62f7679b987db2b3765d9d8058b1cd85c2", + "0xb5302b399c9cdf912fd59007ad4737255552663b1e56dbe64a7b2ddd88d2093c73ea319b45db2dd49d1e03f5bef1a0ae", + "0xa0c2bcfbed4b008e1a56e5d2f2419aa59d7dd0ebd990f1c18588de702ad0fa79f445d69965fa9381e700eda13b309378", + "0x80a44eea1ffe24c26b16b8e2e70ee519258b9ad4b3e83cc4e5cca88ebc48d0160066f8b91d0581095b0de2428390c8b3", + "0x84a90cb9c7d2f799f1c4ed060387a4b793ab41c5c3eaffd3b60face9b9c3bae93cd2017283bf3de1e3dac63d0d84dd42", + "0x81d22febca276a05ba9bbc5591ee087b0491beb35b4d9f8fc0d041d642a574667ddc57660b20f5c568f7d61fdcb41bda", + "0xa3ac965ac27a28e102a439b74fbfc157e75fd57620e4c0750a466165f8aeecb2191dcf8e656f7525aa50d9c7c69b0b5c", + "0x913c17434ff0d9fc52e2ece4fec71b37d4474a18f3ea26925c1be2b250434d49759f58033ba0fce1c6862c6197930dc4", + "0xac430559c151a5e461f67b49c7786c97e1653fa8698e9759ddbdd99f5daf17fc5a012ae6330739440880728f24eba7c9", + "0xb10d8e9f8aed9361b042d1398ec74364f7c7c1cc5c7f917060572761138bdbe89bf409389ee3879f93bc8032dd67b308", + "0x937271005a4cc6a6ec134870c1b56471aa84ed4f4af1b3d5f334bc0c42762fae0c9a6a2828d3de6151a76dad7b72781c", + "0xa10e4dcf51889f69e6bd4c052f8d4036b9571ced98a3d7d779cbcb9fa5c3a82228566ea7cc1d012bf56dea0a40c5a64c", + "0xa0ed026528d9a8bb3201bc9dcd20598933e8c72fd315deea8da63d06e97392aa729d98a55a8a60fa4d5573513ba5c9fe", + "0xb723fcd04cddbd4c36feae827a03746ffef251c4f4c55a88beedaeeee194430a99f566f483668a0d88b13e7a4a37f1de", + "0x84a2cdceed44828c7c05a6a762edec0165e434e7029df617d6646aba48776e6c3b823f40689cee136536f8c93e08a629", + "0xb786264e3a237ac3a1d56c9f4e87438dfed620c867100fd38b01287f5b755c7820937403bfb86644e082094d3e410a00", + "0x92cc35b2065fca157c7bba54410f8bd85907a01c9f760aa0ddb7a82cb55811d24cb4dc6b725367a6a1c293b809a48ead", + "0xa12bbf22b117f00164a42515bc57cc9e6c43cc77fb737ee3d0c0cad94cb50cd3847d61cab469cf8ca76f7958bdcfc771", + "0x85985b00de533bde2a757eddf53be79ea39091d16af3fc92327bcd1cd59bf2bf4411a334da29ad775e8ffaf3cea7d7b8", + "0xaf9eb24185b0d330d0ea1d0b0fa78af0dcf42ced81cb0128f16cafdea687a9c5582bb6d7c5744117b271cd0b3303f0b5", + "0x8c8aaa1d85ed6327f85d579767c7a9158d209171b3efcb3e8a9d9e534c078e821b6aade255101d2c9ef6d67ba66f10be", + "0xa450518a03ffb40e1df89e0f88fd55b5b06f4872cdfb7ec55f40dc40d9424b3b289866336c195bdd54597d95569e0096", + "0x81e61cc69f93c435bd77f155e80626a9c764dd92b6c76af15c41346527948d8a6ca87d6351a0fe7987e2ee3aa66a9625", + "0xb615e0cebf4fdff4cb23a20c8389c370915ba26aa703b28efe4ab070b1603d1c5b6541684acf46b52a915f6aee447539", + "0xa7f51885c7a71885cc84ef734ecd107e8bf5f7a25131415f671d143cc1de92859e65001125323c7985799993af6c410d", + "0xabfbf7a46f32066989c32f774edcc68163f085ca81e94fe8c9fb32f8d451bbb2c20ac45cd8d97f9e618ab40186933b1a", + "0x8cf35a522b5cac1934004aa9dd236bc77198d43272888afa860cfc79b4b28dabf7a3c74098f84510897566fdd609aa45", + "0x86aa927df78f7a06a4985eb0a4f0b93529cef14f9fd2812d46abffbf25e618ead14d99c70e3c3bb2e17f3f7fabc9c264", + "0x860f1b4f4a398e9a8bb4739587cf96979cfbbe1687b7e91e5bd1198db726391b09b1a261bf12e96698818f60b5bd3537", + "0x8e7c4ee19ff115881051e8637dce1f5d6c65e865d0c757e8ce41b6d7bcd86c7070cce60649692bbf28c868c7e2e1e2f4", + "0xacf7ba01b0220419f09169ac8d16e5cc13dce08e88c90b8fdfaa33aab417f011a20b79a178d8a9f7211589d2e0affd7d", + "0xb404bde8e715aefbb9f20a353b911b79173ef3e2cf0aba98b5ae6190b90597d65043b0b4e014ad9ea6c77da2d213ea12", + "0x97e3615d1c77a402253bb55da2d1cdf82de316cefffe42b1022c94b4818d6dc4a313731db85321c537914bdf716a875c", + "0x940e950b96a4096a578c6874d747515936652b9b113a5f27f5a834a610867b05f9881e2679b0b289b8527baa0009b6dd", + "0x8de15a13ca236a3a285ce6e6826c502ae7365bbe468b6e8ac67b15b0bb49be0e996f1eec81ef69e4b7f54f8e4779a054", + "0xa12244777eacb08ecd42b5676b3a51153022ab97e9353ace0f47c6054c22de9ba60d2a60f59a36841c2a791cb1b7c288", + "0x94f7580203e39a2642ee2e7c969b9911f011d7f3a90c398e1302d26edb3df03df1d0c43baa1c6cf90dde95296d49e742", + "0x82ead33144aaecab965faf63af384565992f38fc1066e71e33d53f43ac93892e27fe78c4eaca1cccbc53364e26ff31e9", + "0xa0c129e9706d354249a7f8aa664ccd7ede89aa1445c5547410814b56d10dc086720953363ab1da8ff5f1ed5d8e575104", + "0x93b3057bf3f74edc95237781ae012cc4b1d3fd0455565ceaac7110290aa518ac32478ba4eb9851555fa87270fcc84f1f", + "0x949c2fd0b94f31f7cbf00c679bd3f6ec1a2f4056654708d39edf1a450b4e19a6e251d0bb24eb765087e698f61d3fca2c", + "0x99fd2e50e211ccb66b895eb2fc42f260f3ad5767f04c2fe238b81dae98aa6e3977443a51f4fe7b43f499caabe45699a5", + "0x84fe19626503218f327b5325bfd7c0c3d2614b47d34964aa0259d564e769c6c81502132cc1765b0b31fbe39852706927", + "0xb43287ec29d9010bec4284de58fed48dd1e129bac79f09d45153c9949131782f77b11b0c9f8ee06a39e5e9bbaa8e2c6d", + "0x908902f3ed45482df2f94415fc8e5a308057a40c8905d7cbbd58ec4848e19276577b7f7e69e5e684a8b981738e10f7ef", + "0x85cc7d9c1eae372b4f88758cd6e21604b4bc9f0794e1e74b6d9de96347f81944d01331385fae7a38e5f6096c1dc23465", + "0xaf60288c702082fc258b3dbd6952c6b75c1641a623905f491b1e72f49b9d39b33d150a336450abd3911a4c128166acdf", + "0xa7d8ac7e589558c4014369ab6f4c1f2196205b03e4278152ec0dbbd7ba54e803c3369a71d364a773aac8dbbd117e4a13", + "0x9833aed34e48c206e9328073597aee1123f5bec085339b4e6839a389a429bf3042798a31fac1464ce963204adface76b", + "0x84631a4f012bbb62133030224b57deb32dcf464cacc8ffde7775adbe68707263ab5527a1c75e597e03aa703ba658b889", + "0xa686a61f6467858a2a4c13e70ad81b1901290d3e51bbc0c6e366f9e652f575e91b11c75f640ccef8b0c6c1b05a43c9a0", + "0xb585f0ffd5144907703b41539bfad7f9f058f5985f63db911064ba6b07af8da2796b84b16db42b8d11135c3f846cd9e2", + "0xb525539516c7bb25f1d7e165f269dc8c9eedbba74df44887e178ab8fd798e2a31f39812ca922d6b64d91564f14012a64", + "0x91e480d7568fd2fae39c35b0a8d623e66a3160fee1dd4e9097255004938b11ac1cd3918dc6a1e5fbcb700c95a547e5e8", + "0x936ef55c69b842b6177de71fa48dc5442bf5132116b214302f8f242ca36a273a6bbfbfaf373777104dadbe8e7da5e970", + "0x8e950c0f6688abdff8a3b8bd77be6da6f2565c7b55711f5860ea62a3ab1d51aac31821c602bc11a45e33c69e7dde3ea4", + "0x90eed4595104a0527f8db1e028ff622ff70db4eae99cf47f6c2a0246ec7b103570a6a9a877e32e9647cc74969006743d", + "0xb756344f6c4ea05b792e416d9bd9ce9dd4bd904e7622761f28a85628506bfc9d88a25e5f04db62fad30a92fb1d8d8556", + "0xad79ba76534c1a02ac3e9b7308d390792984cd75b7e1d0e5e4ff123642d99d4ea1825643091aa8117336333c40d5bd94", + "0x832b08144887de0c0341d84f6945450af8d7a4eb32367d7703118186c1be525df9382ce61fed5f3b65a0bb3449185f7f", + "0xa322fb944e46d8e47994820890c94af423674716da810ea1da71e0a7733ad72c22114ca39a4b59c98ce4291a5684c154", + "0xb982851a65140dbea79bd3b5487e236feccee051deddcc17c2853032efca289ddb6eaf64be3dd85a73012fdbe9d2d4f3", + "0x8eed5e230e201830b44b9fadca4e156fe1a16bf840cf29da0f381ea0587b20c226de2465c67e6268973e776809af68e1", + "0x81c8f1c04490f36e41a53ee1b5185cb8adbb37c258fd6c3be8c56835bf574c37183a94d55b6554fca35d6e6dd9af0133", + "0x8c4928724107cc16d36f2976677eac0b852fc4c3c0bb2f9cd4d59cd24a113faf33b2faf405c3fcce25be51d41e42c2c4", + "0x8e4ba842636fdfc4d71f0983538ea5037d420acd26abd12efca48c252eea85544b2fa9fccdfec4e7c2a6359baffa112d", + "0xb4315b84700e26dec26f3488d308430fdff4809c10d4c24309627911cbb769ffaad0d1ecccd622dd02194eaf5ba59f91", + "0xab888308f757faef32648c1db01650dbc9aea248b09d06e6efcc996d395f48ec96f2d54a02de441d753fe8737862d991", + "0x805094cfd77e207d5c75f3cad99f41f763ec15443052cfd758c6a82ba422d831a1103a7f9b100da49c28198279c3d3dc", + "0xad857f33243e4a2cd2a773700def21fc7f94939d1a6d2c2125ecd58fc206ccafb07a2c02a1cfce19857d3654aca2c70c", + "0xa4d12d40149953daa70b89a329e918e9d93efb4e8004a9357fe76682dab9662c8507e16db83e849340f05cdb4933a373", + "0xa0dbac2ed4b5d03606524245e8a31080eb5bd3e9a0c51dad88c3b18e3e6bc5d64953a81c8e60425b80107ee6b62b1fb4", + "0x86da05355900f327164a78901f6e3db857531b33b1e855df1a67a9ba222c6b05fdb6b0ffbacaeb1ba5b45ff8979b6b68", + "0x932c9873aa3e226dd922b5a616c75153bd0390ce8f332a414b9c8cb6606c2501a37a2aa88097bc7d8e2c4261706eb38c", + "0xaccd9cdf07ccdd42033ce3b105e00bfd39e2304b1e3d66f8b1128645634452c20f759ec45adcef2fdf04408f62c4cc04", + "0xb75cfdfc1cb48918752eab17eb579820ee6e71e6667abdb64df834ffc8c1362fbbc23ca2c80dee248fe1fbb72d87dfc8", + "0x88b998c73b00638fde7d3dd650a08c5ab996dac6ac34251337fbff3fb5ae4a25dd20c1a16c987ad7ded19eca23cea891", + "0x8afef0956c942571a27f504553fb312cca9e50ce41b44e0466d0516c5abe4d8acf4594cdb03b1ccdbe3f2e6a9093b713", + "0x9042cd83c5ff261e9ebda26398caa16cac2cb840d19062fa8ae50e044c27104972948318f4c866dc4d578798272d3e49", + "0xad536719a64570a2cd1d72b6590ea1d02c8c49f259a7867be26c8191445165954bcfad50ea12688ace3fdfb0e98143bd", + "0x97c86328d63d297b6bc9718dc1ad5a05b908a750d1c455c700d84315589128ce4eea958aef2bcf0fcf4adbd8e3ce58d1", + "0x8e592cf0802e6a9541eeb654dc55055e11f3d757847285197132935ca35bbb1a9156829a39384dfa6f645ff89eb36738", + "0xac16c614998944f77590bf3913a010e13f2d3bbf6a172293baf5983506c1a2d89989fb72e598f5bba1ea10a691377c93", + "0xab8e6f5b46baa6632de3621497bcbdd584decb999fe7d8a3364843a1e0b76497600630b6a24dd30119d8bcbfca29f335", + "0xabe1d3af5279e60122d9cea8cc6581c819d7a0e20e3715da0f6da7e02d13a7653db643bd946e2fa9ba338eca81fbe140", + "0x8c33bd831ecfb18d1d0713e16beba768e9c42df62170c1f8a16764912be77f2ac5915623d1d25e8c462aa9c2f6669ca4", + "0x903692becae4a6409f7bdb127d9b11de57a5739fe24218dcbaa0092648d5332dfeef29a908ee9e43e5e0a51a4c3639bc", + "0x92591e90347ae286acd365eba32cd9ad8f20f4c9cad2dc579b195147ff290adf0d776bcb3d4b04a25d68a941fc0c781b", + "0xb64bbccf860299aec16e1f95c768a1f337c740bde612e6ba260e393edb8b04540127194761c42597abb9bcb771c576c3", + "0x9194f056ccfdfeb78a11c5347e2255d7a7ebd1251f9aebc0b58feb68d3e03a7dbbb74e3ef7309455853adfb4694bd01a", + "0xaa4f15f6d6a53ae65b7f6f91e8981d07a5919d2138679a561f7bb608dc4596e45ca06c9441d51fb678b2ad89ae7a17ae", + "0x90e3d18507beb30bde08c5001faf489a19ab545c177efb3f73fbf5605f9a0abcdc8bfbc44f832d6028e3e0a834bea98f", + "0x8f31dc0118c8c88a6e79e502d10e57652b7aba8409a5bf572ca63fed6b7cbad7f28bbc92ac2264f649792fc1d0715085", + "0xa307d1067ea4c56437b6f8913aa8fcbf4a24580fc1e3336e7f6518f0f3adb9c4733090e459a3f737414ec0048179c30a", + "0xb7cc41fdf89595cd81a821669be712cd75f3a6c7a18f95da7d7a73de4f51bb0b44771c1f7cd3cd949e6f711313308716", + "0xa9dc74e197fe60e8c0db06b18f8fe536381946edecdf31e9bd90e1ebfcad7f361544884e2fe83c23b5632912ec284faf", + "0x8b3e1e81326d611567e26ed29108f33ddb838c45bbd1355b3ae7e5d463612af64b63fff9fa8e6f2c14c8806021a5a080", + "0x92f6537bca12778866335acc1eb4c3dfc2c8e7e5cf03399743dcea46aa66cac92ac2963b0892784263ad0ebe26ffdbf6", + "0xb5cc0061f7a3e41513199c7dd91ac60d727366482a4c7328527f7bd4fc3509412f711bb722b4413b3736a219b843d15d", + "0xb3e9711d68d2c6f6e2cc27e385d5f603d9a1c9a96edeefa1ffdf390439954d19504d6aadc566b47e229ad4940ef020d2", + "0xa09d0d3f0e5dc73a4a0827b72710b514bbfce4a7fcd5141d498a5aad6c38071077f50d3f91af897d9ab677b7041dedda", + "0xb177fe260f3b86e9ac21f1bfbe2682ae5dd8c9aecebb84f37054bdab6e39094e611ce582210ceeddde66adf759dadb6d", + "0xb0ac6595eba9f5dc4b2fd21856267cfbcfb5b12aa34ec69ca32b80071c5b652e85c25a224d80443d503bf25fbbfe07e9", + "0x81f3c0e11b196bd4a2e8f07f8c037002566dc9037da81f3988add458a520c24dd1be3d43d851e28c0c6a85de4b57a542", + "0xa44308c95615f7fedb2d2127012924468c015df9f48359cc2e36ab4223870b0bfc1e9040baabefdf5266f93afaad896b", + "0x8493ec4c32d5a13b81039f1b436eb83f259945dc950e3c6c2ccf5087ec56dd2f60890ed4edf01728b6a54950e19b35c6", + "0xa1a439ec2a6a95bdac9aaa925ff337ba956c0d236ab5318354270e73ed6b73b4ae2d27b4c1686cf97b6526d04e65be81", + "0xb4659b7b53c55a4b2bbe210b53520b392f893500e18990d843b72d7379d45fb44dd1dd2184348d6fd853d6b9ecc6b7c6", + "0xafb2c68d75d00130b0e1b4f250001920213121791698ec04262db714cf7b1408d39f6cc10421f954845aad5b8250b77e", + "0xb22b843b40a97210f94043b552f348f66743055a3f274856a738e7d90a625b80e9bbb80cbbb450e1666eb56b8bd5c60f", + "0x800895ced82fe13d5fff65a93b0051c3df698bf1221b682accfdb63e3970f669ca37025750697f4e8ff2a3322ad57be4", + "0xb21f598c50d7b9f4a584d548f85e42055ef8e24991906d973749090261584c7f4f5e984b528926f7e75375dd84d51af8", + "0x849b1c68192d18274598dd6d0bf48fb5ee3b1ba25b331cff2d06f345bef3bed49760ca5690848cf33388f6a9a32cd646", + "0xaeb6fd9478b10ef456f6bbb1e6dd19b14475e65497772d12cfc097948383d3fbd191bf95f046b8bf1989954118e483d0", + "0xb1b5e0ea2835f7fc8b66e7731e392b43d16cbce04b52906b6751ab1b91978899db5fecbdabc23a19dabb253005468136", + "0x91b6b1284770cf6f7ef35bc0b872b76c7763ffcfa68f9c8cfabcb2f264a66d47598bb9293f6a40f4c3dd33c265f45176", + "0xb9ffed029846487c2cfb8a4bb61782bd8a878f3afdb73c377a0ebe63139fa070e3fcdc583eec3a53fdc5a421ff1fa877", + "0x998007249d041b0b40ff546131cfc86d0b3598dcedf9a8778a223f7ed68ba4833b97324cbb1de91292b8ff51beab44b3", + "0x8eb77ce9e0e406bf6f002870fb2fd1447646dd240df9bd485f8e0869298a1fc799d8a41b130c04370e9a9cc5c7540ca5", + "0x853db8157462c46f2af7e8f94f2ed1c9b9a7ba2896b4973296898ff3d523d6e29e0b63a5d26cecd5e490b33c87a4cecf", + "0xb1436b6f3278768f0979ee852944258f2599977d255bea6fc912ba17c5dff5bdc850cf3e1fc52be9d6d188e868670f4f", + "0xa76acbc5832019b3b35667ab027feff49f01199a80016620f5c463dfcbfb51bf276ed17b7b683158ba450660cc7973eb", + "0x94540cdb051faf3ae8b8c52662868c2dab66bd02505c4f5f8eb4d6b2e2e5fd9a610890c5dcf8fd887eee796d2b5753a8", + "0xaa35099666bceccf4eb3b65b13bba88e30a8be93693ab6761d8e5523343e8d6dd42d977e66499352fe4e9e9784a1dd0d", + "0x894471aad17be54319083c4b5e40adcfacf7c36c4aab0b671030b7ef321c53590a25eccd836efd20f32a93185fd315bb", + "0x8f52a9f705bb0dea958fcfbd52e2b6c08ad0f89a07a6b2942c1b4c37eead0d97a38a9e9aeb08d5d59b7fa2a9347f738b", + "0x9031c16b4f936c9cab55585dc5064739f696c3347ee2c0792320c9f749e760d120e396e8485ffc79d81c9f3337ad3d1c", + "0x82090a0d0d9b05459ec1c328ecd4707c333b784e3aaa0ef0072cee1eac83f9a653a75d83b9f63512a8c41200494826b4", + "0x92c3a9553001f9ea4d67236b8ad1a33275378202cc1babc03f313895458f4b2549bfbbbdd37bfb8fbff0decb6b9f820a", + "0x88651868f4da37338a22bc553388df5dd1dd0cb78c4d7d07c637d8f6faef4bed72476fdcd4304d5bedf3514011135f08", + "0x83fa0141bfebd88063f1d787719721b4c6b19ecf565b866de9d7d5d1a890e0e3d859b364bb65f8f8e688654456a40263", + "0x90a7fab753e5d56dfc0e53a6b4e6ab14508220f3a62b3f3f30570c4c9ad225e74122635826c92e8e3227ec45e551432a", + "0x8fa375b0345bf6e5e062d108f9feaec91029345ecac67ccf1264eac77b8654cbfdda1f10579f481889c0e210254eadde", + "0xb83f06116da9daebdb013b26724523f077debaf6bc618b48a7a68858a98d275f7899c4ec73a0a827219b9248dd81c8c9", + "0x8be1cada55e0c5ebb4fd460b2d209ae5326285a20c8bdd54ed9d1a87302f4063c8730bfda52d9d40e0d6fe43a0628465", + "0xa68ad6f813743ec13a811f2ef3982c82d9d9ac1f7733936aa1e122f8dc7f4a305cc221579ab8fc170c3f123a1576f9ab", + "0x8878f1128214fdbbb8a0edd85223741e021508ab6d36c50d38680f2951ee713ea056ed03f62b9461897963d50ceefe0b", + "0xacc0d43d1b0260528b7425b260a5dea445b232b37240759fc65fe26f7c9d8e51569c5722bc33e94de6492f4ba1783504", + "0xad80b1dd717b076910ee5ceabcb762e75e4d094dc83b93b65c16de1f75bc712cef223c05d5579c1561829406c07a97d9", + "0xa6fc9803f9c09d95fc326cc284f42ea5566255eb215dba8a9afb0be155ea11bcc55938b2d16f01cd2f2eda218c715efb", + "0x83ad733dbdfbaae8095a403dbf09130513f4ed4f08dcf8dd76ce83d1ea72999b7eea3a7b731da0d2bc80a83c6ee0e3e0", + "0x8748912fbd08cb34a85416b0937d9c4327e9eed20d6e30aeb024a7253f14f1e0d774f3326e54738d71aae080e28da0fe", + "0x8997e78d8acf23051428af67183ae9b2c4aa42b503745ffe33df35a35103c589987e1473ab14dcd28ee78ebcb10d8e95", + "0xa2f340502a7eb3c4a36412e6f028321372c4fa18a4743945607424e932af1271fa3e6598a162c872072529576eba6283", + "0x868ccf19b5044ab93b45c9ed3ae34fcb504fe1453d6c4a1d12c325032cf01eb90356de82080ed897e97dba13cae33a02", + "0xac8867005fe4354d67aa37b866a7e581d2f94f7bd0b9f4efb5c2d1370ec13147a60692051b02fd00ae60b512bce9b1ff", + "0x8fd01886b046819c83c12bb779e432b25ba13713f9227be702074ec3abb2bba6be37220a0a26a4bd4171b99b14e32bc4", + "0xa128981ed199f92b5959975c150a93a62fec50b61c80a3fa0634d90fc8058f76f5cbee77aae6889af12d296b30e613cd", + "0x81fe618552ff7a36c9235c6d4066cf2f930b5b38de4089e18166e4a06ca5723eadd1976d25e34b74b3ce942300b23e5b", + "0xab1223ea049e6e0fbf9b611de7fd7c15e5e9637cbd73aa0e36aea08a7503ba6804f2aa807186fdc9aa7f4f9195f72e24", + "0xb97285286981b2665f898abc13f3243b63005bef8db4cab3f658bf6167036b61af400f08db0fc3c640a9c623b760690d", + "0xae3ddff7c1f0fbb6a13dbbc667a61e863c2c7c51c2051e33cd61620142e7e30a7e0c4c1f8fbb512aa3a8640267c6ac26", + "0x99c2a89d5bef236060e51c4f952664094c20fbfca647e5d24a55c1fb8df2f3df58244fbbf3635db07b1c29ee3234fa6f", + "0xa5010764d4b9cd3b410638334d1f70c5f4843f45b4f4a9316aaea5fbb2c510a97449dd7a07b49f47334a69d37d9955d3", + "0x86706d011dcdc9e9d165d01fea1df68dd74bedaf15a39f92893c030cafe96f4498c4c1fec2d2136354341b3f440a1462", + "0x88fd57eb62bd7dc35722f3a0576c2138403a2f663a2603482e8974a895cf56ddbb02657dc6b89eb2cf5c1f9d1aff6426", + "0xb0dfd4c68e3acb6bb8a776adaa421fc5e268ed4d5964bb90a727091e5113b55b3f9c6d33cedb3ee47ff7acc5df8b1749", + "0x93b92bc942e1a636fc5c2dc1840de5faf158a113d640d5a475b48e2c56ccccaf9db0e37e90ce74c4b3f5c9ac3b2eb523", + "0xb29a16fa1ea95cbfc1873c435ad40dc8495ba6341801b72bd95d908147dcffb1b4bb426dd635f3af4c88984f56594dd8", + "0xb8f367105e1a2d554ac30200c66aeb579d3d30a8953d20fb6ebba2d876ec39c52ea5d654f1bb89b8ddf3d9d651f31cdf", + "0xb5fbc228c983d08adf8612eba5b3db3acff604439226f86aa133b02cce4ffde2f977c8dbb8b446b4375673f71634c89d", + "0xa399bea37d3056e0559f6644faa0af93063b4b545d504d7e228d3dbbc294af83d3c4cf37fe026b63899b4e7d50fd08f5", + "0x928ef411a36414b24aea26fdbed4bdb1bb6bdc2d967e2553ce54c7c4e077e76869cea590257645c9129dd55ce025295c", + "0x9684a4adeed416a9ce82ad79b55c4a3adcfbd43950bc442ed8a340381caedb70f4baaaf821e3a152f483f965d8f56162", + "0x92558a37f214d6f4cb6d72cd2f4ad24dff9d17611b9e4a41ee5c741a5d1ca9e4053b0584533ef4da206110b5dc3e2a35", + "0x973bf0724d1785cc5e85d2a8ee8c354ad4cf557217ced0b7940f6f064024c20b2bfc5b144c820b5083da4bf70690de4d", + "0xadaf1389dfa528210ca9c2657c5ff10d51f7e3b18e93a59c37211be0506c3576cb2c04ec80cd0f82605e53c5a3556620", + "0x85b58b223b09fda6f3ab674d75e780c49eb2167837243df049281e8f4fed653811138b398db9cdfe7405fdb8485602fe", + "0x849504d3db408d80745a07e850b0a804607b91a59922a5d3bc40da2748c029c029419cda38d2a4485cc0824c6b2504f0", + "0xa3f4afcb353bc2582a02be758ebf0cd18752410ca2e64231176bfa23828423e0a450a65f241a9ed8eab36cae8d9c567b", + "0xae362786cdf121206537af9590d330abbc6dc328b53cdd145dbed0e5df1364c816aae757c4c81f9d619e3698dd32bcdf", + "0x9024cfa5b0101eb02ab97866d5a3832944e5aa6888484cfba3d856576b920787b364fba5956bd7c68a305afedc958201", + "0x8a116df09fed923acefb2aecf38a4fbc4b973ee964d67f03791d70bee6356af43ffca117d4e9463ffaf0e0d5d5e5a69f", + "0x9163016175c73f1bbc912ddfe03bd4e1db19c64951c8909ee6befe71a1249d838e0db49f03670bb4c5c9b2ab0fb4fef3", + "0x8f6357318d8d16e7240a02b05ce5a4976b6079d49daa258789c6dbf4a47950ebe9de6411780fab06c7c1f35651433380", + "0x8e63cbae8be7341892dbedee3111adf0307c4ee9e375181aa53478f5ba9cdce164d6ae890e5f480119a3a51c6e989165", + "0xa9782f30674a4874d91bfba7eda63aeb5dbe66b040c768d6a925d8ee135f0655ea56276b105239cc0668fc91ddb68cd1", + "0x8d9d94b61ab84ec08665cbe0244ea41756785df019e453ef078c19380bd44c39d2958e8465c72eacf41eed5696037805", + "0xb1470e6f5d2e314474937cb5a3bc30c8bf5fc3f79014945f6ee895fe20028ffc272f9d3a7320aac93e36c96d8a5454e3", + "0xa444911bbafc71179766594f3606b6eaff041826607fd3192f62dec05cd0f01b78598609a530f6930e8440db66f76713", + "0xa9823d44e2638fca7bcc8796cc91c3eb17f46ad6db9f7f6510e093727614aa3a4f9b2c4011ef91dc1c2d224d08d8d05b", + "0xab86020972c359ab98294212558b4b14862040139876c67fc494184b5c9bcea1dbe32fe0c8dd9e60be9daa304acd599a", + "0xb7e5cb685bbdcfdb1e48259a5d68d047846c8a35c5b3f90172fb183d1df40d22eaf0edaca2761a07c29c577000ccfed0", + "0x8c88319dae4b28989817e79e6667fd891181e8d2ed91b9c6b614985bca14b12982462ec58b17be0463c24bbb79dd62a1", + "0x8c1c6867e7107fb2178157c991b9c8b0f90c8d57a51220bf3650438ccabccf62da4db8a9916491e730ff3d0c106496e3", + "0xa00a79bd58da6528b9af033087260f9f3d00519eafb4746b355204ee994e89481591b508eaa5402821083e250d38467b", + "0x8785abd7c37690f6aa870ee5c799eef72e398a7898b6767f698515be277b9c2fc1af12ea89b0620a848221343a3b5ec3", + "0x8aadae68543db65cef71d0e230a09508d72061398ef2fabec0f856aacff2125b79c70e620744aaf331faf3dfc8afb9bc", + "0x8ff0cd437fcad9630b8a2333176a55e178db4142ec841581590594d74d5b53baeac5fb903fdf7bcf83e245b95b58285e", + "0xaf274e8fad6b190be4e5dc92d2705ba6ac0d7e1ea29e958a5cdd4cb764de46a56d9eef62c999a16e7c50a50b2d9fe3a8", + "0x865e6ec7d1aa848786d6a7a4e87a24d442311f0810b01ef5a74928ab59fdfd651e48880b49680047e5b0df6b3c7c2ecc", + "0x800706baaeb35bf3bc33bdea9a8b5cb00d82df407b3b7e1b781a9359cf44fb410ed311591080181b768aae223d9246aa", + "0xa9496389d0780b309c6998374ae159f58a8d0fe9a1c24c36cebcb45b27d818e653b51a8ee1f01e30a9b2c46a548126ef", + "0xb5fccf4fc3186661939fbee2e89c2aa0e3a6ad4907bcc98c7750520540c4c183b1bbfcdf47f2f1c5e75c3a30cdf30c75", + "0xa90028e39081b736e628c2230cc1338f9210ed01309a40fdf08d39c10cced2cdf71271013bea6dba3a0444fe47963106", + "0xa0815cbb325a8fecf2e1bcc5046644be32d43a8001bd5d8cf0022e4572cd0d481b3e717002f7ab21e16da5f5d16886d6", + "0xb2024787fcda52abc4138150f15e81f4a5be442929b1651ddccbfd558029912be4d61c3c9b467605fff640edf7392494", + "0xab5aa60032304a584cc9245a33f528eae7157808dedd1ad83ebae00aadc25dbe1cd5917eb8b6b2c800df15e67bdd4c4d", + "0x866643847ef512c5119f2f6e4e3b8d3f4abb885f530bb16fcef0edb698a5b0768905e51536283925b6795a5e68b60ddc", + "0x806aa99c9a46ee11cc3ebf0db2344b7515db8c45b09a46a85f8b2082940a6f7263f3c9b12214116c88310e706f8e973a", + "0xa6eada8b9ff3cd010f3174f3d894eb8bb19efdbff4c6d88976514a5b9968b0f1827d8ac4fe510fb0ba92b64583734a1e", + "0x98480db817c3abbc8b7baedf9bf5674ec4afcfd0cd0fd670363510a426dad1bcf1b1cb3bf0f1860e54530deb99460291", + "0x81ab480187af4a3dfbc87be29eca39b342a7e8e1d1df3fc61985e0e43d8d116b8eac2f1021bde4ae4e5e3606c1b67a21", + "0x8a37df12dc997bf9b800f8fd581a614a1d5e32b843f067d63d1ca7fde2e229d24413d3a8308ec1e8389bf88154adb517", + "0xb045a55ca0bb505bd5e8fcc4cfdd5e9af1a7d5fe7a797c7ede3f0b09712b37f493d3fcf6ef0e759d7e0157db1f583c95", + "0xad502e53a50691238323642e1d8b519b3c2c2f0fd6a0dd29de231f453be730cf1adc672887d97df42af0a300f7631087", + "0x80597648f10c6d8fcd7421caf4e7f126179633078a1724817d2adc41b783723f302eabc947a7ba7767166dacf4ce8fa1", + "0xaefb56427966c81081999dffbe89f8a0c402041929cd4e83d6612866cfbb97744f4ab802578349fbecc641fa9955e81b", + "0xa340e493fb3fb604eab864d4b18a6e40ba657003f1f88787e88e48b995da3d0ab4926ce438bdc8d100a41912a47dace0", + "0xa6d777bfc0895eac541a092e14499ff8bf7156689d916a678b50a1460583b38e68158984bea113a0a8e970d8a6799a85", + "0x90ce469410f0e8cfff40472817eb445770833cdcf2895a69bc32bcf959854d41712599ceb2b0422008d7300b05e62e02", + "0x815c51be91d8516d5adc2fd61b6600957ed07cf5fdc809aa652b059bea8ed179638a19077a3f040334032f0e7900ac8b", + "0xb3ec6c0c3c007c49c6b7f7fc2ffd3d3a41cdff5ad3ac40831f53bfc0c799ffeed5f440a27acc5f64432e847cc17dd82e", + "0x823637abeab5fb19e4810b045254558d98828126e9a2d5895a34b9e4b4f49ab0a5b3ee2422f1f378995ea05df5516057", + "0xac05412bcf46c254f6548d8107a63928bba19ab6889de5d331eb68cf4d8ce206055b83af4cb7c6c23b50188391e93f84", + "0x88514163c587068178302bc56e9a8b3ad2fa62afd405db92f2478bb730101358c99c0fe40020eeed818c4e251007de9c", + "0xb1e657d0f7772795b3f5a84317b889e8ded7a08ea5beb2ab437bebf56bcb508ae7215742819ed1e4ae3969995fe3b35d", + "0xa727d4f03027fe858656ca5c51240a65924915bd8bd7ffa3cfc8314a03594738234df717e78bb55a7add61a0a4501836", + "0xb601682830fc4d48ece2bdc9f1a1d5b9a2879c40c46135f00c2c3ae1187c821412f0f0cfbc83d4e144ddd7b702ca8e78", + "0xb5cfea436aa1f29c4446979272a8637cb277f282825674ddb3acac2c280662fb119e6b2bdd52c4b8dbf2c39b1d2070d6", + "0x85c211645ff746669f60aa314093703b9045966604c6aa75aae28422621b256c0c2be835b87e87a00d3f144e8ab7b5f0", + "0x867628d25bab4cb85d448fd50fdd117be1decdd57292e194a8baa0655978fae551912851660a1d5b9de7a2afbb88ef5c", + "0xa4e79c55d1b13c959ff93ddcf1747722c6312a7941a3b49f79006b3165334bab369e5469f1bddebadb12bfaff53806d5", + "0xac61f0973e84546487c5da7991209526c380e3731925b93228d93a93bce1283a3e0807152354f5fe7f3ea44fc447f8fe", + "0xa1aa676735a73a671a4e10de2078fd2725660052aa344ca2eb4d56ee0fd04552fe9873ee14a85b09c55708443182183a", + "0x8e2f13269f0a264ef2b772d24425bef5b9aa7ea5bbfbefbcc5fd2a5efd4927641c3d2374d0548439a9f6302d7e4ba149", + "0xb0aacdaf27548d4f9de6e1ec3ad80e196761e3fb07c440909524a83880d78c93465aea13040e99de0e60340e5a5503cd", + "0xa41b25ae64f66de4726013538411d0ac10fdb974420352f2adb6ce2dcad7b762fd7982c8062a9bac85cdfcc4b577fd18", + "0xb32d87d5d551f93a16ec983fd4ef9c0efcdae4f5e242ce558e77bcde8e472a0df666875af0aeec1a7c10daebebab76ea", + "0xb8515795775856e25899e487bf4e5c2b49e04b7fbe40cb3b5c25378bcccde11971da280e8b7ba44d72b8436e2066e20f", + "0x91769a608c9a32f39ca9d14d5451e10071de2fd6b0baec9a541c8fad22da75ed4946e7f8b081f79cc2a67bd2452066a9", + "0x87b1e6dbca2b9dbc8ce67fd2f54ffe96dfcce9609210a674a4cb47dd71a8d95a5a24191d87ba4effa4a84d7db51f9ba0", + "0xa95accf3dbcbf3798bab280cabe46e3e3688c5db29944dbe8f9bd8559d70352b0cfac023852adc67c73ce203cbb00a81", + "0xa835f8ce7a8aa772c3d7cfe35971c33fc36aa3333b8fae5225787533a1e4839a36c84c0949410bb6aace6d4085588b1e", + "0x8ef7faa2cf93889e7a291713ab39b3a20875576a34a8072a133fed01046f8093ace6b858463e1e8a7f923d57e4e1bc38", + "0x969ecd85643a16d937f148e15fb56c9550aefd68a638425de5058333e8c0f94b1df338eaab1bd683190bfde68460622b", + "0x8982f4c76b782b9b47a9c5aeb135278e5c991b1558e47b79328c4fae4b30b2b20c01204ff1afb62b7797879d9dee48e2", + "0xb5098b7ba813178ced68f873c8c223e23a3283d9f1a061c95b68f37310bca4b2934a3a725fff1de1341c79bb3ba6007e", + "0x97b160787009f7b9649ed63db9387d48a669e17b2aba8656792eb4f5685bb8e6386f275476b4dfbb1b4cb0c2a69bc752", + "0x88b69369c71daad6b84fa51a0f64a6962d8c77e555b13c035ad6fa1038e7190af455b1bd61ae328b65d6a14cf3d5f0d5", + "0xaf88b87801361f0de26bd2533554ee6f4d8067e3122b54161c313c52cc9eafea00661c5c43e2d533485d1f26da4e5510", + "0x98ab18e3bbcb23ac1e34439849e56009bb765ab2f2558ebfd0a57cbe742169f114bceb930533fb911b22cb5a8fe172bc", + "0x9027507f1725d81e5ac0f0854c89ab627df3020fe928cb8745f887bf3310086c58fca1119fd5cd18a7d3561c042d58de", + "0xa676583f8a26e6f8991a0791916ce785b596ce372812f5eb7b4243ba9367ea95c797170fdac5b0c5e6b7f6519cc2b026", + "0xb91b0ab32638aef3365035a41c6068e36d2303bfee8640565e16c9a56c21703270fd45946ce663238a72c053eb3f2230", + "0xaaf4cd1ac0a30906dcd2b66b37848c6cc443da511e0b0367fd792887fdaf1500551590440e61d837dbee9d24c9801108", + "0xa06f20a02d3cd76029baad5a12592f181738378a83a95e90470fa7cc82a5ae9d2ed824a20eeb1e96e6edc0619f298688", + "0xa465d379c3481b294efc3f2f940b651c45579607cf72d143b99705eae42103a0279eb3595966453130e18935265e35d6", + "0x892a8af7816a806295278027a956663ea1297118ede0f2a7e670483b81fb14dccacc7a652e12f160e531d806ca5f2861", + "0xb480917c0e8b6e00de11b4416a20af6c48a343450a32ee43224559d30e1fecdece52cc699493e1754c0571b84f6c02c2", + "0xb3182da84c81e5a52e22cebed985b0efc3056350ec59e8646e7fd984cdb32e6ac14e76609d0ffaca204a7a3c20e9f95d", + "0xa04ea6392f3b5a176fa797ddec3214946962b84a8f729ffbd01ca65767ff6237da8147fc9dc7dd88662ad0faefdb538c", + "0x95c0d10a9ba2b0eb1fd7aa60c743b6cf333bb7f3d7adedce055d6cd35b755d326bf9102afabb1634f209d8dacfd47f1a", + "0xa1a583d28b07601541fa666767f4f45c954431f8f3cc3f96380364c5044ff9f64114160e5002fb2bbc20812b8cbd36cb", + "0xa1a0708af5034545e8fcc771f41e14dff421eed08b4606f6d051f2d7799efd00d3a59a1b9a811fa4eddf5682e63102ea", + "0xab27c7f54096483dd85c866cfb347166abe179dc5ffaca0c29cf3bfe5166864c7fa5f954c919b3ba00bdbab38e03407d", + "0xac8c82271c8ca71125b380ed6c61b326c1cfe5664ccd7f52820e11f2bea334b6f60b1cf1d31599ed94d8218aa6fbf546", + "0xa015ea84237d6aa2adb677ce1ff8a137ef48b460afaca20ae826a53d7e731320ebdd9ee836de7d812178bec010dd6799", + "0x925418cda78a56c5b15d0f2dc66f720bda2885f15ffafb02ce9c9eed7167e68c04ad6ae5aa09c8c1c2f387aa39ad6d1b", + "0x87c00bba80a965b3742deacafb269ca94ead4eb57fdb3ed28e776b1d0989e1b1dba289019cfb1a0f849e58668a4f1552", + "0x948d492db131ca194f4e6f9ae1ea6ebc46ebbed5d11f1f305d3d90d6b4995b1218b9606d114f48282a15661a8a8051ca", + "0x8179617d64306417d6865add8b7be8452f1759721f97d737ef8a3c90da6551034049af781b6686b2ea99f87d376bce64", + "0x918e3da425b7c41e195ed7b726fa26b15a64299fe12a3c22f51a2a257e847611ac6cfcc99294317523fc491e1cbe60c4", + "0xa339682a37844d15ca37f753599d0a71eedfbbf7b241f231dd93e5d349c6f7130e0d0b97e6abd2d894f8b701da37cb11", + "0x8fc284f37bee79067f473bc8b6de4258930a21c28ac54aaf00b36f5ac28230474250f3aa6a703b6057f7fb79a203c2c1", + "0xa2c474e3a52a48cd1928e755f610fefa52d557eb67974d02287dbb935c4b9aab7227a325424fed65f8f6d556d8a46812", + "0x99b88390fa856aa1b8e615a53f19c83e083f9b50705d8a15922e7c3e8216f808a4cc80744ca12506b1661d31d8d962e4", + "0xa1cbd03e4d4f58fc4d48fa165d824b77838c224765f35d976d3107d44a6cf41e13f661f0e86f87589292721f4de703fb", + "0xb3a5dde8a40e55d8d5532beaa5f734ee8e91eafad3696df92399ae10793a8a10319b6dc53495edcc9b5cfd50a389a086", + "0x996e25e1df5c2203647b9a1744bd1b1811857f742aee0801508457a3575666fcc8fc0c047c2b4341d4b507008cd674c2", + "0x93e0a66039e74e324ee6c38809b3608507c492ef752202fff0b2c0e1261ca28f1790b3af4fdb236f0ed7e963e05c1ec0", + "0xb6084e5818d2d860ac1606d3858329fbad4708f79d51a6f072dc370a21fdb1e1b207b74bc265a8547658bfb6a9569bb3", + "0xa5336126a99c0ecfc890584b2a167922a26cae652dfc96a96ab2faf0bf9842f166b39ceaf396cd3d300d0ebb2e6e0ebf", + "0xb8b6f13ce9201decaba76d4eca9b9fa2e7445f9bc7dc9f82c262f49b15a40d45d5335819b71ff2ee40465da47d015c47", + "0xb45df257b40c68b7916b768092e91c72b37d3ed2a44b09bf23102a4f33348849026cb3f9fbb484adfea149e2d2a180ff", + "0xa50d38ee017e28021229c4bb7d83dd9cdad27ab3aa38980b2423b96aa3f7dc618e3b23895b0e1379ca20299ff1919bbf", + "0x97542cf600d34e4fdc07d074e8054e950708284ed99c96c7f15496937242365c66e323b0e09c49c9c38113096640a1b6", + "0x822d198629697dcd663be9c95ff1b39419eae2463fa7e6d996b2c009d746bedc8333be241850153d16c5276749c10b20", + "0x9217bc14974766ebdfbf6b434dd84b32b04658c8d8d3c31b5ff04199795d1cfad583782fd0c7438df865b81b2f116f9c", + "0x93477879fa28a89471a2c65ef6e253f30911da44260833dd51030b7a2130a923770ebd60b9120f551ab373f7d9ed80aa", + "0x87d89ff7373f795a3a798f03e58a0f0f0e7deab8db2802863fab84a7be64ae4dcf82ece18c4ddbefccd356262c2e8176", + "0xa3ba26bd31d3cc53ceeced422eb9a63c0383cde9476b5f1902b7fe2b19e0bbf420a2172ac5c8c24f1f5c466eecc615d4", + "0xa0fe061c76c90d84bd4353e52e1ef4b0561919769dbabe1679b08ef6c98dcfb6258f122bb440993d976c0ab38854386b", + "0xb3070aa470185cb574b3af6c94b4069068b89bb9f7ea7db0a668df0b5e6aabdfe784581f13f0cf35cd4c67726f139a8c", + "0x9365e4cdf25e116cbc4a55de89d609bba0eaf0df2a078e624765509f8f5a862e5da41b81883df086a0e5005ce1576223", + "0xa9036081945e3072fa3b5f022df698a8f78e62ab1e9559c88f9c54e00bc091a547467d5e2c7cbf6bc7396acb96dd2c46", + "0x8309890959fcc2a4b3d7232f9062ee51ece20c7e631a00ec151d6b4d5dfccf14c805ce5f9aa569d74fb13ae25f9a6bbe", + "0xb1dc43f07303634157f78e213c2fae99435661cc56a24be536ccbd345ef666798b3ac53c438209b47eb62b91d6fea90a", + "0x84eb451e0a74ef14a2c2266ff01bd33d9a91163c71f89d0a9c0b8edfcfe918fc549565509cd96eed5720a438ff55f7f2", + "0x9863b85a10db32c4317b19cc9245492b9389b318cf128d9bbc7ec80a694fcbbd3c0d3189a8cad00cc9290e67e5b361ee", + "0x8a150ee474ebe48bdfcac1b29e46ac90dcded8abbe4807a165214e66f780f424be367df5ef1e94b09acf4a00cd2e614d", + "0xa6677a373130b83e30849af12475e192f817ba4f3226529a9cca8baaefb8811db376e4a044b42bf1481268c249b1a66e", + "0xb969cbf444c1297aa50d1dfa0894de4565161cb1fc59ba03af9655c5bf94775006fe8659d3445b546538a22a43be6b93", + "0x8383167e5275e0707e391645dc9dea9e8a19640ecfa23387f7f6fcaddff5cde0b4090dfad7af3c36f8d5c7705568e8d8", + "0xa353ddbc6b6837773e49bb1e33a3e00ca2fb5f7e1dba3a004b0de75f94a4e90860d082a455968851ef050ae5904452e0", + "0xadeccf320d7d2831b495479b4db4aa0e25c5f3574f65a978c112e9981b2663f59de4c2fa88974fdcabb2eedb7adab452", + "0xafa0eacc9fdbe27fb5e640ecad7ecc785df0daf00fc1325af716af61786719dd7f2d9e085a71d8dc059e54fd68a41f24", + "0xa5b803a5bbe0ca77c8b95e1e7bacfd22feae9f053270a191b4fd9bca850ef21a2d4bd9bcd50ecfb971bb458ff2354840", + "0xb023c9c95613d9692a301ef33176b655ba11769a364b787f02b42ceb72338642655ea7a3a55a3eec6e1e3b652c3a179e", + "0x8fa616aa7196fc2402f23a19e54620d4cf4cf48e1adfb7ea1f3711c69705481ddcc4c97236d47a92e974984d124589e5", + "0xa49e11e30cb81cb7617935e8a30110b8d241b67df2d603e5acc66af53702cf1e9c3ef4a9b777be49a9f0f576c65dcc30", + "0x8df70b0f19381752fe327c81cce15192389e695586050f26344f56e451df2be0b1cdf7ec0cba7ce5b911dcff2b9325ae", + "0x8fbbc21a59d5f5a14ff455ca78a9a393cab91deb61cf1c25117db2714d752e0054ed3e7e13dd36ad423815344140f443", + "0xa9a03285488668ab97836a713c6e608986c571d6a6c21e1adbd99ae4009b3dde43721a705d751f1bd4ebf1ea7511dfed", + "0xb2f32b8e19e296e8402251df67bae6066aeefd89047586d887ffa2eacdf38e83d4f9dc32e553799024c7a41818945755", + "0x942cf596b2278ad478be5c0ab6a2ad0ceafe110263cc93d15b9a3f420932104e462cf37586c374f10b1040cb83b862e0", + "0xaaa077a55f501c875ceae0a27ef2b180be9de660ef3d6b2132eb17256771ce609d9bc8aaf687f2b56ae46af34ad12b30", + "0x90ac74885be1448101cf3b957d4486e379673328a006ea42715c39916e9334ea77117ff4a60d858e2ccce9694547a14f", + "0x9256cdfc2339e89db56fd04bd9b0611be0eefc5ee30711bcece4aadf2efcc5a6dcc0cfd5f733e0e307e3a58055dff612", + "0xa4c7384e208a0863f4c056248f595473dcde70f019ddaede45b8caf0752575c241bac6e436439f380ac88eee23a858e9", + "0xa3aa67391781e0736dddc389f86b430b2fc293b7bd56bfd5a8ec01d1dd52ed940593c3ad4ce25905061936da062b0af6", + "0x80299275ec322fbb66cc7dce4482ddd846534e92121186b6906c9a5d5834346b7de75909b22b98d73120caec964e7012", + "0xaa3a6cd88e5f98a12738b6688f54478815e26778357bcc2bc9f2648db408d6076ef73cced92a0a6b8b486453c9379f18", + "0xb07c444681dc87b08a7d7c86708b82e82f8f2dbd4001986027b82cfbed17b9043e1104ade612e8e7993a00a4f8128c93", + "0xaf40e01b68d908ac2a55dca9b07bb46378c969839c6c822d298a01bc91540ea7a0c07720a098be9a3cfe9c27918e80e8", + "0xabd8947c3bbc3883c80d8c873f8e2dc9b878cbbb4fc4a753a68f5027de6d8c26aa8fbbafeb85519ac94e2db660f31f26", + "0xa234f9d1a8f0cb5d017ccca30b591c95ec416c1cb906bd3e71b13627f27960f61f41ed603ffbcf043fd79974ec3169a8", + "0x835aaf52a6af2bc7da4cf1586c1a27c72ad9de03c88922ad172dce7550d70f6f3efcc3820d38cd56ae3f7fc2f901f7a0", + "0xae75db982a45ad01f4aa7bc50d642ff188219652bb8d521d13a9877049425d57852f3c9e4d340ffec12a4d0c639e7062", + "0xb88884aa9187c33dc784a96832c86a44d24e9ffe6315544d47fc25428f11337b9ffd56eb0a03ad709d1bf86175059096", + "0x8492ca5afcc6c0187b06453f01ed45fd57eb56facbeea30c93686b9e1dab8eaabd89e0ccb24b5f35d3d19cd7a58b5338", + "0x9350623b6e1592b7ea31b1349724114512c3cce1e5459cd5bddd3d0a9b2accc64ab2bf67a71382d81190c3ab7466ba08", + "0x98e8bf9bed6ae33b7c7e0e49fc43de135bffdba12b5dcb9ff38cb2d2a5368bb570fe7ee8e7fbe68220084d1d3505d5be", + "0xab56144393f55f4c6f80c67e0ab68f445568d68b5aa0118c0c666664a43ba6307ee6508ba0bb5eb17664817bc9749af0", + "0x827d5717a41b8592cfd1b796a30d6b2c3ca2cdc92455f9f4294b051c4c97b7ad6373f692ddafda67884102e6c2a16113", + "0x8445ce2bb81598067edaa2a9e356eda42fb6dc5dd936ccf3d1ff847139e6020310d43d0fec1fe70296e8f9e41a40eb20", + "0x9405178d965ee51e8d76d29101933837a85710961bb61f743d563ef17263f3c2e161d57e133afac209cdb5c46b105e31", + "0xb209f9ed324c0daa68f79800c0a1338bbaf6d37b539871cb7570f2c235caca238a2c4407961fcb7471a103545495ef2c", + "0x92ae6437af6bbd97e729b82f5b0d8fb081ca822f340e20fae1875bdc65694cd9b8c037a5a1d49aa9cae3d33f5bad414e", + "0x9445bdb666eae03449a38e00851629e29a7415c8274e93343dc0020f439a5df0009cd3c4f5b9ce5c0f79aefa53ceac99", + "0x93fdab5f9f792eada28f75e9ac6042a2c7f3142ba416bfdb1f90aa8461dbe4af524eee6db4f421cb70c7bc204684d043", + "0xa7f4dc949af4c3163953320898104a2b17161f7be5a5615da684f881633174fb0b712d0b7584b76302e811f3fac3c12f", + "0xa8ac84da817b3066ba9789bf2a566ccf84ab0a374210b8a215a9dcf493656a3fa0ecf07c4178920245fee0e46de7c3ec", + "0x8e6a0ae1273acda3aa50d07d293d580414110a63bc3fb6330bb2ee6f824aff0d8f42b7375a1a5ba85c05bfbe9da88cb5", + "0xa5dea98852bd6f51a84fa06e331ea73a08d9d220cda437f694ad9ad02cf10657882242e20bdf21acbbaa545047da4ce5", + "0xb13f410bf4cfce0827a5dfd1d6b5d8eabc60203b26f4c88238b8000f5b3aaf03242cdeadc2973b33109751da367069e1", + "0xa334315a9d61b692ad919b616df0aa75a9f73e4ea6fc27d216f48964e7daebd84b796418580cf97d4f08d4a4b51037cd", + "0x8901ba9e963fcd2f7e08179b6d19c7a3b8193b78ca0e5cf0175916de873ca0d000cd7ac678c0473be371e0ac132f35a2", + "0xb11a445433745f6cb14c9a65314bbf78b852f7b00786501b05d66092b871111cd7bee25f702d9e550d7dd91601620abb", + "0x8c2f7b8e7b906c71f2f154cc9f053e8394509c37c07b9d4f21b4495e80484fc5fc8ab4bdc525bd6cfa9518680ba0d1a2", + "0xb9733cebe92b43b899d3d1bfbf4b71d12f40d1853b2c98e36e635fdd8a0603ab03119890a67127e6bc79afae35b0bef2", + "0xa560f6692e88510d9ba940371e1ada344caf0c36440f492a3067ba38e9b7011caac37ba096a8a4accb1c8656d3c019b3", + "0xac18624339c1487b2626eef00d66b302bdb1526b6340d6847befe2fdfb2b410be5555f82939f8707f756db0e021ed398", + "0xafd9a3b8866a7fe4f7bc13470c0169b9705fcd3073685f5a6dcff3bdbbc2be50ac6d9908f9a10c5104b0bffc2bc14dad", + "0x97f15c92fe1f10949ed9def5dd238bc1429706e5037a0e0afb71c2d0e5845e2fed95a171c393e372077a7c7059f8c0e0", + "0x9453a1d4d09c309b70968ea527007d34df9c4cfd3048e5391aac5f9b64ca0c05dde5b8c949c481cfc83ef2e57b687595", + "0xb80e4b7c379ad435c91b20b3706253b763cbc980db78f782f955d2516af44c07bbfa5888cbf3a8439dc3907320feb25a", + "0x8939f458d28fefe45320b95d75b006e98330254056d063e4a2f20f04bcb25936024efe8d436d491ed34b482f9b9ae49c", + "0xa9ead2e833f71f7e574c766440c4b3c9c3363698c7ade14499a56003a272832ee6d99440887fa43ccdf80265b9d56b97", + "0xb6547a36934f05ce7b779e68049d61351cf229ae72dc211cc96a2a471b2724782f9355fdb415ea6f0ea1eb84fe00e785", + "0x828bfb3099b7b650b29b0f21279f829391f64520a6ab916d1056f647088f1e50fac9253ef7464eceab5380035c5a59c4", + "0x8d714b9ea650be4342ff06c0256189e85c5c125adf6c7aeca3dba9b21d5e01a28b688fc2116ce285a0714a8f1425c0b8", + "0x8a82eda041b2e72a3d73d70d85a568e035fbd6dc32559b6c6cfdf6f4edcb59a6ba85b6294a721aa0a71b07714e0b99ae", + "0xaf5665ebc83d027173b14ffb0e05af0a192b719177889fadc9ac8c082fda721e9a75d9ce3f5602dbfd516600ee3b6405", + "0xa68fdddf03d77bebdb676e40d93e59bd854408793df2935d0a5600601f7691b879981a398d02658c2da39dbbf61ef96c", + "0x8c001ebc84fcf0470b837a08a7b6125126b73a2762db47bbdc38c0e7992b1c66bac7a64faa1bf1020d1c63b40adc3082", + "0x8553889b49f9491109792db0a69347880a9cf2911b4f16f59f7f424e5e6b553687d51282e8f95be6a543635247e2e2c2", + "0xa2c269d6370b541daf1f23cc6b5d2b03a5fa0c7538d53ae500ef875952fe215e74a5010329ff41461f4c58b32ad97b3d", + "0xa5dae097285392b4eba83a9fd24baa03d42d0a157a37fae4b6efc3f45be86024b1182e4a6b6eadcf5efe37704c0a1ae5", + "0x89871a77d2032387d19369933cd50a26bda643e40cfd0ce73febe717a51b39fae981406fd41e50f4a837c02a99524ef9", + "0x8a76d495e90093ec2ac22f53759dc1cf36fbb8370fb586acbd3895c56a90bbf3796bcc4fc422ca4058adf337ead1402e", + "0xad4eb7576c4954d20623c1336c63662c2a6fb46ec6ef99b7f8e946aa47488dcb136eab60b35600f98c78c16c10c99013", + "0x894c2b120cec539feb1d281baaadde1e44beafedeeec29b804473fe024e25c1db652f151c956e88d9081fb39d27e0b19", + "0x9196bd5c100878792444c573d02b380a69e1b4b30cb59a48114852085058a5fd952df4afee3ecceb5c4ede21e1ed4a1a", + "0xa996fffc910764ea87a1eedc3a3d600e6e0ff70e6a999cb435c9b713a89600fc130d1850174efe9fc18244bb7c6c5936", + "0x8591bb8826befa8bee9663230d9a864a5068589f059e37b450e8c85e15ce9a1992f0ce1ead1d9829b452997727edcf9d", + "0x9465e20bb22c41bf1fa728be8e069e25cda3f7c243381ca9973cbedad0c7b07d3dd3e85719d77cf80b1058ce60e16d68", + "0x926b5ce39b6e60b94878ffeae9ff20178656c375fb9cfe160b82318ca500eb3e2e3144608b6c3f8d6c856b8fe1e2fbcf", + "0xa1ef29cbc83c45eb28ad468d0ce5d0fdd6b9d8191ba5ffa1a781c2b232ed23db6b7b04de06ef31763a6bfe377fa2f408", + "0x9328e63a3c8acf457c9f1f28b32d90d0eeadb0f650b5d43486a61d7374757a7ada5fc1def2a1e600fa255d8b3f48036f", + "0xa9c64880fcb7654f4dd08f4c90baac95712dd6dd407e17ea60606e9a97dc8e54dd25cb72a9bf3fc61f8d0ad569fe369d", + "0xa908eb7b940c1963f73046d6b35d40e09013bfbfbeb2ccd64df441867e202b0f3b625fa32dd04987c3d7851360abdffc", + "0xb3947b5ed6d59e59e4472cdb1c3261de1b5278fb7cb9b5fca553f328b3b3e094596861ea526eca02395f7b7358155b7b", + "0x99da7f190d37bc58945f981cf484d40fcf0855cf8178e2ce8d057c7f0a9d9f77425fdbce9ef8366f44f671b20fd27d0b", + "0x913976d77d80e3657977df39571577fdf0be68ba846883705b454f8493578baa741cfaede53783e2c97cc08964395d83", + "0x8d754a61e5164a80b5090c13f3e936056812d4ae8dc5cc649e6c7f37464777249bc4ae760a9806939131f39d92cca5bf", + "0x82ffd098480828a90cb221a8c28584e15904bad477c13b2e2d6ef0b96a861ce4a309a328fe44342365349456ad7c654f", + "0x89ae3ce4b0357044579ca17be85d8361bb1ce3941f87e82077dd67e43ec0f95edd4bd3426225c90994a81a99e79490b7", + "0xa170892074016d57c9d8e5a529379d7e08d2c1158b9ac4487ac9b95266c4fd51cb18ae768a2f74840137eec05000dd5a", + "0xaafd8acd1071103c7af8828a7a08076324d41ea530df90f7d98fafb19735fc27ead91b50c2ca45851545b41d589d0f77", + "0x8623c849e61d8f1696dc9752116a26c8503fd36e2cbbc9650feffdd3a083d8cdbb3b2a4e9743a84b9b2ad91ac33083f2", + "0xac7166ddd253bb22cdbd8f15b0933c001d1e8bc295e7c38dc1d2be30220e88e2155ecd2274e79848087c05e137e64d01", + "0xa5276b216d3df3273bbfa46210b63b84cfe1e599e9e5d87c4e2e9d58666ecf1af66cb7ae65caebbe74b6806677215bd0", + "0x88792f4aa3597bb0aebadb70f52ee8e9db0f7a9d74f398908024ddda4431221a7783e060e0a93bf1f6338af3d9b18f68", + "0x8f5fafff3ecb3aad94787d1b358ab7d232ded49b15b3636b585aa54212f97dc1d6d567c180682cca895d9876cacb7833", + "0xab7cb1337290842b33e936162c781aa1093565e1a5b618d1c4d87dd866daea5cebbcc486aaa93d8b8542a27d2f8694c7", + "0x88480a6827699da98642152ebc89941d54b4791fbc66110b7632fb57a5b7d7e79943c19a4b579177c6cf901769563f2f", + "0xa725ee6d201b3a610ede3459660658ee391803f770acc639cfc402d1667721089fb24e7598f00e49e81e50d9fd8c2423", + "0x98924372da8aca0f67c8c5cad30fa5324519b014fae7849001dcd51b6286118f12b6c49061219c37714e11142b4d46de", + "0xa62c27360221b1a7c99697010dfe1fb31ceb17d3291cf2172624ebeff090cbaa3c3b01ec89fe106dace61d934711d42d", + "0x825173c3080be62cfdc50256c3f06fe190bc5f190d0eb827d0af5b99d80936e284a4155b46c0d462ee574fe31d60983d", + "0xa28980b97023f9595fadf404ed4aa36898d404fe611c32fd66b70252f01618896f5f3fda71aea5595591176aabf0c619", + "0xa50f5f9def2114f6424ff298f3b128068438f40860c2b44e9a6666f43c438f1780be73cf3de884846f1ba67f9bef0802", + "0xb1eee2d730da715543aeb87f104aff6122cb2bf11de15d2519ff082671330a746445777924521ec98568635f26988d0c", + "0x862f6994a1ff4adfd9fb021925cccf542fca4d4b0b80fb794f97e1eb2964ef355608a98eec6e07aadd4b45ee625b2a21", + "0x8ce69a18df2f9b9f6e94a456a7d94842c61dea9b00892da7cf5c08144de9be39b8c304aeca8b2e4222f87ba367e61006", + "0xb5f325b1cecd435f5346b6bc562d92f264f1a6d91be41d612df012684fdd69e86063db077bc11ea4e22c5f2a13ae7bee", + "0x85526870a911127835446cb83db8986b12d5637d59e0f139ad6501ac949a397a6c73bd2e7fba731b1bb357efe068242c", + "0x8552247d3f7778697f77389717def5a149fc20f677914048e1ed41553b039b5427badc930491c0bae663e67668038fd1", + "0xa545640ee5e51f3fe5de7050e914cfe216202056cd9d642c90e89a166566f909ee575353cb43a331fde17f1c9021414e", + "0x8b51229b53cff887d4cab573ba32ec52668d197c084414a9ee5589b285481cea0c3604a50ec133105f661321c3ca50f5", + "0x8cdc0b960522bed284d5c88b1532142863d97bbb7dc344a846dc120397570f7bd507ceb15ed97964d6a80eccfef0f28e", + "0xa40683961b0812d9d53906e795e6470addc1f30d09affebf5d4fbbd21ddfa88ce441ca5ea99c33fd121405be3f7a3757", + "0xa527875eb2b99b4185998b5d4cf97dd0d4a937724b6ad170411fc8e2ec80f6cee2050f0dd2e6fee9a2b77252d98b9e64", + "0x84f3a75f477c4bc4574f16ebc21aaa32924c41ced435703c4bf07c9119dd2b6e066e0c276ff902069887793378f779e0", + "0xa3544bc22d1d0cab2d22d44ced8f7484bfe391b36991b87010394bfd5012f75d580596ffd4f42b00886749457bb6334b", + "0xb81f6eb26934b920285acc20ceef0220dd23081ba1b26e22b365d3165ce2fbae733bbc896bd0932f63dcc84f56428c68", + "0x95e94d40a4f41090185a77bf760915a90b6a3e3ace5e53f0cb08386d438d3aa3479f0cd81081b47a9b718698817265cd", + "0xb69bd1625b3d6c17fd1f87ac6e86efa0d0d8abb69f8355a08739109831baeec03fd3cd4c765b5ff8b1e449d33d050504", + "0x8448f4e4c043519d98552c2573b76eebf2483b82d32abb3e2bfc64a538e79e4f59c6ca92adff1e78b2f9d0a91f19e619", + "0x8f11c42d6a221d1fda50887fb68b15acdb46979ab21d909ed529bcad6ae10a66228ff521a54a42aca0dad6547a528233", + "0xa3adb18d7e4a882b13a067784cf80ea96a1d90f5edc61227d1f6e4da560c627688bdf6555d33fe54cab1bca242986871", + "0xa24d333d807a48dc851932ed21cbdd7e255bad2699909234f1706ba55dea4bb6b6f8812ffc0be206755868ba8a4af3f9", + "0xa322de66c22a606e189f7734dbb7fda5d75766d5e69ec04b4e1671d4477f5bcb9ff139ccc18879980ebc3b64ab4a2c49", + "0x88f54b6b410a1edbf125db738d46ee1a507e69bc5a8f2f443eb787b9aa7dbd6e55014ec1e946aabeb3e27a788914fb04", + "0xb32ee6da1dcd8d0a7fd7c1821bb1f1fe919c8922b4c1eeed56e5b068a5a6e68457c42b192cbaef5dc6d49b17fa45bc0f", + "0x8a44402da0b3a15c97b0f15db63e460506cb8bef56c457166aea5e8881087d8202724c539ef0feb97131919a73aefca8", + "0xb967e3fead6171fa1d19fd976535d428b501baff59e118050f9901a54b12cc8e4606348454c8f0fc25bd6644e0a5532e", + "0xb7a0c9e9371c3efbbb2c6783ce2cc5f149135175f25b6d79b09c808bce74139020e77f0c616fa6dcb3d87a378532529d", + "0xa54207782ffc909cd1bb685a3aafabbc4407cda362d7b3c1b14608b6427e1696817aeb4f3f85304ac36e86d3d8caa65b", + "0x98c1da056813a7bfebc81d8db7206e3ef9b51f147d9948c088976755826cc5123c239ca5e3fe59bed18b5d0a982f3c3f", + "0xae1c86174dfafa9c9546b17b8201719aecd359f5bbeb1900475041f2d5b8a9600d54d0000c43dd061cfda390585726ff", + "0xa8ee5a8be0bd1372a35675c87bfd64221c6696dc16e2d5e0996e481fec5cdbcb222df466c24740331d60f0521285f7d3", + "0x8ddadbe3cf13af50d556ce8fc0dd77971ac83fad9985c3d089b1b02d1e3afc330628635a31707b32595626798ea22d45", + "0xa5c80254baf8a1628dc77c2445ebe21fbda0de09dd458f603e6a9851071b2b7438fe74214df293dfa242c715d4375c95", + "0xb9d83227ed2600a55cb74a7052003a317a85ca4bea50aa3e0570f4982b6fe678e464cc5156be1bd5e7bba722f95e92c5", + "0xb56085f9f3a72bea9aa3a8dc143a96dd78513fa327b4b9ba26d475c088116cab13843c2bff80996bf3b43d3e2bddb1d6", + "0x8fa9b39558c69a9757f1e7bc3f07295e4a433da3e6dd8c0282397d26f64c1ecd8eb3ba9824a7cacfb87496ebbb45d962", + "0x879c6d0cb675812ed9dee68c3479a499f088068501e2677caeae035e6f538da91a49e245f5fcce135066169649872bee", + "0x91aa9fd3fed0c2a23d1edda8a6542188aeb8abee8772818769bdee4b512d431e4625a343af5d59767c468779222cf234", + "0xa6be0bb2348c35c4143482c7ef6da9a93a5356f8545e8e9d791d6c08ed55f14d790d21ee61d3a56a2ae7f888a8fd46ca", + "0x808ee396a94e1b8755f2b13a6ffbedef9e0369e6c2e53627c9f60130c137299d0e4924d8ef367e0a7fad7f68a8c9193c", + "0xad1086028fcdac94d5f1e7629071e7e47e30ad0190ae59aaebfb7a7ef6202ab91323a503c527e3226a23d7937af41a52", + "0x9102bdaf79b907d1b25b2ec6b497e2d301c8eac305e848c6276b392f0ad734131a39cc02ed42989a53ca8da3d6839172", + "0x8c976c48a45b6bc7cd7a7acea3c2d7c5f43042863b0661d5cd8763e8b50730552187a8eecf6b3d17be89110208808e77", + "0xa2624c7e917e8297faa3af89b701953006bf02b7c95dfba00c9f3de77748bc0b13d6e15bb8d01377f4d98fb189538142", + "0xa405f1e66783cdcfe20081bce34623ec3660950222d50b7255f8b3cc5d4369aeb366e265e5224c0204911539f0fa165e", + "0x8d69bdcaa5d883b5636ac8f8842026fcc58c5e2b71b7349844a3f5d6fbecf44443ef4f768eac376f57fb763606e92c9f", + "0x82fce0643017d16ec1c3543db95fb57bfa4855cc325f186d109539fcacf8ea15539be7c4855594d4f6dc628f5ad8a7b0", + "0x8860e6ff58b3e8f9ae294ff2487f0d3ffae4cf54fd3e69931662dabc8efd5b237b26b3def3bcd4042869d5087d22afcf", + "0x88c80c442251e11c558771f0484f56dc0ed1b7340757893a49acbf96006aa73dfc3668208abea6f65375611278afb02a", + "0x8be3d18c6b4aa8e56fcd74a2aacb76f80b518a360814f71edb9ccf3d144bfd247c03f77500f728a62fca7a2e45e504c5", + "0x8b8ebf0df95c3f9b1c9b80469dc0d323784fd4a53f5c5357bb3f250a135f4619498af5700fe54ad08744576588b3dfff", + "0xa8d88abdaadd9c2a66bc8db3072032f63ed8f928d64fdb5f810a65074efc7e830d56e0e738175579f6660738b92d0c65", + "0xa0a10b5d1a525eb846b36357983c6b816b8c387d3890af62efb20f50b1cb6dd69549bbef14dab939f1213118a1ae8ec2", + "0x8aadf9b895aeb8fdc9987daa937e25d6964cbd5ec5d176f5cdf2f0c73f6f145f0f9759e7560ab740bf623a3279736c37", + "0x99aeda8a495031cc5bdf9b842a4d7647c55004576a0edc0bd9b985d60182608361ed5459a9d4b21aa8e2bd353d10a086", + "0x832c8b3bfcd6e68eee4b100d58014522de9d4cefa99498bc06c6dca83741e4572e20778e0d846884b33439f160932bca", + "0x841f56ebefc0823ab484fc445d62f914e13957e47904419e42771aa605e33ab16c44f781f6f9aa42e3a1baf377f54b42", + "0xa6e40271d419e295a182725d3a9b541ffd343f23e37549c51ecaa20d13cf0c8d282d6d15b24def5702bfee8ba10b12ac", + "0x8ac00925ac6187a4c5cde48ea2a4eaf99a607e58b2c617ee6f01df30d03fafada2f0469178dd960d9d64cbd33a0087d8", + "0xb6b80916b540f8a0fe4f23b1a06e2b830008ad138271d5ba3cd16d6619e521fe2a7623c16c41cba48950793386eea942", + "0x8412c0857b96a650e73af9d93087d4109dd092ddf82188e514f18fcac644f44d4d62550bfa63947f2d574a2e9d995bbb", + "0xb871395baa28b857e992a28ac7f6d95ec461934b120a688a387e78498eb26a15913b0228488c3e2360391c6b7260b504", + "0x926e2d25c58c679be77d0e27ec3b580645956ba6f13adcbc2ea548ee1b7925c61fcf74c582337a3b999e5427b3f752f2", + "0xa165fa43fecae9b913d5dcfc232568e3e7b8b320ce96b13800035d52844c38fd5dbf7c4d564241d860c023049de4bcbc", + "0xb4976d7572fd9cc0ee3f24888634433f725230a7a2159405946a79315bc19e2fc371448c1c9d52bf91539fd1fe39574b", + "0xa6b461eb72e07a9e859b9e16dfa5907f4ac92a5a7ca4368b518e4a508dc43f9b4be59db6849739f3ef4c44967b63b103", + "0xb976606d3089345d0bc501a43525d9dca59cf0b25b50dfc8a61c5bd30fac2467331f0638fab2dc68838aa6ee8d2b6bc9", + "0xb16ea61c855da96e180abf7647fa4d9dd6fd90adebadb4c5ed4d7cd24737e500212628fca69615d89cb40e9826e5a214", + "0x95a3e3162eb5ea27a613f8c188f2e0dcc5cbd5b68c239858b989b004d87113e6aa3209fa9fad0ee6ecef42814ba9db1a", + "0xb6a026ab56d3224220e5bce8275d023c8d39d1bdf7eec3b0923429b7d5ef18cf613a3591d364be8727bb1fa0ba11eabb", + "0x949f117e2e141e25972ee9ccdd0b7a21150de7bbf92bbd89624a0c5f5a88da7b2b172ba2e9e94e1768081f260c2a2f8d", + "0xb7c5e9e6630287d2a20a2dfb783ffe6a6ff104ff627c6e4e4342acc2f3eb6e60e9c22f465f8a8dc58c42f49840eca435", + "0x872be5a75c3b85de21447bb06ac9eb610f3a80759f516a2f99304930ddf921f34cbffc7727989cdd7181d5fc62483954", + "0xa50976ea5297d797d220932856afdd214d1248230c9dcd840469ecc28ea9f305b6d7b38339fedb0c00b5251d77af8c95", + "0x80b360f8b44914ff6f0ffbd8b5360e3cabe08639f6fe06d0c1526b1fe9fe9f18c497f1752580b30e950abd3e538ad416", + "0xa2f98f9bf7fac78c9da6bb41de267742a9d31cf5a04b2fb74f551084ec329b376f651a59e1ae919b2928286fb566e495", + "0x8b9d218a8a6c150631548e7f24bbd43f132431ae275c2b72676abbea752f554789c5ff4aac5c0eeee5529af7f2b509ef", + "0xaa21a243b07e9c7b169598bf0b102c3c280861780f83121b2ef543b780d47aaa4b1850430ee7927f33ece9847c4e0e1a", + "0x8a6f90f4ce58c8aa5d3656fe4e05acccf07a6ec188a5f3cde7bf59a8ae468e66f055ac6dfc50b6e8e98f2490d8deedc5", + "0x8e39f77ca4b5149ffe9945ceac35d068760ba338d469d57c14f626dd8c96dbe993dd7011beff727c32117298c95ee854", + "0x83bd641c76504222880183edd42267e0582642c4993fe2c7a20ce7168e4c3cbf7586e1d2d4b08c84d9b0bf2f6b8800b8", + "0xa9d332993cf0c1c55130e5cf3a478eb5e0bfb49c25c07538accc692ef03d82b458750a7b991cc0b41b813d361a5d31e3", + "0xa0fc60e6a6015df9bee04cea8f20f01d02b14b6f7aa03123ab8d65da071b2d0df5012c2a69e7290baae6ed6dd29ebe07", + "0xa2949dde2e48788ceaac7ec7243f287ffe7c3e788cdba97a4ab0772202aeef2d50382bed8bf7eff5478243f7eabe0bda", + "0xa7879373ea18572dba6cf29868ca955ffa55b8af627f29862f6487ee398b81fe3771d8721ca8e06716c5d91b9ac587cb", + "0xb3c7081e2c5306303524fbe9fe5645111a57dffd4ec25b7384da12e56376a0150ab52f9d9cc6ca7bdd950695e39b766d", + "0xa634a6a19d52dcb9f823352b36c345d2de54b75197bcd90528d27830bd6606d1a9971170de0849ed5010afa9f031d5be", + "0x88f2062f405fa181cfdb8475eaf52906587382c666ca09a9522537cfebbc7de8337be12a7fd0db6d6f2f7ab5aefab892", + "0xb1f0058c1f273191247b98783b2a6f5aa716cf799a8370627fc3456683f03a624d0523b63a154fe9243c0dfd5b37c460", + "0xae39a227cc05852437d87be6a446782c3d7fbe6282e25cf57b6b6e12b189bdc0d4a6e2c3a60b3979256b6b5baf8f1c5f", + "0x802a1af228ab0c053b940e695e7ef3338f5be7acf4e5ed01ac8498e55b492d3a9f07996b1700a84e22f0b589638909cd", + "0xa36490832f20e4b2f9e79ee358b66d413f034d6a387534b264cdeac2bca96e8b5bcbdd28d1e98c44498032a8e63d94d2", + "0x8728c9a87db2d006855cb304bba54c3c704bf8f1228ae53a8da66ca93b2dac7e980a2a74f402f22b9bc40cd726e9c438", + "0xa08f08ab0c0a1340e53b3592635e256d0025c4700559939aeb9010ed63f7047c8021b4210088f3605f5c14fb51d1c613", + "0x9670fd7e2d90f241e8e05f9f0b475aa260a5fb99aa1c9e61cd023cbad8ed1270ae912f168e1170e62a0f6d319cf45f49", + "0xa35e60f2dd04f098bf274d2999c3447730fe3e54a8aff703bc5a3c274d22f97db4104d61a37417d93d52276b27ef8f31", + "0x859df7a21bc35daec5695201bd69333dc4f0f9e4328f2b75a223e6615b22b29d63b44d338413ca97eb74f15563628cb7", + "0xb2b44ad3e93bc076548acdf2477803203108b89ecc1d0a19c3fb9814d6b342afc420c20f75e9c2188ad75fdb0d34bb2d", + "0x941173ee2c87765d10758746d103b667b1227301e1bcfecef2f38f9ab612496a9abd3050cef5537bf28cfecd2aacc449", + "0x92b0bea30ebed20ac30648efb37bac2b865daaa514316e6f5470e1de6cb84651ff77c127aa7beed4521bda5e8fc81122", + "0xaf17bf813bb238cf8bb437433f816786612209180a6c0a1d5141292dc2d2c37164ef13bfc50c718bfcc6ce26369298a2", + "0x8461fd951bdfda099318e05cc6f75698784b033f15a71bce26165f0ce421fd632d50df9eeced474838c0050b596e672c", + "0x83281aa18ae4b01e8201e1f64248cc6444c92ee846ae72adb178cef356531558597d84ff93a05abf76bfe313eb7dbe86", + "0xb62b150f73999c341daa4d2f7328d2f6ca1ef3b549e01df58182e42927537fc7971c360fe8264af724f4c0247850ef12", + "0xa7022a201f79c012f982b574c714d813064838a04f56964d1186691413757befeeaada063e7884297606e0eea1b1ed43", + "0xa42ac9e8be88e143853fd8e6a9ff21a0461801f0ac76b69cca669597f9af17ecb62cccdcdcbe7f19b62ab93d7f838406", + "0x80f1ca73b6ba3a2fbae6b79b39c0be8c39df81862d46c4990c87cbf45b87996db7859d833abc20af2fcb4faf059c436a", + "0xb355943e04132d5521d7bbe49aea26f6aa1c32f5d0853e77cc2400595325e923a82e0ff7601d1aee79f45fd8a254f6ae", + "0x87142c891d93e539b31d0b5ead9ea600b9c84db9be9369ff150a8312fe3d10513f4c5b4d483a82b42bc65c45dd9dd3bd", + "0x823c3d7f6dda98a9d8c42b3fee28d3154a95451402accadb6cf75fc45d2653c46a569be75a433094fa9e09c0d5cf1c90", + "0xb3c3497fe7356525c1336435976e79ec59c5624c2fb6185ee09ca0510d58b1e392965e25df8a74d90d464c4e8bb1422b", + "0x88c48d83e8ddc0d7eea051f3d0e21bc0d3a0bb2b6a39ece76750c1c90c382a538c9a35dc9478b8ceb8157dcccbbf187a", + "0x93da81a8939f5f58b668fefdc6f5f7eca6dc1133054de4910b651f8b4a3267af1e44d5a1c9e5964dc7ab741eb146894b", + "0x8b396e64985451ac337f16be61105106e262e381ea04660add0b032409b986e1ac64da3bc2feae788e24e9cb431d8668", + "0x9472068b6e331ea67e9b5fbf8057672da93c209d7ded51e2914dbb98dccd8c72b7079b51fd97a7190f8fc8712c431538", + "0xac47e1446cb92b0a7406f45c708567f520900dfa0070d5e91783139d1bfc946d6e242e2c7b3bf4020500b9f867139709", + "0x896053706869fb26bb6f7933b3d9c7dd6db5c6bd1269c7a0e222b73039e2327d44bda7d7ae82bf5988808b9831d78bcd", + "0xa55e397fa7a02321a9fe686654c86083ecedb5757586d7c0250ec813ca6d37151a12061d5feca4691a0fd59d2f0fdd81", + "0xae23f08ac2b370d845036518f1bddb7fea8dc59371c288a6af310486effeb61963f2eef031ca90f9bdbcf0e475b67068", + "0xb5462921597a79f66c0fec8d4c7cfd89f427692a7ce30d787e6fd6acd2377f238ec74689a0fdbe8ef3c9c9bd24b908dc", + "0xae67e8ea7c46e29e6aae6005131c29472768326819aa294aaf5a280d877de377b44959adb1348fa3e929dcbc3ae1f2c0", + "0x84962b4c66500a20c4424191bdfb619a46cda35bdb34c2d61edcb0b0494f7f61dd5bf8f743302842026b7b7d49edd4b5", + "0x846f76286dc3cc59cb15e5dabb72a54a27c78190631df832d3649b2952fa0408ecde7d4dfdae7046c728efa29879fb51", + "0x8f76c854eaee8b699547e07ad286f7dadfa6974c1328d12502bd7630ae619f6129272fdd15e2137ffef0143c42730977", + "0x8007b163d4ea4ec6d79e7a2aa19d06f388da0b3a56f3ee121441584e22a246c0e792431655632bf6e5e02cb86914eebf", + "0xac4d2cecc1f33e6fb73892980b61e62095ddff5fd6167f53ca93d507328b3c05440729a277dc3649302045b734398af1", + "0x92d2a88f2e9c9875abaff0d42624ccb6d65401de7127b5d42c25e6adccd7a664504c5861618f9031ced8aeb08b779f06", + "0xa832c1821c1b220eb003fc532af02c81196e98df058cdcc9c9748832558362915ea77526937f30a2f74f25073cb89afb", + "0xb6f947ab4cc2baec100ed8ec7739a2fd2f9504c982b39ab84a4516015ca56aea8eef5545cfc057dd44c69b42125fb718", + "0xb24afacf2e90da067e5c050d2a63878ee17aaf8fd446536f2462da4f162de87b7544e92c410d35bf2172465940c19349", + "0xb7a0aa92deac71eaab07be8fa43086e071e5580f5dbf9b624427bdd7764605d27303ae86e5165bed30229c0c11958c38", + "0xb0d1d5bfa1823392c5cf6ed927c1b9e84a09a24b284c2cd8fcb5fda8e392c7c59412d8f74eb7c48c6851dff23ae66f58", + "0xa24125ef03a92d2279fb384186ca0274373509cfec90b34a575490486098438932ee1be0334262d22d5f7d3db91efe67", + "0x83e08e5fba9e8e11c164373794f4067b9b472d54f57f4dbe3c241cf7b5b7374102de9d458018a8c51ab3aed1dddf146f", + "0x9453101b77bb915ed40990e1e1d2c08ea8ec5deb5b571b0c50d45d1c55c2e2512ec0ceca616ff0376a65678a961d344d", + "0x92a0516e9eb6ad233d6b165a8d64a062ce189b25f95d1b3264d6b58da9c8d17da2cd1f534800c43efcf2be73556cd2ff", + "0x958d0b5d7d8faf25d2816aa6a2c5770592ad448db778dd9b374085baa66c755b129822632eaabcb65ee35f0bf4b73634", + "0x90a749de8728b301ad2a6b044e8c5fd646ccd8d20220e125cba97667e0bb1d0a62f6e3143b28f3d93f69cdc6aa04122a", + "0x84bd34c8d8f74dec07595812058db24d62133c11afed5eb2a8320d3bfc28e442c7f0cfd51011b7b0bb3e5409cb7b6290", + "0xaecc250b556115d97b553ad7b2153f1d69e543e087890000eaa60f4368b736921d0342ce5563124f129096f5d5e2ca9d", + "0x977f17ac82ed1fbf422f9b95feb3047a182a27b00960296d804fd74d54bb39ad2c055e665c1240d2ad2e06a3d7501b00", + "0xaf5be9846bd4879ebe0af5e7ad253a632f05aedfe306d31fe6debe701ba5aa4e33b65efc05043bc73aadb199f94baed4", + "0x9199e12ec5f2aaaeed6db5561d2dcc1a8fe9c0854f1a069cba090d2dff5e5ba52b10c841ccbd49006a91d881f206150d", + "0x8f4a96a96ed8ceaf3beba026c89848c9ca4e6452ce23b7cf34d12f9cc532984a498e051de77745bdc17c7c44c31b7c30", + "0xaf3f2a3dbe8652c4bfca0d37fb723f0e66aab4f91b91a625114af1377ad923da8d36da83f75deb7a3219cd63135a3118", + "0xa6d46963195df8962f7aa791d104c709c38caa438ddd192f7647a884282e81f748c94cdf0bb25d38a7b0dc1b1d7bbcf7", + "0x86f3de4b22c42d3e4b24b16e6e8033e60120af341781ab70ae390cb7b5c5216f6e7945313c2e04261a51814a8cb5db92", + "0xb9f86792e3922896cfd847d8ff123ff8d69ecf34968fb3de3f54532f6cd1112b5d34eeabdca46ae64ad9f6e7e5b55edc", + "0x83edfbcbc4968381d1e91ab813b3c74ab940eaf6358c226f79182f8b21148ec130685fd91b0ea65916b0a50bccf524ea", + "0x93b61daca7a8880b7926398760f50016f2558b0bab74c21181280a1baf3414fc539911bb0b79c4288d29d3c4ad0f4417", + "0xad541aeb83a47526d38f2e47a5ce7e23a9adabe5efeae03541026881e6d5ef07da3ac1a6ed466ca924fa8e7a91fcff88", + "0xac4bba31723875025640ed6426003ed8529215a44c9ffd44f37e928feef9fc4dfa889088131c9be3da87e8f3fdf55975", + "0x88fa4d49096586bc9d29592909c38ea3def24629feacd378cc5335b70d13814d6dac415f8c699ee1bf4fe8b85eb89b38", + "0xb67d0b76cbd0d79b71f4673b96e77b6cda516b8faa1510cfe58ff38cc19000bb5d73ff8418b3dab8c1c7960cb9c81e36", + "0x98b4f8766810f0cfecf67bd59f8c58989eb66c07d3dfeee4f4bbce8fd1fce7cc4f69468372eaec7d690748543bd9691d", + "0x8445891af3c298b588dec443beacdf41536adb84c812c413a2b843fd398e484eb379075c64066b460839b5fe8f80177c", + "0xb603635c3ed6fdc013e2a091fc5164e09acf5f6a00347d87c6ebadb1f44e52ff1a5f0466b91f3f7ffc47d25753e44b75", + "0x87ec2fc928174599a9dafe7538fec7dcf72e6873b17d953ed50708afff0da37653758b52b7cafa0bf50dfcf1eafbb46c", + "0xb9dbd0e704d047a457d60efe6822dc679e79846e4cbcb11fa6c02079d65673ee19bbf0d14e8b7b200b9205f4738df7c7", + "0x9591ec7080f3f5ba11197a41f476f9ba17880f414d74f821a072ec5061eab040a2acba3d9856ff8555dfe5eaeb14ca19", + "0xb34c9d1805b5f1ce38a42b800dec4e7f3eb8c38e7d2b0a525378e048426fed150dbfe9cc61f5db82b406d1b9ff2d10bf", + "0xa36fdc649dc08f059dfa361e3969d96b4cc4a1ebf10b0cd01a7dd708430979e8d870961fef85878f8779b8e23caafb18", + "0x88dfc739a80c16c95d9d6f73c3357a92d82fa8c3c670c72bee0f1e4bac9ec338e1751eb786eda3e10f747dd7a686900f", + "0x84a535ad04f0961756c61c70001903a9adf13126983c11709430a18133c4b4040d17a33765b4a06968f5d536f4bfb5c5", + "0x8c86d695052a2d2571c5ace744f2239840ef21bb88e742f050c7fa737cd925418ecef0971333eb89daa6b3ddfede268c", + "0x8e9a700157069dc91e08ddcbdde3a9ad570272ad225844238f1015004239c542fceb0acce6d116c292a55f0d55b6175e", + "0x84d659e7f94e4c1d15526f47bc5877a4ef761c2a5f76ec8b09c3a9a30992d41b0e2e38ed0c0106a6b6c86d670c4235f3", + "0xa99253d45d7863db1d27c0ab561fb85da8c025ba578b4b165528d0f20c511a9ca9aff722f4ff7004843f618eb8fced95", + "0x89a3cacb15b84b20e95cd6135550146bbe6c47632cc6d6e14d825a0c79b1e02b66f05d57d1260cb947dc4ae5b0283882", + "0x8385b1555e794801226c44bd5e878cbe68aeac0a19315625a8e5ea0c3526b58cdd4f53f9a14a167a5e8a293b530d615a", + "0xb68c729e9df66c5cd22af4909fb3b0057b6a231c4a31cd6bf0fa0e53c5809419d15feb483de6e9408b052458e819b097", + "0x924f56eda269ec7ec2fc20c5731bf7f521546ddf573ccbe145592f1c9fee5134747eb648d9335119a8066ca50a1f7e50", + "0xb2100a26b9c3bec7ec5a53f0febbf56303f199be2f26b2d564cfee2adc65483b84192354f2865c2f4c035fa16252ae55", + "0x8f64dbed62e638563967ec1605a83216aed17eb99aa618c0543d74771ea8f60bbb850c88608d4f8584f922e30a8a0a72", + "0xb31b9e1ffe8d7260479c9413f8e680f3fe391ae8fcf44fcca3000d9b2473a40c1d32299f8f63865a57579a2d6c7e9f08", + "0xa5b1d136142eb23e322c6c07cb838a3f58ab6925472352ebd0bb47041a0d8729e1074ca223922f3a7a672ced7a1e562d", + "0x8d9470a5a15d833a447b5f108333d50f30aa7659e331c3f8080b1e928a99922edc650466a2f54f3d48afdb34bff42142", + "0x866368f5891564e5b2de37ad21ff0345c01129a14ea5667f9b64aad12d13ec034622872e414743af0bf20adb2041b497", + "0x88ef9c2ebf25fd0c04b7cfa35fbac2e4156d2f1043fa9f98998b2aa402c8f9a4f1039e782451a46840f3e0e4b3fa47d3", + "0x94ba04a4859273697e264a2d238dc5c9ff573ebc91e4796ea58eebe4080c1bf991255ab2ad8fb1e0301ce7b79cc6e69b", + "0x86b6bd0953309a086e526211bf1a99327269304aa74d8cdc994cee63c3a2d4b883e832b0635888dff2a13f1b02eb8df4", + "0x843ea6ea5f2c7a1fd50be56a5765dcce3ea61c99b77c1a729ee0cd8ec706385ac7062e603479d4c8d3527f030762d049", + "0x8d3675195a3b06f2d935d45becc59f9fa8fa440c8df80c029775e47fe9c90e20f7c8e4cc9a2542dd6bfe87536c428f0d", + "0x8978580b0c9b0aa3ab2d47e3cfd92fa891d3ddee57829ee4f9780e8e651900457d8e759d1a9b3e8f6ae366e4b57f2865", + "0x890112ec81d0f24b0dfbb4d228e418eff02ae63dc691caf59c1d103e1d194e6e2550e1bec41c0bfdb74fed454f621d0c", + "0x97da00bd4b19d1e88caff7f95b8b9a7d29bc0afe85d0c6a163b4b9ef336f0e90e2c49ce6777024bb08df908cc04ea1ca", + "0xb458268d275a5211106ccaa8333ce796ef2939b1c4517e502b6462e1f904b41184a89c3954e7c4f933d68b87427a7bfd", + "0xaac9c043ba8ba9283e8428044e6459f982413380ee7005a996dc3cc468f6a21001ecaa3b845ce2e73644c2e721940033", + "0x82145013c2155a1200246a1e8720adf8a1d1436b10d0854369d5b1b6208353e484dd16ce59280c6be84a223f2d45e5e2", + "0xb301bafa041f9b203a46beab5f16160d463aa92117c77a3dc6a9261a35645991b9bafcc186c8891ca95021bd35f7f971", + "0xa531b8d2ac3de09b92080a8d8857efa48fb6a048595279110e5104fee7db1dd7f3cfb8a9c45c0ed981cbad101082e335", + "0xa22ac1d627d08a32a8abd41504b5222047c87d558ffae4232cefdeb6a3dc2a8671a4d8ddfba2ff9068a9a3ffb0fe99b1", + "0xb8d9f0e383c35afb6d69be7ff04f31e25c74dd5751f0e51290c18814fbb49ee1486649e64355c80e93a3d9278bd21229", + "0x8165babccd13033a3614c878be749dfa1087ecbeee8e95abcfffe3aa06695711122cb94477a4d55cffd2febf0c1173de", + "0xa4c1bc84ecb9d995d1d21c2804adf25621676d60334bd359dac3a2ec5dc8de567aa2831c10147034025fb3e3afb33c4b", + "0xb77307cab8e7cb21e4038493058fb6db9e2ec91dda9d7f96f25acbc90309daf7b6d8a205682143ee35d675e9800c3b08", + "0xaaf7466083cd1f325ba860efe3faf4cebe6a5eecf52c3e8375d72043a5cfc8e6cb4b40f8e48f97266e84f0d488e8badf", + "0x9264a05a3abc2a5b4958f957f3a486a5eb3ddd10ff57aa6943c9430d0cfa01d63b72695b1ade50ac1b302d312175e702", + "0xb3f9e4c589ad28b1eceed99dc9980fac832524cfcbe4a486dfeedb4b97c080e24bdb3967e9ca63d2240e77f9addfaefd", + "0xb2c1e253a78e7179e5d67204422e0debfa09c231970b1bfb70f31a8d77c7f5059a095ca79d2e9830f12c4a8f88881516", + "0x81865a8a25913d1072cb5fd9505c73e0fde45e4c781ddd20fb0a7560d8b1cd5e1f63881c6efc05360e9204dfa6c3ce16", + "0xab71c2ea7fa7853469a2236dedb344a19a6130dc96d5fd6d87d42d3fffda172557d203b7688ce0f86acd913ce362e6cd", + "0x8aa2051bc3926c7bd63565f3782e6f77da824cb3b22bb056aa1c5bccfa274c0d9e49a91df62d0e88876e2bd7776e44b9", + "0xb94e7074167745323d1d353efe7cfb71f40a390e0232354d5dfd041ef523ac8f118fb6dcc42bf16c796e3f61258f36f8", + "0x8210fcf01267300cb1ccf650679cf6e1ee46df24ae4be5364c5ff715332746c113d680c9a8be3f17cacaeb3a7ba226ce", + "0x905ac223568eedc5acd8b54e892be05a21abbb4083c5dbec919129f9d9ffa2c4661d78d43bf5656d8d7aafa06f89d647", + "0xa6e93da7e0c998e6ce2592d1aa87d12bf44e71bec12b825139d56682cdce8f0ba6dbfe9441a9989e10578479351a3d9d", + "0xacde928a5e2df0d65de595288f2b81838155d5673013100a49b0cb0eb3d633237af1378148539e33ccd1b9a897f0fec3", + "0xa6e1a47e77f0114be6ae7acd2a51e6a9e38415cce7726373988153cdd5d4f86ef58f3309adc5681af4a159300ed4e5b5", + "0xad2b6a0d72f454054cb0c2ebc42cd59ff2da7990526bd4c9886003ba63b1302a8343628b8fe3295d3a15aa85150e0969", + "0xb0bc3aea89428d7918c2ee0cc57f159fba134dad224d0e72d21a359ca75b08fbb4373542f57a6408352033e1769f72c6", + "0xaad0497525163b572f135fad23fdd8763631f11deeaf61dea5c423f784fe1449c866040f303555920dc25e39cdb2e9b4", + "0x8ce5d8310d2e17342bf881d517c9afc484d12e1f4b4b08ad026b023d98cba410cd9a7cc8e2c3c63456652a19278b6960", + "0x8d9d57dbb24d68b6152337872bd5d422198da773174ade94b633f7c7f27670ff91969579583532ae7d8fe662c6d8a3b0", + "0x855a1c2d83becb3f02a8f9a83519d1cb112102b61d4cdd396844b5206e606b3fefdbcc5aa8751da2b256d987d74d9506", + "0x90eb7e6f938651f733cf81fcd2e7e8f611b627f8d94d4ac17ac00de6c2b841e4f80cada07f4063a13ae87b4a7736ca28", + "0x8161459a21d55e7f5f1cecfc1595c7f468406a82080bfa46d7fb1af4b5ec0cd2064c2c851949483db2aa376e9df418e6", + "0x8344ccd322b2072479f8db2ab3e46df89f536408cba0596f1e4ec6c1957ff0c73f3840990f9028ae0f21c1e9a729d7df", + "0x929be2190ddd54a5afe98c3b77591d1eae0ab2c9816dc6fe47508d9863d58f1ea029d503938c8d9e387c5e80047d6f1e", + "0x856e3d1f701688c650c258fecd78139ce68e19de5198cf1cd7bb11eba9d0f1c5af958884f58df10e3f9a08d8843f3406", + "0x8490ae5221e27a45a37ca97d99a19a8867bcc026a94f08bdccfbb4b6fa09b83c96b37ec7e0fd6ee05f4ae6141b6b64a8", + "0xb02dbd4d647a05ac248fda13708bba0d6a9cd00cae5634c1938b4c0abbb3a1e4f00f47aa416dcd00ffcdf166330bff9a", + "0x9076164bb99ca7b1a98d1e11cb2f965f5c22866658e8259445589b80e3cb3119c8710ede18f396ba902696785619079c", + "0xaacf016920936dae63778ad171386f996f65fe98e83cfcdd75e23774f189303e65cc8ad334a7a62f9230ed2c6b7f6fa4", + "0xa8031d46c7f2474789123469ef42e81c9c35eb245d38d8f4796bba406c02b57053f5ec554d45373ab437869a0b1af3f0", + "0xa4b76cd82dc1f305a0ee053e9a4212b67f5acc5e69962a8640d190a176b73fbc2b0644f896ff3927cd708d524668ed09", + "0xb00b029c74e6fdf7fb94df95ef1ccad025c452c19cddb5dccfb91efdcb8a9a1c17847cfa4486eae4f510e8a6c1f0791a", + "0x9455e5235f29a73e9f1a707a97ddb104c55b9d6a92cc9952600d49f0447d38ea073ee5cf0d13f7f55f12b4a5132f4b10", + "0xae118847542ed1084d269e8f3b503d0b6571a2c077def116ad685dcca2fca3dcb3f86e3f244284bdcd5ae7ac968d08a5", + "0x8dcb4965cd57e8b89cd71d6fc700d66caa805bfd29ab71357961527a7894e082d49145c2614b670dcb231ab9050d0663", + "0xadd6ed14f3183f4acc73feea19b22c9a330e431c674e5034924da31b69e8c02d79b570d12ef771a04215c4809e0f8a80", + "0x96ae7e110412ee87d0478fdbdbaab290eb0b6edd741bb864961845e87fd44bcbe630371060b8104d8bf17c41f2e3fca0", + "0xa20db17f384e9573ca0928af61affab6ff9dd244296b69b026d737f0c6cd28568846eca8dadf903ee0eecbb47368351d", + "0x937bfdf5feb0797863bc7c1be4dcc4f2423787952a3c77dfa3bfe7356f5dbcc4daebde976b84fc6bd97d5124fb8f85c9", + "0xa7050cc780445c124e46bba1acc0347ddcfa09a85b35a52cc5808bf412c859c0c680c0a82218f15a6daeefe73f0d0309", + "0xa9d9b93450e7630f1c018ea4e6a5ca4c19baa4b662eadfbe5c798fe798d8a3775ed1eb12bd96a458806b37ab82bdc10a", + "0xa52a4d5639e718380915daaefad7de60764d2d795443a3db7aeab5e16a1b8faa9441a4ccc6e809d8f78b0ac13eef3409", + "0x8e6f72b6664a8433b032849b03af68f9376b3c16c0bc86842c43fc7bf31e40bc9fc105952d5c5780c4afa19d7b802caa", + "0xa107ae72f037000c6ee14093de8e9f2c92aa5f89a0a20007f4126419e5cb982469c32187e51a820f94805c9fccd51365", + "0x9708218f9a984fe03abc4e699a4f3378a06530414a2e95e12ca657f031ef2e839c23fd83f96a4ba72f8203d54a1a1e82", + "0xb9129770f4c5fcac999e98c171d67e148abd145e0bf2a36848eb18783bb98dff2c5cef8b7407f2af188de1fae9571b1c", + "0x88cc9db8ff27eb583871eeeb517db83039b85404d735517c0c850bdfa99ae1b57fd24cf661ab60b4726878c17e047f37", + "0xa358c9aadc705a11722df49f90b17a2a6ba057b2e652246dc6131aaf23af66c1ca4ac0d5f11073a304f1a1b006bc0aa5", + "0xac79f25af6364a013ba9b82175ccee143309832df8f9c3f62c193660253679284624e38196733fb2af733488ab1a556e", + "0x82338e3ed162274d41a1783f44ae53329610134e6c62565353fbcc81131e88ce9f8a729d01e59e6d73695a378315111b", + "0xaa5ddcabf580fd43b6b0c3c8be45ffd26c9de8fa8d4546bb92d34f05469642b92a237d0806a1ad354f3046a4fcf14a92", + "0xb308d2c292052a8e17862c52710140ffafa0b3dbedd6a1b6334934b059fe03e49883529d6baf8b361c6e67b3fbf70100", + "0x96d870a15c833dddd8545b695139733d4a4c07d6206771a1524500c12607048731c49ec4ac26f5acc92dd9b974b2172c", + "0x8e99ee9ed51956d05faaf5038bffd48a2957917a76d9974a78df6c1ff3c5423c5d346778f55de07098b578ad623a390e", + "0xa19052d0b4b89b26172c292bbf6fd73e7486e7fd3a63c7a501bbd5cf7244e8e8ce3c1113624086b7cdf1a7693fdad8b5", + "0x958957caf99dc4bb6d3c0bc4821be10e3a816bd0ba18094603b56d9d2d1383ccc3ee8bc36d2d0aea90c8a119d4457eb4", + "0x8482589af6c3fc4aa0a07db201d8c0d750dd21ae5446ff7a2f44decf5bff50965fd6338745d179c67ea54095ecd3add4", + "0x8a088cc12cf618761eaa93da12c9158b050c86f10cd9f865b451c69e076c7e5b5a023e2f91c2e1eed2b40746ca06a643", + "0x85e81101590597d7671f606bd1d7d6220c80d3c62e9f20423e734482c94547714a6ac0307e86847cce91de46503c6a8a", + "0xb1bd39b481fc452d9abf0fcb73b48c501aaae1414c1c073499e079f719c4e034da1118da4ff5e0ce1c5a71d8af3f4279", + "0x942ae5f64ac7a5353e1deb2213f68aa39daa16bff63eb5c69fc8d9260e59178c0452227b982005f720a3c858542246c8", + "0x99fea18230e39df925f98e26ff03ab959cae7044d773de84647d105dfa75fd602b4f519c8e9d9f226ec0e0de0140e168", + "0x97b9841af4efd2bfd56b9e7cd2275bc1b4ff5606728f1f2b6e24630dbe44bc96f4f2132f7103bca6c37057fc792aeaab", + "0x94cdad044a6ab29e646ed30022c6f9a30d259f38043afcea0feceef0edc5f45297770a30718cbfec5ae7d6137f55fe08", + "0xa533a5efa74e67e429b736bb60f2ccab74d3919214351fe01f40a191e3ec321c61f54dd236f2d606c623ad556d9a8b63", + "0xb7bd0bb72cd537660e081f420545f50a6751bb4dd25fde25e8218cab2885dd81ffe3b888d608a396dfcb78d75ba03f3f", + "0xb1479e7aa34594ec8a45a97611d377206597149ece991a8cef1399738e99c3fa124a40396a356ab2ea135550a9f6a89f", + "0xb75570fc94b491aef11f70ef82aeb00b351c17d216770f9f3bd87f3b5ac90893d70f319b8e0d2450dc8e21b57e26df94", + "0xa5e3f3ab112530fe5c3b41167f7db5708e65479b765b941ce137d647adb4f03781f7821bb4de80c5dc282c6d2680a13d", + "0xb9b9c81b4cac7aca7e7c7baac2369d763dd9846c9821536d7467b1a7ec2e2a87b22637ab8bbeddb61879a64d111aa345", + "0xb1e3ee2c4dd03a60b2991d116c372de18f18fe279f712829b61c904103a2bd66202083925bc816d07884982e52a03212", + "0xa13f0593791dbbd360b4f34af42d5cc275816a8db4b82503fe7c2ff6acc22ae4bd9581a1c8c236f682d5c4c02cc274cc", + "0x86ba8238d3ed490abcc3f9ecc541305876315fb71bca8aaf87538012daab019992753bf1e10f8670e33bff0d36db0bf0", + "0xb65fbb89fafb0e2a66fe547a60246d00b98fe2cb65db4922d9cef6668de7b2f4bb6c25970f1e112df06b4d1d953d3f34", + "0xabb2d413e6f9e3c5f582e6020f879104473a829380b96a28123eb2bdd41a7a195f769b6ac70b35ba52a9fee9d6a289c3", + "0x88ec764573e501c9d69098a11ea1ad20cdc171362f76eb215129cfcca43460140741ea06cee65a1f21b708afb6f9d5b0", + "0xa7aaec27246a3337911b0201f4c5b746e45780598004dac15d9d15e5682b4c688158adffdef7179abb654f686e4c6adc", + "0xa1128589258f1fbfa33341604c3cb07f2a30c651086f90dce63ae48b4f01782e27c3829de5102f847cde140374567c58", + "0xaaf2b149c1ca9352c94cc201125452b1ed7ca7c361ed022d626899426cb2d4cc915d76c58fa58b3ad4a6284a9ae1bc45", + "0xaaf5c71b18b27cd8fe1a9028027f2293f0753d400481655c0d88b081f150d0292fb9bd3e6acabb343a6afb4afdb103b5", + "0x947c0257d1fb29ecc26c4dc5eab977ebb47d698b48f9357ce8ff2d2ed461c5725228cc354a285d2331a60d20de09ff67", + "0xb73e996fa30f581699052ed06054c474ebdf3ae662c4dc6f889e827b8b6263df67aeff7f2c7f2919df319a99bdfdceb1", + "0xb696355d3f742dd1bf5f6fbb8eee234e74653131278861bf5a76db85768f0988a73084e1ae03c2100644a1fa86a49688", + "0xb0abca296a8898ac5897f61c50402bd96b59a7932de61b6e3c073d880d39fc8e109998c9dba666b774415edddcff1997", + "0xb7abe07643a82a7cb409ee4177616e4f91ec1cf733699bf24dec90da0617fe3b52622edec6e12f54897c4b288278e4f3", + "0x8a3fae76993edbc81d7b47f049279f4dd5c408133436605d934dee0eadde187d03e6483409713db122a2a412cd631647", + "0x82eb8e48becfdf06b2d1b93bf072c35df210cf64ed6086267033ad219bf130c55ee60718f28a0e1cad7bc0a39d940260", + "0xa88f783e32944a82ea1ea4206e52c4bcf9962b4232e3c3b45bd72932ee1082527bf80864ce82497e5a8e40f2a60962d0", + "0x830cf6b1e99430ae93a3f26fbfb92c741c895b017924dcd9e418c3dc4a5b21105850a8dd2536fa052667e508b90738f2", + "0x990dce4c2c6f44bb6870328fba6aa2a26b0b8b2d57bfb24acf398b1edc0f3790665275f650884bd438d5403973469fa2", + "0xa2e5b6232d81c94bcb7fed782e2d00ff70fc86a3abddbe4332cb0544b4e109ae9639a180ae4c1f416752ed668d918420", + "0xb4cdf7c2b3753c8d96d92eb3d5fa984fef5d346a76dc5016552069e3f110356b82e9585b9c2f5313c76ffaecef3d6fd8", + "0x83b23b87f91d8d602bff3a4aa1ead39fcc04b26cf113a9da6d2bd08ba7ea827f10b69a699c16911605b0126a9132140f", + "0x8aae7a2d9daa8a2b14f9168fe82933b35587a3e9ebf0f9c37bf1f8aa015f18fb116b7fba85a25c0b5e9f4b91ba1d350b", + "0x80d1163675145cc1fab9203d5581e4cd2bed26ad49f077a7927dec88814e0bed7912e6bbe6507613b8e393d5ee3be9be", + "0x93ddeb77b6a4c62f69b11cf36646ed089dcaa491590450456a525faf5659d810323b3effa0b908000887c20ac6b12c80", + "0x9406360a2b105c44c45ba440055e40da5c41f64057e6b35a3786526869b853472e615e6beb957b62698a2e8a93608e13", + "0x93bfc435ab9183d11e9ad17dac977a5b7e518db720e79a99072ce7e1b8fcb13a738806f414df5a3caa3e0b8a6ce38625", + "0x8a12402c2509053500e8456d8b77470f1bbb9785dd7995ebbbe32fd7171406c7ce7bd89a96d0f41dbc6194e8f7442f42", + "0xaab901e35bf17e6422722c52a9da8b7062d065169bf446ef0cbf8d68167a8b92dab57320c1470fee1f4fc6100269c6e2", + "0x8cad277d9e2ba086378190d33f1116ba40071d2cb78d41012ec605c23f13009e187d094d785012b9c55038ec96324001", + "0x85511c72e2894e75075436a163418279f660c417e1d7792edce5f95f2a52024d1b5677e2e150bf4339ad064f70420c60", + "0x85549ca8dcbe49d16d4b3e2b8a30495f16c0de35711978ada1e2d88ad28e80872fca3fb02deb951b8bcb01b6555492e4", + "0x8d379ab35194fe5edf98045a088db240a643509ddc2794c9900aa6b50535476daa92fd2b0a3d3d638c2069e535cd783b", + "0xb45cfebe529556b110392cb64059f4eb4d88aaf10f1000fdd986f7f140fdd878ce529c3c69dfd2c9d06f7b1e426e38f3", + "0xac009efd11f0c4cdd07dd4283a8181420a2ba6a4155b32c2fed6b9f913d98e057d0f5f85e6af82efc19eb4e2a97a82df", + "0xb2c2cdffa82f614e9cb5769b7c33c7d555e264e604e9b6138e19bcfc49284721180b0781ecbf321d7e60259174da9c3c", + "0x95789960f848797abbe1c66ef05d01d920228ca1f698130c7b1e6ca73bfda82cee672d30a9787688620554e8886554ee", + "0x98444018fa01b7273d3370eeb01adc8db902d5a69b9afc0aa9eadfeb43c4356863f19078d3c0d74e80f06ecf5a5223f4", + "0x87d20b058050542f497c6645de59b8310f6eeec53acbc084e38b85414c3ea3016da3da690853498bde1c14de1db6f391", + "0xa5c12b3a40e54bee82a315c503c1ce431309a862458030dde02376745ec1d6b9c1dbeea481ae6883425e9dae608e444e", + "0xb9daa3bf33f0a2979785067dcece83250e7bf6deb75bb1dbbab4af9e95ddfb3d38c288cbef3f80519a8916a77a43b56c", + "0xb682ec3118f71bde6c08f06ea53378ea404f8a1c4c273dd08989f2df39d6634f6463be1d172ac0e06f0fa19ac4a62366", + "0xa4f94fd51ecf9d2065177593970854d3dce745eebb2a6d49c573cbf64a586ae949ddfa60466aaef0c0afb22bd92e0b57", + "0x86cd5609efd570c51adbc606c1c63759c5f4f025fcbefab6bc3045b6ad2423628c68f5931ff56fdda985168ce993cc24", + "0x981192e31e62e45572f933e86cdd5b1d28b1790b255c491c79bd9bb4964359b0e5f94f2ae0e00ef7fe7891b5c3904932", + "0x9898f52b57472ebc7053f7bf7ab6695ce8df6213fc7f2d6f6ea68b5baad86ec1371a29304cae1baadf15083296958d27", + "0xb676c4a8a791ae00a2405a0c88b9544878749a7235d3a5a9f53a3f822e0c5c1b147a7f3f0fc228049dc46e87aa6b6368", + "0x9976e10beff544e5c1645c81a807739eff90449df58ffdd8d1aa45dd50b4c62f9370538b9855a00dd596480f38ebe7a5", + "0xa0e91404894187ec23c16d39d647ada912a2c4febfd050a1ea433c4bfdc1568b4e97a78a89ba643aca3e2782033c3c58", + "0x91a6ea9a80476ed137eb81558ff1d55b8581663cccd41db4fc286876226b6515fd38661557419e1e46b6a3bc9cda3741", + "0xb9e8a1e23c60335a37a16f8085f80178a17d5e055d87ffe8cf63c532af923e5a5a2d76cf078164fb577996683796caa6", + "0xad8e151d87a37e8df438d0a6a7c02c3f511143efb93fde8aef334d218cb25932baf9e97c2f36c633620a024a5626af3d", + "0x978f942f210e8a482015e6fdc35a4c967c67b66e6e2a17a05cc7a0f2163aed227b775d4352b0c3cca6cbf4bd5bafaf75", + "0xb5e2e3d8b2e871c07f5899e108e133f87479959b80cb8a103fbecde00ccdbfbd997540eef33079c5cc14b1c00c009fd1", + "0x88a164b3fefd36857f429ab10002243b053f5d386466dbb9e5135ed3c72dd369a5a25e5e2aaa11f25488535e044e2f12", + "0xa66091c0db4e7cf05a089ec2b9ff74744354d0196968201f5e201699144b52bb13b4e68e12502727163e6db96e3565f2", + "0x8e65aff8e37240461b7374c20bfd1d58b73a525c28994a98f723daed9486130b3189f8efe5c5efcd7f5390cc366038da", + "0x8b37c21dd7304c3aa366959ba8c77ea8b22164a67e136808b6f8e48604297f7429a6c6ecf67b1d09b8b7ec083eacd7e0", + "0xb689b1277ad050f53da91a702516a06d7406ff33a4714ea859b3b2b69f8d0aa8f983c7e039b19c0759a3815d841fa409", + "0xb17f7a0a182ed4937f88489e4c4e6163dcf49fd2ea4d9efbba8126c743bea951cd769752acd02e921774dc8ebcfae33b", + "0x8b7fab4f90be825ac5d782a438e55c0a86be1c314a5dbc3cc6ed60760a8a94ef296391f1f6363652200cce4c188dae67", + "0xab8410c4eaa2bb43b0dd271aa2836061bc95cb600b0be331dada76ddb46711ff7a4ad8c466cc1078b9f9131f0dc9d879", + "0x9194bd7b3cc218624459d51c4d6dbc13da5d3de313448f8175650fa4cfab7cc4afcda5427b6676c3c13897dc638b401e", + "0x980f61a0f01349acd8fc9fdc88fc2c5813610c07eecb6ab14af0845a980792a60dadf13bb4437b0169ae3eff8f5984ce", + "0xb783bee24acea9c99d16434195c6940cf01fc2db135e21f16acae45a509eca3af6b9232a8aa3a86f9715c5f6a85cb1c3", + "0xa3079931c4b90966d1faa948db847741878b5828bc60325f5ebe554dcab4adcc19ee8bce645e48a8f4a9413bb3c6a093", + "0x801f61ac9318f6e033a99071a46ae06ed249394638c19720831fff850226363a4ae8486dd00967746298ee9f1d65462f", + "0xb34dbbed4f3bb91f28285c40f64ce60c691737cc2b2d2be5c7d0210611cd58341bb5bda51bb642d3ee2d80882e642a13", + "0x8750af19abfb915e63c81542b13d84526a0c809179bbcc1cd8a52b29f3aba3ae0f7cf6f4f01790bf64ef7db01d8ee887", + "0xa6ea10000eb2dd4efc242ac95bc3b3873cdd882fbeb7c9538c87e3143a263ca3a2e192b2159316a625cfb5fb0b6cdcb3", + "0xaa40ca54bc758a6c64cb932924917581062e088b3ad43976b28f2e11d8a7dea73f1fb50aeaa0e70182bb2dc07d805bb9", + "0xa4779dfd25b5ec9d75dfb54a4bb030364899a5e75c1492403acb19f2adc782c7ac4daeb66d2f5aeb74135afe9f318e3f", + "0xb4551e2805d63ca453f4f38b1921ac87ff687e1d70575ad38f3469d6f0608ef76b7b1b98ae1e6b1e7d928773aaab6e3b", + "0x99490ee722f96aad2743b08dd37bfeb75a8c59efaee4c9b694eaa05eb8a6bb23861a4480544c7617d04d23fd5e2543b4", + "0x8a7050d964d295fff98ae30d77ce730a055719313457e773fcce94c4d71a9b7cf63db67e54a8aab20fb1335b0130b5d5", + "0x903144e6bbee0a4fec17ff80fef0d2103981140c3d41776cfb184ced17f480a687dd093f6b538584327e6142812e3cd5", + "0xa5b30f7c6939bdc24a84ae784add927fec798b5a5ee3dd156c652df020728dd6d43898be364cf5ee181725fbcffc0964", + "0xb43d97ec2bc66af92d921a5c5c20a03ef2be2bc2c9b345f46d8287409fcbfd88ebc49d4509d64468222cd1d2021bf236", + "0x82dc23c7f5086c9ac6b4566359bfb830d203544b0d8332a210775670f899cd9ff48b94bfeba40040c25664ebdd5cfad8", + "0x9294cd017fea581dabb73dcc8c619904d7e022b664b0a8502c9d30f3807668af279948e7e41030ae296d492225297e95", + "0x8d6c9dc636c8e884f9a4299e5cff06d044ebc94ad783a4b71788347ea4a336d4d048b8a9ecabae789e8fcdc459723dfb", + "0x801a80bc49e882ec81b04e37407713f033f7bdac79252dfa3dc8c5bd0229fcbd4019890e402cf843b9378df08f72ab84", + "0xb4313ca32569d973900f6196363c0b280ddfa1b47c88d019e5f399b805b444a777950fc21ae198fc23ece52674b94abf", + "0x96f06056fd255fdabf78986e315e7c4fdf5495cf850536b7976baa97a994cc6a99c34609c33a0f2facba5e6f1026dce6", + "0x983ed80220a5545ffd70ef5e6ac10217d82ec9cd8f9a27ee77a5ff4074092308c0e6396fc4e9932a77ddd474e61f8b55", + "0x872a059aa630af73c4abbd076e8b333a973ffc5bdecf5dcc0600b00162184213cb19d4f601795030033beb808d5810ce", + "0xb040f318d9d3b8833da854014a44296dbd6762dd17cab13f91987256c54353b7f0800547cb645a7cc231997454209fdd", + "0xa8c4731a555308e8ce0b8325eb7a4cbf6113d07e9f41932df04480b72628d313b941c7055f1cc2ac45c7353b56e96ca9", + "0x8c24031440b77637e045a52e5ea3f488926ab0b426148975edf066c40a4581beecc1bfb18fc4cf5f9f96dc6681b4bd28", + "0xb39254b475abf342f301298feaa17a4b3051f30ea23a18acf59e003e2704ac96fe40691f1da387913bdf7aee6389f9a8", + "0xa1dbf938b604ccc6d60881cc71f38df568aa02752aa44d123514154017503f6c1c335ae43e359f1487bc8934073cd9c1", + "0x8d52aa1be9f429ece0580498d8fe9fef46d4a11f49436a82b8927f9503dacc41245907f126594c1cd30701286f8c092c", + "0xb826f396486942c0326d16f30a01b00a682c30a75553dc6ac34fd5b3e96b13c33b94738f522eebaffb59ff8c571c76e9", + "0xaa89f51cbf6e6c3e2aa2806187b69ab3361c84e89f393f3ed284fe84db46fc3944aa44f8928e3964f9c1a1ec27048f68", + "0xa254df0efa4203fb92b42a1cd81ca955922e14bf408262c8f7cb7dc703da0ca2c71556bd2d05b22ce9a90ad77309833d", + "0x93263c507e4d5f4e5df88e85b3d85c46ea729fb542a718b196333e2d9fb8a2e62dc1347cf146466a54ba12d200ef09d9", + "0x922e3c4a84246d89a07aa3e90f02e04b2cea9bebc0e68b742156f702aed31b28c6dfa7ac936ea2fc2e029adf68361f98", + "0x9a00628eeeda4ccbed3ef7834149aec4c77aac1a14bc2491ba5d1a4a2c5d29afb82ceaa5aac1c5ce1e42cdcaf53e30ba", + "0xab3a88df36d703920f6648a295a70ffa5316c96044f39ff132937bfda768937cb6a479e9ba4a4e66b377f3a9996a88c4", + "0x966b11526ab099d550ab33c6a9667e5cfdedf255da17a80a519d09acd78d2ea24ec18bd1ea7d8d63cf0a408f1c1fe0b3", + "0xb5c21b9817dc32f3df9d9988aa3560e1e840d586d01cd596bc0f850ab416b6013cbf7dbfd05ac981f26014c74bd2d2b2", + "0x9040abef5e2523e7f139c9f744a64b98fea3a57952059ffe4d5ed77fa87068203c090ef4e7f52c88fb82ea8a6fdca33e", + "0xa0dcdaeb7d3f5d30d49c004c5f478818c470187f4b0b4856812dcd1b3a86de58a99acb8ceb44c6b80c3060cf967c43a4", + "0xb5f4be9a69e4a6719ea91104820df8623b6d1073e8ee4168de10a7e49c8babea772bcbc6b0908185e98d607e49cd3609", + "0x8634020a5a78650015763c06121c606d2dd7b324aa17387910513dd6480fb797df541fc15b70d269b2794ad190595084", + "0x9504d1d0fb31ff1926c89040c04d51fd1f5cddf9d7ca3d036e7fd17e7a0f767ef33cee1d8bf7e17e2bc40949e7630417", + "0x812c72846ef6d692cf11d8f8c3de8fa78cc287303315114492667b19c702cd24d462020f1276895df26e937c38f361f8", + "0x8c97aa5e9ef2aa9a1435ef9ddfe62e850f0360864ed5fb82bf9fef4ef04d8fb4f827dc078bc911ee275e4501edd6617c", + "0xac5f7af5e23c8e429aaa6b6825129922b59d25b4608f07b65f21388a9ac3aa89096712f320afe6d56e44e1f0d51a4eb9", + "0xa8c84d9a8593a0cb5be1e450960f59878a4e6b70da54a7613dfc25911b7cc9e6d789d39401b0a0d6471ab9dcdc707976", + "0x8c9d5fd89611392c0f085ffa4fa642a181f0b9b23593deb5e10fdd1642722ca75ef34a037e88a8d03f2888fe7461f27c", + "0x8c74b05f91fb95c85e7bd41f6d9a1e41e667e68f3d19b325c1f25df1767019919edab89b92af237896cbc4e6d6dc1854", + "0xa3caecb91640821f0b2c4981b23f2069df8d2b98ce026c1538bc096b292f5f956a5d52c1c8d6a8165a1608083ba6494b", + "0x8ae8e0c36f8b79a69176ff29855df45d0fcd9e4d1dbaed8899f8fcdece676e418ec034a6c161e2a894f0c834aaecbfd1", + "0xb88d18c67dc3b1b6ed60ee437c441c1ed14ecddebccf43683605716f30058b1aa4ba05ff10cd8171ee97d8f58d70c094", + "0x94f43d84dcdfd9cd19115c7d8e9c1e856828eafbfdec93b876cf0007e317e30b2ad951dbabc186aa6ef90fdee4d91990", + "0xb44e4723f41fc1d5b0057f371e3381ae02566590b3f964b6eb07b2104f66ff78410c407235fa98d04f635694f3baca09", + "0xaddd8390173d29ca0811534d389253831fed75fed135398617836b6e70767269eacb1560b39a58f02042ca3b97fe59c4", + "0x80bdbdacc0c358c7ea52aeacdc5f9ceb6928bcf6e7dee7c17d8ae3bf7c2372aa7a0372363888968fc0921aaf4776d5d0", + "0xa486e2b6f04f403f9e609d69dfb3cfb992af56ecad1683271df3e3faa3b86638b81e73b39978fb829ee7133d72901f2d", + "0xa19472da57457e10c6a6307895393ddaec8f523760d66937fe26a025817319e234eaf69756ffdf1b84c81733424a96d7", + "0xad6a195397cbc2d75171f5e82090441eed60bd1ba42c39ef565b8b5a8281b04400678625b1dc46d617f694a7652a8e5d", + "0x8f98e721c06cec432e2221f2e1b06bb1469d916a8d88d6973acf68d1e003441d00390dafcead8ecdbf9eae4509baf5aa", + "0x91d62a0f9d13c59adfe1376ed6d057eae244d13c6b3d99be49a49e0075cf20f4085cf127774644ac93615be9ac9e5db6", + "0xaf45dec199245e2b326a0d79c4899ed44b1c0219db42602a4a6184ace0ff831a3276297af28f92e8b008ba412318e33e", + "0x8754bde54e8d2d169e6a7d6f0eae6097bc0461c395192bd00dd6f105677ea56ab384c02553ea5eeac0a65adcb0df77ee", + "0xb676afd2f5afc37a314c943d496e31b4885efcbcc2061036e370a74cfde5642bb035622d78d693bfc3136fc036c7edb4", + "0xaab6ffe6cc234397cf1822e02912bc282dfb314e92fb5a9e10d0c34ee9b5856d4b76e166bc2bb6fcdd66aabea35ec4ef", + "0xada6e62f90ee6b852ec4b72b22367acac2896f0df2c105beda27096583ddbedddc710d171330569f111c6e44a5b57ae7", + "0x802139dd15241a6de663d9b810121bdd9cf11f7f8c8ca6de63f4f8e731409e40d1fd3558b4f619ed42ee54929dff1c7e", + "0xad8e70531cec21b4e6f55be1751c2d025bd2d7d8158269b054cfe57fa29252d052ce4478ec7db6ec705789e2118d63b3", + "0xa8e4a4271769480e1b33a28c87a150ecc0b48bfe8a15ae04152197881de4ce4b03453aefe574842424edbbe4173e1a3a", + "0xb98c65726296610cef16c5b58da5491acd33bd5c5c5af4d934a9840649ef85730fbce8018dee09ded14e278009ed094a", + "0x8e213a7861223287b860f040e5caaa563daa0b681e4e09ec79ad00cc459238e70bbeaf7486bbe182fc12650700034ec5", + "0xa2879f9e1a556cf89b9b5b3bd8646a8cce6b60bcbc8095df44637f66a2da5858eee2dc9091475a8f64bb5aff849389cd", + "0x8a17cdb4077b9b0bcf28b93294ac5ae4c8bba8839fce0f1012b53187ac008f9858b02925fbfc421f1123afcdbd8b7753", + "0x86fd9c11528aa43946e4415ff64a3ca6409ee6f807368c68997b18605da65e415ccd85ad913820d450cb386593de666d", + "0x8ed55923b963c3d85a91aca11c40ff9c6c7f1e2b9bc199d1a270e5fb16aa62dec0136e97866145ae9d58a493e8b1cbbb", + "0xae32af5b5d418668ae123c639b149e5eed602404e8516da4a61db944b537a3620545e8e3d38cf10cdaea980ab2f80973", + "0x95cb8d9e9d6762d78dde0ad73869ffaca904a7d763a378b8cc11a7933d3e7d1c8aec4271a079b1b00f8887ee5b1ea21f", + "0xb5ea20b42a3ca247f00ab5328c05f0cf194973d5f7271c66c41c5055b1ffdca136be179709e0c1de209fbe07b9820bf3", + "0x98682f7cce471c92a8d6d15fee4ddf4d43dd97c3e3811d2913618ecacc6440b737717c07736ae4558c910e11ee98104e", + "0xa67da2c7cbba48e929ca4e4b9a6299fe01ef79eff8cc5cd3fdbdc0721a68130e4079f30ae151a573a7dcca8ecf2e684e", + "0xa9981c9f9dcbb3b0f6996f664fb2acd7573189f203be37b2b714662aa273551396abfb1f612ccde4e4c8127a050dbe4b", + "0x92d55eff8da600f886da9bf68e8eecf482faa4b268f3f286b3b3e5cc91b19604081498d4905b201bb4ec68e32b5591d9", + "0x963e3f1728de9d719c86d390f3eb9c3f99d1928347fab0abf10dbb37d76b59ddb64d4734c977863a6cd03ffece5ca895", + "0x93480e2de83c921056b6d8628ac37cd5ef7555ba43b0308fc13386cb0515d42c12ecd06057137aa71a7931beaf90b9ce", + "0x8feae57ff0e6a162cc81c99f45c6187d268fc0bee8c2bffc92142ef76c253d201f0e932943cf2fa312982b281ce1066b", + "0x8f8f4bd4200fb87afcd743274480220d77571928000d4197410dbb75439d368df6a06d941a6152206371d2ca9cac99e4", + "0x8ee7f11e79af4478e0a70eb424fe8078237ad99ba6d7e6bf1a8d5e44e40abd22d404bd39b718ad6fdf4c6601f2a47665", + "0xa98acfcec612b574943195b9ba95bebcc9c0b945c9f6b3e8760b2a4635909246a9d73b0b095c27b4ecb3339704e389b7", + "0xb520efd19f65e81dc285031ea3593f8c5dad793e4426beb9196ab46e45346f265fd71e50adb0da657977c60ed5724128", + "0xa3d9d0b7415280ce4dfa2429d47b2b8e37604a5157280a72cc81d541ffe44612dbb3ef7d03693fc42a569169d5842dc3", + "0x8c29e2d0b33801f6d9a9c065a76c5cad1fb0a001506b970307e21765ee97c732a4cbf1d7c1b72d95e0ad340b3b075224", + "0x839e21f292892a6eb596b9b1e9c4bd7c22a6fe71d3d04487c77840028d48392c5cbe73140a4e742338e0c8475cd0c1ad", + "0x8bea5c68e7743998619185bb662e958f1b4d3ca81019d84ac43c88911aab3abe4ee9bcc73cb95aa3ae87c0138801bde3", + "0xb8f262d21a94604049e008ce03dc857848168e1efca4522acb0ccc827ffb37f545e1947843a356563a76bc6489605b66", + "0xa7bd0842b0bb38d9943b82aa883f36f4eb8a6e8a7790d4f87faf306608f51d250a19b73984f1156cef5dd2581664614b", + "0xa993e649bd953627a88a2539dac3a12ec7f37a4c65b01425d9d34edf7ee10a71aa98f65c9e013107f824faf8aee041a9", + "0x8e07eced75c67cb4d2ec01857f6ac1408482e6b31cb2faa249e8cf99f180575587df530c7782a7539b5221121ef48aa0", + "0xb2f4578f26c05ecb9e2669ca744eb19d4f737321ac7d04fafd18beb7866e0fec9dd063953ae1f077b44b9c6f54db1279", + "0xb6b3788a6c7bcaf467d19daf6ab884d549aa866970c05a9181f544ff190d043192c84fe437a75a30b78b425461cca062", + "0xa270684903c61544b85a7041e81f65e787e1c1e23e57538fa8a69836bed0ca1673861dd29f743a1280f2f38eddd3aa83", + "0xa9c2397c4773dcad2821266dadfd2401d013d9f35de6744f2ec201f3507700adb1e6ec4f5a453be4764da8bf68543f26", + "0x83a3025ed6fd5df9d98be32a74e10a0d9728b560942d33ba028536fb148fc34ae87e92be2df3e420a8dfec08da495982", + "0x90dc70c183a90bab988b4a85b7b921c8070af0e5f220364fe11afa0722990b2c971e1e98eef62d3287fedfd9411f1df7", + "0x82d940937a6c636224d04f8e2536f93dcf20dc97a5f188875ad76c21b804aef9af10839419b61143c1f88a695959a6b4", + "0x8017f9473ce49d498d6f168137e77e62fe553e5a51e75b519cf2cbd1ab9afdafad80fd5e6fd0860e640b0d78ca8ed947", + "0x80573a0ec049fe1f7b3013b2839e145cd87e07c0e43826a29ef8c92516f9a30896c2ffcf3ed77ed22a6cf3101b1789d5", + "0x953349abd2559f9824db07cec857ad54f1a05018f3076425f8dbae37f8d92a46af2c04ab7c8ec0250449541187696e98", + "0xab7bd2c4f05ee9a9f252c4e16a20993a12c535c3809d124bae24642616521a9768d3f19eceaf8524583f47ae1f527684", + "0x9883b77ee834ee0112ca2f366d2a6fc213e0cf454e061438c2901a5ba35b7378f64da8adf6a476eb1562991ef5b4a5bc", + "0x89291811db308637356dbf7ed22cf07bfce33eb977734ee346e8c15a231b35d8b4443574f3fa97a40867b3e23b0bbfa4", + "0x93d753849d7d9588d39e38217500b123a6b628a873876612d9f98b5d611f52c89c573432d2176752b5d1cc2d94899b8b", + "0xa45add3c4844db3b7a237295fc85fddc788ac1ec395a0524d2fc90a539571a247146aea4aa10eec30a95e9617c85b98d", + "0x90f94578842db7a4de672da1e483858ece5e466c73c12f725a0fc71f42ff880c9447a33fa9096839bee817536f2591e2", + "0xb2c1b6fb031bb30460f157356562b44b4de096a0a112eab4fb3cc500aad38bc770da1fc2e73caf687a0da5e8537049c0", + "0xafb15e15fd930929c0e3c66482068a5afe0c7b7f82e216a76c5eb1113625bfa0b045a52259d472284cfbaf4796c71456", + "0xad222a9a3d907713418c151b8793d5e37634354322068f8206b9d0da1a3f53b0004193713d23ec35990639a1b6c2e075", + "0xb44a128dce97e8c4b178cdbca0a5c1b3f6e164490fac0fd68dbfe0aafa89920bb4ea420a8527e06c80dd19c2f135e3ef", + "0x8596e993ef18b8d94e9c42a90cb7060affc586b8e9b526820d25124285de5590134e2e86592e9dc4dd45ccf5d578fa60", + "0xb71bb0ad138141ed506b2253e84110d2db97cc2d24a3fd0d096b0022d9f38f87aa74e2f505074632d64e90bcc491aa30", + "0x84841eafd357309de47b92ca5ec163dec094a2e5271bc65898c31932e0160bee165e4decb23af339cfe09c83e1cc5441", + "0x8a2915ee39a6fd4a240b98533d7690ef1773ce578ed1fb05ed414ebe36f7ef289fa46f41768df57190438c356331e329", + "0x90bb337165386f1990cbd8ed2e8321ef21bc18125b015b4da0c37e5fcc446b26005379ee4fad8ce9348ceb4ab49e82e2", + "0xb707b50ea2ab05c6d183671587f25fe29eef23fe569d731459a1ac111a0b83a2cd65b88242876b34aeead3b05a15d745", + "0xae1f159f79b7996315c4f9acce7e21a6ed59d4ef76331196fc86911fda3035edd5c11d568b105175a36c948d0263b382", + "0x922bc525bace05e5dff6b5cabde5469ddd2c1c601f7131abc04ecefdd35095e6ac015b1aec3c3b25c5dee8d139baf60d", + "0xa7b060405b2740f82db64683187b1bb89e5f40c8438663c7cbc8ef2513929fe5f92625667a7f2f599a72a96b1fc8f08a", + "0xb9dfe94a08651db5efefbb813269bce80d814e3089b80c0654491e438d820bf521f8a4a4477909344ba88f7683eebb43", + "0x841817a9729465743576950b6e8eea32ebf39cca99ace86c4792f9f35926e2d6830c52854a3b2eaeb61694e6845008bd", + "0x934128034bde8fc7b93b952aa56e0ed28b36cfa04cfa1f0d5b38266dd40beedff5e0bab86e4717b0fb56c56be2eae26b", + "0xaee9d64caf28596308782cd8f3cf819506daf3378f86157ff775e618596411adf94efd0e9542787ca942066f02cbd332", + "0x85871184db314411a49575fee088c52ed5dba4e916ee001ec24d90898a0154d9790a06aa8a707ca7a8b986c0293b8d89", + "0x8d3d87edcc0187a099c97b581a598d357a41ac152303bb27c849eb78e72e15cb97cf9a0468fc36f245c3e152c76bb7dd", + "0x900475d165dec18b99eb7b5f9e9ad1d2d4f632e55fdcc4c5ecd7775fed462990e6aaafe9c669f40508f9b15f00bda31f", + "0xa25b5954edd57e7811a0d18532043d975c7b44b80f65cd630935d7b16ada05f30fe2b7be7ae8a2f54c25957faf3f1950", + "0xa089019afa3a7a15f7e7874e73b6773c0a824e6d3379b4c928e173321fb165ad979a6be004d394c28d19d410b2655d3e", + "0xb28f46797dee0c538bd3de815df641a0ef718ad3e52b2764aec380d6905b38b50ad6f60d0f68e096ca39960ba7734355", + "0xb0ac155d3d05851b04104e6b459f1a68e9e155437c92421a7c0e4dd511ef89cf71dfa3cc920769492ee283a65ebf029e", + "0x813c69a810745580d43d5b5480f0ba81000fbef0071e6b655c7346bef5ed774e9214a7816d40eb1774a5bd033767a046", + "0xb176345ca75c64f10ec33daa0dcf1f282b66a862fcd3d8d66c913f9a02db4c9d283dadc02eff13aaab94bc932a42234e", + "0x92560f67e5b995db4a489bb86ee78b4aee0800143b3535ad557a53e9e08716bd0202d9f5714722c2a5e8310046e3f5b3", + "0x8adb427bad9cc15fc6c457a96a6750dda8c46d859c5f69bf0e7ab8fc0964430b33967fd47cf0675b6ba1757f91255e6e", + "0xb120f723b80389a025b2daa891b140b3d7b8d520ae2a6a313f6e3d365a217af73292dcb249dca1f414ec05e865e3cdc7", + "0xa61a5d261a8dfe5996c42ea0a5ae703a2adcfda80e86837074d868eee16f87d38da19596c48b55dbd7a7cbec1a9b4996", + "0x99dc921eacc6bb867c5825ad4c83bc4af9dd78a18b3d0e1a60ad493e3805b8fb9b7922b577da1adb3d805edfc128d51d", + "0x85455fa165a07282aaab4a5bfb88027f47b9532e4af8195c048515f88b0db7e80f42e7a385fd4944faaa7f2a6544ad17", + "0x96dff2d1c8a879d443fe576d46bcceaf5f4551d2e8aad9c1a30883637c91090de99ad5eec228eb5febf93911502d3cbb", + "0xa87eb7f439377fb26c6bfe779701f4aea78dd7980b452a386afec62905e75217a1996c5234853432a62ef8bab21c31c3", + "0xb598278293823e9ccb638232a799211173b906444376337fdf044d0227d28fcc4c5867e6ecb3200e59ca0b139e71cac9", + "0xaa6fe147edc95027654d68140f428ec53cede3552c5f49c09d18bc6f6ae8c739a63042eb7291d14d717a4e1f0778abcb", + "0xae8ee18913d328b2fba71efe65526d3ee9c81beda53cf776baec4019ea30212010758cbb5dc85ed6620ce04b189f01f2", + "0xae9fb686777e88dffdd42805fe4114aa0da1b350d92a27ff3f8a817fb25af1fcfc9a06155affe0273bf13caad16a5351", + "0x95d372ba3a2ee38371538f34aae91b4844488e273f70c02f1992370f89fc2343eff95692d52ce9f21206abbee4959958", + "0xb15260376f0a34ca2827ff53acd7eaaef94c9acc2f244b36500423069cb1cdaa57ac8dd74adb5b53d0fd4265fcbb28ea", + "0xb0ffce6a8059537ef6affdbbc300547ef86e00109289239b0c6930456c562b4ed97f2e523963af17736dd71b46c44ac7", + "0xb5499a1277d34f9892f7579731ff53f423f2ffffa9ea43a6e929df8c525e301396249a2324818a6a03daa0e71fcd47b3", + "0x98dbfb8e97a377a25605a7665d4d53e66146204d8953afda661ae506858c5cd77ff7f21f5f10232e06dbc37378638948", + "0x84177e27e6da0e900c51f17077f5991e0e61bff00ca62c1623e627c5aea1b743f86eef6d55b13219a1947515150bade6", + "0xb50407bb5c61b057ab8935df94fd43ca04870015705b4f30ceac85c1035db0eb8293babc3d40e513b6fb6792ecbc27a9", + "0x988699a16917514e37f41ab5c24f4835ed8a2ca85d99972646fcc47c7e2a83c2816011144a8968a119657c4cda78d517", + "0x920c43fdcb738239ad542cb6504ab34498bce892311c781971d7db4dec70e288676de4d8697024b108cfa8757fa74035", + "0xaaa106329aac882e8d46b523f126a86d3cee2d888035ce65c0be4eaae3e92fd862f6ac2da458a835539cccafaba9e626", + "0x96e4c1562d14b7556f3d3e8a1b34ea4addc5a8170e1df541dc344728bcb74cd1630eb7ba4c70e9c68fd23c5c5d5a729b", + "0xa616ac5016d4e68e03074273cd3df9693ee0ce3458e8758b117a5c1bc6306dd2c7fad96b1bb37219c57ac62c78ad7a3e", + "0x8db7d9b20abfb1445babd484ae9e38ff9153ac8492230d7591e14e3fca7388a5ca6ef7d92ed445c8943cf5263e4a6ad7", + "0x88464134221aa7134878eb10928f31c8bd752ab68c27c9061c1de3f145c85731a4b76acdc7e939b399b6e497f9e6c136", + "0xa5f7c794f70b7c191c835dded21d442b6514bab5e4d19b56f630b6a2f1a84a1d69102d7a0dcca256aab5882d3f30f3ca", + "0xb96b6f98b6817b5fa6b1b1044e2411bdf08bf3ffaa9f38915d59e1d2b9bed8b3d645eee322ee611102ce308be19dbc15", + "0x92c26ade2e57257f498ac4ff0672d60b7ea26dad3eb39ed9a265162ccd205c36b882dba3689758c675f29e20836b62d9", + "0x8379a0299e75774930577071d258e89e471951642b98e5e664c148af584d80df4caa4bd370174dae258848c306f44be5", + "0xa0e53beda02bd82bf3d24bd1b65b656238128e734b6c7a65e3e45d3658d934f909c86ca4c3f2d19e0ac3c7aae58b342e", + "0x8ca5ceaeaf139188afd48f9bf034d8baf77bbf9669791c7e56ebf783394d7fcdf2a25fa4bdfcddfde649aa0dc67ccccd", + "0xa8060e6448844e9db4e9fb4da1c04bcf88fda4542def5d223f62c161490cf1408a85b7c484341929c0f9ce2a1d63e84b", + "0xaf6e1a5ecf50b754bb9eb2723096c9e9a8e82c29e9dcaa8856ab70074430534c5395534e1c0ed9ce98f4b84d4082fa67", + "0x81c8dbbef98f1b561e531683d5ae0f9b27b7f45dc6b2f6d61119ca0d559bf4ceb676d320afc5aba1811eeef7547a59d8", + "0x85b46cd64d605c7090a2faf1a2aadf22403b3692b3de1d83e38b2de0108d90ac56be35b0dca92c7a41c4b179a3567268", + "0x8dd3cc3062ddbe17fd962c2452c2968c73739608f007ad81fa1788931c0e0dda65032f344a12249d743852eb1a6d52a9", + "0x8630f1707aea9c90937b915f1f3d9d7ba6bda6d7fdef7a40877a40c1ee52471fd888f84c2b2c30b125451b2834f90d3b", + "0xb4a747e0bd4e1e0357861184dacec6714b2b7e4ee52fa227724369334cf54861d2f61724a4666dae249aa967d8e3972f", + "0xa72de682e6f9490b808d58f34a0d67f25db393c6941f9342a375de9ca560e4c5825c83797d7df6ed812b71a25e582fff", + "0x8d5ea7d5c01f1f41fffe282a334262cc4c31b5dcf31f42cc31d6c8e37c9bd2f1620a45519dab71e108fe21211c275b6c", + "0x8ccdc7e3642c2894acbf9367f3e99c85963cea46dc5473d175339a2391be57dd8815feacadec766e13645971213b9eb8", + "0x858e9b5fc8c13b651ff8eb92324bdda281db4cf39f7e7bd0472908b3e50b761fa06687f3d46f4047643029dc3e0ceeaa", + "0xae20d36c70cd754128c07cbc18dcb8d58b17d7e83416e84964b71ccff9701f63d93b2b44ec3fddc13bbe42ebdd66221e", + "0x860dbf7013da7709e24b491de198cb2fa2ffd49a392a7714ad2ab69a656ca23f6eafa90d6fdc2aa04a70f2c056af2703", + "0x8f809e5119429840cb464ed0a1428762ba5e177a16c92581679d7a63f59e510fdc651c6cc84d11e3f663834fcafeafdd", + "0x8d8a8dce82c3c8ea7d1cb771865c618d1e3da2348e5d216c4cbbd0ac541107e19b8f8c826220ca631d6f0a329215a8d6", + "0x86e3115c895ae965b819e9161511540445e887815502562930cedc040b162ecb1e8bdc1b6705f74d52bf3e927bc6b057", + "0xb9833b81a14115865ca48c9c6a3855f985228e04cbc285f59bf163dca5e966d69579ea4dba530b1e53f20bd4dccdc919", + "0xa71f5801838a6dbb162aa6f0be7beea56fadac1a4bcd8113a0a74ab14fc470a03775908c76822d64eb52a79b35530c05", + "0xa77ab73ae94b6d3378884f57eee400eff4a2969aa26e76281f577a61257347de704794761ea1465dd22a6cc6304fbc4a", + "0xacd1c5df3c487c04cf27f002e81f2348a0119349b3691012526a7b0d3bf911cdd3accbc9883112ed2ba852145e57fe68", + "0x8a28515a48832ac9eaf8a3fb3ad0829c46c944b4cb28acbcdbca1d0d4c3c623a36cda53a29291b8f2e0ea8ee056b1dee", + "0x846bafca11a7f45b674237359b2966b7bf5161916a18cf69f3ec42c855792d967d3bf3f3799b72d008766206bb7a1aa3", + "0xb24b341675b1db9a72c3405bbe4a95ccdfd18fa96f876ec946ccb5108f73e8816019998218a036b005ef9a458e75aeb3", + "0xb99c267b4a09193f3448bc8c323e91ef5b97e23aeff227033fe5f00e19bab5583f6e5fcb472ec84f12b13a54d5c0e286", + "0xa088aa478dbe45973b04ecafbcbd7ee85c9a77f594046545cdb83697a0c2b01b22b1af0b97dd75d387bb889e17f17aa7", + "0xa0c6b0cdff2d69964134a014e36c3709d9e63f6463c5cd7b01b6f0be673731b202d577539d89dd57a888326da1df95af", + "0xb4e6dc4ef11b2b41794ece70a8968e56705199d183366759568b6fa845d2cae127486e926b5b27ae9118bb21d1682c1d", + "0xa007804353f174098f02540a57e96227232444d5ae0a24232c244647148b6c049848cbd2b50d0a25af3ca9164bfff8ee", + "0x873fb034cc39c9cee553ece908fbf315f62efbc412b9afdde6a1889326b7f6f813e050b0601ba9921688e958cb75942e", + "0xb5676c90f0106c40d8683299e59d564f505ec990230cb076caef3ae33f2021e6aa5c9b27bb8fead05fc076df034c28f5", + "0xb5a67fc4c5539ad1ddf946a063110f824f7f08d2e4d30762c9d437748c96c9147a88efc22260573803ab545c18b108f2", + "0x817ff2b748a949973a91b69b0ec38efbd945aeb26a176d19f0fb76e261c7526c759e6f5516f9ed34de6eb1ac7838c9cb", + "0x99b76bda3526a5d841e059010fdb14eb2fa035a7d10463373a062a98c3c1a123e2da0848421dd7546d776438fd05e304", + "0xaa0d363270f90d56bbee7ea577b0c358532bda36d9247af6c57d000044a97ba41e35bb0db438f4c94551c6350e4e0674", + "0xacdae205d05f54b9544be96c9032350511895ccf413dbbc56d1f03053185df22a6d5b7ffcc3fbe96c3e2ce898ccfa73e", + "0xb091c220a1de18d384f50dd071dca4648ca4e708162c52a60e2cedc0188e77c54639f75bce9a468a64b2549119c07ded", + "0x878676133e5c700b1d4844564fa92a9930badb5293d882aa25ee6721a9f2cfab02088c31d62cf1342ae3edaea99a1ea0", + "0x9756d0793e6aba3b4dff48100bb49a5ec08ec733f966cb438379b91caf52fc2a5930830ec3f49aa15a02c82c1914dc7a", + "0x9722f760184d3b2d67cb2cea7fa41b1ff920a63446006bd98c6347c03d224d2d8328fa20ccd057690093d284b9a80360", + "0xb5a68489de4f253715a67f0879437bfe8f4dfc4e655ca344848980e6153b1d728acde028bb66fd626fa72eedd46ff683", + "0xa8cfc900b34835d9fd3add08044636f69614eff9ae929eac616c39bd760fd275ee89bf24b0f275dd77a66e54fd6b94e5", + "0x89967479bebf70b2893cad993bf7236a9efe4042d4408022fdbb47788fabedcec27d3bba99db778fcde41e43887e45af", + "0x889235938fcec60275c2cf0f19d73a44d03877d817b60bb26f4cbce09db0afae86d42d6847b21f07b650af9b9381fa82", + "0xb7fc321fa94557d8fbdd9fff55ab5c8788764614c1300d5ef1024290b2dbb9216bce15cb125da541f47b411a2e7e3c2d", + "0xb11b0c4dc9477176b3cda6b17858dbd8c35a933ed31364801093f310af082cb5a61700f36851e94835c5d4625bf89e32", + "0x9874e54d2939ee0600f4194f183877c30da26d7515e9e268fea8d24a675dd2945d1565d9016b62b1baab875ac892f4d2", + "0x90df3a77280d6f1fa25a986309bba9d5b89c3cf13656c933069bc78e6c314058716b62eacfa7ab4aff43518b8b815698", + "0x962b08299a287d77f28d3609f39fd31bc0069f7d478de17539e61fcc517045050644b0307c917208b300ce5d32affcca", + "0xb30eedca41afb6f083442aaa00f2e4d5dc0fda58e66aaf0f44e93d4af5c4bf8ea22afec888cacbf3fae26d88e8d344cc", + "0x847747a22fab3fe3c8cd67f3f1d54440f0b34ce7b513225dc8eb4fa789d7d9f3577631c0890a3d251e782a78418fecfa", + "0x8d1ef3cb5836e4039b34ee4e1b4820128eb1e8540e350309e4b8fea80f3ae803d1f25f4b9c115482b324adf7c8178bc7", + "0x8f8a2b0b0f24f09920b58c76f7d99ec2eb2e780b5a66f2f30a9ed267dcaea0ec63b472282076c7bf8548211376c72f6e", + "0x831ee6dc8889bbf4d345eaeb2f425959c112d2190764abbbe33bc44e1d9698af87ff5a54d01fac00cfee5878dee7c0f6", + "0xa7eb2479ac80d0ee23f2648fd46c5e819ad3a1f4752b613607ae712961b300e37f98704880ac0a75f700f87d67853c7a", + "0xaa4d1b9cec62db549833000d51e83b930db21af1d37c250fdc15d97bc98de7a5af60dbf7268c8ec9c194d5d5ccda3c1d", + "0x87396fd7e78c4bcf270369c23bc533b7fb363ca50d67262937dab40c7f15bd8448a8ba42e93cf35fb8b22af76740d5e1", + "0xa958b2a9ffccbca13c0c408f41afcfc14d3c7a4d30ea496ce786927399baaf3514ff70970ef4b2a72740105b8a304509", + "0xa5963a9dd3fe5507e3453b3b8ed4b593a4d2ced75293aee21bfed7280283348d9e08bf8244c1fce459aa2470211d41ea", + "0x8b06ddc3359827558b2bb57caf78b3e5a319504f8047735fcc8ec0becf099c0104a60d4d86773e7b841eb5b6b3c0cc03", + "0x9437e7278283f6d4d1a53d976c3c2c85c5fe9b5aec7e29d54a5423e425b4be15400ed314f72e22e7c44ee4bacf0e681c", + "0xb56067ee26a485ed532c16ec622bb09135a36c29b0451949aa36fee0b0954d4bf012e30d7e3fc56e9f153616b19349bc", + "0xa5c72f7f5d9f5b35e789830a064a59c10175093a0ce17654da7048827d0b9709b443a947346b0e5d96b5ea89b8d7c575", + "0xa8318d01182d4c9af2847a29a6b947feef5795fc12e487a30001cc1ec482b48450c77af4837edfa1aedf69f0642c7e5e", + "0x82ea421c091552d3dafa7da161420cb5601b819e861dd2ba1a788c3d1b5e8fa75cc3f2b0db125dde8742eb45b335efa2", + "0x8679fd1c7771ea3b12006d4a972f4f2892e61f108107d4586f58ee7f2533d95d89b9695d369cdace665f19c6bc3bc85e", + "0xb5ab3e8adee4c950fce4d33a0e2f85d3d886e60a6e2f4454b57bc68725f0cf246372d863167482cce1ea10a7c67c3af2", + "0xa85696927075ec188979180326c689016a0dc7a2f14ae02ea27c39ef91418cd44177d3fca5752cf6b298fd75fa012e26", + "0xa44f87b7232f102cd092f86c952a88afb635484a984da90a41a57a3d883c9469064bf105b9026024090486b6c6baa939", + "0x866ac91a437db945bbfdc11fcee583f3669fa0a78a7cecf50fbfa6ed1026d63ad6125deba8291452bf0c04f2a50e5981", + "0xb780d5a1e278fd4eef6139982e093ceafea16cb71d930768dea07c9689369ff589d0c7f47d5821d75fe93b28c5f41575", + "0xb025d0046e643506e66642c2c6a5397a8117bbfe086cee4175ff8b7120e4f1e6794e1e3f6ec11390993cca26d207ae43", + "0xa04a22b6e28c959ab265c7f48cde42bb6a00832c6beb2595b5df2879080a9424890960417d7d7ceb013d697d0ebf7267", + "0x81de9c656ac27f54d60d0252e33aff4e9e9e9c3363a50740baf15a2b9061f730a51ae1704e8c4a626153cf66d47f19b1", + "0xa15fab90599df889df11fa60c752948b68fba54005491180dafb66c5775547976d0eef33945e55d4818653e0818c6f92", + "0xb06f9be44ddb103a72fa4ebc242c8ee1975fe9bf9ef7124afeda9967ff3db644dbf31440151b824869406851a90984a2", + "0x99abdfe6806ae5efa2d11577da17bd874d847c5f810460148bc045bcf38c4fd564917eacb6ed61bb9164ed58055cd684", + "0xac53231077f83f0ae5f25e52b70bb6105d561c0ba178040c11c3df8450c508ed5df34f067fdaacf716f90b4926f36df5", + "0x99e3f509af44fc8d4ebc693d3682db45fd282971659f142c1b9c61592573a008fc00502c6af296c59c2e3e43ed31ec7a", + "0x98f2f5819670aff9a344e1c401f9faf5db83f5c0953d3244cfa760762560e1c3a3c7692bb7107ea6eaf5247ac6fd7cc8", + "0xb5b9f90391cec935db8d2b142571650fcbb6f6eb65b89c9329e84b10bfa1c656026674d70280ade4ba87eeaf9333714d", + "0xb0696b77ca8a0cdbe86cad12f358880926906fb50e14f55b1afc1e08478ae6376215cbb79bc9035de2808c7cd2b13b85", + "0xa51d746833062a65fd458a48a390631d5d59e98e2230b80d8f852cfc57d77f05eefcfd3c395ade1e86d4a39c2141365c", + "0x812d67654319f4ef3c9e4a2d4f027a4cb7768f1ea3f5fdde8d1b79187a4b874ff9a5c70f15b7efa079c2dc69d1b9b1fe", + "0x968978b653c6416bf810f6c2ffa3d1abbefbd06f66b6686e9a4fdce3f869e0ab1e43cce14dc83786596761c100ae17e1", + "0x98e1e6ab562ca7743783b802faeb0a24f1341abfb9655f106920aef08964a3c0e8083e1acda7ae28fed7cdd5478decb6", + "0xa91c0b982a0a7085a103600edf99e9d0bee4c4e7db6d9f8f376c215c7d42476218462a3765f2928e12c3dd49d688e4fd", + "0x8a43395b3124fab9e2438635bf88952e8e3084dad7ecb3a9927f9af0e0887bce4707084043671fc98ad03621e40a149e", + "0xb0b37626143d4a8c6f5693d5f1fe871525b4dd946c4239cde032b91f60a4d7a930d7ba28959737550d71c4a870a3a3be", + "0xb01c74acae1715c19df08d5f4a10e0c19d1356264eb17938d97127bf57e09ced05ba30d0fc1a9f32d6cff8b0d5f91c9a", + "0xb4c2328eb8a5a673406faed8f0aebb8540d2791646e37ce46e0e382506570ca276eb6f8e166dbbf9e0a84064873473b9", + "0x85cb9f769a185e3538e4a4beda9a008694e1bf8dfeea9dc07c5c40a9ceb1d31fcb13cacfaa52849ba1894b5027cb8c30", + "0x8742f91cddc9a115ddc73982f980f750d82d3760f2d46ee4490d5b17c6c3bb57c7d4c7b8d6311b7b41e59464c009b6a5", + "0x948ef86d17128a061e1bdd3ea7fcc7348e3ec87ec35dc20a58dd757d5d18037fe5e052bb359e27ab4c2320d9a52a6a0b", + "0xa70f6a214097c271e0d2d95e30fce72d38c30a2f186271fdff0e38e005aff5baed53739b8c4f9501aa7f529c5cb2da59", + "0x892a7574cf6704ad75b346c95ae6f2668904f1218c35b89b07a0c2dbf3c62173c348f6fd9473926eef56a37c0f635c04", + "0x837e85a41f39b4ded1420aa8fc3be46a7adb99305e0928c6d7643b7c44434b72984cea08eb68f5f803661df0db78c87d", + "0x94e495329f2aab3eeb68f347961d1006e69d990095877a4dcc376546233adf29a14bf6b16a0c39aa477e15368e87014c", + "0x851860a8fdf76a97048396553262637dade27f1f63f926997e74c7c72b14b10293eae7824e8dedffad1aead57c124f79", + "0x90481017a250972055ab1cf45ff17d2469517f10f18c9d4ef79a9bdc97a49093289bbacfefa8a1e491bbb75388b34ac0", + "0x983db15f7463df28091c691608ca9c51095530fa6b1b7b5b099c612e673d29e16787cc9ae1c64370ba6560582ce623c0", + "0xa477dab41014c778a1b78a7ce5936b7b842124509424e3bfc02cc58878c841c45f9e04ccc58b4f2ff8231488fff0b627", + "0x868ebba1c85d1f2a3bf34c0ab18721ea725378b24f6b6785637ee4019e65d4850e051c8408fe94a995cc918c7b193089", + "0x93cbf4238a37ccd4c8654f01a96af809a7d5b81b9e1eab04be2f861d9d2470996fb67367e5bf9dcd602dc11a3e4cf185", + "0x83113f4e696030cca9fdc2efc96ba179cf26887c677f76cde13820940ad6891cb106bb5b436d6b0f8867f2fd03933f7d", + "0x90c709f4e3359a6d215d03f45ad5cf8067aedd4aab03512dd62229696485a41dcd64e2acce327fda390e0352152fce13", + "0x9945cfced107a36f3cf028ba04c653360afc5013858b9a12fac48802efcbc198c9baf3a7f9b23dfdd5036e88bc7274c8", + "0x832ae60192b47fc735a8ddeaf68314b16256c90ab68099f58e43073e249c6939895c544a02fa34e40805bc6b5db33461", + "0x8b12c335818b643c1d22cbc2869606cf64e7ae54a7713617fc4dd3b2f052ebd6b920ca59ba2e9c7aa8cf71bb4f40f9e8", + "0xa2033eb7a373931c65d66989644aa0892ac3778b9a811b2f413d8bf534e282c339717979f9aa742162abb3468c195f87", + "0xaba2b4c37dea36bed6d39323e5f628ab607699c66767f9bf24ef5df1bfcad00c2664123c0d8d5bd782f1e14a06f4c769", + "0xb71963777535b4d407286d08f6f55da8f50418486392a0018ee10f9ae007a377b8b8336f33386b0eb01c45695c3ed2da", + "0x88dc87826941340913b564a4f9b74985a311371c8e7b47881235d81c081f1682bef313c2f86561a038757fb7d6a1a8dc", + "0x869e13e3fcf91396750150f9dc9307460494c1d365f57893fd06fb8acf87ac7dddc24e4320d9cad0414119013ea739b8", + "0x92194e292303d32b91ae9cecb8d6367c8799c2d928b2e2846dab1b901371a4e522fc4089aad8f4ee676f0614ff8b19d7", + "0xaa589a3e512cb4f8589bc61e826a06d9f9cb9fdfd57cf5c8a5a63841435b0548e30a424ca3d9ef52bf82cc83c6cb1134", + "0x81802e0194bc351b9a5e7a0a47911d3a0a331b280cf1936c6cf86b839d3a4ab64e800a3fe80ea6c72c3751356005a38b", + "0x88e5e9e3c802314ddd21cb86f2014948b7618502a70321c1caf72401654e361aac6990a674239afa1f46698545614c93", + "0xabac1e0f85d5c3ff6d54ed94930c81716d0ac92be49e3d393bed858833f4796c2b80bf7c943e7110de7b2d148463bfbf", + "0xb7eb416004febd574aef281745464f93ef835fd65b77d460b6ad5d5a85a24b536b4dec800cfe80ae98489e54447e8bb6", + "0xb3fd8ed1c30e7c15b0bc0baf0d9d1ecad266bafb281cd4e37c55edc76c202fb1e4ea315a91a2848f40f481793ae35058", + "0x86ef674ddf4b7d303c68bbfb53db00b925ccbf11d7d775ca09e458f4ecd868ca828103e8e7cd9d99672a193e81b83923", + "0x95ef414e9f7e93f0aaaeb63cd84eb37fc059eb8b6eced2f01b24835b043b1afb3458069c45218da790c44de7246860c9", + "0x93ec8f84c20b7752bfc84bb88c11d5f76456136377272b9ac95d46c34fce6dcfc54c0e4f45186dd8df6e2f924f7726ab", + "0x95df5f3f677c03a238a76582d7cb22ed998b9f89aecf701475467616335c18e435283764fb733fb7099810fec35932ae", + "0x8cda640695c6bc1497d19b9edc5ff4ea94c1c135d86f573d744358758f6066c1458901f9367190dcd24432ae41684cf0", + "0xb19aedf5569435ff62019d71baa5e0a970c6d95fe4758081604f16b8e6120e6b557209cdea0ccd2efec6ff9e902d6ce6", + "0xb3041f21f07d52e6bd723068df610aa894dfdde88094897593e50c5694c23025e412ef87a9d16cadd1adbb1c6e89ced4", + "0xa7f8d6ab0a7beb4f8d1cfef6960ebdaa364239eca949b535607dee5caeff8e5dfc2a9cfb880cc4466780c696cff2c3a6", + "0x99a565b4796e2b990bfcb234772d93c5ffdbe10453b5aa94662272009a606ba6ea30cc0c3c26aa22982c1e90738418a5", + "0x90c54b55ff19157c1e679d8d4f7f0687a70a27d88f123179a973c62565adfcc9347cfe31f54539038cf2f34556c86870", + "0x8612f34bcd018d742202d77d7ce26cf9bc4e0d78e50ddf75250b9944583b2c6648f992b635ea13fdaae119764e7c28d5", + "0xa04fb38e5529bf9c76ec2b5e3a1ef3c6f9effb6246c7f67301cfed707356ba1bf774f2867c77a5805933f0c8ad0ec644", + "0xb4800e7b503da0164885d253135c3b989690794d145182572181995e6fa1989f3d0324993e871bbd5f48fadd869d8a18", + "0x9981cd4f28ae7b7dadf454fb3aec29746dc2e0ca3bd371b2a57cd2135a7d93559e02132528ccd2d305b639d7ac51613d", + "0xa3ceec012dd1fbad3ef9f9f1d6fe7618e13d4d59e3f50540d2a57010d651092979c75442ec8b38a1ab678505e30b710d", + "0x8b97b8654d067fb4319a6e4ee439fb8de0f22fd9db5569ba0935a02235cb4edd40a4740836c303ec2394c59a0b96308b", + "0xb3d1bf4410fec669a269622c3ce63282c9ac864620d7b46c9dfcec52d8e79b90c4c90a69c32763136a7f2d148493524e", + "0x93174eba1e03f879e44921084aa0ee3562e48c2be49085de96ed7621c768ff52324d14c8cc81f17d7ed50c38ffb2c964", + "0xaa2194cd0fb7aec3dac9a1bd8ea08be785926ed6812538be6d3c54218ea4b563646af1f5c5f95cb914f37edfae55137d", + "0x93f2c0dd59364f6061d3da189e04d6c64389a3563b062e8f969a982cd68cc55b4f38b21546c8a67c8df466ff4f61f9c5", + "0xaa7dd497cc949c10209c7010ba4ce8a1efd3cd806a849971e3e01716ea06a62e9d5e122ad1d2b8e5a535fae0a01a7761", + "0xad402424b2a32bca775a66aa087580d7a81f0867f293f1c35580b9e87ccc5a2bab00c29a50fd0d7bd711085ae2248965", + "0x96237843d8e29ac77fc6ebf4acc12946ad11697de8e5f152fe5776f2475b790226a7d156ac48968dd68b89512dc55943", + "0xa45c25cdbb9fc327cc49a1666988af9ab4c5f79cea751437d576793a01c3eeea4c962c05c0947852fe0e4c63e1c84771", + "0x93dcf834a614a6f5484cc4ba059e733ab5dcc54253229df65ff5ad57b447353ebbc930736a4c96322e264e65736948dc", + "0xb9a94f82a82c0c5a26f2c1d5381afec3645e8ee04c947dc3b7ad59a73018db1e9965ab3642f2bbf60f32c430b074fb22", + "0x94eab29b3524ccbe0c4b928e5fa5dd8f684074b332fcf301c634d11083653ffee4f7e92ddbcb87ed038024954ad1747b", + "0xb8dca5f679931d6abef0674bad0639aefad64c2b80572d646aaab17adf5ca1ab2ebeecd5a526cadc230bec92ed933fc2", + "0x944d394958e539251b475c4304f103a09f62448b7d8a8eaef2f58e7de4f6e2e657d58d5b38e8513474115f323f6ec601", + "0x8a5ae1f13d433962d05df79d049b28e63fe72688fc3e6660aa28e0876a860c3dbc5fc889d79f5c4dec4b3a34cdf89277", + "0xafa5278724998eced338bb5932ecf1043d2be5dd93f4d231d05d2ea05b4455f2ffdc0eadcb335dcace96dd8b2b4926fb", + "0xb91153a2f4647ae82fc4ee7396d2ca23270ec7f8884ce9eead7e9376270678edd42dd3d4d6c003dfc2dde9fd88cc6e7c", + "0xadc932f1c679bf7889cb1ff4a2d2897d7973483fa283979a0ea3640c80ed106ea0934c1961dd42d74b22504be49851f2", + "0xa82e90761fae684d1415cee0649bb031bcb325ae0b28f128ab8e3650bccedd302a70de1a341ca8decfdda76f3349cad0", + "0x8ae353188b4b98835f4ef0333cccb9e29e1ac3ec11d554bc96f5880c101cb3c84b8eefe72f2287b0812735339fe66cfa", + "0xb8b41135bb1a1ffb64afbd83e2189e755f2c350e1273cf47c38ae9b8c4800d831436a69458b8ef9fa8b95a148d8ec9fd", + "0x96f75a04d8752fa93dc1eaf85ad333cff4eeec902a345576139e16de3a88eeb71b6726224349bb9844065cc454d959e9", + "0xab82b05e3923ad4c26f5727c60dc0d23063c03f5a4fd8077da66aa87042cad1bd99586d4ab35aa5e4ce6f4da6fecf3c1", + "0xa50c83db91c26ef7bf1720d8815b41bd056b49fd99710943679a162ccf46097a7a24585750ece886e38eb4fdb866fa37", + "0xa719f667914a84f62350dcc6f4f30b9ab428eac6837b70318c3ac491c1e69d48af5e1656c021818f377d911fe947c113", + "0xa148807aafddfa0a5624c7cb9e42468219e4bdb9994ec36bc19b6e6d7c4a54d3a0763d13ca80624af48bbd96d73afca5", + "0xaa012f205daf22a03e9fb13a63783dda7666f788a237232598d02a4d4becec7a699ab493f78d722ce68519262924c708", + "0x97fc15fab5952c5a2d698fd6f7ad48aff1c8aa589f7d3b14285fea5e858c471cf72f09a892e814104fa2b27eb9771e73", + "0x8da8840236812667c4c51c8fc8ab96d20dae8e2025290b9cde0147570a03384370b0fcbe20339c6aff09cca5d63e726f", + "0xb477d85359a8e423fed73409f61417a806cb89c9a401967622aba32bf85b569e82bca1b3394c79e180114a0d60b97316", + "0xb3d6ee2ed1e4c5cf8ba2c3a4f329832e41c7fdcbcda8a3fcbe8f60967fdb1717665610b7c1ac65582534d269d762aa09", + "0xa0b3b30b1b830b8331ee19f96b4a4321a6b93a3395b95d3a895682c65ec6ea64774b878b93514eaf353f2e4be28617b8", + "0xa2b88e9617f4d30ef4e686d1932ad43cd555fadcb5102e51bea19e6fca649284ccf4debb37b5cb2090ef386fa5bf5327", + "0x8a4446f7e8463ea977a68d6217a9046ad4356d6fc1c18d46c5d2ab681ea977b8faff136d65abea6bbf8936369cb33117", + "0x91e7464bc56e03f436228104939ddd50caace5a38f68817bb2991e193b57adf6835152bbf3dbcdebf0382ac9823f60c9", + "0x961a441e6cdf8106c4f45e5b47190d35644faec701c9cfc41ced40cfdd1fa83752fd56c1ac49131a47f1970a8f825904", + "0x94b7b165cc71c2ae82976b8f03c035fb70e90028992b853aa902c0467b384c7bcf01d56166bec5def4453e4d0c907e52", + "0xa5d32cffabbf547f900026b34ef46f08075b7a244565f615370d2f04edf50b094c95088a4a139ce07caf55bcd99afa07", + "0xb4e06e73660745f75ab2f34d9f6d2675b58f80f911ab6dd4c5a6ce1095f9a2b50d86f6ff9a05394190bdf96af0827920", + "0xad3fd8f83c0103b29d41319209dffca201d2b98094362da08da3fd6ff0ba96796b49d6bed525c9adb96c2954858e7f48", + "0xb0c27430695f0fd20ae31e1ec621da090094f2203e17411db9384695ffcf5c7c6badf461ba49ba70164aacebd6f278ee", + "0xb9bc6e972fc3b532fd2b1eeafc4bceb77604885f32132af6a9a842fa2440df452f49ec0cd9d86da1180e8deb0723b260", + "0x9729e22d6104b0174c136a854920f542b384d375040adcebe36acc253bdb55845eb43e34dc5a7cc27d22c417973c24d0", + "0xa8b420b36d48786c9231d454468a6e855dd7f71dcfd095efc9855ee70dbece0f06ad277f7829c5813fc30524c3e40308", + "0x8757dff5499668c93fc5d9cea0a8db61817b8ed407200d623030b5849a913d12f8371b667cfde8d8082026eda7407e8c", + "0xb859ad747ca5af661fbd03a1a282df6e84c224ecea645bc2d4ba5e35fa06cbf047387319fca0cbc76b712398c0798968", + "0x8e3173c27875f1460297af0fa736c945dc842ec3e476a973d3d5f790bf183ad3ffe96ac13868c5101d8e299890791864", + "0xa9d725e2b92c878be42b5eecc2c3081c63c7231ccc7e2dee17ca6a4caaeae22788fab1f1465fcbd7fc236613fc2bae4c", + "0x86f6c4f04a354cb2470ef91914816fd740f8d5795ce7ff981f55a2634695fde5951bbae7a4bbc4c63747040f8644170a", + "0x851773cb26f320f0c3f252d95ea7e058ffcc795dd0dc35e459aa1b6b448238909230d809e82022e64b7fca5d40b8324c", + "0x8962641e0306220d9892fe2d452caa286301a3c465185757be7bce2d9b2c9beb3040280099606cc86773e43941fd3439", + "0x8beb6e08c440b0de5fb85251d39d9e72db4e556a2dfe3dae59efd8b359d08492064cebd8d8993254b43bde8bd67d969a", + "0xa7e047894466ffe3dec4ab8d5462f2b1d8ac0df006b1d2dd26caf499ea857d93a811cf42233f9e948c9cb903beec004c", + "0x92eedd95557a91691a5e2835170390ce2401e223da43b78615a804c49566f9d31cbb7f10c8a8390c4bdcf691544fdba9", + "0xa5e5b5d8fa65824e958bbae98d146b4b332f97ed50e0bc2c58851dc2c174ab71bcbb1ae015cd2955c26b368487dd862f", + "0x853a494eafb308175629d581ed04bed71bbc3af9ca4c0dc483d03d27c993a2bbd88cea47c2085a6928d166fe6938fb77", + "0x83f06b88d29afbfbe8f61811690322ac4fdd6abb9a23612162e7a2dd6bcbb5f14cee298ebebc1a382484f7346dc51e60", + "0x8c9cf05735ea5a0e563490bdc7ed29a4426643711c651e35c8551ca6f855c8458ae8f0933a022d0bb9a952edfed411f6", + "0xb906b48d807748a26cc2a8848455a76ce502261afe31f61777b71917bdf7de2fece419db636439478c7582058f626c29", + "0x97efe1fa7c9b25d8bea79d74b6cdcf88f63f1e865f54b58512a2e60428630b0b40b8b6af1b5f71df47520507548c3cad", + "0x8ef5ca6e753818906bb3fc71405928d8e4108854ef0ef01c1009071b353bc2852e771fcb619d5fea45590e8f61003d7f", + "0x8e4d901661e2913740d70ba4d0745df5e8c9c0a260149d9362beadc7e669630ba909ff0e8a6cc85c54d6b7435d0d351e", + "0xb7c6ba3bebbd9592967954e3a480ee8df1d9f5965f04e7d78a5415b645128deae7ddaf6ed507c8877bfca91ce078e529", + "0x840bedb0ad4e25acf6cd25dee4f98fea495b2312dc5cb7a8388c5ab00b2acb9cd25da08e9fbead145a3107972b1ccd5d", + "0xa8d4578dbafdb27f3911af59962d89e75dea74db55346720357790da677312c203107d9c7911535aa563446fde7d4c47", + "0x86d3b77f231bfa09251b7fd2ce09c27ac520ec35d783e912476f9a4863f83d269eb175790d6e735da9260293d707f8ee", + "0xb34909f1cc033232652da0c34051a769dc76adb1aee00674a59dc1b860f6e610974c3b4bb69a69ccc73e01f042431242", + "0x90799854d0cf34e1d91ff8e101bc7c5007423d34d2f3bd9adea2ecac57e83f3a65a506bb93d4caea49b29f6d18149957", + "0x8ef94cde29b037e19a1ce7bf4418ad3c95cd9457412796ea385750c19a6690f13a3bb5bb6a9ee81e7a40face1e0a8bca", + "0x97053d21ae8d75972fb37f6fe516c38c32ab162fb56b9f510f954858f4e3ef6ac8c3a9557ed3f41b7b6aef05fe97f931", + "0x90a9f9f0f40991f3bddc58b92d40382147db22cce50d092d4a05aad251b46b94e71ec9f7107a180243288059fcc5ce29", + "0xa14265b1344ac2921b0f890d13bcfc432e4f648ce403e261fce4d3bb32ffee9e2794c02830346054f998e82784c77040", + "0x91928402ae121e56a3e64cd6f390127e6e92fbfb1967ec6efa4f52f3e8058f1f41a0f4fe96b5bcc11641c1139e790b2b", + "0x921c8c92b6d40da6c5a7b592acc74fc0f577d93767b9aa4a1cd302a72dbf503a1ea5b2c29fa0d0359bff3b8f252246d1", + "0x93ae0ebe0e8e133fd80cf67a499047e30ec4c4660ccec9d49098717ef57721a030f423e00c5e74af4ff4acf014a10497", + "0x82c865e21905aebfe0496af1c6ac7e342b5f446a9edb4f7da0f2fb0340abfd8e6fc545da874459d9aabe6bce0dd9bfcb", + "0xaee3961d8d2687c0f134b9c28b920bdc4021d925fbe14323c84224a9fe161248789249fb85436a5891d0bbff42c2a3e9", + "0x91aee420b98b6949482b8ff4be996b97245b4e8f583a6e085226539074f42aa89818395efd1a6699735a569bfe19d623", + "0xa48eec22c192e495b01722d0016a54acc45ff837e2a95c4294ce81d5a4e43e0053a6f0ead8a4fb3ddd35faf6607275b0", + "0xa26e15937c11faa30ffa64817f035e294cab0e839f73d29de8a244ad039be4e221eb47ea08d9a4658b0152fc3caf6110", + "0xb84450f948aa7c8682fccb9cae84d8e3558adf2d0ca5fb81eb200415291158720f8f3470542ab5b88c6873ad08e7fa9a", + "0xa8e8ec27d0608d020169a85d6ecdb40eb402f006a3b97afe32cc01987721b3a68a92ec693aeb4d357e189e05fadf699e", + "0xac87cd535ef5699312cc26f86adb71baa0be42e858bd5a2d94ac05737dac63430691e29b9a30d2559ad581a172519b2c", + "0xa4481e67b524f8cddf2046625efd3d75efee6aab87ddd2c1b22835647e918157e5e924ac760db2195c86d326f3db1615", + "0x891f29ded231486ee826840c8895cb325f7e84a5a6d2eac246cb3573612cde274720233b1978318a57ed337a046330a6", + "0x906b6e750e6178289012769807d2598925d7e51c260c14497d8af978b1695990e3352e6e809a752f376597a68083870c", + "0xb7a056898ee1e46f7f29702fb39232f678ec173eccd170303b3b0a30c8d8cf1a5321384e3513e3b03bb742c238deaa54", + "0x8f2f035fd96c3a336354c89ec9b8222803bf42e95fb2412c28d4e75eec99c1d4d402501ccae17357b757db8bdb0bfeab", + "0x81228625ffcedf977fba9cfa13f6edead3985e2651d5974789c394a69401cd7face9e20ae6694be4c0d4bab5e99c61a8", + "0x885a83eae25e61439ad809567a2ab148583402e01cfdd77b0e37ab4038935425c64b4e0886949bf06438c35e80aa13f4", + "0x8926387f48752f6933899c48e038cf14e7941ec6a58bcc0a436614b396296a17aa53e6873803dd3041dae470bd493fcb", + "0x95d0d3fa061f4d856eca78a569aa132db14cede7646f97e2aceb6da0c8ea53195d3b7a566fe5ec8c41b95ecdd89a1c6b", + "0xa3c817f4062ed6aa94064ea695d76c1825f3bf77b310fe1db28b8bedc9aaacbf1019dbd128adfd53042fb943d863a2b7", + "0xaf1208417aa584052da309169854149ede38a3ad63c76cad6e43afb6f1a7b854edf8310a0b00088c039259cedf0f859b", + "0x8b713fc3196bad35dbf364089049ada5477e540d78d76a5f0a9df98f7ba4a0e65dd0644509c149f9b07887298bf74b04", + "0x89c09c43c5b733c4a417cd9ebc0795cc3348b72778d31828a9171427779a82ef023c1a4fcfcdc919ae25056f9c826fde", + "0xa0759c850ed320c8c874435e90ace6edfb8e7b3f2a09d942b8ad8339c508044ee2ee26c70f1b626ec49a77971433b6a8", + "0xb85cbc58d4fd52286e714ac4eaaa0b2743a1de06fa03ddf8f6668ec6f1d204acccce93b10620272afb8c0b49bc4b0a43", + "0x814e0a87384e159892a8d23036985fa3f489c53bce192e107bd2d64f57b1bf5ea0acc1ef46c7a42bbc5cd0924d92b4a0", + "0xaa6821da96ad89d7881b878e141076522f104ea9a5bbdd1fce9f641898f7d6232c518a87a0f666871d7e3165c26081e4", + "0xa9041d714bfc067b5427252186fa3557bad598fc0067dc8521aa9bc1ae298f6e96113db5ac9f6bade9a85d5a950c9755", + "0xb8669340f3064692625e1bf682d34fbe69a61689e3aa6d6a3e822c781d406b0300dba9c3f7b8152a8c2513f1310d4291", + "0xa78c53316ce768a1dc5968030bf4fc885f4029b1ddb6a5d84a61c85af686c73727f62823891edfcb6ccf4545de366cff", + "0xad1d3aa29ea28292ddd438c865e2b5d93f32cdf009e6d5f5dc726de996583925727e6348bf1c28c22dec0bd86aaf867f", + "0xae1447a2062e9e28af5f38aecc60fe150cd10c2edeaf2110034aa144f6235ed7fbce432a58805d4fe1f6b12652d6e1cd", + "0xa32146634332d3303934550705353c6d4fae5fa5985105bba35041e74cd71e2aad67b45da171221f6ed80f36bf6dffa3", + "0xa232e8286184196ea77427b53d8b52c44d758ecc42d22556529db3136379b4989dec61cff610cc6cf6700a450a847a94", + "0x8a72c7255125a736da52dff5f77e44c3de29f88fc05f5ff9227c69df296930caaa11446595e6bea3bd946baac5ef957c", + "0x9688a981a9457678067f629f8efa6b522e7318b529f88d37ef56c5bf8f1c34fb9bb3a918ab73caab82bf5abb0c03518b", + "0x88286f3eabd71115fc3b17a6bf6981340a81cf7e5f96b0a1a016d4ec8c18fb486d46c70919123d0c189a6f5d6ff29a1e", + "0xb535e701b40d793c02ac0d625ca91620d3f4a512aa9741f71389e58381008b2f93d597586d06213c4e103d67d0ddf6c5", + "0x80d0c9dd941e8d8d3700cc51a434a5aaa3308cf8ebfd14128ccfd258f826b27cc3cf5c3ad7851340393abb1eeab3a157", + "0x87049225fa2380d93f18d3d90cb0697a56b373b66d7f24ab209966aed8b55a2790194d5885399db29dd5b1f189eda64f", + "0xa52df158ce8670e0290551e8878d63dd33b4759d6f50e448e63fc7fe6ea99dddb6f180be5fc0fc3918ce54c05f80b356", + "0x8b2a728b39c465fb0f60b0c486e5dc8d5845ccec03d3dd93b393cedeeb3fe1b44518359f1ed55fc770a8f74bfeb9923d", + "0x91fc05419dba718fa4a910dcf256ebea356bbea00522d8d5ec3e7ba4271a26035aac15e8d9f707969df1d655d92dac55", + "0x97c8779ae80c24c1f82d5a714762d6ee81069224e39515e41d8a71c9310dc5d1c55cc92bc5c6a4bd391ae4c321d1d4d2", + "0xb5e5aedba378c4484e3a7a4ed41b75b0844f674261c2501497de6f91f7274b5a4c1be0e055f2e0c0cab843d891169fbf", + "0x8a26212f27211b295beea500abc8e9d430a8500d3a350cc62f895d39e8b4668aa638c17633804ba353010000165637ae", + "0x864a95118e5d394e00e99efebd505df0125525c9ebe165764c453b80ad3edc730feebde3d93850745dfd88a27bb8f20b", + "0xa092e0b78290e826cc1ae56afffdd08f7c10954f549a3ea6666f3db1b6cdaeb7df53db28dd2a92446342930fe60a27ce", + "0xa1720224c0626a081b6c637b2a6d37da85d9a82241e5efef3bc15699b02a69f6304e43d8ff3144d60c16e00225d6b39e", + "0xa7b3d098cebea9cf32e19c5195608182b6afe9d4af6b9df532c047eb7a941a971279b2ae6a4b80f2f9d9313a6d788ce3", + "0xa3d2451e6788944802c5077a778d7b7299dbb9d1612676bb6baae78f39976e0fd879493cc4a4d737b8174b472a456850", + "0x930121b73da844571b1411d56760e80923a4ee09917b3e9cff4d3dcb0bc27026ff2c4e2c44e7aca7d3f8383f129c7f9b", + "0xb4b0119d163ee00a2b74bdf188a5cdcf054daaa48c483b94bbb4d09ff615afb4a91347db6363bc7535e2af9054ec2214", + "0xa5846decee706780201095a8cdd48fbf3d3a2eac8d089a818e5e22c29457494bbfb4399323b067f3d2be2197c33dbd98", + "0x96ba600df10ee7af5a9df29c0ca31dbed275d647faf9c66c7342de927ceb25b5bdd852dd7aae0228b27897f90fdd5d62", + "0xb6ac51ddc98edd9fb9f54ef84bf372a041d58dfdf0dfdbdc4b08ddc1a7ba93ddbb1413dda3c1545a3fd7386c6b85975c", + "0xb35f3efd91a0723e0d486188ea9675a3462106470455118392d7610470b623caca2fa33829721c05fbeb0fabcf570bfc", + "0x87f49e85df5f8055714a8ce7adf37f6a278e64e76ed74c60abe3edfc3611ef5b0426d4c6da45e5f3b74d30be1dc6f539", + "0x8ff8bb06902a71b1e9177a77367318b2e3e0a88f5d74d6907ca9943f4f9f1ceb5f297132c2a025259d17a67e880d1bad", + "0x85eb6de6c70fe5c53ab0ab27aa0fec439f136c979c557d317337cafa6e6c5cb3169679c9169567dec5f6c72b3c057d83", + "0xac18715ed1080771d760cb7066c6328faf65d9b30517903f8a5cad8d66d5c6381156b521107d7cd75ebb8c30e250706c", + "0xb95b9eae4703727e4ac9ddf2ae675906487bb78905a5f9cba74a4cbfd118d96b7afb6ef3ed5edf14fd963b830d71338c", + "0xa3b47b52fda16b62b11c8aa4daa56b0b669c4d5c56a3059b7d063284d8a91f6fff9ccccab23d6ceb9650483b2d353039", + "0x96a95b3f327df94c85e92f2e406f1649ac621533c256b062738f3c3ee137059a735a3e6072247acf57b1b0d8c219bd7f", + "0xb19b33cc04570be94eae8e943d5bb17bb0c96e9de4ca84f9f41b37320a1a03d397d53747dc13275fef1b356de557214f", + "0xa1faa3dcb931dd91507f3f12a17c43f6627fa2bc5c71fbdd27548e091eaaaba262477949cd51290e81196bffb954a492", + "0xb060a16079dca1d28a1fb33cbc26f368630ee042d980ce305230005d5b9ab533a7a695281ab76e9214458303932d8bbc", + "0xb303783196a858fe45d67e0520c30576da605fd69964449c20009fbd5099cf1de52a32d326d7c3b864de07440195ef40", + "0xaa550a4c20d1003d137ffd8fbdc1196d09ad53cfa0e202302093a80fa3bbc4c9aff83f34f2151785cc1ce5f30255693b", + "0xa7f8585f45566a351058e10c6f1ff4a7ba24811f1482a47202f581525615ca770da93f2f58878788b45b92cb446ef4ec", + "0x8206f63a9a5b59bd68e64a843e68fcdf706f4c13bbfcdfa9928298e5b9251006ae0bbd80c715aa3c9957d2c0148b5059", + "0xac9490abe1241319658f1c2c645cfa01296f5d4106020c7894b7ba4a65cdd52f6c5401bd3b3cf1c9863e088cd8c9a16f", + "0x85dd6d9c80a1b58c24c4d2cb7590d33d2454f381f58e820979948e5831972360cde67bbd56e1860077ef5192fcacb904", + "0x8b0285944c676fe2519cb68da0973275fa29c0718d838d363ce46651b068d29f867cf9fe579ff8da0bb8b37d202bb23c", + "0x95147275da658d43a758b203b9ca1f1c1478853e9bf77b5218593142e2bd9c0bf46d2206ab64cef99295de6e9a268edc", + "0xb8efa187fdd3e1f46c15cd596e9567690c10e253b5beaa5be8074b6ea4e6d3d06e0f2b05323453239e419ae1e7128521", + "0x8340464f52c92e31806fd3e8e65f56e27194d1f6daa4a0f0b3831e8102aba16f88bb5a621633ddb7dd0342e1d2d12343", + "0x8615d87dcab85a78dc052f05a01e751176b756b5dc9985014347454ce5752f459dd6464e1c5aff36cb6c51b783fa2692", + "0x80c6e35c0d3defbe4d3968792724a23f0b8830dd2fac58663583a49339ea20f1812cc4140e3ee867c7e716177319bbbe", + "0xa7aa63dbfc201dde8f29bb6e23d7aa5020dd35bd18a0cc93c8a10c35d695913fe25b9e8cf9b5fd1899e9657b22bc8863", + "0x97c2a4ba80c4caba2e729a603d2faa0120915e3fe64cbb065f7ff33de5f877f1ec9461cf455e88ec9e9ded9393939dba", + "0xa54bd1419f0e2d2d87757870f37c476c7e3a13502f1ada82fd7394fd29f8a00c4986473d753034d0954a2550badbac0b", + "0x8d3e2bf900d0d2b9b46e6e2f37620f0cc90526dbbcfaad4e4a37ed53f39fdd23bd3a6f21aa7e800eaec937d9710dd6e3", + "0xa88d2b1c7802b2dc216c2b6532406c091bfb12f29121b9a82c1154470e250188413ddd3e79f7e009ea987a4c45b332e5", + "0x8c552c2101dfdc3f99c2da436115452e4d364eefe029b12946f05673c5ce1cfb48d39a579625849236dc6c8e7277dd30", + "0x8415c252d52a26a6400c3189c928a98559bf24162ecf3eef1d10e439269c31d854b0b4f6ec7a2430e3f11b5d77de78d6", + "0x8b38905bad93a8d42339dbdb5e510003c51fcaf05e04f88fd7083753353bc1c4c00a5dd4a67431cd4456d0669c7040e2", + "0xb1d0ed8862250d0f0d9ef9dcf0cd16d84313d1a795dc0c08e0b150dadf9ce73d32d735e04632b289cafa69a6ee75dc89", + "0x9434e18a5fb631b10edb02057f2d1fe16000ee55ada3c26a079c9fc3943e29d6de99e52829fe7b333e962270c712e51e", + "0xb1b9f3914007e6fca8ad3e7e848a1108988cb2318da36df24767d804e95d1272943fda948451135cc1b5052a3953b081", + "0x8c02947a76d7b6c0a700a83dfb971dc105bfe996e18c521445f036310914b349ab28e57571e36ae08d13a46fb01c2f43", + "0x893472fbc225f973a0ac6a0a0130b9cfb7ab6869dff80df71a62b1f6beb4afd069bbf35b4f327165bc31dff39e4fcaa4", + "0xa7c176c0903175f3540d62f9afee994d5d9bf37081e094644b22f017e94c515afefde7bb07f638342abef7de657f8848", + "0x860186c2b1d3b1e657729bc804275fb5f5ee89eaa60848fcabd3871289665ea9f0efc8a95792d884972bcfa2de96223b", + "0x865b38aea6386d0ac8f501a7d934e23d01dc50105324e354d4c4fa3cb1d4c29c26f4566df7b1a728e10cfaa9d24552e6", + "0xb4eea5548de6969dada658df604b5d9c49002e2258352838003e0fdf7b299d81fb025807a7f37cf5b547cebd7f2c1f93", + "0x8982de11ba68d63a649a3b296d4d56c71e3c3eec016db250d733ab7c3b9a620c09c5a5d0b64fd30d3bc03037ca4b17c9", + "0x84d8b8a10d67eda4716673167c360fc9b95717cf36ef1d5bc6f2ef5b9d2624f0e76c2a704d016adf03e775ea8e28d83a", + "0x834d03ebd51aff4d777714783e750b84c16cb6627f8311bd8ff17c3b97fc4a5bba57d6c8f6d74f195d3030bcb5f07612", + "0xaaf49e0def0c4d5f2c1e9c17b51e931d2f754b19e80070954980b6c160178349f6d3c8d4808801d362e77f41a0008918", + "0x8ef4115edec841854e89f2bbd11498dac7396bca35dda554290d3db1c459ffc17be671f4a46d29fa78cbd6064cc2da20", + "0x9641dc8a64f4acd38e343a3062787c48c312f1382f7e310ccea3e95e066ab6dc980f6ed90a633236a435e68bf6b3c625", + "0x8a84cfc2cbeb18a11dd6c2a0aebb3f6fd58a33bb4b26101e826add03748595022e816afac79a4e7c20b3805252839dca", + "0x9770782d729017659844421e1639ffcda66a2044df9e19769b90292df87dcb146b20c6b9141bb2302029d84a5310665d", + "0x98c7ec9696454868ac52799d1c098c15ec4e08b34884dda186ebfe87d32840b81fd3282295df141c91137faf4cc02da8", + "0xa3f6eb921247617292162dfc8eec5b830ddc294a0fb92f5b4828a541091ffdaff34c392c1d7168259d6204405d90ec72", + "0xb185f77a468f07a54222d968a95635234e74fc942485604909308a9028ed2753b15902b9134749f381f7cd6b89cc8c3d", + "0x867608a682d53bd691dbc92eeb460d1c300b362ca49c11a280f6768ccec217f1145f9d59fe50d994f715ce89d38a74e1", + "0xafaad630ad8827cd71aade80edf3d7aeb65a344878db12fa848759e6233f6fceca563aa437e506ea9e0f1e47b126d45b", + "0xa12afbc84e3441594aecf85d089423dd3bb8bb33a1a384ddf7cc14caa72284caaa56aa179c15e3140fd56bb532491a67", + "0x98757b0b5e5837ddc156a4a01ce78f33bb1fce51e0c1254ee9b6d3942268d0feb50b93edbf6aa88f9ea7b3c0309830d8", + "0x89573f4a4ae752e9f964e42bec77d28a41840c28e4bcdf86a98a131d0b85367b885077823a6f916972de6ac110821bd2", + "0xa17f2745052de5de9c059307308fc49f56cb5230e7a41cb7e14a61c9efa742ee14c41023ce90c7f2261adc71e31045f8", + "0x914b07c53a41c0d480083f41a61c10429ea42dafea9a0db93862d2269ff69c41db8b110b4768687b88089b5e095523cf", + "0xb380cc3e0d26370976fe891d24ea4eeb1b6be8cfce01f47fd68838a27190e644fd57b049d3aa0a9589370de20e276944", + "0x906385fdfad60feec79eb1c303e750c659ceb22d9c16a95faaae093daadd53e7aa039a45d57e20951d6e1ca0dc899ef2", + "0xb5211ceee31b194dba60b616bfd91536e71b9213a3aaaf5aaf9b2f4cbdeb05191861d78b97eec58e3c81abe4f0488c04", + "0x97878e9e38c2f69d697800e7a2f132fc4babaacf471c79c26a757f771606e55fe696ece68a3163a0ffeb2f72274cf214", + "0x959431c1f54c46500c05aaa9a2bc4230531dad97ae768fa92bb85436c0ecc6374cf20fb0ef82d122db116820a943b401", + "0xb69e5a1c6798f30d33e42cb8d124f025d2c77c993c4c7107a539aacddf44d8d4d2239e802ece32e60ee4dbfdce201bdb", + "0xa8b09e5e9f802ad273b2efa02bcbc3d4a65ac68510510b9400a08d75b47b31c6f61ffdb3704abf535a3d6d9362fc6244", + "0xa41ace7f1efa930564544af9aa7d42a9f50f8ba834badcaf64b0801aaed0f1616b295284e74ca00c29a1e10c3de68996", + "0xa8f2aa0bbbc19420a7c7cec3e8d4229129b4eb08fff814d959300cd7a017ddb6548c9a6efebad567d5a6fde679a6ac6a", + "0x9683da74490a2161252d671d0bc16eb07110f7af171a1080dc4d9e4684854336a44c022efe3074eb29958ae8a1a14ace", + "0x8ef44d78d10795050c161b36afa9ab2f2f004ccf50fdeef42fe9cdc72ebb15a09389ca72a00001cd6d9b1d7b3bb766c3", + "0xadca54f3b14fb18298098970b0267301b7312afb75894deea1b2afa3e85b7a3b4efac9971ab54c5cbecba2da9f18507e", + "0xac5d4528f06fdccfc1370d5c3d03ed982fed0861a93a3f6453aa64e99360b124926d1892faaf72d89459e663721dfa99", + "0x98aa1c801bd615b8cba728fa993021e181e0ad717ba01c0290e7355694155407083eb53cb70819c4775da39d33224db7", + "0x8b3aea4c7c2bfe1020de3261ec085d79c7bf8a7903b825d2c70ebbb84af197bcc54e3653c5373a2045c3021526b63b66", + "0xa29f3de4cb3d99afff1daf7d431b38a33a9804fedc41626618928ed059df6f6fe9f298a046b594ffee951ed4d4e1400f", + "0x803fd346be540c5242667c18ee41b26bc812456ab13ff117196ed69b90ee608c8cb6554396b64066a546ec87a71ed6a9", + "0xa9c18d81ffd029c0339c72c499bb51685392253b996b6eabd8b76f05c6191ed8444a1397d63b9923743661a319517f7e", + "0xa048d5c390d08f07161faac71c5994baf152c883b205f3bb10d3501709d6516ae54d491b486303a11b751857a31f0052", + "0x9156fb4803e40e28d8d57d928481a8de4373687288da44fe88c5676a8ae013ed1fcc09d56a31140bf74e7f767253810e", + "0x98e289c725b18e0085afdfaf2acbc674dae7b0a2ecc2537a7d0b87e20eb785404ab05973a787f0495d2adb3e5565c09b", + "0x8a7237b249325bd67cdc1f9fb278710069033c304afbf270b7ea24dbc10c8eabe559a484d3edc733c77b4384932deb41", + "0x9056f2e5b02e5c2e04a69fa1323bbf1859d143761268d18e74632e43800a2a9c76fd681e924a19bc141de0e128d3e462", + "0xb9f2bf9e4e7263014296a82b9ecbb05d3f1efa4b2e675e3b38d3eace59da06a89c859256e1b77847886d6aa15f98f649", + "0x83b22949cca19030289bbf7cd2a0d8b84e1d468e78bc85271a6753241b89122627632723bc293cf904a5eb2b5dc6c3ae", + "0xa919aaf35dd0116168d2ee845122026416bec9633df113fbd913d8db5996221e234f98470d029a8ff182825b59fda20a", + "0x91726901f49d32b41afa15219073842278f60dcee223640903d871e318a1c2b541136b7b38a7b2ab7d31e4242fc29674", + "0x942b77666545bc9a858d36cfe857ab1a787c9528f4a0b87918a06bf510793264dcafd12ae6bd3ee300179dab7f40aed0", + "0x80adc1f2f9c47a96d416e44fcba41628abc0fae1f88f6a26aea4648419ab726f7fcc2187c7d5145e3d8f5a75c03937f4", + "0x8041e0f66ba9dcee01e336dd4d16ae5e4e1618512fc147cc8230003aa2940848162dc2187d4130bf550dc1f3559849d4", + "0x999e8adc51bab54386af1c5e8822986ad1b7ecaf1f8a4c2baa5bb2fe9d10710e49545c5a8bd89ed0e61a3d73a908e5ef", + "0x89272ffd39b6e9f99fafdd58bd9dc00f66f26a1d36b38a1ac6215e3546d966739eecda7fc236335479207cef95cce484", + "0xb8e0b7532af13f15dc04a0eb4ea8abd67e58f1b1c6ad2e70c0ffa04a5c18ec2018b5d7f4be2f9f86db5e0b3986f639d9", + "0xb96bd11b0f6ead4abd5fe1e4c6e995da7583b901afd01cc05e87d04663fb997997d6d39dd9fb067c62cb1b1cbb67516f", + "0x94ab08914088b973e8dbd5685decb95f3bf9e7e4700d50a05dbf5aaac9aea4be2c10c83096c02252e9238ceea1351d05", + "0xa188de419b062af21275d976494c131ba18d2b2ead8bdbfa38a777832448e64d4d9725c6a1d530ffb6513f18d5b68d9d", + "0x8f73c8c118fa25c76a4ec5611351953c491452743056a819c8c82ba4737a37d88da0b55f837e7239a5f46d2c05a1bbba", + "0x894a44769e0be1c26648b0d89c4c9f46dbdeb3a71b90c493093bee372bb9f2d3f319850fd886d51f4f58db0de5641742", + "0x87d239923b0db024a8d9b0281111d47b0761d81c50652268b074efa3ea70d793e30f874a91ce33a4acecd0cf38c01951", + "0xb1b48b75a97f9fc2dc9530dc69f6268829dd0ddd574516e7eb1b9f5c3a90058889a7bcf3d378738e6d4b02f5fbfa44db", + "0x83e3ee9526ffcb60c6e75b75550fc017912ec0daf96d0a0d5f58c1b229cce90c684ac7c3e17fb998def8e7e2e155d750", + "0xb9b7bba579e474b0abdc7775ff5f84c9f117c6ca17788cf5a5f01b2c35a14aa39036031c8d799fec2cfb371d9f7471fd", + "0x90d7faf4891fbc368a32f575dfb69f13e37161ab4f63a7139be103285a49490c2851a907f8d36e09e7d1a190dddbc6cd", + "0x968c8b9affe18fc34a4e21f0d8c5518341c566099e6b45b8721c9912bab3693c9cc343406fe90279692a1eef2a3f7311", + "0x8735baaf4704207550f77df73fb701d9a63329993a8cb355ccc0d80daf950145f37e9b4b22be2aba29898e974f9fd552", + "0x90f52b2dccf525b9191d836b205ffe966d9a94f6c5800f8f51f51f6c822619e5abdf1257ee523597858032d2e21014ec", + "0x831209f8f5257bb3eb452d3ee643d5f063299f8e4bfea91b47fc27453ac49fd0ba3cf9d493c24f2ca10d3c06d7c51cd6", + "0xa5a4db4571f69b0f60fb3e63af37c3c2f99b2add4fc0e5baf1a22de24f456e6146c8dc66a2ecaafeb71dce970083cd68", + "0xb63da69108fad437e48bd5c4fc6f7a06c4274afc904b77e3993db4575d3275fce6cffa1246de1346c10a617074b57c07", + "0xa449448d4156b6b701b1fa6e0fe334d7d5dd758432a0f91d785b4d45fb8a78e29d42631bc22aaa4ea26f8669e531fed7", + "0xaabe43de1350b6831ef03b0eef52c49ffb0ccd6189cce6f87f97c57a510ac0440806700ce2902e2e0b7a57b851405845", + "0x91015f144fe12d5d0b0808c61fa03efe0249058e1829bb18770242f5fb3811e4c8b57ff9cb43deccfc70552e4993892f", + "0x8e9c570811ce44133ce3e0a208053acb2493ef18aade57c319276ad532578a60d939ed0bde92f98b0e6a8d8aabd60111", + "0x8b21839b5dc1c9a38515c1076b45cedec245d1c185c0faac1d3d317f71f1bfebba57c2559bcdb413d9d7f0a2b07f3563", + "0x90413bbd162be1b711e9355d83769e6aac52fdfa74802d628ff009325aa174c68f5329ddd552ef93e8fdcb9b03b34af3", + "0x8b6b02e3f9dd1031ebd3df9a30432a3c86e64306062ef00a6d1243620d0cb66dc76f8d0d412eceff877ff8768c2696ce", + "0x9894b41d9fc715f8f6addace65451f41dc5ce7b983dd8cb33757b4d7259bef12f144e0077d0b662aa847d5a45f33c563", + "0xa353a9740f6188d73aa4175a6c5f97898a05ed7aae9d2a365f15b91dfa7c28b921fdef0a32d90b6fb82718b33d3ddb8d", + "0x984eab8faed87c403c9979f2d2340fb090cc26d00cb4092aeb187c3f4ee1df3f57cb8363f7764073188790b16dfc464b", + "0xa5c5ae0ba435fb7f3ddd5ad962358da326239ff236fc3b51bd22e88296236b109951cee1b98f444302badc58d1b5bfbe", + "0x880be1006b0156f2788813432f450f613d235f41aba52a6000d2ad310408ad73d86b79f6081aef1e8c51010d404ba670", + "0x937da751aae68f865c7a33fa38d718f20e2a1c65cb18c8e08f8441f0cdc77662789d2793794dd0a427cad30cd0b33f42", + "0x9496fde66c834ff86f205897db12bbf9a9bb78d9ba8b5fb539cd0a2c927cc6b4120c017b0a652750b45edbe5f650e5dd", + "0x97a6f409ffeb593e149307a14bc47befb632412d70565c5f13d6b7d032acd2e3ed0f7b6af701b387f11d69ee4a8094d7", + "0x97ed94934263dc0260f4f7513745ed3483cdddb9adb85dc33193c3a8b4d52affaf1ded23b59c34651afbffe80d40dc36", + "0xb2b26378d44f916bcf999db218b9892e06de8075f205c7dafd6d37a252185c2d1b58e2e809c717963d25627e31f068e4", + "0xb8f9fa1fb45fb19a45223f7be06c37d3a3501dd227c3e15999d1c34b605f888123026590697d0ae24d6c421df8112520", + "0x997aa71e3b2e8c780f6855e94453c682bee1356b5ce804619ef14834475511105b1e4d01470fe4e2215dc72182d9909c", + "0xac2cb2a7cf55aaf990cfada0218453853047e813d3f51f5a623d09f4714da79de6592671358a5edf938a67f905b6cb5b", + "0x8d8340d0c3081cd30d34f3ff6191e1ff6ad7994b4ebac19e5936f1157ca84e1813228b7605ee226366d6bab1e2bf62a2", + "0x9693b17669086003cb46c75fed26ea83914a54901a145e18c799a777db1df9c9ca6b2ea3ee91e7b0ab848dc89cf77f19", + "0xa6b6b2a6cd8c4922d78c8ba379373b375d66ac6ea04b830a23d5a496cf714a9439d81c865da92d52600aa4e2e43afcf1", + "0x89cb665020abc3f5e11a03c7ba5ec9d890fa9ed2630f1443a8e45a28c32786ed980b5343ffffaea60eeff5b313bc0d66", + "0xb37b989106594221bc6cf33a1a83c3e65ecdef279e90333a9e105b8139dc28384bb2277edd4b77c9e59d15e6afe074c5", + "0x98ce5aee5918d18b2326b30c1ba41669cce20bc7a1d1b585363305fbdea66055164a7ac398ca0f0e670291a3061022eb", + "0xb57f472d5f34beb4cf430d7c0f8ac5bd1c0621a284633ed36e6f7804bc2b7847f54b469c7ea163a436510d9e3b32f97e", + "0xae673a6579dbf0504c8fd0c8fc0252d2f7ae8da615a06f4d215c2f8a8f516201f24e5cc42967630c252905e5dbbd6377", + "0x97c1501835a31091a5a83f0546e01c85ee847a0ca52fb3cc0653f6a826e13d25ddc623a5dea139108f7270a1fd7043ea", + "0x9376ee667f3834f6c0da4324fdcca5c04712e0649877ee19da79a2d23be24640c38758fce562470ce2134ca34148ffe3", + "0x818af89c40379a10074cfaba6d5968ecf667f1a68a7edaa18e8977ccb34e0829f237c5634fbd079e7f22928b277f1096", + "0xb8e0af0be0a252b28df25d4a509f31878bcddf702af0e5553393c3dfd4a1f1247ad8dc2668bc8dedc9b41f6ad8e71b15", + "0x811667ffb60bc4316e44bd04573503f5b4dc44d1ec824393a699c950e5fa085b146537ddd6a08a3fede7700396a0df7d", + "0xad834cbf850b2f61ce799c4a0f8ab0c57039d4e1113933c50b0c00175171aadee84894d1376cf325bfd434c3deb44315", + "0xa8b7dfcdb40373ba4d55e751ccfb9070554434df9e359fc165284ee3dc35db6fb6055657ecf5a9e9b7b8e2e1abea4375", + "0xb56a5b9fd41c9d3f65532aa58bf71a38fcf07782e1ae0084dc537862fa02e6d66658b19d6f71c39cd5dbfac418da1837", + "0xa935af5ed224b9533b41a7e79f872f6851591da9e9d906050ccd1b2c772a1d6d010c5fc7160c4f8cd7d3aa14c3bcdc26", + "0xa81e580fc98692567b28323fc746f70c3139d989fb6aabf3529504d42d0620f05327e3385c2bd5faea010d60dd5c8bdf", + "0xa8b352054cdcde8ddb24989329a249b71498a5593a13edad1e913c795dcad3d24789abca9c7ed1d57efcc9e3156da479", + "0xb0de8a2bd7f93284b2bc700e442f52ada16a22ad8d86329591547411c23fff0333b2ab0c9edf82bf7903ebf69916eed1", + "0x843e9781b653d1a427f3534b2e86add49d308ca247546f9fcf565f9e08df921e4d969e1b8ed83f3f849e98c0f63e39be", + "0x84a4098c5dca9f73e827d44025473096101affd7193c40a0307e3215e850e753e9a08e6e74a442d57626ff26df77faac", + "0xb463eaaa2f3315b511c22a97fad353014d840a6a95fe0d457d0677e63e571407d7f5268f8775381a5e7adc3b4163eb88", + "0xad0417edaa16cfddc288eef4173aa7057ca4f81e815541ac588ef5f24b98d56fed6845deb6ae1a9740a28bb1cd8780a7", + "0x9271963b8fb2288a96e07eac13c0543ec41abdc6d978bd7c44ae08251ea49994412b542c77c8208cd71fd8e7852d4a70", + "0x8b68b6db9044d8bafc155d69e0daba95cd59d6afebb085791e999afed4f33a2479c633d31d534ff767b8cd433d591a23", + "0xa6a06a0e433e385437d9996ce823abda9848754aa9cdd25ec8701af35c9ec15df999825669bbc2e17cedb597a96e8eeb", + "0x94d414bff8b6b8597634b77a77d1060db8e1af0d0ddfb737a9bf1c66c8430e93a425510af2464bce4a7b29bc66cf325b", + "0xb6514049562af1c6fb7d0e8df6987b020f0b7a6e721f4862e36b1ba0e19af19414ede04b346be22d348b50875803d1bf", + "0xa42c7fb34f2fbee8aaccd1d86672d0acdf4e6bb083ff0456512d7e1e43be041cc0924322fcd986e6e1bce5d5ecce6f92", + "0x867cbdd169a52440ae0a75d33a28c7d00aa92b4b65aaac5e62aa53a8fc367c08ab8828cc8fa18b6e7d1f908d158e3382", + "0xa6fe0b768fff3e4a6153e59a7b7508eb2ee8165eaf5274d41ac2812bd4563c4ca2b132f0e27ea2f1c98759cc3589b61c", + "0xb3eb1dba43d10b9e17ffec8def053fc96f9883bacb49330a089a0ca5b9ab0182e8b5111ad4aa55c1ce1b6f4afa5c70a3", + "0xa1531351098bdfcda566ff4d811301c0305626c77f954a38420c490e7c684f517eb1a4e4bd2c3904a10bac889cba314a", + "0x92278d106ad2f27eacdb86bdb1faa0a07a93765bb79dcff191873c52253af83480114b2299ffe5324f9c31d0abbdbbd1", + "0x8900ba95a90c447fb6fa1f528af3d7a378aec25feb0620516b6b97e54b328fc31af42e46a8ad5e6e3029d83a6f2bbe5f", + "0x86053d481179c1ac910d5e7b9a5de82794b442f20e854583512ce1f9c3f09e71d1bf97d6700fe776debfe1527ab97a82", + "0xa32a60de492fc4340336416bccbd2591b5e414fca0aead82281212e24490acc01747537b3da783684e27aeb987245cc8", + "0x9820fe8e0338f21797143f368177e3669a1f3894b40ae9fa3b353125f7c8e85cc424dcf89878f2c7667f65db3b1e4165", + "0x934d64711b4348ac5e1395cc6a3215e5643b540f591380d254165486b0ec2a1d0d21c7d2c6310f9e0eed3d08ecf4b57c", + "0xb9fd32d589432eddcb66dc30ad78981360915854cc44b2afeb826b5d48a08e377dc91be66f5bf1e783d1a8bb320f7ccb", + "0x98c972cf01efff4fc2e485b47572e2d8dde22461d127ef401b71a111b0603203971e3cde40912643affd7341cd27e57a", + "0x8db6c1620760063edabd376f4399b6e1355462e04f5c81cdcb3989fdc00f9a466bc85ed899e886c89c149adad69edbad", + "0xad7b7fda0aa6e2aa66a27235ac5cc680aa04b85dce329fc4be84f75c9c961120a3d9e446aa44539aaac8ea203eecb4eb", + "0x8ccb01eaf41d816ce69ebd57754859e263530915e775c4e7d9dac37b2457a9099b9ae9b4c6cb09eb5ff246e3c9320c59", + "0xb895b83b5f7ca46e02697dbaa6157df6c7571864c83e504a8c77d965bc2ba97bf9353a71c56a020df64498bd40e30b21", + "0x8018c07a81c522fbc25f2cb14f2321c61b98bd8962ed8eb7d5823dbe5d1958a5ec2fb5622fd0868e991bcb6cae016ea1", + "0x95b16364e94d01b3664812264d7185032722a4afc23bdd33bc16ae87ee61816c741657c37138d9312cebfb5fcfbb3b2d", + "0x94a709209990a8b09bfb4b9581ab471aae3a29526eae861108b28edb84aab6d28f1d7a25dddd8150b70af34bee4ca2e4", + "0xae06c80839c5a13269b984ff4d8a5938c6f4d8d647b1b1daa8cf7f6145340b76a286cd615ec251a65501e6290162da50", + "0x875cbd0694eeb90d3567da9dc7f570d97b02bd9cf17bfa011efdd48f1d580608a3213bff4006603b8b4079fa66bded10", + "0xb27f88c455f025e1cd902097d6a224d76bdf9c9195adee30bef4a0b0411fff980787285896e1943a62271d0aca531446", + "0x8024880cde783cdb2b863e3dd856be92bacc5b2a1347e96e039fe34279ce528560d2df7d4d1624a4595dbafb40529697", + "0x8883d02c2a5c0e026d941c785128d4ac6f7a9de625ea735b7d6ff27a5ba10fa4d6370d450d99a855d919f40d64f86afc", + "0xa1beb985c45fdc30ac536f1c385b40b6113ef6fabc2f76d255490fe529468847a776efa674ba8fed72180f07d3f701f1", + "0xab83bd9b007561695210e3276fde72e507456ba277ad4c348a2aec7a6e9ebdc2277cb4bd0bca73bd79bd2240a1fc4456", + "0x8db27f516153812149854fd6bb1250e843a3ae1c9637df818b08bd016a769d0497ab6087fe3b2fd4080882713607bf46", + "0xb3891dde4e00d60386aeff161b4a0fbc30bb31ee7918ce5fc0b49aac3238a000ced192c9c4c08d90de3a0ba973d7cfd6", + "0x90a2049a15c02e59024a7a1cb0adea97501c60b1c7442fbbe560054c3d69264e69627ac57b7d9be01bef498bb2a60198", + "0x87df67a4bd72444b5faa4f3b067204c4927c869dd3b29ad192d859589a9b2c1d6d35ed68310081e140add254a9463092", + "0x8f80986a8dc8a0d6408ebbcb4f234e76413c11cb0d66067f9436bb232373100f20a4fded60f08dec3525315abfaa8523", + "0xb061e10beb12ba3683688a4ae3a91600d14878ef78a308d01b93e4918efc666450e3f7b0e56283468e218934231df98c", + "0x86b9e55f3783d62e381659d3e06699d788b88aab1ff99848db328a83c97d223f602201bf2127c5ecf419752fed0a224d", + "0x858d878e29925c87243e010020007f96fa33264e89c8693af12857b362aee3fac2244057e159651c476ebe1dfbd67bcb", + "0x8fd47cdef87d7a569ffce806d2c2dad100692d6c53e5f5dfc6e274f897dccadcee30fc6c6e61373961bbc1f3ecbfa698", + "0x892f2822daf3df3a759bef03168c1cb07408df62e024747a788e94d2da325f880bb9c6e136c7f6643f45b021c6ccb654", + "0x8714e37ac24f5a198f219e7c88a92172fc3db129e044e914663ac708d8101851e7c53fce79d32d0e6da74f2ccd1d30ff", + "0xae95e1dbba8b9e2c8dfbe1c202e9ccfd04fa396470035a699b902fbd86d5e6a31732a7c8cae00b9a4f6e51c8d560c7c3", + "0xb0cd058e77498e860fa20c5f8d9bd09bb249add1badf84ba8d1bd49e704b9b4bcd67a5c3d211840a2c8fefab3fea639b", + "0xb78e468d3a7da0dd481f333ae56534e2ef97587be2e259a458e25aa37952aed1cc5f835640f812d8052f5bada8f57b12", + "0x835de7965c6b26e7ad1b92eb6f0261d1f376fa12d61eb618d9b342b597c9c117a5a8f6a36269aeea88072b4641e6b5bf", + "0xb4d0eb99136b3643468c9c48a20fad62785a60fbdd3c054efac4bd1fa7979b4c9ca6c2c0b18069c0912bea2f19832790", + "0xa00c47315dc0700a850966836a95f3cebfde04dd094bde0742dee77b89a05b5ad655921f86fafd1e902938ff34d4c58d", + "0xab13fa0afaa92229a71ee91efae6d1b15f14b6eacefffb7401d41d0d6db24e24a8dbe8ee19b4680ecb69d2a0cb4e84e7", + "0xaa56c0fb18401210062dbc653df8e3732aa8921a1280e9737e99b26a0100a13a9cba8ad0317a69bba16193362ee0f030", + "0x8b410324a6406b345df0fa25f541ac20b7313fa55832752f70cf4c79f43b0bd3d5b4cdc447e6ba7bca08d0edffa8e29c", + "0x893362241ae412d9e5df46506407595c58ffbd7fb1fdaf0694c3432470599291238997abe118bf7737e56a4f5c9dc292", + "0x921618194a756be81cb49d6357cb392b32cc62d96c8ffb7e16d9659a0f226a0436bd378da7b835054dbe0de2c6372ef2", + "0x94a2904f10994928ff5367b777e1430047736fbece33442cf452018bfdeae62e84cd75cf80f8468285e347d504c94111", + "0xb4b81545b767f380bfe10e0fea9c3cc62ca8db40b43c83ffb245259378731298e3eb6c3bdc3a16932f88f5d8a86edc4d", + "0x936203c2453ff01c6fc635e4d54320d69e60047d805daae3b75633c2259108497b778f011e5a057249f11b2b888ea76c", + "0xb90bf6378d29339443c3f2008b1e2b5f0345f86e393027f14a295e583bf6e6c2b10f54b6dcc42079ff0d356c405b03bb", + "0x916913f550d327de2d8d6c7723dcef2e3869efaf95fd963d95c8980b97748c61ad8e2e629cead8577266d93fe39203bd", + "0xa033c6f3d5ecbabeb83eb363e54e5faa7ed2d7f4fb771b161762c4f003eac4e1afb236806b784baf2222cad54e2d3cd9", + "0xab289d4a5771147e6c29ff9ac2bf65d70081ea6c6af2d9b728c3c144574a31b5fd8632af57c18c389aa2cd994938bb0b", + "0x9488da2019ff13e290eeac132b491df58b5b7b23c2898ff1a67bffd7e9c9464c39bc8177a57950fd28589e3d9ff9c6c4", + "0xa5abe42b2e0891851440fb2aa6c1d8a86b571bce8b80c8e9e2692e5cb6d45a1b2f055c9fc4c74a7cd292871604129ea9", + "0x90bfef698e83c2ba4dc9304aa01edd274169a978b7154bca518daef394f55857d0d1922ebef3d91fc5ecb3b895d9e0ec", + "0x92328f1372b6406ec80786041b6d57018b8507e3881a08727aadfecfdfcfb0824394cbb1150117ac5da5d71b89e895ae", + "0x9719751c5f7a65ae2bed8aff7b4b8c34539ff011b259b7ff54f63f9d987b3fbdce5c99534ed561aadaf07bb6e939e208", + "0xa151816774aa9379fccec21cf212429a1c68cf91b055cbb9d931f461a8d5616c693331a11ac5c6fcfbd17d84ee0b44e4", + "0xa72977b1285618a45943ad00f33f37102e2885eccd2f76785254eeca495068fb1d8d49865343e9e8313c6c2c3b2024da", + "0xa6f5ad2e023a1585d90625c9f7094f0e8851c79f0eede8ec582ee8e063407cc5b8298e5fdc4c786e4fbbcecaf33e787e", + "0x82901e008febcea0c0a14ae21d985a397630e18ee6e346f4a449f23be228e8f338df567d30211a11180b94fbc5204bec", + "0xb9b57fdb8d14d1be87a25f89553b3966eb7869e0519ffdf4cc4d51f4cec90d68f7b81cdc0450e04207276e9c63ace721", + "0xa06eabcf43585a001448f3dc30411f3d5b74fd0a695c81eda9981842ba2bb0081d3f5a8360aa18b6d43ef13ea78b293d", + "0x926fe48a7e8f07559b7237beff9504476dd97b5b4d67acd01a3633358a6ba4c7abed5c87683a11209aa2ee759888e00e", + "0xa716cd3a84a963e2a5a46145b6ef4ebce705de52bf2945c374152a1e41c228a9c4eae0b6d1e222c1eea8b9c13c002177", + "0x8a9b5985df6fb32cdb06ba1591a977545444478f2fe985ed1b10de61c630f0a4693c2185d63f0dc0256b208072c43b17", + "0xa8eab26ae0ebcdf96a59fad1dc2d5e83b94abb2ea1774b607023f9d9e0fe065853b1e2242e794f989a80a47f550c0bd9", + "0x84adbf38164cd04f3d770a7f4b8eae7a5d25b4a803fb63c02b95b71b33e454319c44e07a760d22bf5f58e7e372d09a16", + "0x90f443a3ba1b9129a0bee400b5b29d42e50bb2aa56b0022bbfc3c6f8d69db40299871ec7c1b68421cc89e1af6b13a39a", + "0x81c5a94b379eb98c494a8d0067c748ba47e87a2ada0105202ed7651eb4e5111a0cd8569b06ae68d392c4fd74a37833d2", + "0x8f92324b14a1549ee0b186073a26691088e41556d33b54258fc6e0b000e9624156db4e97861a0ec22960e6c47ca8a1dd", + "0x8b021cd0fffe055068cc460aec3cc455952e2ac32be5fa060e0d1b6cf30ed15381618f801249e893b1b9f10dd82077b0", + "0xb3e9f0dcb3d6f0b138f589fa54dfb01f849890ab97016372d004aac55103f363a64bc0e606ddf75430f1534a30fc522d", + "0x8fdfe64af891db89b25daa859864d479cb7599486bd6f36e593f8f2f839f942261ffc3eed5001a93fde44cbcdc24c583", + "0xa9e4554373c5073e135874e2bacbee69c65308eb0785532fec6a37834e8d0b437b77a2f11cc63c87d7183b82cd9b6bc9", + "0xb4c47daca723ad7193ac5098cad4dcab654186ec5ea5c0fd014a3ac39726be954565a901694ba211820c011fa1c59e18", + "0x8835427e86cdceb4c11cbea331ed724e4e78af15e3bab5be54f6b926bf66b5d99bcc40dbc456d86342c9fa83a033c2d5", + "0x8ea84590a400cedba047c2661378921a42f5ca0421da58c1bcb37bc686a2aed98afab3fa5e6ba3a51029390ef3cdf4d4", + "0xb48551170fc479d69fffb00fae4fba301e92e37cae08f596db6f6489c3b7020edc074f9e8d7465b84e9dcef1b6b3aecc", + "0xa6f318b1eaab00836a330710e88bfe400395b3081485f6a212e3cba9463f6fe7864ba4f71e57a411ecdf2bcb4d189f96", + "0x848d5137a39999141a79f4bdf91150796ba36352d8525821bf3bd6e070b352792d79147341b8254dd60fa8c36e9e2618", + "0xa8526f8904b1eac4ae2a25534aa91e8031e9aac7b8f58d8f49897e920c36c0232f4a30aa6eed305deb0f7793c115b267", + "0xb8b6a727c44c37a8388383e959d195d1d0e51a657d4ba360633d219d43c5df645383e2406c25f1d418e72b862c3a6e9b", + "0x92e64adf65b42c978f36dd03ab22ba983bfbb61944efccdb45b337ceb486beda99818bf20d32a545503c4572bb0a4983", + "0x9653bb83df66260a0bd059cd4244ef7c661b089e403d26ba777d2090783ff31f963f5d3a9c125b1ad1a1d19134f3fc8d", + "0xa74e72355e71ae5eb36dc75191643500ca3e67f18833ee981010e7e7e60a68e1b01b05901eff05014b9ef29aa4829f45", + "0x8b2139a5da14524cf6acc593144db23db424b95b8c7041d8f6c7a14a6725dda1cd09c42bb3ae26a5a3650affaa742800", + "0xa60ddff4300ca44a7c7a00a1f98441ad1438e07c30275bc46551cee1b681926d2c825cc8f90399ee5f36bb9fbd07d3dd", + "0xa04e5e9958867a5acc15fdea0d88951cfebd37c657102f6ba1dcdaa5e46cf1c823ad0d98718e88e436f260b770599102", + "0x95e977abeb70d46fe8d7584204770f14c856a77680607304ce58077550152733758e7a8b98b11b378540542b1175fecd", + "0x8c9ec93ed35a25ce00d61609e92d567459a45e39922ccd1c64ab512e292787125bd4164c00af4cf89fd3cf9deddcd8bb", + "0x819819ad0338250d9c89aceda9e217df12ac54e940c77fb8420575caa3fa78930689d0377ba88f16d38179a807135dc6", + "0x8baafb379d4150ac382b14a64788d819146480d7a1dccd3deef6889686ded375900f5df069843ef14d754ad3d7540401", + "0xab827236996bb79b447714c6993af941c5ae66248df4d9a6f3650d44b853badb5c0cb67804210e07a7b9d66ca43092f6", + "0x927656c3eac8d2eb575e3daeb77f9605771170c325bee6aeade10c083d42bd8dcbf3bcc3d929ea437001c7cf9a95e2da", + "0xaf22b212d5ee44fd4197966b9690487c38a119cd6536cfb8c181f38a94610dd9e057f95774047a446504dd96dd11e326", + "0xa44bd94b9e01e3ba36340f2ac2201ecb477495d4f1fb6726a6b439302deabb5a35d237c6a6aeb7e3b0a65649f8656716", + "0xaf367aeeae3bba14fbdb05bcc1a521000dd9d37f5c34ae56fb306d3dfda201d0329a8b6e89d98e15825cb3c6bfdb1194", + "0xabcc4fbdea43e50ded9e2fb01464f4e87fb136e960141e8d39214f92794cfab5634f22cd40b18d8c0e501f2307aad23e", + "0x920786cbd674348b9853689915dfcab02cce2a4596d117962bce36aadddf4bdd143891e22f2c8015517039a64e8aede3", + "0x8cde63b9bd57cb3ef743f1f3e8250669eed739e5fbd68c500a3cc0c12f93862a69aebcdbc69dd8f476c2eb307f572a53", + "0xb967e65a5f1cd8d5d570f5e87e7e186fba51b9504f8e466392a76d8a971fb91fd9b7565bcc1647f50d7d15e48b93bc95", + "0x8d5a87b25fedf5edd57d870304bfd9081dc78c3e3e3b38b997260a92edac7feccdaf24feb51822d2edc223b70bb4ed5f", + "0xb6cd5d340a57f8ec73723c4f3ecd6601620dc8137a3e75a5d3c578bc79a9cae86b379950c644dee2ff99dad780d025c1", + "0xb6f0a8e754b7f52a85a2a2e6512cfd017f7fb0418d19bb318308951c4e242d3c65bbcb9748da9cbc91a738f9ca577332", + "0xa89dcf7d410bccec385400dd96b1cc6af89026a431d0f531aa992cbd7bc8bfd7c5f360bcb665bda1d72efa17bb982551", + "0x97788e7522427a46c4b6258d15623ef7a565712812fa80d001e1de8dc1791392702f3fa3cce5a8cd1c5755625a0ad10a", + "0xb5338fb5e137ff625b27c5148298f27ce8f493e2527c5d0facaa49f29cae34580d0d6c3c1074a2e46cd8db3f56004ea9", + "0x8962f006d7b1095dd0dd132ffe7e87e328510c95ad893cf3b2ab21c177c5cf2c27f47d8856f87e9762c547be009d25c0", + "0x87fee9ce9c26aa476e67e0791a809e0a06a8a98facf3faea730d438d3e516cdf75d645fa75c906e4e44ab9237a22c016", + "0xb75ab972e1a1214bab0b38cc3e973d44bb233acda5b4291f5e110b6fb78fdcab93dc63f01168debd898e165f615be1f7", + "0xb5a0fb52bca279d3853761a94b206acaf313df33ae6303d9b71edae90b66fc507adbc60fb11e758888736c81d5d80c0a", + "0x849b8f0005010e684701cd3a4e59e8c89e5fec59af6d2de5b6332cde03b865ea84f07f0b80ec3404380b0e148fbd2c24", + "0x96e2b0b6fe78408f9208f809f5c40398100b2dac202c8c5c33c2189560dea868270a598c419871a5a2b67783354f6014", + "0xb234b81f996142d0df2c719760bf996544820a03195a6dc0ff6a72543692f5a369bf63d1f0b477ef2fe7b3234e41f685", + "0xb85e39bcf40da1a12a535740176f4de749a93824079deb5fdaa004f3282fdefaf5275e3418c88c419bd42a3dd2ed2b3b", + "0xa27279304b89a18a4e2b443246f2368fb8b15f46a34533179b6bd2ef683f6e98e222b7a32880b39b8fac1afa90133803", + "0x8923c22cf15c9c1964213d725b337ece9ea854775a06f75f232c4859c7142a3942f418354e33066298aedfba3cb27e62", + "0xb109f714311fb9bc431ef57911e2cad6a3949455b9f23255cd7edea35be629e07f845fe53e2b12a32305ee2f4f264f27", + "0xb51e82ae5c7d48050e405897d0053e9ea4b2714d002e88f78c9a307cd50b9c6b3ee7cb86f86527be9d964b01895fab20", + "0x90db256931c7f98bcf3bffff4d496739185e7a20f329ee7bffd4e0850a37739948ec745285703967f4ca50ec370cf68b", + "0xa0485ac0445d88dafac56bfba2563b020cfc370f54c1606c89d12cfd8a4d1336d2ba50306e476155a6f5b0e0a1f2d092", + "0xa00754c3462e74bda928da855bbf90f9077db395e32f03cce9b2955546d900b72330d247b7d607b65e130f5b0d883de0", + "0x8547d56727c3ad8b5c8ce622ed9ad86fe8cd78e6e4848c9845914b5063b17330bd10b46d8d3f18f83ca09ecb28d1afb2", + "0x95b937b2a979bce0e159ac75c7d5d659be8599c92305e73e942aab414793364a3ec28c7c1c8491a5750ba84a29828d8d", + "0xb011e150f0294e45a0f4c69409999d0c2e602449dbd67ab95e8258466687cd733a0329083a31b03722f4e2580ddc95e9", + "0x924651a733ad5e5d9adadad3ea6a6babb8e455c8d5f2cb5bdc83fa422e7752592190ccedaa827b866861e73506a6968e", + "0xa4d5180122f8e31503ae027e54da50f72f5cfb910a6f7309bd882b5cd666f454672591f1f20e461e182a47d03b47052a", + "0xab19ae659c4f73ea3d21895269dbec583c7029955a36469124ebe295027010faab56c4a475973497f28e9a77c03b8fd0", + "0xae7ea1a803d0f439e91494f8f35fc1167dae23834c0c699ffe65d3da8b09f8df5a53195a99ca7b8558242279e69578fa", + "0xb9d63cf0e30f9800101b43b980bcd2f229758e74b21ad5354866b4e684791c08a184330dc316228a0d67fe0210f2bc4d", + "0x8c41629744391ddb96dcbbf9cd99b13d36e57d65962e0aeb92ebccf1c4cc769626feb3ec0363def08eceb102b3dd4ad6", + "0xb2848ff24faf9e667a8c19d050a93896e9e75b86595f7b762c7c74ccdfb9db126ae094961fee7f5d1192776c1ac1a524", + "0xaf013bc29206743ce934d5887b8d0fb3667c89bda465d2321835a3618513fba6a459dd7566268220ffce7e0c97e22b2c", + "0x8bb799e36db1132da8e8b028ea8487dd3266b4628c56dfae4ea275f3c47c78e3d7445ab8d0aaee4cbf42148b3a148175", + "0xae2b81fd47c038b5195a52ab8431f0d3cab4cf24c4237252d955aad2156adc16dda9d3270157e0bfe5a44022e5c051ef", + "0x8e0129213b1698d2ec6df132356805a8633ba79e672e586dfef664ffccca71834253ba14f296da962651fcba2c002622", + "0xa1ae30b500ae77cd9bbb803d737b4a5991cc780618ac22b5cc179efd8fe10afb8c135457f2e7b86ded485ea12eae70e5", + "0x8a39723077b7c0df6e3bf6548afa3910c214ee275951fbe5155a39473be98099626ea14d844630a6fa90292b9594665d", + "0xa628386c79b61aa7314b01d9814aeec20c2a66e3deda322a39957e7135c2e52b1da486d1b9cd61c87afb22c1d10f6462", + "0x97867f469b01249820aadd9a54e12d4fdadd4555f2d530450e1f8f6d2dae57360578e2c2c8ba41e3b5950df596537a98", + "0x97f192d0457c217affa5a24267dd16cb4c01de8fefde9df4884e1906d2f22e73382dcee6c7d910bf6430bb03f4a4f1e1", + "0x86d5b5739de8442dc74d0d8dc78e49210fe11bf8c6ff0f0faecbc47b64812d6b28c8afddf6d9c0212f1988451d6ccb1c", + "0x8ff3312ce9693cd4a9f4b8e75bd805f65b0790ee43fd9e075fe4cebc87185bdf161335049819f22530f54fed2779a5b9", + "0x8dc41d85548bee5d51941d55752a500bde3c5a8f3b362da4eec307a963968e26605048a111c9166d448b8dddf6f53892", + "0x996bdfd004b534151e309ac925fa5ee7801c9da4f6b4c43e156d1158b134535a2a3956e1255e0dd72ac2af6bddaebcaf", + "0xaead652704b788bf4983c8f725c644c327a6e9f6683215f5c826c09f82fd2e40631791f51d14e6aded91fdc018d45501", + "0x991ffab58a82b98ed8fc7b00c3faca153589fe09cebf6a137ad506387a1ca4dba475b0e4a1b9bdad829f1422facaec39", + "0x9652e6c4ae084221d6bad855ec0bc11b5f855c6efba67f644e0902ab790a98861cecc6ce047c68273c3aa7eeb2f4c7d9", + "0xb88b816507aaeea6dc92b861eabdc96988b74d7883f20a4b30ba249158acaff3c50d261742fc9ad2e9eba888a8d59065", + "0xacd028a51e16c07a10d2073b9d03070457ac5f1246365295a1359d015c460b92b4861125fabe6f114de8197045df408d", + "0x806d3cd9d02d41c49179fe7dac5b05dcfc9a205a283135d4f008d0771c58e6f963d7ad0f6798606edda718eb5c7ff3ed", + "0xb9b71f1657a6b206fc40159a941e127f252a7b324dea864ecd804f48c0ed86da9778a925fb65491204a92bc2a26fef32", + "0x80ed67bd0e74350c875abedc0e07fd42ce7cb926f0f3fb1949c6ac73f2300b5a14a5c6f6ff8aed99d5ea5029bb8e7ae6", + "0x9875f67a7a473714e4dd75ee0c763ddf88101532d9680724b3848fef69e218b04a96b90f88e0f4409aa40b9a21507ecc", + "0xb4a2bb1b421e5243e5e7576a0672dc19f9f70315a03f6411c19f76616ffbb70fc5dc0e57fd4ab85e24ea2261b7ce38ab", + "0x879723002ce43e6c75ba2246f51436efe3376242beff987d025c3c4476495af32d52a54fad5d9ec329a442b93bcff1ce", + "0xa4121efbefd9c3eb143619afa52a916f199c75024908047763b29466cdfc837c2fcc894aca63044c33c41c777e529b5b", + "0x895f637b497a9766714a3d9e3c275a1f0c9ddab105bf4c8b7e663f36cd79492022415bb4938c1a4849bda73106ace77c", + "0xb119acb8b161ce4384a924645a248a656a831af526cd337d97e08405415b9dd22060849c76b88a4785eb5e7214961759", + "0x802e712f4c0a17009c4be6c1e5ba2ca3b82adcb68793ec81f4489b7985babd8a3873d544de63d5e5de0cb4dc5048c030", + "0xab111051e4651b910c68ecfdc33f2d99e7bf4182df68cedbdbbcac219a543e04d93ecb2763fe32b40c095c7ca193c331", + "0x855c73ef6afc6bcaab4c1e6388519fd5cbb682f91995bebd558167715db454f38012291beccea8186a3fb7045c685b67", + "0xa29d02ec6d9baf84c19dfd0eb378307703bfafc0744b73335550f3cd1b647275e70215f02d1f4ab82a5df4d4e12dd938", + "0x91510a45b8a50cac982d2db8faf8318352418c3f1c59bc6bc95eab0089d5d3a3a215533c415380e50b7928b9d388ff89", + "0x8286e7a2751ca4e23ea7a15851ad96d2cadf5b47f39f43165dde40d38ddb33f63a07bc00600c22e41d68a66fd8a0fa51", + "0xa413d4e619b63799dd0f42ac57e99628d338b676d52aec2bb0d1bb39155ad9344b50cdfe1fe643ff041f1bc9e2cec833", + "0x85524e5bb43ae58784d7e0966a664717289e541c8fcaff651541718d79a718f040a70aa8daf735f6635dabfc85c00663", + "0x97f0d48a4028ff4266faf1c6997b6ad27404daa50ca4420c00b90f0b3e2d82ef8134d0a04108a74955e61e8dfeac082c", + "0x8df6145c6cc39034c2f7331d488b8a411931c8faa25d99c5432831292637fd983d4f6b1a6f55522b4a42a462d63c6845", + "0x98c2060f67a916991b391e67fcf23e5f305112807fe95bdddb8ce6c4084126557e4c5f003afb32e30bc6808b30d4b526", + "0x8964246b3c2b8f7312f0a99647c38ef41daf70d2b99b112412356e680185da6810ab8ee0855ad7409d334173bcc4438f", + "0xb56c2c416a7069c14bdb3f2e208c5a6ad5aac1cbe5b1faf99dc89c7141d0259d1c6250be9d9195500c4a41182ad2ec3d", + "0xb7864583a4cae3b1083dcdcff7f123d24a69920a57d6594d0b7219e31bf0e236682442b6499a1f6795cfeb4f5f236695", + "0xa064f94139bf1b70d476bde97099631b1284aa6b4d87f16bfc65c075e58b2f1b3c2d057605259f806e545674a1169881", + "0x80d1bc4acf14c0f487cd57c5d6157b7f38917e93cb660f1c25e474fcdcac3c3dfda50f6bcccfd6676bae25c4b6b5014e", + "0x8ad9a4976c4e3e282843518149fcf5d454240740f4b91466f6310b7216d23d70b9b47c42870293252f29f092f330967a", + "0x914197593d2d99d784c704cad7ecd3f0b9f55dce03fc928d13e1a1034566c4de754f1c2a5ade047b0956415fe40399ec", + "0x8d77f5e29c572ec3c0ca39cbae2072ba4102403265b3d8c347a00386da9c0b8688d6e3280c96037c300d57b3545f3773", + "0xabfdf79d935fd4f06a04938d6580a8cbf9735f0d498f49677f26e73d3b34b7075d525afcb4f14ef1632cb375bef7dd55", + "0xa97a8c446e3edc86efac7bda5e2e5d0158c909552a3bf86151df20ece63b8d18b608f477286fb1c7f05605ab7e6a7c2c", + "0x8618d946c7fd62486551c35486fa466bdfcdc63c941e4cff5a01fbbe566b7ea9dc763cbe73e2acae063060b619a212a9", + "0x8d03ee468070936004b06acf64b868963f721f37faa09887f8a82c155ad5c5732572a6855b531db58af03b1afe034a18", + "0x8d3247f75966ea63935ef6049f7c889c1651374adb446f49499fc9191dbcde7ea33cbc1f1e2d3d1756b6e69870404643", + "0xafc853c3a3facb4ba0267512b8242327cd88007cef3bf549184ee891b5ddc8c27267bae7700758ad5bc32753ebf55dae", + "0x80df863eaea289de5a2101f2288046fdbfaa64f2cf1d6419a0e0eb8c93e3880d3a3fdf4940f7524ea1514eef77fb514e", + "0x8434b5888c2b51d12d57da6fb7392fff29393c2e3bfee8e3f9d395e23ddc016f10ebe3e3182d9584fddbd93a6effcefc", + "0xb78cbb4c9e80e3808c8f006dc3148a59a9cace55bcbb20dd27597557f931e5df7eb3efd18d880fe63466636701a8925e", + "0xacb140e44098414ae513b6ef38480e4f6180c6d5f9d1ca40ae7fbadb8b046829f79c97fe2cc663cbccd5ccf3994180c6", + "0x936cb8dc959e1fc574f6bb31f28b756499532ebb79b2c97ff58b720d1cd50dc24b1c17d3beb853ba76cb8334106ce807", + "0xadda2116d9fab2c214ec10c0b75f7f1d75e0dd01e9c3e295a0a126af0ea2c66373d977f0aefdda2e569c0a25f4921d0e", + "0x89a5cefb80c92dcad7653b1545f11701d6312aef392986835d048f39d5bc062cabc8a9501c5439c2b922efc5f04954d0", + "0xb9acb52747ce7f759b9cdc781f54938968c7eeacb27c1a080474e59394a55ae1d5734caf22d80289d3392aab76441e89", + "0x8564f72ce60f15a4225f1a223d757ebd19300e341fd9c1fe5a8ece8776c69c601938fa2d5c21b0935bd2bb593293272b", + "0xa5567d7b277c4ebf80e09c7e200c20d6cb27acbaa118c66ef71cbccb33ee3ddce0e0f57b77277ae1db9c66ed6e2d8f30", + "0xb82e9c2d8df1cdd3b2417bf316d53e9f3cb58473c4cb5383f521ef53e0af961ef916e4f6557a6d8b4655ec01415231cd", + "0xaa816dfd2814c8a25bd2cbaf66303ee49784df471bac4b3188074ea30816f00f425234454d40d8ad8035aa925d74da36", + "0x9919f384df20faaa2d226b521cab207dd2b62420d25ebbda28c9b2ca76a2a52203b2ad7844c1a25f5c75f005c5a83149", + "0xb24a6aa35c2d0f87e36598b36224c64427cd69642b6f9c1bd478a62c70f8ee69f85028648f6603b4f04fb21355f2afb1", + "0x892e044bdb1276b455eac2204be105e1821f987c2570494b1f32aa09506caba7ed343cd09b1bc126fed5e0fda3d0eaad", + "0xaf0e01a3ad954dc048de18bc46bb1c4971db2467e839698e4dd05cd1adcb9261013fe9fd0cafb946c0b586f6aad86d4e", + "0xac152f0a9ace425378daf02510eb7923ff1ed2c0f8d1deb918e4efb63655de1ba58c96438e9aa23abdf2431dc771370d", + "0xad8c7419c097709347e2394195924e09617b47ac5c7a84aeb9deab8975f22155de0f70cf20d8a976551b14e3a2683a2b", + "0x808f14f67ae801536fb70a5898ab86e50ad35340cffd0648daed2f2c4564c9ad538034b2a179a6a8bfa27e9d93b4cbe0", + "0x80a74ab7ce4769db93cfa695a166db95f0a9c47885ff826ad5d93310f36d6b18b5351c67c858b9837b925e85a1995b63", + "0x95b88c3cdd64401c345828f4e4754b1a88b4875a14c08a668b90acd499b3b858842669ecd73a46c5d9f1de32ec1a0120", + "0x8ddbd770b7b18a5917eb43926fa05004e819f1d1ead05b915269e4a86b53e0633a90559007e59f6705a3769e2126ac56", + "0xab6db5fc220754f19948bef98844e6e38dd623565d1695e1198040c228ac4fd863c1f168cac1d036bbfb718d9d8dd036", + "0x97bef628e977c069e60c395a17740e0e1bc1828f5607ae7f30ce5a0c95f02b53af2ad062700a75212e462aa22c3c5465", + "0xb68d465e04fd17ca98501e61eccb0ce30401855e98046e0c1debba71c2153d6a7a704aa36a6f12454696e78e87181cdc", + "0xa79cfdd048f4181e005bd0fbac0a8424495474956b58ce858d2b700fb0f931c406282bd33bfa25c8991bc528d12a69c1", + "0x843f55fa0a6a0969daf2b48080738f30b269b2e7ec123a799e5b203c0b3b4b956dc95d095bc6550b0013918cdff8a225", + "0xb683cdf2823036827e5b454bfe04af9bec1850d25a7a7a44aee7696b6ff0468b7ed6885a41dde2b8f3ecc4aec880c3d2", + "0x8b500796e82acdc89778e0c0f230f744fb05f762000fee877bcf57e8fb703d212dbc2374887bdc2e7b7a273d83a85798", + "0xac35a8ee87bafecb1a87f15abc7ccf4109aab4ac91d357821e417f9b1474d196c38cc41cd13667f68d1ffab5e79a6e92", + "0xb6e517739390cfed5b395d33b14bce7cd7aaece57fe79a7eb3cbf150dc10765c3ea9fef7976a21a2243687e6eea38ef6", + "0xb53901eeee26692273365b789f2a60afc9b5f0df229c6d21b07016cf4c0e7985beec748aeca52262f68084393ab038e1", + "0xac4804f33d8ba2b4854ca3537bd8bf2dda72d4e94ff7ecaaf9bd3b7f098343d74d765471ef80072ae34f860b052cbfb1", + "0x8c6a30a93f1dde18039bbdd1ef294552bf79856e20bce863e4b8dd72d906be3ff22468ff3610e06b5a7d1745dde7ead9", + "0x88f0607fa3b7cefe20a02115572b16fc3222be86bb19e592c86c48afbe7e0dd523492b0c29a3bceb9a20f5538bc3134c", + "0xa660b801bbddad725975ddf9a8f606f76ecef831f954be224d6178c368e1c72d346f00c4a4c95c289b62d36f2af323cf", + "0xa75b9a6aea9542b698938dcd6cc2f6fe0c43e29f64b2f54aeb05d35fac73d41aa7fd750af4fa9333644aab8db90775b9", + "0x83e1b7129d963d1cd076c3baa5fe422148e939273db173e4d59d1858a7d841eacac7fe817d15ab8f8a493bf46c2045e6", + "0x9060a2e9c24de11f9c70e039b5ffe9e6d32f1ae39f3dda263610df2265d917679e689898e4a8bd84ad34613dca5e3761", + "0xb42fc8b863a2af15e04d1fe6693c09b46007c0b8298973fb4762b45b4590ad7fe0aa758918b2fe5ed1ed0359754fd955", + "0x83e6de7860fb256ecf7b47506a5e557d0fb0aefe57fb513c7dee2bd9604712d08ca26adca7ba9a54b712372a7c585a26", + "0x90586e9cbbf71475ecd3e7b5753b286804dcce61e165502a82b960099e79272de8b7494b8877b54ae838eb5d0f71af2f", + "0xb2e4b0d21208f73b7b75e08df80cde20c4578e117d37092a490af82354e2afd3a7dbab46fa2d12fcb731cdaece69c2ba", + "0xa010961239bb8809fc7fb4aa08fa30d33a130f9f417ee9ea60f587dcc5ef4e1b7abcdcbf8e848ecdcb7972ef6af46e78", + "0x8f511fd58d1e3403a5eefdc0a4ba6b8af848c7efddbf9575ee84449facde05ae9a24aa41a5725416467f6fbd11369c52", + "0xb24ebbd2d4482eb618cea1ac4fbfd9ed8c46c0988a27259300a7ce5ce1bb256aeca0357828cbbc4cf0dfafbf586040e1", + "0xb3ea29e9cca55250e9b7b9bd854edae40f0f0cc65fe478cd468795d1288cc20d7b34ced33bd1356f1f54a4291faa877d", + "0x8a8b20f222d9e65bbde33638033972e7d44c6a310b92a9d9c5273b324c4ad1a94f2a10cbce8300c34dbd9beb618c877d", + "0xb2436a9a647dc3f12c550e4ddc5b010e6f9cb3f3504742d377384b625fc38f5b71710a49fb73ffaf95b9856047c98201", + "0xa13f8b77c70621e421be94c7412454adc1937b9e09845c2853ef72cdbe500e5c1bf08e3c8b8d6b8eff4bce5b8dec9213", + "0xb25de8780c80d779e6c2e3c4e839a5a107d55b9cccc3ad7c575f9fe37ef44b35db4c1b58f6114a5f2f9ca11e1eb9c5fa", + "0x96ba6ad4358c7a645e5edb07d23836cbd35c47d9a66937d09486570e68da3c8f72a578bd2e14188d3acc17e563a652d7", + "0xa7f55989814051fda73f83b5f1a3d5385cd31dc34baf94b37c208b3eaca008ff696fd7f41e2ecffc2dd586de905bf613", + "0x882d0c7c81e58eb9560349f35c35e4498dcde7af7be8d7974b79d262304c26ab67ffa5ed287bb193d5f0ab46b4096015", + "0xa607158f0c1fd0377a8ee5e9715ac230abf97406c19b233d22f5911ebe716967cc10425546dc44e40c38bd6c2b4bca2e", + "0x87e8cde50e5d852d3f073a43d652f7186bac7354612517cfaecd4a1b942f06fef6f14546279c0dc0262e2997b835b2a4", + "0xa1c93acc6db9d5ee426fb4a0b846bb7a7b8d5915bec777a9fe6907246b0beafb8938941c8c79ed6082155f75dbc1e332", + "0xb1e4f61457b86f76cd93eafd7536f72baf239ce5a62bd5a8085a34e90576b1e118e25002d2de49b01d6e9a245ee7d3a2", + "0xa0435fe9a4bd1031ec5973a103ec9396b2ce9fd982f6d9ed780fa80ac06a6e47a0a6eb2daf52df1dc9292db622ee9fa3", + "0xb66d8e8a1717e4bfa42083b6ef4490e090a73168b2912f2111743e089027be0a4945a229ecf5d0b5eec11b23f0e11303", + "0x8eb764f26904eea4f4169be6e75beaa6a39e4eb524625a15a78befe3d8e3cc82692d9b135590c20ed460d6e4ba630ef7", + "0xb7e4aea6bb09829e53fe83e53f49a7a331a6d7bf76e0073d758577e6d6fbe63dab642b23657355cad48896ad8715119c", + "0x8f94207982373a99ffa282673f192aa98d0c4461fb77c31dc4549628bd9687a249f1b3c66b1840929341e42516c5c64a", + "0xa9c673cb247b13e17fa5e616f0399b7f5c7ad043e143e44ae68855a840870ab3d2aad737ebcf74c2cc9688d17ef3a794", + "0xb02635104dd28c02068985256975c0af783899eb996e37d021d9a35238deeea9e836760db21869be7b6c82aa687ded29", + "0xb33bc0966389710812b5f6698afa3e9c84839a1b85492ba11e6ded26695260abf66be6fb355d12d3a8524966f0f89e0f", + "0xa79c0dd09506951c33da3cbc23843fd02d641fc24c640a205e6e8150240372847312b9381fb03c5d301fe4dbee8d0da2", + "0xb74de6f3a2c502b5b658ebe8a9b7edd78afd036f5a2736aa06502863b6865d131b9e3542e72a86fa2e1d2db4927661ed", + "0x99e365def1452ff9fb4b9eccd36ff4154d128469ba5bd73e83ae457ab53977cf6fc04a5d05bdcde357ab539e34bd9fe0", + "0xb4f2bfb95abb47c67870aa6ca38ac8f3ae1b1a2bed064b1be7ff90865ea12e4930fcf66429c7ecd1183fae4a01539386", + "0xae4bde87f36b912e92398bf72e11d5389e93b2de1b277d7ed4b6fb5a9ab9f71a959ec3bcb734c11079440fe42b86fafd", + "0xb826459e568efdeeb66688482b67ef5020787275123fd3192f979b6175e3b0ed59e17cb734a0a052bf13f0afc7bd237c", + "0xa99dd735f4a7c85cb23dcc7f4835f9ab32026886909aaa95876b98029c37dc4d621726c872d3a9e50403443c958f4029", + "0x99083545034768010988bf8a9f34486c2cd9da27a1d10db3ab86eb69a1dd9c8ee723e7da4ef2aced63c1dbd53ccc52cb", + "0x8ac3209349f0142546c714ef7e9d1b094aab5469b8f080c0a37cb0362da5349e108760f272fbba770aa468e48d9a34c4", + "0xaf5f48ed74b21e3f2c1430192adb4b804dc873cd7e8f07130c556c30e7b78df0ef5a14b205368848fa9185e5a68dee0d", + "0xb8b741b65d68df89443523ba74203226f1e0d13bab073d183662d124e83e76cd318b2bfff09879c04d81b577ac895638", + "0x914abe4282d11176d4f2f08c6f15e6c2d0cde1ab4de00bbe888015c205f51929d97296a0a8d3ca5641f085a29ea89505", + "0x83ec306b2a9a6780efafe799df90b1aebdbff7d47921a136ea8a5648b9708a97231245a1082fea38e47ecafbbe000528", + "0x95d6b58d70b388dfcee4eda0c9805362ccfb60a87603add565b175b2c14ed92999dfdb0d3724ee3e5d30535f282641e9", + "0x97eeb4de607c8306e1d4e494f0d5db126d53fd04983ab5674ec5996b971899e734fa4011f2c889da21154ea1e76dbd2f", + "0x84ff21977fbd873ea06bec444d4ec9ff0e3902edc29dfa25f3bed269b3709e3116e99dc06cc3e77f53c53b736bf8fc29", + "0x8ecf483874a040a4a1c293af145094fedf203a5eb37c3e165857e108cce3e1210e0bfc0f26f4ae5e2194024929ba034d", + "0x97d9b92b2ef34609d69402167f81bce225ed3a95718a3b403f702b93e96a121a8f7f072d0ff47e8b25164e204d1576bf", + "0xab87c39cca1803b4e84b32e40ff30289e3cbbcfbe16a70f9e025643824752359be1f10c3e5398df402b6fec64d5a3537", + "0xaf84ca57e6944332884b5c84750afe0d5950015e127acec161853d55d48fd864c7da8d59cc5aba4ceceac650b813fcc0", + "0xb1d23d98edbe7089ce0a8432e0eb3b427c350fb4bb39eb2aca3c2bef68c432078cb9b4b2c4966255e00e734fa616638b", + "0x8e2b5252e0ea96d40835ebfb5693af49946509975682d68651396d6bb1463f09e75fd0afa04ccea49893b5b9c3e77e40", + "0x8db25e762f1d4a89a9a1cbc61c01698e775906bc88a921b2905735457a35df9ab84bae12e1b1b8dafadd50212f1acda1", + "0xb5f7cd163a801770a4034e2b837e00191b0ac63a2b91032ae9a99ec182d748798df48a14644935fabdbac9a43a26749a", + "0x998e7232e5906843d6272d4e04f3f00ca41a57e6dcc393c68b5b5899e6d3f23001913a24383ed00955d5ec823dbd3844", + "0xab2110a5174ae55ebb0a788f753597bd060ee8d6beafc5f7ce25046ea036dba939d67104bba91103d7838b50e36703d1", + "0xa211972a4f6a0303bec6c86f5c23c0d25ab4df0ba25876cbaad66ae010b5a00aa0c5daded85e4326261a17a563508a25", + "0xa49f53496a4041a01e07f2c2cf1e84e2ee726917bb103fd267451b9b7bb1331c0afde85a79a55409bfde27328b2a4745", + "0x934e915c67c7fc47adeabdde49f63f04644fe234672003be2aa0a2454dc8d9288f94293478936a450f2e3f249d395b5b", + "0xb6e69e9d6808ff7f60a01b7aea6781495d7a20f5b547852d3f0af727a7434209d3015a9dd04cbe3e272918e32e345508", + "0xb348d3462092b5c6fead7e515e09611438db8d69650876dd3b56226e303252bbeb9e9f3b888fb911445b0c87132a1d0e", + "0x8d6510334a905efe5a32001e167f1ba06f9bc4af7ffbf11b7f7bf3c0076b5cca373d8c47e98c1ba8755bb22632bfe0e7", + "0xa2d5200f20985dcd473d119ee97e1c0fafafa0f191185bfed9cac429cef8198d17665dac4f70342eea66e6e4a7370d58", + "0x8dd7eb6b1841b3f33425a158d33a172b79b2dc8a01378e4174e67a1a4c8f4b887f02c7c3a8f354ed9eac718155bcdf37", + "0xb16ca19388642f71afcd9f7007b490d82f83210ac1a989da9d4bf4c419de07af8c048cd301ec7e01b9d06abda7c169d5", + "0x93cb2d847d1a88de8c1c9d5b3c83efd0b7afb3682942bd2c8ab5ef35b33dc31a097a3e181daab8630d4e840b677216dc", + "0xa8b648c769e77a7b41c0c689fe2fba9bc585067e004bcb1732cb7b1618e97b317781c36c23a00680fc780b58c301a789", + "0x918c321100d57712866bdae84edf7e42df30a32853af257e0cb4da028842a43b49e775f3cecb85cd817269c728de7319", + "0xa7b0f6ce42e00c519e69b2c78fd9b75a2e7103e5892d3c1afd70c9b5b9e706180a4bf73dbb2d3eed52bfd521103ec5b3", + "0x90041994af3322b010891356afd8115340bd7fd7ba328716fbc4fe458236c8cad8c7564ae473d6091ec3a54bdab524c0", + "0xacb1ac83809573846231f9be2dc5f3e986cc36dd9574a620b1cced45bad0b11ea957ce8c6cbf964a0af916781c574f05", + "0xac54677dc002698fc4d454c7beb862ad085d0514f92576f3485a44c0cb47afb9db2c085058918a3508f9b3de0137d97c", + "0x8dea56e1bfa150e442f8484b2952b116781d08cfa3072d08657cc09b0217276efc4ab6f5fd726bfd826f6976ced8da29", + "0xa2b09e25baf01d4364b5205fa0c4dea84ef8fe03709113b034f88a0f0a502a81bf92c1d4641e2ac9f3a6f4203d3645ee", + "0xb95fe37aa351b4292691a9c2e547224c37ec2751a31ecce59810cb2ae0993da6fbe5efe0ab82f164462fa3764b6eb20f", + "0xa3498947e91a3a540e86940be664fc82f1e83ff41a0d95eb84b925e820602a41b7393c8b458bd4ebbe574a754586787a", + "0xaa2516d3620c832e5728fefdb1af0be30c871cbad4b166a7a4565af676e73bddc2f2f51acc603b3a022056daad2b330e", + "0xa9251b56467fb55f64c70729e2ec77a59d7eac79cc0b4b25ee405ac02aea46bf1cbc858bc773934a6d9bea57cb528185", + "0xae8c0a4ca7ba6bdca8764bac98df0581f00358db904e57867e6ffdf15542e55f7bad2dedac152ef88038b466ed901934", + "0xb0881e27e52cc6a57c4f3f278dffc7f63a9174b68bc867c16d8a151d9cc4d0aeb703d1074d1927faa9ffb43e10912c9a", + "0xb67138465d6654ded486d18e682f11a238d6a65d90f23d6b13eb6a1b7471efbac9ada6345dfb13e5432196d2a256829a", + "0x944c69a6f1126edd38f6eef60b8a5bd17147ab511e44e8e0a442e87244d8f35236ee0b8d3dac0631f8598f16486a5f74", + "0x995679dbe03dec775da26708cb9200dabcad983825f1ba601eb9395f9da350ca71e8af61dbff4c668fd0eebac7e4e356", + "0x89de362f02dc14de6995d43cdea3c854a0986c605ba5eb5dacf24e3a85983229bc99a2fcf50aba3df59f0fb20daffe29", + "0x84607f0e2d078df22d0866285614f5d78cf7697c94a7d1b5e02b770101ceecbfd53806b377b124a7320d9fed65000b97", + "0x93e3faab60050dac76ab44a29bcd521813e76ec8e4ae22712d77bb489bb49f98f9087acfd6a77016a09a42ddedab2d73", + "0xb7d64a7a35f21747b8e6a874be31ba770c0d13cbd41448411994e8cebb59591295a26bacbf74ee91e248a5b111aacca0", + "0x8dcad429a2b0d66b9eb8c1c3924d7a72979727db6a535526a3518bed2a9532d12aad1c5a778824ca4cb98e3e513f85f8", + "0x980882895faa347bd2fd1dda7b8ee7ed49e69843afe646f677b371eecc7a10e0f4e40bb55f28995a40080df471876816", + "0x89e8e7fb51df79971e2f7bf65783614abbb0d7f3f1b4a15d3f0d160deafa7ed1c446d9a5ae1a77160d4dd94ceed8af13", + "0x93fda8d350392e9c4d4ffe6534f7e7be53f32483d9319093e8436fbb8166a3c01085dc858373e65c7f4d014e0dc2bab7", + "0x897521a87b7ebf7152de5260c0875e3c7df1c53e734c672569219ee6f9bd196c5ecef159b6a1d3b7cd95e91b9b8803ff", + "0xb59affa408a0f7bd7930fa3b88750fd043ce672c10a3adeba95a12f23f0dda1793f761a86f7409ce1e6fd3b3b7195381", + "0xb4422ccc12f4fe99c530cda610053af9ffe635b633d52492fd81271d1f6f91b87171d572d5bd0e46ff63e221fb2fc4a5", + "0xa4542cdf3346ee0867c08d630c2aefc57442f1c05c0eba52d223bfdca5e9d0bb80775cff6ce2e28aa2730231fd7b1bb1", + "0xa7d297bb09118b914d286e5d1e87bdf13f7d174b988e38fb5427902e8e8c674072f36b19055a1070abcf357f8668f35b", + "0x9213b0ae24b7cb43ae95e25c09fead8bdbac55141694137d67eb5eab5e90a348a13d4d4d2cbc6436fc4f4f9f7334ced2", + "0x8aed71a0d116d832a372b42a0bb92a1980f3edf8189bdbaed7cde89fc0418b3ab21a04f5c6e1d3b8edf73f1f62bd6b15", + "0xa6c47d77d714c285c84c6b9458cbec5e3b191c0502dffd10ce049cf1ea27ddf868ef0cff13a2377289fa6c932b8e4f28", + "0x92f45622ec02483f2c1e07075a6695416d3768c8984856f284f40734346d56cb5b3322f20c2c9f0ef8e58ddc294a309a", + "0xaf6450d02b79ac9fc79f35655b58fd3619cd5d38c5317564b453f5f2d79d7a030bf767e399fe01b658a72fbd2cac2356", + "0xa3c01fed5240eb8a61ffa8ff4a120dbcebb53b8e19845949c77fb4f9b2c3dd52c7001df6219ad2f76c785a4ee0f64a2a", + "0xaf3136bfe8f774187bdf87555a1ac505322a956229a285d28bab1c88d4f4d12245af8dff35914a62e90e49f3dce6acb0", + "0xb20e21d28444fc96737958cd951858fda324b924b4d3d08932540fd4b87150f053db6985b96903906ce83dde0578cbb2", + "0xb7978101071268d1f485134b4dfd1e35f89b82c7d99ae91f58b6745f5e0273b7e06f3b23009033ecc3e41b2e9e85219b", + "0x9104b7d75245b784187175912cc0ad869e12f1983b98e052710fb33663224362bffd69ceed43e7d4ad7f998c0a699eb7", + "0xa7624cd71b92699ce3fde0e747976ee04ee820032ac45dd27d769edf3b3379a4b8db358e50c9d057c63b5a9b13d76bcd", + "0x9354a76f294005de8c59db10e638ae6e8c6d6b86a699d8da93143da8478d36116211c788d8285d8e01ea6647dfcaa1aa", + "0xb85935c04cae14af9848db5339ab6420122c041075ec1549314e3c9c5a610d9b794ea3617c50ca7af6b4aec8b06bc7dd", + "0xad6835a62311c84b30ce90e86c91c0f31c4a44bf0a1db65bf331b7cf530cca0488efaac009ab9ed14c1d487da9e88feb", + "0x80339f0245cc37a42bd14cd58d2a8d50c554364d3a8485d0520ea6d2c83db3597bf51a858b10c838bfc8b6bc35619638", + "0xb370420ac1a011f6d8f930511b788708ccf2fe23ca7b775b65faa5f5a15c112a4667ed6496ae452baf2204e9ce0dbf09", + "0x8ceab3dadca807a1c8de58ac5788313419c37bc89603692c7a4d96e2311b7fe9e813cc691a7e25a242828cdf98f8bbcd", + "0xac1526ebc6bd4ac92ee1b239f915e494d0279fbd065e4cab1f1b8a1663f67daa89560f6c99bbc3e63fa845520316d2e6", + "0x8240ab0bc36a29d43ec3059c7e6355ff39567e135f93b243145d3ada97fd1c970743819e0d58bd5171967daec144e7a1", + "0xa99743192a6f1967511b2d3038cc73edacb7e85f84b2926d8880d932d2fa12f5215592311a7548494b68a87ec70c93eb", + "0x8ffffc31c235997e59ab33c2f79f468399eb52b776fd7968f37a73e41949111957434f2c0a27645ab34c741eb627cd1f", + "0x8949d955309415d6d2cf6ee682ccd0427565142c1bfe43b17c38de05cd7185c48549a35b67665a0380f51aef10b62a8e", + "0x9614f727a9dac8ecd22b5b81b6e14d34f516db23a1a7d81771ddaa11f516ed04d4e78b78fda5dc9c276a55372f44c4d4", + "0xaa85d3ef157407bd8aa74032f66bc375fddaff90c612470b5ff5d93659f8c3523b2d1b6937b3cc4201c2aa339621180e", + "0x86f8fe8bf4c262dc6a04620a848e3844f5e39a2e1700c960f20ee66d4a559a90141ef4e5091d0f32acb1e915af1e0472", + "0xb3af2eb785b00588371beb3b49536b7919a3f2175d4817de5dcbf7fcc20c512852ef0f313327fd0589b10173f77b92e0", + "0x8388703c512eea59190351f3bd2cce83ff8bcb3c5aefc114cccf9e9b3f78200d8034c3ebe60448aaf6c912f0ff8f0cc4", + "0x95d0dbbbf08ec1ed3975fe7dd542be0a05156a2b3db5092825d918a849411ee536ed958201f74a5513e9743674d6658d", + "0x8d1a48802f1a2db247e633ddf61d3ef7a2c062c48dda59bf858916e04f56651a7d51e367d6535964ebf3ae6d2b21b421", + "0x971436871bfe868f25247145a55802945409b3150008535b372c949760d7949dd2fdb40d9b96ae7473bc8f6e9b83ecdb", + "0x8ca431728ac0f156763090828a7b6d860bf591e5b9dd3bb3b7f3ba0ca74191f9710ee55efd32db7d18eab5b479cee8a4", + "0x81e28f1a506e84c2b9aba1df720cb50e0b597b2c22f98acc34e710c934cc6f97dcaf33d589e845c2c1f6d8716d05ccac", + "0x8f43b11d3f00c41d16c9bc9bc0c44227c056bd77de4f1ca9a799418c5601e744f99066bef47da2d9088ae88eb259327c", + "0x8d330aa52744c08ef98cc5599eec8b9b4dd18aa01b803f1d1ca0e29b74f1aa2886ed0224390fc377af25852851fbee03", + "0xa06f5b203b67134c685039ec2bdbcc787353e2575ce73a415db24a517c0c31b59d1de89f12b97cbef0219fb6a1e90a20", + "0x9269a5f49bbb8fec1a387b5d105df88a027de615d5ca6afae20fe89b11746f8d23880db78dac238c955fc8bb3de18046", + "0xaf5074b3bc0656421c314547b45b5abd3045ca1b17f5e34ba39d8c1f7928a55d4ca5ea9c2ab59a55909b25255233e04e", + "0x8e7ee5d733c8e08f3fb7d85f0628de3de6835121672c65374905dc6d19e02fa2df14c13d5e9835dacd609a4df09abd26", + "0xa9b9aaf83d31e879dfb8e73a0708801b4dbdb5d7c8654b27d2c0f5797ebcacc8d00a82143e2060f0917c9d41f1a03de6", + "0x904872aa1c093cb00e1c8e369a3bdae6931c5b1ed705dd3bffba243dc4f42df3e7d7cf70303d513b34d2245743d765cf", + "0x8a4d6b3b1d6afe67383c66693f70b397e510be28e3d97dbc8ec543d699b6cbb0e72eb90a7f65e83cf9f7ef50fb18b128", + "0xa914de13916e6a0dc0e0fefecb3a443cca80d83276513b70c22c6e566a2d41acbd33a0e2836ee09abeffd3a4894e437e", + "0xb9c408f5f05934b0aefab301ba22f8254c5ebbf5405b6aa788f76e4b328c150b395f441e3566015a0deb3eca89afe9ff", + "0x8d32aa2c81b2a8b89f347c2e0b6567b2117ddbb778fda8a3f19004b7f5aa9dd814b9b3ad35f9223715d2447b2d12f159", + "0x8230e8b9c84cada1bf14ea6aa9ecdadd978d893cf5962fee6c7167ed21239210ea491987f2c8f2e8cfea8c140704ca28", + "0xa5d7b6285fea51c6f21d0976a7c3a97baa3d733a201bfaac0994db6c65611d91c5fc0ebc2a7724ee02b371e575573649", + "0xa54f00a9530f6930069f5e3a8b8b1d52ee1def0aad1763e3c609ec07f25410969b43d5943a94c235ed5eb207b33a402e", + "0xa8dc6e96399b81397734c61c3a8154e55a670fa25fa5854b3c66734cbb4ec0d8f6ba650ee3c71da3773ffc9e37abf8bd", + "0x8841fbfae1af4d400d49f74495f864804f043416c09c64705251d021b3ab7881f134a00b0241e61010617d04979d747d", + "0x95acea7ff4861cc969c1d8cc8775c5eae014ad6e2e0e2d0a911dd916c34ae69f53eef779cc24ff1eac18c2b478d3ba2b", + "0xa5dce74abcfb8c68031b47364bd9baf71a91db01e45514ab6216f5eb582ef8fe9b06aaa02f17be8b93392d9b19ab9c06", + "0x89e111169e4ae2f4016c07c574a3bdacd8d2f359561fbbdaa3474de9bc24ef8936784dfe6fe0e29a13cac85a3e622b61", + "0xa4c511af6bdf3892939aab651828259e4ef6ebecfdd503ecc14e61001575b313a89e209cb55a77ec19a64d29ada066ef", + "0x923c62156fbf3a44926ffb5dc71f7cef602dbe941a98c61f019a27a18a50c16b6135b6099fe04a2e1dc88a6cad989fb7", + "0xafb9191c541b61afa0ef14652e563cc5a557842ce2afea13e21507dde0ebbe6da5233af949c998c00865c79bb3d45ec8", + "0x8a1f0ad65cb2b225931f41dc53547d756111ecbf5bc57c5ee2cc1ffd61b126d0389d311ffe26cf06eaead95af09c5ca3", + "0x9040b20b5ac2e1a9d30abf7a4eea1ec2db8f3077cb2cfc8736b37222d8d3937f5d9f421167086dc5551e9f0bd2522d07", + "0xb6d888b8c6bd448dccaf99c3f690d47f802e134709ce102fb6f6fc68156943c0762be6f386338163e01eed2d1dd5f734", + "0xb94f0e27bbcda793e4a272603b3dcc739d3bf3207798df7319f8dc9d37cbd850e3724bdd30498c929debad971950223c", + "0x9769827767be9d7bacba1b687289e0794c6fe630d33c9b607da1f6a65e3f34cb8bd65327d9287c8c5f3c8b5f6d3d133e", + "0xaaac72c993aa2356c9a6a030950441de42b2d746bace29865382f0ef54835bc96958b2f00237d805ee6a69ca82117c1b", + "0xa2b1f027d80c1b0e79bfc7dd252e095b436fba23a97a1b2b16cdd39fd39a49e06a1ca9a1345c4dbb3d601ffa99f42bdc", + "0xb3fa0ad1478ca571e8aa230921f95d81aed7eca00275a51b33aadabd5cb9c530030691d1242a6ff24e2d4cfd72a47203", + "0xa43ed4368e78daad51b9bf1a685b1e1bfe05bed7340d4a00df718133f686690c99198b60031513328fc353c6825a5f2f", + "0x965e145711ecf998b01a18843cbb8db6b91ff46f668229281d4ca52236c4d40804ebc54276e9c168d2a2bfc299bcf397", + "0xae18e6efc6f54c1d9230210ac859c2f19180f31d2e37a94da2983a4264dbb58ad328ab3cbc6884ce4637c8c2390f7fc1", + "0x83a9200486d4d85f5671643b6daf3d0290b2e41520fb7ea7030e7e342d7789023da6a293a3984308b27eb55f879ad99d", + "0xb925fb6ca83479355a44abbcdf182bfac8a3c7cce6cfc7962be277ce34460eb837c561257569be3cb28023208dea80dd", + "0x9583dd991b62ae4bd5f379ccd3cec72cfae1c08137ddfbacc659a9641e7d5a82083de60005f74fc807bd2acd218d0789", + "0xae73bc32e9ff5926e1e06c07a3963080881b976c9875777f8e4cf96af91bf41bdbed4bd77e91253b8ec3c15b4a6d3977", + "0xb2a3ea90aa398717ba7d8c46743e4c487b63c5abb140555d8d20e5115df2f70d3c84a2cb9a5e0536b2d93d24f271b38d", + "0x91d119d3bf1d34cd839eb69c6de998b78482ab66bc93fa97e31fb9592f36cdfcd673f52366f8c8e8877e313b92d4a2ad", + "0xa1907e20120902cf68912cc3046f8806cabbd7673e80218814cb088e080dd93b5dccba395b13e0025f5755c183276c3a", + "0xb2e2011df72504065ec4c12cbc2137b95cfcd1355509671feb7b00dbf7f8d500476a49754cb7fb9219cb5cba7c8afe01", + "0xa48589fb7a74a3dfd782cb3503e6294a81dbb6adb412887569f9408e9079371edbd9822388e0b7ec8d3297ba270f53ef", + "0xa203909bfe196ac65ed3e6800d577b6ca5c8fe1d40f7f925a43852951e38883f2ffd250a9e16fab3ed3dc1249650247b", + "0x997ac293722a8b98f7e819f8e6c2d4c5bd1103b82d489d8b8aabeb905e95450b9b75bd61442cf68cc957212ec1c55617", + "0x9895a3de62395c33509b153b7820bd94fd2b011f0cac135fcf916482f1eda272ecc79f83a61837e99c3a3c4ab2c5c2a2", + "0x98c2ece4d49a64ec8e06407a0585081003bcef88af35210e22eab91169f8f0c044d611494b755e5bd915804b1d857747", + "0x8bc6dd083b36d076ddf0e0bb1bb87cfd059283ddabb3886f02eb7e27f1f0539b2819527b56b5c13436523c4603ac1d12", + "0x85ab8b7a696333c82dd5e179e12b2e127e67d911de609ff9a03cab95cbeedb1f364aa1f2b5e59353e4ba0d177f996151", + "0xa9478e214afa68c395aa2c7daf8ba1627feb71ad6d8bc7339734cdcdd5a42838e032736c28e6251c808d5a4875ef0d06", + "0x8c53f62cf06a35321c8af3871ee4459768d0745ebf48942b9f464206309f42fc7b2c50f196ae1e43b664f0e2e718a23a", + "0x8ba80662f6642d8866e832ec8082a4204ebc993fc304c4b794666856de0407620131a18dc053597bb40a3de0bf8aca22", + "0x8c8fac6b911785d1561a985580c03fb2ebc613ae33e486a92638aa7d4493374118d9a6d9d99121e29c68c3d67ee4e3f3", + "0x90f2c793eee07ad90157040b30558bb3b0164e8ddf856389d6742cf5bd1c712e4c6a8e5678da70a8e9e242ec7864117e", + "0x954abed8f6d58896b7f6438c9780236c1c83b02d60a29fa7361559e619e5bc9d67b3646ee39ffafe2b3019bb3357fb50", + "0xb79874f757a33085e1e751544de8fe3afbea92e0234f9c00254c2b36115a16ee46f085f22aa66e0c9177e5106f51b03b", + "0xaa148b287cf4f60c64f774282b421aae075f0eaa93a45aab4927750f47e2ef0b811d1846bbb15eeb2f293c80a7612e83", + "0xa588d8825e7b0168d45499dcff6faf0dfe1ba4f090fdc7c06d50344960c0121f10ad109b0b9d13b06ef22de5a04eef87", + "0x8f61ec93d14ebfa9c31731f9ef0fb8907505fedc79378e9a3f65c27bed4d74b41e129c97672ce5f567d897befbceec8c", + "0xa008218633f1da10efd01c155f7ed739faec902da6dc48e9f19ccbc8d32bb318d71806285cf2003de2c907bbdd4f8b22", + "0x88ad82c66f7085632d7e348d69da84200c53594553acf5432b50dd1e87f410c802dfea91be3cf804e3117ce13103f23e", + "0x8498dba17de0318af227a3f9ed86df37a5c33f9a538be9823f8dce4efc3579e8296cb3b7200cee7c5e0bfd9da23a4b69", + "0xb3c0342231dffe4c9bc7d9265597bc8cc4a82e2980ac6d1407108db5b00349dc91d5116fab51cf2802d58f05f653861d", + "0xb3f2730455f9bf5a058598bc60f47740117ba51f6a767e1134516a4e42338b513f377027acf8825da5c4d047a62984fd", + "0x816360914fbc9d8b865157bfab07aeb7b90bb5a7c5cd64847b1c3184a52266cd3f8f8f3ef99309ba2edc4622304bacc0", + "0x8fd21b2315b44a52d60b39ebc45970a47b9495f42b88217ae057bebcd3ea0e2476c0c3d13de7f72016ae12ae966a008d", + "0xb62014485bc217a0fe892ef1aef0e59604ad5a868face7a93f77a70ba3d7413443fbe7a44552a784d8eae1acb1d1c52b", + "0xa905822507e431b35f56724f6c8d2e93b0607ed7a4533073a99cce2b7c1c35367382447073a53036dfdb0d04978ccf2a", + "0x81672e39c2b31845142963351de3d9cd04c67c806fdfe77467867463dbbd8a9b0e2400ccc55016e57cbedb02d83a0544", + "0x90919c970ec668de8ec48a2a73bb75cb94f0f8380c79a7909fd8084df61ecd631476ddd474b27103c6817c8f3f260db9", + "0x8fbe37dfb04bf1d3029f8070fd988fc5e4b585e61eab6a8b66caf0ffef979d3ed6a662cd99468ce98ec802e985da5fad", + "0x950939aabb90b57a3d667f9820880eb0c4fee5c27fe211ce8ecd34663c21b5543c810b3676111d079ac98644c75ee0ae", + "0xb06201ec3c3cfdaf864a66af128effee8ec42d25f1e173c1edf9207979fa52c871757000c591d71a9b6cde40f5001a06", + "0xa79054e8febd0450c96ac7a5fd6bf419c4b17a5926f3bc23a8616f0cfbc2849d97470174cd1baa7c739b12615334b6b7", + "0x81c7391b2a1844ed26a84f054b5f03865b442b7a8d614cd44805b5705fe6a356ac182b66a3c8d415132e389efac5f6b2", + "0x825af1563d0fe53925ec9ac0df65d8211b333474e59359bf1bde8861eecd03f2ac74534d34b7e61031227c2fa7a74e1e", + "0xb60dd9bf036f1825295cd2014ef1f6d520cf729b4d6cee0b42cb871b60ae539b27c83aa3f96ee3d490ec27ce7e915115", + "0x89ca43d5b7f3622b42df7887572297a7f52d5204d85e2e1ac6e5d7aa7f8aaea5e3a07280477d910db025d17cd2e7373b", + "0xb93a2bc9b1b597f0e514fde76ce5bfb6e61eee39cbf1971ea6db38c3ecb055e7913ec8cd07fb0b0ffae3ca345883101c", + "0x8d45546bc30266b20c6c59fc4339eb633155aa58f115a8f976d13789eaae20a95b064fedead247c46665cc13ba856663", + "0xaa8eacfe00e8a4d9815de3f7619d9c420629ada6489933ca66a571bf6c044d08b391e0d9eec7d1cbebe8def1e7523f1e", + "0xb32fefc59a0d0319ccb1946b351ed70445d78d9fbb536fa710d3162b9659f10288f12d82b32ecc026d55f16cbad55441", + "0x99c7c45c34044c056b24e8f57123ba5e2c2c039e9f038a66899362840cffe021733e078866a8708504cdc35816cb335d", + "0x80def162c134540d5ec071b25ccc3eef4efe158be453af41a310b7916c49ec0ce06bb43dfee96b6d77339e11587de448", + "0xb5f2fa4f68f6a26bcb70d8eab62ad73509c08ee7aa622a14b3d16973ffff508ce6f1aff9ced77b8dcfef7319245cf2de", + "0xb4d0436019e779c789464716e1741c189e8945dab7f3072720bd9aa89882fa5b085a1755c48da21541f3cd70a41b0a71", + "0x931e798ef672e1472f4f84c727a101e70d77b3a9f0c0803a5220958d6bbeb8aeeb56c769ab472a3d6451249a13a3f56e", + "0x918c10a84de268aa8f1ba24b38fe55ff907be07b1e86b4a4adbf305c0d705c1cf5f65ce99e03e11676cedc89f1a4f331", + "0x8e55a8413b823715ccd92daee357cedd797e69a0e78b6fcdacb7318646b9903dfe05e5501f47b3c52e74055b9eb619a4", + "0x8b329bb63e6c985d7d072dff4680b3f8b1217ed20543277386bd30ec25240d9dc378837dcd5cf4fd9548658635f4c537", + "0x8c2be5386052b22986b33dbc63c5afacb6d0095495564ba4aa28fc8c880a3c78242fb083248d788ed928deb1e30a82c2", + "0x83a2b7bdfcbd25d6b059f27218e009ecb5ecc4da68ead885e00216411d8222062ca42f21c4d9cfa19c31522080af677b", + "0x9620334d2633e85646b2e2fc48dc6c3f09c64ef1706ed78a3bb6ce1f6b274a727364df71e97531dfdcb392f70f27f536", + "0xb6c84970ec04545121ec3b79376f4e45053c97e8bf2b11922cc2490a429c38735466097ecb81cc9d9692c74d2fb8abc8", + "0x8e55d707dcf265c5ae29a32c27ce66f200fddb724faa5bbf145ef42280ef645fa2f0cc3cfe2db8599b26c83b91e077df", + "0xb910b96b763966402bbebd68a32c15a225ec21e1357fa298478c5981a4310e556103fef0c73bd8903e11c4ed2c065647", + "0xa8fd933a0e9fe8c459809bd93b8ce153e2af55df94b61a1490736b19c89469954da8b72dbd072d798fc06fc3d7a3d60a", + "0x811b279c113828e114fd82c2070caa7eb089a46c8cabf865f9c77354a77ebebe0c4c6400dda0e66dd017cfc44d76851d", + "0x8ed03e91c331afb3ad6e42767e1b3e8d3a35fb831805ff1b5fd3e91878e04027ff5af1165a3ac295f1578faf2c83b581", + "0x95bf53683d64a0621bf1ca6ee17446783f6c535b7a54d6ea57723487a215759a54f886597a55dfdd560424e368ab2759", + "0xa9bea378768fb1d7ba365a16531c51fc1975f1c73caf2a0891da28509805fa84e2a8db7c6ccfbc620e9002317abf174c", + "0xb8308250891015deaf851c4e5a4cf4704d104f94064418488d7e3076d49f36240dcf6fdcf83f45fe8a1d97fb02e3db59", + "0xadcda6b63da21f4074f142f8e7f3a2274f624c733e3a4001054a1809711529c61356aa087f73aed877a58ccb41d38d12", + "0xb80e7869239ae26d1da2e6683f064d1dc93cf4a2b66e9439b3ad9b25324e969bf98014760d29e6b8de7ff152ef498d0f", + "0x8e9bf968911df3bb5e3a7655e9d8143e91ee87f14464d7ba9c86e1e31b03ab31b91eda121281b79cd974d9ed2657e33e", + "0x9007277e8335a43e6bc3c2f5f98c0ba7024a679b7156aeefe964f1a962e5ac82154ac39d1ffbad85a8f2440f3c1e354b", + "0x9422b9d670e997b7c919a429499f38e863c69c6a4d2bb28d85e36ae0895c620f68b71e39eba785e3d39a45be91507757", + "0x926094e01132938000d82dd9a571fef5ef104cd25b4015a25e3442af0329e585aaad5472f0e7a69899ba2d6f734b40aa", + "0x95552d8057f7e32c24d69e4d6c51c98403f198a20c5be8826254d19cab2f84d5758e2220cea7e38b7c8a7a23178fd564", + "0x8abcf8dcc8488bcc9ab23c51b9e7a0d91dfc7bebe88b7ed370ee68eceba643e939c5eae66a4aa5fe85120751780e351c", + "0xa91bf8198f029e6a4cf6f0cc39b629e9aeff1c77b8739e1d5c73d8c1d3fb5c8f6f23e27b435bf10b5b4ec1cf6a7249ed", + "0xb932d87ee3a4b81341511f90fe5aa36c571e8b914f25abcc33dd40ca67a3f6444fe9362c1434744e4af18d6e045c54a3", + "0xa8e960c2be9b1d805d387b3ebe2134d421a65f1fd4c1b4cccdce78f9926f139eea78e3afb449b3d6dd19b5d16ace48fe", + "0xa7e2f57cce509fe66707eaba9b4c042c1be93fd6034a9b51d1d30c45c4363eac79d54663d525c9873ab0eec0b1cc4ed3", + "0xaa162a31c2078f4b080199debf24494a8dfdfb9d8fc85b198a861b12a629c73128c55a883e4c2de3dfed6e0e1b83eeab", + "0xb5a4d075433eaf4115717a84b4dc37f843d44bba0bf820c92ecdedd5afb61be60f7708c8a151a678d9d5c0ae531bffb7", + "0xb56ab96f7a463c0079e05dc766f3a6a31cae5c5044947734ebe0a26e01367c6763cc8de6c2ee2f3b8218f05bef217474", + "0xb60792ac506b901065a8bc0180a86e028fe34b62ceae1ad640c759538ebf3a2ad9c8c927d662deed6f489ff3ff7813c4", + "0x8c8c2cdf075504d12d441a58542e1f8e4bdf92b3ee4775e836b2734c5ec1e3df919b931386417d04489a1dca806c87d2", + "0x8ed78e91e5c4a68894cefc2f7fa71f02e5e12d40f1bb74332139bc7be4d92c24e07d5ece0e82150ed474aa1337af4c18", + "0x87119c22ff8aa31150bde537d863cad661cc5159b12f084cc319224c533f0deb28526ed8568d00a1441e7d8bb4f05673", + "0x83a60ba5a9cccf22cebadf7318b706c9f29abd25db0e2fc1c802965351b53cbf316df72ee3e9b2d3ae7f3c4494cfdff1", + "0xb73b6a9fdd3e7463fbdaabc9a885b7c82201ad867d1bced1c2484300a01cbbb3f1e21afa95d4c7cbb6cb983416b63b90", + "0xb1d89ad16981ff9217708090d4017662d8838f21f3a3296cffe14590b533905fa06a20e40dd497bd291fa4dfd1bfc511", + "0x8abde560083e071a402e3c7bf31930f537f67d2a7bbc734a7480b1b760aa712ebd1cbcb65b00e11e384e980222fe14a9", + "0x89c731d8f31afea8bdc9c32527bdca257f2a840764d40f6e49403b8e75ae51017d505ea4fff91bf28b6f3a1bc65b8bbc", + "0x80e9ac8e077e86ad050ee73dfce268a69564ff1b8419e9c236d981fe7a5f0c2bc756e8603ec604b3b9e36da8fe10a49c", + "0xb4f1eea0f304898b1323c6382732e6f40e556bfc68af9ce73f6d54e92f5f23cc4f78eb3f43d578d81e7627fb40f092b3", + "0xa0e3a8d1348f8f153e08ac4839232d75d1d6e81b5de184ec4724f8213baf98d3fe739a96f6b39d79a053b628c3a09981", + "0xa6915ba0b52ffe4a381bbb8ff3791d9d3b848bf89b3bacbb2a7d2e5ae21f1353cdc304b3cb6e82416f7e604035c27d7e", + "0xb2c4c9cdfdd2fc9a340ba3ade9423344b9f429e8c7e20a8abbf26400376e312f3ae35d1c456be99dfb5c02fc8a36cbfa", + "0x9657d57ca0641825a0aa5687f3f87659d893f33aee819bafa5b1ca1db554811c1c844f971e278606e3a2f096defdc67c", + "0xa4ad24d0a557704ada24d8e27a15604bca28679e260b2c69ccc8e6cae5499866724b700605a90df7dfb35130756939b9", + "0xb18d9ea6682f73a1f99a9a4fc98c38fcda02c1a18e8c5fc080cf935a2ac877dc5223fca273dcde190b906178d0fd05bc", + "0x8ea5fefad0799c885f50ff10d94bd0af5b99b0a446cd1f367ae5ff529cc47e09f3018115f3c0ccac2fa05bb65b84945e", + "0x92450d52e6c7d13ebfcdf5674d6761bbae2fc5aabc865d35d031b588c383e0a64cf69a73dc93948632e2b98f74a5ed86", + "0xa356f171a98df4ec5a96d556eaccc6ad34b4238aafcf0e94ece27cdbb491749fc9692e78b84dfe80bdef2914079d34b5", + "0xb918703a4d3507d266414712ba8eb7ad17da07cc5f952b5c62ef130cc6ed1ae3bf01237fc8848c179725bdddd465b301", + "0xad2b0554570bfc9d97510cf59bc38e10ca54a93649c30ac9919bd0255e43bf525ab11b74f78a51ac0973cd0c5a5dcb54", + "0xa7ecaf4b631d179d32ac1632390d95196a0035e00da6c0e6e13b5c09ae44b15ae6c21538b5a31b73bc5f650ecd979b59", + "0xa37704eb4d728df2a367e59fcb6c26023136230e37f3b8a2f3ceeb1467f5cd30186fc0116f98b64a8146fd2c5903e8d9", + "0xb09373ce92314678299ae10ec1f93c702911beb4115c6b5ba6efbcab9c7afb599f59793912df70a98868bce6545a33dd", + "0xb52a878a1393094fd2b93f2d1eccabf2830ab10800ba4cc24dcc7849cd0978733263aef2fcb766a7cb575a7a99383db8", + "0x8dac097e006fda4fb9d6d7ae52adabd9448ebc8d5bd5b38ac0c4ed38ceb510763174f7adfb0b473c38e52147ccab4239", + "0x86b19c41efb949937d74a7875549ee5e997f9fdac7f7198085afda233cf74341a38d0ca3767c76cd35f875b89a35f78c", + "0x99f0d927e5ad25cd134f1c70b72631cc6b5cb4ddb86c0642b900464e33d971213a5239dddaf71f7a42f2d6d02a12dcc6", + "0x8355c38806c335d747d4e97f0083fb96585677da18b409a85175ec35dc3f74671817b34203eb18c2f729717ce083ede8", + "0xabb3603adb061a036eae0afa5f23d79c3b62442e0e3bcdeef896f88995585c1105cd3065410368456a4d36b5b0485a83", + "0x9051c5c0011784885187d04749f774b9b4f6bc594b0e4e18226de79dedc4d7aefa3529c3d2c728e180f96f3e204d578b", + "0x91888213e7d321d0bfac884edbd5cb756b280753bb5f8bc6acfc208f525757beca24bdf86fc68d3d8736ef176a960b49", + "0x91258bd7ce6e3b7516fe2f5391a368d826da299e0e99b1f82eaa44b62b110ab696adc92debab8ba098a52f38dfb3c5d8", + "0x96e3907340dffa9da3602d3b94bacff7e1bb8649edd3b9bbd06e1bc6781e78f91ababab12c0b9be7c66dfedc7001b66e", + "0x9513555688fcfb12ba63952ab36a67b36affdd71f7b843e8eb99ccbd45421698024608233efbdc905eaeb26b334b33af", + "0x9913ca9bcf11eeb408da02e4317c5ca0010fb2f4490b282ddb758001c08b438c3b35351a8cbe10b7fffc1293ccd22d4b", + "0x85dc2471860ebca88e5a2766161fdd77f926d2a34825d1134a30418f91a741759668e32fd1e37c415d07ab5824338e8a", + "0x8b128917e828a0b5eb6fa8ed72b52fae2dfaf74febee69a2e2f87e8df702f0c5bc0fb620c8d1d2a07f35a15ec9c0f5a8", + "0x964c39e7840c130b01bb481ae7bfc92682b0f124c9c383f9dbf3027f2249151925f4faf36905af476a54778d69da3f48", + "0x80671ece658cf850e522d46d25678f934ce6df043f25f8707235125765d40c2eaaf39eda6092f75039b22cb58bf2c29d", + "0xad4bb0e79fdaa340b1347a46b0f64e801c72a89770dda0a6e4bfd35f2df5146fce9934e4baecb1c2671077c771eb8089", + "0x80b3bd3adc6cf198fcd997f8867d2839a2eb28f57390352ec423b8a14cc1f2ab21c6e286505d6a21fb134dcd8d8f11cf", + "0xa26d46a6b8a75748895a1d599e7fd120d896340e79813167a400b2fe463452532a4cab419074663fe1d29fa716b76a33", + "0x82b1f3a8a1df29207d7ff020809113ab06080a7f0c631f76ad33f47cdfb6a567143144df97b4ed7f676d929195b04bba", + "0xad96633a3744648ff0a2e4491e8219c9c6ba6e655cb058c36320a8f72cd5f72c00bddf97083d07650ea9ddc005fc1ff4", + "0x91d0783788626c91662359dc3ff36a8bcc6831e3f4114f85c99910256b1d8f88a8612f53c7c417d55581dea486f38926", + "0x84edd9e87ff3d193ebb25f43474c33fe502a1e2100fd3f93fda6520f5e42214cc12e9f8045f99aa2423a0ee35e671854", + "0xb55e06a4b1fc3ff9a5520e0b7c8b5ac11b28385cce78d91ce93b82f1bd7f7afdd4195d0c13a76e80d0ed5a4f12325fa7", + "0xb0b15c7ddede2b81d9c835ecaa887650622e75d0d85f81b8bbec7ef24e9a31a9c9e3de1f382d8c76d878d1b01373f6c8", + "0xb1adb47c20f29784116b80f3670182d01b17612d5d91bd6502b0dcecdcf072541f582aafc5e7dd9a765cad52151684f4", + "0x8efd1018df9c9e9814a9c48f68c168551b999914a6719229f0c5bf0f20a288a2f5ba4a48ba966c5bffb0fbd346a4fcc6", + "0xb34ea2bd3269a4ddb2fbf2514401d2712fc46c22642f3557e3b9c7acbce9b454dcf789573ede9aa14f39605fdd03f8c4", + "0xa9e1428ce24eacfc460aec2e787c053327ba612f50d93510d58b2cb0f13291ca3d16358325ab3e86693fe686e4f526f7", + "0x91eac7361af4c66f725c153da665a3c55aca9ae73ead84ca2662cf736fe6a348a301be1954723206dda4a2120202954b", + "0xa6f02db89739c686407825fa7e84000ceedb9bd943e8a0908fef6f0d35dbc33c336072ba65e33e15ecfcd5714d01c2f0", + "0xa25666faa12e843a80365c0fef7d328a480c6e3cb7f224763c11d8cbabd0e7e91a5b647585ee905cc036afca14842bae", + "0xb4348576439cd2e48c01cb9cded7cc4a0ea364ab936dd679ddc7d58b48807e7fab070f2f1ea88595b11af4500849026a", + "0xa8c6c731e0d0464ef7e4fc1b049065eb4ce100c01e1a376365c636a0b23851022bf55805963bc15eb57434a837e81167", + "0xb0952937b154e3a4c206f96cd96c76ba37624956b0e4d43470bdd97b4af878326b589e3eaee82fc192437123096799a2", + "0x97d07ec31ecc9923192e48d37df2cf08750050fb452dcfbdb350fbc43e146bae3590c5b732b31ebfa1ce5d884ad5ad57", + "0xa69359aebbfe4cbc4d39d178150039fbf284cbc0edc68a6bd635ee3a1c76569a4a575c907fff691b2a4d82a384c2945f", + "0xb321c2c0f6b5902ee9056cce7404d858da9a573d27348c1a6bfea29b2746f2aee7abcb6192504e5a583b0caeaba117d7", + "0xa74e738aa6eb4eea58855ae6f422af22812fb388c83aacca5bd5fa4a88d4c01463174a229aea2830c348dd9ab9307854", + "0x94306a3b106bc1644346bc45c05cdc8287811d5c86cad691bde0c65d6a686eb9c0ce79ad91baa4547e5d058ae8bf7310", + "0xb64140fd77a07633e4ca8d60786452311dcdb8ce7095ba51dad8486f57c3bf4e69bced92603f71da992a48ad817ab275", + "0xaffe7f4310f1dc68e5e3cd640bedf864f51bfb46bb752063bfc18e95930021f784e509261ff9c560f53000c361b142d1", + "0xb0d2fee222c6f963ba3385547f921a48964da031d737892604f8f2677d4905dbf615046db57eae6c6dd756709ae6932a", + "0x81700c66aad7c2e51168e028b0fe086dea75d3b17d93a4dc1f47a6a0f025df0bae1c8c997901837ad859a84197e7bb00", + "0xaa4ac5fdd602f8b79cace18690e67bad557a93d00c0e295074185e8c6b4059a65495d9971685de2fc01d2171ac8b706a", + "0xa8becb3a64fdf35d65d2857898dcf8053b5057a73ab8c5bb5324af1a8015cff47efb85dc3eae7364cd5c850b7962bedf", + "0xb72ea09bd0b72f8cde3466f359ea69b194ede93dced534efba1b9ebc6f3bd53942fe2965e992e82edb6050cac4ed88dd", + "0x85bb8dd7eef023a251fb6f220af54687747f4c91983ff728163c4618ffac40ee6edc29a0aa6d455276bbe017f63757c2", + "0x85a485254a11b4c4a943d9ec509c0dd1cbfc0ff5273a00cf5c9f0babec973efb15348e5d9451b548293d778e3a2b62a5", + "0xb109f3ac809391e772b589c196b013db69a9b2b10ac3898feb70b986973731f30722b573cd0c9324158ec20416825385", + "0x8a4eb579a840d438bed008644f373ea9ba2f28470d50cf1d70af38ba0e17326c948527b1719dd1bd9ac656ebd5aedd10", + "0xa52e9d66ead5ee1e02ce6108e4ded790d8ec83164a0fa275ab1f89a32200726c8e988d66df131df9e62dd80203c13dce", + "0xb541cee9febf15d252475507e11d65c4b7819c26cf6d90352f5e8a8f5c63e254eddf22df0c35a7be5b244233e8e4ee5e", + "0x8153c297772adf4603c39349142f98cc15baeccaeae10c3230ee87d62255f6814d88d6ed208c368d2c02332426589748", + "0x970dc9782f1828474e9fab7dcdec19aa106725465a5844caed948eef5c9e48199c1b6bc1a637ed7864116927e84bc65a", + "0xa975a920624967f4ecc77ea5d9869c434caa64c330024194615a8d0640c5d4d4fb139ea11a0c73a5c6ae6dd3fbf0ab5d", + "0x811f0f9e0c12acfb4b9dca359eaef3bed18083bad96188befc036ad3143b121fff4777ca6dc70a835bbc4921bd25f5ff", + "0x82341c6ebdb97c8b72910da95c7eebccd1308b6a92999886aab552f0642882d5c7cc60931577d200efd6066530c998dd", + "0x860f7162c2f5fd1c0953c6ce75bd8c52eaa48032b914410681b8cc05e00b64130d1f96ec5a52df66a04c78a9f9f42981", + "0x8a578e674875571fe1a0459843495a5ee1d9fb6cd684b244feb9488f999a46f43363938cd0542879ea18ed14fba10a6e", + "0x8df217aba4da6781f0f5139aced472025523ed6e17e504511c04b677ca8197488e237d8bb5dff7b6b3898cd5a6393dd5", + "0xb2c9230ad35d7b471d3aee6f771517cf3145ad26200bd6fe9c7cf28120e2945fed402e212d2330a692f97bb9ac4dcf12", + "0xb78b89e29e8b782603b222cc8724eeb83b2d9d56bc02f59a3c899ab76429dc721358b07dcdaf422f59520b7e7ab4fb55", + "0x82682a5617843c4ac8d4efb4c3ce715c76c1da2c3bab1ede387db503f3489c1bfdfc07d9231d96f955df84fd225bc81b", + "0xb0f53725cc610e78b8e8a4e6823a2ffe44dd15a9a5bc8151ab7a3787ddd97e1d7f2f0e6efd2876e5f96417157143e3bf", + "0x92c5a93233085e2b244519078770c7192af62f3562113abc8902f9d72591eacf52bd15ce78653ab9170d5067606287f8", + "0xa43ef97dcd9b6ad288846bf31fccf78df72f94bc7ad768baf5bf0d5dfa27bd74ffcc6b6c6ed1d1f09e09be3afa5eaedf", + "0x817d43bd684a261fb30f709f7926cc4e1a31fd3a1a5e7e53ba4d664856827b340d7867e23d55617ab3514c8a26a7040d", + "0xa599e22d3286b32fafaaf79bd5b0c5b72f6bf266ec68948478f055391336d756b58f9afea0167b961fd94234989f0f02", + "0xb70db7d8e8356df2e2070f8d658e560081442f3f3b95e20f4bf30106835d76161101163659d5d12cc0f335fb042dc66e", + "0xb8f725b70c957aa3cd6b4bef0d9647393f7c9e0b7343e92439372f0e9aa3ceddd0cb9c30be331742b87c53f2eb030593", + "0xb2fb5e7762f26036e7e966f4454f886758804d1f4c2da17f3d13b0b67ca337f1fd89fd3cc798b07da6e05e8582c9537b", + "0xa377f944dccc300921e238ed67989872338137fe57f04cb5a913c787842e08b8a1adcfb4d2200abdc911fc1c766a7092", + "0xb82e98a606071c2a33f2ad44e7ace6d9471d5434500de8307b5d4e0083e3a5cbc67f0609ca8055f0ea0ee7501b9ed916", + "0x8e58f9a04d33a41ace4944615041662dc35057e645f63e127cf0d70f96ac307d33a62ce98f164d6eed8536c1a747dcbe", + "0xb5b11388071ffbf57ac47fc195736613b964ebb91cc8e2c17b32646f91d64ea506282b881897fca96c317364d3290de2", + "0xa40ee9b7551133856cfb3904837f9949a9558e59a418898affb78adf1500fd6ef6328fc4422161909aea2c79ad08c14b", + "0x81f9eb4ef28aacdb43e11dfc9aa92ba990be4d3c14b484fa677edad3a3fbfeaa859a7f9322b5e95818240d7326215abf", + "0x84939b2b6bc859437d1a7a8d6ec9a357c6b716c4b4cc22abc274af872655940cfc72c99f5d0283d90e05191fcdb1c232", + "0xb78a5b74a90a805410b6225fb9576d6d73752520f25cc3fd1edf8ea9f6559d3080f9acaa2246809b6a66879cd2ae446b", + "0x8d0a92baa88bf38dce5385ccf15d345b28e2e5d0a2d469e689353d80eaed8e8408933816d70ad752f226c59a0d5b5f0c", + "0xa7e15f8a8c1655b7b346c9488cff278c793505379b781b31b273b4bf09b3bdfca1c8ab2334746075d636b2e05859f215", + "0xb70daf14f2adce03c7b92d6aa181f0c507a80a37493d8dd12419d5ed5f943a98099fefb46ac827d6e4efb9b8233c99d6", + "0x8c2480814661744d116fba7355bc6b1914975e44cf0e976d50b6a20092bb1c636b7b44ed3fe8d63b5555ffc89fa759d6", + "0xa6059528a4fed36abb74ab992b22a4f9bf1d05c5de2bfe6837b9af1adfed98bc37ed7481b5a99675d432743021fcfdb3", + "0xb7e19f1b25bc159e5a769811e773c3a8ffe8be8ac77ed0b711540915e5c6e7bafdb407cf9b85c551f67fd621ce8142a5", + "0xa2f66d4f7d16ed3e7ef5fc90b42676c61a98ff18bd26ccce91de03b6a0130c1db17a6bc57be135e410a76d2255b15813", + "0xa139c916927dc3d3fb83598da9217ca64f0ae127215332e9a7ed82be923b89a801c44580d5617297175f9dafb1c4eaf3", + "0xaf08e1e1b04ec95366a12d99c80a9a9ac40ac984a575dd0230cdf4eb346a7686da55ef0a276f3356f814af31f9cbf1aa", + "0x98840aefe287369221c0721cd7c1b15b1d670c3cbbfda191cdb5434bcad757e59c30ec82b2d8c75947405888d44da435", + "0xb7c61c8d42daf2e278a12d8f6eed76090b71c82275f8b33504aba75d95103840e8acd083e97a5a5aa79897876a68940d", + "0xa0264048d2a2061d32eee4f661957ff351e78436bf49ef973c059612874ce9c91970869d011dc13a5b7c754476880a68", + "0x897199a4d8db8aa2db5d9be3d4f4312e41fa0739eb06c62e2e046c4b9be829a447e5d47227e2d96195d3b7b66eb59da6", + "0xb512a9082881f5dc90b02f8bc4f38b133348c2e933813852f6a8e7d8c270c9ce68a5524af7d1d3123e53b2d02a53d465", + "0x80b332469254a96f53c95ec79bb5a8bb1c387d40e58b73d72f84384c696ba0d3c81d6ac90be2979c364c44294e90432e", + "0xab680c2e547ea5cbf95bf813020beb461d50ee4341dea944eb48f6a8584d35682d20186e3b190b849a1ba25625a7f499", + "0x9070581993a0531d6be372d370c2e4ab2ee53f30e04a75ae61ea0fc2c320914506c4d2d4b4487c1f8fa88356fc45c895", + "0x8424303dad6b4051ab633ad27ee51783b2ead61c5a6dae1eb3ed72fc1f36e2a9b1f315504a4bd90f9664091f2f403d4c", + "0x82225611eee626556553b9316dab4043aff241a81826a33aebd9864a91e299b765ba1fb43eea2c2047e6b75b6d7fe3de", + "0x8a3fb221c616ad55c352dd5e0c09ee892022013d6965aef40d4f277a42e9fa01226fe973cb99aaf6ffe4f4f348fb54d1", + "0xb07c07679aa51713e8a7d7bc304dc15ed5664b66bd371877023f3b110b3927e09e259ef22895c4001421a69c6c013cc6", + "0x83556c76bdac0dd8db6da231b863c335be076e7299802eebc259e0818c369f933a4a4b18e2df8ca07e82f60767b462e0", + "0xa516f659b7915d2f7cd0f0f5ea2491b15f0c84dcb191e7671b28adf7cf14a56d42cfc0da94b3c269b45c535f6eeded49", + "0x80d7cc6f26066f753041b17ff1bd27f6d4b5603a43729d33d596e21a67356db84ca9710158089def425f6afaf3207f9e", + "0xb802a47f9009dbd48851209ea1e2739020e717f0ae80671d9f97a0e43de923273f66b7fcc136a064c8467372a5b02d28", + "0xac92fec1864a8a911633f377df87aab56713876316d48240fefeee49ab97f7406c22e70f4938b5912c5c4e766146b7a5", + "0x89224225b9835d04428b0a74edbff53dee2be285ddd1e5a3a8c37307c0500578155f0c4052e4bc8be04c56862fac099d", + "0xb1d3c8492fbf22ea60732745edd3b0163ba5a20d1a3315e3773f2540ee38cf308d42ec72cbb3e3dcea457d1d132c3904", + "0x8bd00e38ec30ee6c44a0e5b222f1f737c9ed2a4bb9225f1741d6334df966318c8a0fd2fbb109557fe8c9479694b8d8dc", + "0xa930ce5454efc0b247dc148aff869963fc5c240241d5590415cbd36634801a04d3873d93635911bb9c0c42ecb005cc63", + "0xb83d4f80e9e0fa47b42175df74935ba8aad2e559b80e84478ab1685bc3eb65d51b93e5738d5ca968cc055ca0c552a03c", + "0xb3ae21258f98051f13af3878b8103bc541fe6f20b1c3f8fb4689ddb8800b3c25cca9b55f0a4104bdf15dc4d5844abb8c", + "0x831ef8684c1cd446c58c59d0152aeade5cc305bca6aa296b92162615f052ba280fe289edd62fda6d9f0667c186445f52", + "0x97bf9659b14f133885916733b7d4ac7e215495953caba970fa259f7bf6b79e661090ec8d79e1c9ce8dfb17e8552f93af", + "0x84d5a89cc2332baaaf3d19627a65f4b107f8dd9228a1434b327732f59883bb54fb8ce60d6acd026ed4b0e94e545d1c33", + "0x8e66cb743f95ca5486400b0d89d02e20b98044be1e3a12983ff9fe086179e5a0ebf4dcd5098703191552e9aa660a6de5", + "0x87b4cfb35bacec805f8148786788db84eb8f4bcecdd0570ecb592c705450ce1a90b6d183d37ef58780ede3995be67497", + "0xa72a4fece5478011973afa543f6d8a8ea06a64b241cf7d8bd81fa3740ac2a4cf10e5120abcc1c1101f94da89507a40ca", + "0x89dc6001a96adcd2679916f43dd19ea00508c8d5dd6b0090eab7982fd2f3571b62f3029588a0649e73f49124525407ea", + "0x8ca75edf1259599e873530eff6151c822a4018e71a340534219ef8641cb6683215891df41d4e3c0ca2560e57a7aa913e", + "0x9282d32f868e5ee6f7fc229dda5b94b603476de30cec0a44a30edf396b52dc0ebd472b8f726d4b67d76179fecc1666a1", + "0xafa24704223707db89690bcf9761f07a093f6009ca9fc945e0a8801fc29f9f51292bf95243e466fe736088af36c55ca6", + "0xb51332508ddd9a2610edd2b0ad120272ca342e96c28baae37a2c4f07e689303a46c237712d07e446b1d67c75aa8ce32f", + "0x9219249f3799dfa4eb4770ee323f821e559e7406bb11b1f1889286221b22c8b40ccacbd9ac50ea3fa9ed754860bc24f0", + "0x993515270c128ede64fe6f06755259105d0ec74947b7eb05924a375fa5c6d14822f3d7d41dd04fa5df8aa2aa205a1dec", + "0xa83be4c2511bae430034ab15b194ac719d7b7041f9c0e321317f513a97db39e97b9ee1df92a1962f265b7a3e98cdd753", + "0x8ac7feaecd26f7b99fda3ed0b8a08bd6dd33ed5ba687c913ec0ffc64bbbefcda6f265072add4d944f2005634601ce68b", + "0xb4e3ac6b09299db9e1a469f3a0b2d8d724ee47a417a517bebc4c2ac3efc5cde086b57b9aa4efccdef2bcf8f456d973f6", + "0x9262a24a84fb7b2a84d700f98dcf3fefab8b47293778c20bfc356860cb84e0bf102bae9facd9986d92d1762e0a955836", + "0x97be2041c42bd25e5eb519279163b0857f8bef627492c27b1182f8bf0033769246be5886422cbd2409c08a2615352465", + "0xb0b87d059a00e3effa2e5e4925da913b245785f2932ac3ed364ad19a064d3561b8aa6afea22c951316074f0df179af36", + "0x891644b7b3321b06a2a40cd96c2b8b29d81cde5b48546483fdda439000982a9cbf1f6333fb6c089d39da6492cdfaefe9", + "0x8da9149b7f4783a24240b7b9c7e6df4abf8d699d3834e31ee591489bf4744141ab199c173db64397c1f9bd5f9c862ca1", + "0x8ad7f9fb2742654aa2964fd468e7645436cefd1308b064fd63fdf0d3adb4caf6cfe5426354f6cc284f208b03d6b2d918", + "0x8435e4668f7aeb027100d21e4e0b6ee22b401d21966a3736b95610de86c7e2f2c9ee5d0f901353675eee5ff458dad69e", + "0x9010895f045538bd11b47bb8996f27198c8d6cffd3220569e6b7407f68f35c47d1efdbcecbf9b5e241c3c2879a4f6936", + "0x92a9aa443b5ee7bf13b6f43f2d8d8db7f6f33fd4073a606ec5772421a55f464831419726130dd97829a7d4bfeb1ab078", + "0x843f3266560be6dcbe0258c3c7d7e332330e10630c069892954290288eda301e247f479505a8a1bf7e59c99ccafd104f", + "0x915bd1dad808f8a568725bd243f80b5476a2999d0ef60ea3ef6e754155bc4121b2b879d01570725b510c5a3f09cd83ef", + "0x97250d781815b1825be192714884630e9f564b9bd737d55b8ac79ab48d0fb3ca53bd21ead7b2fa82a05f24083f25645d", + "0x81e2d52333391ff2faab39611689a62d6ead77039e8703f4e012d53eea17a4d46f2e3342e44b6edbe73a542b461bda45", + "0x89c9f9fd5f638156b018831c1bb70c91215f4a2f5a73c84b1208bdf6ad652a55df7213336ce12bd910a0e1a726474f95", + "0x92bd02984d090ea7e2f3eb7d36d1e7b9d731b6b047e3cdd4af7cc4ee177415fea7a145205e484b366d84191f06af85c9", + "0x85a86fc61d5d916ccbb219db52953e1495230aaaca63237e9165276405f07ad9644e253ae394f1ccdd231944e7143313", + "0xa2ca5b3fbc9f3530f88c0ed7071ec3d89b272174c366eedb5d15d2b648c65d23c0faa4e92c776357e7c6883a0084d03c", + "0xad171f5badcc99c8ffc9d8b707d792046f86cd0aa478e0e2fbb32fe095f96cd134ca548d1f7713057694dc6b26465315", + "0x96bd15d57da9980870fbadc98c68db76824407dff2700c45b859bb70d98374d4a4ba99e3ed0b0c17f480fe08f16c6b8a", + "0x8300bac69ca088c3ff35749b437215e9e35a16393e9dc094f520516ba57a485def7029d30adfc72bca36eeb285c19301", + "0x8a09e20be64f346668fcc7b07fee9c0ea8094c935cbf4f3a4cdbb613d4b936c1edb9256b7c884efb72393d97c0da00e1", + "0xb1f85827ee6f041f93ab174d847a55710824fa131c9ade9561168c3962a25c617475ebc4105eba6e738961a754442bc8", + "0xa131558f92e215969f41b6a57d1e2f424149eea531723821dd4cf8c54325cbe66b002de2c8287de6b41ab4b5c35f060a", + "0x81ba492b8956f73557f361a856c6c884ebb300d828287d5699e22e0cfa75c8e77a61616551d0be5178263898c461d6f7", + "0xb2608f44d3c22fac8e13cb59e4ade8b9a98c4eb1ec0959ea400c97eb937ae3f66837e91917057148befade8389af2f6a", + "0xa6ff0323b5a18a4becb2cc6b376086b47cb2baffbfd1b0f2229ef2286fb4a34c5cd83a5faed5def7bbad519fcab8a856", + "0x857d879cb9eff22501d883071382832730704bfcc5cd5b07cdce7ab8dc41c565a1eb0e7e4befce8e0e03a4975d3f11ef", + "0xa2879a20c0360c516811c490289be7dfbf7dbd41d2f172c9239f99e3d091957e0446854f9d0f753d90384a80feb6fa56", + "0x83518624f33f19f87096a47d7b8e5f2d019b927e935a9021823fac6564c4f2328dcb172e25bb052748191e75ac682bd0", + "0x817ec79132faa4e2950665712b2c503d7fb542aa57b7b36e324f77cda79f8b77bde12314e2df65c5b5296a6bca9bb0b4", + "0xb2abf8fb7c3690816fa133d5b4aa509cd5a6e3257cfeb7513d1408b12371c4d58c44d123ac07360be0d0dd378e5bcf99", + "0xa9fe1e4fb1574c1affac5560939face1af6657f5d6abce08d32fc9d98ef03186dbb2dbb9fd1decd6d8f4e4687afecce9", + "0x89b2f41e51f33c3ca3e44b692e8a6681eb42a7f90b81c9e0a0bc538341df9e2039ee61f26d2ebe9e68df5ed1bccf8cdf", + "0x8b35aa7b1d9e2135b35a1d801f6c9f47c08a80e48603f3850b425f64e7fb9860d1adda04f92a1ba22d00dd0a26e781ca", + "0x960574978cadedbd4cd9f764bee92f94e08b7af65403de36b21bffc9424bcee845b3b028af2e9e545dd77cf1e69a6a7d", + "0x840aa0f34b5b6c39471f54d9e85f1eb946468c4fc01963a9027cd7864df01f73c2e864f1f07aeed4b1b1af72808dfa07", + "0x834464a84a11200e3c60f816044c254a7d9baed64aed45a17325cef7fd62338e0a26da78d199d30ac3411714dc813223", + "0xb4ac6fe2f5059546f4ad9a361426ead33237b6b9030b129bf0122085c85fe4ccb33cf90f5a7f23c5b708a5ac64b487f6", + "0xa12aa9035464795f2a67f3eaba478d5ebc838ed9e997c7dfa241e1ed60a94b367d3f969ccf0ef02028c35215698b309f", + "0xac8d926492ec2bb68c6d8aa9bce49085d3d266f3d5f1f924032b87c42b44e41da7c047eeb01e4618f9d0f123dcaa537d", + "0xa5142425825d813ed8ce1849d81aa40b11f1cc3daa89a9f798dd83065c74820b4da6122b3308f528b074531df66e1a5e", + "0x87ff55c9f5aae079e7bf24084dd9c6b3bc260727d942d79cbe8dc13341d98525b4ece3ed8169994b56a387642f09134a", + "0x88e680f148ef2ecdcfed33b61f9e0224790fddc9069bd6999e9bede1791e761637c0fd60b52990b6c93e6e5429e483ce", + "0x94bc20bf5aac6e9f1060d02eacd06c42aeac9a1c5635b15a83985dfb03938ddb4999a822e865635201489c7f75601b29", + "0x849221cab7599f25f0b114df092bd5e8c2430503ae959bef1543a101de0790a78245db6a145e26f40b5f9bcf533219a3", + "0x88b6f2c2e7a7954fad11009d839ce50780921f80292320868d481e38d26aecd80fa607e82219a99532d88cf33b39f562", + "0xb0d82947dc23c0b88b86c321b582c15decdb825ed909a731b42d46bc895009515a3dc646c98dbec7d71b0722df82392e", + "0xa2cfb9f7c1a76c8073363c1c3bebe5dc29fa76533caea41046c51ea9bbdc693a121b957cd96be5b6da18704d1865cff7", + "0x8f0ffab9a83355a22683a9d998d1c1089449eb308711eaad4265f05927ec6d0d1ca39217082a0b372e02234e78dbaaad", + "0xab024661e2b2937ad374c8cf2e3669f1dc55558a3a881e9ec4d461f27e0fa92e2bc88230f038bfb051cf2145ca747a07", + "0xb98d9b9ec9eefa56d38cca959ce1aee7b6d4b41a8dbbd34b3f50c0a5f97f84ed2502ded1ce8cdb5895872360d4ba6d61", + "0x851244158b3184a62d2c98d148e2b1102cf0d5500906bbc2deda95acc5e3bc4b4a3344febbb31ce05a56dfee86a74913", + "0x860d9e2cb886bd3620b5d7499d14b415532482569bd45fd76e3e8052d78a73ae4b2b41f139f9cfb136564108cd93c0f3", + "0x8305a052a0fb2bcd41f3aca075c5f7f233bd8f861451d03f3a6e6e31f7d08dd89fe1eb4dd7b238a78b12ddceaad9768c", + "0xadb703e4778c7e14fb83541ab00b5fc344108243ec6827c5d9b302ee68321aa569da1718424e6a57979ab7536d5eb43b", + "0xb1a754b87b9e21aeb86217ec5b4fadb7535344567f1bd15e88ec12a833fed68e26bfbe03b7709ce24ba6c925ea0a0e07", + "0x8c1e2f6bf820e1653f3b8213e9d959d8649196223c2aab57b7ebda094f4919f88d883bcc6a0cd0be335f26f5a2a9c962", + "0xa082deb9865fe8668e91db0e4fd7fb50fb3fdae3e7bf1217ce0aa6f286a624624cf936d762bb2b6c3fead6826694f846", + "0xa10540ca05fbcccdd0a2a66aabab3b36e9bb525794cbae68bc3dace6116f58942218e9d5e9af10d67b5f6fb6c774fdd4", + "0xb81d22c4ab0ccaf447cc5fc2ff3bd21746617e6773bf43257c0d80331be2e8437b88c9c45309ee46402b38d3d4911caf", + "0x84c7c6e924713cab3b149f641dabf63ad5abbc17c1d8ee7802a6630507aa1137f7e034ba1d12ec13f1e31efbab79bf13", + "0x8773b9d236e5fcfa8c32e471b555264692006bf9a869a3c327aed33da22dfbf5780ecea7158904d4d6ac4acfe9789388", + "0xa4c2c1bb7290eb7af2013f7dde78282148593f066b09faf42e61a3fcf81297caa5a00fdbf6b93609c8c5782a0f25341a", + "0xa7bfa6e3f273da3dcfac7cb9906bbe9fa4fc2872b184d79813ee273e6cc4d7f37f46164362707a1976f5b6a2c5d7ed1a", + "0x8b71502019e4263fcda354a0fd10aaa7da47f4abb7a0c715c7b017e9eea14f2b64009b29b467394668c7ca995adedf82", + "0xad7460fba7deccc3f9a7d204233de47ce30ffa55e1e164975cdf06480a6108720bc397b93ca8c959df77d44a1e1f05f4", + "0xa5b8df96ccb7b078a3918e74b1b10da21df982538d2c9313f5129b2797c8a6db9ff8707241ff72d3e9d5983397321736", + "0xaa6cfa6386660c01879656da6c4e72497690708bae6c5cd1d088f443cb5bbbe75561d6eec256a72b9728377eb83ef973", + "0xb9699ce7c5c878e44114ab7a598646c6c7616b8e08a9ef8ec291189ef9945c1a538d2abf1ce3b0da0f8eecb303b81b43", + "0xb8d0fd1d278f53c455de92ec4357885fc6648dc5f276930263da7dc885b4a9628a2113e28b66b1e64fd08189427c614f", + "0x84ad8d262f6ef5d93e82ff6f4af995148eedf6d8e079124daee9b99f506e2968922eac2c7d4aea741fceb7733f20b2d2", + "0xab5e30ab54641e3a44450118b8235554e0fcfffdfbe1430ceb3f7ef33325725741995fbbbb0c16f0875aef0f1e0c98ec", + "0x80e2cf8bf386ebda46045852751611f2af80eca2e910d9ec5f6e2c7376611534604ceafa639272b3d503b02bd66525a6", + "0xaaac69af8fbb87da1c1b7c1b9e59942887ae839a91f0c1d191c40fe8163d7f1dbe984e4fd33619c73e63abfa7058f1e3", + "0xa6194224ad838ab86e84dc80e9b8abb121ae6c3c7fddc476463d81f14168131e429a9757e18219b3896a667edda2c751", + "0xb68f36aa57aedc7d65752b74761e49127afa65466005a42556230dd608ecc8f5efdb2ce90bb445a8466e1fc780eea8c3", + "0x886c3fa235d6977822846b3d6eccb77f1e2cd8ba3dc04780666cf070cae208b7513dc4525d19a3fb6385cb55f5048e2a", + "0xa9801273ef850b99eb28f3dee84ba4c4017c95398730c447efe8c1146b0719f252709d3397ce60509e05da74ed0f373f", + "0xa58c2a5dd13e08ffa26a6c5e5eb18bd8f761ab64a711e928e6101512401ef2b1c41f67ba6d0823e16e89395d6b03ebb7", + "0x91318b564ec8b2d8c347ca827d4d3a060272aec585e1acd693b2bafa750565c72fec6a52c73bb3ae964fdaa479700532", + "0xa058db5d76f329c7e6873e80c7b6a088974522390ccaf171896066f0476742fd87a12fe9606c20d80920786a88d42cec", + "0x9838e07f9ed8b3fbca701be0ef32a3f90752bbe325aca4eaea5150d99eb2243332745c9e544fd1bb17e7e917202edab9", + "0x85a9ae7dd354f36e73baa5ecf8465d03f0c53b24caf510036b3e796e4764a2bc17f0373013af5b9f1b8973226eb58cd1", + "0x896a4ff4508d069a7da6ef7bed66e1080991daee8b227f3c959b4f47feaf75fd1b9e03d0917b247c2db11e105395d685", + "0xa36d9a6a037bf498dfc0e535f2034e6cd433c7b52e520469811eb2e9f04499a6ce40257d2905300df7d81f38d1bba075", + "0x97aac3c5492aca879b4c06db1834b30b8850a244d29296046a84c637d9580c8521ab4752ef814c96f255a139660d7639", + "0x8552bf592a84ab4b356d01643c90347377ebf1f2b38a8c2e55a3f34537b8c7dcbd62e6776d6c2114f2bc2d4344d1567c", + "0x84474ad163db8e590943ccd1dc50b4f444beb8275919b33f53d42cba89831e9d42ce2de52b26f4412e2a0676ce913277", + "0x900799dfaf5eafeb297c7b4f892438bf2a65ce04034d66f8e5cc3836e4eaffe782fba4f4455a0fcab49102a240d1780e", + "0x817176415e35ad4a204b9fd5771bae6cc270f6ff050996cec89efbe461b2940ae5dd3c6c7d7e31b1da5285b207efed27", + "0x965e5791c927d47569bc54ec9b4c5305788aecd87a26e402aabeaeccc03480df46f0586ca2e2a9918885cd03332af166", + "0xb96d9ada4b5a04a94807d71726bd557de94fbd44042d7dba40560eebe8658d1da49eba54499360619f3b2c38e8b5ed6a", + "0xa07b6d641a43e02e7868f30db4dd5069a2f221b4f122ce9b11eac04abadc4f25f3207f1d2d86c7935b1a3d9992ea9814", + "0x8250d4d8ccac846a4b1a9fa392d9279b5bf2283c8b95d8164c3c0d199fec8849eab85755f2a2a99d584a0407742e3200", + "0x8324cf49f56fc14162f9a9ebda1ebda0388d09d8688f1938aef7dbf9505fc119069efc552f68cc7cd9213f96fda2c6de", + "0xa98e6f1e85268dccbe3bf4e92c9f455c58dcb53de1dba3b78589adf2e50e79f8e245f956e0d098eb46f5d3746826c6dd", + "0xb103ec12f266b4153d67b54d8fc079357ee342cbe5008adc3e0689a7f788534c4601e60e939731f49e4a1e24fd589f82", + "0xb2d7681e866420413cc98eae67614d383943e3762d5742cb3c57e26157633c20880eea1209feaf68402d5d33dd699708", + "0x99fed0ae4112ec9ed74baac70d202a885aa51cb555a3886b49016744dd4017640dd5dd564998c4d842a9f38f3e004e68", + "0x95c35401314467219c8bfb1ccd1f1eae6ef4fa9e48fbea14f70d5315e67b16c46cd03554471840e4a5030b077d2a3856", + "0x8d029380e0c294400d6b8673a23aed43697cb6460fc1bcf217aca3b47cf240886644ed09521d6a05f6abf56f99722d84", + "0x8ef54d1dc0b84575d3a01ecba8a249739edfd25513714dd4d1941fbde99dbbc392f7eb9fb96690d7052609af23aa57f7", + "0xb8ad2b7af4812417aa8de8f33a26547f84bb84f39501d4b7c484cc8bb54c7e166c849b95240fbe459a4719a6e3bf1651", + "0x9858545de898721d19930d8b360cacc5ce262c8e004867a050f849f7a2f2aba968c28d51f24a9af56aaba23a9ded4349", + "0x94ea5043b70df1db63f9b66b4f9d8082776f721b559f27d37b45e0a84faf47f948d7c4532dfd854a4bac49fb2ec8e69e", + "0xa2fd88d7b15e3c2778f6c74470d0f9e1a1f979a4d58bd205361eacadab9973d585a6508e685e640b272d6f8a448eae05", + "0x88defd6bccd55db8ca84e3c8d0fc55a3456b41788f1e209d0aec19c9c70febebf3ae32cacaa1dbbf796d7ddea4b17995", + "0x88b8cde2449d5ee7de2ee2f32e845d27e171a51ef64f1d3d8a5fd7dbb9f898ea70eb7f6410cddfd7b7ae70ea8073cc2e", + "0x8e044fff6ec557824866ac76301b6d93ed19b7177aa6baa95046330f5d69b572b59200e3653cf2f2b559455e782e8960", + "0xb5446b4d6741c824885790d2d26258729dc0ba2f469c85a47d38886d933b785a4f38a951d37f3ef4bd5091c03fa3a071", + "0x956c8afa8056e9a71ab2e8be5241ddbb3a8b3cff2110cb0e7389493d9fa45e6c4b769ebef540a952db6dcd8bd55baf64", + "0x925950cae25615246e29d594ebf34fa7d52f78a9867338648158f2131e6eb4dc17e18f9db8a5fdd76d017b3a9798b3a7", + "0xa17ea4b43211ba990270c21562690b3ef154a46c3d669c4674c80bd424cdfa95d8850c8e882b8d06504f929cba3d93af", + "0xb315ec723973a138508afc387ef651fd8a8804f93975fc36c2eeb796a304eeb1508518d8703e666a74d14318253f526f", + "0xa995742d7433b3f230e622de23cb2d81cac76de54831491cc29768eb4a56da60a5cbd573e1da81fddc359b489a98f85c", + "0xadb2e89f0d15294d7118fc06d4fdbd9c51d3ecbcc23c69797e5b8197eea0d6cd1240910cf22fcab4ef1e2dc2dd99da91", + "0xb5ec9f9fcd0b5d176b643df989bb4c4c1c167112373d662fb414875662d1a93160dc0b5cdf540e8a30e5fcbe6cfbbd49", + "0xb1291b53f90aed275df8b540c74a1f9c6f582e16c5df9f5393a453a3e95624ab7552e93d6e2999784e164046e92ef219", + "0x8bc7b7b1a584a12d5ae63d0bbe4dc1b63c9df9c89bdd1095ff4b8e7c822bf8c1994c92310a3644033c7c9689f4b7d2b0", + "0xad7fc45506a10ca48f991714ecc055cea376c0cbe667f3b40ee8dad8446218835439ae59bccc474cf47b053748ceba6d", + "0xb134756828a5f5725c0b95109e09ca450e3834b127163a0aeeb544e63cc0cdcdf66f8ed98c331c7c98758f46af369a84", + "0x94535bf1636be0974b112fcec480ed8eafc529933f3065c40e417e608e43a392206cfde8bb5a87b720263446c90de663", + "0xa4df4f6efbc3701000fb072e5cbed2754b9ef5618386c51ff12f95d281d1b700fea81fc1365f4afc66a7c83bd0228fbf", + "0xb0336b3552b721087c7e2194976a9119aee13ebed9f1c3c494353707fffde52d004a712965f460062ec9443620716302", + "0x99a39d1d1ee4283b75fa8c1fa42b6a3836b734be48bdd48050f9b05e48db6354fef509623c6ec8d447d630a9b3352b77", + "0x8e3dc3583d40956f9e784e8bbd0b5e65671d2ff2a7c387b20fcb7da9b969f2d122aaf7f054d450dc611737604548c03a", + "0xb5068ec5b7bcb5d8583d51cb25345990f50d1f7b82fe535a6a6b17756355885047916f466ea3ab09eef5516bbf2dda90", + "0xa8284ec1eb1d21e693f31a6c074199ee85d8a8da2167bffab5fe240defa2773971c8437e358a18f7e58d1e2954f57f6f", + "0xaa7415639d29081acbaac3e9c6b059d68e8702db3f430b86bb6e220d476fa74841c875e9d471c8a5423c58b6fee3cb54", + "0x8afcfe6f65fa6e07c2cb3e1756c0ef2c589830be96edd50c3c248e3b17f51a4b08ba92ef7eed7991d81667ddfbf2bf7f", + "0x83b9c8dec8ca8f9b85f0e36c08c5523cfeafb15a544398e6f93b48b5fc4b15a0bd05c0f176a9c2469664acab8dffb0a8", + "0x82a128a89ea46b9debe5c903b950c0ab30cd7570b979ca911500b5c2cca5c4ee6b2c2fa414b5f28e367f4671ffce60f4", + "0xb79fd0ccd2629a361cd6f9307c02ecd4d1f07e4ee03ce4b542997e055b07a026cbc0ba05fe3da309efc58db2e401a8fe", + "0xb190751141093823b4b5324cc26c4f3258552f7893241201f2fca1ae9b1a1d4d4964a9abdde8642cf308ded61ce5ef09", + "0x935fd48b95aa6f9eada0cf9a25a573f0ffe039888b3410788c41d173747bf384c0ec40371bb4383ddcc7d9f2db3d386b", + "0xb9affe100d878491ff345636ffd874ce1f27852a92417694afce4163e6a80c78b2f28d78102fd06c3283ef273ad37642", + "0xa877670276d49ec1d16c9f1671e43ade11c0c1a1413755f6b92be9ad56bc283e4bd2ad860367c675d5b32ff567301fc4", + "0x8c660d16464878590761bd1990fd0fc30766e7e49e97b82ec24346937856f43990e45aa8ad37283cb83fa16080d4a818", + "0xae1412087da5a88f3ccc45b1483096aeb4dcf4f519ff3dbe613f63712f484bdd8b2c98a152a9db54cf1a239ae808f075", + "0xad83cead97a9c3d26a141604268f8a627a100c3db7e5eefaf55a1787ddc1dd5ffc7544e4947784cb73b90d1729003c8f", + "0x97c3140ce435512a509e6ff3150da385fdf9e0883a5dc7cb83d616ec8d0a0014e4e0fa57a4d12c7997cd84e07d49a303", + "0xa353773ff68f1615454555bf658eabdcca40a9c7bced8537ea6fa8d54764fd1f032889e910d2a2a342835513352e2d2e", + "0x89e8df0c17a36ffe08149c2ef8b27306d04cdf437135aaeba697abc65e3c8e91bcf1817919a8a826acdbbe7dce79a18a", + "0x9928c2da15ac6cb20b15859c22508cfcd452c5643cd22eb84abf5f0a1a694fdefcd8fc329c9b40babc52630743d6b65a", + "0x99d837b556f8d13108eef6c26333a183f59383b39958dd807b10590c3d37f62ade6c4a320ca2e70567e0218b0ad5807d", + "0x9272da080e4aa18720b634640b01bf1fe506c7c8a89dee8759a53e2ca5cdbbd4a4f3aca54924c46b935362cf1eca066e", + "0xb4d39752c882de1c1daf3854202c1d58c2bcf35c882006eb640fe54a97be2655281cdb91c30d1a41c698617c2cf64b01", + "0x8bf827f4a7d47e07374d338a3d8b5c2cc3183015b5a474b64b6086fcf0cdcf4852046c9e34d7917d69caa65a9f80346c", + "0x901bffc7db9c9416e06f593a76d14f6d9e5dea1c5f9557bd8c93b9e70aa4782bab3518775c2a5b285739323579f7cf0a", + "0xaf7e204388568627ca23e517bcf95112ca8afd4c6056b7f2c77c4da4b838c48791191565fd38398587761c8047d11c47", + "0xab2576b5366e6bd88b347703f9549da7947520d4e9de95d7e49966d98249406ed9270fe69347c7752dad47e42c4ea2f4", + "0xb12e3b228b761dedd99d02928105494ded6d4fea3026d73d65ebffa2e85e2cd75b6d091135d418dd95ac102c22b5ee31", + "0xa20b4a752685d5e31ee7e2353c8a1b9a5265f12bb775004d282a3ecd9deda44831bac1ac5151646428b66909b2a423f5", + "0x91a1d4bc0062a86cc6786a96fd3eb4436d8a4a187b7cbba02190d1cd6ed3c3797d9ae7d6ddc413f1c94a21f62bd04ef5", + "0x977f18da1a5df5cfdd0276f583cfba2b2a0fc6139520664e20068f8dfdde33e29d179abfd722f142448f4677aa47be6c", + "0xabc3ece90f0f7b1d80fd917de27ab0d88cca584ef959da520825e54cb5a71336b15f8b348532d08d47a6fa600527ef25", + "0x888d36a2c7cc13a1c1aa338a183a74a1f57713e76cb825f9837f43279ce4741999b76a16928147537bcc20f2e0195b0f", + "0xaf3f5dfdc2dcfe19de893f385f39f550cb1dab67c2e97f1d5fa735e5ec96d6680066803e8a0eb010dd4399f654195513", + "0xa0fb4e08ff56530a940a86c28830956eb6dec2f020f7faaea7566faf0a4fafe0cffe01480e87763ec22f201be51a6451", + "0x92343c5b107910b203c64a79c93d354f7ee5b7d1e62e56732386776e275285561cb887019cc00d3fdbe3b5d54460bec1", + "0xacfe7df83c4624188a1011ad88c1e1490d31a8a8c8016b40aebcdd7590d9c0793e80d2d7ce6a7048876621c252a06a5e", + "0xa7da001dc1e33e0e129c192d469d2bd6e5d2982eb38f3ba78bae0670690c8e70f40e8114a57bd0718c870ca5dd25b648", + "0xa903de5ff97dc83628290d781e206ef9d7c6b6d00cadc5bacffb31dc8935623ab96ade616413cb196a50f533e63641d6", + "0x8f9658d42ad14a60bbf7263f6bd516cfee6b37b91a8f53715d69f718a090ad92484061c2cef999816760a78552fae45b", + "0x8c15b72b3d5fcb9ffd377fd67d9dfbdd706593fba9629002639973db12aac987bd1db70250ded31c88e19efff612cdb8", + "0x88a2a4034decd854fb557960194ff3404e239953818a8a891bf72a0b26a8e570a65c4a630884de991ae7452b3234f31a", + "0xa09cae5c4c190537bf1dd75bd7bce56f7b799762af865bb9d1ee970f6a133c27cce0dd0f14a0e0516ceac41054e6998f", + "0x9760ebb1b40f9a97530c3b940d4ef772a225e5b63bf18283f8e302b9436c5209f6294980fd37058060e429fb7fdc3a56", + "0xadaa9400eb86d857dc591b25dbe3bc8f207b69e77b03cb5ee01f7e4b006b5c8f6ba2b51b5a45687479885708509363de", + "0x949efe6b00b3248846747a9ad4a934d6e4255994c2b540a59fbbde395fe96d69bb67908441cfadd8c8bbb561fe52da03", + "0xa19a45504b6b1dc3a0fe0e6a1384734a3dcd5a7cb8fb59eb70e49426c4fc44946547443d558e5719a04884ab3a2811ca", + "0x8934c9ee21e8d1435426fd0f64232a0670a7946ec524c054cd4f2cc8b1be9f89cc11002ca8aebae646a2050d91716b10", + "0xb1150ff8ffb34ffdcf7d603348c0aed61e5f90ee0a1b814079fc2a41325c75f2f9ee81542797ede3f947884266a772e0", + "0x86ce8cc7c1f92af68de2bca96ccb732f9b3374dad6657dfd523a95e8a931a0af2a80df74098514a06174406a40c16ba5", + "0x90faabb9ace9e13fd9584932846ab28a618f50958d2ce0d50310a50c3bc6b0da4338288e06e5fcbaa499f24a42c000d5", + "0xaf4a935c2d8df73332a16dc6da490075cf93365bd0e53e2374ef397514c30c250bcac569b6df443985cf3720a4534889", + "0xb7f948ee90f394789eb0644d9f5ad0b700c8e44e5e9ed0e49da4cc18483676d25740710b1c15a557965da635f425b62e", + "0xa917913091245beed6a997ff7043ecf60c4d655c4db0b1ef1c704fd9b0e1ea1335ce8b9f45d6e120f81805ce31555e30", + "0xa48099da8406399bfb1ba834f6f7d864111d0036969a5cb64089947a63dd9467d3857b605e9f57f5ad5f4ec915088d9b", + "0x9784c3f9be42eed354542b1446d734521f8e3f01cd9d495ae98f2e4a3a16767fe2ad909e0def5d9a6267f3fc6a172cd2", + "0x8d9afaa323847a3226ad7d7b60d87322ffcda2e4a8df89f58a076f7972d896588de685a2e155e243bcf9456b0a0d6d1f", + "0x994413faf0b843f4ec1842c706c45ea5f24351c68674a27887bc8b182eda756856e507a4e8bbfd937e2c4c581b629ee6", + "0xb3e72d9d1ddaa00c7d22f25462d6e9f2faf55e30d138dce8bb1517eb0b67132db758668aac26164fd934d732633bdea5", + "0x8e95875e338f714e9e293df104f0ad66833bbd7a49d53a4f7f5fd5b18a66a61aa0a0f65cc31d55e0c075e0d3e412cb90", + "0xb980091862b1a9f9334b428eae14bbf1cecb4849e3a5809773b0d071d609727270f6ad97f329eca896c178ce65883db9", + "0x915d7ae5ae780bdba27ba51a9788a8852a15355b569581d1f18f0d94bcdfed2c1ed5a4f58e049e9825cda11f92b2c2d4", + "0x83e581058edf9259d0b06128282327cacbb6afc939578223cbf93544599f799a8dce1fb21d52464f990a877086f42506", + "0x803612a38b6f6efb97941997e101ac1878e192456f8fbddb3359aa7f3023434ed8fa92e60ec8e7b4473b1948850e4311", + "0x864a1bf4ac046161617dde282e44ab3cc1843da01a09ca58aa00ed00eaea9351a07a9ec16d910819e7dcc28b8d2c8ada", + "0x922eb142845975d5f6f7dcfee6cac8c299b3730400e6bf82cc0bdd9888de21de9d9f1530640f702c003e1ed63b140cc7", + "0xa7db03c5be647dce1385ebc02f4825a654447fa8c4c8d4b22e635dbdd2b3ccdf219384e49a80cfb1e9e6182b6e4227ed", + "0xa167289ff0f0967bbab6479e4a8a6f508b001bbe0d16cad36ab4c105ad44f3f180e39a6694e6cd53bc300fe64dac1e8c", + "0xb7766431f6379ce62cba22ab938cdbb1b0c7903dfb43980a417e0ee96c10b86b447241e9dd4722fa716283061b847fb3", + "0x90cda18c5d66f5945c07c8c7dc453dee1370217ccb851bbea32578599aa669b4dd245dd8a9711b27c5df918eadf9746c", + "0xac690cd2af39932874385fbf73c22b5d0162f371c2d818ec8a83761e0a57d2db2fca1d757343e141e1a0348016d5fc44", + "0xabac820f170ae9daa820661f32a603ed81013c6130d1ca1659137d94835e1546c39a2be898b187108662cdcbb99d24fe", + "0xb2ea5a5950096772f2b210d9f562f1a4cfacc021c2e3801ac3a935f2120d537471307d27b13d538dcbf877a35ff79a2e", + "0xad94af4d0699cd49ba8ca3f15945bd09f3f7d20c3aa282a3113cdf89f943d7793e59468386b067e3c1d53425dfe84db4", + "0x83788367ec97cc4bbc18241cbed465b19baa76fab51759355d5618067009298c79d0a62a22e2a1e6dc63c7b90f21a4a5", + "0xa3e142d879096d90b1e0a778e726351fa71996466c39ee58a964e6b5a29855123d4a8af47e159027e8e6be0ca93d9955", + "0x860831f8d3edaabd41be5d4d79c94921625252aaec806251fb508e364e39fde8808d38b10d557e487603a1b274c9bc3a", + "0x88da39f334bd656a73c414ec17dda532059183664bbbac44eb4686c2601629ef8ff9da992c337a842e3885b684dd0032", + "0xb50addbdf7164e8303f33de5ce854d6f023d39c1c1984b214d9e5fb6f6001cd5bdda816f048a438ff3d696872672f805", + "0x999e58c4c69a912b84561cb09610e415b43832beeb95897eca8c403ef4754f4277754d492eef3673afd4362f50060fc9", + "0xb88ea0f60f8119c5a1fd9294796d387472dfad22442b29659713d1d88e7d854cb7cf5c9ef773627781188626bb2fb573", + "0xa068b3844e9dbcf74b54fd55904d56af754d8ce4c619fead7a07f9bfb9d02118db7c512ccec2489d2a84374ec1d1fb6d", + "0x871dee023768636003c799e6f6fd8d31315a4c0da7286345cd64264a016693b3485e0732be1bbd34dd5fa04dfa58a983", + "0x8021e8f508680df12e4a5a1bd49f2d7142df65158b0a7198ffa83abd16053a542fb93ffc33e5279020ba8c6a26feacf2", + "0xb5d3cd64df5bc965228b0bd4ce9e5797c409f7b64a172ba165e44a8e4b38e3d5fabc3e0b9a19afbfe427f887c40a315d", + "0xa54fdebbb594bafcefb1a03697711e0091c072e1cc24fb441fefd4e0a0518675a1d7b0966cb8294051d7ec0ac175d0cd", + "0x93922202337f72969d6d6e14a29c9c75e0420dfba712029941d1504b9f6f9761d706cbc0652cd09a1aa5d22aec766af1", + "0x9711ebf1c7c7426190d4afd5dd03b014a456bbd9d90ed101623866a280550df26a629dde400c03ee3699f7d827dc0bb9", + "0xb4d686d8bc5c1e822a50124c1cc23c6bc3a1577a3d0b8d4b70d1797418aaa763283c09e8a0d31ae6d4e6115f39e713c4", + "0xa533ea2ac683e4ba07e320501a5d82a1cfc4fa1d65451000c3043f0fdac0a765cc1125d6cc14fe69975f3b346be0fdde", + "0x94ee563134fe233a4a48cf1380df55ead2a8ec3bf58313c208659003fb615a71477e5c994dc4dcfb2a8c6f2d0cb27594", + "0x93e97d3f3f70664d0925be7aee3a358e95ae7da394220928ae48da7251e287a6dfbd3e04003a31fab771c874328ae005", + "0xb57440d34615e2e7b1f676f2a8e379e1d961209fe00a0cf6798f42b7c28dbd03172fce689305e5b83e54424bc3f4a47c", + "0x97644084c6f7b4162bc098bed781dd3af6e49e7661db510975528f1dea8154f3d87e979bcae90c3df3a7752eb0752889", + "0xa923b27b225b2a6dd5bdc2e3d295b101cac5b629a86c483577e073cea1c7d942c457d7ff66b42fcf33e26c510b180bc2", + "0x86698d3b3873ed3f8ab3269556f03ac8d53c6e2c47e5174ec5d14b3ed5c939750245441c00e2e9bb4d6f604179f255ef", + "0x87946826d3aa6c7d53435c78005509b178fdb9befc191c107aee0b48fbe4c88a54cebf1aae08c32c3df103c678bad0ca", + "0x860864896c32b5d4cb075176f4755ea87fea6b9cb541c255a83d56c0a4092f92396a3e2b357c71833979b23508865457", + "0xb78fa75d687349e28b4ddfe9e2d32bb6a3be13220b8f3ff1ded712088bd0643da9b72778bcca9e3b103b80097f48bdd0", + "0x8a188b940446598d1f0e8c6d81d3cada34c4c1ae0118ec7e0eacc70d1bced28ae34b99667d5793d9d315a414601c3b22", + "0x842ac6f7dc14191ab6dddffcbc7cb9effba42700a77584aa6a8e17a855cd444c5d138f9d61bf55f43c6ffbcc83f92bc9", + "0xb6742902c3d145a6af9738c01cf9880dd05c85f0d0ef7dbe93c06fdd6493333d218339ebc2a02be1895436a2f734a866", + "0x98bf18488483c627b7181b049d3e6f849fce1f15794de59dcde6e5a9b0d76fd484a46e48822a6a93001d3aa12f48bc6d", + "0x8769cac10bda8c53a1c19419ef073a5998f73dcf2ba1b849561615a17cbc0a49bfe3eb4ff8801dd36a22fa34b9a3a7e2", + "0xb45c084d58028fdfae792210fcd183abc4ffddeb4cf52ebf3f8a50e4c4eec2a2758f1241b0920bebcb24b757c778577c", + "0x85c1216eec8e1fbc1af9b36b93c5d073a81d5fba86a6daae38748ec1573eacc6bef209e76c87a6efbd7a3f80e11d4c3c", + "0xb8007e34bb3f927ec06a050b51e633d7eb9e9a44715d5b39712e69c36177a03cd68391090cc3293098e54f6cf65f6caf", + "0x8e85527b27c9152b1ba3fdd532a76a79064ab097570508f233e09978761dfe3012d537411b47d0e4b65265eb32cea2ae", + "0x899779f3c31a20b76068ec8d59d97a64d2249588ddfd69dcbaac6bfaee8ce0ff3c5afc4e17c934ae7cd041b760eb555d", + "0xa5dac3d8f5fbef018509612e25d179f60d2a62451c76426bf546e9666fcdc73263d34aa6fa7e2bfd4c9947bbf5095eff", + "0x896900eeef9be2b2e755128e7b1c436af6fb3984f1e66c444bc15fcf3959013b4902c381f0eab1247f878a6ebd1f4ee0", + "0x8cb17f4b0af2e9b2cbb56f46e6a5d6874ea0daf147aae77303020b4e592ddc92e0dd058def7da96258b3a68b223bf22d", + "0xa1b6d3f09a9fa7ecc021ab7c5396541895da6e9bf1f9a156c08fc6f2b815a57f18c337ccfe540b62d79e0d261facb2be", + "0xae70888811434ef93da60aeee44f113510069fd21161e5bb787295492eb8df85103794663fc9305f04adcbcf11ff0c5e", + "0xa84bbc8624100acfae080ba8cfb48fd4d0229a60b62d070bd08fade709efc6914dc232d3f7bed76a59204f9252321aad", + "0xaea47d54652abd8ca213cfc623c8e30780f37b095b59ac4795252a29c2b6bc703a5203acff8831314478b8ee8771d4d7", + "0x8dd438eb8be14935f759aa93021c2b24e1d588f7a162c42c90ec3a647b0ff857f60e24c0a8953eb7bb04e04be70f11ce", + "0x922b07b5469680a10e7532766e099896f4dc3d70c522d8add18f5f7765d4ddb840df109146607b51ceddd2189fa7b9c0", + "0x83ef6ebd0ae6c569d580093e8b0b78daa964760556272d202d343e824c38eccb424262e5b7809d3c586f9e2e9c5c5f22", + "0x97f98bd357db6e093e967fe180cf67ed09fa711580a5ad48f07cf095b2e8fabbe6319f97d1f15d62c0ec2227569d8dbf", + "0xa1953a4a22fe6c2beaf2a5e39666b0eb53018af6976e3a7aab5515550ff2efa89400605a43fb2c4ac1e51961dbd271d8", + "0xa5cbd67f4c0bc98e20aa74c09e6f5fb6f42c08e59aaa477b4b4e61434c8884bc14f17cf11faecf46dc4b6c055affbad2", + "0x87d96818f2c4f12fd7705cf4060a97bd28037c5ac0f0cc38f71189ec49361e438ce863e6617651977708094d5336d1da", + "0x85e7c2daae5fe59f8a1541c94df50402a671a17dbb8838113fa4b7aaff6114cf2bb5969410cf21e6a162857f2f7a83a8", + "0xa19575083e1731bb04bb4a49414e97aaadb36d883aa993d1f6847db50007315444814740e67e10177a14e0e074fd4c7d", + "0xa00ebfb5bcc3a6da835078189038a1e56b7dab6be74332b5ff7440e53b0f9e1eb9973effecbbf37000021fcf50c7c1ff", + "0x8969d7943abd3b1375fdfc7d6124dde82b0f7193068ed6ec83bcf908734daf3487a6a30f7b322e54a4818ae5f86d91c0", + "0xb959c8d210fa43af9b20d1fe0ea8c4921280eb4544ef6ea913309ff9d61c9327096707e84dc1662960519be8e7d080a4", + "0x9011d8ac651c42e0cb03931a9e960f58e02524c6b666047525e3b9097e9f35fb2b4b278efcce2bd5ad463c6d7fd56694", + "0x937e3b22ed0fcdbd9ea5a1b97b84bbe86b7f5b2de3866a930611112f2217f4ee7d9822c4ab1253823f77bceeae0c8e10", + "0x828997e5d121f4c305e018a0a0ba338bd6a34a7b4dc3c5ceab098ee57490311c130e2c045b9238a83908d07098d9fc32", + "0x8d114808eac0f2e1a942d80dad16756ec24f0276763cd6771acb6049472e05a9bb1d3bbd5957f092936b415d25c746b0", + "0xa063c5c26267ae12887387cbebbe51fd31bc604630b3a6e8e177e71d4f26263be89112cd12d139dd4c39f55f0e496be0", + "0xab1e1582c8d67196d10f969eeb44e6e16214f1316aa4a2a821f65ba5834326da6cba04373eabfd3b3072e79e5c9717e6", + "0xa17b1dbaa11d41457e71a9d45d032448091df7a006c1a7836557923ab1a8d7290ec92a7a02b7e2a29fcea8f8e374c096", + "0xa1ed7198da3591771c7c6802a1d547cf4fcd055ca9010756d2a89a49a3581dfe9886e02ee08c4a2f00b2688d0600509a", + "0xaf09aa60c0a185e19b3d99ffdc8c6196d8806169086c8ff577bf3801c8ab371e74165ba0f7329981e9252bfe965be617", + "0x98c04cc8bb26ffce187fa0051d068977c8f09303a08a575175072744e0a5fb61191b1769f663a426c30d405515329986", + "0xa542bf1c9c3262d488ea896f973d62923be982e572172e2461e0146190f2a531f62acd44a5e955a9f1e242b3e46d63ae", + "0xaef7b7f30efd50e4a66c87482386f39f095bff6108e68f74fd3bb92156c71c75757912b111060cdee46a6b3452eed657", + "0x8afe1e0ccd00079702f16ab364a23bbbd3da1889d07c4f8cb04fd994bf9353216360dbd364492932bfe20b8b69ae8028", + "0x9896c690999db3c08cd7b25efb1b912c3e0f976db98a3e830f086aef93222d06ce570a7b2babcd7c81d8f9955169669c", + "0xac7bcab6a281468907ef1ea8a6c1cd624159c88839131bef6aa0c22f331fc87ec6128a2c2a333fb79df549e4587e1a12", + "0x987935c08a30b099d19f96901315a2e60591baf898581c40bf5eddcda806ff24a4536e30ed1e6c0b128a83fc77b6e81d", + "0xa0a6945bbede3bb09a4a09ef27baa20619d3e15af5673b9350601bcebe952597c989870746cf75767ffb73b32c6c9c6f", + "0xb0f5590079f0a0302b08a0cc1b7a5f39cc6900c2a5cdc7baa333d8328a731b2df5dbb67e27a154d3c44ed1a795fc4adb", + "0xa7294bdeea210e528f277f3d50e89e6d79950494478998181ecb38de675020130256f2f2a075899170be964d478458b0", + "0x8ab3041b895a631869b439d5599a66facba919226ca9b39d915f19d59f9fc82393ea781377e9bd3bcc5a310e41376914", + "0x8da399b59151fd48b2579948bb82698e3c9804d70ec7d6f3cc7e82901f9f2de5ee850349a7d6f43e5e9ebd47bd78620f", + "0x80e8c32de83d1083916d768b11a982955614a345d26d85b457f2280ff6c52bb776958add7c1c8878f7d520d815b8e014", + "0x81bbec7bd99d2917d2dcd8a288722fb33ad5a4bf5416fba8609fa215fb80e0f873535349e7dc287f892aa56eb9e39c4a", + "0x9665796fe04c8519206fba58496bc84a8b9113e7ea8e152b65f7f732e88beea271dc97b1ea420dbc8257cc4b18a77463", + "0xa97e342aaaf693ddc87e02790278e4bb50117af4413cd703bdf3b7cad2d1facf31fde1303b43ab2e0265467474f97a8a", + "0x925549ebebed348886e37773b05cd8ad04906eca4536bfed951d1ee41b3d362ddc6e1a302c21ff3a2d1e70e95117922c", + "0x818fdf74d7903502101551bbf48d3c7819786b04b192d9e94362d2fcb85760d8b6f45165a5443aa5221bef400525ddb4", + "0xa9d29de7e8fd31b59f4a087168d062a478b1329cd3c81c31e56de4fb40de7a5be9a5269ef0be452c487443a0b097dd50", + "0xa85286ad573db4c9aa56221135da1e31d742e0f6ff01d6b159086d7258f78b08dad55ec8eb5c91ee9d3404b2eeb67e1e", + "0x92a79b37db5e777f9ebbebde24a95430a199e866e56597c7d0b0e7fb54c7b092c2f6cf61fb24470ddf250cf609898281", + "0x8d79f5ca67ed67d52c82949af342a9fc60fb793c47c76d84b4863c550796fcae2dd59e285897c6fb96fe31cee1efa62c", + "0x8ad2e0bda03415ab86324992bb62dfa3612d2d003765bcad1468087c27971d08bdbae5252681f0115a184f4885d444e4", + "0xa08815af979286538c31b4aa5ec805053790af1ca58a8c4341be51136d094a8a05e569d876a079033298ad355ccb7ca8", + "0xb96c2978d0165d619d08281d295e90df78bc2375d0afbc3142ebff9c2cd4b0f0aa97a9a0e3740bc4dce0ff8a9fac8252", + "0xb7752cd0e582f35ab0d0036ca9c0a9fe893a6ad325164d78d865a604a85d3d23729e0362553e8b8a3d51816beeaa30cf", + "0x99cef1fafc29e7adfe247c753c475ad4bda7a5f9558b79c86e8a65968ede67adb38dc30071925c9d66a13860027a6735", + "0xb9f6c65af178c791b6137d71980651fb09cb5b42f268999c728c6e129985a9c7d77b3dc3b50751bd29ec9ee0b3111dfc", + "0x8d73ae61fff5be883a281782698075c5650083f00399992688738856d76d159803be0059fbd9dec48f4f0432f0590bbb", + "0xa8a4a2865226de9bbf19e12c7e75318439fa6cf1cbf344d5e79a8f363439d3bc5bcf4df91b54581e7866e46db04eaf0d", + "0x894582aeff222e145f092ba15c60d3207340c38f2c6792ee2ab4d82d50fb544ae366c2985cc2b6c2f970bcc5f4b46385", + "0x956014ba2d20a056fd86cb8c7ceeab9a2c6f905dae24fc1c5278fa5b84335148ebdefec5dcde8eb9b084700724fc93d7", + "0xaf217fe2b654eff6d11a2a79fe0339a1d4cb3708b7be9f09d852158b5a44b4f9b04406d6d67c4f144fb6b69a41ae9d0f", + "0xa90752a784bc00df94d960e523f5596695d16a534fc806179e0f878fc0e82a91b25e758e91a165debd815dd1af5f1028", + "0xa697606fb32979549ad822b31df8eaaf50de4ead984439a0a33e955937d326519bb9f62c8243ad37f764655f8d32cc80", + "0xa3ad4a30922e45a3e665551e5611384f1c2d414f6fa806184b0c826af05f014dc872585e255543794ee41e43cdadd856", + "0xb29c255843a82ea74a013bac6c36a694646e61e6b9cefc4c130e2ee261e3bb5da3e0fe3ee7e6fbb009deed0530bc1c82", + "0x87e1cc7febefa829cf050aa2aea59385d1048f8617abba691f7ea9ef58eb90ad12eeb9c439af228b0e34897ba1cf1b47", + "0x994d3222f89e9c8c154362190be7167c8c2662f0cfa9d50eb4d8175b255ff0de09dc548ee312fc8226963c8c16f43e8b", + "0x8f1a980be640820f2d1e953264ca4c30330878971669852be3d5d6b41c488be1628b935388bfa2bd4de484acb0fe661d", + "0x854d90d0721579c8c88e147a4aa83553c960617b18075f8224b975562dccb30b0e02e81fa9df7070f356a0eeffc3b14f", + "0x8e156da9d4330a03e32a25a2f0b861fd3ea5c719fa4f834119baab6e5fa5236a9baaf0d44147bf0841418900037f6eac", + "0x96586fc49e53a6799242ddf617000db5a0ad20c6cb1686af2102623d64a71aaddb8e468b15fa6d100d0384e448548db4", + "0xb44d8d85c8df95d504f82d597f8c515866d4d4a326fa1b816dcc5bb0cc4ef1a52647aa5d2e84c62e194c01cae0885d21", + "0xb75c43e676a7efd199f8b32ae31f176ec667e714df355e9eecee97246f72af5bef9c5b04c11e7e90fc37bb9163f957ec", + "0xa49835ac0565a79f6a9078cf0443c5be20561a68b448289589721fded55188583f1d301925a34eea647f90a6e66c6774", + "0xb47c17ff6824a00b8f29df0adb7f06223208d062bd703b0f763c6eee4ae62d4217eef2da4f4dde33f0b469c2f2db9e42", + "0x957cf039cea6f6d41e368e2bd0cf77315938a0738f15ed9ca342f0a28658b763659ac1d1a85ecb362f13de12b77bb582", + "0x903a52f8d2439fa63f59e1e9aba864d87b0464ded63814474947112375236a6f84e8fa003cc4433c8208d80e05fbd1b0", + "0x8afd524209ff08d1eb6312b078f7afeb8e1155af649e930ab711dedda226dc2db6b0354aab9652eea7f433f90015bf7b", + "0xa95c3c9277b11bc8fe191773bf567641be57c0549913b973fb18740ff9cd7b3f7ce198fa4dc1086b2b8a446012459193", + "0x9455ce8163fce04aeff61e7808ef3aac4725e51404f0858fe5d39d7344f55dcc7871ca332aa5cb1a63a4399529e48907", + "0x809fa35b6958f94e781f2c584438b33f5ed528a6b492d08960cf22ecf63ea3aa1e2d29bc879e17296e0a6cc495439cb6", + "0xb0f50774de212dd33e5837f6b496556215c665437e657f674fc5117e5c07dadbd0d057e6ac4c42d50a8eb81edfebf315", + "0x844c65e263891d0b2fea7db6934cc4b7fb6bee2c1d0b9ab4c47f2eb3e9c5d7197dad828d38c54139123740151420280b", + "0xb13c78c9efcbb3b28eb3fe0b971380b7d5151c80948a99cd93c78b4c3ab0e86df6226a64d91e0a2ea4a1c0a46bc0404e", + "0x90300a541decad460c348b8f4257f7a29687b2362ebee8d92fd03cc0e85b285ccb0ab1cb2ff5e29c5cc5295e351017cd", + "0xac49b409ded770c6d74f6e70104c2cdc95b7b90609da0743c9923179e8e5201ead03becc0ab10d65b3d91a5be0d52371", + "0xa257b815bd8289dfdfc21af218aaba12ccfd84ebf77642cc4cf744d9b0174ca0b0d7ab2a545c2a314fd5f63c140f41ab", + "0xa34778d8446e4d74d8fe33de64b2694ef1e50bc140e252af6eff3ce7b57acf8b6577a02ba94b74a8ae32e5113cf0a29b", + "0xab9e935bcf0d8607e3d66f013d9bce7909962cb7a81174923db02dc89e485c2b1c33d6065bdc7bbbe0450b5c49fbe640", + "0x94d2c5c5c309c9eac04be4636f61bc47fd9579b47aded57cc6c736fefb8dfd8f8a5de32210f7baf2052d04c0219d3b4b", + "0xb8dda9046ae265214086355101be3460421f7cd0ed01bde9c1621da510941d42bc93cd8060fd73f374fb1b0a5f38d45e", + "0xa6674649dab5f92ab9fa811d9da1d342cf89ff6eff13ad49f4d81de45438e81a384098d3ae5ccce4c67bda5dbe246d95", + "0x8d619f7564677bacba29c346c4ef67c211f7a3a14c73433dd1a7692e16a7e2562f1d0532454af62fc04c2fd2bb1789b0", + "0xa2b93d2fd4c707f5908f624a0fc889e20164d3c61850af9125f47a1719757a6ce6375aa1910eafa4c1e8b6e20c312775", + "0xa07d5585447654d82817ef4d199984542328b238157976eb9a267f0bdb2229acc25aee510be68f65a312b68fdd9e0447", + "0x8ef55cf95e2b24d8ec88e4136399a7763bd1b73d5e90ea45e9845123e9d39a625cc336e9b67988374b8ebcbc75f2ed21", + "0xb62c1fc32e27c767c461411b02fe9aa44a86586e1427406f4ef0b346d077db91952abce79318b382ec75b7be23058cac", + "0xb252900345f5fa15a4b77fb6af6a2d04db16e878b7bd98005333f7f6e3c8e6e46cf38fc5d1b2bc399c5c2ff4af730dc6", + "0xa4ab5ac0cc15d3d17b1747c6e3133d586870eae0a0d9c8fa7fd990ebd4fbb62e9090557ca2792a6bc6271856aa3c9a05", + "0x8e706b3f2e902faee10b22742c6c33bea6f670a8937c243db96885143c1db5c979e33ab73a38359b52b8d668ccd092a9", + "0x8a6792190ee6c959d79f60c22980ca140c638d88d75660adaf9bcbe6dc4692ab5f01e0c460170f09f74d5e582e85ff1f", + "0x97ffeedfc94c98ec85ea937e064d7b290a326838e62cebd407facd1ab4f08d9c0c109d79af7cb6170fccfa6c8243c127", + "0xb79970b67c09453614ffd83a0c923c17f857c6ce3c87a356298f8351cab0def7ed83efd4f6638f48df67e07bef4ad9d8", + "0xb90f1931c7cf1822cc0a97401119910cdfd0482daf09a4d7612e4e05046295cfb4cc50d5214b31676bb1a1c9d15f9c7f", + "0x922921ad813c01fb5d12fa7fb7ed8e0b0abbf7b19affa190b36013c55b88fe3c7df0ae663c970eec7725ba37b95a7cb7", + "0xa124f33e7f28feabb4089a063a08d52b7395d24eecd06857a720439dd9414b7073bb86fbd0b04e7bfac62d3dc0fdb2f2", + "0xb252fe50bc6677c004550f240fe670974a33ffe7191ed7675da6ac36c780c2f8d02be7da5d92cbe2d0ce90147847f8b1", + "0xae5f8c9c56070f919f3df2d2284348fa4b2e39881f7bc42c9b2f5b7cb1ebeef8ecac000f37329bbe04cc1680cefc7f4e", + "0xb432a4575caf7337f11eecfcbd34a6705d0f82c216301725ceae2b3c9df20fa53d1ebef65513e305013d1e0c2df522b6", + "0xb7c016fbbc4614cdbb12db1c9ac41f9a45d5e5ce82594d568a30cd2c66c3cc9d91a2c959697b67c582a0913de661505d", + "0x8f6f3e5e0347dddc1b2a34ec0dbbbb7cafbf976f19c9c902efb5c1427d1bbd4b71abd9f3fba20dda75c35a39393c989f", + "0xb0042a1d33a1ee9fdf3fad2299b8d70c4f1862d8393b5ebe3ac2189a2c5a58bb826128cd7a39b70d524a6dd976097e26", + "0x85297c4e8ae8d9b44c3fe51aa926c77d55db766c2a9f91b659040de36e34c9a4fc6f44380f8d61704498f6fd52395a49", + "0x8c61a988b6a00fe5a277450f30bf6daa932e42a2eae844568e3babf8815e09311f3c352dae6eb2d57a98d16b7beb2d22", + "0x990be28aaecd932e7edb2a97b9be2789a3905cb88737b1c79881302585801c69a3dd5fb230808b39db1352fc06e0b4a8", + "0x82fd14bdb335aa46f022dfe0ed4d631911e6b6f5eefb10d11e9e2e02a7df55012ed8162249d10b58eb76ced5a7b06cda", + "0xac39cb058df764e161db9c39b185f09aa210bddbd66f681f1697ddbe6b305735612d5dd321d3ffbb4876771bdb321e2f", + "0x858a3f7e57ccb81387caf8e89f9b6039e9aadeab06886d8688fe6427151a59ab2e77e85ba850c67d099965426c97779a", + "0xb57fb9ea623cec432946819937c6bded0b5d03c8c67b52b44a4b67d34adfb055e6cabca67a48e4d859b4be45162c5083", + "0xb84d2990b563d6d7fe1f4c1894989db25b81745090b94b1fe2ef708ac3b2110ef93d647820b2a51fcf78e3f00fef5412", + "0x817d85b9f5e1521733d2b1fa6d4f4957ac445dc803f97fc495e20b819b14e651332f9e0573d684b854fd47824c53f0e8", + "0xb09e18e97e93a8523101af594422fb71afc5b8826002314269016fcc1b44002d91bcb7c90d923d460f0cc03bddfe9af1", + "0xb867cbede82102de7cf6cd0dae68506869576eaa66c3fc806e73585310602682fc912dc37adf5ff6f0f34a07831735b1", + "0xb1126255798368b692f2796a3470ed16e5ffdee2d8c9e0f7ee3d2e92950c3e6365c32895171c3494aff2a6d6356f7e25", + "0xb05f0a0996dec16335c770a5df3f0b08e20020c838c2caaa1d3a4a2490ede98552f5de349de2ce6e4c4a839731d80919", + "0x98c512bb91c8fa191120ddf5d63c88076581cf41e15eec3c168822f12b3dd0ce4d6df74a7e3093d3e35cad1cb3135421", + "0x84ce38fd97f7f90012c2c1e59a67bf9f465a7ccfb6f308bdd0446cc82b8a26ff7c30e5c7cc375011718cad1b31adaa9f", + "0x93139db52c9fb96dee97a0825f21e34c5d6d36838e1e42f4d12d01eacbe94426c85a811fe16ca78e89e08f1c27383d28", + "0x81454037b1e7a1765f67e4288b8742eebf6d864d9b0f508ab44fa3243168ce0ed30cb5f33dfcdb995cd2c2710ff97a6d", + "0x828deb2a26efb2ff1842f735e2cc27162360f619b6e3e27a85bedf384912d4726bb2759a3016937973092ece1bf90540", + "0x87e5a7d4e7bd301078f625d9a99b99e6e8e1207c9f8a679f8ebbbfb467bfa0b5f7ef4a4d577c7d2670efa88221153012", + "0xb9dc9d0ea48deee201e34379447bec789c8924aecd030eeb93db159af77eff230976ef60ea9f4b4a9e9e95c1f9f4284e", + "0xaa6528268d46bf0627d87d58e243d3ac34b863513c725908a2617e4c6a46ccb1d8c8334bd6dd0eea7ffebec44259dae5", + "0x8d26c9ce07293f6a32a664d31e6df9a7ace47e6c38001635918efd9872aceab62de7757b13b783d422eb67bd28ce7bbb", + "0xb0d3ca88d9829a7459b89b0dcbdb8bbb5180b00d750bd959bd110f53c2dd5d4db554b6005c4765fbe7ec5903669e5ebc", + "0xa94d1c72bf3b2dc6bfebc9dee40f6a89a516b252bd9f4fad96f156e3dbfc151a9b8a02324d764c7656d59230a18eb61f", + "0x88996e79171e30b16505638d8ecb25afd875e5f3cc3e29860937f2b5e751c66e78dc77f744a0cc454a8a655142a93ffb", + "0xaf4d94f342665fe7ecda318de6cf1bc1c40c37dd83d060fedaf827459728152b5f0e280286ff5e6a0012036f6715f53f", + "0x96beaa7a2d565ec14a4e5cb895d33624c69da56b75c8d06ac729cb6d0cb64470ed4f9b0387083cd827b1609c8cabde8c", + "0x96b773fa2fcb7377bf71a7e286f37f1f24ee42cba5b4f33903c4566e5e5bcc501ea360e3c8435749107c3de84e272d8e", + "0xa69ac6218454c3f40ad0beb48821a218fb0a4f33ebade986d2fffd9a3900d8cfa613bc71676c46cfeaa5f644d1f239a9", + "0x857f139c08fcc45370f448ce3e4915bcb30f23daa4134407fc6d78efac7d718b2cd89e9a743eec7bf2cc0eccf55eb907", + "0xadeeba36af137fd3c371a2adbefea614c3ae3a69f8755ce892d0dd7102fb60717f5245d30119c69c582804e7e56f1626", + "0xafa97ca3548b35aeda6bfed7fbb39af907ed82a09348004d5705b4bb000173270ce44eb5d181819088aa5a2f20a547a2", + "0x8423bd2d07073b0e87819b4e81997e4d3188b0a5592621a30981dc0a5a9d0578fde1638a364f015078a001afb00891c2", + "0xb92e9d4ec3966981ee574695d6e4865810b8e75313e48c1e4bc5eebae77eb28740e97ecc3e5c42040f9eb1ee4b13b0ea", + "0xb07b218321d54cecfcd2ed54a5fd588a6be8d7a5b6a66dff7facfe061222c40553e076e57cbdfa0bdb08e0a009c94ba5", + "0xa71e1ae4d6096eac9ea4c21f621c875423de7c620544e520fb6ec3cb41a78554aedd79493cbd2c2ba4f0387f902ddd2a", + "0x807cdac291246a02f60c8937532c8969e689b1cfe811f239bfdee0791e7aa0545e9686cfb9ed0c1df84748e5efa5e3da", + "0xa1faeb4504c057304d27d54fb3ec681462384a354a4f0b6c759d4fa313253a789250c6b0f44f751b0718592637438a19", + "0x996bcd3215182d49f1cd15a05e1e0a4bf57e264400bf14f7253c6611d2571de7130cce81fd28e0411e0a80e9054f4f98", + "0x89d15b38f14bcd46f4b2dcae82b0e7bf9a35e40bf57aa947e9c4a8f87a440b5cea95229708de08ca596762062c34aaa0", + "0x8d8ddcaf79374c750b8b0b3d196acb6bb921e51b4619876a29d09161ba82a42271066187211ef746f9f40a5ca17b75f7", + "0xa3dc7f70f3a6c7edc483e712770abbaa94bfa3174cfee872b2cc011b267e0ef9baa1ab49e4a6c6c30dbba0e0a1237117", + "0xaa9e958bbdcb192b19c43fc6fd34afcd754949fdada98e9f4848e8db0e23acb27d19dd073c951a8819000f2356aa22e1", + "0xa4714e45ec853eadfe5c3bee7f683b81f97857bbd7833192a48936dd1460aee68f700a21658658b74b737c4fecf90c7f", + "0xa1ecab4215c1892e4a8ff3405d710163875e5dfef8a8cb84f5cac4e317d89c7696e3f496ed1747ca6f52b304190f4ba1", + "0xb9b48943eca3686219575026d395b969e6ff8159dc5317005df090e79d26901984e40ae4b1af060ed3ff6f42e0417d76", + "0x9644b9f90a66edb0396abd8c00066886f978ebf56fc22081031fbc9ce371bf9b04aa5a4ef59e59319b3a05bb7fb88b43", + "0xb2bb14f1c055a78596488e4e2d4135a6470c1ee43961952160b8498f674a4d23040606e937c02c1fc23dbd47e9bd4633", + "0x8c61f2fce9a42b94a389c7e52d7d093fc011099d0f4914f6d6f05b631df7b88182826edf9bbb1225971a080ca5c0d15a", + "0xaa6a7b8499cc7d256043eacad18528d38bf3be970bea4c6d4cb886690280bdb373688ceba3e506471e1d9493dc76f3f4", + "0x8127703363b3b35b06762c2353d4de82b7b85bb860db1028d3640f46bdb78f2d104fa77ee3e0d9db83833d2b12a966f8", + "0xb7b01f5909f2c66ae0fab156be5d79954e3a304615e1fe55945049dd4bd95f973bb3821117eb54db7e9ed1ee9a527652", + "0x8be47ba5dfe212420649193490838670c40540e0ea24adbab18c4a66e7ac3dcf94f068dec2533b60e08c1f64e7533e54", + "0x905a6c7e24b86aa54a05c329a6b4616d335bb0b1f1e9987562eee0acf82ad302c7c44981a1dd6b24c6121ca12fb92996", + "0x86969ccfd91deed93b355a2c21319e3bb08cc652b741463bf68c626b7ba2afce3f7cc397f2fb74588c2893477c948ae2", + "0xb5a9d20eb12c331d0d300fd4b85b0ac0bb74573178a5fac8ec9dce5e95acba07fab444260355ece442a846737a2dcd1c", + "0xa13497c11df21b11fc1a63b0ffdcf7f432da4dc2c98f8d07d36da4fa68aceb57af2158088e5b05e334fe0f264aeb7a97", + "0x882e4597cc66498a45e86a2ed9ee24652da4699af00ad35f73b5e74fde6ac3cee70630962d5ddd86162d4aaf11bbc11c", + "0xb748858c2bafa4a14ce44af35195e9c52aa75e109719243bbe278095acbfd6a7ae7e084caf8dae6939039b5a4e8fd675", + "0x83a2e0524507e74f51fe976441108f8226ba1b3a33f4e16ec45c5661ce80cb1840a93d17122cb8ca9e0f80d14f69877d", + "0x846cd2946c93ee5f24243d9ebc69936b3a1a6d59f45fec6c79b1eddf15ce30a8e73ad03cf606ee66baea3d8ff115f70f", + "0x8d98d0a3a94f6efe158f8423c041b546416145c5c2254bfa157efea0d1c99fe58acc7df6424ef29f75960b18d664ea4e", + "0xa39fa47e4b79f54dbf59d0b1726f1e78bc219fcfc56ad238c84b4b610e7892ff1e65d537baf5118a32f5e2eb80d5ee0c", + "0x8c30969a4519131de5e30121c84c04f67b98c8ad109fa4710dd3149cae303d51778add3f258f0482f1c89c169824dffc", + "0xaf7f80d141ceb78b4762015de17fef49d7ff6202d292e9604deb508272ee7569f7fd5be3b2438da1dfecf0c26533ef86", + "0x97cf82f70128251944d79b8845506975405bd720e150d836205b048ff36ba8801eb74cdcc6425f28f6bc0acec0a81463", + "0x8c276c876eb88688957d1868bf3a1462375e608ff72b49870a5dac82cbf6584e00e3f36f236f732348a47502ccf9539d", + "0x964765f1a5c8a41d8025ddf56dc01b78424703d8a64a4e5539e477cb2445cb541c70127c561e717256d13f91a830ba83", + "0xa2aacd9e21b8c8efaf2319611addea1b9f41430aee42e7f2a640cc693aa395287cc8fdc2806b76b577d84fbd05378ead", + "0xab11eabbf5be4345a77323a3b75f9ee93b011fd2a9d0154e88183cafe47f82a7888666af16b40d3cb677c94bcc755ff7", + "0xa0bfe715a7af5a29b1b6148b8cbee585d2b49fa6ce59bcd173ea3bbc60d71a62f9da27ffcbbd5a6da75502112fe44d70", + "0x902e6cc38ee42245103d90b65028a471bc7a48b825599d361aa81d8c56e0fcf9fbe8d4c13802040d2cfb85b7e022eea1", + "0x8832e2b5014fdef4003bdbb87e3298fdbdbbe49673f6b66e2373f1cb2605f9c4af2cdf9bfd45d1993208681d29ee1c9d", + "0xa7d39d3fa1ec1e0c87730fa43d4900e91932d1cafb36c76b2934907becf7d15a1d84d7234591ad4c322b5a24673bba8d", + "0x836ed5f09d99624204aa3aa7ac601980fda223f3b4b96b4a8fb235c574a3545d518787c12f81bd5851987f2860d41886", + "0x94235e94445e6086f6e9331923262070a4c2ed930ec519eabb8a30133bd4fc6debb99185f4b668431fae1b485c5c81b7", + "0x9828ffe20b9405f117dac044159be2d3c6e2b50ecdd1651d6a73f7633e6e2a7ba3d783ae939973604446d3a1ef0fb20f", + "0x92f03dc365dfe9154743ca70e6dd2758f064e3286fc543cf8c50f68effdf7c554bd17b3507c6ff4127046d9bbb5522ef", + "0x91ed07df479d8eb3d31292a0e987672a7f3d45ecafe72935b7abbc3f23493605134ce573f309e226c9efe830b6868220", + "0x93bee582661e6d6cefeff29002afc2f36dd2c13dbf33f0574c35b290ddc426170a5f7f196369ad592efcd72cfb6f8fc0", + "0x89a51467d966f48fed15dea5a12dda54d0015f69e2169b5e34f44c7b5a5d4c282d6f138116a0cd06a8476980e420f8d8", + "0xb8ccebc14b6679ba2399370848864f15f63512fd6139df7359b7b93e82c1007fd85137ecb0597294b46643e1a9e7ab5e", + "0x841fa301567fc57b2cd09508ce75326684e12bfb8add671dc208f579b2500b93d5b641e9f59bba798ed4ed1259757f7d", + "0xb3cb45c15eb00b4ccb7013299f761cb8fefc17adf6db50e9ecb8abe927a3bc7f28e359e64693813e078e1dac800ad55b", + "0x96e55d3b9f445f5679e34fa5425b3e87cb221cfbdd07f8353868c7f7f4ba388ee3841cb9a1d638583bc20d03a9d071f2", + "0xa7dee9377de740270c5b57cf86699004ba8dc2766af56b388b5cb0814ec71bb99ecf43ee3d82a552733854ecc7def0fe", + "0xb129dfff23b3c1c95ddb214c4711961fcb129efe2b6557ec9e116ada909593d0d2eec2c628434493393c58c52aa86847", + "0xaed2670e201cb3e38a8be3c86735a4d76255e1e5a4c67b91df6ed262d09c8d10b0a3891da3e6ab934058cc9a7178931b", + "0xb20b8921ae52e5b3c94fa3a8b46489044174f7b897779e7763d6eb419e808d76705b7e7ba5131576f425aa81b6b0de53", + "0xa7e45bbc3ba1bc36617291ba7663806e247f1b57a89e31520c64a90cbf8d426cac2e2f381338baf78c8f92fdbbcb7026", + "0xa99e651e73a507e9e663e2364fcc193ec77e8afdc08c2bed6ad864e49b537ec31e9114ee72291a7657899f2033a849e2", + "0xaf966033636c2e9e8280d173f556fe07f8b6940bbcf6b2df7e2165c30bea66cced2596f6c17ca7c1aa0e614174953ba9", + "0xb69ca7a79e3d55ef21e0ebdc6f0c4bd17182d30cf6290cccca7d2551c91c12b966020d8e40e4ee4179488c9809c03ae4", + "0xb981cd36244e035fef043f70b1d7188d7cd045b4de0581c459fc5730e10eb7f3d5893b54cc4243849c0855e4e621167a", + "0xb20fea858a36921b35a3051ce787b73f70fdecd3fef283c15a2eb1bffb1dcba5991eee4a047ce4e87802da923fd9457b", + "0xb040e6f2e56dc1860274c263d4045837456f74b354a679f6b5ea70919835ebe5d32bf1f519e218730096c98ff396dc9d", + "0x8d2dd60e702c923a7204b530e7d6c193c6f93ca648c4f7bb38f4edbeb0aaed84184213afafb8db6aeb9197c24364276c", + "0x95dfa7348709e43d71285b28a0bfad3ca805b6ed4ae99753e9f736c79d58a35a3a50b42760ccdd03eda50f6e59494968", + "0xb8585632a13f18c139a411bb2f02df809591834d127cd1ff081e26d0abfe0e3fbb54abea26538b25a0dcb4d7e969590e", + "0xb46ba47858a29c6d523c9982660949567666daf2582b93393a4802a9e077eedbc0d49d454731696bc8e46ca50c7caa40", + "0x84b756b901b98a4404e58d70f39f6ccac877146c866732ae65e7e82727448d1550343bf7cdff1bfd4ee1ed73793db255", + "0x83e5be888eaf877a2c755897410865f64a6d1169a8ccf0336092f3932abab915e542ab75a35ffe016042340d581ee987", + "0x8cb274fc39285aed451a7def72cfbf73168ee10be02affe355a2bf87cf361a81ad284e9334cf00c5bf99a13d9f75e116", + "0x91ff6220924b94ae13f50eeac16a159232e4f16a73fbd5c22c0e185cd1998403904d36bad203baa82b85819ee4a8ac10", + "0x87f46e08e09aea2ab37b55fc300689d9b58ff3e72f1cffe023386035888f714fac4673c7c5193d3f3f3c568c640694f0", + "0x835d7d84ca7641e1b15095830114aa6072fe12260d2202456cafe2308c22651af9ffbcf6b7e56af97167dd0c4e2a4cf2", + "0x91202183f79794f114fd9e3b9bd05553c0e8985919965101a57d97ef666b028863e6cea9735af016dc1864f1542dee51", + "0x81ab2b02a9b0a490a74ae615ddd4fe560734c1bfdde6b8dd13303c1481ba0e8ab14473535a93cfe4e824a0ab29445f8c", + "0x8a32d73f4fc006551d4e2c61eec6130355ec9b8c39a65c24ec1edc00e80155ca83a8ef2455e892521a3d47634d82a987", + "0xaf70d7b8f13bc90193cc1cfb0c400c4224cf10f1887848aa93e6380f7087782fc41a159926ab53c53eb95c2383b1a849", + "0x989bf42f9d357c51774f1c7c0f7c0c46a8cb7398a74497141c32685be098e38b4230ffe833a6d880ec391a35b1a747b6", + "0x94cb6715ee95700020c630b8c19e35f231de970219bd7e6ba7ced01899197da473b6c45cacfab0d652ddaf547b4ea58c", + "0xb12e3331f1f7d7458393a785e22e9a5e1d1daea521b4e78c0ee8ca59b41ade1735a29820e18f6afb2f2c3c56fecc16b6", + "0xad4b7cf654349d136fb41fb0dd65b588199f68b462b05f5c4e5c2b468bfaa6c26329033e3c3f7873dc8ace89cf873ea5", + "0xa3279969e1ab596df0559ffc5ac7a6dc849680354e01c3f4fd34c6413a3f9f046f89c1e1be0b315d8b6dfab3d23d5c14", + "0xac74cc5562836ed89d09a9ae6a3644c936d64bdda9e77659d9982f1be29541b03ef2723236d5465e398373ea19a4ccc6", + "0x98138ebce1af531dd8b631b3e74c84f0c700355a2a9bde31e5e51bb10c8bbd766559c63f6041f4002568803fe08438e0", + "0x9006445da131349fe5714e0777a4f82a82da343612589a0c1596393e8b6894ce1cf42784f95ff67a8384ffe1f1a4ad76", + "0x88502a84a85e4ce54cfed297b5d355867cc770a8ffd0714a6f23b1ab320a9903c6e42809e034bb67dbf94c4fc0d9c790", + "0xaa8b4bf123d1a6ccaa44b86be8f980005f2a0a388a76cb111b0e85cd072ef64167fb0c097c7b23c4bca64c0260f6cce0", + "0xad49eb35dfea9feabb513a78dd1152ad7eba22fbb02a80cefc494a7037699c8df81202dfec12acc1b9e33ad680cb72d2", + "0x8694da730231b29afd5196371ddcb15b4dcc499574bdd063f4864ab80749833ea38ab8b0ca1629a367fe378e87a60a86", + "0x8eca7b488e810c479e7e32e24b8afcd837f7df183fe4f621a0336b53a9ed77603c84bdc365d8be68179a32b71a1deb7e", + "0x8875cd3e23c7e1af55af1b091025a08255743984186770bcd43f30b4a58d175cfdf1984bad97a15e08dac2da27198c3d", + "0xabdafcf58ec72997e494d4714645f40d09dcd0fbd0733e640eca44eeea67c25bb0c270299c459991f2fae59d13b4f4d5", + "0x8f040970141e61489284f3efd907705eae6ec757fe8e1d284eac123d313e9ac1e8dc14ae3f04d281e1effc49d5d2f51d", + "0xa7ff115f0d2dbf66c0e8770b3d05157b37357b9e33e9a447f0f3fa9da69ad04e371fd1e4848cfb9e8d05e3165bd969d8", + "0xa39b1a8c39d317fcc97bf6c396e6ed4a85640aeeadbf45166bd02bc3bdfb6266509159c03afd492e642384c635b824c0", + "0xa2e1b90f3dd2d0038eaa5be52127844ccf35d997143179d95ffd3749c0896398b130094d01eb1bb31ffe80ef34b42b48", + "0xa2bbe31f89b0c3c375ffaf63c8b7831860a921d5e388eb7907dbf61f2601ea40db86bb3952ecaa26a5eca4317a848ff9", + "0x87d885bb0f2ce04b40ce94d2557c15f1698dc652e938f9a2d69a73ccf4899e08eafa1a59a20cae92823795f5b94f04b9", + "0x8f7746370f8a24a2889d351f3e36b8a7d60e75e50e8f5abeea7dafc75441e95915721654e61ceac51bb6f112780d352c", + "0xa7272847526ed3d9e0d0fea1d8685b07b5b908971490bf8a46748c8b1783c629b8644feb5bac772ae615daae383d5e72", + "0x978c9aa2996d8bd6fda7e0393fa8b38747f8f99712427705c00f6e9a12c36f8d8b4cedb03fcb9867155cbddb5200e6e1", + "0xa4dec4a2354b2b32434c5bcdc380bf84580c6f9940f94dc0498a5bfe89c675a0921e66b807a3d859a6059a464cb2a9ac", + "0x99459ddecc7abce437f68722dae556d8ffaf8ed974f459e52e6d4a64f176caa4d42c2f2ec57e8a5b5f2034638e8acb0a", + "0x928c68c0c9213fe6258ab5bb0c693d97203d15da359784de7824dec143212da57d062a1fc70a79172cee31adc7aff382", + "0xaad3f318f1622ea87e12541dfd982d71629b8f1ded4c301f9f6b6af9432716ad057773c33bdaa6f15dc151b0ee4505ea", + "0x8eb8e978f149a983fd6ad01773f9aacf57bd0cc622d8a301e404184b37e610123dd081faeda571a0ab1f149a3960af10", + "0x851e7191d7b94bd422bcece5b92609fc1b1c8556229bc53e32963b2d2fd1cacd8ce5da9040b599eca6e610540f8a7987", + "0x9414157fe9d50e5a0b5a7397417681bcb3a651eec1cab63f2a88d5df68ab1fef6e4c1d7ba657cbaf241a7cb790297633", + "0xb5cb2dafdc5408959780754a58b2da55b2a9136672ebca42f34da4e329ddc89360e7218cde3efdbf784ddb390deacc57", + "0xac6b70f65503a8e94b773fda3e72615745824930114fe72b6d833484285462392617c1b2eea4a250fedbee88f503f3ba", + "0xb0829a5312f9ac6c06fddee2f835a3452fe994f6d42c9edfc390d7d5b3240ca544433b544cbbddd6516b38a6d5d7c21d", + "0x95f8e2c59905957e34d53be3d6fb85732f834e2cb9ab4c333fea2f502452a87ccd035fc9075d7c0bd8530bb0a0c96527", + "0xb93f279b7045f2d97c674495f6e69a3e352f32f43cc60300193b936c2850b2805c15457251f7e3f633f435cb2b60405c", + "0x915abf16cba1a0b655b92a8a70c03e7fb306b86f3bbfb66967ca63e64c003b59c7a5953675efa4fa0bce9bed536b6700", + "0xac2047f50a319d09df1ec44d71afdcec5ac3bd2765dc98aba347734aa780863545df9f6d71214d443e3f37edc0dae45a", + "0xad49c74ddb24c8a26b14ec08bc807313c77c5967fbb36237f55994d7511bbac8d7e7b9b8ec53eb1b3b066989f078dbd9", + "0x961483105f605e959213fe9e8a52b76dac62d7efd2319ec71fc4e92d68fbe44cd2f65d7adefb2eb64d591b91648b8085", + "0xb67fcafc97d8df2b3075bbff7b3d7471dbf1f3048f309e55d5e2c5bcbc7a73aebcb0697859be9f387cbc7ce98041e154", + "0x8da70ac16468cab6066992389cb37c79ff5e0babbe67d76878aef9408b9597a3dc2eb5de87428bc761a0d78957b0eb28", + "0xaec0ce89770d299b631f15ae12f94b1e1014ac57d38fcf037c2c7712d770d074affa06e97c60691bad8733874b6ad2ed", + "0x8b702c85fa4c915a09fc86507f44d7aeda0993b77af87780d70cc98d580c6e996b64b7c16cdb4dd4562cb0f75da36ee7", + "0xaaeb43aa472aac2253e211fd1066c3a5422ea041cef20168702d0618a1a742a44f7fb30a76677640fea1a24e7fae1996", + "0xa8820e92825d6e02b9b4ad5ebc86161d3244cddd3d244333ba1576b6ae10948145b68d9e926bf6b7a2c25dab4cf43f3e", + "0x8ffdae28a1f1d15d7ffa473628a66ee9a739073f59ba781248286b39cb8f7255f66d62337064246713cbb5017e615174", + "0xadfc5dd142b7911326d8424881d5d92006f3b17de4cce91674d6ea37f00fbb266c791ac13f6c7a0f61d04f2a952e6a04", + "0x87f98982444bf661f539bec73a10256f079a4baa88a1cea0351ae3de929e1c500485b2d1b5d933063cd7d9123d5050e4", + "0x8f217ba4dd404c5ee384f0c9a126686db001ff0344c01c82174c5e5ef89d1a241b146008c534b13a0da6c8afe7450fbb", + "0xafc85476dddaf1cbb4ba8b22186789f3818c7964f9f613e55010278800cd95422702248bdf9c73760702ef24854795ec", + "0xa59e0f6ac2ccdfbd01f002008034390c0ea78716f5e0de4e474e3558755705c9c7afb6e3c5c4370e7bbc85958a9c7a63", + "0x97c0695c58d792ec31d9b86d3b2fc1382f0855057b24d5f6a54c41f76f9e2f52882cadc89a8b2f121530e7f1393faa95", + "0x8e49112de0b2649c08a96cf737af68fa8055f1af594846a2d0534c94df6f926f200405edaa6e6ac9db7e380707a2571d", + "0x99a1bd83a7ac5f8d77ddf044c80ebfc5745b998714696d67b94d185c97e9d6db989bacac646d9def463127a8b2febc00", + "0xaba80725f9f9f7abe10760eca73ba427ca8df864a157122eb9af828a05b0199de3add02019a297750bdab5380e505c58", + "0xae18f62573275c1eb268f74c5e54e8958547f9e7d1d36a05b084eb53e5704fafe2200b8aff95cc7e9af5be2391c42b7c", + "0x908b8031d09d22b2aefeaa876a998e0a97c7a1070aad9e9c97836cc5aa6d2d5ef94230e1222074837b5e21b4e6490f01", + "0xb3132282e8b41ca6789ec5c43c1fecf3a65b8eefbc2f3d10f746a843b9ba4ce6db664678e75e424f7b11a00c1440de15", + "0xa1eb49440cc106ebc09cf198c93e8070271eb5a936d31c04858a2b311a037350100c7957d5545c9653f396aa968b91f4", + "0x81df6ad1bdd5eee4cc2f94318467b8602d15cc1be2b48b09ade12cc46ee05cbaaf77a20397e5015030b1f1db5dd9dac0", + "0x87236c68a2a93c8442d15d7f1d1dc01d1fd123439c183e1d843f4ddd2bcf638c128f66f1ef9b710e5d1f64a52726007a", + "0x84f2e7f85563bb2f61b10a712c7605d63f79af5be0dba056814fd3efebc20e9c53227c56577b72c68d185571b775eff6", + "0xa36d4ae06688ece2927aeb2c7f058a3cd2aa1de1601282d4e688e1d76ef20728b892928deda2314eba41675eba3912f1", + "0xb8326dcbcdcfce017b263c456c47692fb476c4225c95981666fff0b7d4522fc23b7f12273f0f47cf0442662124e6648f", + "0x84c66463ab277cda2cc7007d0509269e89cdd41c5e0d3773a92615f0fc5da63811186b05d7a11088048a5d4834a7e0df", + "0xb20d3571d970712ef4699b0e7034fd269c361f53e1572e2ea2676b4245e992d43b8b5931a801439a44d977a988cc360b", + "0x94dba6007e6d4998ca1eb84aa8e2a7e9f5c164b9d80df2825f2208ce5640a05aacac2e4f08918268990f43ae1ccab69a", + "0xa1c25f0b3ef9d1982153207570d9ce8d692e1b6963b509958dc4d9bcd80074bb221c46804a6d9a29e76149cc7787c282", + "0x8857748fcdab1199fc96084323a81d3bd8b5a7f0b1abc5bc3b5252a19268344e2e7d2d086c90fc9b5fa4b92feedb93a4", + "0x8b9c1d841447354b6c086549e4d1d435ab64c13933488c34bc30f0f6eb36c5c5b838b7b6bb018542247edd1ada091045", + "0x8f5b655416da0e719a204fc567e93792c301acb4374cf7bbabc6ce51dbeaaadfd75c2db0e16ce073ab8e91fd3d7ea9d4", + "0x90f2846b19be46a75c5cd0cafefcf9192e6fd80c479e8d6320c4b8d8d7d96703c9e77ff31a67afa9858e6b7bde1f7cce", + "0xa53e383947fd98aa1a55ac956214b46b20a52758461e8ba41341a23a835ebb713038bf048edb1202bbfd0b56a96bf292", + "0x9542d7debbcfb9cda6fa279c699a7b655c03b9a9b456a5d3cfc41a826c94eafa43e01155a29e39ff0bcd965f4c0c512d", + "0xa43792864ec5fc549f7afc02622454afc0e425c310c4039ba615067243ebb26a4c7ebfd19bd4d57ff412a4bb2a7958a0", + "0xb85123950e30c048465bf32365d24a5d4b21fffc6183cdbf71643a07b87463989b72dd9a6a47f134856f704909a6b38f", + "0x944ea689aec1376f855c0bc9c51378ad06ff758a2c075b95a60b535b88b36eca0be11e4edb5152e98cb2137d6e749f27", + "0xa6bef52cda22325e4c62d323e2a0e3fa91c5552fcfce951edfd52ad6f652bfdcc2341f1cd349e6b5d447924dc569bfe2", + "0xb56bff8ffe981bfcb30791836da10b87f2ccbe17ed969e7f7a650af07d27ae0223805b1264d985148208483be50578a6", + "0x8b209cac898dd580c82d854a553e2517497ad1a4cd198e1360b8b50639b380aee70ee4b87625d9b2278228ff644cd25c", + "0x877cce233fec74c7158b3c5bf108365e98238418b8a71f058f1aca44a0fd3a1021e3e9025bd11fe244d9fe0f5034ce7f", + "0xb1b871aeedb03d6f6accc99816b89f5958178738d8d8cd9717527d04363c80fdb5f6848122ae19fdbc450cfa11e753c8", + "0x858aca51b9e5b0a724e88688d5124eb24c9faf01a3d465e74d31de6da315f311143f22f60201ea09f62c92f61f09d889", + "0x8521d409615dfc8c8289e00f6aaa6297c2c4e1439b25952afd76aac641b81c70b9cef07cd58c1c0198382bddd2bd8544", + "0x88647c3e41666b88acca42505f1f5da226937e0522b538fe0cebb724e9a99730ca2522989e94a96cac94109aef675c0f", + "0xb417fdaf719caf38854e89ce52031b30ce61a632e6c3135adec9002280e022d82ab0ea4ac5ebdb21f1f0169e4c37bcda", + "0x9367a6feb5e23ea2eab8ddd5e7bdf32b4d2419fad1c71a1ed327b77362d8942dad971a1c2e6f7073885149cdf0a0c339", + "0xa71c5c08d50c57d094d6a4f02e97d3799bada92f238ffc07bd223bbe8379507b7310d20b28f5bbbf331e5e153515e491", + "0x9630a9a3bcb044b51299c4d3d3388a4ff47308dd27be3229601985478c0f6b55faa7e20815d8694f910611396a9d0d45", + "0xb0bfaf56a5aa59b48960aa7c1617e832e65c823523fb2a5cd44ba606800501cf873e8db1d0dda64065285743dc40786e" + ], "g1_lagrange": [ "0xa0413c0dcafec6dbc9f47d66785cf1e8c981044f7d13cfe3e4fcbb71b5408dfde6312493cb3c1d30516cb3ca88c03654", "0x8b997fb25730d661918371bb41f2a6e899cac23f04fc5365800b75433c0a953250e15e7a98fb5ca5cc56a8cd34c20c57", From 7876f5b7adf5aeae463899953c3b6d579915a976 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Wed, 17 Jan 2024 17:57:56 +0530 Subject: [PATCH 610/775] Add an option for the inbox reader to only read safe or finalized L1 blocks --- arbnode/inbox_reader.go | 102 ++++++++++++++++++++++++++++------------ arbnode/node.go | 7 +++ 2 files changed, 80 insertions(+), 29 deletions(-) diff --git a/arbnode/inbox_reader.go b/arbnode/inbox_reader.go index 9c830e3c8..f452b0d89 100644 --- a/arbnode/inbox_reader.go +++ b/arbnode/inbox_reader.go @@ -31,6 +31,7 @@ type InboxReaderConfig struct { DefaultBlocksToRead uint64 `koanf:"default-blocks-to-read" reload:"hot"` TargetMessagesRead uint64 `koanf:"target-messages-read" reload:"hot"` MaxBlocksToRead uint64 `koanf:"max-blocks-to-read" reload:"hot"` + ReadMode string `koanf:"read-mode" reload:"hot"` } type InboxReaderConfigFetcher func() *InboxReaderConfig @@ -39,6 +40,12 @@ func (c *InboxReaderConfig) Validate() error { if c.MaxBlocksToRead == 0 || c.MaxBlocksToRead < c.DefaultBlocksToRead { return errors.New("inbox reader max-blocks-to-read cannot be zero or less than default-blocks-to-read") } + if c.ReadMode != "latest" { + c.ReadMode = strings.ToLower(c.ReadMode) + if c.ReadMode != "safe" && c.ReadMode != "finalized" { + return fmt.Errorf("inbox reader read-mode is invalid, want: safe or finalized, got: %s", c.ReadMode) + } + } return nil } @@ -50,6 +57,7 @@ func InboxReaderConfigAddOptions(prefix string, f *flag.FlagSet) { f.Uint64(prefix+".default-blocks-to-read", DefaultInboxReaderConfig.DefaultBlocksToRead, "the default number of blocks to read at once (will vary based on traffic by default)") f.Uint64(prefix+".target-messages-read", DefaultInboxReaderConfig.TargetMessagesRead, "if adjust-blocks-to-read is enabled, the target number of messages to read at once") f.Uint64(prefix+".max-blocks-to-read", DefaultInboxReaderConfig.MaxBlocksToRead, "if adjust-blocks-to-read is enabled, the maximum number of blocks to read at once") + f.String(prefix+".read-mode", DefaultInboxReaderConfig.ReadMode, "mode to only read safe or finalized L1 blocks. Takes string input, valid strings- safe, finalized") } var DefaultInboxReaderConfig = InboxReaderConfig{ @@ -60,6 +68,7 @@ var DefaultInboxReaderConfig = InboxReaderConfig{ DefaultBlocksToRead: 100, TargetMessagesRead: 500, MaxBlocksToRead: 2000, + ReadMode: "latest", } var TestInboxReaderConfig = InboxReaderConfig{ @@ -70,6 +79,7 @@ var TestInboxReaderConfig = InboxReaderConfig{ DefaultBlocksToRead: 100, TargetMessagesRead: 500, MaxBlocksToRead: 2000, + ReadMode: "latest", } type InboxReader struct { @@ -218,6 +228,7 @@ func (r *InboxReader) CaughtUp() chan struct{} { } func (r *InboxReader) run(ctx context.Context, hadError bool) error { + readMode := r.config().ReadMode from, err := r.getNextBlockToRead() if err != nil { return err @@ -238,38 +249,71 @@ func (r *InboxReader) run(ctx context.Context, hadError bool) error { } defer storeSeenBatchCount() // in case of error for { - - latestHeader, err := r.l1Reader.LastHeader(ctx) - if err != nil { - return err - } config := r.config() - currentHeight := latestHeader.Number - - neededBlockAdvance := config.DelayBlocks + arbmath.SaturatingUSub(config.MinBlocksToRead, 1) - neededBlockHeight := arbmath.BigAddByUint(from, neededBlockAdvance) - checkDelayTimer := time.NewTimer(config.CheckDelay) - WaitForHeight: - for arbmath.BigLessThan(currentHeight, neededBlockHeight) { - select { - case latestHeader = <-newHeaders: - if latestHeader == nil { - // shutting down + currentHeight := big.NewInt(0) + if readMode != "latest" { + var blockNum uint64 + fetchLatestSafeOrFinalized := func() { + if readMode == "safe" { + blockNum, err = r.l1Reader.LatestSafeBlockNr(ctx) + } else { + blockNum, err = r.l1Reader.LatestFinalizedBlockNr(ctx) + } + } + fetchLatestSafeOrFinalized() + if err != nil || blockNum == 0 { + return fmt.Errorf("inboxreader running in read only %s mode and unable to fetch latest %s block. err: %w", readMode, readMode, err) + } + currentHeight.SetUint64(blockNum) + // latest block in our db is newer than the latest safe/finalized block hence reset 'from' to match the last safe/finalized block number + if from.Uint64() > currentHeight.Uint64()+1 { + from.Set(currentHeight) + } + for currentHeight.Cmp(from) <= 0 { + select { + case <-newHeaders: + fetchLatestSafeOrFinalized() + if err != nil || blockNum == 0 { + return fmt.Errorf("inboxreader waiting for recent %s block and unable to fetch its block number. err: %w", readMode, err) + } + currentHeight.SetUint64(blockNum) + case <-ctx.Done(): return nil } - currentHeight = new(big.Int).Set(latestHeader.Number) - case <-ctx.Done(): - return nil - case <-checkDelayTimer.C: - break WaitForHeight } - } - checkDelayTimer.Stop() + } else { + + latestHeader, err := r.l1Reader.LastHeader(ctx) + if err != nil { + return err + } + currentHeight = latestHeader.Number + + neededBlockAdvance := config.DelayBlocks + arbmath.SaturatingUSub(config.MinBlocksToRead, 1) + neededBlockHeight := arbmath.BigAddByUint(from, neededBlockAdvance) + checkDelayTimer := time.NewTimer(config.CheckDelay) + WaitForHeight: + for arbmath.BigLessThan(currentHeight, neededBlockHeight) { + select { + case latestHeader = <-newHeaders: + if latestHeader == nil { + // shutting down + return nil + } + currentHeight = new(big.Int).Set(latestHeader.Number) + case <-ctx.Done(): + return nil + case <-checkDelayTimer.C: + break WaitForHeight + } + } + checkDelayTimer.Stop() - if config.DelayBlocks > 0 { - currentHeight = new(big.Int).Sub(currentHeight, new(big.Int).SetUint64(config.DelayBlocks)) - if currentHeight.Cmp(r.firstMessageBlock) < 0 { - currentHeight = new(big.Int).Set(r.firstMessageBlock) + if config.DelayBlocks > 0 { + currentHeight = new(big.Int).Sub(currentHeight, new(big.Int).SetUint64(config.DelayBlocks)) + if currentHeight.Cmp(r.firstMessageBlock) < 0 { + currentHeight = new(big.Int).Set(r.firstMessageBlock) + } } } @@ -358,7 +402,7 @@ func (r *InboxReader) run(ctx context.Context, hadError bool) error { r.lastReadBatchCount = checkingBatchCount r.lastReadMutex.Unlock() storeSeenBatchCount() - if !r.caughtUp { + if !r.caughtUp && readMode == "latest" { r.caughtUp = true close(r.caughtUpChan) } @@ -406,7 +450,7 @@ func (r *InboxReader) run(ctx context.Context, hadError bool) error { if err != nil { return err } - if !r.caughtUp && to.Cmp(currentHeight) == 0 { + if !r.caughtUp && to.Cmp(currentHeight) == 0 && readMode == "latest" { r.caughtUp = true close(r.caughtUpChan) } diff --git a/arbnode/node.go b/arbnode/node.go index f92dcefe7..55bd69118 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -99,6 +99,13 @@ func (c *Config) Validate() error { if c.DelayedSequencer.Enable && !c.Sequencer { return errors.New("cannot enable delayed sequencer without enabling sequencer") } + if c.InboxReader.ReadMode != "latest" { + if c.Sequencer { + return errors.New("cannot enable inboxreader in safe or finalized mode along with sequencer") + } + c.Feed.Output.Enable = false + c.Feed.Input.URL = []string{} + } if err := c.BlockValidator.Validate(); err != nil { return err } From 409caa4e357a3026b90c1296dcaecce4404e92f2 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Thu, 18 Jan 2024 15:30:37 +0530 Subject: [PATCH 611/775] Add context to fatal error messages while connecting to feed --- broadcastclient/broadcastclient.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/broadcastclient/broadcastclient.go b/broadcastclient/broadcastclient.go index f27fc28fa..1167dba13 100644 --- a/broadcastclient/broadcastclient.go +++ b/broadcastclient/broadcastclient.go @@ -191,7 +191,7 @@ func (bc *BroadcastClient) Start(ctxIn context.Context) { errors.Is(err, ErrIncorrectChainId) || errors.Is(err, ErrMissingFeedServerVersion) || errors.Is(err, ErrIncorrectFeedServerVersion) { - bc.fatalErrChan <- err + bc.fatalErrChan <- fmt.Errorf("failed connecting to server feed due to %w", err) return } if err == nil { From 4570eef488debb50c3f32bfebe337c4e532970df Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 18 Jan 2024 09:36:16 -0700 Subject: [PATCH 612/775] update storage/database API to geth 1.13 --- arbnode/dataposter/storage_test.go | 2 +- arbos/arbosState/initialization_test.go | 2 +- system_tests/conditionaltx_test.go | 7 +++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arbnode/dataposter/storage_test.go b/arbnode/dataposter/storage_test.go index fb4aade75..cf9918941 100644 --- a/arbnode/dataposter/storage_test.go +++ b/arbnode/dataposter/storage_test.go @@ -44,7 +44,7 @@ func newLevelDBStorage(t *testing.T, encF storage.EncoderDecoderF) *dbstorage.St func newPebbleDBStorage(t *testing.T, encF storage.EncoderDecoderF) *dbstorage.Storage { t.Helper() - db, err := rawdb.NewPebbleDBDatabase(path.Join(t.TempDir(), "pebble.db"), 0, 0, "default", false) + db, err := rawdb.NewPebbleDBDatabase(path.Join(t.TempDir(), "pebble.db"), 0, 0, "default", false, true) if err != nil { t.Fatalf("NewPebbleDBDatabase() unexpected error: %v", err) } diff --git a/arbos/arbosState/initialization_test.go b/arbos/arbosState/initialization_test.go index 968f533e3..3de1fc5d3 100644 --- a/arbos/arbosState/initialization_test.go +++ b/arbos/arbosState/initialization_test.go @@ -158,7 +158,7 @@ func checkAccounts(db *state.StateDB, arbState *ArbosState, accts []statetransfe if !bytes.Equal(acct.ContractInfo.Code, db.GetCode(addr)) { t.Fatal() } - err := db.ForEachStorage(addr, func(key common.Hash, value common.Hash) bool { + err := state.ForEachStorage(db, addr, func(key common.Hash, value common.Hash) bool { if key == (common.Hash{}) { // Unfortunately, geth doesn't seem capable of giving us storage keys any more. // Even with the triedb Preimages set to true, it doesn't record the necessary diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index 08367aa62..438e42d37 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/arbitrum_types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rpc" @@ -28,9 +29,7 @@ func getStorageRootHash(t *testing.T, execNode *gethexec.ExecutionNode, address t.Helper() statedb, err := execNode.Backend.ArbInterface().BlockChain().State() Require(t, err) - trie, err := statedb.StorageTrie(address) - Require(t, err) - return trie.Hash() + return statedb.GetStorageRoot(address) } func getStorageSlotValue(t *testing.T, execNode *gethexec.ExecutionNode, address common.Address) map[common.Hash]common.Hash { @@ -39,7 +38,7 @@ func getStorageSlotValue(t *testing.T, execNode *gethexec.ExecutionNode, address Require(t, err) slotValue := make(map[common.Hash]common.Hash) Require(t, err) - err = statedb.ForEachStorage(address, func(key, value common.Hash) bool { + err = state.ForEachStorage(statedb, address, func(key, value common.Hash) bool { slotValue[key] = value return true }) From 50b340a22262f70dd68b210daa1e1f9b7c7c6485 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 18 Jan 2024 09:36:52 -0700 Subject: [PATCH 613/775] update txpool API for geth 1.13 --- system_tests/delayedinboxlong_test.go | 11 +++++------ system_tests/twonodeslong_test.go | 13 ++++++------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/system_tests/delayedinboxlong_test.go b/system_tests/delayedinboxlong_test.go index b5743bfb6..ed9e40cdc 100644 --- a/system_tests/delayedinboxlong_test.go +++ b/system_tests/delayedinboxlong_test.go @@ -14,7 +14,6 @@ import ( "testing" "time" - "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" ) @@ -38,8 +37,8 @@ func TestDelayInboxLong(t *testing.T) { var lastDelayedMessage *types.Transaction for i := 0; i < addLocalLoops; i++ { - wrappedL1Txs := make([]*txpool.Transaction, 0, messagesPerAddLocal) - for len(wrappedL1Txs) < messagesPerAddLocal { + l1Txs := make([]*types.Transaction, 0, messagesPerAddLocal) + for len(l1Txs) < messagesPerAddLocal { randNum := rand.Int() % messagesPerDelayed var l1tx *types.Transaction if randNum == 0 { @@ -50,17 +49,17 @@ func TestDelayInboxLong(t *testing.T) { } else { l1tx = builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) } - wrappedL1Txs = append(wrappedL1Txs, &txpool.Transaction{Tx: l1tx}) + l1Txs = append(l1Txs, l1tx) } // adding multiple messages in the same Add with local=true to get them in the same L1 block - errs := builder.L1.L1Backend.TxPool().Add(wrappedL1Txs, true, false) + errs := builder.L1.L1Backend.TxPool().Add(l1Txs, true, false) for _, err := range errs { Require(t, err) } // Checking every tx is expensive, so we just check the last, assuming that the others succeeded too confirmLatestBlock(ctx, t, builder.L1Info, builder.L1.Client) - _, err := builder.L1.EnsureTxSucceeded(wrappedL1Txs[len(wrappedL1Txs)-1].Tx) + _, err := builder.L1.EnsureTxSucceeded(l1Txs[len(l1Txs)-1]) Require(t, err) } diff --git a/system_tests/twonodeslong_test.go b/system_tests/twonodeslong_test.go index 25110330c..ce3244462 100644 --- a/system_tests/twonodeslong_test.go +++ b/system_tests/twonodeslong_test.go @@ -17,7 +17,6 @@ import ( "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbutil" - "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" ) @@ -85,8 +84,8 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { } for i := 0; i < largeLoops; i++ { l1TxsThisTime := rand.Int() % (avgTotalL1MessagesPerLoop * 2) - wrappedL1Txs := make([]*txpool.Transaction, 0, l1TxsThisTime) - for len(wrappedL1Txs) < l1TxsThisTime { + l1Txs := make([]*types.Transaction, 0, l1TxsThisTime) + for len(l1Txs) < l1TxsThisTime { randNum := rand.Int() % avgTotalL1MessagesPerLoop var l1tx *types.Transaction if randNum < avgDelayedMessagesPerLoop { @@ -97,11 +96,11 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { } else { l1tx = builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) } - wrappedL1Txs = append(wrappedL1Txs, &txpool.Transaction{Tx: l1tx}) + l1Txs = append(l1Txs, l1tx) } // adding multiple messages in the same Add with local=true to get them in the same L1 block - errs := builder.L1.L1Backend.TxPool().Add(wrappedL1Txs, true, false) + errs := builder.L1.L1Backend.TxPool().Add(l1Txs, true, false) for _, err := range errs { if err != nil { Fatal(t, err) @@ -114,8 +113,8 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { } builder.L2.SendWaitTestTransactions(t, l2Txs) directTransfers += int64(l2TxsThisTime) - if len(wrappedL1Txs) > 0 { - _, err := builder.L1.EnsureTxSucceeded(wrappedL1Txs[len(wrappedL1Txs)-1].Tx) + if len(l1Txs) > 0 { + _, err := builder.L1.EnsureTxSucceeded(l1Txs[len(l1Txs)-1]) if err != nil { Fatal(t, err) } From dc3d8c98f1931bddf90c2e390c69f7836cd597e3 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 18 Jan 2024 09:37:13 -0700 Subject: [PATCH 614/775] upgate geth to 1.13 --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 1e2855b24..c4b3aa68a 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 1e2855b24d6555c8cfaf471bd9e2c3d19ab5c32c +Subproject commit c4b3aa68a05f468e0c30147f9383bfc76d82388f From 47c6024b32bd1a51b44307f4fbd47a638343ff33 Mon Sep 17 00:00:00 2001 From: Harry Kalodner Date: Thu, 18 Jan 2024 14:27:59 -0500 Subject: [PATCH 615/775] Update readme and license for AEP --- LICENSE => LICENSE.md | 25 +++++++++++++------------ README.md | 6 +++++- 2 files changed, 18 insertions(+), 13 deletions(-) rename LICENSE => LICENSE.md (80%) diff --git a/LICENSE b/LICENSE.md similarity index 80% rename from LICENSE rename to LICENSE.md index c96c4d6cb..0f679ff24 100644 --- a/LICENSE +++ b/LICENSE.md @@ -16,18 +16,19 @@ Additional Use Grant: You may use the Licensed Work in a production environment to provide a point of interface to permit end users or applications utilizing the Covered Arbitrum Chains to interact and query the state of a Covered Arbitrum Chain, including without limitation - validating the correctness of the posted chain state. For purposes - of this Additional Use Grant, the "Covered Arbitrum Chains" are - means (a) Arbitrum One (chainid:42161), Arbitrum Nova (chainid:42170), - Arbitrum Rinkeby testnet/Rinkarby (chainid:421611), and - Arbitrum Nitro Goerli testnet (chainid:421613) (b) any future - blockchains authorized to be designated as Covered Arbitrum Chains - by the decentralized autonomous organization governing the Arbitrum - network; and (c) any “Layer 3” Arbitrum-based blockchain that is built - on and settles to another Covered Arbitrum Chain. - - - + validating the correctness of the posted chain state, or to deploy + and operate (x) a blockchain that settles to a Covered Arbitrum Chain + or (y) a blockchain in accordance with, and subject to, the [Arbitrum + Expansion Program Term of Use](https://docs.arbitrum.foundation/assets/files/Arbitrum%20Expansion%20Program%20Jan182024.pdf). For purposes of this + Additional Use Grant, the "Covered Arbitrum Chains" are means + (a) Arbitrum One (chainid:42161), Arbitrum Nova (chainid:42170), + rbitrum Rinkeby testnet/Rinkarby (chainid:421611),Arbitrum Nitro + Goerli testnet (chainid:421613), and Arbitrum Sepolia Testnet + (chainid:421614); (b) any future blockchains authorized to be + designated as Covered Arbitrum Chains by the decentralized autonomous + organization governing the Arbitrum network; and (c) any “Layer 3” + Arbitrum-based blockchain that is built on and settles to another + Covered Arbitrum Chain. Change Date: Dec 31, 2028 diff --git a/README.md b/README.md index 67a182ec3..a02d55456 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,11 @@ Arbitrum One successfully migrated from the Classic Arbitrum stack onto Nitro on ## License -We currently have Nitro [licensed](./LICENSE) under a Business Source License, similar to our friends at Uniswap and Aave, with an "Additional Use Grant" to ensure that everyone can have full comfort using and running nodes on all public Arbitrum chains. +Nitro is currently licensed under a [Business Source License](./LICENSE), similar to our friends at Uniswap and Aave, with an "Additional Use Grant" to ensure that everyone can have full comfort using and running nodes on all public Arbitrum chains. + +The Additional Use Grant also permits the deployment of the Nitro software, in a permissionless fashion and without cost, as a new blockchain provided that the chain settles to either Arbitrum One or Arbitrum Nova. + +For those that prefer to deploy the Nitro software either directly on Ethereum (i.e. an L2) or have it settle to another Layer-2 on top of Ethereum, the [Arbitrum Expansion Program (the "AEP")](https://docs.arbitrum.foundation/assets/files/Arbitrum%20Expansion%20Program%20Jan182024.pdf) was recently established. The AEP allows for the permissionless deployment in the aforementioned fashion provided that 10% of net revenue (as more fully described in the AEP) is contributed back to the Arbitrum community in accordance with the requirements of the AEP. ## Contact From f1e34a7d6963d229fd939dfee67f41f3550ba02d Mon Sep 17 00:00:00 2001 From: Harry Kalodner Date: Thu, 18 Jan 2024 14:45:11 -0500 Subject: [PATCH 616/775] Fix typo in BSL --- LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.md b/LICENSE.md index 0f679ff24..c03439a3b 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -20,7 +20,7 @@ Additional Use Grant: You may use the Licensed Work in a production environment and operate (x) a blockchain that settles to a Covered Arbitrum Chain or (y) a blockchain in accordance with, and subject to, the [Arbitrum Expansion Program Term of Use](https://docs.arbitrum.foundation/assets/files/Arbitrum%20Expansion%20Program%20Jan182024.pdf). For purposes of this - Additional Use Grant, the "Covered Arbitrum Chains" are means + Additional Use Grant, the "Covered Arbitrum Chains" are (a) Arbitrum One (chainid:42161), Arbitrum Nova (chainid:42170), rbitrum Rinkeby testnet/Rinkarby (chainid:421611),Arbitrum Nitro Goerli testnet (chainid:421613), and Arbitrum Sepolia Testnet From 4ad269370febf749294c3957966e4257f7dea294 Mon Sep 17 00:00:00 2001 From: Harry Kalodner Date: Thu, 18 Jan 2024 14:59:23 -0500 Subject: [PATCH 617/775] Fix AEP link --- LICENSE.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index c03439a3b..ea9a53da7 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -19,7 +19,7 @@ Additional Use Grant: You may use the Licensed Work in a production environment validating the correctness of the posted chain state, or to deploy and operate (x) a blockchain that settles to a Covered Arbitrum Chain or (y) a blockchain in accordance with, and subject to, the [Arbitrum - Expansion Program Term of Use](https://docs.arbitrum.foundation/assets/files/Arbitrum%20Expansion%20Program%20Jan182024.pdf). For purposes of this + Expansion Program Term of Use](https://docs.arbitrum.foundation/assets/files/Arbitrum%20Expansion%20Program%20Jan182024-4f08b0c2cb476a55dc153380fa3e64b0.pdf). For purposes of this Additional Use Grant, the "Covered Arbitrum Chains" are (a) Arbitrum One (chainid:42161), Arbitrum Nova (chainid:42170), rbitrum Rinkeby testnet/Rinkarby (chainid:421611),Arbitrum Nitro diff --git a/README.md b/README.md index a02d55456..4a522be82 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Nitro is currently licensed under a [Business Source License](./LICENSE), simila The Additional Use Grant also permits the deployment of the Nitro software, in a permissionless fashion and without cost, as a new blockchain provided that the chain settles to either Arbitrum One or Arbitrum Nova. -For those that prefer to deploy the Nitro software either directly on Ethereum (i.e. an L2) or have it settle to another Layer-2 on top of Ethereum, the [Arbitrum Expansion Program (the "AEP")](https://docs.arbitrum.foundation/assets/files/Arbitrum%20Expansion%20Program%20Jan182024.pdf) was recently established. The AEP allows for the permissionless deployment in the aforementioned fashion provided that 10% of net revenue (as more fully described in the AEP) is contributed back to the Arbitrum community in accordance with the requirements of the AEP. +For those that prefer to deploy the Nitro software either directly on Ethereum (i.e. an L2) or have it settle to another Layer-2 on top of Ethereum, the [Arbitrum Expansion Program (the "AEP")](https://docs.arbitrum.foundation/assets/files/Arbitrum%20Expansion%20Program%20Jan182024-4f08b0c2cb476a55dc153380fa3e64b0.pdf) was recently established. The AEP allows for the permissionless deployment in the aforementioned fashion provided that 10% of net revenue (as more fully described in the AEP) is contributed back to the Arbitrum community in accordance with the requirements of the AEP. ## Contact From 5d90681d0db4316a40dfc2bbc0f86a42cfde534e Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 18 Jan 2024 13:06:41 -0700 Subject: [PATCH 618/775] Fix delayed sequencer finality not recognizing Arbitrum --- arbnode/delayed_sequencer.go | 2 +- util/headerreader/header_reader.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arbnode/delayed_sequencer.go b/arbnode/delayed_sequencer.go index 5d439e32d..f1b912e0f 100644 --- a/arbnode/delayed_sequencer.go +++ b/arbnode/delayed_sequencer.go @@ -100,7 +100,7 @@ func (d *DelayedSequencer) sequenceWithoutLockout(ctx context.Context, lastBlock } var finalized uint64 - if config.UseMergeFinality && lastBlockHeader.Difficulty.Sign() == 0 { + if config.UseMergeFinality && headerreader.HeaderIndicatesFinalitySupport(lastBlockHeader) { var err error if config.RequireFullFinality { finalized, err = d.l1Reader.LatestFinalizedBlockNr(ctx) diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index c5b8fa23f..06dfcfbfa 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -436,7 +436,7 @@ func (s *HeaderReader) LastPendingCallBlockNr() uint64 { var ErrBlockNumberNotSupported = errors.New("block number not supported") -func headerIndicatesFinalitySupport(header *types.Header) bool { +func HeaderIndicatesFinalitySupport(header *types.Header) bool { if header.Difficulty.Sign() == 0 { // This is an Ethereum PoS chain return true @@ -466,7 +466,7 @@ func (s *HeaderReader) getCached(ctx context.Context, c *cachedHeader) (*types.H if HeadersEqual(currentHead, c.headWhenCached) { return c.header, nil } - if !s.config().UseFinalityData || !headerIndicatesFinalitySupport(currentHead) { + if !s.config().UseFinalityData || !HeaderIndicatesFinalitySupport(currentHead) { return nil, ErrBlockNumberNotSupported } header, err := s.client.HeaderByNumber(ctx, c.rpcBlockNum) From 640e3e62f55431dc952da262f4bf37d65f8f79bd Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 18 Jan 2024 12:07:34 -0800 Subject: [PATCH 619/775] Use 4844-only contracts branch --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 0a149d2af..798934bc5 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 0a149d2af9aee566c4abf493479ec15e5fc32d98 +Subproject commit 798934bc5601ed9926ad9e8744575ecc075e0902 From 312efbb74cabc3ca2d36dfe307d929fbda9b24da Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 18 Jan 2024 12:10:26 -0800 Subject: [PATCH 620/775] Handle MaxTimeVariation contract change --- arbnode/batch_poster.go | 12 ++++++------ arbnode/node.go | 8 ++++---- system_tests/full_challenge_impl_test.go | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index c4fc500d7..9b8089fbd 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -921,22 +921,22 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) return false, fmt.Errorf("error getting L1 bound block: %w", err) } - maxTimeVariation, err := b.seqInbox.MaxTimeVariation(&bind.CallOpts{ + maxTimeVariationDelayBlocks, maxTimeVariationFutureBlocks, maxTimeVariationDelaySeconds, maxTimeVariationFutureSeconds, err := b.seqInbox.MaxTimeVariation(&bind.CallOpts{ Context: ctx, BlockNumber: l1Bound.Number, }) if err != nil { // This might happen if the latest finalized block is old enough that our L1 node no longer has its state log.Warn("error getting max time variation on L1 bound block; falling back on latest block", "err", err) - maxTimeVariation, err = b.seqInbox.MaxTimeVariation(&bind.CallOpts{Context: ctx}) + maxTimeVariationDelayBlocks, maxTimeVariationFutureBlocks, maxTimeVariationDelaySeconds, maxTimeVariationFutureSeconds, err = b.seqInbox.MaxTimeVariation(&bind.CallOpts{Context: ctx}) if err != nil { return false, fmt.Errorf("error getting max time variation: %w", err) } } l1BoundBlockNumber := arbutil.ParentHeaderToL1BlockNumber(l1Bound) - l1BoundMaxBlockNumber = arbmath.SaturatingUAdd(l1BoundBlockNumber, arbmath.BigToUintSaturating(maxTimeVariation.FutureBlocks)) - l1BoundMaxTimestamp = arbmath.SaturatingUAdd(l1Bound.Time, arbmath.BigToUintSaturating(maxTimeVariation.FutureSeconds)) + l1BoundMaxBlockNumber = arbmath.SaturatingUAdd(l1BoundBlockNumber, arbmath.BigToUintSaturating(maxTimeVariationFutureBlocks)) + l1BoundMaxTimestamp = arbmath.SaturatingUAdd(l1Bound.Time, arbmath.BigToUintSaturating(maxTimeVariationFutureSeconds)) if config.L1BlockBoundBypass > 0 { latestHeader, err := b.l1Reader.LastHeader(ctx) @@ -947,8 +947,8 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) blockNumberWithPadding := arbmath.SaturatingUAdd(latestBlockNumber, uint64(config.L1BlockBoundBypass/ethPosBlockTime)) timestampWithPadding := arbmath.SaturatingUAdd(latestHeader.Time, uint64(config.L1BlockBoundBypass/time.Second)) - l1BoundMinBlockNumber = arbmath.SaturatingUSub(blockNumberWithPadding, arbmath.BigToUintSaturating(maxTimeVariation.DelayBlocks)) - l1BoundMinTimestamp = arbmath.SaturatingUSub(timestampWithPadding, arbmath.BigToUintSaturating(maxTimeVariation.DelaySeconds)) + l1BoundMinBlockNumber = arbmath.SaturatingUSub(blockNumberWithPadding, arbmath.BigToUintSaturating(maxTimeVariationDelayBlocks)) + l1BoundMinTimestamp = arbmath.SaturatingUSub(timestampWithPadding, arbmath.BigToUintSaturating(maxTimeVariationDelaySeconds)) } } diff --git a/arbnode/node.go b/arbnode/node.go index f92dcefe7..6119a4fb5 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -65,10 +65,10 @@ func GenerateRollupConfig(prod bool, wasmModuleRoot common.Hash, rollupOwner com // TODO could the ChainConfig be just []byte? ChainConfig: string(serializedChainConfig), SequencerInboxMaxTimeVariation: rollupgen.ISequencerInboxMaxTimeVariation{ - DelayBlocks: big.NewInt(60 * 60 * 24 / 15), - FutureBlocks: big.NewInt(12), - DelaySeconds: big.NewInt(60 * 60 * 24), - FutureSeconds: big.NewInt(60 * 60), + DelayBlocks: 60 * 60 * 24 / 15, + FutureBlocks: 12, + DelaySeconds: 60 * 60 * 24, + FutureSeconds: 60 * 60, }, } } diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index 118d17ec8..ecbfd67c7 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -200,10 +200,10 @@ func setupSequencerInboxStub(ctx context.Context, t *testing.T, l1Info *Blockcha _, err = EnsureTxSucceeded(ctx, l1Client, tx) Require(t, err) timeBounds := mocksgen.ISequencerInboxMaxTimeVariation{ - DelayBlocks: big.NewInt(10000), - FutureBlocks: big.NewInt(10000), - DelaySeconds: big.NewInt(10000), - FutureSeconds: big.NewInt(10000), + DelayBlocks: 10000, + FutureBlocks: 10000, + DelaySeconds: 10000, + FutureSeconds: 10000, } seqInboxAddr, tx, seqInbox, err := mocksgen.DeploySequencerInboxStub( &txOpts, From b9fa60817f908b9b1692cd65ad659f0048534125 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 18 Jan 2024 12:11:24 -0800 Subject: [PATCH 621/775] Handle TimeBounds move to Bridge --- arbnode/delayed_seq_reorg_test.go | 8 ++++---- arbnode/sequencer_inbox.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arbnode/delayed_seq_reorg_test.go b/arbnode/delayed_seq_reorg_test.go index a28eebb5d..9ad984ae6 100644 --- a/arbnode/delayed_seq_reorg_test.go +++ b/arbnode/delayed_seq_reorg_test.go @@ -61,7 +61,7 @@ func TestSequencerReorgFromDelayed(t *testing.T) { AfterInboxAcc: [32]byte{1}, AfterDelayedAcc: initMsgDelayed.AfterInboxAcc(), AfterDelayedCount: 1, - TimeBounds: bridgegen.ISequencerInboxTimeBounds{}, + TimeBounds: bridgegen.IBridgeTimeBounds{}, rawLog: types.Log{}, dataLocation: 0, bridgeAddress: [20]byte{}, @@ -77,7 +77,7 @@ func TestSequencerReorgFromDelayed(t *testing.T) { AfterInboxAcc: [32]byte{2}, AfterDelayedAcc: userDelayed.AfterInboxAcc(), AfterDelayedCount: 2, - TimeBounds: bridgegen.ISequencerInboxTimeBounds{}, + TimeBounds: bridgegen.IBridgeTimeBounds{}, rawLog: types.Log{}, dataLocation: 0, bridgeAddress: [20]byte{}, @@ -91,7 +91,7 @@ func TestSequencerReorgFromDelayed(t *testing.T) { AfterInboxAcc: [32]byte{3}, AfterDelayedAcc: userDelayed.AfterInboxAcc(), AfterDelayedCount: 2, - TimeBounds: bridgegen.ISequencerInboxTimeBounds{}, + TimeBounds: bridgegen.IBridgeTimeBounds{}, rawLog: types.Log{}, dataLocation: 0, bridgeAddress: [20]byte{}, @@ -130,7 +130,7 @@ func TestSequencerReorgFromDelayed(t *testing.T) { AfterInboxAcc: [32]byte{2}, AfterDelayedAcc: initMsgDelayed.AfterInboxAcc(), AfterDelayedCount: 1, - TimeBounds: bridgegen.ISequencerInboxTimeBounds{}, + TimeBounds: bridgegen.IBridgeTimeBounds{}, rawLog: types.Log{}, dataLocation: 0, bridgeAddress: [20]byte{}, diff --git a/arbnode/sequencer_inbox.go b/arbnode/sequencer_inbox.go index 2adfcb60b..d0cdebfef 100644 --- a/arbnode/sequencer_inbox.go +++ b/arbnode/sequencer_inbox.go @@ -102,7 +102,7 @@ type SequencerInboxBatch struct { AfterInboxAcc common.Hash AfterDelayedAcc common.Hash AfterDelayedCount uint64 - TimeBounds bridgegen.ISequencerInboxTimeBounds + TimeBounds bridgegen.IBridgeTimeBounds rawLog types.Log dataLocation batchDataLocation bridgeAddress common.Address From 659553f0af167228212f54367cb546ae0b3cf661 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 18 Jan 2024 15:07:13 -0800 Subject: [PATCH 622/775] Placeholder zero addresses in DeploySequencerInbox --- deploy/deploy.go | 2 +- system_tests/full_challenge_impl_test.go | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/deploy/deploy.go b/deploy/deploy.go index bd2f2ec32..b1a3523cf 100644 --- a/deploy/deploy.go +++ b/deploy/deploy.go @@ -40,7 +40,7 @@ func deployBridgeCreator(ctx context.Context, l1Reader *headerreader.HeaderReade return common.Address{}, fmt.Errorf("bridge deploy error: %w", err) } - seqInboxTemplate, tx, _, err := bridgegen.DeploySequencerInbox(auth, client, maxDataSize) + seqInboxTemplate, tx, _, err := bridgegen.DeploySequencerInbox(auth, client, maxDataSize, common.Address{}, common.Address{}) // TODO upload the DataHashReader and BlobBasefeeReader err = andTxSucceeded(ctx, l1Reader, tx, err) if err != nil { return common.Address{}, fmt.Errorf("sequencer inbox deploy error: %w", err) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index ecbfd67c7..c14f4c0d5 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -199,19 +199,13 @@ func setupSequencerInboxStub(ctx context.Context, t *testing.T, l1Info *Blockcha Require(t, err) _, err = EnsureTxSucceeded(ctx, l1Client, tx) Require(t, err) - timeBounds := mocksgen.ISequencerInboxMaxTimeVariation{ - DelayBlocks: 10000, - FutureBlocks: 10000, - DelaySeconds: 10000, - FutureSeconds: 10000, - } seqInboxAddr, tx, seqInbox, err := mocksgen.DeploySequencerInboxStub( &txOpts, l1Client, - bridgeAddr, l1Info.GetAddress("sequencer"), - timeBounds, big.NewInt(117964), + common.Address{}, // TODO addresses for DataHashReader and BlobBasefeeReader + common.Address{}, ) Require(t, err) _, err = EnsureTxSucceeded(ctx, l1Client, tx) From 9e39151423eec4d66b175a8a87b9920a2feefdd2 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 18 Jan 2024 20:23:08 -0700 Subject: [PATCH 623/775] Get non-challenge tests passing --- Makefile | 1 + arbnode/batch_poster.go | 8 ++--- contracts | 2 +- deploy/deploy.go | 13 +++++++- solgen/gen.go | 38 ++++++++++++++++++++++++ system_tests/common_test.go | 7 ++++- system_tests/full_challenge_impl_test.go | 4 +-- 7 files changed, 63 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 422110096..edc6c3a6d 100644 --- a/Makefile +++ b/Makefile @@ -331,6 +331,7 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro .make/solidity: $(DEP_PREDICATE) contracts/src/*/*.sol .make/yarndeps $(ORDER_ONLY_PREDICATE) .make yarn --cwd contracts build + yarn --cwd contracts build:forge:yul @touch $@ .make/yarndeps: $(DEP_PREDICATE) contracts/package.json contracts/yarn.lock $(ORDER_ONLY_PREDICATE) .make diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 9b8089fbd..07034ee6f 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -338,10 +338,7 @@ func AccessList(opts *AccessListOpts) types.AccessList { StorageKeys: []common.Hash{ common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), // totalDelayedMessagesRead common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"), // bridge - common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000004"), // maxTimeVariation.delayBlocks - common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000005"), // maxTimeVariation.futureBlocks - common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000006"), // maxTimeVariation.delaySeconds - common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000007"), // maxTimeVariation.futureSeconds + common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000000a"), // maxTimeVariation // ADMIN_SLOT from OpenZeppelin, keccak-256 hash of // "eip1967.proxy.admin" subtracted by 1. common.HexToHash("0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"), @@ -427,7 +424,8 @@ func (b *BatchPoster) checkReverts(ctx context.Context, to int64) (bool, error) if shouldHalt { logLevel = log.Error } - logLevel("Transaction from batch poster reverted", "nonce", tx.Nonce(), "txHash", tx.Hash(), "blockNumber", r.BlockNumber, "blockHash", r.BlockHash) + txErr := arbutil.DetailTxError(ctx, b.l1Reader.Client(), tx, r) + logLevel("Transaction from batch poster reverted", "nonce", tx.Nonce(), "txHash", tx.Hash(), "blockNumber", r.BlockNumber, "blockHash", r.BlockHash, "txErr", txErr) return shouldHalt, nil } } diff --git a/contracts b/contracts index 798934bc5..b95ab0854 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 798934bc5601ed9926ad9e8744575ecc075e0902 +Subproject commit b95ab08544ae339c5ee7e7d708c9acb5e4ab1f75 diff --git a/deploy/deploy.go b/deploy/deploy.go index b1a3523cf..94a8e81a2 100644 --- a/deploy/deploy.go +++ b/deploy/deploy.go @@ -16,6 +16,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/ospgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" + "github.com/offchainlabs/nitro/solgen/go/yulgen" "github.com/offchainlabs/nitro/util/headerreader" ) @@ -40,7 +41,17 @@ func deployBridgeCreator(ctx context.Context, l1Reader *headerreader.HeaderReade return common.Address{}, fmt.Errorf("bridge deploy error: %w", err) } - seqInboxTemplate, tx, _, err := bridgegen.DeploySequencerInbox(auth, client, maxDataSize, common.Address{}, common.Address{}) // TODO upload the DataHashReader and BlobBasefeeReader + dataHashesReader, tx, _, err := yulgen.DeployDataHashesReader(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("data hashes reader deploy error: %w", err) + } + blobBasefeeReader, tx, _, err := yulgen.DeployBlobBasefeeReader(auth, client) + err = andTxSucceeded(ctx, l1Reader, tx, err) + if err != nil { + return common.Address{}, fmt.Errorf("blob basefee reader deploy error: %w", err) + } + seqInboxTemplate, tx, _, err := bridgegen.DeploySequencerInbox(auth, client, maxDataSize, dataHashesReader, blobBasefeeReader) err = andTxSucceeded(ctx, l1Reader, tx, err) if err != nil { return common.Address{}, fmt.Errorf("sequencer inbox deploy error: %w", err) diff --git a/solgen/gen.go b/solgen/gen.go index 5d43946fa..770fa0857 100644 --- a/solgen/gen.go +++ b/solgen/gen.go @@ -23,6 +23,15 @@ type HardHatArtifact struct { Bytecode string `json:"bytecode"` } +type FoundryBytecode struct { + Object string `json:"object"` +} + +type FoundryArtifact struct { + Abi []interface{} `json:"abi"` + Bytecode FoundryBytecode `json:"bytecode"` +} + type moduleInfo struct { contractNames []string abis []string @@ -96,6 +105,35 @@ func main() { modInfo.addArtifact(artifact) } + yulFilePaths, err := filepath.Glob(filepath.Join(parent, "contracts", "out", "yul", "*", "*.json")) + if err != nil { + log.Fatal(err) + } + yulModInfo := modules["yulgen"] + if yulModInfo == nil { + yulModInfo = &moduleInfo{} + modules["yulgen"] = yulModInfo + } + for _, path := range yulFilePaths { + _, file := filepath.Split(path) + name := file[:len(file)-5] + + data, err := os.ReadFile(path) + if err != nil { + log.Fatal("could not read", path, "for contract", name, err) + } + + artifact := FoundryArtifact{} + if err := json.Unmarshal(data, &artifact); err != nil { + log.Fatal("failed to parse contract", name, err) + } + yulModInfo.addArtifact(HardHatArtifact{ + ContractName: name, + Abi: artifact.Abi, + Bytecode: artifact.Bytecode.Object, + }) + } + // add upgrade executor module which is not compiled locally, but imported from 'nitro-contracts' depedencies upgExecutorPath := filepath.Join(parent, "contracts", "node_modules", "@offchainlabs", "upgrade-executor", "build", "contracts", "src", "UpgradeExecutor.sol", "UpgradeExecutor.json") _, err = os.Stat(upgExecutorPath) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 2e17a50ed..a950ebd7c 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -43,6 +43,9 @@ import ( "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/filters" + "github.com/ethereum/go-ethereum/eth/tracers" + _ "github.com/ethereum/go-ethereum/eth/tracers/js" + _ "github.com/ethereum/go-ethereum/eth/tracers/native" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" @@ -474,9 +477,10 @@ func createStackConfigForTest(dataDir string) *node.Config { stackConf.DataDir = dataDir stackConf.UseLightweightKDF = true stackConf.WSPort = 0 + stackConf.WSModules = append(stackConf.WSModules, "eth", "debug") stackConf.HTTPPort = 0 stackConf.HTTPHost = "" - stackConf.HTTPModules = append(stackConf.HTTPModules, "eth") + stackConf.HTTPModules = append(stackConf.HTTPModules, "eth", "debug") stackConf.P2P.NoDiscovery = true stackConf.P2P.NoDial = true stackConf.P2P.ListenAddr = "" @@ -605,6 +609,7 @@ func createTestL1BlockChainWithConfig(t *testing.T, l1info info, stackConfig *no Namespace: "eth", Service: filters.NewFilterAPI(filters.NewFilterSystem(l1backend.APIBackend, filters.Config{}), false), }}) + stack.RegisterAPIs(tracers.APIs(l1backend.APIBackend)) Require(t, stack.Start()) Require(t, l1backend.StartMining()) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index c14f4c0d5..1a7747092 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -204,8 +204,8 @@ func setupSequencerInboxStub(ctx context.Context, t *testing.T, l1Info *Blockcha l1Client, l1Info.GetAddress("sequencer"), big.NewInt(117964), - common.Address{}, // TODO addresses for DataHashReader and BlobBasefeeReader - common.Address{}, + common.Address{1}, // TODO addresses for DataHashReader and BlobBasefeeReader + common.Address{1}, ) Require(t, err) _, err = EnsureTxSucceeded(ctx, l1Client, tx) From 5e2dfea42614e7bdfa500ce21a7ec8ba29a5107a Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 19 Jan 2024 01:20:54 -0700 Subject: [PATCH 624/775] Use new SequencerInboxStub to fix challenge tests --- contracts | 2 +- system_tests/full_challenge_impl_test.go | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/contracts b/contracts index b95ab0854..77ce30ee8 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit b95ab08544ae339c5ee7e7d708c9acb5e4ab1f75 +Subproject commit 77ce30ee8393a7b489e42f7afdbe6f3966538e72 diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index 1a7747092..a2668d69e 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -199,10 +199,18 @@ func setupSequencerInboxStub(ctx context.Context, t *testing.T, l1Info *Blockcha Require(t, err) _, err = EnsureTxSucceeded(ctx, l1Client, tx) Require(t, err) + timeBounds := mocksgen.ISequencerInboxMaxTimeVariation{ + DelayBlocks: 10000, + FutureBlocks: 10000, + DelaySeconds: 10000, + FutureSeconds: 10000, + } seqInboxAddr, tx, seqInbox, err := mocksgen.DeploySequencerInboxStub( &txOpts, l1Client, + bridgeAddr, l1Info.GetAddress("sequencer"), + timeBounds, big.NewInt(117964), common.Address{1}, // TODO addresses for DataHashReader and BlobBasefeeReader common.Address{1}, From 750a15f5f4505ef484b0539fdc86a292f144e3b3 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 19 Jan 2024 01:24:45 -0700 Subject: [PATCH 625/775] Use real blob data readers in challenge tests --- system_tests/full_challenge_impl_test.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index a2668d69e..8dc9b83f3 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -35,6 +35,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/challengegen" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/ospgen" + "github.com/offchainlabs/nitro/solgen/go/yulgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/validator" "github.com/offchainlabs/nitro/validator/server_common" @@ -199,6 +200,14 @@ func setupSequencerInboxStub(ctx context.Context, t *testing.T, l1Info *Blockcha Require(t, err) _, err = EnsureTxSucceeded(ctx, l1Client, tx) Require(t, err) + dataHashesReader, tx, _, err := yulgen.DeployDataHashesReader(&txOpts, l1Client) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, l1Client, tx) + Require(t, err) + blobBasefeeReader, tx, _, err := yulgen.DeployBlobBasefeeReader(&txOpts, l1Client) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, l1Client, tx) + Require(t, err) timeBounds := mocksgen.ISequencerInboxMaxTimeVariation{ DelayBlocks: 10000, FutureBlocks: 10000, @@ -212,8 +221,8 @@ func setupSequencerInboxStub(ctx context.Context, t *testing.T, l1Info *Blockcha l1Info.GetAddress("sequencer"), timeBounds, big.NewInt(117964), - common.Address{1}, // TODO addresses for DataHashReader and BlobBasefeeReader - common.Address{1}, + dataHashesReader, + blobBasefeeReader, ) Require(t, err) _, err = EnsureTxSucceeded(ctx, l1Client, tx) From cfd5fca27d57979c55fa6e8481d7608ccffaecc9 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 19 Jan 2024 14:25:10 +0530 Subject: [PATCH 626/775] =?UTF-8?q?Add=20a=20CLI=20option=20for=20the=20RP?= =?UTF-8?q?C=20=E2=80=9Cfinalized=E2=80=9D=20block=20to=20wait=20for=20the?= =?UTF-8?q?=20block=20validator=20to=20complete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- arbnode/sync_monitor.go | 47 ++++++++++++++++++++++++++++++++++----- staker/block_validator.go | 6 +++++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/arbnode/sync_monitor.go b/arbnode/sync_monitor.go index 598ea4fb3..90621d9b5 100644 --- a/arbnode/sync_monitor.go +++ b/arbnode/sync_monitor.go @@ -26,21 +26,27 @@ func NewSyncMonitor(config *SyncMonitorConfig) *SyncMonitor { } type SyncMonitorConfig struct { - BlockBuildLag uint64 `koanf:"block-build-lag"` - BlockBuildSequencerInboxLag uint64 `koanf:"block-build-sequencer-inbox-lag"` - CoordinatorMsgLag uint64 `koanf:"coordinator-msg-lag"` + BlockBuildLag uint64 `koanf:"block-build-lag"` + BlockBuildSequencerInboxLag uint64 `koanf:"block-build-sequencer-inbox-lag"` + CoordinatorMsgLag uint64 `koanf:"coordinator-msg-lag"` + SafeBlockWaitForBlockValidator bool `koanf:"safe-block-wait-for-block-validator"` + FinalizedBlockWaitForBlockValidator bool `koanf:"finalized-block-wait-for-block-validator"` } var DefaultSyncMonitorConfig = SyncMonitorConfig{ - BlockBuildLag: 20, - BlockBuildSequencerInboxLag: 0, - CoordinatorMsgLag: 15, + BlockBuildLag: 20, + BlockBuildSequencerInboxLag: 0, + CoordinatorMsgLag: 15, + SafeBlockWaitForBlockValidator: false, + FinalizedBlockWaitForBlockValidator: false, } func SyncMonitorConfigAddOptions(prefix string, f *flag.FlagSet) { f.Uint64(prefix+".block-build-lag", DefaultSyncMonitorConfig.BlockBuildLag, "allowed lag between messages read and blocks built") f.Uint64(prefix+".block-build-sequencer-inbox-lag", DefaultSyncMonitorConfig.BlockBuildSequencerInboxLag, "allowed lag between messages read from sequencer inbox and blocks built") f.Uint64(prefix+".coordinator-msg-lag", DefaultSyncMonitorConfig.CoordinatorMsgLag, "allowed lag between local and remote messages") + f.Bool(prefix+".safe-block-wait-for-block-validator", DefaultSyncMonitorConfig.SafeBlockWaitForBlockValidator, "wait for block validator to complete before returning safe block number") + f.Bool(prefix+".finalized-block-wait-for-block-validator", DefaultSyncMonitorConfig.FinalizedBlockWaitForBlockValidator, "wait for block validator to complete before returning finalized block number") } func (s *SyncMonitor) Initialize(inboxReader *InboxReader, txStreamer *TransactionStreamer, coordinator *SeqCoordinator, exec execution.FullExecutionClient) { @@ -153,10 +159,29 @@ func (s *SyncMonitor) SafeBlockNumber(ctx context.Context) (uint64, error) { if err != nil { return 0, err } + // If SafeBlockWaitForBlockValidator is true, we want to wait for the block validator to finish + if s.config.SafeBlockWaitForBlockValidator { + latestValidatedCount, err := s.getLatestValidatedCount() + if err != nil { + return 0, err + } + if msg > latestValidatedCount { + msg = latestValidatedCount + } + } block := s.exec.MessageIndexToBlockNumber(msg - 1) return block, nil } +func (s *SyncMonitor) getLatestValidatedCount() (arbutil.MessageIndex, error) { + latestValidatedGS := s.txStreamer.validator.GetLastValidated() + count, err := s.inboxReader.tracker.GetBatchMessageCount(latestValidatedGS.Batch - 1) + if err != nil { + return 0, err + } + count += arbutil.MessageIndex(latestValidatedGS.PosInBatch) +} + func (s *SyncMonitor) FinalizedBlockNumber(ctx context.Context) (uint64, error) { if s.inboxReader == nil || !s.initialized { return 0, errors.New("not set up for safeblock") @@ -165,6 +190,16 @@ func (s *SyncMonitor) FinalizedBlockNumber(ctx context.Context) (uint64, error) if err != nil { return 0, err } + // If FinalizedBlockWaitForBlockValidator is true, we want to wait for the block validator to finish + if s.config.FinalizedBlockWaitForBlockValidator { + latestValidatedCount, err := s.getLatestValidatedCount() + if err != nil { + return 0, err + } + if msg > latestValidatedCount { + msg = latestValidatedCount + } + } block := s.exec.MessageIndexToBlockNumber(msg - 1) return block, nil } diff --git a/staker/block_validator.go b/staker/block_validator.go index 352335a5d..a33112673 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -1206,3 +1206,9 @@ func (v *BlockValidator) WaitForPos(t *testing.T, ctx context.Context, pos arbut } } } + +func (v *BlockValidator) GetLastValidated() validator.GoGlobalState { + v.reorgMutex.Lock() + defer v.reorgMutex.Unlock() + return v.lastValidGS +} From ecd379f524e860432345a67edfd55ef05b0e23f9 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 19 Jan 2024 14:31:50 +0530 Subject: [PATCH 627/775] Fix --- arbnode/sync_monitor.go | 1 + 1 file changed, 1 insertion(+) diff --git a/arbnode/sync_monitor.go b/arbnode/sync_monitor.go index 90621d9b5..5fa9dbabc 100644 --- a/arbnode/sync_monitor.go +++ b/arbnode/sync_monitor.go @@ -180,6 +180,7 @@ func (s *SyncMonitor) getLatestValidatedCount() (arbutil.MessageIndex, error) { return 0, err } count += arbutil.MessageIndex(latestValidatedGS.PosInBatch) + return count, nil } func (s *SyncMonitor) FinalizedBlockNumber(ctx context.Context) (uint64, error) { From 3619cd1a097e9f62de69a6acd970c38034a69120 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 19 Jan 2024 10:39:18 -0700 Subject: [PATCH 628/775] Update contracts to latest (unified 4844 reader contract) --- contracts | 2 +- deploy/deploy.go | 9 ++------- system_tests/full_challenge_impl_test.go | 9 ++------- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/contracts b/contracts index 77ce30ee8..a8e7709bf 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 77ce30ee8393a7b489e42f7afdbe6f3966538e72 +Subproject commit a8e7709bfc918f9b8e2888d47f2fd8454779fd11 diff --git a/deploy/deploy.go b/deploy/deploy.go index 94a8e81a2..59760e2c2 100644 --- a/deploy/deploy.go +++ b/deploy/deploy.go @@ -41,17 +41,12 @@ func deployBridgeCreator(ctx context.Context, l1Reader *headerreader.HeaderReade return common.Address{}, fmt.Errorf("bridge deploy error: %w", err) } - dataHashesReader, tx, _, err := yulgen.DeployDataHashesReader(auth, client) - err = andTxSucceeded(ctx, l1Reader, tx, err) - if err != nil { - return common.Address{}, fmt.Errorf("data hashes reader deploy error: %w", err) - } - blobBasefeeReader, tx, _, err := yulgen.DeployBlobBasefeeReader(auth, client) + reader4844, tx, _, err := yulgen.DeployReader4844(auth, client) err = andTxSucceeded(ctx, l1Reader, tx, err) if err != nil { return common.Address{}, fmt.Errorf("blob basefee reader deploy error: %w", err) } - seqInboxTemplate, tx, _, err := bridgegen.DeploySequencerInbox(auth, client, maxDataSize, dataHashesReader, blobBasefeeReader) + seqInboxTemplate, tx, _, err := bridgegen.DeploySequencerInbox(auth, client, maxDataSize, reader4844) err = andTxSucceeded(ctx, l1Reader, tx, err) if err != nil { return common.Address{}, fmt.Errorf("sequencer inbox deploy error: %w", err) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index 8dc9b83f3..0fa483b6e 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -200,11 +200,7 @@ func setupSequencerInboxStub(ctx context.Context, t *testing.T, l1Info *Blockcha Require(t, err) _, err = EnsureTxSucceeded(ctx, l1Client, tx) Require(t, err) - dataHashesReader, tx, _, err := yulgen.DeployDataHashesReader(&txOpts, l1Client) - Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1Client, tx) - Require(t, err) - blobBasefeeReader, tx, _, err := yulgen.DeployBlobBasefeeReader(&txOpts, l1Client) + reader4844, tx, _, err := yulgen.DeployReader4844(&txOpts, l1Client) Require(t, err) _, err = EnsureTxSucceeded(ctx, l1Client, tx) Require(t, err) @@ -221,8 +217,7 @@ func setupSequencerInboxStub(ctx context.Context, t *testing.T, l1Info *Blockcha l1Info.GetAddress("sequencer"), timeBounds, big.NewInt(117964), - dataHashesReader, - blobBasefeeReader, + reader4844, ) Require(t, err) _, err = EnsureTxSucceeded(ctx, l1Client, tx) From 28ca156a1a441cd2eb70a9dee8a37f2398c4c380 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 19 Jan 2024 18:43:57 -0700 Subject: [PATCH 629/775] update go modules --- go.mod | 14 +++++++------- go.sum | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index bdda6a61a..9d1df5274 100644 --- a/go.mod +++ b/go.mod @@ -34,15 +34,15 @@ require ( github.com/ipfs/kubo v0.19.1 github.com/knadh/koanf v1.4.0 github.com/libp2p/go-libp2p v0.27.8 - github.com/multiformats/go-multiaddr v0.9.0 - github.com/multiformats/go-multihash v0.2.1 + github.com/multiformats/go-multiaddr v0.12.1 + github.com/multiformats/go-multihash v0.2.3 github.com/r3labs/diff/v3 v3.0.1 github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 github.com/spf13/pflag v1.0.5 github.com/wealdtech/go-merkletree v1.0.0 - golang.org/x/crypto v0.14.0 - golang.org/x/sys v0.13.0 - golang.org/x/term v0.13.0 + golang.org/x/crypto v0.17.0 + golang.org/x/sys v0.15.0 + golang.org/x/term v0.15.0 golang.org/x/tools v0.9.1 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) @@ -213,7 +213,7 @@ require ( github.com/miekg/dns v1.1.53 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect - github.com/minio/sha256-simd v1.0.0 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect @@ -283,7 +283,7 @@ require ( golang.org/x/mod v0.11.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sync v0.3.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect diff --git a/go.sum b/go.sum index bf8b4b826..5791615d5 100644 --- a/go.sum +++ b/go.sum @@ -51,6 +51,7 @@ github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3 github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= @@ -232,8 +233,11 @@ github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZe github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= +github.com/cockroachdb/pebble v1.0.0/go.mod h1:bynZ3gvVyhlvjLI7PT6dmZ7g76xzJ7HpxfjgkzCGz6s= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codeclysm/extract/v3 v3.0.2 h1:sB4LcE3Php7LkhZwN0n2p8GCwZe92PEQutdbGURf5xc= github.com/codeclysm/extract/v3 v3.0.2/go.mod h1:NKsw+hqua9H+Rlwy/w/3Qgt9jDonYEgB6wJu+25eOKw= @@ -260,6 +264,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= github.com/crate-crypto/go-kzg-4844 v0.3.0 h1:UBlWE0CgyFqqzTI+IFyCzA7A3Zw4iip6uzRv5NIXG0A= @@ -277,7 +282,9 @@ github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= @@ -347,6 +354,7 @@ github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4 github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= @@ -362,6 +370,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= @@ -374,6 +383,7 @@ github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5 github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= +github.com/getsentry/sentry-go v0.26.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= @@ -395,6 +405,7 @@ github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -455,6 +466,7 @@ github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= @@ -567,6 +579,7 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= @@ -590,6 +603,7 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-bexpr v0.1.13/go.mod h1:gN7hRKB3s7yT+YvTdnhZVLTENejvhlkZ8UE4YVBS+Q8= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= @@ -891,6 +905,7 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -1209,6 +1224,7 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -1238,6 +1254,8 @@ github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1 github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -1269,6 +1287,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= @@ -1295,6 +1314,8 @@ github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWz github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= +github.com/multiformats/go-multiaddr v0.12.1 h1:vm+BA/WZA8QZDp1pF1FWhi5CT3g1tbi5GJmqpb6wnlk= +github.com/multiformats/go-multiaddr v0.12.1/go.mod h1:7mPkiBMmLeFipt+nNSq9pHZUeJSt8lHBgH6yhj0YQzE= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= @@ -1329,6 +1350,8 @@ github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJ github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84= github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= +github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= +github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= @@ -1410,6 +1433,7 @@ github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAv github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk= +github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -1646,6 +1670,7 @@ github.com/wealdtech/go-merkletree v1.0.0/go.mod h1:cdil512d/8ZC7Kx3bfrDvGMQXB25 github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4= github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= +github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa h1:EyA027ZAkuaCLoxVX4r1TZMPy1d31fM6hbfQ4OU4I5o= github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= @@ -1790,6 +1815,8 @@ golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -2011,12 +2038,16 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2030,6 +2061,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 02e2be04e5d3e0e415e2119f1fee5202b5490a3c Mon Sep 17 00:00:00 2001 From: amsanghi Date: Mon, 22 Jan 2024 20:25:30 +0530 Subject: [PATCH 630/775] Prefetch state needed for future block executions by executing them in parallel against old state --- arbnode/transaction_streamer.go | 10 ++++++- execution/gethexec/executionengine.go | 38 +++++++++++++++++++++++---- execution/gethexec/node.go | 4 +-- execution/gethexec/sequencer.go | 7 +++++ execution/interface.go | 2 +- 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 24ef2a7cc..5491cbdbf 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -968,7 +968,15 @@ func (s *TransactionStreamer) executeNextMsg(ctx context.Context, exec execution log.Error("feedOneMsg failed to readMessage", "err", err, "pos", pos) return false } - err = s.exec.DigestMessage(pos, msg) + var msgForPrefetch *arbostypes.MessageWithMetadata + if pos+1 < msgCount { + msgForPrefetch, err = s.GetMessage(pos + 1) + if err != nil { + log.Error("feedOneMsg failed to readMessage", "err", err, "pos", pos+1) + return false + } + } + err = s.exec.DigestMessage(pos, msg, msgForPrefetch) if err != nil { logger := log.Warn if prevMessageCount < msgCount { diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 58e91a197..d376c59ba 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -41,6 +41,8 @@ type ExecutionEngine struct { nextScheduledVersionCheck time.Time // protected by the createBlocksMutex reorgSequencing bool + + prefetchBlock bool } func NewExecutionEngine(bc *core.BlockChain) (*ExecutionEngine, error) { @@ -71,6 +73,16 @@ func (s *ExecutionEngine) EnableReorgSequencing() { s.reorgSequencing = true } +func (s *ExecutionEngine) EnablePrefetchBlock() { + if s.Started() { + panic("trying to enable prefetch block after start") + } + if s.prefetchBlock { + panic("trying to enable prefetch block when already set") + } + s.prefetchBlock = true +} + func (s *ExecutionEngine) SetTransactionStreamer(streamer execution.TransactionStreamer) { if s.Started() { panic("trying to set transaction streamer after start") @@ -107,7 +119,11 @@ func (s *ExecutionEngine) Reorg(count arbutil.MessageIndex, newMessages []arbost return err } for i := range newMessages { - err := s.digestMessageWithBlockMutex(count+arbutil.MessageIndex(i), &newMessages[i]) + var msgForPrefetch *arbostypes.MessageWithMetadata + if i < len(newMessages)-1 { + msgForPrefetch = &newMessages[i] + } + err := s.digestMessageWithBlockMutex(count+arbutil.MessageIndex(i), &newMessages[i], msgForPrefetch) if err != nil { return err } @@ -486,15 +502,15 @@ func (s *ExecutionEngine) ResultAtPos(pos arbutil.MessageIndex) (*execution.Mess return s.resultFromHeader(s.bc.GetHeaderByNumber(s.MessageIndexToBlockNumber(pos))) } -func (s *ExecutionEngine) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata) error { +func (s *ExecutionEngine) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) error { if !s.createBlocksMutex.TryLock() { return errors.New("createBlock mutex held") } defer s.createBlocksMutex.Unlock() - return s.digestMessageWithBlockMutex(num, msg) + return s.digestMessageWithBlockMutex(num, msg, msgForPrefetch) } -func (s *ExecutionEngine) digestMessageWithBlockMutex(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata) error { +func (s *ExecutionEngine) digestMessageWithBlockMutex(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) error { currentHeader, err := s.getCurrentHeader() if err != nil { return err @@ -508,11 +524,23 @@ func (s *ExecutionEngine) digestMessageWithBlockMutex(num arbutil.MessageIndex, } startTime := time.Now() + var wg sync.WaitGroup + if s.prefetchBlock && msgForPrefetch != nil { + wg.Add(1) + go func() { + defer wg.Done() + _, _, _, err := s.createBlockFromNextMessage(msgForPrefetch) + if err != nil { + return + } + }() + } + block, statedb, receipts, err := s.createBlockFromNextMessage(msg) if err != nil { return err } - + wg.Wait() err = s.appendBlock(block, statedb, receipts, time.Since(startTime)) if err != nil { return err diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 00337cc35..1ad73febe 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -311,8 +311,8 @@ func (n *ExecutionNode) StopAndWait() { // } } -func (n *ExecutionNode) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata) error { - return n.ExecEngine.DigestMessage(num, msg) +func (n *ExecutionNode) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) error { + return n.ExecEngine.DigestMessage(num, msg, msgForPrefetch) } func (n *ExecutionNode) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadata, oldMessages []*arbostypes.MessageWithMetadata) error { return n.ExecEngine.Reorg(count, newMessages, oldMessages) diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 5db38cbb4..9bc6f4378 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -66,6 +66,7 @@ type SequencerConfig struct { MaxTxDataSize int `koanf:"max-tx-data-size" reload:"hot"` NonceFailureCacheSize int `koanf:"nonce-failure-cache-size" reload:"hot"` NonceFailureCacheExpiry time.Duration `koanf:"nonce-failure-cache-expiry" reload:"hot"` + EnablePrefetchBlock bool `koanf:"enable-prefetch-block"` } func (c *SequencerConfig) Validate() error { @@ -97,6 +98,7 @@ var DefaultSequencerConfig = SequencerConfig{ MaxTxDataSize: 95000, NonceFailureCacheSize: 1024, NonceFailureCacheExpiry: time.Second, + EnablePrefetchBlock: false, } var TestSequencerConfig = SequencerConfig{ @@ -112,6 +114,7 @@ var TestSequencerConfig = SequencerConfig{ MaxTxDataSize: 95000, NonceFailureCacheSize: 1024, NonceFailureCacheExpiry: time.Second, + EnablePrefetchBlock: false, } func SequencerConfigAddOptions(prefix string, f *flag.FlagSet) { @@ -127,6 +130,7 @@ func SequencerConfigAddOptions(prefix string, f *flag.FlagSet) { f.Int(prefix+".max-tx-data-size", DefaultSequencerConfig.MaxTxDataSize, "maximum transaction size the sequencer will accept") f.Int(prefix+".nonce-failure-cache-size", DefaultSequencerConfig.NonceFailureCacheSize, "number of transactions with too high of a nonce to keep in memory while waiting for their predecessor") f.Duration(prefix+".nonce-failure-cache-expiry", DefaultSequencerConfig.NonceFailureCacheExpiry, "maximum amount of time to wait for a predecessor before rejecting a tx with nonce too high") + f.Bool(prefix+".enable-prefetch-block", DefaultSequencerConfig.EnablePrefetchBlock, "enable prefetching of blocks") } type txQueueItem struct { @@ -324,6 +328,9 @@ func NewSequencer(execEngine *ExecutionEngine, l1Reader *headerreader.HeaderRead } s.Pause() execEngine.EnableReorgSequencing() + if config.EnablePrefetchBlock { + execEngine.EnablePrefetchBlock() + } return s, nil } diff --git a/execution/interface.go b/execution/interface.go index ef9409b9c..414c31f64 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -28,7 +28,7 @@ var ErrSequencerInsertLockTaken = errors.New("insert lock taken") // always needed type ExecutionClient interface { - DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata) error + DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) error Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadata, oldMessages []*arbostypes.MessageWithMetadata) error HeadMessageNumber() (arbutil.MessageIndex, error) HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) From 574fb738c71290d3055df78ae01f80d7e57cccf2 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Mon, 22 Jan 2024 08:54:16 -0800 Subject: [PATCH 631/775] go mod tidy after merging in geth-1.13 branch --- go.mod | 16 ++++++++-------- go.sum | 38 ++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/go.mod b/go.mod index bdda6a61a..f6f6bce80 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.10 github.com/aws/aws-sdk-go-v2/service/s3 v1.26.9 github.com/cavaliergopher/grab/v3 v3.0.1 - github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 + github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 github.com/codeclysm/extract/v3 v3.0.2 github.com/dgraph-io/badger/v3 v3.2103.2 github.com/enescakir/emoji v1.0.0 @@ -53,6 +53,7 @@ require ( bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc // indirect github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect github.com/DataDog/zstd v1.5.2 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect @@ -97,7 +98,7 @@ require ( github.com/dgraph-io/ristretto v0.1.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -131,7 +132,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect - github.com/huin/goupnp v1.1.0 // indirect + github.com/huin/goupnp v1.3.0 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect github.com/ipfs/go-block-format v0.1.1 // indirect @@ -307,13 +308,13 @@ require ( ) require ( - github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect - github.com/go-ole/go-ole v1.2.1 // indirect + github.com/go-ole/go-ole v1.2.5 // indirect github.com/go-redis/redis/v8 v8.11.4 github.com/go-stack/stack v1.8.1 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect @@ -333,8 +334,7 @@ require ( github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/status-im/keycard-go v0.2.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/tklauser/go-sysconf v0.3.5 // indirect - github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect - gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect ) diff --git a/go.sum b/go.sum index bf8b4b826..a0b83650a 100644 --- a/go.sum +++ b/go.sum @@ -55,6 +55,8 @@ github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKz github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= @@ -63,8 +65,8 @@ github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fT github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI+XWrX9Wf2XH0s= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -223,15 +225,15 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/datadriven v1.0.3-0.20230801171734-e384cf455877 h1:1MLK4YpFtIEo3ZtMA5C795Wtv5VuUnrXX7mQG+aHg6o= github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= -github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= +github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 h1:T+Np/xtzIjYM/P5NAw0e2Rf1FGvzDau1h54MKvx8G7w= +github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06/go.mod h1:bynZ3gvVyhlvjLI7PT6dmZ7g76xzJ7HpxfjgkzCGz6s= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= @@ -305,8 +307,8 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= +github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -401,8 +403,8 @@ github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -638,8 +640,8 @@ github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZm github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= -github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -1598,10 +1600,10 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= -github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= -github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= -github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= @@ -1948,6 +1950,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1987,7 +1990,6 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2009,6 +2011,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -2249,8 +2253,6 @@ gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= From 189912a109962521adb7a7f89b05bd6dcbad5a80 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 22 Jan 2024 14:10:08 -0700 Subject: [PATCH 632/775] update go.mod --- go.mod | 16 ++++++++-------- go.sum | 38 ++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/go.mod b/go.mod index bdda6a61a..f6f6bce80 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.10 github.com/aws/aws-sdk-go-v2/service/s3 v1.26.9 github.com/cavaliergopher/grab/v3 v3.0.1 - github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 + github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 github.com/codeclysm/extract/v3 v3.0.2 github.com/dgraph-io/badger/v3 v3.2103.2 github.com/enescakir/emoji v1.0.0 @@ -53,6 +53,7 @@ require ( bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc // indirect github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect github.com/DataDog/zstd v1.5.2 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect @@ -97,7 +98,7 @@ require ( github.com/dgraph-io/ristretto v0.1.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -131,7 +132,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect - github.com/huin/goupnp v1.1.0 // indirect + github.com/huin/goupnp v1.3.0 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect github.com/ipfs/go-block-format v0.1.1 // indirect @@ -307,13 +308,13 @@ require ( ) require ( - github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect - github.com/go-ole/go-ole v1.2.1 // indirect + github.com/go-ole/go-ole v1.2.5 // indirect github.com/go-redis/redis/v8 v8.11.4 github.com/go-stack/stack v1.8.1 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect @@ -333,8 +334,7 @@ require ( github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/status-im/keycard-go v0.2.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/tklauser/go-sysconf v0.3.5 // indirect - github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect - gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect ) diff --git a/go.sum b/go.sum index bf8b4b826..a0b83650a 100644 --- a/go.sum +++ b/go.sum @@ -55,6 +55,8 @@ github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKz github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= @@ -63,8 +65,8 @@ github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fT github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI+XWrX9Wf2XH0s= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -223,15 +225,15 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/datadriven v1.0.3-0.20230801171734-e384cf455877 h1:1MLK4YpFtIEo3ZtMA5C795Wtv5VuUnrXX7mQG+aHg6o= github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= -github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= +github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 h1:T+Np/xtzIjYM/P5NAw0e2Rf1FGvzDau1h54MKvx8G7w= +github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06/go.mod h1:bynZ3gvVyhlvjLI7PT6dmZ7g76xzJ7HpxfjgkzCGz6s= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= @@ -305,8 +307,8 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= +github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -401,8 +403,8 @@ github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -638,8 +640,8 @@ github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZm github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= -github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -1598,10 +1600,10 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= -github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= -github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= -github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= @@ -1948,6 +1950,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1987,7 +1990,6 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2009,6 +2011,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -2249,8 +2253,6 @@ gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= From cd2349a771d5cdfe10d2745b01af402cf13af563 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 22 Jan 2024 18:43:19 -0700 Subject: [PATCH 633/775] Add support for consensus v11.1 to Dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index b62e56925..2e60c427b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -165,6 +165,7 @@ RUN ./download-machine.sh consensus-v10.1 0xda4e3ad5e7feacb817c21c8d0220da7650fe RUN ./download-machine.sh consensus-v10.2 0x0754e09320c381566cc0449904c377a52bd34a6b9404432e80afd573b67f7b17 RUN ./download-machine.sh consensus-v10.3 0xf559b6d4fa869472dabce70fe1c15221bdda837533dfd891916836975b434dec RUN ./download-machine.sh consensus-v11 0xf4389b835497a910d7ba3ebfb77aa93da985634f3c052de1290360635be40c4a +RUN ./download-machine.sh consensus-v11.1 0x68e4fe5023f792d4ef584796c84d710303a5e12ea02d6e37e2b5e9c4332507c4 FROM golang:1.20-bullseye as node-builder WORKDIR /workspace From fe654290f345218a632139787f63cc5e39275c92 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Mon, 22 Jan 2024 17:46:13 -0800 Subject: [PATCH 634/775] Port BlobClient from old 4844 branch This ports BlobClient from the eip-4844-experimental branch, with the prysm dependency removed (relevant code copied to util/beaconclient) and the kZGToVersionedHash function copied from geth rather than modifying our fork to make it public as I had done before, since it is so simple. "A little copying is better than a little dependency." - Rob Pike, Go Proverbs --- arbnode/blob_reader.go | 185 +++++++++++++++++++++++++++++++++++ go.mod | 2 +- util/beaconclient/client.go | 98 +++++++++++++++++++ util/beaconclient/errors.go | 40 ++++++++ util/beaconclient/options.go | 48 +++++++++ 5 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 arbnode/blob_reader.go create mode 100644 util/beaconclient/client.go create mode 100644 util/beaconclient/errors.go create mode 100644 util/beaconclient/options.go diff --git a/arbnode/blob_reader.go b/arbnode/blob_reader.go new file mode 100644 index 000000000..673df37b1 --- /dev/null +++ b/arbnode/blob_reader.go @@ -0,0 +1,185 @@ +// Copyright 2023, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package arbnode + +import ( + "context" + "crypto/sha256" + "encoding/json" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto/kzg4844" + "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/util/beaconclient" + "github.com/offchainlabs/nitro/util/pretty" + "github.com/pkg/errors" + + "github.com/spf13/pflag" +) + +type BlobClient struct { + bc *beaconclient.Client + ec arbutil.L1Interface + + // The genesis time time won't change so only request it once. + cachedGenesisTime uint64 +} + +type BlobClientConfig struct { + BeaconChainUrl string `koanf:"beacon-chain-url"` +} + +var DefaultBlobClientConfig = BlobClientConfig{ + BeaconChainUrl: "", +} + +func BlobClientAddOptions(prefix string, f *pflag.FlagSet) { + f.String(prefix+".beacon-chain-url", DefaultBlobClientConfig.BeaconChainUrl, "Beacon Chain url to use for fetching blobs") +} + +func NewBlobClient(bc *beaconclient.Client, ec arbutil.L1Interface) *BlobClient { + return &BlobClient{bc: bc, ec: ec} +} + +// Get all the blobs associated with a particular block. +func (b *BlobClient) GetBlobs(ctx context.Context, blockHash common.Hash, versionedHashes []common.Hash) ([]kzg4844.Blob, error) { + header, err := b.ec.HeaderByHash(ctx, blockHash) + if err != nil { + return nil, err + } + + genesisTime, err := b.genesisTime(ctx) + if err != nil { + return nil, err + } + + // TODO make denominator configurable for devnets with faster block time + slot := (header.Time - genesisTime) / 12 + + return b.blobSidecars(ctx, slot, versionedHashes) +} + +type blobResponse struct { + Data []blobResponseItem `json:"data"` +} +type blobResponseItem struct { + BlockRoot string `json:"block_root"` + Index int `json:"index"` + Slot uint64 `json:"slot"` + BlockParentRoot string `json:"block_parent_root"` + ProposerIndex uint64 `json:"proposer_index"` + Blob string `json:"blob"` + KzgCommitment string `json:"kzg_commitment"` + KzgProof string `json:"kzg_proof"` +} + +func (b *BlobClient) blobSidecars(ctx context.Context, slot uint64, versionedHashes []common.Hash) ([]kzg4844.Blob, error) { + body, err := b.bc.Get(ctx, fmt.Sprintf("/eth/v1/beacon/blob_sidecars/%d", slot)) + if err != nil { + return nil, errors.Wrap(err, "error calling beacon client in blobSidecars") + } + + br := &blobResponse{} + err = json.Unmarshal(body, br) + if err != nil { + return nil, errors.Wrap(err, "error decoding json response in blobSidecars") + } + + if len(br.Data) == 0 { + return nil, fmt.Errorf("no blobs found for slot %d", slot) + } + + blobs := make([]kzg4844.Blob, len(versionedHashes)) + var totalFound int + + for i := range blobs { + commitmentBytes, err := hexutil.Decode(br.Data[i].KzgCommitment) + if err != nil { + return nil, fmt.Errorf("couldn't decode commitment for slot(%d) at index(%d), commitment(%s)", slot, br.Data[i].Index, pretty.FirstFewChars(br.Data[i].KzgCommitment)) + } + var commitment kzg4844.Commitment + copy(commitment[:], commitmentBytes) + versionedHash := kZGToVersionedHash(commitment) + + // The versioned hashes of the blob commitments are produced in the by HASH_OPCODE_BYTE, + // presumably in the order they were added to the tx. The spec is unclear if the blobs + // need to be returned in any particular order from the beacon API, so we put them back in + // the order from the tx. + var j int + var found bool + for j = range versionedHashes { + if versionedHashes[j] == versionedHash { + found = true + totalFound++ + break + } + } + if !found { + continue + } + + blob, err := hexutil.Decode(br.Data[i].Blob) + if err != nil { + return nil, fmt.Errorf("couldn't decode blob for slot(%d) at index(%d), blob(%s)", slot, br.Data[i].Index, pretty.FirstFewChars(br.Data[i].Blob)) + } + copy(blobs[j][:], blob) + + proofBytes, err := hexutil.Decode(br.Data[i].KzgProof) + if err != nil { + return nil, fmt.Errorf("couldn't decode proof for slot(%d) at index(%d), proof(%s)", slot, br.Data[i].Index, pretty.FirstFewChars(br.Data[i].KzgProof)) + } + var proof kzg4844.Proof + copy(proof[:], proofBytes) + + err = kzg4844.VerifyBlobProof(blobs[j], commitment, proof) + if err != nil { + return nil, fmt.Errorf("failed to verify blob proof for blob at slot(%d) at index(%d), blob(%s)", slot, br.Data[i].Index, pretty.FirstFewChars(br.Data[i].Blob)) + } + } + + if totalFound < len(versionedHashes) { + return nil, fmt.Errorf("not all of the requested blobs (%d/%d) were found at slot (%d), can't reconstruct batch payload", totalFound, len(versionedHashes), slot) + } + + return blobs, nil +} + +type genesisResponse struct { + GenesisTime uint64 `json:"genesis_time"` + // don't currently care about other fields, add if needed +} + +func (b *BlobClient) genesisTime(ctx context.Context) (uint64, error) { + if b.cachedGenesisTime > 0 { + return b.cachedGenesisTime, nil + } + + body, err := b.bc.Get(ctx, "/eth/v1/beacon/genesis") + if err != nil { + return 0, errors.Wrap(err, "error calling beacon client in genesisTime") + } + + gr := &genesisResponse{} + dataWrapper := &struct{ Data *genesisResponse }{Data: gr} + err = json.Unmarshal(body, dataWrapper) + if err != nil { + return 0, errors.Wrap(err, "error decoding json response in genesisTime") + } + + return gr.GenesisTime, nil +} + +// The following code is taken from core/vm/contracts.go +const ( + blobCommitmentVersionKZG uint8 = 0x01 // Version byte for the point evaluation precompile. +) + +func kZGToVersionedHash(kzg kzg4844.Commitment) common.Hash { + h := sha256.Sum256(kzg[:]) + h[0] = blobCommitmentVersionKZG + + return h +} diff --git a/go.mod b/go.mod index f6f6bce80..69cbcd988 100644 --- a/go.mod +++ b/go.mod @@ -36,6 +36,7 @@ require ( github.com/libp2p/go-libp2p v0.27.8 github.com/multiformats/go-multiaddr v0.9.0 github.com/multiformats/go-multihash v0.2.1 + github.com/pkg/errors v0.9.1 github.com/r3labs/diff/v3 v3.0.1 github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 github.com/spf13/pflag v1.0.5 @@ -233,7 +234,6 @@ require ( github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/openzipkin/zipkin-go v0.4.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/polydawn/refmt v0.89.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect diff --git a/util/beaconclient/client.go b/util/beaconclient/client.go new file mode 100644 index 000000000..e2dfd8e6b --- /dev/null +++ b/util/beaconclient/client.go @@ -0,0 +1,98 @@ +package beaconclient + +import ( + "context" + "io" + "net" + "net/http" + "net/url" + + "github.com/pkg/errors" +) + +// Client is a wrapper object around the HTTP client. +// Taken from prysm/api/client. +type Client struct { + hc *http.Client + baseURL *url.URL + token string +} + +// NewClient constructs a new client with the provided options (ex WithTimeout). +// `host` is the base host + port used to construct request urls. This value can be +// a URL string, or NewClient will assume an http endpoint if just `host:port` is used. +func NewClient(host string, opts ...ClientOpt) (*Client, error) { + u, err := urlForHost(host) + if err != nil { + return nil, err + } + c := &Client{ + hc: &http.Client{}, + baseURL: u, + } + for _, o := range opts { + o(c) + } + return c, nil +} + +// Token returns the bearer token used for jwt authentication +func (c *Client) Token() string { + return c.token +} + +// BaseURL returns the base url of the client +func (c *Client) BaseURL() *url.URL { + return c.baseURL +} + +// Do execute the request against the http client +func (c *Client) Do(req *http.Request) (*http.Response, error) { + return c.hc.Do(req) +} + +func urlForHost(h string) (*url.URL, error) { + // try to parse as url (being permissive) + u, err := url.Parse(h) + if err == nil && u.Host != "" { + return u, nil + } + // try to parse as host:port + host, port, err := net.SplitHostPort(h) + if err != nil { + return nil, ErrMalformedHostname + } + return &url.URL{Host: net.JoinHostPort(host, port), Scheme: "http"}, nil +} + +// NodeURL returns a human-readable string representation of the beacon node base url. +func (c *Client) NodeURL() string { + return c.baseURL.String() +} + +// Get is a generic, opinionated GET function to reduce boilerplate amongst the getters in this package. +func (c *Client) Get(ctx context.Context, path string, opts ...ReqOption) ([]byte, error) { + u := c.baseURL.ResolveReference(&url.URL{Path: path}) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) + if err != nil { + return nil, err + } + for _, o := range opts { + o(req) + } + r, err := c.hc.Do(req) + if err != nil { + return nil, err + } + defer func() { + err = r.Body.Close() + }() + if r.StatusCode != http.StatusOK { + return nil, Non200Err(r) + } + b, err := io.ReadAll(r.Body) + if err != nil { + return nil, errors.Wrap(err, "error reading http response body") + } + return b, nil +} diff --git a/util/beaconclient/errors.go b/util/beaconclient/errors.go new file mode 100644 index 000000000..7ee88805c --- /dev/null +++ b/util/beaconclient/errors.go @@ -0,0 +1,40 @@ +package beaconclient + +import ( + "fmt" + "io" + "net/http" + + "github.com/pkg/errors" +) + +// ErrMalformedHostname is used to indicate if a host name's format is incorrect. +var ErrMalformedHostname = errors.New("hostname must include port, separated by one colon, like example.com:3500") + +// ErrNotOK is used to indicate when an HTTP request to the API failed with any non-2xx response code. +// More specific errors may be returned, but an error in reaction to a non-2xx response will always wrap ErrNotOK. +var ErrNotOK = errors.New("did not receive 2xx response from API") + +// ErrNotFound specifically means that a '404 - NOT FOUND' response was received from the API. +var ErrNotFound = errors.Wrap(ErrNotOK, "recv 404 NotFound response from API") + +// ErrInvalidNodeVersion indicates that the /eth/v1/node/version API response format was not recognized. +var ErrInvalidNodeVersion = errors.New("invalid node version response") + +// Non200Err is a function that parses an HTTP response to handle responses that are not 200 with a formatted error. +func Non200Err(response *http.Response) error { + bodyBytes, err := io.ReadAll(response.Body) + var body string + if err != nil { + body = "(Unable to read response body.)" + } else { + body = "response body:\n" + string(bodyBytes) + } + msg := fmt.Sprintf("code=%d, url=%s, body=%s", response.StatusCode, response.Request.URL, body) + switch response.StatusCode { + case 404: + return errors.Wrap(ErrNotFound, msg) + default: + return errors.Wrap(ErrNotOK, msg) + } +} diff --git a/util/beaconclient/options.go b/util/beaconclient/options.go new file mode 100644 index 000000000..98a37e17a --- /dev/null +++ b/util/beaconclient/options.go @@ -0,0 +1,48 @@ +package beaconclient + +import ( + "fmt" + "net/http" + "time" +) + +// ReqOption is a request functional option. +type ReqOption func(*http.Request) + +// WithSSZEncoding is a request functional option that adds SSZ encoding header. +func WithSSZEncoding() ReqOption { + return func(req *http.Request) { + req.Header.Set("Accept", "application/octet-stream") + } +} + +// WithAuthorizationToken is a request functional option that adds header for authorization token. +func WithAuthorizationToken(token string) ReqOption { + return func(req *http.Request) { + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) + } +} + +// ClientOpt is a functional option for the Client type (http.Client wrapper) +type ClientOpt func(*Client) + +// WithTimeout sets the .Timeout attribute of the wrapped http.Client. +func WithTimeout(timeout time.Duration) ClientOpt { + return func(c *Client) { + c.hc.Timeout = timeout + } +} + +// WithRoundTripper replaces the underlying HTTP's transport with a custom one. +func WithRoundTripper(t http.RoundTripper) ClientOpt { + return func(c *Client) { + c.hc.Transport = t + } +} + +// WithAuthenticationToken sets an oauth token to be used. +func WithAuthenticationToken(token string) ClientOpt { + return func(c *Client) { + c.token = token + } +} From eefa47a66e7c2d1622b442803bc6b5cb51f291c4 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 22 Jan 2024 19:56:02 -0700 Subject: [PATCH 635/775] Rename HexBytes to HexBytesParser --- arbitrator/prover/src/kzg.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arbitrator/prover/src/kzg.rs b/arbitrator/prover/src/kzg.rs index 9eff9747e..280073aac 100644 --- a/arbitrator/prover/src/kzg.rs +++ b/arbitrator/prover/src/kzg.rs @@ -9,9 +9,9 @@ use serde::{de::Error as _, Deserialize}; use sha2::{Digest, Sha256}; use std::{convert::TryFrom, io::Write}; -struct HexBytes; +struct HexBytesParser; -impl<'de, const N: usize> serde_with::DeserializeAs<'de, [u8; N]> for HexBytes { +impl<'de, const N: usize> serde_with::DeserializeAs<'de, [u8; N]> for HexBytesParser { fn deserialize_as(deserializer: D) -> Result<[u8; N], D::Error> where D: serde::Deserializer<'de>, @@ -31,9 +31,9 @@ impl<'de, const N: usize> serde_with::DeserializeAs<'de, [u8; N]> for HexBytes { #[derive(Deserialize)] struct TrustedSetup { - #[serde(with = "serde_with::As::>")] + #[serde(with = "serde_with::As::>")] g1_lagrange: Vec<[u8; BYTES_PER_G1_POINT]>, - #[serde(with = "serde_with::As::>")] + #[serde(with = "serde_with::As::>")] g2_monomial: Vec<[u8; BYTES_PER_G2_POINT]>, } From 11e61aafd6b41623e5989cd64dd46ad97cfc1a9a Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 22 Jan 2024 21:07:46 -0700 Subject: [PATCH 636/775] Implement 4844 blob reading in replay binary --- arbnode/delayed_seq_reorg_test.go | 2 +- arbnode/inbox_tracker.go | 14 ++++-- arbnode/node.go | 16 +++++- arbstate/das_reader.go | 7 +++ arbstate/inbox.go | 49 ++++++++++++++++-- arbstate/inbox_fuzz_test.go | 9 ++-- cmd/pruning/pruning.go | 2 +- cmd/replay/main.go | 32 ++++++++++-- staker/stateless_block_validator.go | 4 ++ system_tests/state_fuzz_test.go | 8 +-- util/blobs/blobs.go | 77 +++++++++++++++++++++++++++++ 11 files changed, 196 insertions(+), 24 deletions(-) create mode 100644 util/blobs/blobs.go diff --git a/arbnode/delayed_seq_reorg_test.go b/arbnode/delayed_seq_reorg_test.go index 9ad984ae6..beb2656e2 100644 --- a/arbnode/delayed_seq_reorg_test.go +++ b/arbnode/delayed_seq_reorg_test.go @@ -19,7 +19,7 @@ func TestSequencerReorgFromDelayed(t *testing.T) { defer cancel() exec, streamer, db, _ := NewTransactionStreamerForTest(t, common.Address{}) - tracker, err := NewInboxTracker(db, streamer, nil) + tracker, err := NewInboxTracker(db, streamer, nil, nil) Require(t, err) err = streamer.Start(ctx) diff --git a/arbnode/inbox_tracker.go b/arbnode/inbox_tracker.go index 51f74cbeb..eaf863bff 100644 --- a/arbnode/inbox_tracker.go +++ b/arbnode/inbox_tracker.go @@ -38,12 +38,13 @@ type InboxTracker struct { mutex sync.Mutex validator *staker.BlockValidator das arbstate.DataAvailabilityReader + blobReader arbstate.BlobReader batchMetaMutex sync.Mutex batchMeta *containers.LruCache[uint64, BatchMetadata] } -func NewInboxTracker(db ethdb.Database, txStreamer *TransactionStreamer, das arbstate.DataAvailabilityReader) (*InboxTracker, error) { +func NewInboxTracker(db ethdb.Database, txStreamer *TransactionStreamer, das arbstate.DataAvailabilityReader, blobReader arbstate.BlobReader) (*InboxTracker, error) { // We support a nil txStreamer for the pruning code if txStreamer != nil && txStreamer.chainConfig.ArbitrumChainParams.DataAvailabilityCommittee && das == nil { return nil, errors.New("data availability service required but unconfigured") @@ -52,6 +53,7 @@ func NewInboxTracker(db ethdb.Database, txStreamer *TransactionStreamer, das arb db: db, txStreamer: txStreamer, das: das, + blobReader: blobReader, batchMeta: containers.NewLruCache[uint64, BatchMetadata](1000), } return tracker, nil @@ -504,11 +506,12 @@ type multiplexerBackend struct { inbox *InboxTracker } -func (b *multiplexerBackend) PeekSequencerInbox() ([]byte, error) { +func (b *multiplexerBackend) PeekSequencerInbox() ([]byte, common.Hash, error) { if len(b.batches) == 0 { - return nil, errors.New("read past end of specified sequencer batches") + return nil, common.Hash{}, errors.New("read past end of specified sequencer batches") } - return b.batches[0].Serialize(b.ctx, b.client) + bytes, err := b.batches[0].Serialize(b.ctx, b.client) + return bytes, b.batches[0].BlockHash, err } func (b *multiplexerBackend) GetSequencerInboxPosition() uint64 { @@ -603,7 +606,8 @@ func (t *InboxTracker) AddSequencerBatches(ctx context.Context, client arbutil.L ctx: ctx, client: client, } - multiplexer := arbstate.NewInboxMultiplexer(backend, prevbatchmeta.DelayedMessageCount, t.das, arbstate.KeysetValidate) + + multiplexer := arbstate.NewInboxMultiplexer(backend, prevbatchmeta.DelayedMessageCount, t.das, t.blobReader, arbstate.KeysetValidate) batchMessageCounts := make(map[uint64]arbutil.MessageIndex) currentpos := prevbatchmeta.MessageCount + 1 for { diff --git a/arbnode/node.go b/arbnode/node.go index 6119a4fb5..99ecb541e 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -26,6 +26,7 @@ import ( "github.com/offchainlabs/nitro/arbnode/dataposter" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbnode/resourcemanager" + "github.com/offchainlabs/nitro/arbstate" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcastclient" "github.com/offchainlabs/nitro/broadcastclients" @@ -39,6 +40,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/staker/validatorwallet" + "github.com/offchainlabs/nitro/util/beaconclient" "github.com/offchainlabs/nitro/util/contracts" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/redisutil" @@ -85,6 +87,7 @@ type Config struct { Staker staker.L1ValidatorConfig `koanf:"staker" reload:"hot"` SeqCoordinator SeqCoordinatorConfig `koanf:"seq-coordinator"` DataAvailability das.DataAvailabilityConfig `koanf:"data-availability"` + BlobClient BlobClientConfig `koanf:"blob-client"` SyncMonitor SyncMonitorConfig `koanf:"sync-monitor"` Dangerous DangerousConfig `koanf:"dangerous"` TransactionStreamer TransactionStreamerConfig `koanf:"transaction-streamer" reload:"hot"` @@ -142,6 +145,7 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet, feedInputEnable bool, feed staker.L1ValidatorConfigAddOptions(prefix+".staker", f) SeqCoordinatorConfigAddOptions(prefix+".seq-coordinator", f) das.DataAvailabilityConfigAddNodeOptions(prefix+".data-availability", f) + BlobClientAddOptions(prefix+".blob-client", f) SyncMonitorConfigAddOptions(prefix+".sync-monitor", f) DangerousConfigAddOptions(prefix+".dangerous", f) TransactionStreamerConfigAddOptions(prefix+".transaction-streamer", f) @@ -512,7 +516,17 @@ func createNodeImpl( return nil, errors.New("a data availability service is required for this chain, but it was not configured") } - inboxTracker, err := NewInboxTracker(arbDb, txStreamer, daReader) + var blobReader arbstate.BlobReader + if config.BlobClient.BeaconChainUrl != "" { + bc, err := beaconclient.NewClient(config.BlobClient.BeaconChainUrl) + if err != nil { + return nil, err + } + + blobReader = NewBlobClient(bc, l1client) + } + + inboxTracker, err := NewInboxTracker(arbDb, txStreamer, daReader, blobReader) if err != nil { return nil, err } diff --git a/arbstate/das_reader.go b/arbstate/das_reader.go index a6d351b49..5f568605b 100644 --- a/arbstate/das_reader.go +++ b/arbstate/das_reader.go @@ -40,6 +40,9 @@ const L1AuthenticatedMessageHeaderFlag byte = 0x40 // ZeroheavyMessageHeaderFlag indicates that this message is zeroheavy-encoded. const ZeroheavyMessageHeaderFlag byte = 0x20 +// BlobHashesHeaderFlag indicates that this message contains EIP 4844 versioned hashes of the committments calculated over the blob data for the batch data. +const BlobHashesHeaderFlag byte = L1AuthenticatedMessageHeaderFlag | 0x10 // 0x50 + // BrotliMessageHeaderByte indicates that the message is brotli-compressed. const BrotliMessageHeaderByte byte = 0 @@ -55,6 +58,10 @@ func IsZeroheavyEncodedHeaderByte(header byte) bool { return (ZeroheavyMessageHeaderFlag & header) > 0 } +func IsBlobHashesHeaderByte(header byte) bool { + return (BlobHashesHeaderFlag & header) > 0 +} + func IsBrotliMessageHeaderByte(b uint8) bool { return b == BrotliMessageHeaderByte } diff --git a/arbstate/inbox.go b/arbstate/inbox.go index 3995bcf30..cf8f61e97 100644 --- a/arbstate/inbox.go +++ b/arbstate/inbox.go @@ -8,11 +8,13 @@ import ( "context" "encoding/binary" "errors" + "fmt" "io" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" @@ -21,11 +23,12 @@ import ( "github.com/offchainlabs/nitro/arbos/l1pricing" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/das/dastree" + "github.com/offchainlabs/nitro/util/blobs" "github.com/offchainlabs/nitro/zeroheavy" ) type InboxBackend interface { - PeekSequencerInbox() ([]byte, error) + PeekSequencerInbox() ([]byte, common.Hash, error) GetSequencerInboxPosition() uint64 AdvanceSequencerInbox() @@ -36,6 +39,14 @@ type InboxBackend interface { ReadDelayedInbox(seqNum uint64) (*arbostypes.L1IncomingMessage, error) } +type BlobReader interface { + GetBlobs( + ctx context.Context, + batchBlockHash common.Hash, + versionedHashes []common.Hash, + ) ([]kzg4844.Blob, error) +} + type sequencerMessage struct { minTimestamp uint64 maxTimestamp uint64 @@ -50,7 +61,7 @@ const maxZeroheavyDecompressedLen = 101*MaxDecompressedLen/100 + 64 const MaxSegmentsPerSequencerMessage = 100 * 1024 const MinLifetimeSecondsForDataAvailabilityCert = 7 * 24 * 60 * 60 // one week -func parseSequencerMessage(ctx context.Context, batchNum uint64, data []byte, dasReader DataAvailabilityReader, keysetValidationMode KeysetValidationMode) (*sequencerMessage, error) { +func parseSequencerMessage(ctx context.Context, batchNum uint64, batchBlockHash common.Hash, data []byte, dasReader DataAvailabilityReader, blobReader BlobReader, keysetValidationMode KeysetValidationMode) (*sequencerMessage, error) { if len(data) < 40 { return nil, errors.New("sequencer message missing L1 header") } @@ -79,6 +90,31 @@ func parseSequencerMessage(ctx context.Context, batchNum uint64, data []byte, da } } + if len(payload) > 0 && IsBlobHashesHeaderByte(payload[0]) { + blobHashes := payload[1:] + if len(blobHashes)%len(common.Hash{}) != 0 { + return nil, fmt.Errorf("blob batch data is not a list of hashes as expected") + } + versionedHashes := make([]common.Hash, len(blobHashes)/len(common.Hash{})) + for i := 0; i*32 < len(blobHashes); i += 1 { + copy(versionedHashes[i][:], blobHashes[i*32:(i+1)*32]) + } + + if blobReader == nil { + return nil, errors.New("blob batch payload was encountered but no BlobReader was configured") + } + + kzgBlobs, err := blobReader.GetBlobs(ctx, batchBlockHash, versionedHashes) + if err != nil { + return nil, fmt.Errorf("failed to get blobs: %w", err) + } + payload, err = blobs.DecodeBlobs(kzgBlobs) + if err != nil { + log.Warn("Failed to decode blobs", "batchBlockHash", batchBlockHash, "versionedHashes", versionedHashes, "err", err) + return parsedMsg, nil + } + } + if len(payload) > 0 && IsZeroheavyEncodedHeaderByte(payload[0]) { pl, err := io.ReadAll(io.LimitReader(zeroheavy.NewZeroheavyDecoder(bytes.NewReader(payload[1:])), int64(maxZeroheavyDecompressedLen))) if err != nil { @@ -242,6 +278,7 @@ type inboxMultiplexer struct { backend InboxBackend delayedMessagesRead uint64 dasReader DataAvailabilityReader + blobReader BlobReader cachedSequencerMessage *sequencerMessage cachedSequencerMessageNum uint64 cachedSegmentNum uint64 @@ -251,11 +288,12 @@ type inboxMultiplexer struct { keysetValidationMode KeysetValidationMode } -func NewInboxMultiplexer(backend InboxBackend, delayedMessagesRead uint64, dasReader DataAvailabilityReader, keysetValidationMode KeysetValidationMode) arbostypes.InboxMultiplexer { +func NewInboxMultiplexer(backend InboxBackend, delayedMessagesRead uint64, dasReader DataAvailabilityReader, blobReader BlobReader, keysetValidationMode KeysetValidationMode) arbostypes.InboxMultiplexer { return &inboxMultiplexer{ backend: backend, delayedMessagesRead: delayedMessagesRead, dasReader: dasReader, + blobReader: blobReader, keysetValidationMode: keysetValidationMode, } } @@ -270,13 +308,14 @@ const BatchSegmentKindAdvanceL1BlockNumber uint8 = 4 // Note: this does *not* return parse errors, those are transformed into invalid messages func (r *inboxMultiplexer) Pop(ctx context.Context) (*arbostypes.MessageWithMetadata, error) { if r.cachedSequencerMessage == nil { - bytes, realErr := r.backend.PeekSequencerInbox() + // Note: batchBlockHash will be zero in the replay binary, but that's fine + bytes, batchBlockHash, realErr := r.backend.PeekSequencerInbox() if realErr != nil { return nil, realErr } r.cachedSequencerMessageNum = r.backend.GetSequencerInboxPosition() var err error - r.cachedSequencerMessage, err = parseSequencerMessage(ctx, r.cachedSequencerMessageNum, bytes, r.dasReader, r.keysetValidationMode) + r.cachedSequencerMessage, err = parseSequencerMessage(ctx, r.cachedSequencerMessageNum, batchBlockHash, bytes, r.dasReader, r.blobReader, r.keysetValidationMode) if err != nil { return nil, err } diff --git a/arbstate/inbox_fuzz_test.go b/arbstate/inbox_fuzz_test.go index fcb80cbd7..dcf43fd0d 100644 --- a/arbstate/inbox_fuzz_test.go +++ b/arbstate/inbox_fuzz_test.go @@ -9,6 +9,7 @@ import ( "errors" "testing" + "github.com/ethereum/go-ethereum/common" "github.com/offchainlabs/nitro/arbos/arbostypes" ) @@ -19,11 +20,11 @@ type multiplexerBackend struct { positionWithinMessage uint64 } -func (b *multiplexerBackend) PeekSequencerInbox() ([]byte, error) { +func (b *multiplexerBackend) PeekSequencerInbox() ([]byte, common.Hash, error) { if b.batchSeqNum != 0 { - return nil, errors.New("reading unknown sequencer batch") + return nil, common.Hash{}, errors.New("reading unknown sequencer batch") } - return b.batch, nil + return b.batch, common.Hash{}, nil } func (b *multiplexerBackend) GetSequencerInboxPosition() uint64 { @@ -66,7 +67,7 @@ func FuzzInboxMultiplexer(f *testing.F) { delayedMessage: delayedMsg, positionWithinMessage: 0, } - multiplexer := NewInboxMultiplexer(backend, 0, nil, KeysetValidate) + multiplexer := NewInboxMultiplexer(backend, 0, nil, nil, KeysetValidate) _, err := multiplexer.Pop(context.TODO()) if err != nil { panic(err) diff --git a/cmd/pruning/pruning.go b/cmd/pruning/pruning.go index 68d89302f..da015ac52 100644 --- a/cmd/pruning/pruning.go +++ b/cmd/pruning/pruning.go @@ -189,7 +189,7 @@ func findImportantRoots(ctx context.Context, chainDb ethdb.Database, stack *node return nil, fmt.Errorf("failed to get finalized block: %w", err) } l1BlockNum := l1Block.NumberU64() - tracker, err := arbnode.NewInboxTracker(arbDb, nil, nil) + tracker, err := arbnode.NewInboxTracker(arbDb, nil, nil, nil) if err != nil { return nil, err } diff --git a/cmd/replay/main.go b/cmd/replay/main.go index 2fb13ceed..b634a2d5b 100644 --- a/cmd/replay/main.go +++ b/cmd/replay/main.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" @@ -62,11 +63,12 @@ func (c WavmChainContext) GetHeader(hash common.Hash, num uint64) *types.Header type WavmInbox struct{} -func (i WavmInbox) PeekSequencerInbox() ([]byte, error) { +func (i WavmInbox) PeekSequencerInbox() ([]byte, common.Hash, error) { pos := wavmio.GetInboxPosition() res := wavmio.ReadInboxMessage(pos) log.Info("PeekSequencerInbox", "pos", pos, "res[:8]", res[:8]) - return res, nil + // Our BlobPreimageReader doesn't need the block hash + return res, common.Hash{}, nil } func (i WavmInbox) GetSequencerInboxPosition() uint64 { @@ -117,6 +119,30 @@ func (dasReader *PreimageDASReader) ExpirationPolicy(ctx context.Context) (arbst return arbstate.DiscardImmediately, nil } +type BlobPreimageReader struct { +} + +func (r *BlobPreimageReader) GetBlobs( + ctx context.Context, + batchBlockHash common.Hash, + versionedHashes []common.Hash, +) ([]kzg4844.Blob, error) { + var blobs []kzg4844.Blob + for _, h := range versionedHashes { + var blob kzg4844.Blob + var preimage []byte + if true { + panic("TODO: fill in preimage with wavmio.ResolvePreimage(h, wavmio.PreimageTypeEthVersionedHash) once KZG proof support is merged into this branch") + } + if len(preimage) != len(blob) { + return nil, fmt.Errorf("for blob %v got back preimage of length %v but expected blob length %v", h, len(preimage), len(blob)) + } + copy(blob[:], preimage) + blobs = append(blobs, blob) + } + return blobs, nil +} + // To generate: // key, _ := crypto.HexToECDSA("0000000000000000000000000000000000000000000000000000000000000001") // sig, _ := crypto.Sign(make([]byte, 32), key) @@ -180,7 +206,7 @@ func main() { if backend.GetPositionWithinMessage() > 0 { keysetValidationMode = arbstate.KeysetDontValidate } - inboxMultiplexer := arbstate.NewInboxMultiplexer(backend, delayedMessagesRead, dasReader, keysetValidationMode) + inboxMultiplexer := arbstate.NewInboxMultiplexer(backend, delayedMessagesRead, dasReader, &BlobPreimageReader{}, keysetValidationMode) ctx := context.Background() message, err := inboxMultiplexer.Pop(ctx) if err != nil { diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index acd86f862..d35304be2 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -284,6 +284,10 @@ func (v *StatelessBlockValidator) ValidationEntryRecord(ctx context.Context, e * if len(batch.Data) <= 40 { continue } + if arbstate.IsBlobHashesHeaderByte(batch.Data[40]) { + // TODO: fetch blob preimages + panic("TODO: fetch blob preimages") + } if !arbstate.IsDASMessageHeaderByte(batch.Data[40]) { continue } diff --git a/system_tests/state_fuzz_test.go b/system_tests/state_fuzz_test.go index b14215fbf..28bcbec9b 100644 --- a/system_tests/state_fuzz_test.go +++ b/system_tests/state_fuzz_test.go @@ -41,7 +41,7 @@ func BuildBlock( if lastBlockHeader != nil { delayedMessagesRead = lastBlockHeader.Nonce.Uint64() } - inboxMultiplexer := arbstate.NewInboxMultiplexer(inbox, delayedMessagesRead, nil, arbstate.KeysetValidate) + inboxMultiplexer := arbstate.NewInboxMultiplexer(inbox, delayedMessagesRead, nil, nil, arbstate.KeysetValidate) ctx := context.Background() message, err := inboxMultiplexer.Pop(ctx) @@ -69,11 +69,11 @@ type inboxBackend struct { delayedMessages [][]byte } -func (b *inboxBackend) PeekSequencerInbox() ([]byte, error) { +func (b *inboxBackend) PeekSequencerInbox() ([]byte, common.Hash, error) { if len(b.batches) == 0 { - return nil, errors.New("read past end of specified sequencer batches") + return nil, common.Hash{}, errors.New("read past end of specified sequencer batches") } - return b.batches[0], nil + return b.batches[0], common.Hash{}, nil } func (b *inboxBackend) GetSequencerInboxPosition() uint64 { diff --git a/util/blobs/blobs.go b/util/blobs/blobs.go new file mode 100644 index 000000000..c8025dc25 --- /dev/null +++ b/util/blobs/blobs.go @@ -0,0 +1,77 @@ +// Copyright 2023-2024, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package blobs + +import ( + "crypto/sha256" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto/kzg4844" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" +) + +// EncodeBlobs takes in raw bytes data to convert into blobs used for KZG commitment EIP-4844 +// transactions on Ethereum. +func EncodeBlobs(data []byte) ([]kzg4844.Blob, error) { + data, err := rlp.EncodeToBytes(data) + if err != nil { + return nil, err + } + blobs := []kzg4844.Blob{{}} + blobIndex := 0 + fieldIndex := -1 + for i := 0; i < len(data); i += 31 { + fieldIndex++ + if fieldIndex == params.BlobTxFieldElementsPerBlob { + blobs = append(blobs, kzg4844.Blob{}) + blobIndex++ + fieldIndex = 0 + } + max := i + 31 + if max > len(data) { + max = len(data) + } + copy(blobs[blobIndex][fieldIndex*32+1:], data[i:max]) + } + return blobs, nil +} + +// DecodeBlobs decodes blobs into the batch data encoded in them. +func DecodeBlobs(blobs []kzg4844.Blob) ([]byte, error) { + var rlpData []byte + for _, blob := range blobs { + for fieldIndex := 0; fieldIndex < params.BlobTxFieldElementsPerBlob; fieldIndex++ { + rlpData = append(rlpData, blob[fieldIndex*32+1:(fieldIndex+1)*32]...) + } + } + var outputData []byte + err := rlp.DecodeBytes(rlpData, &outputData) + return outputData, err +} + +// Return KZG commitments, proofs, and versioned hashes that corresponds to these blobs +func ComputeCommitmentsProofsAndHashes(blobs []kzg4844.Blob) ([]kzg4844.Commitment, []kzg4844.Proof, []common.Hash, error) { + commitments := make([]kzg4844.Commitment, len(blobs)) + proofs := make([]kzg4844.Proof, len(blobs)) + versionedHashes := make([]common.Hash, len(blobs)) + + for i := range blobs { + var err error + commitments[i], err = kzg4844.BlobToCommitment(blobs[i]) + if err != nil { + return nil, nil, nil, err + } + proofs[i], err = kzg4844.ComputeBlobProof(blobs[i], commitments[i]) + if err != nil { + return nil, nil, nil, err + } + // As per the EIP-4844 spec, the versioned hash is the SHA-256 hash of the commitment with the first byte set to 1. + hash := sha256.Sum256(commitments[i][:]) + hash[0] = 1 + versionedHashes[i] = hash + } + + return commitments, proofs, versionedHashes, nil +} From 511480e86ba87752b7d06977f6fafee447e9f5e0 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 22 Jan 2024 21:14:21 -0700 Subject: [PATCH 637/775] Add foundry to CI --- .github/workflows/arbitrator-ci.yml | 5 +++++ .github/workflows/ci.yml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index 8c491a421..96080831c 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -96,6 +96,11 @@ jobs: make -j make install + - name: Install foundry + run: | + curl -L https://foundry.paradigm.xyz | bash + foundryup + - name: Cache cbrotli uses: actions/cache@v3 id: cache-cbrotli diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2c4fac84..7ebc3b873 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,6 +58,11 @@ jobs: with: targets: 'wasm32-unknown-unknown, wasm32-wasi' + - name: Install foundry + run: | + curl -L https://foundry.paradigm.xyz | bash + foundryup + - name: Cache Build Products uses: actions/cache@v3 with: From 5377d0f8e527240bd24b567c106945c163502b34 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 22 Jan 2024 21:21:04 -0700 Subject: [PATCH 638/775] Install foundry in docker and fix CI --- .github/workflows/arbitrator-ci.yml | 6 ++---- .github/workflows/ci.yml | 6 ++---- Dockerfile | 5 +++-- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index 96080831c..571f3ca98 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -96,10 +96,8 @@ jobs: make -j make install - - name: Install foundry - run: | - curl -L https://foundry.paradigm.xyz | bash - foundryup + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 - name: Cache cbrotli uses: actions/cache@v3 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ebc3b873..fbf00bcb2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,10 +58,8 @@ jobs: with: targets: 'wasm32-unknown-unknown, wasm32-wasi' - - name: Install foundry - run: | - curl -L https://foundry.paradigm.xyz | bash - foundryup + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 - name: Cache Build Products uses: actions/cache@v3 diff --git a/Dockerfile b/Dockerfile index b62e56925..ea3294190 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,13 +26,14 @@ COPY --from=brotli-library-builder /workspace/install/ / FROM node:16-bullseye-slim as contracts-builder RUN apt-get update && \ - apt-get install -y git python3 make g++ + apt-get install -y git python3 make g++ curl +RUN curl -L https://foundry.paradigm.xyz | bash && . ~/.bashrc && ~/.foundry/bin/foundryup WORKDIR /workspace COPY contracts/package.json contracts/yarn.lock contracts/ RUN cd contracts && yarn install COPY contracts contracts/ COPY Makefile . -RUN NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-solidity +RUN . ~/.bashrc && NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-solidity FROM debian:bullseye-20211220 as wasm-base WORKDIR /workspace From 6cca7042da059ddfbec16ff35a52139f424fc47e Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 22 Jan 2024 21:32:34 -0700 Subject: [PATCH 639/775] Fix docker build --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index ea3294190..173c0ff2a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -184,6 +184,7 @@ COPY fastcache/go.mod fastcache/go.sum fastcache/ RUN go mod download COPY . ./ COPY --from=contracts-builder workspace/contracts/build/ contracts/build/ +COPY --from=contracts-builder workspace/contracts/out/ contracts/out/ COPY --from=contracts-builder workspace/contracts/node_modules/@offchainlabs/upgrade-executor/build/contracts/src/UpgradeExecutor.sol/UpgradeExecutor.json contracts/node_modules/@offchainlabs/upgrade-executor/build/contracts/src/UpgradeExecutor.sol/ COPY --from=contracts-builder workspace/.make/ .make/ COPY --from=prover-header-export / target/ From 609b4cf43a2279703282cdd779c6ac01fa106868 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 22 Jan 2024 23:59:07 -0700 Subject: [PATCH 640/775] Add 4844 blob tx support to data poster (rbf is wip) --- arbnode/batch_poster.go | 1 + arbnode/dataposter/data_poster.go | 178 ++++++++++++++++++++------ arbnode/dataposter/storage/storage.go | 10 +- arbnode/dataposter/storage_test.go | 2 +- staker/validatorwallet/contract.go | 7 +- staker/validatorwallet/eoa.go | 3 +- 6 files changed, 152 insertions(+), 49 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 07034ee6f..01a84b1c4 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -1071,6 +1071,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) data, gasLimit, new(big.Int), + nil, // TODO: use blobs accessList, ) if err != nil { diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 09f3e218b..425dba8e1 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -23,7 +23,9 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -31,12 +33,14 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/go-redis/redis/v8" + "github.com/holiman/uint256" "github.com/offchainlabs/nitro/arbnode/dataposter/dbstorage" "github.com/offchainlabs/nitro/arbnode/dataposter/noop" "github.com/offchainlabs/nitro/arbnode/dataposter/slice" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/blobs" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/signature" "github.com/offchainlabs/nitro/util/stopwaiter" @@ -64,6 +68,7 @@ type DataPoster struct { metadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error) extraBacklog func() uint64 parentChainID *big.Int + parentChainID256 *uint256.Int // These fields are protected by the mutex. // TODO: factor out these fields into separate structure, since now one @@ -177,6 +182,11 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro extraBacklog: opts.ExtraBacklog, parentChainID: opts.ParentChainID, } + var overflow bool + dp.parentChainID256, overflow = uint256.FromBig(opts.ParentChainID) + if overflow { + return nil, fmt.Errorf("parent chain ID %v overflows uint256 (necessary for blob transactions)", opts.ParentChainID) + } if dp.extraBacklog == nil { dp.extraBacklog = func() uint64 { return 0 } } @@ -363,7 +373,7 @@ func (p *DataPoster) getNextNonceAndMaybeMeta(ctx context.Context) (uint64, []by return 0, nil, false, fmt.Errorf("fetching last element from queue: %w", err) } if lastQueueItem != nil { - nextNonce := lastQueueItem.Data.Nonce + 1 + nextNonce := lastQueueItem.FullTx.Nonce() + 1 if err := p.canPostWithNonce(ctx, nextNonce); err != nil { return 0, nil, false, err } @@ -442,27 +452,34 @@ func (p *DataPoster) evalMaxFeeCapExpr(backlogOfBatches uint64, elapsed time.Dur var big4 = big.NewInt(4) // The dataPosterBacklog argument should *not* include extraBacklog (it's added in in this function) -func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit uint64, lastFeeCap *big.Int, lastTipCap *big.Int, dataCreatedAt time.Time, dataPosterBacklog uint64) (*big.Int, *big.Int, error) { +func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit uint64, numBlobs int, lastFeeCap *big.Int, lastTipCap *big.Int, dataCreatedAt time.Time, dataPosterBacklog uint64) (*big.Int, *big.Int, *big.Int, error) { config := p.config() dataPosterBacklog += p.extraBacklog() latestHeader, err := p.headerReader.LastHeader(ctx) if err != nil { - return nil, nil, err + return nil, nil, nil, err } if latestHeader.BaseFee == nil { - return nil, nil, fmt.Errorf("latest parent chain block %v missing BaseFee (either the parent chain does not have EIP-1559 or the parent chain node is not synced)", latestHeader.Number) + return nil, nil, nil, fmt.Errorf("latest parent chain block %v missing BaseFee (either the parent chain does not have EIP-1559 or the parent chain node is not synced)", latestHeader.Number) + } + newBlobFeeCap := big.NewInt(0) + if latestHeader.ExcessBlobGas != nil { + newBlobFeeCap = eip4844.CalcBlobFee(*latestHeader.ExcessBlobGas) + newBlobFeeCap.Mul(newBlobFeeCap, common.Big2) + } else if numBlobs > 0 { + return nil, nil, nil, fmt.Errorf("latest parent chain block %v missing ExcessBlobGas but blobs were specified in data poster transaction (either the parent chain node is not synced or EIP-4844 was improperly activated)", latestHeader.Number) } softConfBlock := arbmath.BigSubByUint(latestHeader.Number, config.NonceRbfSoftConfs) softConfNonce, err := p.client.NonceAt(ctx, p.Sender(), softConfBlock) if err != nil { - return nil, nil, fmt.Errorf("failed to get latest nonce %v blocks ago (block %v): %w", config.NonceRbfSoftConfs, softConfBlock, err) + return nil, nil, nil, fmt.Errorf("failed to get latest nonce %v blocks ago (block %v): %w", config.NonceRbfSoftConfs, softConfBlock, err) } - newFeeCap := new(big.Int).Mul(latestHeader.BaseFee, big.NewInt(2)) + newFeeCap := new(big.Int).Mul(latestHeader.BaseFee, common.Big2) newFeeCap = arbmath.BigMax(newFeeCap, arbmath.FloatToBig(config.MinFeeCapGwei*params.GWei)) newTipCap, err := p.client.SuggestGasTipCap(ctx) if err != nil { - return nil, nil, err + return nil, nil, nil, err } newTipCap = arbmath.BigMax(newTipCap, arbmath.FloatToBig(config.MinTipCapGwei*params.GWei)) newTipCap = arbmath.BigMin(newTipCap, arbmath.FloatToBig(config.MaxTipCapGwei*params.GWei)) @@ -481,10 +498,13 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u newFeeCap = arbmath.BigMax(newFeeCap, arbmath.BigMulByBips(lastFeeCap, minRbfIncrease)) } + // TODO: if we're significantly increasing the blob fee cap, we also need to increase the fee cap my minRbfIncrease + // TODO: look more into geth's blob mempool and make sure this behavior conforms (I think minRbfIncrease might be higher there) + elapsed := time.Since(dataCreatedAt) maxFeeCap, err := p.evalMaxFeeCapExpr(dataPosterBacklog, elapsed) if err != nil { - return nil, nil, err + return nil, nil, nil, err } if arbmath.BigGreaterThan(newFeeCap, maxFeeCap) { log.Warn( @@ -496,6 +516,8 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u newFeeCap = maxFeeCap } + // TODO: also have an expression limiting the max blob fee cap + latestBalance := p.balance balanceForTx := new(big.Int).Set(latestBalance) if config.AllocateMempoolBalance && !p.usingNoOpStorage { @@ -525,6 +547,7 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u balanceForTx.Div(balanceForTx, arbmath.UintToBig(config.MaxMempoolTransactions-1)) } } + // TODO: take into account blob costs balanceFeeCap := arbmath.BigDivByUint(balanceForTx, gasLimit) if arbmath.BigGreaterThan(newFeeCap, balanceFeeCap) { log.Warn( @@ -550,10 +573,14 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u newTipCap = new(big.Int).Set(newFeeCap) } - return newFeeCap, newTipCap, nil + return newFeeCap, newTipCap, newBlobFeeCap, nil } -func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Time, nonce uint64, meta []byte, to common.Address, calldata []byte, gasLimit uint64, value *big.Int, accessList types.AccessList) (*types.Transaction, error) { +func (p *DataPoster) PostSimpleTransaction(ctx context.Context, nonce uint64, to common.Address, calldata []byte, gasLimit uint64, value *big.Int) (*types.Transaction, error) { + return p.PostTransaction(ctx, time.Now(), nonce, nil, to, calldata, gasLimit, value, nil, nil) +} + +func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Time, nonce uint64, meta []byte, to common.Address, calldata []byte, gasLimit uint64, value *big.Int, kzgBlobs []kzg4844.Blob, accessList types.AccessList) (*types.Transaction, error) { p.mutex.Lock() defer p.mutex.Unlock() @@ -570,27 +597,65 @@ func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Tim return nil, fmt.Errorf("failed to update data poster balance: %w", err) } - feeCap, tipCap, err := p.feeAndTipCaps(ctx, nonce, gasLimit, nil, nil, dataCreatedAt, 0) + feeCap, tipCap, blobFeeCap, err := p.feeAndTipCaps(ctx, nonce, gasLimit, len(kzgBlobs), nil, nil, dataCreatedAt, 0) if err != nil { return nil, err } - inner := types.DynamicFeeTx{ - Nonce: nonce, - GasTipCap: tipCap, - GasFeeCap: feeCap, - Gas: gasLimit, - To: &to, - Value: value, - Data: calldata, - AccessList: accessList, - ChainID: p.parentChainID, - } - fullTx, err := p.signer(ctx, p.Sender(), types.NewTx(&inner)) + + var deprecatedData types.DynamicFeeTx + var inner types.TxData + if len(kzgBlobs) > 0 { + value256, overflow := uint256.FromBig(value) + if overflow { + return nil, fmt.Errorf("blob transaction callvalue %v overflows uint256", value) + } + // Intentionally break out of date data poster redis clients, + // so they don't try to replace by fee a tx they don't understand + deprecatedData.Nonce = ^uint64(0) + commitments, proofs, blobHashes, err := blobs.ComputeCommitmentsProofsAndHashes(kzgBlobs) + if err != nil { + return nil, fmt.Errorf("failed to compute KZG metadata: %w", err) + } + inner = &types.BlobTx{ + Nonce: nonce, + Gas: gasLimit, + To: to, + Value: value256, + Data: calldata, + Sidecar: &types.BlobTxSidecar{ + Blobs: kzgBlobs, + Commitments: commitments, + Proofs: proofs, + }, + BlobHashes: blobHashes, + AccessList: accessList, + ChainID: p.parentChainID256, + } + // reuse the code to convert gas fee and tip caps to uint256s + inner, err = updateTxDataGasCaps(inner, feeCap, tipCap, blobFeeCap) + if err != nil { + return nil, err + } + } else { + deprecatedData = types.DynamicFeeTx{ + Nonce: nonce, + GasFeeCap: feeCap, + GasTipCap: tipCap, + Gas: gasLimit, + To: &to, + Value: value, + Data: calldata, + AccessList: accessList, + ChainID: p.parentChainID, + } + inner = &deprecatedData + } + fullTx, err := p.signer(ctx, p.Sender(), types.NewTx(inner)) if err != nil { return nil, fmt.Errorf("signing transaction: %w", err) } queuedTx := storage.QueuedTransaction{ - Data: inner, + DeprecatedData: deprecatedData, FullTx: fullTx, Meta: meta, Sent: false, @@ -603,8 +668,8 @@ func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Tim // the mutex must be held by the caller func (p *DataPoster) saveTx(ctx context.Context, prevTx, newTx *storage.QueuedTransaction) error { if prevTx != nil { - if prevTx.Data.Nonce != newTx.Data.Nonce { - return fmt.Errorf("prevTx nonce %v doesn't match newTx nonce %v", prevTx.Data.Nonce, newTx.Data.Nonce) + if prevTx.FullTx.Nonce() != newTx.FullTx.Nonce() { + return fmt.Errorf("prevTx nonce %v doesn't match newTx nonce %v", prevTx.FullTx.Nonce(), newTx.FullTx.Nonce()) } // Check if prevTx is the same as newTx and we don't need to do anything @@ -621,7 +686,7 @@ func (p *DataPoster) saveTx(ctx context.Context, prevTx, newTx *storage.QueuedTr return nil } } - if err := p.queue.Put(ctx, newTx.Data.Nonce, prevTx, newTx); err != nil { + if err := p.queue.Put(ctx, newTx.FullTx.Nonce(), prevTx, newTx); err != nil { return fmt.Errorf("putting new tx in the queue: %w", err) } return nil @@ -645,22 +710,57 @@ func (p *DataPoster) sendTx(ctx context.Context, prevTx *storage.QueuedTransacti return p.saveTx(ctx, newTx, &newerTx) } +func updateTxDataGasCaps(data types.TxData, newFeeCap, newTipCap, newBlobFeeCap *big.Int) (types.TxData, error) { + switch data := data.(type) { + case *types.DynamicFeeTx: + data.GasFeeCap = newFeeCap + data.GasTipCap = newTipCap + return data, nil + case *types.BlobTx: + var overflow bool + data.GasFeeCap, overflow = uint256.FromBig(newFeeCap) + if overflow { + return nil, fmt.Errorf("blob tx fee cap %v exceeds uint256", newFeeCap) + } + data.GasTipCap, overflow = uint256.FromBig(newTipCap) + if overflow { + return nil, fmt.Errorf("blob tx tip cap %v exceeds uint256", newTipCap) + } + data.BlobFeeCap, overflow = uint256.FromBig(newBlobFeeCap) + if overflow { + return nil, fmt.Errorf("blob tx blob fee cap %v exceeds uint256", newBlobFeeCap) + } + return data, nil + default: + return nil, fmt.Errorf("unexpected transaction data type %T", data) + } +} + +func updateGasCaps(tx *types.Transaction, newFeeCap, newTipCap, newBlobFeeCap *big.Int) (*types.Transaction, error) { + data, err := updateTxDataGasCaps(tx.GetInner(), newFeeCap, newTipCap, newBlobFeeCap) + if err != nil { + return nil, err + } + return types.NewTx(data), nil +} + // The mutex must be held by the caller. func (p *DataPoster) replaceTx(ctx context.Context, prevTx *storage.QueuedTransaction, backlogOfBatches uint64) error { - newFeeCap, newTipCap, err := p.feeAndTipCaps(ctx, prevTx.Data.Nonce, prevTx.Data.Gas, prevTx.Data.GasFeeCap, prevTx.Data.GasTipCap, prevTx.Created, backlogOfBatches) + newFeeCap, newTipCap, newBlobFeeCap, err := p.feeAndTipCaps(ctx, prevTx.FullTx.Nonce(), prevTx.FullTx.Gas(), len(prevTx.FullTx.BlobHashes()), prevTx.FullTx.GasFeeCap(), prevTx.FullTx.GasTipCap(), prevTx.Created, backlogOfBatches) if err != nil { return err } - minNewFeeCap := arbmath.BigMulByBips(prevTx.Data.GasFeeCap, minRbfIncrease) + minNewFeeCap := arbmath.BigMulByBips(prevTx.FullTx.GasFeeCap(), minRbfIncrease) newTx := *prevTx + // TODO: also look at the blob fee cap if newFeeCap.Cmp(minNewFeeCap) < 0 { log.Debug( "no need to replace by fee transaction", - "nonce", prevTx.Data.Nonce, - "lastFeeCap", prevTx.Data.GasFeeCap, + "nonce", prevTx.FullTx.Nonce(), + "lastFeeCap", prevTx.FullTx.GasFeeCap(), "recommendedFeeCap", newFeeCap, - "lastTipCap", prevTx.Data.GasTipCap, + "lastTipCap", prevTx.FullTx.GasTipCap(), "recommendedTipCap", newTipCap, ) newTx.NextReplacement = time.Now().Add(time.Minute) @@ -676,9 +776,13 @@ func (p *DataPoster) replaceTx(ctx context.Context, prevTx *storage.QueuedTransa break } newTx.Sent = false - newTx.Data.GasFeeCap = newFeeCap - newTx.Data.GasTipCap = newTipCap - newTx.FullTx, err = p.signer(ctx, p.Sender(), types.NewTx(&newTx.Data)) + newTx.DeprecatedData.GasFeeCap = newFeeCap + newTx.DeprecatedData.GasTipCap = newTipCap + unsignedTx, err := updateGasCaps(newTx.FullTx, newFeeCap, newTipCap, newBlobFeeCap) + if err != nil { + return err + } + newTx.FullTx, err = p.signer(ctx, p.Sender(), unsignedTx) if err != nil { return err } @@ -750,7 +854,7 @@ func (p *DataPoster) updateBalance(ctx context.Context) error { const maxConsecutiveIntermittentErrors = 10 func (p *DataPoster) maybeLogError(err error, tx *storage.QueuedTransaction, msg string) { - nonce := tx.Data.Nonce + nonce := tx.FullTx.Nonce() if err == nil { delete(p.errorCount, nonce) return @@ -764,7 +868,7 @@ func (p *DataPoster) maybeLogError(err error, tx *storage.QueuedTransaction, msg } else { delete(p.errorCount, nonce) } - logLevel(msg, "err", err, "nonce", nonce, "feeCap", tx.Data.GasFeeCap, "tipCap", tx.Data.GasTipCap, "gas", tx.Data.Gas) + logLevel(msg, "err", err, "nonce", nonce, "feeCap", tx.FullTx.GasFeeCap(), "tipCap", tx.FullTx.GasTipCap(), "gas", tx.FullTx.Gas()) } const minWait = time.Second * 10 diff --git a/arbnode/dataposter/storage/storage.go b/arbnode/dataposter/storage/storage.go index a9e78fcc5..9586b9c9a 100644 --- a/arbnode/dataposter/storage/storage.go +++ b/arbnode/dataposter/storage/storage.go @@ -27,7 +27,7 @@ var ( type QueuedTransaction struct { FullTx *types.Transaction - Data types.DynamicFeeTx + DeprecatedData types.DynamicFeeTx // FullTx should be used instead Meta []byte Sent bool Created time.Time // may be earlier than the tx was given to the tx poster @@ -46,7 +46,7 @@ type queuedTransactionForEncoding struct { func (qt *QueuedTransaction) EncodeRLP(w io.Writer) error { return rlp.Encode(w, queuedTransactionForEncoding{ FullTx: qt.FullTx, - Data: qt.Data, + Data: qt.DeprecatedData, Meta: qt.Meta, Sent: qt.Sent, Created: (RlpTime)(qt.Created), @@ -60,7 +60,7 @@ func (qt *QueuedTransaction) DecodeRLP(s *rlp.Stream) error { return err } qt.FullTx = qtEnc.FullTx - qt.Data = qtEnc.Data + qt.DeprecatedData = qtEnc.Data qt.Meta = qtEnc.Meta qt.Sent = qtEnc.Sent qt.Created = time.Time(qtEnc.Created) @@ -107,7 +107,7 @@ func LegacyToQueuedTransaction(legacyQT *LegacyQueuedTransaction) (*QueuedTransa } return &QueuedTransaction{ FullTx: legacyQT.FullTx, - Data: legacyQT.Data, + DeprecatedData: legacyQT.Data, Meta: meta, Sent: legacyQT.Sent, Created: legacyQT.Created, @@ -127,7 +127,7 @@ func QueuedTransactionToLegacy(qt *QueuedTransaction) (*LegacyQueuedTransaction, } return &LegacyQueuedTransaction{ FullTx: qt.FullTx, - Data: qt.Data, + Data: qt.DeprecatedData, Meta: meta, Sent: qt.Sent, Created: qt.Created, diff --git a/arbnode/dataposter/storage_test.go b/arbnode/dataposter/storage_test.go index cf9918941..f98c120f3 100644 --- a/arbnode/dataposter/storage_test.go +++ b/arbnode/dataposter/storage_test.go @@ -84,7 +84,7 @@ func valueOf(t *testing.T, i int) *storage.QueuedTransaction { big.NewInt(int64(i)), []byte{byte(i)}), Meta: meta, - Data: types.DynamicFeeTx{ + DeprecatedData: types.DynamicFeeTx{ ChainID: big.NewInt(int64(i)), Nonce: uint64(i), GasTipCap: big.NewInt(int64(i)), diff --git a/staker/validatorwallet/contract.go b/staker/validatorwallet/contract.go index 774e9ab40..deed7942a 100644 --- a/staker/validatorwallet/contract.go +++ b/staker/validatorwallet/contract.go @@ -10,7 +10,6 @@ import ( "math/big" "strings" "sync/atomic" - "time" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" @@ -177,7 +176,7 @@ func (v *Contract) executeTransaction(ctx context.Context, tx *types.Transaction if err != nil { return nil, fmt.Errorf("getting gas for tx data: %w", err) } - return v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), data, gas, auth.Value, nil) + return v.dataPoster.PostSimpleTransaction(ctx, auth.Nonce.Uint64(), *v.Address(), data, gas, auth.Value) } func (v *Contract) populateWallet(ctx context.Context, createIfMissing bool) error { @@ -288,7 +287,7 @@ func (v *Contract) ExecuteTransactions(ctx context.Context, builder *txbuilder.B if err != nil { return nil, fmt.Errorf("getting gas for tx data: %w", err) } - arbTx, err := v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), txData, gas, auth.Value, nil) + arbTx, err := v.dataPoster.PostSimpleTransaction(ctx, auth.Nonce.Uint64(), *v.Address(), txData, gas, auth.Value) if err != nil { return nil, err } @@ -338,7 +337,7 @@ func (v *Contract) TimeoutChallenges(ctx context.Context, challenges []uint64) ( if err != nil { return nil, fmt.Errorf("getting gas for tx data: %w", err) } - return v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), data, gas, auth.Value, nil) + return v.dataPoster.PostSimpleTransaction(ctx, auth.Nonce.Uint64(), *v.Address(), data, gas, auth.Value) } // gasForTxData returns auth.GasLimit if it's nonzero, otherwise returns estimate. diff --git a/staker/validatorwallet/eoa.go b/staker/validatorwallet/eoa.go index 44af5e2b6..3ae305b36 100644 --- a/staker/validatorwallet/eoa.go +++ b/staker/validatorwallet/eoa.go @@ -6,7 +6,6 @@ package validatorwallet import ( "context" "fmt" - "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -95,7 +94,7 @@ func (w *EOA) postTransaction(ctx context.Context, baseTx *types.Transaction) (* return nil, err } gas := baseTx.Gas() + w.getExtraGas() - newTx, err := w.dataPoster.PostTransaction(ctx, time.Now(), nonce, nil, *baseTx.To(), baseTx.Data(), gas, baseTx.Value(), nil) + newTx, err := w.dataPoster.PostSimpleTransaction(ctx, nonce, *baseTx.To(), baseTx.Data(), gas, baseTx.Value()) if err != nil { return nil, fmt.Errorf("post transaction: %w", err) } From d3d0e0fb1270ce82f82a4a12c57b589fa18e24b7 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 00:25:54 -0700 Subject: [PATCH 641/775] Add support for 4844 batch posting --- arbnode/batch_poster.go | 138 ++++++++++++++++++++++++------ arbnode/dataposter/data_poster.go | 10 ++- arbutil/wait_for_l1.go | 2 + util/blobs/blobs.go | 28 ++++-- 4 files changed, 140 insertions(+), 38 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 01a84b1c4..2dc9bac34 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -18,15 +18,18 @@ import ( "github.com/andybalholm/brotli" "github.com/spf13/pflag" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbnode/dataposter" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" @@ -40,6 +43,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/util" "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/blobs" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/redisutil" "github.com/offchainlabs/nitro/util/stopwaiter" @@ -48,7 +52,16 @@ import ( var ( batchPosterWalletBalance = metrics.NewRegisteredGaugeFloat64("arb/batchposter/wallet/balanceether", nil) batchPosterGasRefunderBalance = metrics.NewRegisteredGaugeFloat64("arb/batchposter/gasrefunder/balanceether", nil) + + usableBytesInBlob = big.NewInt(int64(len(kzg4844.Blob{}) * 31 / 32)) + blobTxBlobGasPerBlob = big.NewInt(params.BlobTxBlobGasPerBlob) +) + +const ( batchPosterSimpleRedisLockKey = "node.batch-poster.redis-lock.simple-lock-key" + + sequencerBatchPostMethodName = "addSequencerL2BatchFromOrigin0" + sequencerBatchPostWithBlobsMethodName = "addSequencerL2BatchFromBlob" // TODO: this will probably get updated to have a plural name ) type batchPosterPosition struct { @@ -119,6 +132,7 @@ type BatchPosterConfig struct { RedisUrl string `koanf:"redis-url"` RedisLock redislock.SimpleCfg `koanf:"redis-lock" reload:"hot"` ExtraBatchGas uint64 `koanf:"extra-batch-gas" reload:"hot"` + Post4844Blobs bool `koanf:"post-4844-blobs" reload:"hot"` ParentChainWallet genericconf.WalletConfig `koanf:"parent-chain-wallet"` L1BlockBound string `koanf:"l1-block-bound" reload:"hot"` L1BlockBoundBypass time.Duration `koanf:"l1-block-bound-bypass" reload:"hot"` @@ -166,6 +180,7 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Duration(prefix+".das-retention-period", DefaultBatchPosterConfig.DASRetentionPeriod, "In AnyTrust mode, the period which DASes are requested to retain the stored batches.") f.String(prefix+".gas-refunder-address", DefaultBatchPosterConfig.GasRefunderAddress, "The gas refunder contract address (optional)") f.Uint64(prefix+".extra-batch-gas", DefaultBatchPosterConfig.ExtraBatchGas, "use this much more gas than estimation says is necessary to post batches") + f.Bool(prefix+".post-4844-blobs", DefaultBatchPosterConfig.Post4844Blobs, "if the parent chain supports 4844 blobs and they're well priced, post EIP-4844 blobs") f.String(prefix+".redis-url", DefaultBatchPosterConfig.RedisUrl, "if non-empty, the Redis URL to store queued transactions in") f.String(prefix+".l1-block-bound", DefaultBatchPosterConfig.L1BlockBound, "only post messages to batches when they're within the max future block/timestamp as of this L1 block tag (\"safe\", \"finalized\", \"latest\", or \"ignore\" to ignore this check)") f.Duration(prefix+".l1-block-bound-bypass", DefaultBatchPosterConfig.L1BlockBoundBypass, "post batches even if not within the layer 1 future bounds if we're within this margin of the max delay") @@ -188,6 +203,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ DASRetentionPeriod: time.Hour * 24 * 15, GasRefunderAddress: "", ExtraBatchGas: 50_000, + Post4844Blobs: true, DataPoster: dataposter.DefaultDataPosterConfig, ParentChainWallet: DefaultBatchPosterL1WalletConfig, L1BlockBound: "", @@ -215,6 +231,7 @@ var TestBatchPosterConfig = BatchPosterConfig{ DASRetentionPeriod: time.Hour * 24 * 15, GasRefunderAddress: "", ExtraBatchGas: 10_000, + Post4844Blobs: true, DataPoster: dataposter.TestDataPosterConfig, ParentChainWallet: DefaultBatchPosterL1WalletConfig, L1BlockBound: "", @@ -753,30 +770,73 @@ func (s *batchSegments) CloseAndGetBytes() ([]byte, error) { return fullMsg, nil } -func (b *BatchPoster) encodeAddBatch(seqNum *big.Int, prevMsgNum arbutil.MessageIndex, newMsgNum arbutil.MessageIndex, message []byte, delayedMsg uint64) ([]byte, error) { - method, ok := b.seqInboxABI.Methods["addSequencerL2BatchFromOrigin0"] +func (b *BatchPoster) encodeAddBatch( + seqNum *big.Int, + prevMsgNum arbutil.MessageIndex, + newMsgNum arbutil.MessageIndex, + l2MessageData []byte, + delayedMsg uint64, + use4844 bool, +) ([]byte, []kzg4844.Blob, error) { + methodName := sequencerBatchPostMethodName + if use4844 { + methodName = sequencerBatchPostWithBlobsMethodName + } + method, ok := b.seqInboxABI.Methods[methodName] if !ok { - return nil, errors.New("failed to find add batch method") - } - inputData, err := method.Inputs.Pack( - seqNum, - message, - new(big.Int).SetUint64(delayedMsg), - b.config().gasRefunder, - new(big.Int).SetUint64(uint64(prevMsgNum)), - new(big.Int).SetUint64(uint64(newMsgNum)), - ) + return nil, nil, errors.New("failed to find add batch method") + } + var calldata []byte + var kzgBlobs []kzg4844.Blob + var err error + if use4844 { + kzgBlobs, err = blobs.EncodeBlobs(l2MessageData) + if err != nil { + return nil, nil, fmt.Errorf("failed to encode blobs: %w", err) + } + // EIP4844 transactions to the sequencer inbox will not use transaction calldata for L2 info. + calldata, err = method.Inputs.Pack( + seqNum, + new(big.Int).SetUint64(delayedMsg), + b.config().gasRefunder, + new(big.Int).SetUint64(uint64(prevMsgNum)), + new(big.Int).SetUint64(uint64(newMsgNum)), + ) + } else { + calldata, err = method.Inputs.Pack( + seqNum, + l2MessageData, + new(big.Int).SetUint64(delayedMsg), + b.config().gasRefunder, + new(big.Int).SetUint64(uint64(prevMsgNum)), + new(big.Int).SetUint64(uint64(newMsgNum)), + ) + } if err != nil { - return nil, err + return nil, nil, err } - fullData := append([]byte{}, method.ID...) - fullData = append(fullData, inputData...) - return fullData, nil + fullCalldata := append([]byte{}, method.ID...) + fullCalldata = append(fullCalldata, calldata...) + return fullCalldata, kzgBlobs, nil } var ErrNormalGasEstimationFailed = errors.New("normal gas estimation failed") -func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, delayedMessages uint64, realData []byte, realNonce uint64, realAccessList types.AccessList) (uint64, error) { +type estimateGasParams struct { + From common.Address `json:"from"` + To *common.Address `json:"to"` + Data []byte `json:"data"` + AccessList types.AccessList `json:"accessList"` + BlobHashes []common.Hash `json:"blobVersionedHashes"` +} + +func estimateGas(client rpc.ClientInterface, ctx context.Context, params estimateGasParams) (uint64, error) { + var gas uint64 + err := client.CallContext(ctx, &gas, "eth_estimateGas", params) + return gas, err +} + +func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, delayedMessages uint64, realData []byte, realBlobs []kzg4844.Blob, realNonce uint64, realAccessList types.AccessList) (uint64, error) { config := b.config() useNormalEstimation := b.dataPoster.MaxMempoolTransactions() == 1 if !useNormalEstimation { @@ -787,12 +847,18 @@ func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, } useNormalEstimation = latestNonce == realNonce } + rawRpcClient := b.l1Reader.Client().Client() if useNormalEstimation { + _, realBlobHashes, err := blobs.ComputeCommitmentsAndHashes(realBlobs) + if err != nil { + return 0, fmt.Errorf("failed to compute real blob commitments: %w", err) + } // If we're at the latest nonce, we can skip the special future tx estimate stuff - gas, err := b.l1Reader.Client().EstimateGas(ctx, ethereum.CallMsg{ + gas, err := estimateGas(rawRpcClient, ctx, estimateGasParams{ From: b.dataPoster.Sender(), To: &b.seqInboxAddr, Data: realData, + BlobHashes: realBlobHashes, AccessList: realAccessList, }) if err != nil { @@ -805,14 +871,19 @@ func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, // However, we set nextMsgNum to 1 because it is necessary for a correct estimation for the final to be non-zero. // Because we're likely estimating against older state, this might not be the actual next message, // but the gas used should be the same. - data, err := b.encodeAddBatch(abi.MaxUint256, 0, 1, sequencerMessage, delayedMessages) + data, kzgBlobs, err := b.encodeAddBatch(abi.MaxUint256, 0, 1, sequencerMessage, delayedMessages, len(realBlobs) > 0) if err != nil { return 0, err } - gas, err := b.l1Reader.Client().EstimateGas(ctx, ethereum.CallMsg{ - From: b.dataPoster.Sender(), - To: &b.seqInboxAddr, - Data: data, + _, blobHashes, err := blobs.ComputeCommitmentsAndHashes(kzgBlobs) + if err != nil { + return 0, fmt.Errorf("failed to compute blob commitments: %w", err) + } + gas, err := estimateGas(rawRpcClient, ctx, estimateGasParams{ + From: b.dataPoster.Sender(), + To: &b.seqInboxAddr, + Data: data, + BlobHashes: blobHashes, // This isn't perfect because we're probably estimating the batch at a different sequence number, // but it should overestimate rather than underestimate which is fine. AccessList: realAccessList, @@ -1039,7 +1110,20 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) } } - data, err := b.encodeAddBatch(new(big.Int).SetUint64(batchPosition.NextSeqNum), batchPosition.MessageCount, b.building.msgCount, sequencerMsg, b.building.segments.delayedMsg) + latestHeader, err := b.l1Reader.LastHeader(ctx) + if err != nil { + return false, err + } + var use4844 bool + if config.Post4844Blobs && latestHeader.ExcessBlobGas != nil { + blobFeePerByte := eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*latestHeader.ExcessBlobGas, *latestHeader.BlobGasUsed)) + blobFeePerByte.Mul(blobFeePerByte, blobTxBlobGasPerBlob) + blobFeePerByte.Div(blobFeePerByte, usableBytesInBlob) + + calldataFeePerByte := arbmath.BigMulByUint(latestHeader.BaseFee, 16) + use4844 = arbmath.BigLessThan(blobFeePerByte, calldataFeePerByte) + } + data, kzgBlobs, err := b.encodeAddBatch(new(big.Int).SetUint64(batchPosition.NextSeqNum), batchPosition.MessageCount, b.building.msgCount, sequencerMsg, b.building.segments.delayedMsg, use4844) if err != nil { return false, err } @@ -1051,7 +1135,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) // In theory, this might reduce gas usage, but only by a factor that's already // accounted for in `config.ExtraBatchGas`, as that same factor can appear if a user // posts a new delayed message that we didn't see while gas estimating. - gasLimit, err := b.estimateGas(ctx, sequencerMsg, lastPotentialMsg.DelayedMessagesRead, data, nonce, accessList) + gasLimit, err := b.estimateGas(ctx, sequencerMsg, lastPotentialMsg.DelayedMessagesRead, data, kzgBlobs, nonce, accessList) if err != nil { return false, err } @@ -1071,7 +1155,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) data, gasLimit, new(big.Int), - nil, // TODO: use blobs + kzgBlobs, accessList, ) if err != nil { diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 425dba8e1..ba9c278ba 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -464,7 +464,7 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u } newBlobFeeCap := big.NewInt(0) if latestHeader.ExcessBlobGas != nil { - newBlobFeeCap = eip4844.CalcBlobFee(*latestHeader.ExcessBlobGas) + newBlobFeeCap = eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*latestHeader.ExcessBlobGas, *latestHeader.BlobGasUsed)) newBlobFeeCap.Mul(newBlobFeeCap, common.Big2) } else if numBlobs > 0 { return nil, nil, nil, fmt.Errorf("latest parent chain block %v missing ExcessBlobGas but blobs were specified in data poster transaction (either the parent chain node is not synced or EIP-4844 was improperly activated)", latestHeader.Number) @@ -612,9 +612,13 @@ func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Tim // Intentionally break out of date data poster redis clients, // so they don't try to replace by fee a tx they don't understand deprecatedData.Nonce = ^uint64(0) - commitments, proofs, blobHashes, err := blobs.ComputeCommitmentsProofsAndHashes(kzgBlobs) + commitments, blobHashes, err := blobs.ComputeCommitmentsAndHashes(kzgBlobs) if err != nil { - return nil, fmt.Errorf("failed to compute KZG metadata: %w", err) + return nil, fmt.Errorf("failed to compute KZG commitments: %w", err) + } + proofs, err := blobs.ComputeBlobProofs(kzgBlobs, commitments) + if err != nil { + return nil, fmt.Errorf("failed to compute KZG proofs: %w", err) } inner = &types.BlobTx{ Nonce: nonce, diff --git a/arbutil/wait_for_l1.go b/arbutil/wait_for_l1.go index b66710dbf..9fb2cd10f 100644 --- a/arbutil/wait_for_l1.go +++ b/arbutil/wait_for_l1.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/rpc" ) type L1Interface interface { @@ -25,6 +26,7 @@ type L1Interface interface { BlockNumber(ctx context.Context) (uint64, error) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) ChainID(ctx context.Context) (*big.Int, error) + Client() rpc.ClientInterface } func SendTxAsCall(ctx context.Context, client L1Interface, tx *types.Transaction, from common.Address, blockNum *big.Int, unlimitedGas bool) ([]byte, error) { diff --git a/util/blobs/blobs.go b/util/blobs/blobs.go index c8025dc25..60cc89875 100644 --- a/util/blobs/blobs.go +++ b/util/blobs/blobs.go @@ -5,6 +5,7 @@ package blobs import ( "crypto/sha256" + "fmt" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto/kzg4844" @@ -52,20 +53,15 @@ func DecodeBlobs(blobs []kzg4844.Blob) ([]byte, error) { } // Return KZG commitments, proofs, and versioned hashes that corresponds to these blobs -func ComputeCommitmentsProofsAndHashes(blobs []kzg4844.Blob) ([]kzg4844.Commitment, []kzg4844.Proof, []common.Hash, error) { +func ComputeCommitmentsAndHashes(blobs []kzg4844.Blob) ([]kzg4844.Commitment, []common.Hash, error) { commitments := make([]kzg4844.Commitment, len(blobs)) - proofs := make([]kzg4844.Proof, len(blobs)) versionedHashes := make([]common.Hash, len(blobs)) for i := range blobs { var err error commitments[i], err = kzg4844.BlobToCommitment(blobs[i]) if err != nil { - return nil, nil, nil, err - } - proofs[i], err = kzg4844.ComputeBlobProof(blobs[i], commitments[i]) - if err != nil { - return nil, nil, nil, err + return nil, nil, err } // As per the EIP-4844 spec, the versioned hash is the SHA-256 hash of the commitment with the first byte set to 1. hash := sha256.Sum256(commitments[i][:]) @@ -73,5 +69,21 @@ func ComputeCommitmentsProofsAndHashes(blobs []kzg4844.Blob) ([]kzg4844.Commitme versionedHashes[i] = hash } - return commitments, proofs, versionedHashes, nil + return commitments, versionedHashes, nil +} + +func ComputeBlobProofs(blobs []kzg4844.Blob, commitments []kzg4844.Commitment) ([]kzg4844.Proof, error) { + if len(blobs) != len(commitments) { + return nil, fmt.Errorf("ComputeBlobProofs got %v blobs but %v commitments", len(blobs), len(commitments)) + } + proofs := make([]kzg4844.Proof, len(blobs)) + for i := range blobs { + var err error + proofs[i], err = kzg4844.ComputeBlobProof(blobs[i], commitments[i]) + if err != nil { + return nil, err + } + } + + return proofs, nil } From d229f3c306fb89f5c7193ebbbeb2b8aa165433ce Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 00:30:51 -0700 Subject: [PATCH 642/775] Use updated contracts --- arbnode/batch_poster.go | 2 +- contracts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 2dc9bac34..87170caa8 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -61,7 +61,7 @@ const ( batchPosterSimpleRedisLockKey = "node.batch-poster.redis-lock.simple-lock-key" sequencerBatchPostMethodName = "addSequencerL2BatchFromOrigin0" - sequencerBatchPostWithBlobsMethodName = "addSequencerL2BatchFromBlob" // TODO: this will probably get updated to have a plural name + sequencerBatchPostWithBlobsMethodName = "addSequencerL2BatchFromBlobs" ) type batchPosterPosition struct { diff --git a/contracts b/contracts index a8e7709bf..00d4d6257 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit a8e7709bfc918f9b8e2888d47f2fd8454779fd11 +Subproject commit 00d4d6257835ba58bb381ce8d884a819d7ce9448 From 4bcb5ec449e6a5d286e7bb6f7ee7739aa8674bef Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 23 Jan 2024 16:29:18 +0530 Subject: [PATCH 643/775] Fix --- arbnode/transaction_streamer.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 5491cbdbf..f7ccae678 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -970,14 +970,14 @@ func (s *TransactionStreamer) executeNextMsg(ctx context.Context, exec execution } var msgForPrefetch *arbostypes.MessageWithMetadata if pos+1 < msgCount { - msgForPrefetch, err = s.GetMessage(pos + 1) + msg, err := s.GetMessage(pos + 1) if err != nil { log.Error("feedOneMsg failed to readMessage", "err", err, "pos", pos+1) return false } + msgForPrefetch = msg } - err = s.exec.DigestMessage(pos, msg, msgForPrefetch) - if err != nil { + if err = s.exec.DigestMessage(pos, msg, msgForPrefetch); err != nil { logger := log.Warn if prevMessageCount < msgCount { logger = log.Debug From 2694d8e70f5b0c932fcaabe9b9a5b3bff352dff5 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 23 Jan 2024 17:00:18 +0530 Subject: [PATCH 644/775] Add comments --- execution/gethexec/executionengine.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index d376c59ba..e941faf9f 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -502,6 +502,11 @@ func (s *ExecutionEngine) ResultAtPos(pos arbutil.MessageIndex) (*execution.Mess return s.resultFromHeader(s.bc.GetHeaderByNumber(s.MessageIndexToBlockNumber(pos))) } +// DigestMessage is used to create a block by executing msg against the latest state and storing it. +// Also, while creating a block by executing msg against the latest state, +// in parallel, creates a block by executing msgForPrefetch (msg+1) against the latest state +// but does not store the block. +// This helps in filling the cache, so that the next block creation is faster. func (s *ExecutionEngine) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) error { if !s.createBlocksMutex.TryLock() { return errors.New("createBlock mutex held") From 411e2b5ecb73fcacf460e50bfdf5c8e75f958083 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 10:04:55 -0700 Subject: [PATCH 645/775] Add safety check of KZG preimage length --- arbitrator/prover/src/kzg.rs | 11 +++++++---- arbitrator/prover/src/machine.rs | 6 +++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/arbitrator/prover/src/kzg.rs b/arbitrator/prover/src/kzg.rs index 280073aac..0d859f323 100644 --- a/arbitrator/prover/src/kzg.rs +++ b/arbitrator/prover/src/kzg.rs @@ -2,7 +2,7 @@ // For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE use crate::utils::Bytes32; -use c_kzg::{KzgSettings, BYTES_PER_G1_POINT, BYTES_PER_G2_POINT}; +use c_kzg::{KzgSettings, BYTES_PER_G1_POINT, BYTES_PER_G2_POINT, FIELD_ELEMENTS_PER_BLOB, BYTES_PER_BLOB}; use eyre::{ensure, Result, WrapErr}; use num::BigUint; use serde::{de::Error as _, Deserialize}; @@ -37,8 +37,6 @@ struct TrustedSetup { g2_monomial: Vec<[u8; BYTES_PER_G2_POINT]>, } -const FIELD_ELEMENTS_PER_BLOB: usize = 4096; - lazy_static::lazy_static! { pub static ref ETHEREUM_KZG_SETTINGS: KzgSettings = { let trusted_setup = serde_json::from_str::(include_str!("kzg-trusted-setup.json")) @@ -63,6 +61,11 @@ pub fn prove_kzg_preimage( offset: u32, out: &mut impl Write, ) -> Result<()> { + ensure!( + preimage.len() == BYTES_PER_BLOB, + "Trying to KZG prove preimage of unexpected length {}", + preimage.len(), + ); let blob = c_kzg::Blob::from_bytes(preimage).wrap_err("Failed to generate KZG blob from preimage")?; let commitment = c_kzg::KzgCommitment::blob_to_kzg_commitment(&blob, ÐEREUM_KZG_SETTINGS) @@ -116,5 +119,5 @@ pub fn prove_kzg_preimage( #[cfg(test)] #[test] fn load_trusted_setup() { - let _: &KzgSettings = &*ETHEREUM_KZG_SETTINGS; + let _: &KzgSettings = ÐEREUM_KZG_SETTINGS; } diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index f66a10dc1..85ea14e10 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -16,7 +16,7 @@ use crate::{ }, }; use arbutil::{Color, PreimageType}; -use c_kzg::FIELD_ELEMENTS_PER_BLOB; +use c_kzg::BYTES_PER_BLOB; use digest::Digest; use eyre::{bail, ensure, eyre, Result, WrapErr}; use fnv::FnvHashMap as HashMap; @@ -1876,12 +1876,12 @@ impl Machine { self.preimage_resolver.get(self.context, preimage_ty, hash) { if preimage_ty == PreimageType::EthVersionedHash - && preimage.len() != 32 * FIELD_ELEMENTS_PER_BLOB + && preimage.len() != BYTES_PER_BLOB { bail!( "kzg hash {} preimage should be {} bytes long but is instead {}", hash, - 32 * FIELD_ELEMENTS_PER_BLOB, + BYTES_PER_BLOB, preimage.len(), ); } From 6b9ac0a0a2012cf59ef4cd859f9cd6d976758ba1 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 10:37:48 -0700 Subject: [PATCH 646/775] Fix formatting --- arbitrator/prover/src/kzg.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arbitrator/prover/src/kzg.rs b/arbitrator/prover/src/kzg.rs index 0d859f323..66a71c52b 100644 --- a/arbitrator/prover/src/kzg.rs +++ b/arbitrator/prover/src/kzg.rs @@ -2,7 +2,9 @@ // For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE use crate::utils::Bytes32; -use c_kzg::{KzgSettings, BYTES_PER_G1_POINT, BYTES_PER_G2_POINT, FIELD_ELEMENTS_PER_BLOB, BYTES_PER_BLOB}; +use c_kzg::{ + KzgSettings, BYTES_PER_BLOB, BYTES_PER_G1_POINT, BYTES_PER_G2_POINT, FIELD_ELEMENTS_PER_BLOB, +}; use eyre::{ensure, Result, WrapErr}; use num::BigUint; use serde::{de::Error as _, Deserialize}; From eba35e5dca4dbddfec6759d2a68fc2df91fcaa02 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 12:53:25 -0700 Subject: [PATCH 647/775] Fix bit checks --- arbstate/das_reader.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arbstate/das_reader.go b/arbstate/das_reader.go index 5f568605b..46d01b7bb 100644 --- a/arbstate/das_reader.go +++ b/arbstate/das_reader.go @@ -46,20 +46,24 @@ const BlobHashesHeaderFlag byte = L1AuthenticatedMessageHeaderFlag | 0x10 // 0x5 // BrotliMessageHeaderByte indicates that the message is brotli-compressed. const BrotliMessageHeaderByte byte = 0 +func hasBits(checking byte, bits byte) bool { + return (checking & bits) == bits +} + func IsDASMessageHeaderByte(header byte) bool { - return (DASMessageHeaderFlag & header) > 0 + return hasBits(header, DASMessageHeaderFlag) } func IsTreeDASMessageHeaderByte(header byte) bool { - return (TreeDASMessageHeaderFlag & header) > 0 + return hasBits(header, TreeDASMessageHeaderFlag) } func IsZeroheavyEncodedHeaderByte(header byte) bool { - return (ZeroheavyMessageHeaderFlag & header) > 0 + return hasBits(header, ZeroheavyMessageHeaderFlag) } func IsBlobHashesHeaderByte(header byte) bool { - return (BlobHashesHeaderFlag & header) > 0 + return hasBits(header, BlobHashesHeaderFlag) } func IsBrotliMessageHeaderByte(b uint8) bool { From 863911649278001d7324e4a000be0f02e871fbb0 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 12:26:19 -0700 Subject: [PATCH 648/775] Fix Data field type in estimateGasParams --- arbnode/batch_poster.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 87170caa8..b4bf4c807 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -21,6 +21,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto/kzg4844" @@ -825,7 +826,7 @@ var ErrNormalGasEstimationFailed = errors.New("normal gas estimation failed") type estimateGasParams struct { From common.Address `json:"from"` To *common.Address `json:"to"` - Data []byte `json:"data"` + Data hexutil.Bytes `json:"data"` AccessList types.AccessList `json:"accessList"` BlobHashes []common.Hash `json:"blobVersionedHashes"` } From 5cdcde12efbce6fe425df4bdebd7cef842135892 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 16:14:32 -0700 Subject: [PATCH 649/775] Fix raw estimateGas in batch poster --- arbnode/batch_poster.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index b4bf4c807..28c248043 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -832,9 +832,9 @@ type estimateGasParams struct { } func estimateGas(client rpc.ClientInterface, ctx context.Context, params estimateGasParams) (uint64, error) { - var gas uint64 + var gas hexutil.Uint64 err := client.CallContext(ctx, &gas, "eth_estimateGas", params) - return gas, err + return uint64(gas), err } func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, delayedMessages uint64, realData []byte, realBlobs []kzg4844.Blob, realNonce uint64, realAccessList types.AccessList) (uint64, error) { From 54ee5c31ffdba4119a124dcd9bce09813f670e52 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 16:14:49 -0700 Subject: [PATCH 650/775] Misc refactors while I was tracking down the previous bug --- arbnode/batch_poster.go | 11 ++++++----- arbnode/dataposter/data_poster.go | 19 ++++++++++--------- system_tests/batch_poster_test.go | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 28c248043..53d3e7f40 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -828,7 +828,7 @@ type estimateGasParams struct { To *common.Address `json:"to"` Data hexutil.Bytes `json:"data"` AccessList types.AccessList `json:"accessList"` - BlobHashes []common.Hash `json:"blobVersionedHashes"` + BlobHashes []common.Hash `json:"blobVersionedHashes,omitempty"` } func estimateGas(client rpc.ClientInterface, ctx context.Context, params estimateGasParams) (uint64, error) { @@ -1164,12 +1164,13 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) } log.Info( "BatchPoster: batch sent", - "sequence nr.", batchPosition.NextSeqNum, + "sequenceNumber", batchPosition.NextSeqNum, "from", batchPosition.MessageCount, "to", b.building.msgCount, - "prev delayed", batchPosition.DelayedMessageCount, - "current delayed", b.building.segments.delayedMsg, - "total segments", len(b.building.segments.rawSegments), + "prevDelayed", batchPosition.DelayedMessageCount, + "currentDelayed", b.building.segments.delayedMsg, + "totalSegments", len(b.building.segments.rawSegments), + "numBlobs", len(kzgBlobs), ) recentlyHitL1Bounds := time.Since(b.lastHitL1Bounds) < config.PollInterval*3 postedMessages := b.building.msgCount - batchPosition.MessageCount diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index ba9c278ba..4f3f514d1 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -636,7 +636,7 @@ func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Tim ChainID: p.parentChainID256, } // reuse the code to convert gas fee and tip caps to uint256s - inner, err = updateTxDataGasCaps(inner, feeCap, tipCap, blobFeeCap) + err = updateTxDataGasCaps(inner, feeCap, tipCap, blobFeeCap) if err != nil { return nil, err } @@ -714,34 +714,35 @@ func (p *DataPoster) sendTx(ctx context.Context, prevTx *storage.QueuedTransacti return p.saveTx(ctx, newTx, &newerTx) } -func updateTxDataGasCaps(data types.TxData, newFeeCap, newTipCap, newBlobFeeCap *big.Int) (types.TxData, error) { +func updateTxDataGasCaps(data types.TxData, newFeeCap, newTipCap, newBlobFeeCap *big.Int) error { switch data := data.(type) { case *types.DynamicFeeTx: data.GasFeeCap = newFeeCap data.GasTipCap = newTipCap - return data, nil + return nil case *types.BlobTx: var overflow bool data.GasFeeCap, overflow = uint256.FromBig(newFeeCap) if overflow { - return nil, fmt.Errorf("blob tx fee cap %v exceeds uint256", newFeeCap) + return fmt.Errorf("blob tx fee cap %v exceeds uint256", newFeeCap) } data.GasTipCap, overflow = uint256.FromBig(newTipCap) if overflow { - return nil, fmt.Errorf("blob tx tip cap %v exceeds uint256", newTipCap) + return fmt.Errorf("blob tx tip cap %v exceeds uint256", newTipCap) } data.BlobFeeCap, overflow = uint256.FromBig(newBlobFeeCap) if overflow { - return nil, fmt.Errorf("blob tx blob fee cap %v exceeds uint256", newBlobFeeCap) + return fmt.Errorf("blob tx blob fee cap %v exceeds uint256", newBlobFeeCap) } - return data, nil + return nil default: - return nil, fmt.Errorf("unexpected transaction data type %T", data) + return fmt.Errorf("unexpected transaction data type %T", data) } } func updateGasCaps(tx *types.Transaction, newFeeCap, newTipCap, newBlobFeeCap *big.Int) (*types.Transaction, error) { - data, err := updateTxDataGasCaps(tx.GetInner(), newFeeCap, newTipCap, newBlobFeeCap) + data := tx.GetInner() + err := updateTxDataGasCaps(data, newFeeCap, newTipCap, newBlobFeeCap) if err != nil { return nil, err } diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index f7bf74f69..cacbe3cee 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -180,7 +180,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { } lastTxHash := txs[len(txs)-1].Hash() - for i := 90; i > 0; i-- { + for i := 90; i >= 0; i-- { builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) From 4925e63acaafc651c64302062f976cd9d4c754fe Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 16:23:23 -0700 Subject: [PATCH 651/775] Add option to force posting 4844 blobs --- arbnode/batch_poster.go | 20 ++++++++++++++------ arbnode/dataposter/data_poster.go | 8 ++++++-- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 53d3e7f40..4a07d3652 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -134,6 +134,7 @@ type BatchPosterConfig struct { RedisLock redislock.SimpleCfg `koanf:"redis-lock" reload:"hot"` ExtraBatchGas uint64 `koanf:"extra-batch-gas" reload:"hot"` Post4844Blobs bool `koanf:"post-4844-blobs" reload:"hot"` + ForcePost4844Blobs bool `koanf:"force-post-4844-blobs" reload:"hot"` ParentChainWallet genericconf.WalletConfig `koanf:"parent-chain-wallet"` L1BlockBound string `koanf:"l1-block-bound" reload:"hot"` L1BlockBoundBypass time.Duration `koanf:"l1-block-bound-bypass" reload:"hot"` @@ -182,6 +183,7 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".gas-refunder-address", DefaultBatchPosterConfig.GasRefunderAddress, "The gas refunder contract address (optional)") f.Uint64(prefix+".extra-batch-gas", DefaultBatchPosterConfig.ExtraBatchGas, "use this much more gas than estimation says is necessary to post batches") f.Bool(prefix+".post-4844-blobs", DefaultBatchPosterConfig.Post4844Blobs, "if the parent chain supports 4844 blobs and they're well priced, post EIP-4844 blobs") + f.Bool(prefix+".force-post-4844-blobs", DefaultBatchPosterConfig.ForcePost4844Blobs, "if the parent chain supports 4844 blobs and post-4844-blobs is true, post 4844 blobs even if it's not price efficient") f.String(prefix+".redis-url", DefaultBatchPosterConfig.RedisUrl, "if non-empty, the Redis URL to store queued transactions in") f.String(prefix+".l1-block-bound", DefaultBatchPosterConfig.L1BlockBound, "only post messages to batches when they're within the max future block/timestamp as of this L1 block tag (\"safe\", \"finalized\", \"latest\", or \"ignore\" to ignore this check)") f.Duration(prefix+".l1-block-bound-bypass", DefaultBatchPosterConfig.L1BlockBoundBypass, "post batches even if not within the layer 1 future bounds if we're within this margin of the max delay") @@ -205,6 +207,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ GasRefunderAddress: "", ExtraBatchGas: 50_000, Post4844Blobs: true, + ForcePost4844Blobs: false, DataPoster: dataposter.DefaultDataPosterConfig, ParentChainWallet: DefaultBatchPosterL1WalletConfig, L1BlockBound: "", @@ -233,6 +236,7 @@ var TestBatchPosterConfig = BatchPosterConfig{ GasRefunderAddress: "", ExtraBatchGas: 10_000, Post4844Blobs: true, + ForcePost4844Blobs: false, DataPoster: dataposter.TestDataPosterConfig, ParentChainWallet: DefaultBatchPosterL1WalletConfig, L1BlockBound: "", @@ -1116,13 +1120,17 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) return false, err } var use4844 bool - if config.Post4844Blobs && latestHeader.ExcessBlobGas != nil { - blobFeePerByte := eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*latestHeader.ExcessBlobGas, *latestHeader.BlobGasUsed)) - blobFeePerByte.Mul(blobFeePerByte, blobTxBlobGasPerBlob) - blobFeePerByte.Div(blobFeePerByte, usableBytesInBlob) + if config.Post4844Blobs && latestHeader.ExcessBlobGas != nil && latestHeader.BlobGasUsed != nil { + if config.ForcePost4844Blobs { + use4844 = true + } else { + blobFeePerByte := eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*latestHeader.ExcessBlobGas, *latestHeader.BlobGasUsed)) + blobFeePerByte.Mul(blobFeePerByte, blobTxBlobGasPerBlob) + blobFeePerByte.Div(blobFeePerByte, usableBytesInBlob) - calldataFeePerByte := arbmath.BigMulByUint(latestHeader.BaseFee, 16) - use4844 = arbmath.BigLessThan(blobFeePerByte, calldataFeePerByte) + calldataFeePerByte := arbmath.BigMulByUint(latestHeader.BaseFee, 16) + use4844 = arbmath.BigLessThan(blobFeePerByte, calldataFeePerByte) + } } data, kzgBlobs, err := b.encodeAddBatch(new(big.Int).SetUint64(batchPosition.NextSeqNum), batchPosition.MessageCount, b.building.msgCount, sequencerMsg, b.building.segments.delayedMsg, use4844) if err != nil { diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 4f3f514d1..1415f7814 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -463,11 +463,15 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u return nil, nil, nil, fmt.Errorf("latest parent chain block %v missing BaseFee (either the parent chain does not have EIP-1559 or the parent chain node is not synced)", latestHeader.Number) } newBlobFeeCap := big.NewInt(0) - if latestHeader.ExcessBlobGas != nil { + if latestHeader.ExcessBlobGas != nil && latestHeader.BlobGasUsed != nil { newBlobFeeCap = eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*latestHeader.ExcessBlobGas, *latestHeader.BlobGasUsed)) newBlobFeeCap.Mul(newBlobFeeCap, common.Big2) } else if numBlobs > 0 { - return nil, nil, nil, fmt.Errorf("latest parent chain block %v missing ExcessBlobGas but blobs were specified in data poster transaction (either the parent chain node is not synced or EIP-4844 was improperly activated)", latestHeader.Number) + return nil, nil, nil, fmt.Errorf( + "latest parent chain block %v missing ExcessBlobGas or BlobGasUsed but blobs were specified in data poster transaction "+ + "(either the parent chain node is not synced or the EIP-4844 was improperly activated)", + latestHeader.Number, + ) } softConfBlock := arbmath.BigSubByUint(latestHeader.Number, config.NonceRbfSoftConfs) softConfNonce, err := p.client.NonceAt(ctx, p.Sender(), softConfBlock) From 89d5415d46d70f272b17ccb15ccf141c2647880b Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 23 Jan 2024 17:28:47 -0700 Subject: [PATCH 652/775] broadcastclient_test: avoid deadlock in test --- broadcastclient/broadcastclient_test.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/broadcastclient/broadcastclient_test.go b/broadcastclient/broadcastclient_test.go index b75bc44c1..84356d77e 100644 --- a/broadcastclient/broadcastclient_test.go +++ b/broadcastclient/broadcastclient_test.go @@ -232,7 +232,21 @@ func startMakeBroadcastClient(ctx context.Context, t *testing.T, clientConfig Co go func() { defer wg.Done() - defer broadcastClient.StopAndWait() + // drain messages so messages could be sent on ts.messageReceiver + defer func() { + clientDone := make(chan struct{}) + go func() { + for { + select { + case <-ts.messageReceiver: + case <-clientDone: + return + } + } + }() + broadcastClient.StopAndWait() + close(clientDone) + }() var timeout time.Duration if expectedCount == 0 { timeout = 1 * time.Second From b6b54ef82b6f803fc5998777ffc138c23a4faa59 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 17:35:49 -0700 Subject: [PATCH 653/775] Use custom beacon request helper --- arbnode/blob_reader.go | 158 ++++++++++++++++++----------------- arbnode/node.go | 8 +- util/beaconclient/client.go | 98 ---------------------- util/beaconclient/errors.go | 40 --------- util/beaconclient/options.go | 48 ----------- util/blobs/blobs.go | 12 ++- 6 files changed, 90 insertions(+), 274 deletions(-) delete mode 100644 util/beaconclient/client.go delete mode 100644 util/beaconclient/errors.go delete mode 100644 util/beaconclient/options.go diff --git a/arbnode/blob_reader.go b/arbnode/blob_reader.go index 673df37b1..d7560f47e 100644 --- a/arbnode/blob_reader.go +++ b/arbnode/blob_reader.go @@ -5,24 +5,26 @@ package arbnode import ( "context" - "crypto/sha256" "encoding/json" "fmt" + "io" + "net/http" + "path" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/offchainlabs/nitro/arbutil" - "github.com/offchainlabs/nitro/util/beaconclient" + "github.com/offchainlabs/nitro/util/blobs" "github.com/offchainlabs/nitro/util/pretty" - "github.com/pkg/errors" "github.com/spf13/pflag" ) type BlobClient struct { - bc *beaconclient.Client - ec arbutil.L1Interface + config BlobClientConfig + ec arbutil.L1Interface + httpClient *http.Client // The genesis time time won't change so only request it once. cachedGenesisTime uint64 @@ -40,8 +42,45 @@ func BlobClientAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".beacon-chain-url", DefaultBlobClientConfig.BeaconChainUrl, "Beacon Chain url to use for fetching blobs") } -func NewBlobClient(bc *beaconclient.Client, ec arbutil.L1Interface) *BlobClient { - return &BlobClient{bc: bc, ec: ec} +func NewBlobClient(config BlobClientConfig, ec arbutil.L1Interface) *BlobClient { + return &BlobClient{ + config: config, + ec: ec, + httpClient: &http.Client{}, + } +} + +type fullResult[T any] struct { + Data T `json:"data"` +} + +func beaconRequest[T interface{}](b *BlobClient, ctx context.Context, beaconPath string) (T, error) { + // Unfortunately, methods on a struct can't be generic. + + var empty T + + req, err := http.NewRequestWithContext(ctx, "GET", path.Join(b.config.BeaconChainUrl, beaconPath), http.NoBody) + if err != nil { + return empty, err + } + + resp, err := b.httpClient.Do(req) + if err != nil { + return empty, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return empty, err + } + + var full fullResult[T] + if err := json.Unmarshal(body, &full); err != nil { + return empty, err + } + + return full.Data, nil } // Get all the blobs associated with a particular block. @@ -62,58 +101,48 @@ func (b *BlobClient) GetBlobs(ctx context.Context, blockHash common.Hash, versio return b.blobSidecars(ctx, slot, versionedHashes) } -type blobResponse struct { - Data []blobResponseItem `json:"data"` -} type blobResponseItem struct { - BlockRoot string `json:"block_root"` - Index int `json:"index"` - Slot uint64 `json:"slot"` - BlockParentRoot string `json:"block_parent_root"` - ProposerIndex uint64 `json:"proposer_index"` - Blob string `json:"blob"` - KzgCommitment string `json:"kzg_commitment"` - KzgProof string `json:"kzg_proof"` + BlockRoot string `json:"block_root"` + Index int `json:"index"` + Slot uint64 `json:"slot"` + BlockParentRoot string `json:"block_parent_root"` + ProposerIndex uint64 `json:"proposer_index"` + Blob hexutil.Bytes `json:"blob"` + KzgCommitment hexutil.Bytes `json:"kzg_commitment"` + KzgProof hexutil.Bytes `json:"kzg_proof"` } func (b *BlobClient) blobSidecars(ctx context.Context, slot uint64, versionedHashes []common.Hash) ([]kzg4844.Blob, error) { - body, err := b.bc.Get(ctx, fmt.Sprintf("/eth/v1/beacon/blob_sidecars/%d", slot)) + response, err := beaconRequest[[]blobResponseItem](b, ctx, fmt.Sprintf("/eth/v1/beacon/blob_sidecars/%d", slot)) if err != nil { - return nil, errors.Wrap(err, "error calling beacon client in blobSidecars") + return nil, fmt.Errorf("error calling beacon client in blobSidecars: %w", err) } - br := &blobResponse{} - err = json.Unmarshal(body, br) - if err != nil { - return nil, errors.Wrap(err, "error decoding json response in blobSidecars") - } - - if len(br.Data) == 0 { - return nil, fmt.Errorf("no blobs found for slot %d", slot) + if len(response) < len(versionedHashes) { + return nil, fmt.Errorf("expected at least %d blobs for slot %d but only got %d", len(versionedHashes), slot, len(response)) } - blobs := make([]kzg4844.Blob, len(versionedHashes)) - var totalFound int + output := make([]kzg4844.Blob, len(versionedHashes)) + outputsFound := make([]bool, len(versionedHashes)) - for i := range blobs { - commitmentBytes, err := hexutil.Decode(br.Data[i].KzgCommitment) - if err != nil { - return nil, fmt.Errorf("couldn't decode commitment for slot(%d) at index(%d), commitment(%s)", slot, br.Data[i].Index, pretty.FirstFewChars(br.Data[i].KzgCommitment)) - } + for _, blobItem := range response { var commitment kzg4844.Commitment - copy(commitment[:], commitmentBytes) - versionedHash := kZGToVersionedHash(commitment) + copy(commitment[:], blobItem.KzgCommitment) + versionedHash := blobs.CommitmentToVersionedHash(commitment) // The versioned hashes of the blob commitments are produced in the by HASH_OPCODE_BYTE, // presumably in the order they were added to the tx. The spec is unclear if the blobs // need to be returned in any particular order from the beacon API, so we put them back in // the order from the tx. - var j int + var outputIdx int var found bool - for j = range versionedHashes { - if versionedHashes[j] == versionedHash { + for outputIdx = range versionedHashes { + if versionedHashes[outputIdx] == versionedHash { found = true - totalFound++ + if outputsFound[outputIdx] { + return nil, fmt.Errorf("found blob with versioned hash %v twice", versionedHash) + } + outputsFound[outputIdx] = true break } } @@ -121,30 +150,24 @@ func (b *BlobClient) blobSidecars(ctx context.Context, slot uint64, versionedHas continue } - blob, err := hexutil.Decode(br.Data[i].Blob) - if err != nil { - return nil, fmt.Errorf("couldn't decode blob for slot(%d) at index(%d), blob(%s)", slot, br.Data[i].Index, pretty.FirstFewChars(br.Data[i].Blob)) - } - copy(blobs[j][:], blob) + copy(output[outputIdx][:], blobItem.Blob) - proofBytes, err := hexutil.Decode(br.Data[i].KzgProof) - if err != nil { - return nil, fmt.Errorf("couldn't decode proof for slot(%d) at index(%d), proof(%s)", slot, br.Data[i].Index, pretty.FirstFewChars(br.Data[i].KzgProof)) - } var proof kzg4844.Proof - copy(proof[:], proofBytes) + copy(proof[:], blobItem.KzgProof) - err = kzg4844.VerifyBlobProof(blobs[j], commitment, proof) + err = kzg4844.VerifyBlobProof(output[outputIdx], commitment, proof) if err != nil { - return nil, fmt.Errorf("failed to verify blob proof for blob at slot(%d) at index(%d), blob(%s)", slot, br.Data[i].Index, pretty.FirstFewChars(br.Data[i].Blob)) + return nil, fmt.Errorf("failed to verify blob proof for blob at slot(%d) at index(%d), blob(%s)", slot, blobItem.Index, pretty.FirstFewChars(blobItem.Blob.String())) } } - if totalFound < len(versionedHashes) { - return nil, fmt.Errorf("not all of the requested blobs (%d/%d) were found at slot (%d), can't reconstruct batch payload", totalFound, len(versionedHashes), slot) + for i, found := range outputsFound { + if !found { + return nil, fmt.Errorf("missing blob %v in slot %v, can't reconstruct batch payload", versionedHashes[i], slot) + } } - return blobs, nil + return output, nil } type genesisResponse struct { @@ -157,29 +180,10 @@ func (b *BlobClient) genesisTime(ctx context.Context) (uint64, error) { return b.cachedGenesisTime, nil } - body, err := b.bc.Get(ctx, "/eth/v1/beacon/genesis") + gr, err := beaconRequest[genesisResponse](b, ctx, "/eth/v1/beacon/genesis") if err != nil { - return 0, errors.Wrap(err, "error calling beacon client in genesisTime") - } - - gr := &genesisResponse{} - dataWrapper := &struct{ Data *genesisResponse }{Data: gr} - err = json.Unmarshal(body, dataWrapper) - if err != nil { - return 0, errors.Wrap(err, "error decoding json response in genesisTime") + return 0, fmt.Errorf("error calling beacon client in genesisTime: %w", err) } return gr.GenesisTime, nil } - -// The following code is taken from core/vm/contracts.go -const ( - blobCommitmentVersionKZG uint8 = 0x01 // Version byte for the point evaluation precompile. -) - -func kZGToVersionedHash(kzg kzg4844.Commitment) common.Hash { - h := sha256.Sum256(kzg[:]) - h[0] = blobCommitmentVersionKZG - - return h -} diff --git a/arbnode/node.go b/arbnode/node.go index 99ecb541e..9f5626bba 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -40,7 +40,6 @@ import ( "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/staker/validatorwallet" - "github.com/offchainlabs/nitro/util/beaconclient" "github.com/offchainlabs/nitro/util/contracts" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/redisutil" @@ -518,12 +517,7 @@ func createNodeImpl( var blobReader arbstate.BlobReader if config.BlobClient.BeaconChainUrl != "" { - bc, err := beaconclient.NewClient(config.BlobClient.BeaconChainUrl) - if err != nil { - return nil, err - } - - blobReader = NewBlobClient(bc, l1client) + blobReader = NewBlobClient(config.BlobClient, l1client) } inboxTracker, err := NewInboxTracker(arbDb, txStreamer, daReader, blobReader) diff --git a/util/beaconclient/client.go b/util/beaconclient/client.go deleted file mode 100644 index e2dfd8e6b..000000000 --- a/util/beaconclient/client.go +++ /dev/null @@ -1,98 +0,0 @@ -package beaconclient - -import ( - "context" - "io" - "net" - "net/http" - "net/url" - - "github.com/pkg/errors" -) - -// Client is a wrapper object around the HTTP client. -// Taken from prysm/api/client. -type Client struct { - hc *http.Client - baseURL *url.URL - token string -} - -// NewClient constructs a new client with the provided options (ex WithTimeout). -// `host` is the base host + port used to construct request urls. This value can be -// a URL string, or NewClient will assume an http endpoint if just `host:port` is used. -func NewClient(host string, opts ...ClientOpt) (*Client, error) { - u, err := urlForHost(host) - if err != nil { - return nil, err - } - c := &Client{ - hc: &http.Client{}, - baseURL: u, - } - for _, o := range opts { - o(c) - } - return c, nil -} - -// Token returns the bearer token used for jwt authentication -func (c *Client) Token() string { - return c.token -} - -// BaseURL returns the base url of the client -func (c *Client) BaseURL() *url.URL { - return c.baseURL -} - -// Do execute the request against the http client -func (c *Client) Do(req *http.Request) (*http.Response, error) { - return c.hc.Do(req) -} - -func urlForHost(h string) (*url.URL, error) { - // try to parse as url (being permissive) - u, err := url.Parse(h) - if err == nil && u.Host != "" { - return u, nil - } - // try to parse as host:port - host, port, err := net.SplitHostPort(h) - if err != nil { - return nil, ErrMalformedHostname - } - return &url.URL{Host: net.JoinHostPort(host, port), Scheme: "http"}, nil -} - -// NodeURL returns a human-readable string representation of the beacon node base url. -func (c *Client) NodeURL() string { - return c.baseURL.String() -} - -// Get is a generic, opinionated GET function to reduce boilerplate amongst the getters in this package. -func (c *Client) Get(ctx context.Context, path string, opts ...ReqOption) ([]byte, error) { - u := c.baseURL.ResolveReference(&url.URL{Path: path}) - req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) - if err != nil { - return nil, err - } - for _, o := range opts { - o(req) - } - r, err := c.hc.Do(req) - if err != nil { - return nil, err - } - defer func() { - err = r.Body.Close() - }() - if r.StatusCode != http.StatusOK { - return nil, Non200Err(r) - } - b, err := io.ReadAll(r.Body) - if err != nil { - return nil, errors.Wrap(err, "error reading http response body") - } - return b, nil -} diff --git a/util/beaconclient/errors.go b/util/beaconclient/errors.go deleted file mode 100644 index 7ee88805c..000000000 --- a/util/beaconclient/errors.go +++ /dev/null @@ -1,40 +0,0 @@ -package beaconclient - -import ( - "fmt" - "io" - "net/http" - - "github.com/pkg/errors" -) - -// ErrMalformedHostname is used to indicate if a host name's format is incorrect. -var ErrMalformedHostname = errors.New("hostname must include port, separated by one colon, like example.com:3500") - -// ErrNotOK is used to indicate when an HTTP request to the API failed with any non-2xx response code. -// More specific errors may be returned, but an error in reaction to a non-2xx response will always wrap ErrNotOK. -var ErrNotOK = errors.New("did not receive 2xx response from API") - -// ErrNotFound specifically means that a '404 - NOT FOUND' response was received from the API. -var ErrNotFound = errors.Wrap(ErrNotOK, "recv 404 NotFound response from API") - -// ErrInvalidNodeVersion indicates that the /eth/v1/node/version API response format was not recognized. -var ErrInvalidNodeVersion = errors.New("invalid node version response") - -// Non200Err is a function that parses an HTTP response to handle responses that are not 200 with a formatted error. -func Non200Err(response *http.Response) error { - bodyBytes, err := io.ReadAll(response.Body) - var body string - if err != nil { - body = "(Unable to read response body.)" - } else { - body = "response body:\n" + string(bodyBytes) - } - msg := fmt.Sprintf("code=%d, url=%s, body=%s", response.StatusCode, response.Request.URL, body) - switch response.StatusCode { - case 404: - return errors.Wrap(ErrNotFound, msg) - default: - return errors.Wrap(ErrNotOK, msg) - } -} diff --git a/util/beaconclient/options.go b/util/beaconclient/options.go deleted file mode 100644 index 98a37e17a..000000000 --- a/util/beaconclient/options.go +++ /dev/null @@ -1,48 +0,0 @@ -package beaconclient - -import ( - "fmt" - "net/http" - "time" -) - -// ReqOption is a request functional option. -type ReqOption func(*http.Request) - -// WithSSZEncoding is a request functional option that adds SSZ encoding header. -func WithSSZEncoding() ReqOption { - return func(req *http.Request) { - req.Header.Set("Accept", "application/octet-stream") - } -} - -// WithAuthorizationToken is a request functional option that adds header for authorization token. -func WithAuthorizationToken(token string) ReqOption { - return func(req *http.Request) { - req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) - } -} - -// ClientOpt is a functional option for the Client type (http.Client wrapper) -type ClientOpt func(*Client) - -// WithTimeout sets the .Timeout attribute of the wrapped http.Client. -func WithTimeout(timeout time.Duration) ClientOpt { - return func(c *Client) { - c.hc.Timeout = timeout - } -} - -// WithRoundTripper replaces the underlying HTTP's transport with a custom one. -func WithRoundTripper(t http.RoundTripper) ClientOpt { - return func(c *Client) { - c.hc.Transport = t - } -} - -// WithAuthenticationToken sets an oauth token to be used. -func WithAuthenticationToken(token string) ClientOpt { - return func(c *Client) { - c.token = token - } -} diff --git a/util/blobs/blobs.go b/util/blobs/blobs.go index c8025dc25..9f6c8d130 100644 --- a/util/blobs/blobs.go +++ b/util/blobs/blobs.go @@ -51,6 +51,13 @@ func DecodeBlobs(blobs []kzg4844.Blob) ([]byte, error) { return outputData, err } +func CommitmentToVersionedHash(commitment kzg4844.Commitment) common.Hash { + // As per the EIP-4844 spec, the versioned hash is the SHA-256 hash of the commitment with the first byte set to 1. + hash := sha256.Sum256(commitment[:]) + hash[0] = 1 + return hash +} + // Return KZG commitments, proofs, and versioned hashes that corresponds to these blobs func ComputeCommitmentsProofsAndHashes(blobs []kzg4844.Blob) ([]kzg4844.Commitment, []kzg4844.Proof, []common.Hash, error) { commitments := make([]kzg4844.Commitment, len(blobs)) @@ -67,10 +74,7 @@ func ComputeCommitmentsProofsAndHashes(blobs []kzg4844.Blob) ([]kzg4844.Commitme if err != nil { return nil, nil, nil, err } - // As per the EIP-4844 spec, the versioned hash is the SHA-256 hash of the commitment with the first byte set to 1. - hash := sha256.Sum256(commitments[i][:]) - hash[0] = 1 - versionedHashes[i] = hash + versionedHashes[i] = CommitmentToVersionedHash(commitments[i]) } return commitments, proofs, versionedHashes, nil From 18a47f7b2edde6f6f5ed39cbab34b2c425054c12 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 23 Jan 2024 18:09:31 -0700 Subject: [PATCH 654/775] update geth commit --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index c4b3aa68a..5a266a5b6 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit c4b3aa68a05f468e0c30147f9383bfc76d82388f +Subproject commit 5a266a5b6853a9ddd76f25c3e02ac2265fef7996 From 2ba1c490c3fb0fef695ade891e102da167350c0e Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 18:14:17 -0700 Subject: [PATCH 655/775] Update contracts to support zero basefee for gas estimation --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 00d4d6257..e253b8b1b 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 00d4d6257835ba58bb381ce8d884a819d7ce9448 +Subproject commit e253b8b1b5865f135ac63ea3d3cea1bfe8ef2ad7 From 2bd34c65b3d5fba594690dba15be296c27b80454 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Tue, 23 Jan 2024 17:25:51 -0800 Subject: [PATCH 656/775] Fetch seconds per slot from beacon endpoint --- arbnode/blob_reader.go | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/arbnode/blob_reader.go b/arbnode/blob_reader.go index d7560f47e..02626efff 100644 --- a/arbnode/blob_reader.go +++ b/arbnode/blob_reader.go @@ -26,8 +26,9 @@ type BlobClient struct { ec arbutil.L1Interface httpClient *http.Client - // The genesis time time won't change so only request it once. - cachedGenesisTime uint64 + // The genesis time time and seconds per slot won't change so only request them once. + cachedGenesisTime uint64 + cachedSecondsPerSlot uint64 } type BlobClientConfig struct { @@ -89,15 +90,15 @@ func (b *BlobClient) GetBlobs(ctx context.Context, blockHash common.Hash, versio if err != nil { return nil, err } - genesisTime, err := b.genesisTime(ctx) if err != nil { return nil, err } - - // TODO make denominator configurable for devnets with faster block time - slot := (header.Time - genesisTime) / 12 - + secondsPerSlot, err := b.secondsPerSlot(ctx) + if err != nil { + return nil, err + } + slot := (header.Time - genesisTime) / secondsPerSlot return b.blobSidecars(ctx, slot, versionedHashes) } @@ -179,11 +180,27 @@ func (b *BlobClient) genesisTime(ctx context.Context) (uint64, error) { if b.cachedGenesisTime > 0 { return b.cachedGenesisTime, nil } - gr, err := beaconRequest[genesisResponse](b, ctx, "/eth/v1/beacon/genesis") if err != nil { return 0, fmt.Errorf("error calling beacon client in genesisTime: %w", err) } + b.cachedGenesisTime = gr.GenesisTime + return b.cachedGenesisTime, nil +} + +type getSpecResponse struct { + SecondsPerSlot uint64 `json:"SECONDS_PER_SLOT"` +} + +func (b *BlobClient) secondsPerSlot(ctx context.Context) (uint64, error) { + if b.cachedSecondsPerSlot > 0 { + return b.cachedSecondsPerSlot, nil + } + gr, err := beaconRequest[getSpecResponse](b, ctx, "/eth/v1/config/spec") + if err != nil { + return 0, fmt.Errorf("error calling beacon client in secondsPerSlot: %w", err) + } + b.cachedSecondsPerSlot = gr.SecondsPerSlot + return b.cachedSecondsPerSlot, nil - return gr.GenesisTime, nil } From fe9fce1c995734b2fcedb4c0d8658a578156a43e Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 18:55:45 -0700 Subject: [PATCH 657/775] Update go-ethereum pin to fix trusted setup --- go-ethereum | 2 +- go.mod | 6 +++--- go.sum | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go-ethereum b/go-ethereum index c4b3aa68a..eca6e11da 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit c4b3aa68a05f468e0c30147f9383bfc76d82388f +Subproject commit eca6e11dad2c7f8cd1276e38678afec271323422 diff --git a/go.mod b/go.mod index e38f3209d..d50090f6c 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,6 @@ require ( github.com/libp2p/go-libp2p v0.27.8 github.com/multiformats/go-multiaddr v0.12.1 github.com/multiformats/go-multihash v0.2.3 - github.com/pkg/errors v0.9.1 github.com/r3labs/diff/v3 v3.0.1 github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 github.com/spf13/pflag v1.0.5 @@ -90,7 +89,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect - github.com/crate-crypto/go-kzg-4844 v0.3.0 // indirect + github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/cskr/pubsub v1.0.2 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect @@ -103,7 +102,7 @@ require ( github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/ethereum/c-kzg-4844 v0.3.1 // indirect + github.com/ethereum/c-kzg-4844 v0.4.0 // indirect github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect @@ -234,6 +233,7 @@ require ( github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/openzipkin/zipkin-go v0.4.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/polydawn/refmt v0.89.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect diff --git a/go.sum b/go.sum index 872afcafb..d066f8521 100644 --- a/go.sum +++ b/go.sum @@ -264,8 +264,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= -github.com/crate-crypto/go-kzg-4844 v0.3.0 h1:UBlWE0CgyFqqzTI+IFyCzA7A3Zw4iip6uzRv5NIXG0A= -github.com/crate-crypto/go-kzg-4844 v0.3.0/go.mod h1:SBP7ikXEgDnUPONgm33HtuDZEDtWa3L4QtN1ocJSEQ4= +github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= +github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= @@ -338,8 +338,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum/c-kzg-4844 v0.3.1 h1:sR65+68+WdnMKxseNWxSJuAv2tsUrihTpVBTfM/U5Zg= -github.com/ethereum/c-kzg-4844 v0.3.1/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= +github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= From ac0978f6ad0758be8ae435d1c2fdafb4e68e41a4 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 19:14:06 -0700 Subject: [PATCH 658/775] Support batch data location for batch hashes --- arbnode/sequencer_inbox.go | 15 +++++++++++++++ arbutil/transaction_data.go | 12 ++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/arbnode/sequencer_inbox.go b/arbnode/sequencer_inbox.go index d0cdebfef..b743bf0ef 100644 --- a/arbnode/sequencer_inbox.go +++ b/arbnode/sequencer_inbox.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/offchainlabs/nitro/arbstate" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/solgen/go/bridgegen" @@ -33,6 +34,7 @@ const ( batchDataTxInput batchDataLocation = iota batchDataSeparateEvent batchDataNone + batchDataBlobHashes ) func init() { @@ -149,6 +151,19 @@ func (m *SequencerInboxBatch) getSequencerData(ctx context.Context, client arbut case batchDataNone: // No data when in a force inclusion batch return nil, nil + case batchDataBlobHashes: + tx, err := arbutil.GetLogTransaction(ctx, client, m.rawLog) + if err != nil { + return nil, err + } + if len(tx.BlobHashes()) == 0 { + return nil, fmt.Errorf("blob batch transaction %v has no blobs", tx.Hash()) + } + data := []byte{arbstate.BlobHashesHeaderFlag} + for _, h := range tx.BlobHashes() { + data = append(data, h[:]...) + } + return data, nil default: return nil, fmt.Errorf("batch has invalid data location %v", m.dataLocation) } diff --git a/arbutil/transaction_data.go b/arbutil/transaction_data.go index 7741af6e9..8270a628b 100644 --- a/arbutil/transaction_data.go +++ b/arbutil/transaction_data.go @@ -10,8 +10,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -// GetLogEmitterTxData requires that the tx's data is at least 4 bytes long -func GetLogEmitterTxData(ctx context.Context, client L1Interface, log types.Log) ([]byte, error) { +func GetLogTransaction(ctx context.Context, client L1Interface, log types.Log) (*types.Transaction, error) { tx, err := client.TransactionInBlock(ctx, log.BlockHash, log.TxIndex) if err != nil { return nil, err @@ -19,6 +18,15 @@ func GetLogEmitterTxData(ctx context.Context, client L1Interface, log types.Log) if tx.Hash() != log.TxHash { return nil, fmt.Errorf("L1 client returned unexpected transaction hash %v when looking up block %v transaction %v with expected hash %v", tx.Hash(), log.BlockHash, log.TxIndex, log.TxHash) } + return tx, nil +} + +// GetLogEmitterTxData requires that the tx's data is at least 4 bytes long +func GetLogEmitterTxData(ctx context.Context, client L1Interface, log types.Log) ([]byte, error) { + tx, err := GetLogTransaction(ctx, client, log) + if err != nil { + return nil, err + } if len(tx.Data()) < 4 { return nil, fmt.Errorf("log emitting transaction %v unexpectedly does not have enough data", tx.Hash()) } From 8ca7cf89c2c375a93c6510adfa09613bea830616 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 19:17:34 -0700 Subject: [PATCH 659/775] Fix beacon URL concatenation --- arbnode/blob_reader.go | 19 ++++++++++++++----- arbnode/node.go | 5 ++++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/arbnode/blob_reader.go b/arbnode/blob_reader.go index 02626efff..cf7c26651 100644 --- a/arbnode/blob_reader.go +++ b/arbnode/blob_reader.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "net/http" + "net/url" "path" "github.com/ethereum/go-ethereum/common" @@ -22,8 +23,8 @@ import ( ) type BlobClient struct { - config BlobClientConfig ec arbutil.L1Interface + beaconUrl *url.URL httpClient *http.Client // The genesis time time and seconds per slot won't change so only request them once. @@ -43,12 +44,16 @@ func BlobClientAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".beacon-chain-url", DefaultBlobClientConfig.BeaconChainUrl, "Beacon Chain url to use for fetching blobs") } -func NewBlobClient(config BlobClientConfig, ec arbutil.L1Interface) *BlobClient { +func NewBlobClient(config BlobClientConfig, ec arbutil.L1Interface) (*BlobClient, error) { + beaconUrl, err := url.Parse(config.BeaconChainUrl) + if err != nil { + return nil, fmt.Errorf("failed to parse beacon chain URL: %w", err) + } return &BlobClient{ - config: config, ec: ec, + beaconUrl: beaconUrl, httpClient: &http.Client{}, - } + }, nil } type fullResult[T any] struct { @@ -60,7 +65,11 @@ func beaconRequest[T interface{}](b *BlobClient, ctx context.Context, beaconPath var empty T - req, err := http.NewRequestWithContext(ctx, "GET", path.Join(b.config.BeaconChainUrl, beaconPath), http.NoBody) + // not really a deep copy, but copies the Path part we care about + url := *b.beaconUrl + url.Path = path.Join(url.Path, beaconPath) + + req, err := http.NewRequestWithContext(ctx, "GET", url.String(), http.NoBody) if err != nil { return empty, err } diff --git a/arbnode/node.go b/arbnode/node.go index 9f5626bba..5990cfdbe 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -517,7 +517,10 @@ func createNodeImpl( var blobReader arbstate.BlobReader if config.BlobClient.BeaconChainUrl != "" { - blobReader = NewBlobClient(config.BlobClient, l1client) + blobReader, err = NewBlobClient(config.BlobClient, l1client) + if err != nil { + return nil, err + } } inboxTracker, err := NewInboxTracker(arbDb, txStreamer, daReader, blobReader) From ef832b23d559e1ff24142d3128a4bfd910e2148f Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 19:30:29 -0700 Subject: [PATCH 660/775] Unmarshal beacon chain JSON integers as strings --- arbnode/blob_reader.go | 25 +++++++++++++------------ util/jsonapi/uint64_string.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 util/jsonapi/uint64_string.go diff --git a/arbnode/blob_reader.go b/arbnode/blob_reader.go index cf7c26651..142428583 100644 --- a/arbnode/blob_reader.go +++ b/arbnode/blob_reader.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/util/blobs" + "github.com/offchainlabs/nitro/util/jsonapi" "github.com/offchainlabs/nitro/util/pretty" "github.com/spf13/pflag" @@ -112,14 +113,14 @@ func (b *BlobClient) GetBlobs(ctx context.Context, blockHash common.Hash, versio } type blobResponseItem struct { - BlockRoot string `json:"block_root"` - Index int `json:"index"` - Slot uint64 `json:"slot"` - BlockParentRoot string `json:"block_parent_root"` - ProposerIndex uint64 `json:"proposer_index"` - Blob hexutil.Bytes `json:"blob"` - KzgCommitment hexutil.Bytes `json:"kzg_commitment"` - KzgProof hexutil.Bytes `json:"kzg_proof"` + BlockRoot string `json:"block_root"` + Index jsonapi.Uint64String `json:"index"` + Slot jsonapi.Uint64String `json:"slot"` + BlockParentRoot string `json:"block_parent_root"` + ProposerIndex jsonapi.Uint64String `json:"proposer_index"` + Blob hexutil.Bytes `json:"blob"` + KzgCommitment hexutil.Bytes `json:"kzg_commitment"` + KzgProof hexutil.Bytes `json:"kzg_proof"` } func (b *BlobClient) blobSidecars(ctx context.Context, slot uint64, versionedHashes []common.Hash) ([]kzg4844.Blob, error) { @@ -181,7 +182,7 @@ func (b *BlobClient) blobSidecars(ctx context.Context, slot uint64, versionedHas } type genesisResponse struct { - GenesisTime uint64 `json:"genesis_time"` + GenesisTime jsonapi.Uint64String `json:"genesis_time"` // don't currently care about other fields, add if needed } @@ -193,12 +194,12 @@ func (b *BlobClient) genesisTime(ctx context.Context) (uint64, error) { if err != nil { return 0, fmt.Errorf("error calling beacon client in genesisTime: %w", err) } - b.cachedGenesisTime = gr.GenesisTime + b.cachedGenesisTime = uint64(gr.GenesisTime) return b.cachedGenesisTime, nil } type getSpecResponse struct { - SecondsPerSlot uint64 `json:"SECONDS_PER_SLOT"` + SecondsPerSlot jsonapi.Uint64String `json:"SECONDS_PER_SLOT"` } func (b *BlobClient) secondsPerSlot(ctx context.Context) (uint64, error) { @@ -209,7 +210,7 @@ func (b *BlobClient) secondsPerSlot(ctx context.Context) (uint64, error) { if err != nil { return 0, fmt.Errorf("error calling beacon client in secondsPerSlot: %w", err) } - b.cachedSecondsPerSlot = gr.SecondsPerSlot + b.cachedSecondsPerSlot = uint64(gr.SecondsPerSlot) return b.cachedSecondsPerSlot, nil } diff --git a/util/jsonapi/uint64_string.go b/util/jsonapi/uint64_string.go new file mode 100644 index 000000000..27cbb1852 --- /dev/null +++ b/util/jsonapi/uint64_string.go @@ -0,0 +1,32 @@ +// Copyright 2024, Offchain Labs, Inc. +// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE + +package jsonapi + +import ( + "fmt" + "strconv" +) + +// Uint64String is a uint64 that JSON marshals and unmarshals as string in decimal +type Uint64String uint64 + +func (u *Uint64String) UnmarshalJSON(b []byte) error { + s := string(b) + if s == "null" { + return nil + } + + // Parse string as uint64, removing quotes + value, err := strconv.ParseUint(s[1:len(s)-1], 10, 64) + if err != nil { + return err + } + + *u = Uint64String(value) + return nil +} + +func (u Uint64String) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf("\"%d\"", uint64(u))), nil +} From 13ed4c63a4e8822d93354171e74b43e89bd7646b Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 19:30:41 -0700 Subject: [PATCH 661/775] Fix blob decoding not accepting trailing bytes --- util/blobs/blobs.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util/blobs/blobs.go b/util/blobs/blobs.go index 9f6c8d130..02a22556a 100644 --- a/util/blobs/blobs.go +++ b/util/blobs/blobs.go @@ -4,6 +4,7 @@ package blobs import ( + "bytes" "crypto/sha256" "github.com/ethereum/go-ethereum/common" @@ -47,7 +48,7 @@ func DecodeBlobs(blobs []kzg4844.Blob) ([]byte, error) { } } var outputData []byte - err := rlp.DecodeBytes(rlpData, &outputData) + err := rlp.Decode(bytes.NewReader(rlpData), &outputData) return outputData, err } From b48224390ae90975a7d249fe2cc2fcc266fd09d3 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 19:54:09 -0700 Subject: [PATCH 662/775] Fix arbitrator tests and hopefully CI --- .github/workflows/codeql-analysis.yml | 3 +++ .../prover/test-cases/rust/data/msg0.bin | Bin 1 -> 2 bytes .../prover/test-cases/rust/data/msg1.bin | Bin 32 -> 32 bytes .../prover/test-cases/rust/src/bin/host-io.rs | 19 +++++++++++------- contracts | 2 +- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8fb9d80c2..8b7ebd0e1 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -75,6 +75,9 @@ jobs: - name: Install rust stable uses: dtolnay/rust-toolchain@stable + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + - name: Cache Rust Build Products uses: actions/cache@v3 with: diff --git a/arbitrator/prover/test-cases/rust/data/msg0.bin b/arbitrator/prover/test-cases/rust/data/msg0.bin index 5cd813e5c5f312673ce9cf39fb832fb2d55116cc..7eb0b7fdf9dac856acf46ccada40589a72c84592 100644 GIT binary patch literal 2 JcmZQr1pol70IL81 literal 1 IcmZ1l00651s{jB1 diff --git a/arbitrator/prover/test-cases/rust/data/msg1.bin b/arbitrator/prover/test-cases/rust/data/msg1.bin index 2ea3dec3e1641a99198fd86a817f906db6ddaf76..fefa1cc823e0ec463b7923972b03901b52808fc1 100644 GIT binary patch delta 6 NcmY#TU}Tse4*&wG0Pz3- literal 32 ncmZQ%VrF4wW9Q)H;^yJy;};MV5*85^6PJ*bl9rK`lUD!$7k~m0 diff --git a/arbitrator/prover/test-cases/rust/src/bin/host-io.rs b/arbitrator/prover/test-cases/rust/src/bin/host-io.rs index d16f60ff5..679ee1448 100644 --- a/arbitrator/prover/test-cases/rust/src/bin/host-io.rs +++ b/arbitrator/prover/test-cases/rust/src/bin/host-io.rs @@ -29,24 +29,29 @@ fn main() { let mut bytebuffer = Bytes32([0x0; 32]); // in delayed inbox - we're skipping the "kind" byte println!("delayed inbox message 0"); + let mut expected_buffer = bytebuffer.0; let len = wavm_read_delayed_inbox_message(0, bytebuffer.0.as_mut_ptr(), DELAYED_HEADER_LEN); - assert_eq!(len, 2); - assert_eq!(bytebuffer.0[1], 0xaa); + assert_eq!(len, 3); + expected_buffer[2] = 0xaa; + assert_eq!(bytebuffer.0, expected_buffer); println!("delayed inbox message 1"); let len = wavm_read_delayed_inbox_message(1, bytebuffer.0.as_mut_ptr(), DELAYED_HEADER_LEN); assert_eq!(len, 32); - for j in 1..31 { - assert_eq!(bytebuffer.0[j], (j as u8)); + for j in 1..32 { + assert_eq!(bytebuffer.0[j], (j as u8) - 1); } println!("inbox message 0"); + expected_buffer = bytebuffer.0; let len = wavm_read_inbox_message(0, bytebuffer.0.as_mut_ptr(), INBOX_HEADER_LEN); - assert_eq!(len, 1); - assert_eq!(bytebuffer.0[0], 0xaa); + expected_buffer[0] = 0; + expected_buffer[1] = 0xaa; + assert_eq!(len, 2); + assert_eq!(bytebuffer.0, expected_buffer); println!("inbox message 1"); let len = wavm_read_inbox_message(1, bytebuffer.0.as_mut_ptr(), INBOX_HEADER_LEN); assert_eq!(len, 32); for j in 0..32 { - assert_eq!(bytebuffer.0[j], (j as u8) + 1); + assert_eq!(bytebuffer.0[j], (j as u8)); } let keccak_hash = hex!("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"); diff --git a/contracts b/contracts index e253b8b1b..cd5093d45 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit e253b8b1b5865f135ac63ea3d3cea1bfe8ef2ad7 +Subproject commit cd5093d45ef0353fc5b2718ead70bd7f36e1a92c From ae7a199bfd6c00b7438f94d82f93dfa97d633c8f Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 20:22:21 -0700 Subject: [PATCH 663/775] Use KZG preimage support in replay binary --- cmd/replay/main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/replay/main.go b/cmd/replay/main.go index b634a2d5b..dd8a0fd1f 100644 --- a/cmd/replay/main.go +++ b/cmd/replay/main.go @@ -130,9 +130,9 @@ func (r *BlobPreimageReader) GetBlobs( var blobs []kzg4844.Blob for _, h := range versionedHashes { var blob kzg4844.Blob - var preimage []byte - if true { - panic("TODO: fill in preimage with wavmio.ResolvePreimage(h, wavmio.PreimageTypeEthVersionedHash) once KZG proof support is merged into this branch") + preimage, err := wavmio.ResolveTypedPreimage(arbutil.EthVersionedHashPreimageType, h) + if err != nil { + return nil, err } if len(preimage) != len(blob) { return nil, fmt.Errorf("for blob %v got back preimage of length %v but expected blob length %v", h, len(preimage), len(blob)) From 3de7b73eb70c5711acce731981d36cb26c2dffd2 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 20:22:48 -0700 Subject: [PATCH 664/775] Fix arbitrator handling of non-keccak preimages --- arbitrator/jit/src/wavmio.rs | 4 ++-- arbitrator/prover/src/lib.rs | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/arbitrator/jit/src/wavmio.rs b/arbitrator/jit/src/wavmio.rs index a398cb22f..dfc7f2177 100644 --- a/arbitrator/jit/src/wavmio.rs +++ b/arbitrator/jit/src/wavmio.rs @@ -193,8 +193,8 @@ pub fn resolve_preimage_impl( }; let offset = match u32::try_from(offset) { - Ok(offset) => offset as usize, - Err(_) => error!("bad offset {offset} in {name}"), + Ok(offset) if offset % 32 == 0 => offset as usize, + _ => error!("bad offset {offset} in {name}"), }; let len = std::cmp::min(32, preimage.len().saturating_sub(offset)); diff --git a/arbitrator/prover/src/lib.rs b/arbitrator/prover/src/lib.rs index 8285c011d..c7610ab31 100644 --- a/arbitrator/prover/src/lib.rs +++ b/arbitrator/prover/src/lib.rs @@ -19,7 +19,6 @@ use crate::machine::{argument_data_to_inbox, Machine}; use arbutil::PreimageType; use eyre::Result; use machine::{get_empty_preimage_resolver, GlobalState, MachineStatus, PreimageResolver}; -use sha3::{Digest, Keccak256}; use static_assertions::const_assert_eq; use std::{ ffi::CStr, @@ -303,13 +302,18 @@ pub unsafe extern "C" fn arbitrator_set_preimage_resolver( return None; } let data = CBytes::from_raw_parts(res.ptr, res.len as usize); - let have_hash = Keccak256::digest(&data); - if have_hash.as_slice() != *hash { - panic!( - "Resolved incorrect data for hash {}: got {}", + #[cfg(debug_assertions)] + match crate::utils::hash_preimage(&data, ty) { + Ok(have_hash) if have_hash.as_slice() == *hash => {} + Ok(got_hash) => panic!( + "Resolved incorrect data for hash {} (rehashed to {})", hash, - hex::encode(data), - ); + Bytes32(got_hash), + ), + Err(err) => panic!( + "Failed to hash preimage from resolver (expecting hash {}): {}", + hash, err, + ), } Some(data) }, From e82ac7272443055041ef286af187fb225e44d8ea Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 20:23:04 -0700 Subject: [PATCH 665/775] Provide blob preimages during validation --- arbnode/inbox_reader.go | 15 ++++--- arbnode/node.go | 1 + arbnode/transaction_streamer.go | 2 +- execution/gethexec/block_recorder.go | 7 +-- execution/gethexec/executionengine.go | 5 ++- execution/interface.go | 2 +- staker/block_validator.go | 30 +++++++------ staker/stateless_block_validator.go | 56 ++++++++++++++++-------- system_tests/full_challenge_impl_test.go | 4 +- system_tests/staker_test.go | 2 + validator/validation_entry.go | 5 ++- 11 files changed, 81 insertions(+), 48 deletions(-) diff --git a/arbnode/inbox_reader.go b/arbnode/inbox_reader.go index 9c830e3c8..5fca3c7ee 100644 --- a/arbnode/inbox_reader.go +++ b/arbnode/inbox_reader.go @@ -14,6 +14,7 @@ import ( "sync/atomic" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" flag "github.com/spf13/pflag" @@ -401,7 +402,8 @@ func (r *InboxReader) run(ctx context.Context, hadError bool) error { } log.Warn("missing mentioned batch in L1 message lookup", "batch", batchNum) } - return r.GetSequencerMessageBytes(ctx, batchNum) + data, _, err := r.GetSequencerMessageBytes(ctx, batchNum) + return data, err }) if err != nil { return err @@ -570,24 +572,25 @@ func (r *InboxReader) getNextBlockToRead() (*big.Int, error) { return msgBlock, nil } -func (r *InboxReader) GetSequencerMessageBytes(ctx context.Context, seqNum uint64) ([]byte, error) { +func (r *InboxReader) GetSequencerMessageBytes(ctx context.Context, seqNum uint64) ([]byte, common.Hash, error) { metadata, err := r.tracker.GetBatchMetadata(seqNum) if err != nil { - return nil, err + return nil, common.Hash{}, err } blockNum := arbmath.UintToBig(metadata.ParentChainBlock) seqBatches, err := r.sequencerInbox.LookupBatchesInRange(ctx, blockNum, blockNum) if err != nil { - return nil, err + return nil, common.Hash{}, err } var seenBatches []uint64 for _, batch := range seqBatches { if batch.SequenceNumber == seqNum { - return batch.Serialize(ctx, r.client) + data, err := batch.Serialize(ctx, r.client) + return data, batch.BlockHash, err } seenBatches = append(seenBatches, batch.SequenceNumber) } - return nil, fmt.Errorf("sequencer batch %v not found in L1 block %v (found batches %v)", seqNum, metadata.ParentChainBlock, seenBatches) + return nil, common.Hash{}, fmt.Errorf("sequencer batch %v not found in L1 block %v (found batches %v)", seqNum, metadata.ParentChainBlock, seenBatches) } func (r *InboxReader) GetLastReadBlockAndBatchCount() (uint64, uint64) { diff --git a/arbnode/node.go b/arbnode/node.go index 5990cfdbe..de9745f2a 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -542,6 +542,7 @@ func createNodeImpl( exec, rawdb.NewTable(arbDb, storage.BlockValidatorPrefix), daReader, + blobReader, func() *staker.BlockValidatorConfig { return &configFetcher.Get().BlockValidator }, stack, ) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 24ef2a7cc..f96d51ce0 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -820,7 +820,7 @@ func (s *TransactionStreamer) addMessagesAndEndBatchImpl(messageStartPos arbutil return nil } -func (s *TransactionStreamer) FetchBatch(batchNum uint64) ([]byte, error) { +func (s *TransactionStreamer) FetchBatch(batchNum uint64) ([]byte, common.Hash, error) { return s.inboxReader.GetSequencerMessageBytes(context.TODO(), batchNum) } diff --git a/execution/gethexec/block_recorder.go b/execution/gethexec/block_recorder.go index a0f6d837e..d7e702f3c 100644 --- a/execution/gethexec/block_recorder.go +++ b/execution/gethexec/block_recorder.go @@ -123,13 +123,14 @@ func (r *BlockRecorder) RecordBlockCreation( var readBatchInfo []validator.BatchInfo if msg != nil { batchFetcher := func(batchNum uint64) ([]byte, error) { - data, err := r.execEngine.streamer.FetchBatch(batchNum) + data, blockHash, err := r.execEngine.streamer.FetchBatch(batchNum) if err != nil { return nil, err } readBatchInfo = append(readBatchInfo, validator.BatchInfo{ - Number: batchNum, - Data: data, + Number: batchNum, + BlockHash: blockHash, + Data: data, }) return data, nil } diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 58e91a197..20e9ca6f3 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -449,7 +449,10 @@ func (s *ExecutionEngine) createBlockFromNextMessage(msg *arbostypes.MessageWith statedb, s.bc, s.bc.Config(), - s.streamer.FetchBatch, + func(batchNum uint64) ([]byte, error) { + data, _, err := s.streamer.FetchBatch(batchNum) + return data, err + }, ) return block, statedb, receipts, err diff --git a/execution/interface.go b/execution/interface.go index ef9409b9c..5f7c01719 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -73,7 +73,7 @@ type FullExecutionClient interface { // not implemented in execution, used as input type BatchFetcher interface { - FetchBatch(batchNum uint64) ([]byte, error) + FetchBatch(batchNum uint64) ([]byte, common.Hash, error) } type TransactionStreamer interface { diff --git a/staker/block_validator.go b/staker/block_validator.go index 352335a5d..fad5e9c39 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -45,11 +45,12 @@ type BlockValidator struct { chainCaughtUp bool // can only be accessed from creation thread or if holding reorg-write - nextCreateBatch []byte - nextCreateBatchMsgCount arbutil.MessageIndex - nextCreateBatchReread bool - nextCreateStartGS validator.GoGlobalState - nextCreatePrevDelayed uint64 + nextCreateBatch []byte + nextCreateBatchBlockHash common.Hash + nextCreateBatchMsgCount arbutil.MessageIndex + nextCreateBatchReread bool + nextCreateStartGS validator.GoGlobalState + nextCreatePrevDelayed uint64 // can only be accessed from from validation thread or if holding reorg-write lastValidGS validator.GoGlobalState @@ -455,23 +456,23 @@ func (v *BlockValidator) SetCurrentWasmModuleRoot(hash common.Hash) error { ) } -func (v *BlockValidator) readBatch(ctx context.Context, batchNum uint64) (bool, []byte, arbutil.MessageIndex, error) { +func (v *BlockValidator) readBatch(ctx context.Context, batchNum uint64) (bool, []byte, common.Hash, arbutil.MessageIndex, error) { batchCount, err := v.inboxTracker.GetBatchCount() if err != nil { - return false, nil, 0, err + return false, nil, common.Hash{}, 0, err } if batchCount <= batchNum { - return false, nil, 0, nil + return false, nil, common.Hash{}, 0, nil } batchMsgCount, err := v.inboxTracker.GetBatchMessageCount(batchNum) if err != nil { - return false, nil, 0, err + return false, nil, common.Hash{}, 0, err } - batch, err := v.inboxReader.GetSequencerMessageBytes(ctx, batchNum) + batch, batchBlockHash, err := v.inboxReader.GetSequencerMessageBytes(ctx, batchNum) if err != nil { - return false, nil, 0, err + return false, nil, common.Hash{}, 0, err } - return true, batch, batchMsgCount, nil + return true, batch, batchBlockHash, batchMsgCount, nil } func (v *BlockValidator) createNextValidationEntry(ctx context.Context) (bool, error) { @@ -500,11 +501,12 @@ func (v *BlockValidator) createNextValidationEntry(ctx context.Context) (bool, e } if v.nextCreateStartGS.PosInBatch == 0 || v.nextCreateBatchReread { // new batch - found, batch, count, err := v.readBatch(ctx, v.nextCreateStartGS.Batch) + found, batch, batchBlockHash, count, err := v.readBatch(ctx, v.nextCreateStartGS.Batch) if !found { return false, err } v.nextCreateBatch = batch + v.nextCreateBatchBlockHash = batchBlockHash v.nextCreateBatchMsgCount = count validatorMsgCountCurrentBatch.Update(int64(count)) v.nextCreateBatchReread = false @@ -522,7 +524,7 @@ func (v *BlockValidator) createNextValidationEntry(ctx context.Context) (bool, e } else { return false, fmt.Errorf("illegal batch msg count %d pos %d batch %d", v.nextCreateBatchMsgCount, pos, endGS.Batch) } - entry, err := newValidationEntry(pos, v.nextCreateStartGS, endGS, msg, v.nextCreateBatch, v.nextCreatePrevDelayed) + entry, err := newValidationEntry(pos, v.nextCreateStartGS, endGS, msg, v.nextCreateBatch, v.nextCreateBatchBlockHash, v.nextCreatePrevDelayed) if err != nil { return false, err } diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index d35304be2..13b16e42c 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -39,6 +39,7 @@ type StatelessBlockValidator struct { streamer TransactionStreamerInterface db ethdb.Database daService arbstate.DataAvailabilityReader + blobReader arbstate.BlobReader moduleMutex sync.Mutex currentWasmModuleRoot common.Hash @@ -67,7 +68,7 @@ type TransactionStreamerInterface interface { } type InboxReaderInterface interface { - GetSequencerMessageBytes(ctx context.Context, seqNum uint64) ([]byte, error) + GetSequencerMessageBytes(ctx context.Context, seqNum uint64) ([]byte, common.Hash, error) } type GlobalStatePosition struct { @@ -186,11 +187,13 @@ func newValidationEntry( end validator.GoGlobalState, msg *arbostypes.MessageWithMetadata, batch []byte, + batchBlockHash common.Hash, prevDelayed uint64, ) (*validationEntry, error) { batchInfo := validator.BatchInfo{ - Number: start.Batch, - Data: batch, + Number: start.Batch, + BlockHash: batchBlockHash, + Data: batch, } hasDelayed := false var delayedNum uint64 @@ -219,6 +222,7 @@ func NewStatelessBlockValidator( recorder execution.ExecutionRecorder, arbdb ethdb.Database, das arbstate.DataAvailabilityReader, + blobReader arbstate.BlobReader, config func() *BlockValidatorConfig, stack *node.Node, ) (*StatelessBlockValidator, error) { @@ -235,6 +239,7 @@ func NewStatelessBlockValidator( streamer: streamer, db: arbdb, daService: das, + blobReader: blobReader, } return validator, nil } @@ -285,20 +290,35 @@ func (v *StatelessBlockValidator) ValidationEntryRecord(ctx context.Context, e * continue } if arbstate.IsBlobHashesHeaderByte(batch.Data[40]) { - // TODO: fetch blob preimages - panic("TODO: fetch blob preimages") - } - if !arbstate.IsDASMessageHeaderByte(batch.Data[40]) { - continue - } - if v.daService == nil { - log.Warn("No DAS configured, but sequencer message found with DAS header") - } else { - _, err := arbstate.RecoverPayloadFromDasBatch( - ctx, batch.Number, batch.Data, v.daService, e.Preimages, arbstate.KeysetValidate, - ) + payload := batch.Data[41:] + if len(payload)%len(common.Hash{}) != 0 { + return fmt.Errorf("blob batch data is not a list of hashes as expected") + } + versionedHashes := make([]common.Hash, len(payload)/len(common.Hash{})) + for i := 0; i*32 < len(payload); i += 1 { + copy(versionedHashes[i][:], payload[i*32:(i+1)*32]) + } + blobs, err := v.blobReader.GetBlobs(ctx, batch.BlockHash, versionedHashes) if err != nil { - return err + return fmt.Errorf("failed to get blobs: %w", err) + } + if e.Preimages[arbutil.EthVersionedHashPreimageType] == nil { + e.Preimages[arbutil.EthVersionedHashPreimageType] = make(map[common.Hash][]byte) + } + for i, blob := range blobs { + e.Preimages[arbutil.EthVersionedHashPreimageType][versionedHashes[i]] = blob[:] + } + } + if arbstate.IsDASMessageHeaderByte(batch.Data[40]) { + if v.daService == nil { + log.Warn("No DAS configured, but sequencer message found with DAS header") + } else { + _, err := arbstate.RecoverPayloadFromDasBatch( + ctx, batch.Number, batch.Data, v.daService, e.Preimages, arbstate.KeysetValidate, + ) + if err != nil { + return err + } } } } @@ -363,11 +383,11 @@ func (v *StatelessBlockValidator) CreateReadyValidationEntry(ctx context.Context } start := buildGlobalState(*prevResult, startPos) end := buildGlobalState(*result, endPos) - seqMsg, err := v.inboxReader.GetSequencerMessageBytes(ctx, startPos.BatchNumber) + seqMsg, batchBlockHash, err := v.inboxReader.GetSequencerMessageBytes(ctx, startPos.BatchNumber) if err != nil { return nil, err } - entry, err := newValidationEntry(pos, start, end, msg, seqMsg, prevDelayed) + entry, err := newValidationEntry(pos, start, end, msg, seqMsg, batchBlockHash, prevDelayed) if err != nil { return nil, err } diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index 0fa483b6e..b8f891e3e 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -385,7 +385,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall confirmLatestBlock(ctx, t, l1Info, l1Backend) - asserterValidator, err := staker.NewStatelessBlockValidator(asserterL2.InboxReader, asserterL2.InboxTracker, asserterL2.TxStreamer, asserterExec.Recorder, asserterL2ArbDb, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) + asserterValidator, err := staker.NewStatelessBlockValidator(asserterL2.InboxReader, asserterL2.InboxTracker, asserterL2.TxStreamer, asserterExec.Recorder, asserterL2ArbDb, nil, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) if err != nil { Fatal(t, err) } @@ -402,7 +402,7 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall if err != nil { Fatal(t, err) } - challengerValidator, err := staker.NewStatelessBlockValidator(challengerL2.InboxReader, challengerL2.InboxTracker, challengerL2.TxStreamer, challengerExec.Recorder, challengerL2ArbDb, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) + challengerValidator, err := staker.NewStatelessBlockValidator(challengerL2.InboxReader, challengerL2.InboxTracker, challengerL2.TxStreamer, challengerExec.Recorder, challengerL2ArbDb, nil, nil, StaticFetcherFrom(t, &conf.BlockValidator), valStack) if err != nil { Fatal(t, err) } diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 6e3ffd612..62e89ff78 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -208,6 +208,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) execNodeA, l2nodeA.ArbDB, nil, + nil, StaticFetcherFrom(t, &blockValidatorConfig), valStack, ) @@ -260,6 +261,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) execNodeB, l2nodeB.ArbDB, nil, + nil, StaticFetcherFrom(t, &blockValidatorConfig), valStack, ) diff --git a/validator/validation_entry.go b/validator/validation_entry.go index fed1940f1..8bb021335 100644 --- a/validator/validation_entry.go +++ b/validator/validation_entry.go @@ -6,8 +6,9 @@ import ( ) type BatchInfo struct { - Number uint64 - Data []byte + Number uint64 + BlockHash common.Hash + Data []byte } type ValidationInput struct { From 59a8935a9bb651ce43370e441db2cae702a2f004 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 20:31:50 -0700 Subject: [PATCH 666/775] Fix arbitrator CI --- .github/workflows/arbitrator-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index ba3cf016f..54a948e04 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -161,4 +161,5 @@ jobs: cd contracts yarn install yarn build + yarn build:forge:yul yarn hardhat --network localhost test test/prover/*.ts From f646430e65d44936e984ec6e4d8cb47044801ba0 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 20:43:42 -0700 Subject: [PATCH 667/775] Fix Go test --- system_tests/meaningless_reorg_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system_tests/meaningless_reorg_test.go b/system_tests/meaningless_reorg_test.go index f09f68041..e1715dc63 100644 --- a/system_tests/meaningless_reorg_test.go +++ b/system_tests/meaningless_reorg_test.go @@ -95,7 +95,7 @@ func TestMeaninglessBatchReorg(t *testing.T) { time.Sleep(10 * time.Millisecond) } - _, err = builder.L2.ConsensusNode.InboxReader.GetSequencerMessageBytes(ctx, 1) + _, _, err = builder.L2.ConsensusNode.InboxReader.GetSequencerMessageBytes(ctx, 1) Require(t, err) l2Header, err := builder.L2.Client.HeaderByNumber(ctx, l2Receipt.BlockNumber) From d2b7c9db14667046d08557d1503cf38dad267117 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 21:26:43 -0700 Subject: [PATCH 668/775] Strengthen Uint64String parsing --- util/jsonapi/uint64_string.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/util/jsonapi/uint64_string.go b/util/jsonapi/uint64_string.go index 27cbb1852..980b97a94 100644 --- a/util/jsonapi/uint64_string.go +++ b/util/jsonapi/uint64_string.go @@ -4,6 +4,7 @@ package jsonapi import ( + "encoding/json" "fmt" "strconv" ) @@ -12,13 +13,18 @@ import ( type Uint64String uint64 func (u *Uint64String) UnmarshalJSON(b []byte) error { - s := string(b) - if s == "null" { + jsonString := string(b) + if jsonString == "null" { return nil } - // Parse string as uint64, removing quotes - value, err := strconv.ParseUint(s[1:len(s)-1], 10, 64) + var s string + err := json.Unmarshal(b, &s) + if err != nil { + return err + } + + value, err := strconv.ParseUint(s, 10, 64) if err != nil { return err } From 277f241004def543f547bdb65aa4688216994bbc Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Jan 2024 23:40:07 -0700 Subject: [PATCH 669/775] Pack more bits into blobs --- util/blobs/blobs.go | 74 ++++++++++++++++++++++++++++++++-------- util/blobs/blobs_test.go | 52 ++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 util/blobs/blobs_test.go diff --git a/util/blobs/blobs.go b/util/blobs/blobs.go index 55df57f9d..2852f2b29 100644 --- a/util/blobs/blobs.go +++ b/util/blobs/blobs.go @@ -14,6 +14,44 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) +func fillBlobBytes(blob []byte, data []byte) []byte { + for fieldElement := 0; fieldElement < params.BlobTxFieldElementsPerBlob; fieldElement++ { + startIdx := fieldElement*32 + 1 + copy(blob[startIdx:startIdx+31], data) + if len(data) <= 31 { + return nil + } + data = data[31:] + } + return data +} + +// The number of bits in a BLS scalar that aren't part of a whole byte. +const spareBlobBits = 6 // = math.floor(math.log2(BLS_MODULUS)) % 8 + +func fillBlobBits(blob []byte, data []byte) ([]byte, error) { + var acc uint16 + accBits := 0 + for fieldElement := 0; fieldElement < params.BlobTxFieldElementsPerBlob; fieldElement++ { + if accBits < spareBlobBits && len(data) > 0 { + acc |= uint16(data[0]) << accBits + accBits += 8 + data = data[1:] + } + blob[fieldElement*32] = uint8(acc & ((1 << spareBlobBits) - 1)) + accBits -= spareBlobBits + if accBits < 0 { + // We're out of data + break + } + acc >>= spareBlobBits + } + if accBits > 0 { + return nil, fmt.Errorf("somehow ended up with %v spare accBits", accBits) + } + return data, nil +} + // EncodeBlobs takes in raw bytes data to convert into blobs used for KZG commitment EIP-4844 // transactions on Ethereum. func EncodeBlobs(data []byte) ([]kzg4844.Blob, error) { @@ -21,21 +59,15 @@ func EncodeBlobs(data []byte) ([]kzg4844.Blob, error) { if err != nil { return nil, err } - blobs := []kzg4844.Blob{{}} - blobIndex := 0 - fieldIndex := -1 - for i := 0; i < len(data); i += 31 { - fieldIndex++ - if fieldIndex == params.BlobTxFieldElementsPerBlob { - blobs = append(blobs, kzg4844.Blob{}) - blobIndex++ - fieldIndex = 0 - } - max := i + 31 - if max > len(data) { - max = len(data) + var blobs []kzg4844.Blob + for len(data) > 0 { + var b kzg4844.Blob + data = fillBlobBytes(b[:], data) + data, err = fillBlobBits(b[:], data) + if err != nil { + return nil, err } - copy(blobs[blobIndex][fieldIndex*32+1:], data[i:max]) + blobs = append(blobs, b) } return blobs, nil } @@ -47,6 +79,20 @@ func DecodeBlobs(blobs []kzg4844.Blob) ([]byte, error) { for fieldIndex := 0; fieldIndex < params.BlobTxFieldElementsPerBlob; fieldIndex++ { rlpData = append(rlpData, blob[fieldIndex*32+1:(fieldIndex+1)*32]...) } + var acc uint16 + accBits := 0 + for fieldIndex := 0; fieldIndex < params.BlobTxFieldElementsPerBlob; fieldIndex++ { + acc |= uint16(blob[fieldIndex*32]) << accBits + accBits += spareBlobBits + if accBits >= 8 { + rlpData = append(rlpData, uint8(acc)) + acc >>= 8 + accBits -= 8 + } + } + if accBits != 0 { + return nil, fmt.Errorf("somehow ended up with %v spare accBits", accBits) + } } var outputData []byte err := rlp.Decode(bytes.NewReader(rlpData), &outputData) diff --git a/util/blobs/blobs_test.go b/util/blobs/blobs_test.go new file mode 100644 index 000000000..753b50a48 --- /dev/null +++ b/util/blobs/blobs_test.go @@ -0,0 +1,52 @@ +// Copyright 2024, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package blobs + +import ( + "bytes" + "math/big" + "math/rand" + "testing" + + "github.com/ethereum/go-ethereum/params" +) + +const bytesEncodedPerBlob = 254 * 4096 / 8 + +var blsModulus, _ = new(big.Int).SetString("52435875175126190479447740508185965837690552500527637822603658699938581184513", 10) + +func TestBlobEncoding(t *testing.T) { + r := rand.New(rand.NewSource(1)) +outer: + for i := 0; i < 40; i++ { + data := make([]byte, r.Int()%bytesEncodedPerBlob*3) + _, err := r.Read(data) + if err != nil { + t.Fatalf("failed to generate random bytes: %v", err) + } + enc, err := EncodeBlobs(data) + if err != nil { + t.Errorf("failed to encode blobs for length %v: %v", len(data), err) + continue + } + for _, b := range enc { + for fieldElement := 0; fieldElement < params.BlobTxFieldElementsPerBlob; fieldElement++ { + bigInt := new(big.Int).SetBytes(b[fieldElement*32 : (fieldElement+1)*32]) + if bigInt.Cmp(blsModulus) >= 0 { + t.Errorf("for length %v blob %v has field element %v value %v >= modulus %v", len(data), b, fieldElement, bigInt, blsModulus) + continue outer + } + } + } + dec, err := DecodeBlobs(enc) + if err != nil { + t.Errorf("failed to decode blobs for length %v: %v", len(data), err) + continue + } + if !bytes.Equal(data, dec) { + t.Errorf("got different decoding for length %v", len(data)) + continue + } + } +} From 03b2fe8a801d5429b759603a1fd12d9f8d4186f6 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 24 Jan 2024 08:13:20 -0700 Subject: [PATCH 670/775] Add separate max batch size for 4844 --- arbnode/batch_poster.go | 66 ++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 4a07d3652..65ef76e0a 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -118,6 +118,8 @@ type BatchPosterConfig struct { DisableDasFallbackStoreDataOnChain bool `koanf:"disable-das-fallback-store-data-on-chain" reload:"hot"` // Max batch size. MaxSize int `koanf:"max-size" reload:"hot"` + // Maximum 4844 blob enabled batch size. + Max4844BatchSize int `koanf:"max-4844-batch-size" reload:"hot"` // Max batch post delay. MaxDelay time.Duration `koanf:"max-delay" reload:"hot"` // Wait for max BatchPost delay. @@ -174,6 +176,7 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Bool(prefix+".enable", DefaultBatchPosterConfig.Enable, "enable posting batches to l1") f.Bool(prefix+".disable-das-fallback-store-data-on-chain", DefaultBatchPosterConfig.DisableDasFallbackStoreDataOnChain, "If unable to batch to DAS, disable fallback storing data on chain") f.Int(prefix+".max-size", DefaultBatchPosterConfig.MaxSize, "maximum batch size") + f.Int(prefix+".max-4844-batch-size", DefaultBatchPosterConfig.Max4844BatchSize, "maximum 4844 blob enabled batch size") f.Duration(prefix+".max-delay", DefaultBatchPosterConfig.MaxDelay, "maximum batch posting delay") f.Bool(prefix+".wait-for-max-delay", DefaultBatchPosterConfig.WaitForMaxDelay, "wait for the max batch delay, even if the batch is full") f.Duration(prefix+".poll-interval", DefaultBatchPosterConfig.PollInterval, "how long to wait after no batches are ready to be posted before checking again") @@ -197,7 +200,9 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ Enable: false, DisableDasFallbackStoreDataOnChain: false, // This default is overridden for L3 chains in applyChainParameters in cmd/nitro/nitro.go - MaxSize: 100000, + MaxSize: 100000, + // TODO: is 1000 bytes an appropriate margin for error vs blob space efficiency? + Max4844BatchSize: (254 * params.BlobTxFieldElementsPerBlob / 8 * (params.MaxBlobGasPerBlock / params.BlobTxBlobGasPerBlob)) - 1000, PollInterval: time.Second * 10, ErrorDelay: time.Second * 10, MaxDelay: time.Hour, @@ -227,6 +232,7 @@ var DefaultBatchPosterL1WalletConfig = genericconf.WalletConfig{ var TestBatchPosterConfig = BatchPosterConfig{ Enable: true, MaxSize: 100000, + Max4844BatchSize: DefaultBatchPosterConfig.Max4844BatchSize, PollInterval: time.Millisecond * 10, ErrorDelay: time.Millisecond * 10, MaxDelay: 0, @@ -552,13 +558,20 @@ type buildingBatch struct { startMsgCount arbutil.MessageIndex msgCount arbutil.MessageIndex haveUsefulMessage bool + use4844 bool } -func newBatchSegments(firstDelayed uint64, config *BatchPosterConfig, backlog uint64) *batchSegments { - compressedBuffer := bytes.NewBuffer(make([]byte, 0, config.MaxSize*2)) - if config.MaxSize <= 40 { - panic("MaxBatchSize too small") +func newBatchSegments(firstDelayed uint64, config *BatchPosterConfig, backlog uint64, use4844 bool) *batchSegments { + maxSize := config.MaxSize + if use4844 { + maxSize = config.Max4844BatchSize + } else { + if maxSize <= 40 { + panic("Maximum batch size too small") + } + maxSize -= 40 } + compressedBuffer := bytes.NewBuffer(make([]byte, 0, maxSize*2)) compressionLevel := config.CompressionLevel recompressionLevel := config.CompressionLevel if backlog > 20 { @@ -582,7 +595,7 @@ func newBatchSegments(firstDelayed uint64, config *BatchPosterConfig, backlog ui return &batchSegments{ compressedBuffer: compressedBuffer, compressedWriter: brotli.NewWriterLevel(compressedBuffer, compressionLevel), - sizeLimit: config.MaxSize - 40, // TODO + sizeLimit: maxSize, recompressionLevel: recompressionLevel, rawSegments: make([][]byte, 0, 128), delayedMsg: firstDelayed, @@ -936,10 +949,29 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) } if b.building == nil || b.building.startMsgCount != batchPosition.MessageCount { + latestHeader, err := b.l1Reader.LastHeader(ctx) + if err != nil { + return false, err + } + var use4844 bool + config := b.config() + if config.Post4844Blobs && latestHeader.ExcessBlobGas != nil && latestHeader.BlobGasUsed != nil { + if config.ForcePost4844Blobs { + use4844 = true + } else { + blobFeePerByte := eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*latestHeader.ExcessBlobGas, *latestHeader.BlobGasUsed)) + blobFeePerByte.Mul(blobFeePerByte, blobTxBlobGasPerBlob) + blobFeePerByte.Div(blobFeePerByte, usableBytesInBlob) + + calldataFeePerByte := arbmath.BigMulByUint(latestHeader.BaseFee, 16) + use4844 = arbmath.BigLessThan(blobFeePerByte, calldataFeePerByte) + } + } b.building = &buildingBatch{ - segments: newBatchSegments(batchPosition.DelayedMessageCount, b.config(), b.GetBacklogEstimate()), + segments: newBatchSegments(batchPosition.DelayedMessageCount, b.config(), b.GetBacklogEstimate(), use4844), msgCount: batchPosition.MessageCount, startMsgCount: batchPosition.MessageCount, + use4844: use4844, } } msgCount, err := b.streamer.GetMessageCount() @@ -1115,26 +1147,12 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) } } - latestHeader, err := b.l1Reader.LastHeader(ctx) + data, kzgBlobs, err := b.encodeAddBatch(new(big.Int).SetUint64(batchPosition.NextSeqNum), batchPosition.MessageCount, b.building.msgCount, sequencerMsg, b.building.segments.delayedMsg, b.building.use4844) if err != nil { return false, err } - var use4844 bool - if config.Post4844Blobs && latestHeader.ExcessBlobGas != nil && latestHeader.BlobGasUsed != nil { - if config.ForcePost4844Blobs { - use4844 = true - } else { - blobFeePerByte := eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*latestHeader.ExcessBlobGas, *latestHeader.BlobGasUsed)) - blobFeePerByte.Mul(blobFeePerByte, blobTxBlobGasPerBlob) - blobFeePerByte.Div(blobFeePerByte, usableBytesInBlob) - - calldataFeePerByte := arbmath.BigMulByUint(latestHeader.BaseFee, 16) - use4844 = arbmath.BigLessThan(blobFeePerByte, calldataFeePerByte) - } - } - data, kzgBlobs, err := b.encodeAddBatch(new(big.Int).SetUint64(batchPosition.NextSeqNum), batchPosition.MessageCount, b.building.msgCount, sequencerMsg, b.building.segments.delayedMsg, use4844) - if err != nil { - return false, err + if len(kzgBlobs)*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock { + return false, fmt.Errorf("produced %v blobs for batch but a block can only hold %v", len(kzgBlobs), params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob) } accessList := b.accessList(int(batchPosition.NextSeqNum), int(b.building.segments.delayedMsg)) // On restart, we may be trying to estimate gas for a batch whose successor has From ec2541b8e79d35c280301136717af707e844ae95 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 25 Jan 2024 15:33:24 +0100 Subject: [PATCH 671/775] Fix nitro-fuzzer entrypoint argument --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9f8a5a75d..8a4b40e1f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -198,7 +198,7 @@ FROM debian:bookworm-slim as nitro-fuzzer COPY --from=fuzz-builder /workspace/fuzzers/*.fuzz /usr/local/bin/ COPY ./scripts/fuzz.bash /usr/local/bin RUN mkdir /fuzzcache -ENTRYPOINT [ "/usr/local/bin/fuzz.bash", "--binary-path", "/usr/local/bin/", "--fuzzcache-path", "/fuzzcache" ] +ENTRYPOINT [ "/usr/local/bin/fuzz.bash", "FuzzStateTransition", "--binary-path", "/usr/local/bin/", "--fuzzcache-path", "/fuzzcache" ] FROM debian:bookworm-slim as nitro-node-slim WORKDIR /home/user From 4445f9337909e5da6ab5118dd858feac244efe3d Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 25 Jan 2024 15:44:07 +0100 Subject: [PATCH 672/775] Fix script to complain when neither build nor fuzzer name is specified --- scripts/fuzz.bash | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/fuzz.bash b/scripts/fuzz.bash index d236f90ce..f1f84d9ba 100755 --- a/scripts/fuzz.bash +++ b/scripts/fuzz.bash @@ -83,6 +83,11 @@ while [[ $# -gt 0 ]]; do esac done +if [[ "$run_build" == "false" && -z "$test_group" ]]; then + echo you must specify either --build flag or fuzzer-name + printusage +fi + if $run_build; then for build_group in system_tests arbstate; do go test -c ${nitropath}/${build_group} -fuzz Fuzz -o "$binpath"/${build_group}.fuzz From 2e5832e33b91fa851c2267ad76cddec59d335f36 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 25 Jan 2024 16:26:54 +0100 Subject: [PATCH 673/775] Add flag to fuzz script for timeout --- scripts/fuzz.bash | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/scripts/fuzz.bash b/scripts/fuzz.bash index f1f84d9ba..91373d81f 100755 --- a/scripts/fuzz.bash +++ b/scripts/fuzz.bash @@ -7,12 +7,14 @@ cd "$mydir" function printusage { echo Usage: $0 --build \[--binary-path PATH\] - echo " " $0 \ \[--binary-path PATH\] \[--fuzzcache-path PATH\] \[--nitro-path PATH\] + echo " " $0 \ \[--binary-path PATH\] \[--fuzzcache-path PATH\] \[--nitro-path PATH\] \[--duration DURATION\] echo echo fuzzer names: echo " " FuzzPrecompiles echo " " FuzzInboxMultiplexer echo " " FuzzStateTransition + echo + echo " " duration in minutes } if [[ $# -eq 0 ]]; then @@ -26,6 +28,7 @@ fuzzcachepath=../target/var/fuzz-cache nitropath=../ run_build=false test_group="" +duration=60 while [[ $# -gt 0 ]]; do case $1 in --nitro-path) @@ -55,6 +58,15 @@ while [[ $# -gt 0 ]]; do shift shift ;; + --duration) + duration="$2" + if ! [[ "$duration" =~ ^[0-9]+$ ]]; then + echo "Invalid timeout duration. Please specify positive integer (in minutes)" + exit 1 + fi + shift + shift + ;; --build) run_build=true shift @@ -95,5 +107,5 @@ if $run_build; then fi if [[ ! -z $test_group ]]; then - "$binpath"/${test_group}.fuzz -test.run "^$" -test.fuzzcachedir "$fuzzcachepath" -test.fuzz $test_name + timeout "$((60 * duration))" "$binpath"/${test_group}.fuzz -test.run "^$" -test.fuzzcachedir "$fuzzcachepath" -test.fuzz $test_name fi From 601681a1e758ee3bb0b09989fc76e27adb8b1739 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 25 Jan 2024 16:31:53 +0100 Subject: [PATCH 674/775] Add workflow for release ci that is triggered with PR tag, run nitro fuzzer in it --- .github/workflows/release-ci.yml | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/release-ci.yml diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml new file mode 100644 index 000000000..729b2696f --- /dev/null +++ b/.github/workflows/release-ci.yml @@ -0,0 +1,37 @@ +name: Release CI +run-name: Release CI triggered from @${{ github.actor }} of ${{ github.head_ref }} + +on: + pull_request: + types: + - master + - develop + +jobs: + build_and_run: + runs-on: ubuntu-8 + + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Check PR Title For Release Candidate Tag ([Release]) + run: | + if [[ ${{ github.event.pull_request.title }} == "[Release]" ]]; then + echo "Release candidate." + else + echo "Not a release candidate. Skipping workflow." + exit 0 + fi + + - name: Build nitro-fuzzer Docker Image + run: docker build --target nitro-fuzzer -t nitro-fuzzer-image . + + - name: Run Docker Container + run: docker run --name nitro-fuzzer-container nitro-fuzzer-image & + + - name: Stop Docker Container + run: docker stop nitro-fuzzer-container From 86cf5ca837284a0f2671799be9c68aa457f070a3 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 25 Jan 2024 16:41:03 +0100 Subject: [PATCH 675/775] Trigger workflow from label instead of PR title --- .github/workflows/release-ci.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index 729b2696f..8dff82ec9 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -18,9 +18,9 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - - name: Check PR Title For Release Candidate Tag ([Release]) + - name: Check PR Label For Release label run: | - if [[ ${{ github.event.pull_request.title }} == "[Release]" ]]; then + if contains(github.event.pull_request.labels.*.name, 'release') echo "Release candidate." else echo "Not a release candidate. Skipping workflow." @@ -28,10 +28,7 @@ jobs: fi - name: Build nitro-fuzzer Docker Image - run: docker build --target nitro-fuzzer -t nitro-fuzzer-image . + run: docker build --target nitro-fuzzer -t nitro-fuzzer . - name: Run Docker Container - run: docker run --name nitro-fuzzer-container nitro-fuzzer-image & - - - name: Stop Docker Container - run: docker stop nitro-fuzzer-container + run: docker run nitro-fuzzer From 041aa35ef1630e846ae06cba4861f8180e7be85c Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 25 Jan 2024 08:42:46 -0700 Subject: [PATCH 676/775] upgrade geth to 1.13.3 this version of geth doesn't support Address.Hash() function, so we converted these. --- arbnode/inbox_test.go | 3 ++- go-ethereum | 2 +- go.mod | 15 +++++++------ go.sum | 34 +++++++++++++++-------------- precompiles/precompile_test.go | 21 ++++++++---------- staker/validatorwallet/contract.go | 2 +- system_tests/initialization_test.go | 10 ++++----- 7 files changed, 44 insertions(+), 43 deletions(-) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 92d216f76..e979979de 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -144,12 +144,13 @@ func TestTransactionStreamer(t *testing.T) { } else { dest = state.accounts[rand.Int()%len(state.accounts)] } + destHash := common.BytesToHash(dest.Bytes()) var gas uint64 = 100000 var l2Message []byte l2Message = append(l2Message, arbos.L2MessageKind_ContractTx) l2Message = append(l2Message, arbmath.Uint64ToU256Bytes(gas)...) l2Message = append(l2Message, arbmath.Uint64ToU256Bytes(l2pricing.InitialBaseFeeWei)...) - l2Message = append(l2Message, dest.Hash().Bytes()...) + l2Message = append(l2Message, destHash.Bytes()...) l2Message = append(l2Message, arbmath.U256Bytes(value)...) var requestId common.Hash binary.BigEndian.PutUint64(requestId.Bytes()[:8], uint64(i)) diff --git a/go-ethereum b/go-ethereum index 5a266a5b6..85f420d8e 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 5a266a5b6853a9ddd76f25c3e02ac2265fef7996 +Subproject commit 85f420d8eb6d82b91e808b2ee5ae3c8c6ff9cd9d diff --git a/go.mod b/go.mod index 1d76b3997..2d689f489 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.10 github.com/aws/aws-sdk-go-v2/service/s3 v1.26.9 github.com/cavaliergopher/grab/v3 v3.0.1 - github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 + github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 github.com/codeclysm/extract/v3 v3.0.2 github.com/dgraph-io/badger/v3 v3.2103.2 github.com/enescakir/emoji v1.0.0 @@ -43,7 +43,7 @@ require ( golang.org/x/crypto v0.17.0 golang.org/x/sys v0.15.0 golang.org/x/term v0.15.0 - golang.org/x/tools v0.9.1 + golang.org/x/tools v0.13.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) @@ -83,13 +83,14 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect - github.com/crate-crypto/go-kzg-4844 v0.3.0 // indirect + github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/cskr/pubsub v1.0.2 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect @@ -102,7 +103,7 @@ require ( github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/ethereum/c-kzg-4844 v0.3.1 // indirect + github.com/ethereum/c-kzg-4844 v0.4.0 // indirect github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect @@ -252,7 +253,7 @@ require ( github.com/samber/lo v1.36.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/supranational/blst v0.3.11 // indirect - github.com/urfave/cli/v2 v2.24.1 // indirect + github.com/urfave/cli/v2 v2.25.7 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect @@ -280,8 +281,8 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.24.0 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect - golang.org/x/exp v0.0.0-20230810033253-352e893a4cad // indirect - golang.org/x/mod v0.11.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sync v0.3.0 // indirect golang.org/x/text v0.14.0 // indirect diff --git a/go.sum b/go.sum index 872afcafb..a2b483c10 100644 --- a/go.sum +++ b/go.sum @@ -45,7 +45,7 @@ github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOv github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= @@ -226,16 +226,18 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/datadriven v1.0.3-0.20230801171734-e384cf455877 h1:1MLK4YpFtIEo3ZtMA5C795Wtv5VuUnrXX7mQG+aHg6o= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 h1:T+Np/xtzIjYM/P5NAw0e2Rf1FGvzDau1h54MKvx8G7w= -github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06/go.mod h1:bynZ3gvVyhlvjLI7PT6dmZ7g76xzJ7HpxfjgkzCGz6s= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codeclysm/extract/v3 v3.0.2 h1:sB4LcE3Php7LkhZwN0n2p8GCwZe92PEQutdbGURf5xc= github.com/codeclysm/extract/v3 v3.0.2/go.mod h1:NKsw+hqua9H+Rlwy/w/3Qgt9jDonYEgB6wJu+25eOKw= @@ -264,8 +266,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= -github.com/crate-crypto/go-kzg-4844 v0.3.0 h1:UBlWE0CgyFqqzTI+IFyCzA7A3Zw4iip6uzRv5NIXG0A= -github.com/crate-crypto/go-kzg-4844 v0.3.0/go.mod h1:SBP7ikXEgDnUPONgm33HtuDZEDtWa3L4QtN1ocJSEQ4= +github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= +github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= @@ -338,8 +340,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum/c-kzg-4844 v0.3.1 h1:sR65+68+WdnMKxseNWxSJuAv2tsUrihTpVBTfM/U5Zg= -github.com/ethereum/c-kzg-4844 v0.3.1/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= +github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= @@ -1621,8 +1623,8 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/urfave/cli/v2 v2.24.1 h1:/QYYr7g0EhwXEML8jO+8OYt5trPnLHS0p3mrgExJ5NU= -github.com/urfave/cli/v2 v2.24.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -1803,8 +1805,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230810033253-352e893a4cad h1:g0bG7Z4uG+OgH2QDODnjp6ggkk1bJDsINcuWmJN1iJU= -golang.org/x/exp v0.0.0-20230810033253-352e893a4cad/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1829,8 +1831,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= -golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2102,8 +2104,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/precompiles/precompile_test.go b/precompiles/precompile_test.go index b19b2d435..02d962f0b 100644 --- a/precompiles/precompile_test.go +++ b/precompiles/precompile_test.go @@ -4,7 +4,6 @@ package precompiles import ( - "bytes" "math/big" "testing" @@ -35,16 +34,14 @@ func TestEvents(t *testing.T) { } } - zeroHash := crypto.Keccak256([]byte{0x00}) - trueHash := common.Hash{}.Bytes() - falseHash := common.Hash{}.Bytes() - trueHash[31] = 0x01 + zeroHash := crypto.Keccak256Hash([]byte{0x00}) + falseHash := common.Hash{} var data []byte payload := [][]byte{ method.template.ID, // select the `Events` method - falseHash, // set the flag to false - zeroHash, // set the value to something known + falseHash.Bytes(), // set the flag to false + zeroHash.Bytes(), // set the value to something known } for _, bytes := range payload { data = append(data, bytes...) @@ -100,13 +97,13 @@ func TestEvents(t *testing.T) { basicTopics := logs[0].Topics mixedTopics := logs[1].Topics - if !bytes.Equal(basicTopics[1].Bytes(), zeroHash) || !bytes.Equal(mixedTopics[2].Bytes(), zeroHash) { + if basicTopics[1] != zeroHash || mixedTopics[2] != zeroHash { Fail(t, "indexing a bytes32 didn't work") } - if !bytes.Equal(mixedTopics[1].Bytes(), falseHash) { + if mixedTopics[1] != falseHash { Fail(t, "indexing a bool didn't work") } - if !bytes.Equal(mixedTopics[3].Bytes(), caller.Hash().Bytes()) { + if mixedTopics[3] != common.BytesToHash(caller.Bytes()) { Fail(t, "indexing an address didn't work") } @@ -117,10 +114,10 @@ func TestEvents(t *testing.T) { Fail(t, "failed to parse event logs", "\nprecompile:", cerr, "\nbasic:", berr, "\nmixed:", merr) } - if basic.Flag != true || !bytes.Equal(basic.Value[:], zeroHash) { + if basic.Flag != true || basic.Value != zeroHash { Fail(t, "event Basic's data isn't correct") } - if mixed.Flag != false || mixed.Not != true || !bytes.Equal(mixed.Value[:], zeroHash) { + if mixed.Flag != false || mixed.Not != true || mixed.Value != zeroHash { Fail(t, "event Mixed's data isn't correct") } if mixed.Conn != debugContractAddr || mixed.Caller != caller { diff --git a/staker/validatorwallet/contract.go b/staker/validatorwallet/contract.go index 774e9ab40..d5c783421 100644 --- a/staker/validatorwallet/contract.go +++ b/staker/validatorwallet/contract.go @@ -420,7 +420,7 @@ func GetValidatorWalletContract( FromBlock: big.NewInt(fromBlock), ToBlock: nil, Addresses: []common.Address{validatorWalletFactoryAddr}, - Topics: [][]common.Hash{{walletCreatedID}, nil, {transactAuth.From.Hash()}}, + Topics: [][]common.Hash{{walletCreatedID}, nil, {common.BytesToHash(transactAuth.From.Bytes())}}, } logs, err := client.FilterLogs(ctx, query) if err != nil { diff --git a/system_tests/initialization_test.go b/system_tests/initialization_test.go index 6707df1c6..f0797404a 100644 --- a/system_tests/initialization_test.go +++ b/system_tests/initialization_test.go @@ -24,11 +24,11 @@ func InitOneContract(prand *testhelpers.PseudoRandomDataSource) (*statetransfer. numCells := int(prand.GetUint64() % 1000) for i := 0; i < numCells; i++ { storageAddr := prand.GetHash() - storageVal := prand.GetAddress().Hash() // 20 bytes so sum won't overflow - code = append(code, 0x7f) // PUSH32 - code = append(code, storageAddr[:]...) // storageAdr - code = append(code, 0x54) // SLOAD - code = append(code, 0x01) // ADD + storageVal := common.BytesToHash(prand.GetAddress().Bytes()) // 20 bytes so sum won't overflow + code = append(code, 0x7f) // PUSH32 + code = append(code, storageAddr[:]...) // storageAdr + code = append(code, 0x54) // SLOAD + code = append(code, 0x01) // ADD storageMap[storageAddr] = storageVal sum.Add(sum, storageVal.Big()) } From 32ea163d1549ad40300370f09efa61b979ad8b45 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 25 Jan 2024 16:44:53 +0100 Subject: [PATCH 677/775] Update workflow triggering conditions --- .github/workflows/release-ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index 8dff82ec9..14121e6ec 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -2,11 +2,13 @@ name: Release CI run-name: Release CI triggered from @${{ github.actor }} of ${{ github.head_ref }} on: + workflow_dispatch: + merge_group: pull_request: - types: + push: + branches: - master - develop - jobs: build_and_run: runs-on: ubuntu-8 From 991f055de6a9867c1b1d4514d1d9273114d24c50 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 25 Jan 2024 17:01:58 +0100 Subject: [PATCH 678/775] Fix workflow syntax --- .github/workflows/release-ci.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index 14121e6ec..9fbe22d87 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -21,13 +21,10 @@ jobs: uses: docker/setup-buildx-action@v1 - name: Check PR Label For Release label + if: !contains(github.event.pull_request.labels.*.name, 'release') run: | - if contains(github.event.pull_request.labels.*.name, 'release') - echo "Release candidate." - else - echo "Not a release candidate. Skipping workflow." - exit 0 - fi + echo "Not a release candidate. Skipping workflow." + exit 0 - name: Build nitro-fuzzer Docker Image run: docker build --target nitro-fuzzer -t nitro-fuzzer . From e71ca4b5148db599b304bb9849067ae39f230873 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 25 Jan 2024 17:08:32 +0100 Subject: [PATCH 679/775] Yet another attempt to fix workflow syntax --- .github/workflows/release-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index 9fbe22d87..b5dae5745 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -21,7 +21,7 @@ jobs: uses: docker/setup-buildx-action@v1 - name: Check PR Label For Release label - if: !contains(github.event.pull_request.labels.*.name, 'release') + if: ${{ !contains(github.event.*.labels.*.name, 'release') }} run: | echo "Not a release candidate. Skipping workflow." exit 0 From ee8cc8d2350c05ba5b429748aec8a94e06cf58fa Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 25 Jan 2024 17:17:45 +0100 Subject: [PATCH 680/775] Checout submodules recursively in the workflow, cache docker layers --- .github/workflows/release-ci.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index b5dae5745..4981513a1 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -14,11 +14,23 @@ jobs: runs-on: ubuntu-8 steps: - - name: Checkout Repository - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 + with: + driver-opts: network=host + + - name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ hashFiles('Dockerfile') }} + restore-keys: ${{ runner.os }}-buildx- + - name: Check PR Label For Release label if: ${{ !contains(github.event.*.labels.*.name, 'release') }} From 47053b95dfb3e9b516a177f70c91c5ccc176cef1 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 25 Jan 2024 13:08:33 -0700 Subject: [PATCH 681/775] In delayed sequencer, check accumulator against safe block hash --- arbnode/delayed.go | 41 +++++++++++++++++++++++++++++++----- arbnode/delayed_sequencer.go | 10 ++++++--- arbnode/inbox_reader.go | 3 ++- arbutil/wait_for_l1.go | 1 + 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/arbnode/delayed.go b/arbnode/delayed.go index 498aa0475..2a1745c54 100644 --- a/arbnode/delayed.go +++ b/arbnode/delayed.go @@ -7,6 +7,7 @@ import ( "bytes" "context" "errors" + "fmt" "math/big" "sort" @@ -14,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -28,6 +30,7 @@ var messageDeliveredID common.Hash var inboxMessageDeliveredID common.Hash var inboxMessageFromOriginID common.Hash var l2MessageFromOriginCallABI abi.Method +var delayedInboxAccsCallABI abi.Method func init() { parsedIBridgeABI, err := bridgegen.IBridgeMetaData.GetAbi() @@ -35,6 +38,7 @@ func init() { panic(err) } messageDeliveredID = parsedIBridgeABI.Events["MessageDelivered"].ID + delayedInboxAccsCallABI = parsedIBridgeABI.Methods["delayedInboxAccs"] parsedIMessageProviderABI, err := bridgegen.IDelayedMessageProviderMetaData.GetAbi() if err != nil { @@ -95,12 +99,39 @@ func (b *DelayedBridge) GetMessageCount(ctx context.Context, blockNumber *big.In return bigRes.Uint64(), nil } -func (b *DelayedBridge) GetAccumulator(ctx context.Context, sequenceNumber uint64, blockNumber *big.Int) (common.Hash, error) { - opts := &bind.CallOpts{ - Context: ctx, - BlockNumber: blockNumber, +// Uses blockHash if nonzero, otherwise uses blockNumber +func (b *DelayedBridge) GetAccumulator(ctx context.Context, sequenceNumber uint64, blockNumber *big.Int, blockHash common.Hash) (common.Hash, error) { + calldata := append([]byte{}, delayedInboxAccsCallABI.ID...) + inputs, err := delayedInboxAccsCallABI.Inputs.Pack(arbmath.UintToBig(sequenceNumber)) + if err != nil { + return common.Hash{}, err + } + calldata = append(calldata, inputs...) + msg := ethereum.CallMsg{ + To: &b.address, + Data: calldata, + } + var result hexutil.Bytes + if blockHash != (common.Hash{}) { + result, err = b.client.CallContractAtHash(ctx, msg, blockHash) + } else { + result, err = b.client.CallContract(ctx, msg, blockNumber) + } + if err != nil { + return common.Hash{}, err + } + values, err := delayedInboxAccsCallABI.Outputs.Unpack(result) + if err != nil { + return common.Hash{}, err + } + if len(values) != 1 { + return common.Hash{}, fmt.Errorf("expected 1 return value from %v, got %v", delayedInboxAccsCallABI.Name, len(values)) + } + hash, ok := values[0].([32]byte) + if !ok { + return common.Hash{}, fmt.Errorf("expected [32]uint8 return value from %v, got %T", delayedInboxAccsCallABI.Name, values[0]) } - return b.con.DelayedInboxAccs(opts, new(big.Int).SetUint64(sequenceNumber)) + return hash, nil } type DelayedInboxMessage struct { diff --git a/arbnode/delayed_sequencer.go b/arbnode/delayed_sequencer.go index f1b912e0f..8cbb094c1 100644 --- a/arbnode/delayed_sequencer.go +++ b/arbnode/delayed_sequencer.go @@ -100,16 +100,20 @@ func (d *DelayedSequencer) sequenceWithoutLockout(ctx context.Context, lastBlock } var finalized uint64 + var finalizedHash common.Hash if config.UseMergeFinality && headerreader.HeaderIndicatesFinalitySupport(lastBlockHeader) { + var header *types.Header var err error if config.RequireFullFinality { - finalized, err = d.l1Reader.LatestFinalizedBlockNr(ctx) + header, err = d.l1Reader.LatestFinalizedBlockHeader(ctx) } else { - finalized, err = d.l1Reader.LatestSafeBlockNr(ctx) + header, err = d.l1Reader.LatestSafeBlockHeader(ctx) } if err != nil { return err } + finalized = header.Number.Uint64() + finalizedHash = header.Hash() } else { currentNum := lastBlockHeader.Number.Int64() if currentNum < config.FinalizeDistance { @@ -167,7 +171,7 @@ func (d *DelayedSequencer) sequenceWithoutLockout(ctx context.Context, lastBlock // Sequence the delayed messages, if any if len(messages) > 0 { - delayedBridgeAcc, err := d.bridge.GetAccumulator(ctx, pos-1, new(big.Int).SetUint64(finalized)) + delayedBridgeAcc, err := d.bridge.GetAccumulator(ctx, pos-1, new(big.Int).SetUint64(finalized), finalizedHash) if err != nil { return err } diff --git a/arbnode/inbox_reader.go b/arbnode/inbox_reader.go index 9c830e3c8..7a2ffa505 100644 --- a/arbnode/inbox_reader.go +++ b/arbnode/inbox_reader.go @@ -14,6 +14,7 @@ import ( "sync/atomic" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" flag "github.com/spf13/pflag" @@ -299,7 +300,7 @@ func (r *InboxReader) run(ctx context.Context, hadError bool) error { } if checkingDelayedCount > 0 { checkingDelayedSeqNum := checkingDelayedCount - 1 - l1DelayedAcc, err := r.delayedBridge.GetAccumulator(ctx, checkingDelayedSeqNum, currentHeight) + l1DelayedAcc, err := r.delayedBridge.GetAccumulator(ctx, checkingDelayedSeqNum, currentHeight, common.Hash{}) if err != nil { return err } diff --git a/arbutil/wait_for_l1.go b/arbutil/wait_for_l1.go index b66710dbf..a80502610 100644 --- a/arbutil/wait_for_l1.go +++ b/arbutil/wait_for_l1.go @@ -23,6 +23,7 @@ type L1Interface interface { ethereum.TransactionReader TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) BlockNumber(ctx context.Context) (uint64, error) + CallContractAtHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) ([]byte, error) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) ChainID(ctx context.Context) (*big.Int, error) } From 158bf199046f966f31a53736978b980e989156e8 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 25 Jan 2024 13:38:39 -0700 Subject: [PATCH 682/775] update geth branch --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 85f420d8e..e5ecb9d3f 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 85f420d8eb6d82b91e808b2ee5ae3c8c6ff9cd9d +Subproject commit e5ecb9d3f4305cd83e458cc99b256ba4dfd05451 From ddefe8ba8fb3bf9b7f37be646d550fdd818ee905 Mon Sep 17 00:00:00 2001 From: Joshua Colvin Date: Thu, 25 Jan 2024 17:47:23 -0700 Subject: [PATCH 683/775] update geth pin --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index e5ecb9d3f..18a471f98 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit e5ecb9d3f4305cd83e458cc99b256ba4dfd05451 +Subproject commit 18a471f98ecac1b0877bb64773f482446aba191b From 14fb850901b57393809853b7d532537cf65c78d2 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Fri, 26 Jan 2024 12:04:44 +0100 Subject: [PATCH 684/775] Ignore timeout error, and error out only if the fuzzing binary errors out --- scripts/fuzz.bash | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/fuzz.bash b/scripts/fuzz.bash index 91373d81f..6271b917b 100755 --- a/scripts/fuzz.bash +++ b/scripts/fuzz.bash @@ -107,5 +107,12 @@ if $run_build; then fi if [[ ! -z $test_group ]]; then - timeout "$((60 * duration))" "$binpath"/${test_group}.fuzz -test.run "^$" -test.fuzzcachedir "$fuzzcachepath" -test.fuzz $test_name + timeout "$((60 * duration))" "$binpath"/${test_group}.fuzz -test.run "^$" -test.fuzzcachedir "$fuzzcachepath" -test.fuzz $test_name || exit_status=$? fi + +if [ -n "$exit_status" ] && [ $exit_status -ne 0 ] && [ $exit_status -ne 124 ]; then + echo "Fuzzing failed." + exit $exit_status +fi + +echo "Fuzzing succeeded." From 8789f1c4a6fdaa9d4de45479d08c70a30f958e03 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 26 Jan 2024 11:01:10 -0700 Subject: [PATCH 685/775] Fix LookupNodeChildren for L3s --- staker/rollup_watcher.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/staker/rollup_watcher.go b/staker/rollup_watcher.go index c9fa3b132..118ce15b4 100644 --- a/staker/rollup_watcher.go +++ b/staker/rollup_watcher.go @@ -176,16 +176,18 @@ func (r *RollupWatcher) LookupNodeChildren(ctx context.Context, nodeNum uint64, if node.NodeHash != nodeHash { return nil, fmt.Errorf("got unexpected node hash %v looking for node number %v with expected hash %v (reorg?)", node.NodeHash, nodeNum, nodeHash) } - latestChild, err := r.RollupUserLogic.GetNode(r.getCallOpts(ctx), node.LatestChildNumber) - if err != nil { - return nil, err - } var query = ethereum.FilterQuery{ - FromBlock: new(big.Int).SetUint64(node.CreatedAtBlock), - ToBlock: new(big.Int).SetUint64(latestChild.CreatedAtBlock), Addresses: []common.Address{r.address}, Topics: [][]common.Hash{{nodeCreatedID}, nil, {nodeHash}}, } + query.FromBlock, err = r.getNodeCreationBlock(ctx, nodeNum) + if err != nil { + return nil, err + } + query.ToBlock, err = r.getNodeCreationBlock(ctx, node.LatestChildNumber) + if err != nil { + return nil, err + } logs, err := r.client.FilterLogs(ctx, query) if err != nil { return nil, err From 3d85d89f50d76c785a840f08a608eb16ebe545fb Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Fri, 26 Jan 2024 15:30:34 -0600 Subject: [PATCH 686/775] Add a flag to enable re-execution of a range of historic blocks --- blocks_reexecutor/blocks_reexecutor.go | 172 +++++++++++++++++++++++++ cmd/nitro/nitro.go | 96 ++++++++------ system_tests/blocks_reexecutor_test.go | 87 +++++++++++++ 3 files changed, 313 insertions(+), 42 deletions(-) create mode 100644 blocks_reexecutor/blocks_reexecutor.go create mode 100644 system_tests/blocks_reexecutor_test.go diff --git a/blocks_reexecutor/blocks_reexecutor.go b/blocks_reexecutor/blocks_reexecutor.go new file mode 100644 index 000000000..f367ad734 --- /dev/null +++ b/blocks_reexecutor/blocks_reexecutor.go @@ -0,0 +1,172 @@ +package blocksreexecutor + +import ( + "context" + "errors" + "fmt" + "math/rand" + "runtime" + + "github.com/ethereum/go-ethereum/arbitrum" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/stopwaiter" + flag "github.com/spf13/pflag" +) + +type Config struct { + Enable bool `koanf:"enable"` + Mode string `koanf:"mode"` + StartBlock uint64 `koanf:"start-block"` + EndBlock uint64 `koanf:"end-block"` + Room int `koanf:"room"` + BlocksPerThread uint64 `koanf:"blocks-per-thread"` +} + +func (c *Config) Validate() error { + if c.Enable && c.Mode != "random" && c.Mode != "full" { + return errors.New("invalid mode for blocks re-execution") + } + if c.EndBlock < c.StartBlock { + return errors.New("invalid block range for blocks re-execution") + } + if c.Room == 0 { + return errors.New("room for blocks re-execution cannot be zero") + } + return nil +} + +var DefaultConfig = Config{ + Enable: false, + Mode: "random", + Room: runtime.NumCPU(), + BlocksPerThread: 10000, +} + +var TestConfig = Config{ + Enable: true, + Mode: "full", + Room: runtime.NumCPU(), + BlocksPerThread: 10, +} + +func ConfigAddOptions(prefix string, f *flag.FlagSet) { + f.Bool(prefix+".enable", DefaultConfig.Enable, "enables re-execution of a range of blocks against historic state") + f.String(prefix+".mode", DefaultConfig.Mode, "mode to run the blocks-reexecutor on. Valid modes full and random. full - execute all the blocks in the given range. random - execute a random sample range of blocks with in a given range") + f.Uint64(prefix+".start-block", DefaultConfig.StartBlock, "first block number of the block range for re-execution") + f.Uint64(prefix+".end-block", DefaultConfig.EndBlock, "last block number of the block range for re-execution") + f.Int(prefix+".room", DefaultConfig.Room, "number of threads to parallelize blocks re-execution") + f.Uint64(prefix+".blocks-per-thread", DefaultConfig.BlocksPerThread, "minimum number of blocks to execute per thread. When mode is random this acts as the size of random block range sample") +} + +type BlocksReExecutor struct { + stopwaiter.StopWaiter + config *Config + blockchain *core.BlockChain + stateFor func(header *types.Header) (*state.StateDB, error) + done chan struct{} + fatalErrChan chan error + startBlock uint64 + currentBlock uint64 +} + +func New(c *Config, blockchain *core.BlockChain, fatalErrChan chan error) *BlocksReExecutor { + start := c.StartBlock + end := c.EndBlock + chainStart := blockchain.Config().ArbitrumChainParams.GenesisBlockNum + chainEnd := blockchain.CurrentBlock().Number.Uint64() + if start == 0 && end == 0 { + start = chainStart + end = chainEnd + } + if start < chainStart { + log.Warn("state reexecutor's start block number is lower than genesis, resetting to genesis") + start = chainStart + } + if end > chainEnd { + log.Warn("state reexecutor's end block number is greater than latest, resetting to latest") + end = chainEnd + } + if c.Mode == "random" && end != start { + if c.BlocksPerThread > end-start { + c.BlocksPerThread = end - start + } + start += uint64(rand.Intn(int(end - start - c.BlocksPerThread + 1))) + end = start + c.BlocksPerThread + } + // inclusive of block reexecution [start, end] + if start > 0 { + start-- + } + return &BlocksReExecutor{ + config: c, + blockchain: blockchain, + currentBlock: end, + startBlock: start, + done: make(chan struct{}, c.Room), + fatalErrChan: fatalErrChan, + stateFor: func(header *types.Header) (*state.StateDB, error) { return blockchain.StateAt(header.Root) }, + } +} + +// LaunchBlocksReExecution launches the thread to apply blocks of range [currentBlock-s.config.BlocksPerThread, currentBlock] to the last available valid state +func (s *BlocksReExecutor) LaunchBlocksReExecution(ctx context.Context, currentBlock uint64) uint64 { + start := arbmath.SaturatingUSub(currentBlock, s.config.BlocksPerThread) + if start < s.startBlock { + start = s.startBlock + } + startState, startHeader, err := arbitrum.FindLastAvailableState(ctx, s.blockchain, s.stateFor, s.blockchain.GetHeaderByNumber(start), nil, -1) + if err != nil { + s.fatalErrChan <- fmt.Errorf("blocksReExecutor failed to get last available state while searching for state at %d, err: %w", start, err) + return s.startBlock + } + start = startHeader.Number.Uint64() + s.LaunchThread(func(ctx context.Context) { + _, err := arbitrum.AdvanceStateUpToBlock(ctx, s.blockchain, startState, s.blockchain.GetHeaderByNumber(currentBlock), startHeader, nil) + if err != nil { + s.fatalErrChan <- fmt.Errorf("blocksReExecutor errored advancing state from block %d to block %d, err: %w", start, currentBlock, err) + } else { + log.Info("Successfully reexecuted blocks against historic state", "stateAt", start, "startBlock", start+1, "endBlock", currentBlock) + } + s.done <- struct{}{} + }) + return start +} + +func (s *BlocksReExecutor) Impl(ctx context.Context) { + var threadsLaunched uint64 + end := s.currentBlock + for i := 0; i < s.config.Room && s.currentBlock > s.startBlock; i++ { + threadsLaunched++ + s.currentBlock = s.LaunchBlocksReExecution(ctx, s.currentBlock) + } + for { + select { + case <-s.done: + if s.currentBlock > s.startBlock { + s.currentBlock = s.LaunchBlocksReExecution(ctx, s.currentBlock) + } else { + threadsLaunched-- + } + + case <-ctx.Done(): + return + } + if threadsLaunched == 0 { + break + } + } + log.Info("BlocksReExecutor successfully completed re-execution of blocks against historic state", "stateAt", s.startBlock, "startBlock", s.startBlock+1, "endBlock", end) +} + +func (s *BlocksReExecutor) Start(ctx context.Context) { + s.StopWaiter.Start(ctx, s) + s.LaunchThread(s.Impl) +} + +func (s *BlocksReExecutor) StopAndWait() { + s.StopWaiter.StopAndWait() +} diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 45f539488..f50908413 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -43,6 +43,7 @@ import ( "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbnode/resourcemanager" "github.com/offchainlabs/nitro/arbutil" + blocksreexecutor "github.com/offchainlabs/nitro/blocks_reexecutor" "github.com/offchainlabs/nitro/cmd/chaininfo" "github.com/offchainlabs/nitro/cmd/conf" "github.com/offchainlabs/nitro/cmd/genericconf" @@ -624,6 +625,11 @@ func mainImpl() int { // remove previous deferFuncs, StopAndWait closes database and blockchain. deferFuncs = []func(){func() { currentNode.StopAndWait() }} } + if nodeConfig.BlocksReExecutor.Enable && l2BlockChain != nil { + blocksReExecutor := blocksreexecutor.New(&nodeConfig.BlocksReExecutor, l2BlockChain, fatalErrChan) + blocksReExecutor.Start(ctx) + deferFuncs = append(deferFuncs, func() { blocksReExecutor.StopAndWait() }) + } sigint := make(chan os.Signal, 1) signal.Notify(sigint, os.Interrupt, syscall.SIGTERM) @@ -659,51 +665,53 @@ func mainImpl() int { } type NodeConfig struct { - Conf genericconf.ConfConfig `koanf:"conf" reload:"hot"` - Node arbnode.Config `koanf:"node" reload:"hot"` - Execution gethexec.Config `koanf:"execution" reload:"hot"` - Validation valnode.Config `koanf:"validation" reload:"hot"` - ParentChain conf.L1Config `koanf:"parent-chain" reload:"hot"` - Chain conf.L2Config `koanf:"chain"` - LogLevel int `koanf:"log-level" reload:"hot"` - LogType string `koanf:"log-type" reload:"hot"` - FileLogging genericconf.FileLoggingConfig `koanf:"file-logging" reload:"hot"` - Persistent conf.PersistentConfig `koanf:"persistent"` - HTTP genericconf.HTTPConfig `koanf:"http"` - WS genericconf.WSConfig `koanf:"ws"` - IPC genericconf.IPCConfig `koanf:"ipc"` - Auth genericconf.AuthRPCConfig `koanf:"auth"` - GraphQL genericconf.GraphQLConfig `koanf:"graphql"` - Metrics bool `koanf:"metrics"` - MetricsServer genericconf.MetricsServerConfig `koanf:"metrics-server"` - PProf bool `koanf:"pprof"` - PprofCfg genericconf.PProf `koanf:"pprof-cfg"` - Init conf.InitConfig `koanf:"init"` - Rpc genericconf.RpcConfig `koanf:"rpc"` + Conf genericconf.ConfConfig `koanf:"conf" reload:"hot"` + Node arbnode.Config `koanf:"node" reload:"hot"` + Execution gethexec.Config `koanf:"execution" reload:"hot"` + Validation valnode.Config `koanf:"validation" reload:"hot"` + ParentChain conf.L1Config `koanf:"parent-chain" reload:"hot"` + Chain conf.L2Config `koanf:"chain"` + LogLevel int `koanf:"log-level" reload:"hot"` + LogType string `koanf:"log-type" reload:"hot"` + FileLogging genericconf.FileLoggingConfig `koanf:"file-logging" reload:"hot"` + Persistent conf.PersistentConfig `koanf:"persistent"` + HTTP genericconf.HTTPConfig `koanf:"http"` + WS genericconf.WSConfig `koanf:"ws"` + IPC genericconf.IPCConfig `koanf:"ipc"` + Auth genericconf.AuthRPCConfig `koanf:"auth"` + GraphQL genericconf.GraphQLConfig `koanf:"graphql"` + Metrics bool `koanf:"metrics"` + MetricsServer genericconf.MetricsServerConfig `koanf:"metrics-server"` + PProf bool `koanf:"pprof"` + PprofCfg genericconf.PProf `koanf:"pprof-cfg"` + Init conf.InitConfig `koanf:"init"` + Rpc genericconf.RpcConfig `koanf:"rpc"` + BlocksReExecutor blocksreexecutor.Config `koanf:"blocks-reexecutor"` } var NodeConfigDefault = NodeConfig{ - Conf: genericconf.ConfConfigDefault, - Node: arbnode.ConfigDefault, - Execution: gethexec.ConfigDefault, - Validation: valnode.DefaultValidationConfig, - ParentChain: conf.L1ConfigDefault, - Chain: conf.L2ConfigDefault, - LogLevel: int(log.LvlInfo), - LogType: "plaintext", - FileLogging: genericconf.DefaultFileLoggingConfig, - Persistent: conf.PersistentConfigDefault, - HTTP: genericconf.HTTPConfigDefault, - WS: genericconf.WSConfigDefault, - IPC: genericconf.IPCConfigDefault, - Auth: genericconf.AuthRPCConfigDefault, - GraphQL: genericconf.GraphQLConfigDefault, - Metrics: false, - MetricsServer: genericconf.MetricsServerConfigDefault, - Init: conf.InitConfigDefault, - Rpc: genericconf.DefaultRpcConfig, - PProf: false, - PprofCfg: genericconf.PProfDefault, + Conf: genericconf.ConfConfigDefault, + Node: arbnode.ConfigDefault, + Execution: gethexec.ConfigDefault, + Validation: valnode.DefaultValidationConfig, + ParentChain: conf.L1ConfigDefault, + Chain: conf.L2ConfigDefault, + LogLevel: int(log.LvlInfo), + LogType: "plaintext", + FileLogging: genericconf.DefaultFileLoggingConfig, + Persistent: conf.PersistentConfigDefault, + HTTP: genericconf.HTTPConfigDefault, + WS: genericconf.WSConfigDefault, + IPC: genericconf.IPCConfigDefault, + Auth: genericconf.AuthRPCConfigDefault, + GraphQL: genericconf.GraphQLConfigDefault, + Metrics: false, + MetricsServer: genericconf.MetricsServerConfigDefault, + Init: conf.InitConfigDefault, + Rpc: genericconf.DefaultRpcConfig, + PProf: false, + PprofCfg: genericconf.PProfDefault, + BlocksReExecutor: blocksreexecutor.DefaultConfig, } func NodeConfigAddOptions(f *flag.FlagSet) { @@ -729,6 +737,7 @@ func NodeConfigAddOptions(f *flag.FlagSet) { conf.InitConfigAddOptions("init", f) genericconf.RpcConfigAddOptions("rpc", f) + blocksreexecutor.ConfigAddOptions("blocks-reexecutor", f) } func (c *NodeConfig) ResolveDirectoryNames() error { @@ -790,6 +799,9 @@ func (c *NodeConfig) Validate() error { if err := c.Execution.Validate(); err != nil { return err } + if err := c.BlocksReExecutor.Validate(); err != nil { + return err + } return c.Persistent.Validate() } diff --git a/system_tests/blocks_reexecutor_test.go b/system_tests/blocks_reexecutor_test.go new file mode 100644 index 000000000..76034570b --- /dev/null +++ b/system_tests/blocks_reexecutor_test.go @@ -0,0 +1,87 @@ +package arbtest + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/params" + "github.com/offchainlabs/nitro/arbnode" + blocksreexecutor "github.com/offchainlabs/nitro/blocks_reexecutor" + "github.com/offchainlabs/nitro/execution/gethexec" +) + +func TestBlocksReExecutorModes(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + execConfig := gethexec.ConfigDefaultTest() + Require(t, execConfig.Validate()) + l2info, stack, chainDb, arbDb, blockchain := createL2BlockChain(t, nil, t.TempDir(), params.ArbitrumDevTestChainConfig(), &execConfig.Caching) + + execConfigFetcher := func() *gethexec.Config { return execConfig } + execNode, err := gethexec.CreateExecutionNode(ctx, stack, chainDb, blockchain, nil, execConfigFetcher) + Require(t, err) + + parentChainID := big.NewInt(1234) + feedErrChan := make(chan error, 10) + node, err := arbnode.CreateNode(ctx, stack, execNode, arbDb, NewFetcherFromConfig(arbnode.ConfigDefaultL2Test()), blockchain.Config(), nil, nil, nil, nil, nil, feedErrChan, parentChainID) + Require(t, err) + err = node.TxStreamer.AddFakeInitMessage() + Require(t, err) + Require(t, node.Start(ctx)) + client := ClientForStack(t, stack) + + l2info.GenerateAccount("User2") + for i := 0; i < 100; i++ { + tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, common.Big1, nil) + err := client.SendTransaction(ctx, tx) + Require(t, err) + receipt, err := EnsureTxSucceeded(ctx, client, tx) + Require(t, err) + if have, want := receipt.BlockNumber.Uint64(), uint64(i)+1; have != want { + Fatal(t, "internal test error - tx got included in unexpected block number, have:", have, "want:", want) + } + } + + success := make(chan struct{}) + + // Reexecute blocks at mode full + go func() { + executorFull := blocksreexecutor.New(&blocksreexecutor.TestConfig, blockchain, feedErrChan) + executorFull.StopWaiter.Start(ctx, executorFull) + executorFull.Impl(ctx) + executorFull.StopAndWait() + success <- struct{}{} + }() + select { + case err := <-feedErrChan: + t.Errorf("error occurred: %v", err) + if node != nil { + node.StopAndWait() + } + t.FailNow() + case <-success: + } + + // Reexecute blocks at mode random + go func() { + c := &blocksreexecutor.TestConfig + c.Mode = "random" + executorRandom := blocksreexecutor.New(c, blockchain, feedErrChan) + executorRandom.StopWaiter.Start(ctx, executorRandom) + executorRandom.Impl(ctx) + executorRandom.StopAndWait() + success <- struct{}{} + }() + select { + case err := <-feedErrChan: + t.Errorf("error occurred: %v", err) + if node != nil { + node.StopAndWait() + } + t.FailNow() + case <-success: + } +} From 1ba8e075fa8b4ca0a096c1a44e72c8ee6b9fd229 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sat, 27 Jan 2024 23:06:59 -0700 Subject: [PATCH 687/775] Move contracts back to previous pin --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index a8e7709bf..cd5093d45 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit a8e7709bfc918f9b8e2888d47f2fd8454779fd11 +Subproject commit cd5093d45ef0353fc5b2718ead70bd7f36e1a92c From f3b06106937970e573690ccf2c4feed6b04cf774 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 28 Jan 2024 11:12:37 -0700 Subject: [PATCH 688/775] Support and test ArbOS 20 --- arbos/arbosState/arbosstate.go | 34 ++++++++++++++++------------ execution/gethexec/tx_pre_checker.go | 5 ++++ go-ethereum | 2 +- system_tests/block_validator_test.go | 1 + system_tests/estimation_test.go | 17 ++++++++++++++ 5 files changed, 43 insertions(+), 16 deletions(-) diff --git a/arbos/arbosState/arbosstate.go b/arbos/arbosState/arbosstate.go index caf44e2a9..7fdb61aba 100644 --- a/arbos/arbosState/arbosstate.go +++ b/arbos/arbosState/arbosstate.go @@ -277,14 +277,13 @@ func (state *ArbosState) UpgradeArbosVersion( } } - switch state.arbosVersion { - case 1: - ensure(state.l1PricingState.SetLastSurplus(common.Big0, 1)) + nextArbosVersion := state.arbosVersion + 1 + switch nextArbosVersion { case 2: + ensure(state.l1PricingState.SetLastSurplus(common.Big0, 1)) + case 3: ensure(state.l1PricingState.SetPerBatchGasCost(0)) ensure(state.l1PricingState.SetAmortizedCostCapBips(math.MaxUint64)) - case 3: - // no state changes needed case 4: // no state changes needed case 5: @@ -296,10 +295,12 @@ func (state *ArbosState) UpgradeArbosVersion( case 8: // no state changes needed case 9: + // no state changes needed + case 10: ensure(state.l1PricingState.SetL1FeesAvailable(stateDB.GetBalance( l1pricing.L1PricerFundsPoolAddress, ))) - case 10: + case 11: // Update the PerBatchGasCost to a more accurate value compared to the old v6 default. ensure(state.l1PricingState.SetPerBatchGasCost(l1pricing.InitialPerBatchGasCostV12)) @@ -316,26 +317,29 @@ func (state *ArbosState) UpgradeArbosVersion( ensure(state.chainOwners.ClearList()) } // ArbOS versions 12 through 19 are left to Orbit chains for custom upgrades. - // TODO: currently you can't get to ArbOS 20 without hitting the default case. - case 19: + case 20: if !chainConfig.DebugMode() { // This upgrade isn't finalized so we only want to support it for testing return fmt.Errorf( "the chain is upgrading to unsupported ArbOS version %v, %w", - state.arbosVersion+1, + nextArbosVersion, ErrFatalNodeOutOfDate, ) } // Update Brotli compression level for fast compression from 0 to 1 ensure(state.SetBrotliCompressionLevel(1)) default: - return fmt.Errorf( - "the chain is upgrading to unsupported ArbOS version %v, %w", - state.arbosVersion+1, - ErrFatalNodeOutOfDate, - ) + if nextArbosVersion >= 12 && state.arbosVersion < 20 { + // ArbOS versions 12 through 19 are left to Orbit chains for custom upgrades. + } else { + return fmt.Errorf( + "the chain is upgrading to unsupported ArbOS version %v, %w", + nextArbosVersion, + ErrFatalNodeOutOfDate, + ) + } } - state.arbosVersion++ + state.arbosVersion = nextArbosVersion } if firstTime && upgradeTo >= 6 { diff --git a/execution/gethexec/tx_pre_checker.go b/execution/gethexec/tx_pre_checker.go index 51ba88fec..cff8b04d3 100644 --- a/execution/gethexec/tx_pre_checker.go +++ b/execution/gethexec/tx_pre_checker.go @@ -116,6 +116,11 @@ func PreCheckTx(bc *core.BlockChain, chainConfig *params.ChainConfig, header *ty if tx.Gas() < params.TxGas { return core.ErrIntrinsicGas } + if tx.Type() >= types.ArbitrumDepositTxType || tx.Type() == types.BlobTxType { + // Should be unreachable for Arbitrum types due to UnmarshalBinary not accepting Arbitrum internal txs + // and we want to disallow BlobTxType since Arbitrum doesn't support EIP-4844 txs yet. + return types.ErrTxTypeNotSupported + } sender, err := types.Sender(types.MakeSigner(chainConfig, header.Number, header.Time), tx) if err != nil { return err diff --git a/go-ethereum b/go-ethereum index 214d1c1c9..1acd9c64a 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 214d1c1c9b6ef7830dfb22c3bba7563b89d18960 +Subproject commit 1acd9c64ac5804729475ef60aa578b4ec52fa0e6 diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index e2e4227bf..1fcf2bab3 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -93,6 +93,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops contractCode = append(contractCode, byte(vm.PUSH0)) contractCode = append(contractCode, byte(vm.CODECOPY)) contractCode = append(contractCode, byte(vm.PUSH0)) + contractCode = append(contractCode, byte(vm.BLOBHASH)) contractCode = append(contractCode, byte(vm.RETURN)) basefee := builder.L2.GetBaseFee(t) var err error diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index eda7fb449..6f47c14f1 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/solgen/go/mocksgen" @@ -180,6 +181,22 @@ func TestDifficultyForArbOSTen(t *testing.T) { } } +func TestBlobBasefeeReverts(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() + + _, err := builder.L2.Client.CallContract(ctx, ethereum.CallMsg{ + Data: []byte{byte(vm.BLOBBASEFEE)}, + }, nil) + if err == nil { + t.Error("Expected BLOBBASEFEE to revert") + } +} + func TestComponentEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() From fe0d6231fc6196cbb1f048fe1e7c0f73ae2095d2 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 28 Jan 2024 11:38:39 -0700 Subject: [PATCH 689/775] Add missing L1 pricing getters to ArbGasInfo in ArbOS 20 --- arbos/l1pricing/l1pricing.go | 8 -------- contracts | 2 +- precompiles/ArbGasInfo.go | 24 ++++++++++++++++++++++-- precompiles/precompile.go | 5 +++++ 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/arbos/l1pricing/l1pricing.go b/arbos/l1pricing/l1pricing.go index 27ecae8b8..f2312c46d 100644 --- a/arbos/l1pricing/l1pricing.go +++ b/arbos/l1pricing/l1pricing.go @@ -146,10 +146,6 @@ func (ps *L1PricingState) SetPayRewardsTo(addr common.Address) error { return ps.payRewardsTo.Set(addr) } -func (ps *L1PricingState) GetRewardsRecepient() (common.Address, error) { - return ps.payRewardsTo.Get() -} - func (ps *L1PricingState) EquilibrationUnits() (*big.Int, error) { return ps.equilibrationUnits.Get() } @@ -174,10 +170,6 @@ func (ps *L1PricingState) SetPerUnitReward(weiPerUnit uint64) error { return ps.perUnitReward.Set(weiPerUnit) } -func (ps *L1PricingState) GetRewardsRate() (uint64, error) { - return ps.perUnitReward.Get() -} - func (ps *L1PricingState) LastUpdateTime() (uint64, error) { return ps.lastUpdateTime.Get() } diff --git a/contracts b/contracts index cd5093d45..7b84be56e 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit cd5093d45ef0353fc5b2718ead70bd7f36e1a92c +Subproject commit 7b84be56ec5352aaeb85c58fea7f50725e1927d9 diff --git a/precompiles/ArbGasInfo.go b/precompiles/ArbGasInfo.go index 378d48c78..cda5350a4 100644 --- a/precompiles/ArbGasInfo.go +++ b/precompiles/ArbGasInfo.go @@ -164,12 +164,12 @@ func (con ArbGasInfo) GetL1BaseFeeEstimateInertia(c ctx, evm mech) (uint64, erro // GetL1RewardRate gets the L1 pricer reward rate func (con ArbGasInfo) GetL1RewardRate(c ctx, evm mech) (uint64, error) { - return c.State.L1PricingState().GetRewardsRate() + return c.State.L1PricingState().PerUnitReward() } // GetL1RewardRecipient gets the L1 pricer reward recipient func (con ArbGasInfo) GetL1RewardRecipient(c ctx, evm mech) (common.Address, error) { - return c.State.L1PricingState().GetRewardsRecepient() + return c.State.L1PricingState().PayRewardsTo() } // GetL1GasPriceEstimate gets the current estimate of the L1 basefee @@ -244,3 +244,23 @@ func (con ArbGasInfo) GetAmortizedCostCapBips(c ctx, evm mech) (uint64, error) { func (con ArbGasInfo) GetL1FeesAvailable(c ctx, evm mech) (huge, error) { return c.State.L1PricingState().L1FeesAvailable() } + +func (con ArbGasInfo) GetL1PricingEquilibrationUnits(c ctx, evm mech) (*big.Int, error) { + return c.State.L1PricingState().EquilibrationUnits() +} + +func (con ArbGasInfo) GetLastL1PricingUpdateTime(c ctx, evm mech) (uint64, error) { + return c.State.L1PricingState().LastUpdateTime() +} + +func (con ArbGasInfo) GetL1PricingFundsDueForRewards(c ctx, evm mech) (*big.Int, error) { + return c.State.L1PricingState().FundsDueForRewards() +} + +func (con ArbGasInfo) GetL1PricingUnitsSinceUpdate(c ctx, evm mech) (uint64, error) { + return c.State.L1PricingState().UnitsSinceUpdate() +} + +func (con ArbGasInfo) GetLastL1PricingSurplus(c ctx, evm mech) (*big.Int, error) { + return c.State.L1PricingState().LastSurplus() +} diff --git a/precompiles/precompile.go b/precompiles/precompile.go index 330eb9a2e..5d2ecce74 100644 --- a/precompiles/precompile.go +++ b/precompiles/precompile.go @@ -538,6 +538,11 @@ func Precompiles() map[addr]ArbosPrecompile { ArbGasInfo.methodsByName["GetL1FeesAvailable"].arbosVersion = 10 ArbGasInfo.methodsByName["GetL1RewardRate"].arbosVersion = 11 ArbGasInfo.methodsByName["GetL1RewardRecipient"].arbosVersion = 11 + ArbGasInfo.methodsByName["GetL1PricingEquilibrationUnits"].arbosVersion = 20 + ArbGasInfo.methodsByName["GetLastL1PricingUpdateTime"].arbosVersion = 20 + ArbGasInfo.methodsByName["GetL1PricingFundsDueForRewards"].arbosVersion = 20 + ArbGasInfo.methodsByName["GetL1PricingUnitsSinceUpdate"].arbosVersion = 20 + ArbGasInfo.methodsByName["GetLastL1PricingSurplus"].arbosVersion = 20 insert(MakePrecompile(templates.ArbAggregatorMetaData, &ArbAggregator{Address: hex("6d")})) insert(MakePrecompile(templates.ArbStatisticsMetaData, &ArbStatistics{Address: hex("6f")})) From b7d26784af334b71be7567cc2e3682ed732898d8 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 28 Jan 2024 11:41:45 -0700 Subject: [PATCH 690/775] Disable EIP-4844 batch posting by default for now --- arbnode/batch_poster.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 65ef76e0a..e3af0b2af 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -211,7 +211,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ DASRetentionPeriod: time.Hour * 24 * 15, GasRefunderAddress: "", ExtraBatchGas: 50_000, - Post4844Blobs: true, + Post4844Blobs: false, ForcePost4844Blobs: false, DataPoster: dataposter.DefaultDataPosterConfig, ParentChainWallet: DefaultBatchPosterL1WalletConfig, From a80fa288679b0f4145e477ffd54ef2af34ad0f99 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 28 Jan 2024 16:53:47 -0700 Subject: [PATCH 691/775] Add ArbOS precompile method to get scheduled upgrade --- contracts | 2 +- precompiles/ArbOwnerPublic.go | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/contracts b/contracts index 7b84be56e..6e61fdb47 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 7b84be56ec5352aaeb85c58fea7f50725e1927d9 +Subproject commit 6e61fdb475bb4b38870e40827dd37627afc4bacd diff --git a/precompiles/ArbOwnerPublic.go b/precompiles/ArbOwnerPublic.go index 4064f41be..451e18e1c 100644 --- a/precompiles/ArbOwnerPublic.go +++ b/precompiles/ArbOwnerPublic.go @@ -52,3 +52,16 @@ func (con ArbOwnerPublic) GetInfraFeeAccount(c ctx, evm mech) (addr, error) { func (con ArbOwnerPublic) GetBrotliCompressionLevel(c ctx, evm mech) (uint64, error) { return c.State.BrotliCompressionLevel() } + +// GetScheduledUpgrade gets the next scheduled ArbOS version upgrade and its activation timestamp. +// Returns (0, 0, nil) if no ArbOS upgrade is scheduled. +func (con ArbOwnerPublic) GetScheduledUpgrade(c ctx, evm mech) (uint64, uint64, error) { + version, timestamp, err := c.State.GetScheduledUpgrade() + if err != nil { + return 0, 0, err + } + if c.State.ArbOSVersion() >= version { + return 0, 0, nil + } + return version, timestamp, nil +} From 76924e06efc3a4292b36dcf489a9a86d7dbd44b9 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 28 Jan 2024 16:58:19 -0700 Subject: [PATCH 692/775] Bump contracts pin --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 6e61fdb47..9a6bfad23 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 6e61fdb475bb4b38870e40827dd37627afc4bacd +Subproject commit 9a6bfad2363322099d399698751551ff044c7a72 From 4db1014c0f0e5854177b4dc7c07e5c8b6380d870 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 28 Jan 2024 17:06:51 -0700 Subject: [PATCH 693/775] Add test of scheduling upgrade and getting it --- system_tests/precompile_test.go | 51 +++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/system_tests/precompile_test.go b/system_tests/precompile_test.go index 10db09275..7040a956c 100644 --- a/system_tests/precompile_test.go +++ b/system_tests/precompile_test.go @@ -120,3 +120,54 @@ func TestPrecompileErrorGasLeft(t *testing.T) { Require(t, err) assertNotAllGasConsumed(common.HexToAddress("0xff"), arbDebug.Methods["legacyError"].ID) } + +func TestScheduleArbosUpgrade(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() + + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + + arbOwnerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("0x6b"), builder.L2.Client) + Require(t, err, "could not bind ArbOwner contract") + + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), builder.L2.Client) + Require(t, err, "could not bind ArbOwner contract") + + callOpts := &bind.CallOpts{Context: ctx} + scheduled, err := arbOwnerPublic.GetScheduledUpgrade(callOpts) + Require(t, err, "failed to call GetScheduledUpgrade before scheduling upgrade") + if scheduled.ArbosVersion != 0 || scheduled.ScheduledForTimestamp != 0 { + t.Errorf("expected no upgrade to be scheduled, got version %v timestamp %v", scheduled.ArbosVersion, scheduled.ScheduledForTimestamp) + } + + // Schedule a noop upgrade, which should test GetScheduledUpgrade in the same way an already completed upgrade would. + tx, err := arbOwner.ScheduleArbOSUpgrade(&auth, 1, 1) + Require(t, err) + _, err = builder.L2.EnsureTxSucceeded(tx) + Require(t, err) + + scheduled, err = arbOwnerPublic.GetScheduledUpgrade(callOpts) + Require(t, err, "failed to call GetScheduledUpgrade after scheduling noop upgrade") + if scheduled.ArbosVersion != 0 || scheduled.ScheduledForTimestamp != 0 { + t.Errorf("expected completed scheduled upgrade to be ignored, got version %v timestamp %v", scheduled.ArbosVersion, scheduled.ScheduledForTimestamp) + } + + // TODO: Once we have an ArbOS 30, test a real upgrade with it + // We can't test 11 -> 20 because 11 doesn't have the GetScheduledUpgrade method we want to test + var testVersion uint64 = 100 + var testTimestamp uint64 = 1 >> 62 + tx, err = arbOwner.ScheduleArbOSUpgrade(&auth, 100, 1>>62) + Require(t, err) + _, err = builder.L2.EnsureTxSucceeded(tx) + Require(t, err) + + scheduled, err = arbOwnerPublic.GetScheduledUpgrade(callOpts) + Require(t, err, "failed to call GetScheduledUpgrade after scheduling upgrade") + if scheduled.ArbosVersion != testVersion || scheduled.ScheduledForTimestamp != testTimestamp { + t.Errorf("expected upgrade to be scheduled for version %v timestamp %v, got version %v timestamp %v", testVersion, testTimestamp, scheduled.ArbosVersion, scheduled.ScheduledForTimestamp) + } +} From 7bc141282c4d81a2b7d41723a1f39046e9da2e39 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Sun, 28 Jan 2024 17:10:04 -0700 Subject: [PATCH 694/775] Fix testTimestamp --- system_tests/precompile_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system_tests/precompile_test.go b/system_tests/precompile_test.go index 7040a956c..e0a9c2ce7 100644 --- a/system_tests/precompile_test.go +++ b/system_tests/precompile_test.go @@ -159,8 +159,8 @@ func TestScheduleArbosUpgrade(t *testing.T) { // TODO: Once we have an ArbOS 30, test a real upgrade with it // We can't test 11 -> 20 because 11 doesn't have the GetScheduledUpgrade method we want to test var testVersion uint64 = 100 - var testTimestamp uint64 = 1 >> 62 - tx, err = arbOwner.ScheduleArbOSUpgrade(&auth, 100, 1>>62) + var testTimestamp uint64 = 1 << 62 + tx, err = arbOwner.ScheduleArbOSUpgrade(&auth, 100, 1<<62) Require(t, err) _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) From a4cbf3b9fab7f22311d4274fc8992d49162f3567 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 29 Jan 2024 11:42:08 +0100 Subject: [PATCH 695/775] Implement linter for checking 1>>x expressions --- Makefile | 1 + linter/koanf/koanf.go | 4 -- linter/koanf/koanf_test.go | 2 +- linter/pointercheck/pointer.go | 4 -- linter/pointercheck/pointer_test.go | 2 +- linter/rightshift/rightshift.go | 76 ++++++++++++++++++++ linter/rightshift/rightshift_test.go | 36 ++++++++++ linter/structinit/structinit.go | 4 -- linter/structinit/structinit_test.go | 2 +- linter/testdata/src/rightshift/rightshift.go | 14 ++++ 10 files changed, 130 insertions(+), 15 deletions(-) create mode 100644 linter/rightshift/rightshift.go create mode 100644 linter/rightshift/rightshift_test.go create mode 100644 linter/testdata/src/rightshift/rightshift.go diff --git a/Makefile b/Makefile index 8b149bc0e..956ab0c35 100644 --- a/Makefile +++ b/Makefile @@ -313,6 +313,7 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make go run ./linter/koanf ./... go run ./linter/pointercheck ./... + go run ./linter/rightshift ./... golangci-lint run --fix yarn --cwd contracts solhint @touch $@ diff --git a/linter/koanf/koanf.go b/linter/koanf/koanf.go index d6780760e..f09fdd3d0 100644 --- a/linter/koanf/koanf.go +++ b/linter/koanf/koanf.go @@ -18,10 +18,6 @@ var ( errIncorrectFlag = errors.New("mismatching flag initialization") ) -func New(conf any) ([]*analysis.Analyzer, error) { - return []*analysis.Analyzer{Analyzer}, nil -} - var Analyzer = &analysis.Analyzer{ Name: "koanfcheck", Doc: "check for koanf misconfigurations", diff --git a/linter/koanf/koanf_test.go b/linter/koanf/koanf_test.go index 064ae533c..0840ae521 100644 --- a/linter/koanf/koanf_test.go +++ b/linter/koanf/koanf_test.go @@ -20,7 +20,7 @@ func testData(t *testing.T) string { t.Helper() wd, err := os.Getwd() if err != nil { - t.Fatalf("Failed to get wd: %s", err) + t.Fatalf("Failed to get working directory: %v", err) } return filepath.Join(filepath.Dir(wd), "testdata") } diff --git a/linter/pointercheck/pointer.go b/linter/pointercheck/pointer.go index 6500b0122..4da2d8cc2 100644 --- a/linter/pointercheck/pointer.go +++ b/linter/pointercheck/pointer.go @@ -11,10 +11,6 @@ import ( "golang.org/x/tools/go/analysis/singlechecker" ) -func New(conf any) ([]*analysis.Analyzer, error) { - return []*analysis.Analyzer{Analyzer}, nil -} - var Analyzer = &analysis.Analyzer{ Name: "pointercheck", Doc: "check for pointer comparison", diff --git a/linter/pointercheck/pointer_test.go b/linter/pointercheck/pointer_test.go index 290e3826d..47d5c6301 100644 --- a/linter/pointercheck/pointer_test.go +++ b/linter/pointercheck/pointer_test.go @@ -11,7 +11,7 @@ import ( func TestAll(t *testing.T) { wd, err := os.Getwd() if err != nil { - t.Fatalf("Failed to get wd: %s", err) + t.Fatalf("Failed to get working directory: %v", err) } testdata := filepath.Join(filepath.Dir(wd), "testdata") res := analysistest.Run(t, testdata, analyzerForTests, "pointercheck") diff --git a/linter/rightshift/rightshift.go b/linter/rightshift/rightshift.go new file mode 100644 index 000000000..f50d8a25a --- /dev/null +++ b/linter/rightshift/rightshift.go @@ -0,0 +1,76 @@ +package main + +import ( + "go/ast" + "go/token" + "reflect" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/singlechecker" +) + +var Analyzer = &analysis.Analyzer{ + Name: "rightshift", + Doc: "check for 1 >> x operation", + Run: func(p *analysis.Pass) (interface{}, error) { return run(false, p) }, + ResultType: reflect.TypeOf(Result{}), +} + +var analyzerForTests = &analysis.Analyzer{ + Name: "testrightshift", + Doc: "check for pointer comparison (for tests)", + Run: func(p *analysis.Pass) (interface{}, error) { return run(true, p) }, + ResultType: reflect.TypeOf(Result{}), +} + +// rightShiftError indicates the position of pointer comparison. +type rightShiftError struct { + Pos token.Position + Message string +} + +// Result is returned from the checkStruct function, and holds all rightshift +// operations. +type Result struct { + Errors []rightShiftError +} + +func run(dryRun bool, pass *analysis.Pass) (interface{}, error) { + var ret Result + for _, f := range pass.Files { + ast.Inspect(f, func(node ast.Node) bool { + be, ok := node.(*ast.BinaryExpr) + if !ok { + return true + } + // Check if the expression is '1 >> x'. + if be.Op == token.SHR && isOne(be.X) { + err := rightShiftError{ + Pos: pass.Fset.Position(be.Pos()), + Message: "found rightshift ('1 >> x') expression, did you mean '1 << x' ?", + } + ret.Errors = append(ret.Errors, err) + if !dryRun { + pass.Report(analysis.Diagnostic{ + Pos: pass.Fset.File(f.Pos()).Pos(err.Pos.Offset), + Message: err.Message, + Category: "pointercheck", + }) + } + } + return true + }, + ) + } + return ret, nil +} + +// isOne checks if the expression is a constant 1. +func isOne(expr ast.Expr) bool { + bl, ok := expr.(*ast.BasicLit) + return ok && bl.Kind == token.INT && bl.Value == "1" +} + +func main() { + singlechecker.Main(Analyzer) +} diff --git a/linter/rightshift/rightshift_test.go b/linter/rightshift/rightshift_test.go new file mode 100644 index 000000000..41555c068 --- /dev/null +++ b/linter/rightshift/rightshift_test.go @@ -0,0 +1,36 @@ +package main + +import ( + "os" + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "golang.org/x/tools/go/analysis/analysistest" +) + +func TestAll(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get working directory: %v", err) + } + testdata := filepath.Join(filepath.Dir(wd), "testdata") + res := analysistest.Run(t, testdata, analyzerForTests, "rightshift") + want := []int{6, 11, 12} + got := erroLines(res) + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("analysistest.Ru() unexpected diff in error lines:\n%s\n", diff) + } +} + +func erroLines(errs []*analysistest.Result) []int { + var ret []int + for _, e := range errs { + if r, ok := e.Result.(Result); ok { + for _, err := range r.Errors { + ret = append(ret, err.Pos.Line) + } + } + } + return ret +} diff --git a/linter/structinit/structinit.go b/linter/structinit/structinit.go index e4e65bc3f..31baf1c90 100644 --- a/linter/structinit/structinit.go +++ b/linter/structinit/structinit.go @@ -16,10 +16,6 @@ import ( // Note: comment should be directly line above the struct definition. const linterTip = "// lint:require-exhaustive-initialization" -func New(conf any) ([]*analysis.Analyzer, error) { - return []*analysis.Analyzer{Analyzer}, nil -} - // Analyzer implements struct analyzer for structs that are annotated with // `linterTip`, it checks that every instantiation initializes all the fields. var Analyzer = &analysis.Analyzer{ diff --git a/linter/structinit/structinit_test.go b/linter/structinit/structinit_test.go index db3676e18..df8588a58 100644 --- a/linter/structinit/structinit_test.go +++ b/linter/structinit/structinit_test.go @@ -12,7 +12,7 @@ func testData(t *testing.T) string { t.Helper() wd, err := os.Getwd() if err != nil { - t.Fatalf("Failed to get wd: %s", err) + t.Fatalf("Failed to get working directory: %v", err) } return filepath.Join(filepath.Dir(wd), "testdata") } diff --git a/linter/testdata/src/rightshift/rightshift.go b/linter/testdata/src/rightshift/rightshift.go new file mode 100644 index 000000000..3ad6d9598 --- /dev/null +++ b/linter/testdata/src/rightshift/rightshift.go @@ -0,0 +1,14 @@ +package rightshift + +import "fmt" + +func doThing(v int) int { + return 1 >> v // Error: Ln: 6 +} + +func calc() { + val := 10 + fmt.Printf("%v", 1>>val) // Error: Ln 11 + _ = doThing(1 >> val) // Error: Ln 12 + fmt.Printf("%v", 1< Date: Mon, 29 Jan 2024 21:41:07 +0000 Subject: [PATCH 696/775] add state recovery option --- cmd/conf/init.go | 59 +++++++++--------- cmd/nitro/init.go | 8 +++ cmd/staterecovery/staterecovery.go | 83 +++++++++++++++++++++++++ execution/gethexec/blockchain.go | 1 + system_tests/staterecovery_test.go | 99 ++++++++++++++++++++++++++++++ 5 files changed, 222 insertions(+), 28 deletions(-) create mode 100644 cmd/staterecovery/staterecovery.go create mode 100644 system_tests/staterecovery_test.go diff --git a/cmd/conf/init.go b/cmd/conf/init.go index bebf1955b..313e5bbee 100644 --- a/cmd/conf/init.go +++ b/cmd/conf/init.go @@ -7,37 +7,39 @@ import ( ) type InitConfig struct { - Force bool `koanf:"force"` - Url string `koanf:"url"` - DownloadPath string `koanf:"download-path"` - DownloadPoll time.Duration `koanf:"download-poll"` - DevInit bool `koanf:"dev-init"` - DevInitAddress string `koanf:"dev-init-address"` - DevInitBlockNum uint64 `koanf:"dev-init-blocknum"` - Empty bool `koanf:"empty"` - AccountsPerSync uint `koanf:"accounts-per-sync"` - ImportFile string `koanf:"import-file"` - ThenQuit bool `koanf:"then-quit"` - Prune string `koanf:"prune"` - PruneBloomSize uint64 `koanf:"prune-bloom-size"` - ResetToMessage int64 `koanf:"reset-to-message"` + Force bool `koanf:"force"` + Url string `koanf:"url"` + DownloadPath string `koanf:"download-path"` + DownloadPoll time.Duration `koanf:"download-poll"` + DevInit bool `koanf:"dev-init"` + DevInitAddress string `koanf:"dev-init-address"` + DevInitBlockNum uint64 `koanf:"dev-init-blocknum"` + Empty bool `koanf:"empty"` + AccountsPerSync uint `koanf:"accounts-per-sync"` + ImportFile string `koanf:"import-file"` + ThenQuit bool `koanf:"then-quit"` + Prune string `koanf:"prune"` + PruneBloomSize uint64 `koanf:"prune-bloom-size"` + ResetToMessage int64 `koanf:"reset-to-message"` + RecreateMissingState bool `koanf:"recreate-missing-state"` } var InitConfigDefault = InitConfig{ - Force: false, - Url: "", - DownloadPath: "/tmp/", - DownloadPoll: time.Minute, - DevInit: false, - DevInitAddress: "", - DevInitBlockNum: 0, - Empty: false, - ImportFile: "", - AccountsPerSync: 100000, - ThenQuit: false, - Prune: "", - PruneBloomSize: 2048, - ResetToMessage: -1, + Force: false, + Url: "", + DownloadPath: "/tmp/", + DownloadPoll: time.Minute, + DevInit: false, + DevInitAddress: "", + DevInitBlockNum: 0, + Empty: false, + ImportFile: "", + AccountsPerSync: 100000, + ThenQuit: false, + Prune: "", + PruneBloomSize: 2048, + ResetToMessage: -1, + RecreateMissingState: false, } func InitConfigAddOptions(prefix string, f *pflag.FlagSet) { @@ -55,4 +57,5 @@ func InitConfigAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".prune", InitConfigDefault.Prune, "pruning for a given use: \"full\" for full nodes serving RPC requests, or \"validator\" for validators") 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.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.Bool(prefix+".recreate-missing-state", InitConfigDefault.RecreateMissingState, "if true: in case database exists and force=false, missing state will be recreated and committed to disk") } diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 4cf5dcda0..bab15b615 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -34,6 +34,7 @@ import ( "github.com/offchainlabs/nitro/cmd/conf" "github.com/offchainlabs/nitro/cmd/ipfshelper" "github.com/offchainlabs/nitro/cmd/pruning" + "github.com/offchainlabs/nitro/cmd/staterecovery" "github.com/offchainlabs/nitro/cmd/util" "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/statetransfer" @@ -183,6 +184,13 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if err != nil { return chainDb, l2BlockChain, err } + if config.Init.RecreateMissingState { + err = staterecovery.RecreateMissingStates(chainDb, l2BlockChain, cachingConfig) + if err != nil { + return chainDb, l2BlockChain, err + } + } + return chainDb, l2BlockChain, nil } readOnlyDb.Close() diff --git a/cmd/staterecovery/staterecovery.go b/cmd/staterecovery/staterecovery.go new file mode 100644 index 000000000..0f2eba5c6 --- /dev/null +++ b/cmd/staterecovery/staterecovery.go @@ -0,0 +1,83 @@ +package staterecovery + +import ( + "fmt" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/triedb/hashdb" +) + +func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheConfig *core.CacheConfig) error { + log.Info("Recreating missing states...") + start := time.Now() + current := bc.Genesis().NumberU64() + 1 + last := bc.CurrentBlock().Number.Uint64() + + previousBlock := bc.GetBlockByNumber(current - 1) + if previousBlock == nil { + return fmt.Errorf("genesis block is missing") + } + hashConfig := *hashdb.Defaults + hashConfig.CleanCacheSize = cacheConfig.TrieCleanLimit + trieConfig := &trie.Config{ + Preimages: false, + HashDB: &hashConfig, + } + database := state.NewDatabaseWithConfig(chainDb, trieConfig) + defer database.TrieDB().Close() + previousState, err := state.New(previousBlock.Root(), database, nil) + if err != nil { + return fmt.Errorf("genesis state is missing: %w", err) + } + database.TrieDB().Reference(previousBlock.Root(), common.Hash{}) + logged := time.Now() + recreated := 0 + for current <= last { + if time.Since(logged) > 1*time.Minute { + log.Info("Recreating missing states", "block", current, "target", last, "remaining", last-current, "elapsed", time.Since(start), "recreated", recreated) + logged = time.Now() + } + currentBlock := bc.GetBlockByNumber(current) + if currentBlock == nil { + return fmt.Errorf("missing block %d", current) + } + currentState, err := state.New(currentBlock.Root(), database, nil) + if err != nil { + _, _, _, err := bc.Processor().Process(currentBlock, previousState, vm.Config{}) + if err != nil { + return fmt.Errorf("processing block %d failed: %v", current, err) + } + root, err := previousState.Commit(current, bc.Config().IsEIP158(currentBlock.Number())) + if err != nil { + return fmt.Errorf("StateDB commit failed, number %d root %v: %w", current, currentBlock.Root().Hex(), err) + } + if root.Cmp(currentBlock.Root()) != 0 { + return fmt.Errorf("reached different state root after processing block %d, want %v, have %v", current, currentBlock.Root(), root) + } + // commit to disk + err = database.TrieDB().Commit(root, false) // TODO report = true, do we want this many logs? + if err != nil { + return fmt.Errorf("TrieDB commit failed, number %d root %v: %w", current, root, err) + } + currentState, err = state.New(currentBlock.Root(), database, nil) + if err != nil { + return fmt.Errorf("state reset after block %d failed: %v", current, err) + } + database.TrieDB().Reference(currentBlock.Root(), common.Hash{}) + database.TrieDB().Dereference(previousBlock.Root()) + recreated++ + } + current++ + previousState = currentState + previousBlock = currentBlock + } + log.Info("Finished recreating missing states", "elapsed", time.Since(start), "recreated", recreated) + return nil +} diff --git a/execution/gethexec/blockchain.go b/execution/gethexec/blockchain.go index a85224b63..2a20c3da2 100644 --- a/execution/gethexec/blockchain.go +++ b/execution/gethexec/blockchain.go @@ -67,6 +67,7 @@ var DefaultCachingConfig = CachingConfig{ MaxAmountOfGasToSkipStateSaving: 0, } +// TODO remove stack from parameters as it is no longer needed here func DefaultCacheConfigFor(stack *node.Node, cachingConfig *CachingConfig) *core.CacheConfig { baseConf := ethconfig.Defaults if cachingConfig.Archive { diff --git a/system_tests/staterecovery_test.go b/system_tests/staterecovery_test.go new file mode 100644 index 000000000..561e88915 --- /dev/null +++ b/system_tests/staterecovery_test.go @@ -0,0 +1,99 @@ +package arbtest + +import ( + "context" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/trie" + "github.com/offchainlabs/nitro/cmd/staterecovery" + "github.com/offchainlabs/nitro/execution/gethexec" +) + +func TestRectreateMissingStates(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 16 + _ = builder.Build(t) + l2cleanupDone := false + defer func() { + if !l2cleanupDone { + builder.L2.cleanup() + } + builder.L1.cleanup() + }() + builder.L2Info.GenerateAccount("User2") + var txs []*types.Transaction + for i := uint64(0); i < 200; i++ { + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) + txs = append(txs, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) + Require(t, err) + } + for _, tx := range txs { + _, err := builder.L2.EnsureTxSucceeded(tx) + Require(t, err) + } + lastBlock, err := builder.L2.Client.BlockNumber(ctx) + Require(t, err) + l2cleanupDone = true + builder.L2.cleanup() + t.Log("stopped l2 node") + func() { + stack, err := node.New(builder.l2StackConfig) + Require(t, err) + defer stack.Close() + chainDb, err := stack.OpenDatabase("chaindb", 0, 0, "", false) + Require(t, err) + defer chainDb.Close() + cacheConfig := gethexec.DefaultCacheConfigFor(stack, &gethexec.DefaultCachingConfig) + bc, err := gethexec.GetBlockChain(chainDb, cacheConfig, builder.chainConfig, builder.execConfig.TxLookupLimit) + Require(t, err) + err = staterecovery.RecreateMissingStates(chainDb, bc, cacheConfig) + Require(t, err) + }() + + testClient, cleanup := builder.Build2ndNode(t, &SecondNodeParams{stackConfig: builder.l2StackConfig}) + defer cleanup() + + currentBlock := uint64(0) + // wait for the chain to catch up + for currentBlock < lastBlock { + currentBlock, err = testClient.Client.BlockNumber(ctx) + Require(t, err) + time.Sleep(20 * time.Millisecond) + } + + currentBlock, err = testClient.Client.BlockNumber(ctx) + Require(t, err) + bc := testClient.ExecNode.Backend.ArbInterface().BlockChain() + triedb := bc.StateCache().TrieDB() + var start uint64 + if currentBlock+1 >= builder.execConfig.Caching.BlockCount { + start = currentBlock + 1 - builder.execConfig.Caching.BlockCount + } else { + start = 0 + } + for i := start; i <= currentBlock; i++ { + header := bc.GetHeaderByNumber(i) + _, err := bc.StateAt(header.Root) + Require(t, err) + tr, err := trie.New(trie.TrieID(header.Root), triedb) + Require(t, err) + it, err := tr.NodeIterator(nil) + Require(t, err) + for it.Next(true) { + } + Require(t, it.Error()) + } + + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) + err = testClient.Client.SendTransaction(ctx, tx) + Require(t, err) + _, err = testClient.EnsureTxSucceeded(tx) + Require(t, err) +} From 333e46fa5513e3996856b11eae74be4a09e08dd0 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 29 Jan 2024 21:47:14 +0000 Subject: [PATCH 697/775] fix referencing --- cmd/nitro/init.go | 2 +- cmd/staterecovery/staterecovery.go | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index bab15b615..c7d850ac7 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -185,7 +185,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo return chainDb, l2BlockChain, err } if config.Init.RecreateMissingState { - err = staterecovery.RecreateMissingStates(chainDb, l2BlockChain, cachingConfig) + err = staterecovery.RecreateMissingStates(chainDb, l2BlockChain, cacheConfig) if err != nil { return chainDb, l2BlockChain, err } diff --git a/cmd/staterecovery/staterecovery.go b/cmd/staterecovery/staterecovery.go index 0f2eba5c6..a2918a81f 100644 --- a/cmd/staterecovery/staterecovery.go +++ b/cmd/staterecovery/staterecovery.go @@ -36,7 +36,7 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon if err != nil { return fmt.Errorf("genesis state is missing: %w", err) } - database.TrieDB().Reference(previousBlock.Root(), common.Hash{}) + _ = database.TrieDB().Reference(previousBlock.Root(), common.Hash{}) logged := time.Now() recreated := 0 for current <= last { @@ -52,11 +52,11 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon if err != nil { _, _, _, err := bc.Processor().Process(currentBlock, previousState, vm.Config{}) if err != nil { - return fmt.Errorf("processing block %d failed: %v", current, err) + return fmt.Errorf("processing block %d failed: %w", current, err) } root, err := previousState.Commit(current, bc.Config().IsEIP158(currentBlock.Number())) if err != nil { - return fmt.Errorf("StateDB commit failed, number %d root %v: %w", current, currentBlock.Root().Hex(), err) + return fmt.Errorf("StateDB commit failed, number %d root %v: %w", current, currentBlock.Root(), err) } if root.Cmp(currentBlock.Root()) != 0 { return fmt.Errorf("reached different state root after processing block %d, want %v, have %v", current, currentBlock.Root(), root) @@ -68,16 +68,17 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon } currentState, err = state.New(currentBlock.Root(), database, nil) if err != nil { - return fmt.Errorf("state reset after block %d failed: %v", current, err) + return fmt.Errorf("state reset after block %d failed: %w", current, err) } - database.TrieDB().Reference(currentBlock.Root(), common.Hash{}) - database.TrieDB().Dereference(previousBlock.Root()) recreated++ } + _ = database.TrieDB().Reference(currentBlock.Root(), common.Hash{}) + _ = database.TrieDB().Dereference(previousBlock.Root()) current++ - previousState = currentState previousBlock = currentBlock + previousState = currentState } + _ = database.TrieDB().Dereference(previousBlock.Root()) log.Info("Finished recreating missing states", "elapsed", time.Since(start), "recreated", recreated) return nil } From 5a54d22a7e80023c347b3ebfdb9a80b28d67e934 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 29 Jan 2024 15:36:56 -0700 Subject: [PATCH 698/775] Prevent a 4844 header from being used inside Anytrust data --- arbstate/inbox.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arbstate/inbox.go b/arbstate/inbox.go index cf8f61e97..fcb1c1ebc 100644 --- a/arbstate/inbox.go +++ b/arbstate/inbox.go @@ -75,6 +75,9 @@ func parseSequencerMessage(ctx context.Context, batchNum uint64, batchBlockHash } payload := data[40:] + // Stage 1: Extract the payload from any data availability header. + // It's important that multiple DAS strategies can't both be invoked in the same batch, + // as these headers are validated by the sequencer inbox and not other DASs. if len(payload) > 0 && IsDASMessageHeaderByte(payload[0]) { if dasReader == nil { log.Error("No DAS Reader configured, but sequencer message found with DAS header") @@ -88,9 +91,7 @@ func parseSequencerMessage(ctx context.Context, batchNum uint64, batchBlockHash return parsedMsg, nil } } - } - - if len(payload) > 0 && IsBlobHashesHeaderByte(payload[0]) { + } else if len(payload) > 0 && IsBlobHashesHeaderByte(payload[0]) { blobHashes := payload[1:] if len(blobHashes)%len(common.Hash{}) != 0 { return nil, fmt.Errorf("blob batch data is not a list of hashes as expected") @@ -115,6 +116,7 @@ func parseSequencerMessage(ctx context.Context, batchNum uint64, batchBlockHash } } + // Stage 2: If enabled, decode the zero heavy payload (saves gas based on calldata charging). if len(payload) > 0 && IsZeroheavyEncodedHeaderByte(payload[0]) { pl, err := io.ReadAll(io.LimitReader(zeroheavy.NewZeroheavyDecoder(bytes.NewReader(payload[1:])), int64(maxZeroheavyDecompressedLen))) if err != nil { @@ -124,6 +126,7 @@ func parseSequencerMessage(ctx context.Context, batchNum uint64, batchBlockHash payload = pl } + // Stage 3: Decompress the brotli payload and fill the parsedMsg.segments list. if len(payload) > 0 && IsBrotliMessageHeaderByte(payload[0]) { decompressed, err := arbcompress.Decompress(payload[1:], MaxDecompressedLen) if err == nil { From 254de23352ce8f03398e249a4452207a8ec8851b Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Tue, 30 Jan 2024 14:21:04 +0100 Subject: [PATCH 699/775] Revert running fuzzer in release-ci --- .github/workflows/release-ci.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index 4981513a1..29a1732f1 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -37,9 +37,3 @@ jobs: run: | echo "Not a release candidate. Skipping workflow." exit 0 - - - name: Build nitro-fuzzer Docker Image - run: docker build --target nitro-fuzzer -t nitro-fuzzer . - - - name: Run Docker Container - run: docker run nitro-fuzzer From d920feb2cc11cfdd5cd9d03f74dd205b054e8d50 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Tue, 30 Jan 2024 16:59:38 +0100 Subject: [PATCH 700/775] Consolidate linters into single binary --- Makefile | 4 +--- {linter => linters}/koanf/handlers.go | 2 +- {linter => linters}/koanf/koanf.go | 7 +------ {linter => linters}/koanf/koanf_test.go | 2 +- linters/linters.go | 18 ++++++++++++++++++ .../pointercheck/pointercheck.go | 7 +------ .../pointercheck/pointercheck_test.go | 2 +- {linter => linters}/rightshift/rightshift.go | 7 +------ .../rightshift/rightshift_test.go | 2 +- {linter => linters}/structinit/structinit.go | 7 +------ .../structinit/structinit_test.go | 2 +- {linter => linters}/testdata/src/koanf/a/a.go | 0 {linter => linters}/testdata/src/koanf/b/b.go | 0 .../testdata/src/pointercheck/pointercheck.go | 0 .../testdata/src/rightshift/rightshift.go | 0 .../testdata/src/structinit/a/a.go | 0 16 files changed, 28 insertions(+), 32 deletions(-) rename {linter => linters}/koanf/handlers.go (99%) rename {linter => linters}/koanf/koanf.go (95%) rename {linter => linters}/koanf/koanf_test.go (99%) create mode 100644 linters/linters.go rename linter/pointercheck/pointer.go => linters/pointercheck/pointercheck.go (95%) rename linter/pointercheck/pointer_test.go => linters/pointercheck/pointercheck_test.go (96%) rename {linter => linters}/rightshift/rightshift.go (94%) rename {linter => linters}/rightshift/rightshift_test.go (97%) rename {linter => linters}/structinit/structinit.go (96%) rename {linter => linters}/structinit/structinit_test.go (97%) rename {linter => linters}/testdata/src/koanf/a/a.go (100%) rename {linter => linters}/testdata/src/koanf/b/b.go (100%) rename {linter => linters}/testdata/src/pointercheck/pointercheck.go (100%) rename {linter => linters}/testdata/src/rightshift/rightshift.go (100%) rename {linter => linters}/testdata/src/structinit/a/a.go (100%) diff --git a/Makefile b/Makefile index 956ab0c35..d03b94072 100644 --- a/Makefile +++ b/Makefile @@ -311,9 +311,7 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro # strategic rules to minimize dependency building .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make - go run ./linter/koanf ./... - go run ./linter/pointercheck ./... - go run ./linter/rightshift ./... + go run ./linters ./... golangci-lint run --fix yarn --cwd contracts solhint @touch $@ diff --git a/linter/koanf/handlers.go b/linters/koanf/handlers.go similarity index 99% rename from linter/koanf/handlers.go rename to linters/koanf/handlers.go index 582600401..5ee3b80f9 100644 --- a/linter/koanf/handlers.go +++ b/linters/koanf/handlers.go @@ -1,4 +1,4 @@ -package main +package koanf import ( "fmt" diff --git a/linter/koanf/koanf.go b/linters/koanf/koanf.go similarity index 95% rename from linter/koanf/koanf.go rename to linters/koanf/koanf.go index f09fdd3d0..e53064b6b 100644 --- a/linter/koanf/koanf.go +++ b/linters/koanf/koanf.go @@ -1,4 +1,4 @@ -package main +package koanf import ( "errors" @@ -8,7 +8,6 @@ import ( "reflect" "golang.org/x/tools/go/analysis" - "golang.org/x/tools/go/analysis/singlechecker" ) var ( @@ -97,7 +96,3 @@ func run(dryRun bool, pass *analysis.Pass) (interface{}, error) { } return ret, nil } - -func main() { - singlechecker.Main(Analyzer) -} diff --git a/linter/koanf/koanf_test.go b/linters/koanf/koanf_test.go similarity index 99% rename from linter/koanf/koanf_test.go rename to linters/koanf/koanf_test.go index 0840ae521..9029951df 100644 --- a/linter/koanf/koanf_test.go +++ b/linters/koanf/koanf_test.go @@ -1,4 +1,4 @@ -package main +package koanf import ( "errors" diff --git a/linters/linters.go b/linters/linters.go new file mode 100644 index 000000000..a6c9f6d55 --- /dev/null +++ b/linters/linters.go @@ -0,0 +1,18 @@ +package main + +import ( + "github.com/offchainlabs/nitro/linters/koanf" + "github.com/offchainlabs/nitro/linters/pointercheck" + "github.com/offchainlabs/nitro/linters/rightshift" + "github.com/offchainlabs/nitro/linters/structinit" + "golang.org/x/tools/go/analysis/multichecker" +) + +func main() { + multichecker.Main( + koanf.Analyzer, + pointercheck.Analyzer, + rightshift.Analyzer, + structinit.Analyzer, + ) +} diff --git a/linter/pointercheck/pointer.go b/linters/pointercheck/pointercheck.go similarity index 95% rename from linter/pointercheck/pointer.go rename to linters/pointercheck/pointercheck.go index 4da2d8cc2..682ebd935 100644 --- a/linter/pointercheck/pointer.go +++ b/linters/pointercheck/pointercheck.go @@ -1,4 +1,4 @@ -package main +package pointercheck import ( "fmt" @@ -8,7 +8,6 @@ import ( "reflect" "golang.org/x/tools/go/analysis" - "golang.org/x/tools/go/analysis/singlechecker" ) var Analyzer = &analysis.Analyzer{ @@ -90,7 +89,3 @@ func ptrIdent(pass *analysis.Pass, e ast.Expr) bool { } return false } - -func main() { - singlechecker.Main(Analyzer) -} diff --git a/linter/pointercheck/pointer_test.go b/linters/pointercheck/pointercheck_test.go similarity index 96% rename from linter/pointercheck/pointer_test.go rename to linters/pointercheck/pointercheck_test.go index 47d5c6301..24f4534bc 100644 --- a/linter/pointercheck/pointer_test.go +++ b/linters/pointercheck/pointercheck_test.go @@ -1,4 +1,4 @@ -package main +package pointercheck import ( "os" diff --git a/linter/rightshift/rightshift.go b/linters/rightshift/rightshift.go similarity index 94% rename from linter/rightshift/rightshift.go rename to linters/rightshift/rightshift.go index f50d8a25a..d6fcbfec6 100644 --- a/linter/rightshift/rightshift.go +++ b/linters/rightshift/rightshift.go @@ -1,4 +1,4 @@ -package main +package rightshift import ( "go/ast" @@ -6,7 +6,6 @@ import ( "reflect" "golang.org/x/tools/go/analysis" - "golang.org/x/tools/go/analysis/singlechecker" ) var Analyzer = &analysis.Analyzer{ @@ -70,7 +69,3 @@ func isOne(expr ast.Expr) bool { bl, ok := expr.(*ast.BasicLit) return ok && bl.Kind == token.INT && bl.Value == "1" } - -func main() { - singlechecker.Main(Analyzer) -} diff --git a/linter/rightshift/rightshift_test.go b/linters/rightshift/rightshift_test.go similarity index 97% rename from linter/rightshift/rightshift_test.go rename to linters/rightshift/rightshift_test.go index 41555c068..3640d7997 100644 --- a/linter/rightshift/rightshift_test.go +++ b/linters/rightshift/rightshift_test.go @@ -1,4 +1,4 @@ -package main +package rightshift import ( "os" diff --git a/linter/structinit/structinit.go b/linters/structinit/structinit.go similarity index 96% rename from linter/structinit/structinit.go rename to linters/structinit/structinit.go index 31baf1c90..236b8747b 100644 --- a/linter/structinit/structinit.go +++ b/linters/structinit/structinit.go @@ -1,4 +1,4 @@ -package main +package structinit import ( "fmt" @@ -8,7 +8,6 @@ import ( "strings" "golang.org/x/tools/go/analysis" - "golang.org/x/tools/go/analysis/singlechecker" ) // Tip for linter that struct that has this comment should be included in the @@ -112,7 +111,3 @@ type position struct { fileName string line int } - -func main() { - singlechecker.Main(Analyzer) -} diff --git a/linter/structinit/structinit_test.go b/linters/structinit/structinit_test.go similarity index 97% rename from linter/structinit/structinit_test.go rename to linters/structinit/structinit_test.go index df8588a58..57dfc2b00 100644 --- a/linter/structinit/structinit_test.go +++ b/linters/structinit/structinit_test.go @@ -1,4 +1,4 @@ -package main +package structinit import ( "os" diff --git a/linter/testdata/src/koanf/a/a.go b/linters/testdata/src/koanf/a/a.go similarity index 100% rename from linter/testdata/src/koanf/a/a.go rename to linters/testdata/src/koanf/a/a.go diff --git a/linter/testdata/src/koanf/b/b.go b/linters/testdata/src/koanf/b/b.go similarity index 100% rename from linter/testdata/src/koanf/b/b.go rename to linters/testdata/src/koanf/b/b.go diff --git a/linter/testdata/src/pointercheck/pointercheck.go b/linters/testdata/src/pointercheck/pointercheck.go similarity index 100% rename from linter/testdata/src/pointercheck/pointercheck.go rename to linters/testdata/src/pointercheck/pointercheck.go diff --git a/linter/testdata/src/rightshift/rightshift.go b/linters/testdata/src/rightshift/rightshift.go similarity index 100% rename from linter/testdata/src/rightshift/rightshift.go rename to linters/testdata/src/rightshift/rightshift.go diff --git a/linter/testdata/src/structinit/a/a.go b/linters/testdata/src/structinit/a/a.go similarity index 100% rename from linter/testdata/src/structinit/a/a.go rename to linters/testdata/src/structinit/a/a.go From 68d8534e96f7a5bb3c8a3b582df527602263dbcd Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Tue, 30 Jan 2024 17:13:55 +0100 Subject: [PATCH 701/775] Update Go CI workflow with consolidated linters binary --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbf00bcb2..b27c196a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -117,8 +117,7 @@ jobs: skip-pkg-cache: true - name: Custom Lint run: | - go run ./linter/koanf ./... - go run ./linter/pointercheck ./... + go run ./linters ./... - name: Set environment variables run: | From c53c26ac50dfafb5402b2bafb532c85f10a9ecda Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 30 Jan 2024 18:20:09 +0000 Subject: [PATCH 702/775] defer last dereference call --- cmd/staterecovery/staterecovery.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/staterecovery/staterecovery.go b/cmd/staterecovery/staterecovery.go index a2918a81f..43faa6405 100644 --- a/cmd/staterecovery/staterecovery.go +++ b/cmd/staterecovery/staterecovery.go @@ -37,6 +37,9 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon return fmt.Errorf("genesis state is missing: %w", err) } _ = database.TrieDB().Reference(previousBlock.Root(), common.Hash{}) + defer func() { + _ = database.TrieDB().Dereference(previousBlock.Root()) + }() logged := time.Now() recreated := 0 for current <= last { @@ -78,7 +81,6 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon previousBlock = currentBlock previousState = currentState } - _ = database.TrieDB().Dereference(previousBlock.Root()) log.Info("Finished recreating missing states", "elapsed", time.Since(start), "recreated", recreated) return nil } From 2cb13424eec12b336ed62c5213d75d2a63c5a9df Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 30 Jan 2024 18:42:13 +0000 Subject: [PATCH 703/775] don't use referencing when recovering states --- cmd/staterecovery/staterecovery.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/cmd/staterecovery/staterecovery.go b/cmd/staterecovery/staterecovery.go index 43faa6405..f2feb5c7a 100644 --- a/cmd/staterecovery/staterecovery.go +++ b/cmd/staterecovery/staterecovery.go @@ -4,7 +4,6 @@ import ( "fmt" "time" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" @@ -36,10 +35,9 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon if err != nil { return fmt.Errorf("genesis state is missing: %w", err) } - _ = database.TrieDB().Reference(previousBlock.Root(), common.Hash{}) - defer func() { - _ = database.TrieDB().Dereference(previousBlock.Root()) - }() + // we don't need to reference states with `trie.Database.Reference` here, because: + // * either the state nodes will be read from disk and then cached in cleans cache + // * or they will be recreated, saved to disk and then also cached in cleans cache logged := time.Now() recreated := 0 for current <= last { @@ -75,8 +73,6 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon } recreated++ } - _ = database.TrieDB().Reference(currentBlock.Root(), common.Hash{}) - _ = database.TrieDB().Dereference(previousBlock.Root()) current++ previousBlock = currentBlock previousState = currentState From a594bc23bc2fa00053bb71cdedf984a1e11861d0 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 30 Jan 2024 19:04:21 +0000 Subject: [PATCH 704/775] remove unsused assignment --- cmd/staterecovery/staterecovery.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cmd/staterecovery/staterecovery.go b/cmd/staterecovery/staterecovery.go index f2feb5c7a..f21d213ba 100644 --- a/cmd/staterecovery/staterecovery.go +++ b/cmd/staterecovery/staterecovery.go @@ -19,8 +19,8 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon current := bc.Genesis().NumberU64() + 1 last := bc.CurrentBlock().Number.Uint64() - previousBlock := bc.GetBlockByNumber(current - 1) - if previousBlock == nil { + genesisBlock := bc.GetBlockByNumber(current - 1) + if genesisBlock == nil { return fmt.Errorf("genesis block is missing") } hashConfig := *hashdb.Defaults @@ -31,7 +31,7 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon } database := state.NewDatabaseWithConfig(chainDb, trieConfig) defer database.TrieDB().Close() - previousState, err := state.New(previousBlock.Root(), database, nil) + previousState, err := state.New(genesisBlock.Root(), database, nil) if err != nil { return fmt.Errorf("genesis state is missing: %w", err) } @@ -60,7 +60,7 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon return fmt.Errorf("StateDB commit failed, number %d root %v: %w", current, currentBlock.Root(), err) } if root.Cmp(currentBlock.Root()) != 0 { - return fmt.Errorf("reached different state root after processing block %d, want %v, have %v", current, currentBlock.Root(), root) + return fmt.Errorf("reached different state root after processing block %d, have %v, want %v", current, root, currentBlock.Root()) } // commit to disk err = database.TrieDB().Commit(root, false) // TODO report = true, do we want this many logs? @@ -74,7 +74,6 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon recreated++ } current++ - previousBlock = currentBlock previousState = currentState } log.Info("Finished recreating missing states", "elapsed", time.Since(start), "recreated", recreated) From aa304a9e321bec9985d8d00b8248816e1e381b81 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 30 Jan 2024 21:24:18 +0000 Subject: [PATCH 705/775] don't rely on BlockChain.CurrentBlock to get last available block --- cmd/nitro/init.go | 2 +- cmd/staterecovery/staterecovery.go | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index c7d850ac7..65c8962aa 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -187,7 +187,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if config.Init.RecreateMissingState { err = staterecovery.RecreateMissingStates(chainDb, l2BlockChain, cacheConfig) if err != nil { - return chainDb, l2BlockChain, err + return chainDb, l2BlockChain, fmt.Errorf("failed to recreate missing states: %w", err) } } diff --git a/cmd/staterecovery/staterecovery.go b/cmd/staterecovery/staterecovery.go index f21d213ba..0d35d89b2 100644 --- a/cmd/staterecovery/staterecovery.go +++ b/cmd/staterecovery/staterecovery.go @@ -1,6 +1,7 @@ package staterecovery import ( + "errors" "fmt" "time" @@ -14,15 +15,18 @@ import ( ) func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheConfig *core.CacheConfig) error { - log.Info("Recreating missing states...") start := time.Now() current := bc.Genesis().NumberU64() + 1 - last := bc.CurrentBlock().Number.Uint64() - genesisBlock := bc.GetBlockByNumber(current - 1) if genesisBlock == nil { - return fmt.Errorf("genesis block is missing") + return errors.New("genesis block is missing") + } + // find last available block - we cannot rely on bc.CurrentBlock() + last := current + for bc.GetBlockByNumber(last) != nil { + last++ } + last-- hashConfig := *hashdb.Defaults hashConfig.CleanCacheSize = cacheConfig.TrieCleanLimit trieConfig := &trie.Config{ @@ -38,7 +42,7 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon // we don't need to reference states with `trie.Database.Reference` here, because: // * either the state nodes will be read from disk and then cached in cleans cache // * or they will be recreated, saved to disk and then also cached in cleans cache - logged := time.Now() + logged := time.Unix(0, 0) recreated := 0 for current <= last { if time.Since(logged) > 1*time.Minute { From 43a8aeb122f4ee87810d992f9d6be20a661a1a4a Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 30 Jan 2024 21:32:30 +0000 Subject: [PATCH 706/775] improve recovery test --- system_tests/staterecovery_test.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/system_tests/staterecovery_test.go b/system_tests/staterecovery_test.go index 561e88915..33608bc8a 100644 --- a/system_tests/staterecovery_test.go +++ b/system_tests/staterecovery_test.go @@ -72,13 +72,7 @@ func TestRectreateMissingStates(t *testing.T) { Require(t, err) bc := testClient.ExecNode.Backend.ArbInterface().BlockChain() triedb := bc.StateCache().TrieDB() - var start uint64 - if currentBlock+1 >= builder.execConfig.Caching.BlockCount { - start = currentBlock + 1 - builder.execConfig.Caching.BlockCount - } else { - start = 0 - } - for i := start; i <= currentBlock; i++ { + for i := uint64(0); i <= currentBlock; i++ { header := bc.GetHeaderByNumber(i) _, err := bc.StateAt(header.Root) Require(t, err) From d5989b5a8cc00a385f3f094a220e21968fd95620 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 30 Jan 2024 21:49:25 +0000 Subject: [PATCH 707/775] add recreate-missing-state config validation --- cmd/conf/init.go | 8 ++++++++ cmd/nitro/nitro.go | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/cmd/conf/init.go b/cmd/conf/init.go index 313e5bbee..73848ebcf 100644 --- a/cmd/conf/init.go +++ b/cmd/conf/init.go @@ -3,6 +3,7 @@ package conf import ( "time" + "github.com/ethereum/go-ethereum/log" "github.com/spf13/pflag" ) @@ -59,3 +60,10 @@ func InitConfigAddOptions(prefix string, f *pflag.FlagSet) { 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.Bool(prefix+".recreate-missing-state", InitConfigDefault.RecreateMissingState, "if true: in case database exists and force=false, missing state will be recreated and committed to disk") } + +func (c *InitConfig) Validate() error { + if c.Force && c.RecreateMissingState { + log.Warn("--init.force enabled, --init.recreate-missing-state will have no effect") + } + return nil +} diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 45f539488..4838d981e 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -781,6 +781,12 @@ func (c *NodeConfig) CanReload(new *NodeConfig) error { } func (c *NodeConfig) Validate() error { + if c.Init.RecreateMissingState && !c.Execution.Caching.Archive { + return errors.New("--init.recreate-missing-state enabled for a non-archive node") + } + if err := c.Init.Validate(); err != nil { + return err + } if err := c.ParentChain.Validate(); err != nil { return err } From 6f9d044f92b15e1bf0bf5a22466f3a25991a46dc Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 30 Jan 2024 21:52:20 +0000 Subject: [PATCH 708/775] update log messages --- cmd/conf/init.go | 2 +- cmd/nitro/nitro.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/conf/init.go b/cmd/conf/init.go index 73848ebcf..b9617f30a 100644 --- a/cmd/conf/init.go +++ b/cmd/conf/init.go @@ -63,7 +63,7 @@ func InitConfigAddOptions(prefix string, f *pflag.FlagSet) { func (c *InitConfig) Validate() error { if c.Force && c.RecreateMissingState { - log.Warn("--init.force enabled, --init.recreate-missing-state will have no effect") + log.Warn("force init enabled, recreate-missing-state will have no effect") } return nil } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 4838d981e..3932e0ed9 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -782,7 +782,7 @@ func (c *NodeConfig) CanReload(new *NodeConfig) error { func (c *NodeConfig) Validate() error { if c.Init.RecreateMissingState && !c.Execution.Caching.Archive { - return errors.New("--init.recreate-missing-state enabled for a non-archive node") + return errors.New("recreate-missing-state enabled for a non-archive node") } if err := c.Init.Validate(); err != nil { return err From 07c74c7d4cecd4e456e63bf87d71b59f55ae8ef1 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Wed, 31 Jan 2024 11:55:12 +0100 Subject: [PATCH 709/775] Change release workflow trigger condition --- .github/workflows/release-ci.yml | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index 29a1732f1..0439b3f42 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -2,13 +2,9 @@ name: Release CI run-name: Release CI triggered from @${{ github.actor }} of ${{ github.head_ref }} on: - workflow_dispatch: - merge_group: - pull_request: - push: - branches: - - master - - develop + release: + types: [created, published] + jobs: build_and_run: runs-on: ubuntu-8 @@ -30,10 +26,3 @@ jobs: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ hashFiles('Dockerfile') }} restore-keys: ${{ runner.os }}-buildx- - - - - name: Check PR Label For Release label - if: ${{ !contains(github.event.*.labels.*.name, 'release') }} - run: | - echo "Not a release candidate. Skipping workflow." - exit 0 From 5969a112e883c0e9bd885cca15887a71536acc93 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Thu, 1 Feb 2024 13:54:59 +0100 Subject: [PATCH 710/775] Change trigger to workflow_dispatch only --- .github/workflows/release-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index 0439b3f42..036bf4653 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -2,8 +2,7 @@ name: Release CI run-name: Release CI triggered from @${{ github.actor }} of ${{ github.head_ref }} on: - release: - types: [created, published] + workflow_dispatch: jobs: build_and_run: From f61ad77e1f0253f12059aec3e17ae7a7a10821b1 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 1 Feb 2024 20:23:42 +0000 Subject: [PATCH 711/775] allow setting start block for missing states recreation, fix tests --- cmd/conf/init.go | 66 +++++++++++++++--------------- cmd/nitro/init.go | 4 +- cmd/nitro/nitro.go | 4 +- cmd/staterecovery/staterecovery.go | 22 ++++++---- system_tests/Session.vim | 34 +++++++++++++++ system_tests/staterecovery_test.go | 4 +- 6 files changed, 87 insertions(+), 47 deletions(-) create mode 100644 system_tests/Session.vim diff --git a/cmd/conf/init.go b/cmd/conf/init.go index b9617f30a..71709a830 100644 --- a/cmd/conf/init.go +++ b/cmd/conf/init.go @@ -8,39 +8,39 @@ import ( ) type InitConfig struct { - Force bool `koanf:"force"` - Url string `koanf:"url"` - DownloadPath string `koanf:"download-path"` - DownloadPoll time.Duration `koanf:"download-poll"` - DevInit bool `koanf:"dev-init"` - DevInitAddress string `koanf:"dev-init-address"` - DevInitBlockNum uint64 `koanf:"dev-init-blocknum"` - Empty bool `koanf:"empty"` - AccountsPerSync uint `koanf:"accounts-per-sync"` - ImportFile string `koanf:"import-file"` - ThenQuit bool `koanf:"then-quit"` - Prune string `koanf:"prune"` - PruneBloomSize uint64 `koanf:"prune-bloom-size"` - ResetToMessage int64 `koanf:"reset-to-message"` - RecreateMissingState bool `koanf:"recreate-missing-state"` + Force bool `koanf:"force"` + Url string `koanf:"url"` + DownloadPath string `koanf:"download-path"` + DownloadPoll time.Duration `koanf:"download-poll"` + DevInit bool `koanf:"dev-init"` + DevInitAddress string `koanf:"dev-init-address"` + DevInitBlockNum uint64 `koanf:"dev-init-blocknum"` + Empty bool `koanf:"empty"` + AccountsPerSync uint `koanf:"accounts-per-sync"` + ImportFile string `koanf:"import-file"` + ThenQuit bool `koanf:"then-quit"` + Prune string `koanf:"prune"` + PruneBloomSize uint64 `koanf:"prune-bloom-size"` + ResetToMessage int64 `koanf:"reset-to-message"` + RecreateMissingStateFrom uint64 `koanf:"recreate-missing-state-from"` } var InitConfigDefault = InitConfig{ - Force: false, - Url: "", - DownloadPath: "/tmp/", - DownloadPoll: time.Minute, - DevInit: false, - DevInitAddress: "", - DevInitBlockNum: 0, - Empty: false, - ImportFile: "", - AccountsPerSync: 100000, - ThenQuit: false, - Prune: "", - PruneBloomSize: 2048, - ResetToMessage: -1, - RecreateMissingState: false, + Force: false, + Url: "", + DownloadPath: "/tmp/", + DownloadPoll: time.Minute, + DevInit: false, + DevInitAddress: "", + DevInitBlockNum: 0, + Empty: false, + ImportFile: "", + AccountsPerSync: 100000, + ThenQuit: false, + Prune: "", + PruneBloomSize: 2048, + ResetToMessage: -1, + RecreateMissingStateFrom: 0, // 0 = disabled } func InitConfigAddOptions(prefix string, f *pflag.FlagSet) { @@ -58,12 +58,12 @@ func InitConfigAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".prune", InitConfigDefault.Prune, "pruning for a given use: \"full\" for full nodes serving RPC requests, or \"validator\" for validators") 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.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.Bool(prefix+".recreate-missing-state", InitConfigDefault.RecreateMissingState, "if true: in case database exists and force=false, missing state will be recreated and committed to disk") + f.Uint64(prefix+".recreate-missing-state-from", InitConfigDefault.RecreateMissingStateFrom, "block number to start recreating missing states form (0 = disabled)") } func (c *InitConfig) Validate() error { - if c.Force && c.RecreateMissingState { - log.Warn("force init enabled, recreate-missing-state will have no effect") + if c.Force && c.RecreateMissingStateFrom > 0 { + log.Warn("force init enabled, recreate-missing-state-from will have no effect") } return nil } diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 65c8962aa..ebc57b13b 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -184,8 +184,8 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if err != nil { return chainDb, l2BlockChain, err } - if config.Init.RecreateMissingState { - err = staterecovery.RecreateMissingStates(chainDb, l2BlockChain, cacheConfig) + if config.Init.RecreateMissingStateFrom > 0 { + err = staterecovery.RecreateMissingStates(chainDb, l2BlockChain, cacheConfig, config.Init.RecreateMissingStateFrom) if err != nil { return chainDb, l2BlockChain, fmt.Errorf("failed to recreate missing states: %w", err) } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 3932e0ed9..e5b97d4a1 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -781,8 +781,8 @@ func (c *NodeConfig) CanReload(new *NodeConfig) error { } func (c *NodeConfig) Validate() error { - if c.Init.RecreateMissingState && !c.Execution.Caching.Archive { - return errors.New("recreate-missing-state enabled for a non-archive node") + if c.Init.RecreateMissingStateFrom > 0 && !c.Execution.Caching.Archive { + return errors.New("recreate-missing-state-from enabled for a non-archive node") } if err := c.Init.Validate(); err != nil { return err diff --git a/cmd/staterecovery/staterecovery.go b/cmd/staterecovery/staterecovery.go index 0d35d89b2..4b5f9b846 100644 --- a/cmd/staterecovery/staterecovery.go +++ b/cmd/staterecovery/staterecovery.go @@ -1,7 +1,6 @@ package staterecovery import ( - "errors" "fmt" "time" @@ -14,12 +13,17 @@ import ( "github.com/ethereum/go-ethereum/trie/triedb/hashdb" ) -func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheConfig *core.CacheConfig) error { +func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheConfig *core.CacheConfig, startBlock uint64) error { start := time.Now() - current := bc.Genesis().NumberU64() + 1 - genesisBlock := bc.GetBlockByNumber(current - 1) - if genesisBlock == nil { - return errors.New("genesis block is missing") + current := startBlock + genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum + if current < genesis+1 { + log.Warn("recreate-missing-states-from before genesis+1, starting from genesis+1") + current = genesis + 1 + } + previousBlock := bc.GetBlockByNumber(current - 1) + if previousBlock == nil { + return fmt.Errorf("start block parent is missing, parent block number: %d", current-1) } // find last available block - we cannot rely on bc.CurrentBlock() last := current @@ -35,9 +39,9 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon } database := state.NewDatabaseWithConfig(chainDb, trieConfig) defer database.TrieDB().Close() - previousState, err := state.New(genesisBlock.Root(), database, nil) + previousState, err := state.New(previousBlock.Root(), database, nil) if err != nil { - return fmt.Errorf("genesis state is missing: %w", err) + return fmt.Errorf("state of start block parent is missing: %w", err) } // we don't need to reference states with `trie.Database.Reference` here, because: // * either the state nodes will be read from disk and then cached in cleans cache @@ -67,7 +71,7 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon return fmt.Errorf("reached different state root after processing block %d, have %v, want %v", current, root, currentBlock.Root()) } // commit to disk - err = database.TrieDB().Commit(root, false) // TODO report = true, do we want this many logs? + err = database.TrieDB().Commit(root, false) if err != nil { return fmt.Errorf("TrieDB commit failed, number %d root %v: %w", current, root, err) } diff --git a/system_tests/Session.vim b/system_tests/Session.vim new file mode 100644 index 000000000..fd61e4244 --- /dev/null +++ b/system_tests/Session.vim @@ -0,0 +1,34 @@ +let SessionLoad = 1 +let s:so_save = &g:so | let s:siso_save = &g:siso | setg so=0 siso=0 | setl so=-1 siso=-1 +let v:this_session=expand(":p") +silent only +silent tabonly +cd ~/repos/nitro3/system_tests +if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' + let s:wipebuf = bufnr('%') +endif +let s:shortmess_save = &shortmess +if &shortmess =~ 'A' + set shortmess=aoOA +else + set shortmess=aoO +endif +argglobal +%argdel +tabnext 1 +if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' + silent exe 'bwipe ' . s:wipebuf +endif +unlet! s:wipebuf +set winheight=1 winwidth=20 +let &shortmess = s:shortmess_save +let s:sx = expand(":p:r")."x.vim" +if filereadable(s:sx) + exe "source " . fnameescape(s:sx) +endif +let &g:so = s:so_save | let &g:siso = s:siso_save +set hlsearch +nohlsearch +doautoall SessionLoadPost +unlet SessionLoad +" vim: set ft=vim : diff --git a/system_tests/staterecovery_test.go b/system_tests/staterecovery_test.go index 33608bc8a..ac30038cc 100644 --- a/system_tests/staterecovery_test.go +++ b/system_tests/staterecovery_test.go @@ -17,7 +17,9 @@ func TestRectreateMissingStates(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.execConfig.Caching.Archive = true builder.execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 16 + builder.execConfig.Caching.SnapshotCache = 0 // disable snapshots _ = builder.Build(t) l2cleanupDone := false defer func() { @@ -53,7 +55,7 @@ func TestRectreateMissingStates(t *testing.T) { cacheConfig := gethexec.DefaultCacheConfigFor(stack, &gethexec.DefaultCachingConfig) bc, err := gethexec.GetBlockChain(chainDb, cacheConfig, builder.chainConfig, builder.execConfig.TxLookupLimit) Require(t, err) - err = staterecovery.RecreateMissingStates(chainDb, bc, cacheConfig) + err = staterecovery.RecreateMissingStates(chainDb, bc, cacheConfig, 1) Require(t, err) }() From ea34814fbfebc1a6b3d2eaf29d49d8b03e8a2378 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 1 Feb 2024 20:28:03 +0000 Subject: [PATCH 712/775] remove Session.vim added by mistake --- system_tests/Session.vim | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 system_tests/Session.vim diff --git a/system_tests/Session.vim b/system_tests/Session.vim deleted file mode 100644 index fd61e4244..000000000 --- a/system_tests/Session.vim +++ /dev/null @@ -1,34 +0,0 @@ -let SessionLoad = 1 -let s:so_save = &g:so | let s:siso_save = &g:siso | setg so=0 siso=0 | setl so=-1 siso=-1 -let v:this_session=expand(":p") -silent only -silent tabonly -cd ~/repos/nitro3/system_tests -if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' - let s:wipebuf = bufnr('%') -endif -let s:shortmess_save = &shortmess -if &shortmess =~ 'A' - set shortmess=aoOA -else - set shortmess=aoO -endif -argglobal -%argdel -tabnext 1 -if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' - silent exe 'bwipe ' . s:wipebuf -endif -unlet! s:wipebuf -set winheight=1 winwidth=20 -let &shortmess = s:shortmess_save -let s:sx = expand(":p:r")."x.vim" -if filereadable(s:sx) - exe "source " . fnameescape(s:sx) -endif -let &g:so = s:so_save | let &g:siso = s:siso_save -set hlsearch -nohlsearch -doautoall SessionLoadPost -unlet SessionLoad -" vim: set ft=vim : From b9a1c4945de373d41f16957b46692b0ca9ce0d64 Mon Sep 17 00:00:00 2001 From: Chris Buckland Date: Thu, 1 Feb 2024 20:36:37 +0000 Subject: [PATCH 713/775] Log error data where available --- util/rpcclient/rpcclient.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/util/rpcclient/rpcclient.go b/util/rpcclient/rpcclient.go index dee6e9252..d88e6dfc3 100644 --- a/util/rpcclient/rpcclient.go +++ b/util/rpcclient/rpcclient.go @@ -155,13 +155,25 @@ func (c *RpcClient) CallContext(ctx_in context.Context, result interface{}, meth ctx, cancelCtx = context.WithCancel(ctx_in) } err = c.client.CallContext(ctx, result, method, args...) + cancelCtx() logger := log.Trace limit := int(c.config().ArgLogLimit) if err != nil && err.Error() != "already known" { logger = log.Info } - logger("rpc response", "method", method, "logId", logId, "err", err, "result", limitedMarshal{limit, result}, "attempt", i, "args", limitedArgumentsMarshal{limit, args}) + logEntry := []interface{}{ + "method", method, + "logId", logId, + "err", err, + "result", limitedMarshal{limit, result}, + "attempt", i, + "args", limitedArgumentsMarshal{limit, args}, + } + if da, ok := err.(rpc.DataError); ok { + logEntry = append(logEntry, "errorData", limitedMarshal{limit, da.ErrorData()}) + } + logger("rpc response", logEntry...) if err == nil { return nil } From e8167fee6804ba612ed0721b39d42a6b858094ed Mon Sep 17 00:00:00 2001 From: Chris Buckland Date: Thu, 1 Feb 2024 20:58:31 +0000 Subject: [PATCH 714/775] Use lint reco for errors.as --- util/rpcclient/rpcclient.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/util/rpcclient/rpcclient.go b/util/rpcclient/rpcclient.go index d88e6dfc3..dbc145d49 100644 --- a/util/rpcclient/rpcclient.go +++ b/util/rpcclient/rpcclient.go @@ -170,8 +170,9 @@ func (c *RpcClient) CallContext(ctx_in context.Context, result interface{}, meth "attempt", i, "args", limitedArgumentsMarshal{limit, args}, } - if da, ok := err.(rpc.DataError); ok { - logEntry = append(logEntry, "errorData", limitedMarshal{limit, da.ErrorData()}) + var dataErr rpc.DataError + if errors.As(err, &dataErr) { + logEntry = append(logEntry, "errorData", limitedMarshal{limit, dataErr.ErrorData()}) } logger("rpc response", logEntry...) if err == nil { From 03138e0c783fb794afc0241b81f908869fd89cd7 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 1 Feb 2024 14:28:37 -0700 Subject: [PATCH 715/775] Pull in geth changes to parse ABI errors --- go-ethereum | 2 +- precompiles/precompile.go | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/go-ethereum b/go-ethereum index 1acd9c64a..a0685a71f 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 1acd9c64ac5804729475ef60aa578b4ec52fa0e6 +Subproject commit a0685a71f31c14f414c01cb5c7c91170fd0e84be diff --git a/precompiles/precompile.go b/precompiles/precompile.go index 5d2ecce74..175bb2190 100644 --- a/precompiles/precompile.go +++ b/precompiles/precompile.go @@ -96,12 +96,8 @@ func RenderSolError(solErr abi.Error, data []byte) (string, error) { if err != nil { return "", err } - valsRange, ok := vals.([]interface{}) - if !ok { - return "", errors.New("unexpected unpack result") - } - strVals := make([]string, 0, len(valsRange)) - for _, val := range valsRange { + strVals := make([]string, 0, len(vals)) + for _, val := range vals { strVals = append(strVals, fmt.Sprintf("%v", val)) } return fmt.Sprintf("error %v(%v)", solErr.Name, strings.Join(strVals, ", ")), nil From 5bda2077f85595aa4f176330d922393edc0b9ebb Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 1 Feb 2024 22:27:58 +0000 Subject: [PATCH 716/775] fix typo --- cmd/conf/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/conf/init.go b/cmd/conf/init.go index 71709a830..8a6c5096f 100644 --- a/cmd/conf/init.go +++ b/cmd/conf/init.go @@ -58,7 +58,7 @@ func InitConfigAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".prune", InitConfigDefault.Prune, "pruning for a given use: \"full\" for full nodes serving RPC requests, or \"validator\" for validators") 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.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 form (0 = disabled)") + f.Uint64(prefix+".recreate-missing-state-from", InitConfigDefault.RecreateMissingStateFrom, "block number to start recreating missing states from (0 = disabled)") } func (c *InitConfig) Validate() error { From b94cf9c2455fd2c687493b32ccb9a124b007fd62 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 1 Feb 2024 22:49:37 +0000 Subject: [PATCH 717/775] address review comment --- cmd/staterecovery/staterecovery.go | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/cmd/staterecovery/staterecovery.go b/cmd/staterecovery/staterecovery.go index 4b5f9b846..97c570e9b 100644 --- a/cmd/staterecovery/staterecovery.go +++ b/cmd/staterecovery/staterecovery.go @@ -25,12 +25,6 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon if previousBlock == nil { return fmt.Errorf("start block parent is missing, parent block number: %d", current-1) } - // find last available block - we cannot rely on bc.CurrentBlock() - last := current - for bc.GetBlockByNumber(last) != nil { - last++ - } - last-- hashConfig := *hashdb.Defaults hashConfig.CleanCacheSize = cacheConfig.TrieCleanLimit trieConfig := &trie.Config{ @@ -48,14 +42,18 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon // * or they will be recreated, saved to disk and then also cached in cleans cache logged := time.Unix(0, 0) recreated := 0 - for current <= last { - if time.Since(logged) > 1*time.Minute { - log.Info("Recreating missing states", "block", current, "target", last, "remaining", last-current, "elapsed", time.Since(start), "recreated", recreated) - logged = time.Now() - } + for { currentBlock := bc.GetBlockByNumber(current) if currentBlock == nil { - return fmt.Errorf("missing block %d", current) + break + } + if time.Since(logged) > 1*time.Minute { + var target uint64 + if h := bc.CurrentBlock(); h != nil { + target = h.Number.Uint64() + } + log.Info("Recreating missing states", "block", current, "target", target, "remaining", target-current, "elapsed", time.Since(start), "recreated", recreated) + logged = time.Now() } currentState, err := state.New(currentBlock.Root(), database, nil) if err != nil { From b3f42cdd7e7bcb8ee064c19504caa07ee684bb58 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 1 Feb 2024 23:04:36 +0000 Subject: [PATCH 718/775] set target only once --- cmd/staterecovery/staterecovery.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cmd/staterecovery/staterecovery.go b/cmd/staterecovery/staterecovery.go index 97c570e9b..bb6783035 100644 --- a/cmd/staterecovery/staterecovery.go +++ b/cmd/staterecovery/staterecovery.go @@ -15,6 +15,11 @@ import ( func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheConfig *core.CacheConfig, startBlock uint64) error { start := time.Now() + currentHeader := bc.CurrentBlock() + if currentHeader == nil { + return fmt.Errorf("current header is nil") + } + target := currentHeader.Number.Uint64() current := startBlock genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum if current < genesis+1 { @@ -48,11 +53,7 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon break } if time.Since(logged) > 1*time.Minute { - var target uint64 - if h := bc.CurrentBlock(); h != nil { - target = h.Number.Uint64() - } - log.Info("Recreating missing states", "block", current, "target", target, "remaining", target-current, "elapsed", time.Since(start), "recreated", recreated) + log.Info("Recreating missing states", "block", current, "target", target, "remaining", int64(target)-int64(current), "elapsed", time.Since(start), "recreated", recreated) logged = time.Now() } currentState, err := state.New(currentBlock.Root(), database, nil) From 74692529c3883e1f8341cede2f585da71323559a Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 1 Feb 2024 16:39:46 -0700 Subject: [PATCH 719/775] Fix tests --- system_tests/precompile_test.go | 8 ++++++-- system_tests/retryable_test.go | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/system_tests/precompile_test.go b/system_tests/precompile_test.go index e0a9c2ce7..0ad0f8f1e 100644 --- a/system_tests/precompile_test.go +++ b/system_tests/precompile_test.go @@ -5,6 +5,7 @@ package arbtest import ( "context" + "fmt" "math/big" "testing" @@ -67,7 +68,9 @@ func TestCustomSolidityErrors(t *testing.T) { Fatal(t, "customRevert call should have errored") } observedMessage := customError.Error() - expectedMessage := "execution reverted: error Custom(1024, This spider family wards off bugs: /\\oo/\\ //\\(oo)/\\ /\\oo/\\, true)" + expectedError := "Custom(1024, This spider family wards off bugs: /\\oo/\\ //\\(oo)/\\ /\\oo/\\, true)" + // The first error is server side. The second error is client side ABI decoding. + expectedMessage := fmt.Sprintf("execution reverted: error %v: %v", expectedError, expectedError) if observedMessage != expectedMessage { Fatal(t, observedMessage) } @@ -79,7 +82,8 @@ func TestCustomSolidityErrors(t *testing.T) { Fatal(t, "out of range ArbBlockHash call should have errored") } observedMessage = customError.Error() - expectedMessage = "execution reverted: error InvalidBlockNumber(1000000000, 1)" + expectedError = "InvalidBlockNumber(1000000000, 1)" + expectedMessage = fmt.Sprintf("execution reverted: error %v: %v", expectedError, expectedError) if observedMessage != expectedMessage { Fatal(t, observedMessage) } diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 461967170..4e7bd2c7d 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -121,7 +121,8 @@ func TestRetryableNoExist(t *testing.T) { arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), builder.L2.Client) Require(t, err) _, err = arbRetryableTx.GetTimeout(&bind.CallOpts{}, common.Hash{}) - if err.Error() != "execution reverted: error NoTicketWithID()" { + // The first error is server side. The second error is client side ABI decoding. + if err.Error() != "execution reverted: error NoTicketWithID(): NoTicketWithID()" { Fatal(t, "didn't get expected NoTicketWithID error") } } From f632620e486df8b5a9fcbf2d4501aab0696c1787 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 1 Feb 2024 23:45:17 +0000 Subject: [PATCH 720/775] update override warning --- cmd/staterecovery/staterecovery.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/staterecovery/staterecovery.go b/cmd/staterecovery/staterecovery.go index bb6783035..6390826a9 100644 --- a/cmd/staterecovery/staterecovery.go +++ b/cmd/staterecovery/staterecovery.go @@ -23,8 +23,8 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon current := startBlock genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum if current < genesis+1 { - log.Warn("recreate-missing-states-from before genesis+1, starting from genesis+1") current = genesis + 1 + log.Warn("recreate-missing-states-from before genesis+1, starting from genesis+1", "configured", startBlock, "override", current) } previousBlock := bc.GetBlockByNumber(current - 1) if previousBlock == nil { From d36491aaf91f2589bfbb227cd6d2efdc230139df Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 2 Feb 2024 10:50:35 +0800 Subject: [PATCH 721/775] Update common_test.go --- system_tests/common_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index a950ebd7c..be782c72f 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -929,7 +929,7 @@ func Create2ndNodeWithConfig( currentExec, err := gethexec.CreateExecutionNode(ctx, l2stack, l2chainDb, l2blockchain, l1client, configFetcher) Require(t, err) - currentNode, err := arbnode.CreateNode(ctx, l2stack, currentExec, l2arbDb, NewFetcherFromConfig(nodeConfig), l2blockchain.Config(), l1client, first.DeployInfo, &txOpts, &txOpts, dataSigner, feedErrChan, big.NewInt(13)) + currentNode, err := arbnode.CreateNode(ctx, l2stack, currentExec, l2arbDb, NewFetcherFromConfig(nodeConfig), l2blockchain.Config(), l1client, first.DeployInfo, &txOpts, &txOpts, dataSigner, feedErrChan, big.NewInt(1337)) Require(t, err) err = currentNode.Start(ctx) From f0156ccb615771393feb7b9ba69a24a093925c5a Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 2 Feb 2024 21:25:02 +0530 Subject: [PATCH 722/775] Add P2P options --- cmd/genericconf/server.go | 54 ++++++++++++++++++++++++++++++++++++++ cmd/nitro-val/config.go | 3 +++ cmd/nitro-val/nitro_val.go | 4 +-- cmd/nitro/nitro.go | 7 ++--- 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/cmd/genericconf/server.go b/cmd/genericconf/server.go index 3da027ab2..f207e9ff3 100644 --- a/cmd/genericconf/server.go +++ b/cmd/genericconf/server.go @@ -4,6 +4,8 @@ package genericconf import ( + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/enode" "time" flag "github.com/spf13/pflag" @@ -185,6 +187,58 @@ func AuthRPCConfigAddOptions(prefix string, f *flag.FlagSet) { f.StringSlice(prefix+".api", AuthRPCConfigDefault.API, "APIs offered over the AUTH-RPC interface") } +type P2PConfig struct { + ListenAddr string `koanf:"listen-addr"` + NoDial bool `koanf:"no-dial"` + NoDiscovery bool `koanf:"no-discovery"` + MaxPeers int `koanf:"max-peers"` + DiscoveryV5 bool `koanf:"discovery-v5"` + DiscoveryV4 bool `koanf:"discovery-v4"` + Bootnodes []string `koanf:"bootnodes"` + BootnodesV5 []string `koanf:"bootnodes-v5"` +} + +func (p P2PConfig) Apply(stackConf *node.Config) { + stackConf.P2P.ListenAddr = p.ListenAddr + stackConf.P2P.NoDial = p.NoDial + stackConf.P2P.NoDiscovery = p.NoDiscovery + stackConf.P2P.MaxPeers = p.MaxPeers + stackConf.P2P.DiscoveryV5 = p.DiscoveryV5 + stackConf.P2P.DiscoveryV4 = p.DiscoveryV4 + stackConf.P2P.BootstrapNodes = parseBootnodes(p.Bootnodes) + stackConf.P2P.BootstrapNodesV5 = parseBootnodes(p.BootnodesV5) +} + +func parseBootnodes(urls []string) []*enode.Node { + nodes := make([]*enode.Node, 0, len(urls)) + for _, url := range urls { + if url != "" { + node, err := enode.Parse(enode.ValidSchemes, url) + if err != nil { + log.Crit("Bootstrap URL invalid", "enode", url, "err", err) + return nil + } + nodes = append(nodes, node) + } + } + return nodes +} + +var P2PConfigDefault = P2PConfig{ + ListenAddr: "", + NoDial: true, + NoDiscovery: true, + MaxPeers: 50, + DiscoveryV5: false, + DiscoveryV4: false, +} + +func P2PConfigAddOptions(prefix string, f *flag.FlagSet) { + f.String(prefix+".listen-addr", P2PConfigDefault.ListenAddr, "P2P listen address") + f.Bool(prefix+".no-dial", P2PConfigDefault.NoDial, "P2P no dial") + f.Bool(prefix+".no-discovery", P2PConfigDefault.NoDiscovery, "P2P no discovery") +} + type MetricsServerConfig struct { Addr string `koanf:"addr"` Port int `koanf:"port"` diff --git a/cmd/nitro-val/config.go b/cmd/nitro-val/config.go index cf10787d6..51d397883 100644 --- a/cmd/nitro-val/config.go +++ b/cmd/nitro-val/config.go @@ -27,6 +27,7 @@ type ValidationNodeConfig struct { HTTP genericconf.HTTPConfig `koanf:"http"` WS genericconf.WSConfig `koanf:"ws"` IPC genericconf.IPCConfig `koanf:"ipc"` + P2P genericconf.P2PConfig `koanf:"p2p"` Auth genericconf.AuthRPCConfig `koanf:"auth"` Metrics bool `koanf:"metrics"` MetricsServer genericconf.MetricsServerConfig `koanf:"metrics-server"` @@ -66,6 +67,7 @@ var ValidationNodeConfigDefault = ValidationNodeConfig{ HTTP: HTTPConfigDefault, WS: WSConfigDefault, IPC: IPCConfigDefault, + P2P: genericconf.P2PConfigDefault, Auth: genericconf.AuthRPCConfigDefault, Metrics: false, MetricsServer: genericconf.MetricsServerConfigDefault, @@ -85,6 +87,7 @@ func ValidationNodeConfigAddOptions(f *flag.FlagSet) { genericconf.WSConfigAddOptions("ws", f) genericconf.IPCConfigAddOptions("ipc", f) genericconf.AuthRPCConfigAddOptions("auth", f) + genericconf.P2PConfigAddOptions("p2p", f) f.Bool("metrics", ValidationNodeConfigDefault.Metrics, "enable metrics") genericconf.MetricsServerAddOptions("metrics-server", f) f.Bool("pprof", ValidationNodeConfigDefault.PProf, "enable pprof") diff --git a/cmd/nitro-val/nitro_val.go b/cmd/nitro-val/nitro_val.go index 20b8b2362..fea95cbb1 100644 --- a/cmd/nitro-val/nitro_val.go +++ b/cmd/nitro-val/nitro_val.go @@ -70,9 +70,7 @@ func mainImpl() int { nodeConfig.WS.Apply(&stackConf) nodeConfig.Auth.Apply(&stackConf) nodeConfig.IPC.Apply(&stackConf) - stackConf.P2P.ListenAddr = "" - stackConf.P2P.NoDial = true - stackConf.P2P.NoDiscovery = true + nodeConfig.P2P.Apply(&stackConf) vcsRevision, strippedRevision, vcsTime := confighelpers.GetVersion() stackConf.Version = strippedRevision diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index e5b97d4a1..f956b4674 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -178,9 +178,7 @@ func mainImpl() int { if nodeConfig.WS.ExposeAll { stackConf.WSModules = append(stackConf.WSModules, "personal") } - stackConf.P2P.ListenAddr = "" - stackConf.P2P.NoDial = true - stackConf.P2P.NoDiscovery = true + nodeConfig.P2P.Apply(&stackConf) vcsRevision, strippedRevision, vcsTime := confighelpers.GetVersion() stackConf.Version = strippedRevision @@ -674,6 +672,7 @@ type NodeConfig struct { IPC genericconf.IPCConfig `koanf:"ipc"` Auth genericconf.AuthRPCConfig `koanf:"auth"` GraphQL genericconf.GraphQLConfig `koanf:"graphql"` + P2P genericconf.P2PConfig `koanf:"p2p"` Metrics bool `koanf:"metrics"` MetricsServer genericconf.MetricsServerConfig `koanf:"metrics-server"` PProf bool `koanf:"pprof"` @@ -698,6 +697,7 @@ var NodeConfigDefault = NodeConfig{ IPC: genericconf.IPCConfigDefault, Auth: genericconf.AuthRPCConfigDefault, GraphQL: genericconf.GraphQLConfigDefault, + P2P: genericconf.P2PConfigDefault, Metrics: false, MetricsServer: genericconf.MetricsServerConfigDefault, Init: conf.InitConfigDefault, @@ -721,6 +721,7 @@ func NodeConfigAddOptions(f *flag.FlagSet) { genericconf.WSConfigAddOptions("ws", f) genericconf.IPCConfigAddOptions("ipc", f) genericconf.AuthRPCConfigAddOptions("auth", f) + genericconf.P2PConfigAddOptions("p2p", f) genericconf.GraphQLConfigAddOptions("graphql", f) f.Bool("metrics", NodeConfigDefault.Metrics, "enable metrics") genericconf.MetricsServerAddOptions("metrics-server", f) From 8eb64f241b9d969ffb81f43163adb8f06f32242c Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 2 Feb 2024 21:25:58 +0530 Subject: [PATCH 723/775] minor fix --- cmd/genericconf/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/genericconf/server.go b/cmd/genericconf/server.go index f207e9ff3..a8a47fae4 100644 --- a/cmd/genericconf/server.go +++ b/cmd/genericconf/server.go @@ -4,13 +4,13 @@ package genericconf import ( - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p/enode" "time" flag "github.com/spf13/pflag" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/p2p/enode" ) type HTTPConfig struct { From 2aa56569efc935cd5629ac9d1fa37557b1328447 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 2 Feb 2024 21:27:06 +0530 Subject: [PATCH 724/775] minor fix --- cmd/genericconf/server.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmd/genericconf/server.go b/cmd/genericconf/server.go index a8a47fae4..7550791d6 100644 --- a/cmd/genericconf/server.go +++ b/cmd/genericconf/server.go @@ -231,12 +231,19 @@ var P2PConfigDefault = P2PConfig{ MaxPeers: 50, DiscoveryV5: false, DiscoveryV4: false, + Bootnodes: []string{}, + BootnodesV5: []string{}, } func P2PConfigAddOptions(prefix string, f *flag.FlagSet) { f.String(prefix+".listen-addr", P2PConfigDefault.ListenAddr, "P2P listen address") f.Bool(prefix+".no-dial", P2PConfigDefault.NoDial, "P2P no dial") f.Bool(prefix+".no-discovery", P2PConfigDefault.NoDiscovery, "P2P no discovery") + f.Int(prefix+".max-peers", P2PConfigDefault.MaxPeers, "P2P max peers") + f.Bool(prefix+".discovery-v5", P2PConfigDefault.DiscoveryV5, "P2P discovery v5") + f.Bool(prefix+".discovery-v4", P2PConfigDefault.DiscoveryV4, "P2P discovery v4") + f.StringSlice(prefix+".bootnodes", P2PConfigDefault.Bootnodes, "P2P bootnodes") + f.StringSlice(prefix+".bootnodes-v5", P2PConfigDefault.BootnodesV5, "P2P bootnodes v5") } type MetricsServerConfig struct { From acc85b37dd2796fc49de3f15a3fd30c4749850e3 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 2 Feb 2024 10:31:44 -0700 Subject: [PATCH 725/775] Gate GetScheduledUpgrade to ArbOS 20 --- precompiles/precompile.go | 1 + 1 file changed, 1 insertion(+) diff --git a/precompiles/precompile.go b/precompiles/precompile.go index 5d2ecce74..5a16a1f90 100644 --- a/precompiles/precompile.go +++ b/precompiles/precompile.go @@ -560,6 +560,7 @@ func Precompiles() map[addr]ArbosPrecompile { ArbOwnerPublic.methodsByName["GetInfraFeeAccount"].arbosVersion = 5 ArbOwnerPublic.methodsByName["RectifyChainOwner"].arbosVersion = 11 ArbOwnerPublic.methodsByName["GetBrotliCompressionLevel"].arbosVersion = 20 + ArbOwnerPublic.methodsByName["GetScheduledUpgrade"].arbosVersion = 20 ArbRetryableImpl := &ArbRetryableTx{Address: types.ArbRetryableTxAddress} ArbRetryable := insert(MakePrecompile(templates.ArbRetryableTxMetaData, ArbRetryableImpl)) From f16bc040a326b0a766044a23015cb7b7f2c20a9b Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 2 Feb 2024 11:46:11 -0700 Subject: [PATCH 726/775] Test precompiles per ArbOS version --- precompiles/precompile_test.go | 48 ++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/precompiles/precompile_test.go b/precompiles/precompile_test.go index 02d962f0b..975856bce 100644 --- a/precompiles/precompile_test.go +++ b/precompiles/precompile_test.go @@ -4,10 +4,13 @@ package precompiles import ( + "fmt" "math/big" + "os" "testing" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -176,22 +179,35 @@ func TestEventCosts(t *testing.T) { } } -type FatalBurner struct { - t *testing.T - count uint64 - gasLeft uint64 -} - -func NewFatalBurner(t *testing.T, limit uint64) FatalBurner { - return FatalBurner{t, 0, limit} -} +func TestPrecompilesPerArbosVersion(t *testing.T) { + // Set up a logger in case log.Crit is called by Precompiles() + glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) + glogger.Verbosity(log.LvlWarn) + log.Root().SetHandler(glogger) + + expectedNewMethodsPerArbosVersion := map[uint64]int{ + 0: 89, + 5: 3, + 10: 2, + 11: 4, + 20: 8, + } + + precompiles := Precompiles() + newMethodsPerArbosVersion := make(map[uint64]int) + for _, precompile := range precompiles { + for _, method := range precompile.Precompile().methods { + newMethodsPerArbosVersion[method.arbosVersion]++ + } + } -func (burner FatalBurner) Burn(amount uint64) error { - burner.t.Helper() - burner.count += 1 - if burner.gasLeft < amount { - Fail(burner.t, "out of gas after", burner.count, "burns") + if len(expectedNewMethodsPerArbosVersion) != len(newMethodsPerArbosVersion) { + t.Errorf("expected %v ArbOS versions with new precompile methods but got %v", len(expectedNewMethodsPerArbosVersion), len(newMethodsPerArbosVersion)) + } + for version, count := range newMethodsPerArbosVersion { + fmt.Printf("got %v version count %v\n", version, count) + if expectedNewMethodsPerArbosVersion[version] != count { + t.Errorf("expected %v new precompile methods for ArbOS version %v but got %v", expectedNewMethodsPerArbosVersion[version], version, count) + } } - burner.gasLeft -= amount - return nil } From ab4d316c0855908e45a0ac76633856963853152f Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 6 Feb 2024 21:17:29 +0530 Subject: [PATCH 727/775] Changes based on PR comments --- arbnode/sync_monitor.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arbnode/sync_monitor.go b/arbnode/sync_monitor.go index 5fa9dbabc..24b00a4af 100644 --- a/arbnode/sync_monitor.go +++ b/arbnode/sync_monitor.go @@ -175,9 +175,13 @@ func (s *SyncMonitor) SafeBlockNumber(ctx context.Context) (uint64, error) { func (s *SyncMonitor) getLatestValidatedCount() (arbutil.MessageIndex, error) { latestValidatedGS := s.txStreamer.validator.GetLastValidated() - count, err := s.inboxReader.tracker.GetBatchMessageCount(latestValidatedGS.Batch - 1) - if err != nil { - return 0, err + var count arbutil.MessageIndex + var err error + if latestValidatedGS.Batch > 0 { + count, err = s.inboxReader.tracker.GetBatchMessageCount(latestValidatedGS.Batch - 1) + if err != nil { + return 0, err + } } count += arbutil.MessageIndex(latestValidatedGS.PosInBatch) return count, nil From 38fb7dc974c5020ecc6c6f613d074bfdd96cfddb Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 6 Feb 2024 22:21:49 +0530 Subject: [PATCH 728/775] Changes based on PR comments --- arbnode/sync_monitor.go | 13 +++---------- staker/block_validator.go | 8 ++++---- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/arbnode/sync_monitor.go b/arbnode/sync_monitor.go index 24b00a4af..99a66abde 100644 --- a/arbnode/sync_monitor.go +++ b/arbnode/sync_monitor.go @@ -174,17 +174,10 @@ func (s *SyncMonitor) SafeBlockNumber(ctx context.Context) (uint64, error) { } func (s *SyncMonitor) getLatestValidatedCount() (arbutil.MessageIndex, error) { - latestValidatedGS := s.txStreamer.validator.GetLastValidated() - var count arbutil.MessageIndex - var err error - if latestValidatedGS.Batch > 0 { - count, err = s.inboxReader.tracker.GetBatchMessageCount(latestValidatedGS.Batch - 1) - if err != nil { - return 0, err - } + if s.txStreamer.validator == nil { + return 0, errors.New("validator not set up") } - count += arbutil.MessageIndex(latestValidatedGS.PosInBatch) - return count, nil + return s.txStreamer.validator.GetValidated(), nil } func (s *SyncMonitor) FinalizedBlockNumber(ctx context.Context) (uint64, error) { diff --git a/staker/block_validator.go b/staker/block_validator.go index 4ab31c852..03d216654 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -1209,8 +1209,8 @@ func (v *BlockValidator) WaitForPos(t *testing.T, ctx context.Context, pos arbut } } -func (v *BlockValidator) GetLastValidated() validator.GoGlobalState { - v.reorgMutex.Lock() - defer v.reorgMutex.Unlock() - return v.lastValidGS +func (v *BlockValidator) GetValidated() arbutil.MessageIndex { + v.reorgMutex.RLock() + defer v.reorgMutex.RUnlock() + return v.validated() } From be921962b76b71e615b088b3aba2d3c6462384a7 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 6 Feb 2024 12:04:17 -0600 Subject: [PATCH 729/775] Bump go-ethereum submodule pin to latest master --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index a0685a71f..36cc85793 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit a0685a71f31c14f414c01cb5c7c91170fd0e84be +Subproject commit 36cc85793228ad142923402b969fd489c02db2a5 From 3bce233ceed826f8ea9e1aed18bde34271721efd Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 6 Feb 2024 14:36:04 -0600 Subject: [PATCH 730/775] address PR comments --- arbnode/inbox_reader.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arbnode/inbox_reader.go b/arbnode/inbox_reader.go index f452b0d89..7b6b96d43 100644 --- a/arbnode/inbox_reader.go +++ b/arbnode/inbox_reader.go @@ -40,11 +40,9 @@ func (c *InboxReaderConfig) Validate() error { if c.MaxBlocksToRead == 0 || c.MaxBlocksToRead < c.DefaultBlocksToRead { return errors.New("inbox reader max-blocks-to-read cannot be zero or less than default-blocks-to-read") } - if c.ReadMode != "latest" { - c.ReadMode = strings.ToLower(c.ReadMode) - if c.ReadMode != "safe" && c.ReadMode != "finalized" { - return fmt.Errorf("inbox reader read-mode is invalid, want: safe or finalized, got: %s", c.ReadMode) - } + c.ReadMode = strings.ToLower(c.ReadMode) + if c.ReadMode != "latest" && c.ReadMode != "safe" && c.ReadMode != "finalized" { + return fmt.Errorf("inbox reader read-mode is invalid, want: latest or safe or finalized, got: %s", c.ReadMode) } return nil } @@ -57,7 +55,7 @@ func InboxReaderConfigAddOptions(prefix string, f *flag.FlagSet) { f.Uint64(prefix+".default-blocks-to-read", DefaultInboxReaderConfig.DefaultBlocksToRead, "the default number of blocks to read at once (will vary based on traffic by default)") f.Uint64(prefix+".target-messages-read", DefaultInboxReaderConfig.TargetMessagesRead, "if adjust-blocks-to-read is enabled, the target number of messages to read at once") f.Uint64(prefix+".max-blocks-to-read", DefaultInboxReaderConfig.MaxBlocksToRead, "if adjust-blocks-to-read is enabled, the maximum number of blocks to read at once") - f.String(prefix+".read-mode", DefaultInboxReaderConfig.ReadMode, "mode to only read safe or finalized L1 blocks. Takes string input, valid strings- safe, finalized") + f.String(prefix+".read-mode", DefaultInboxReaderConfig.ReadMode, "mode to only read latest or safe or finalized L1 blocks. Enabling safe or finalized disables feed input and output. Defaults to latest. Takes string input, valid strings- latest, safe, finalized") } var DefaultInboxReaderConfig = InboxReaderConfig{ From 668393b744afc490a37f27fa8e78c4e79c9875ae Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 7 Feb 2024 19:57:59 -0600 Subject: [PATCH 731/775] Produce better error messages when failing to read the delayed inbox --- arbnode/delayed.go | 4 ++-- arbnode/inbox_tracker.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arbnode/delayed.go b/arbnode/delayed.go index 2a1745c54..c166aa2b9 100644 --- a/arbnode/delayed.go +++ b/arbnode/delayed.go @@ -221,10 +221,10 @@ func (b *DelayedBridge) logsToDeliveredMessages(ctx context.Context, logs []type msgKey := common.BigToHash(parsedLog.MessageIndex) data, ok := messageData[msgKey] if !ok { - return nil, errors.New("message not found") + return nil, fmt.Errorf("message %v data not found", parsedLog.MessageIndex) } if crypto.Keccak256Hash(data) != parsedLog.MessageDataHash { - return nil, errors.New("found message data with mismatched hash") + return nil, fmt.Errorf("found message %v data with mismatched hash", parsedLog.MessageIndex) } requestId := common.BigToHash(parsedLog.MessageIndex) diff --git a/arbnode/inbox_tracker.go b/arbnode/inbox_tracker.go index eaf863bff..763ddcc42 100644 --- a/arbnode/inbox_tracker.go +++ b/arbnode/inbox_tracker.go @@ -374,11 +374,11 @@ func (t *InboxTracker) AddDelayedMessages(messages []*DelayedInboxMessage, hardR } if seqNum != pos { - return errors.New("unexpected delayed sequence number") + return fmt.Errorf("unexpected delayed sequence number %v, expected %v", seqNum, pos) } if nextAcc != message.BeforeInboxAcc { - return errors.New("previous delayed accumulator mismatch") + return fmt.Errorf("previous delayed accumulator mismatch for message %v", seqNum) } nextAcc = message.AfterInboxAcc() From cf2c513f2cf68a2c4ba251a4a515d053a9e2d0b3 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 8 Feb 2024 19:47:41 -0800 Subject: [PATCH 732/775] Gate 4844 Batch Posting on ArbOS 20 Plumb ExecutionEngine to BatchPoster as the ArbOSVersionGetter interface so that it can post 4844 batches for only ArbOS 20 and above. BatchPoster finds if ArbOS 20 or greater was already enabled as of MessageIndex of the first message in the batch using the ArbOSVersionGetter interface. --- arbnode/batch_poster.go | 92 +++++++++++++++------------ arbnode/node.go | 5 +- execution/gethexec/executionengine.go | 11 +++- system_tests/batch_poster_test.go | 1 + 4 files changed, 67 insertions(+), 42 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index e3af0b2af..b617adcf3 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -71,24 +71,29 @@ type batchPosterPosition struct { NextSeqNum uint64 } +type ArbOSVersionGetter interface { + ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) +} + type BatchPoster struct { stopwaiter.StopWaiter - l1Reader *headerreader.HeaderReader - inbox *InboxTracker - streamer *TransactionStreamer - config BatchPosterConfigFetcher - seqInbox *bridgegen.SequencerInbox - bridge *bridgegen.Bridge - syncMonitor *SyncMonitor - seqInboxABI *abi.ABI - seqInboxAddr common.Address - bridgeAddr common.Address - gasRefunderAddr common.Address - building *buildingBatch - daWriter das.DataAvailabilityServiceWriter - dataPoster *dataposter.DataPoster - redisLock *redislock.Simple - messagesPerBatch *arbmath.MovingAverage[uint64] + l1Reader *headerreader.HeaderReader + inbox *InboxTracker + streamer *TransactionStreamer + arbOSVersionGetter ArbOSVersionGetter + config BatchPosterConfigFetcher + seqInbox *bridgegen.SequencerInbox + bridge *bridgegen.Bridge + syncMonitor *SyncMonitor + seqInboxABI *abi.ABI + seqInboxAddr common.Address + bridgeAddr common.Address + gasRefunderAddr common.Address + building *buildingBatch + daWriter das.DataAvailabilityServiceWriter + dataPoster *dataposter.DataPoster + redisLock *redislock.Simple + messagesPerBatch *arbmath.MovingAverage[uint64] // This is an atomic variable that should only be accessed atomically. // An estimate of the number of batches we want to post but haven't yet. // This doesn't include batches which we don't want to post yet due to the L1 bounds. @@ -174,7 +179,7 @@ type BatchPosterConfigFetcher func() *BatchPosterConfig func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Bool(prefix+".enable", DefaultBatchPosterConfig.Enable, "enable posting batches to l1") - f.Bool(prefix+".disable-das-fallback-store-data-on-chain", DefaultBatchPosterConfig.DisableDasFallbackStoreDataOnChain, "If unable to batch to DAS, disable fallback storing data on chain") + f.Bool(prefix+".disable-das-fallback-store-data-on-chain", DefaultBatchPosterConfig.DisableDasFallbackStoreDataOnChain, "If unable to batch to AS, disable fallback storing data on chain") f.Int(prefix+".max-size", DefaultBatchPosterConfig.MaxSize, "maximum batch size") f.Int(prefix+".max-4844-batch-size", DefaultBatchPosterConfig.Max4844BatchSize, "maximum 4844 blob enabled batch size") f.Duration(prefix+".max-delay", DefaultBatchPosterConfig.MaxDelay, "maximum batch posting delay") @@ -255,6 +260,7 @@ type BatchPosterOpts struct { L1Reader *headerreader.HeaderReader Inbox *InboxTracker Streamer *TransactionStreamer + VersionGetter ArbOSVersionGetter SyncMonitor *SyncMonitor Config BatchPosterConfigFetcher DeployInfo *chaininfo.RollupAddresses @@ -293,19 +299,20 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e return nil, err } b := &BatchPoster{ - l1Reader: opts.L1Reader, - inbox: opts.Inbox, - streamer: opts.Streamer, - syncMonitor: opts.SyncMonitor, - config: opts.Config, - bridge: bridge, - seqInbox: seqInbox, - seqInboxABI: seqInboxABI, - seqInboxAddr: opts.DeployInfo.SequencerInbox, - gasRefunderAddr: opts.Config().gasRefunder, - bridgeAddr: opts.DeployInfo.Bridge, - daWriter: opts.DAWriter, - redisLock: redisLock, + l1Reader: opts.L1Reader, + inbox: opts.Inbox, + streamer: opts.Streamer, + arbOSVersionGetter: opts.VersionGetter, + syncMonitor: opts.SyncMonitor, + config: opts.Config, + bridge: bridge, + seqInbox: seqInbox, + seqInboxABI: seqInboxABI, + seqInboxAddr: opts.DeployInfo.SequencerInbox, + gasRefunderAddr: opts.Config().gasRefunder, + bridgeAddr: opts.DeployInfo.Bridge, + daWriter: opts.DAWriter, + redisLock: redisLock, } b.messagesPerBatch, err = arbmath.NewMovingAverage[uint64](20) if err != nil { @@ -956,17 +963,24 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) var use4844 bool config := b.config() if config.Post4844Blobs && latestHeader.ExcessBlobGas != nil && latestHeader.BlobGasUsed != nil { - if config.ForcePost4844Blobs { - use4844 = true - } else { - blobFeePerByte := eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*latestHeader.ExcessBlobGas, *latestHeader.BlobGasUsed)) - blobFeePerByte.Mul(blobFeePerByte, blobTxBlobGasPerBlob) - blobFeePerByte.Div(blobFeePerByte, usableBytesInBlob) - - calldataFeePerByte := arbmath.BigMulByUint(latestHeader.BaseFee, 16) - use4844 = arbmath.BigLessThan(blobFeePerByte, calldataFeePerByte) + arbOSVersion, err := b.arbOSVersionGetter.ArbOSVersionForMessageNumber(batchPosition.MessageCount) + if err != nil { + return false, err + } + if arbOSVersion >= 20 { + if config.ForcePost4844Blobs { + use4844 = true + } else { + blobFeePerByte := eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*latestHeader.ExcessBlobGas, *latestHeader.BlobGasUsed)) + blobFeePerByte.Mul(blobFeePerByte, blobTxBlobGasPerBlob) + blobFeePerByte.Div(blobFeePerByte, usableBytesInBlob) + + calldataFeePerByte := arbmath.BigMulByUint(latestHeader.BaseFee, 16) + use4844 = arbmath.BigLessThan(blobFeePerByte, calldataFeePerByte) + } } } + b.building = &buildingBatch{ segments: newBatchSegments(batchPosition.DelayedMessageCount, b.config(), b.GetBacklogEstimate(), use4844), msgCount: batchPosition.MessageCount, diff --git a/arbnode/node.go b/arbnode/node.go index de9745f2a..24d929896 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -341,7 +341,7 @@ func StakerDataposter( func createNodeImpl( ctx context.Context, stack *node.Node, - exec execution.FullExecutionClient, + exec *gethexec.ExecutionNode, arbDb ethdb.Database, configFetcher ConfigFetcher, l2Config *params.ChainConfig, @@ -654,6 +654,7 @@ func createNodeImpl( L1Reader: l1Reader, Inbox: inboxTracker, Streamer: txStreamer, + VersionGetter: exec.ExecEngine, SyncMonitor: syncMonitor, Config: func() *BatchPosterConfig { return &configFetcher.Get().BatchPoster }, DeployInfo: deployInfo, @@ -707,7 +708,7 @@ func (n *Node) OnConfigReload(_ *Config, _ *Config) error { func CreateNode( ctx context.Context, stack *node.Node, - exec execution.FullExecutionClient, + exec *gethexec.ExecutionNode, arbDb ethdb.Database, configFetcher ConfigFetcher, l2Config *params.ChainConfig, diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 003159589..a662de362 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -101,7 +101,7 @@ func (s *ExecutionEngine) Reorg(count arbutil.MessageIndex, newMessages []arbost resequencing := false defer func() { // if we are resequencing old messages - don't release the lock - // lock will be relesed by thread listening to resequenceChan + // lock will be released by thread listening to resequenceChan if !resequencing { s.createBlocksMutex.Unlock() } @@ -601,6 +601,15 @@ func (s *ExecutionEngine) digestMessageWithBlockMutex(num arbutil.MessageIndex, return nil } +func (s *ExecutionEngine) ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) { + block := s.bc.GetBlockByNumber(s.MessageIndexToBlockNumber(messageNum)) + if block == nil { + return 0, fmt.Errorf("couldn't find block for message number %d", messageNum) + } + extra := types.DeserializeHeaderExtraInformation(block.Header()) + return extra.ArbOSFormatVersion, nil +} + func (s *ExecutionEngine) Start(ctx_in context.Context) { s.StopWaiter.Start(ctx_in, s) s.LaunchThread(func(ctx context.Context) { diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index cacbe3cee..4a62e438a 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -166,6 +166,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { L1Reader: builder.L2.ConsensusNode.L1Reader, Inbox: builder.L2.ConsensusNode.InboxTracker, Streamer: builder.L2.ConsensusNode.TxStreamer, + VersionGetter: builder.L2.ExecNode.ExecEngine, SyncMonitor: builder.L2.ConsensusNode.SyncMonitor, Config: func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, DeployInfo: builder.L2.ConsensusNode.DeployInfo, From b8e5ed4a6b4b9e35eb60d5fa2147a1c6915fd506 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 9 Feb 2024 19:21:56 +0530 Subject: [PATCH 733/775] Move Prefetch flag from sequencer to execution node --- execution/gethexec/node.go | 6 ++++++ execution/gethexec/sequencer.go | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 1ad73febe..fc415c2ef 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -50,6 +50,7 @@ type Config struct { RPC arbitrum.Config `koanf:"rpc"` TxLookupLimit uint64 `koanf:"tx-lookup-limit"` Dangerous DangerousConfig `koanf:"dangerous"` + EnablePrefetchBlock bool `koanf:"enable-prefetch-block"` forwardingTarget string } @@ -84,6 +85,7 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { CachingConfigAddOptions(prefix+".caching", 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") } var ConfigDefault = Config{ @@ -98,6 +100,7 @@ var ConfigDefault = Config{ Caching: DefaultCachingConfig, Dangerous: DefaultDangerousConfig, Forwarder: DefaultNodeForwarderConfig, + EnablePrefetchBlock: true, } func ConfigDefaultNonSequencerTest() *Config { @@ -149,6 +152,9 @@ func CreateExecutionNode( ) (*ExecutionNode, error) { config := configFetcher() execEngine, err := NewExecutionEngine(l2BlockChain) + if config.EnablePrefetchBlock { + execEngine.EnablePrefetchBlock() + } if err != nil { return nil, err } diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 9bc6f4378..43856cd3c 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -98,7 +98,6 @@ var DefaultSequencerConfig = SequencerConfig{ MaxTxDataSize: 95000, NonceFailureCacheSize: 1024, NonceFailureCacheExpiry: time.Second, - EnablePrefetchBlock: false, } var TestSequencerConfig = SequencerConfig{ @@ -114,7 +113,6 @@ var TestSequencerConfig = SequencerConfig{ MaxTxDataSize: 95000, NonceFailureCacheSize: 1024, NonceFailureCacheExpiry: time.Second, - EnablePrefetchBlock: false, } func SequencerConfigAddOptions(prefix string, f *flag.FlagSet) { @@ -130,7 +128,6 @@ func SequencerConfigAddOptions(prefix string, f *flag.FlagSet) { f.Int(prefix+".max-tx-data-size", DefaultSequencerConfig.MaxTxDataSize, "maximum transaction size the sequencer will accept") f.Int(prefix+".nonce-failure-cache-size", DefaultSequencerConfig.NonceFailureCacheSize, "number of transactions with too high of a nonce to keep in memory while waiting for their predecessor") f.Duration(prefix+".nonce-failure-cache-expiry", DefaultSequencerConfig.NonceFailureCacheExpiry, "maximum amount of time to wait for a predecessor before rejecting a tx with nonce too high") - f.Bool(prefix+".enable-prefetch-block", DefaultSequencerConfig.EnablePrefetchBlock, "enable prefetching of blocks") } type txQueueItem struct { @@ -328,9 +325,6 @@ func NewSequencer(execEngine *ExecutionEngine, l1Reader *headerreader.HeaderRead } s.Pause() execEngine.EnableReorgSequencing() - if config.EnablePrefetchBlock { - execEngine.EnablePrefetchBlock() - } return s, nil } From ae0d7c65e1059cb7c53ebad5c21ac4e6241f6f84 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 9 Feb 2024 19:38:48 +0530 Subject: [PATCH 734/775] Minor fix --- execution/gethexec/sequencer.go | 1 - 1 file changed, 1 deletion(-) diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 43856cd3c..5db38cbb4 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -66,7 +66,6 @@ type SequencerConfig struct { MaxTxDataSize int `koanf:"max-tx-data-size" reload:"hot"` NonceFailureCacheSize int `koanf:"nonce-failure-cache-size" reload:"hot"` NonceFailureCacheExpiry time.Duration `koanf:"nonce-failure-cache-expiry" reload:"hot"` - EnablePrefetchBlock bool `koanf:"enable-prefetch-block"` } func (c *SequencerConfig) Validate() error { From 56f355a48f268d2335325f5373e226a79cf37647 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Fri, 9 Feb 2024 15:43:48 +0100 Subject: [PATCH 735/775] Startup nitro-testnode in release CI --- .github/workflows/release-ci.yml | 3 +++ scripts/startup-testnode.bash | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100755 scripts/startup-testnode.bash diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index 036bf4653..1084d1f8b 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -25,3 +25,6 @@ jobs: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ hashFiles('Dockerfile') }} restore-keys: ${{ runner.os }}-buildx- + + - name: Startup Nitro testnode + run: .scripts/startup-testnode.bash diff --git a/scripts/startup-testnode.bash b/scripts/startup-testnode.bash new file mode 100755 index 000000000..701e7ff59 --- /dev/null +++ b/scripts/startup-testnode.bash @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# The script starts up the test node (with timeout 1 minute), to make sure the +# nitro-testnode script isn't out of sync with flags with nitro. +# This is used in CI, basically as smoke test. + +timeout 60 ./nitro-testnode/test-node.bash --init --dev || exit_status=$? + +if [ -n "$exit_status" ] && [ $exit_status -ne 0 ] && [ $exit_status -ne 124 ]; then + echo "Startup failed." + exit $exit_status +fi + +echo "Startup succeeded." From b658c0975f4471e57dc7db7e28529c1ba6580f32 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Fri, 9 Feb 2024 15:50:30 +0100 Subject: [PATCH 736/775] Fix typo --- .github/workflows/release-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index 1084d1f8b..5282510e8 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -27,4 +27,4 @@ jobs: restore-keys: ${{ runner.os }}-buildx- - name: Startup Nitro testnode - run: .scripts/startup-testnode.bash + run: ./scripts/startup-testnode.bash From f271c1725ee59cb60af7f600011aa3f65ec7261c Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Fri, 9 Feb 2024 10:46:05 -0600 Subject: [PATCH 737/775] minor fix --- cmd/nitro/nitro.go | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index e4c33ac03..9de981731 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -689,28 +689,29 @@ type NodeConfig struct { } var NodeConfigDefault = NodeConfig{ - Conf: genericconf.ConfConfigDefault, - Node: arbnode.ConfigDefault, - Execution: gethexec.ConfigDefault, - Validation: valnode.DefaultValidationConfig, - ParentChain: conf.L1ConfigDefault, - Chain: conf.L2ConfigDefault, - LogLevel: int(log.LvlInfo), - LogType: "plaintext", - FileLogging: genericconf.DefaultFileLoggingConfig, - Persistent: conf.PersistentConfigDefault, - HTTP: genericconf.HTTPConfigDefault, - WS: genericconf.WSConfigDefault, - IPC: genericconf.IPCConfigDefault, - Auth: genericconf.AuthRPCConfigDefault, - GraphQL: genericconf.GraphQLConfigDefault, - P2P: genericconf.P2PConfigDefault, - Metrics: false, - MetricsServer: genericconf.MetricsServerConfigDefault, - Init: conf.InitConfigDefault, - Rpc: genericconf.DefaultRpcConfig, - PProf: false, - PprofCfg: genericconf.PProfDefault, + Conf: genericconf.ConfConfigDefault, + Node: arbnode.ConfigDefault, + Execution: gethexec.ConfigDefault, + Validation: valnode.DefaultValidationConfig, + ParentChain: conf.L1ConfigDefault, + Chain: conf.L2ConfigDefault, + LogLevel: int(log.LvlInfo), + LogType: "plaintext", + FileLogging: genericconf.DefaultFileLoggingConfig, + Persistent: conf.PersistentConfigDefault, + HTTP: genericconf.HTTPConfigDefault, + WS: genericconf.WSConfigDefault, + IPC: genericconf.IPCConfigDefault, + Auth: genericconf.AuthRPCConfigDefault, + GraphQL: genericconf.GraphQLConfigDefault, + P2P: genericconf.P2PConfigDefault, + Metrics: false, + MetricsServer: genericconf.MetricsServerConfigDefault, + Init: conf.InitConfigDefault, + Rpc: genericconf.DefaultRpcConfig, + PProf: false, + PprofCfg: genericconf.PProfDefault, + BlocksReExecutor: blocksreexecutor.DefaultConfig, } func NodeConfigAddOptions(f *flag.FlagSet) { From 97638718755fd063934b04bc2e9757bbf5769772 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 9 Feb 2024 17:39:43 -0800 Subject: [PATCH 738/775] Fix batch msg arbos version check off by 1 batchPosterPosition.MessageCount is the count of messages, therefore it is the index of the next message that may not exist yet. --- arbnode/batch_poster.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index b617adcf3..6c2f352b2 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -954,7 +954,6 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) if dbBatchCount > batchPosition.NextSeqNum { return false, fmt.Errorf("attempting to post batch %v, but the local inbox tracker database already has %v batches", batchPosition.NextSeqNum, dbBatchCount) } - if b.building == nil || b.building.startMsgCount != batchPosition.MessageCount { latestHeader, err := b.l1Reader.LastHeader(ctx) if err != nil { @@ -963,7 +962,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) var use4844 bool config := b.config() if config.Post4844Blobs && latestHeader.ExcessBlobGas != nil && latestHeader.BlobGasUsed != nil { - arbOSVersion, err := b.arbOSVersionGetter.ArbOSVersionForMessageNumber(batchPosition.MessageCount) + arbOSVersion, err := b.arbOSVersionGetter.ArbOSVersionForMessageNumber(arbutil.MessageIndex(arbmath.SaturatingUSub(uint64(batchPosition.MessageCount), 1))) if err != nil { return false, err } From 9964983f30573681aeb523c177d12a676cc7b048 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Fri, 9 Feb 2024 17:57:33 -0800 Subject: [PATCH 739/775] Fix stray edit --- arbnode/batch_poster.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 6c2f352b2..317c74be6 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -179,7 +179,7 @@ type BatchPosterConfigFetcher func() *BatchPosterConfig func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Bool(prefix+".enable", DefaultBatchPosterConfig.Enable, "enable posting batches to l1") - f.Bool(prefix+".disable-das-fallback-store-data-on-chain", DefaultBatchPosterConfig.DisableDasFallbackStoreDataOnChain, "If unable to batch to AS, disable fallback storing data on chain") + f.Bool(prefix+".disable-das-fallback-store-data-on-chain", DefaultBatchPosterConfig.DisableDasFallbackStoreDataOnChain, "If unable to batch to DAS, disable fallback storing data on chain") f.Int(prefix+".max-size", DefaultBatchPosterConfig.MaxSize, "maximum batch size") f.Int(prefix+".max-4844-batch-size", DefaultBatchPosterConfig.Max4844BatchSize, "maximum 4844 blob enabled batch size") f.Duration(prefix+".max-delay", DefaultBatchPosterConfig.MaxDelay, "maximum batch posting delay") From 5b2e861929d94b8e2b562ede38890308b75b8b1b Mon Sep 17 00:00:00 2001 From: amsanghi Date: Mon, 12 Feb 2024 19:15:48 +0530 Subject: [PATCH 740/775] Test INVALID opcode (using withdrawEth) in the flatCallTracer --- go-ethereum | 2 +- system_tests/debugapi_test.go | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 36cc85793..efaa6d0eb 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 36cc85793228ad142923402b969fd489c02db2a5 +Subproject commit efaa6d0eb73bbb6ac4c5436d68eb5140aca6a0d2 diff --git a/system_tests/debugapi_test.go b/system_tests/debugapi_test.go index 4568e2809..dfe42e691 100644 --- a/system_tests/debugapi_test.go +++ b/system_tests/debugapi_test.go @@ -4,10 +4,14 @@ import ( "context" "testing" + "encoding/json" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/rpc" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" ) func TestDebugAPI(t *testing.T) { @@ -35,4 +39,18 @@ func TestDebugAPI(t *testing.T) { err = l2rpc.CallContext(ctx, &dumpIt, "debug_accountRange", rpc.PendingBlockNumber, hexutil.Bytes{}, 10, true, true, false) Require(t, err) + arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, builder.L2.Client) + Require(t, err) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + tx, err := arbSys.WithdrawEth(&auth, common.Address{}) + Require(t, err) + receipt, err := builder.L2.EnsureTxSucceeded(tx) + Require(t, err) + if len(receipt.Logs) != 1 { + Fatal(t, "Unexpected number of logs", len(receipt.Logs)) + } + + var result json.RawMessage + err = l2rpc.CallContext(ctx, &result, "debug_traceTransaction", tx.Hash(), "{\"tracer\": \"flatCallTracer\"}") + Require(t, err) } From 7fc2f7659dfba923954407bb28090543ad5c1b5f Mon Sep 17 00:00:00 2001 From: amsanghi Date: Mon, 12 Feb 2024 19:34:57 +0530 Subject: [PATCH 741/775] Minor fix --- system_tests/debugapi_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system_tests/debugapi_test.go b/system_tests/debugapi_test.go index dfe42e691..52a6bb25c 100644 --- a/system_tests/debugapi_test.go +++ b/system_tests/debugapi_test.go @@ -2,6 +2,7 @@ package arbtest import ( "context" + "github.com/ethereum/go-ethereum/eth/tracers" "testing" "encoding/json" @@ -51,6 +52,7 @@ func TestDebugAPI(t *testing.T) { } var result json.RawMessage - err = l2rpc.CallContext(ctx, &result, "debug_traceTransaction", tx.Hash(), "{\"tracer\": \"flatCallTracer\"}") + flatCallTracer := "flatCallTracer" + err = l2rpc.CallContext(ctx, &result, "debug_traceTransaction", tx.Hash(), &tracers.TraceConfig{Tracer: &flatCallTracer}) Require(t, err) } From f81d226b871df8eb5ddbc8e756641a5764c73254 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Tue, 13 Feb 2024 14:43:59 -0800 Subject: [PATCH 742/775] Move ArbOSVersionForMessageNumber --- arbnode/batch_poster.go | 9 +++------ arbnode/node.go | 6 +++--- execution/gethexec/node.go | 3 +++ execution/interface.go | 2 ++ system_tests/batch_poster_test.go | 2 +- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 317c74be6..3b4f36dfc 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -41,6 +41,7 @@ import ( "github.com/offchainlabs/nitro/cmd/chaininfo" "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/das" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/util" "github.com/offchainlabs/nitro/util/arbmath" @@ -71,16 +72,12 @@ type batchPosterPosition struct { NextSeqNum uint64 } -type ArbOSVersionGetter interface { - ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) -} - type BatchPoster struct { stopwaiter.StopWaiter l1Reader *headerreader.HeaderReader inbox *InboxTracker streamer *TransactionStreamer - arbOSVersionGetter ArbOSVersionGetter + arbOSVersionGetter execution.FullExecutionClient config BatchPosterConfigFetcher seqInbox *bridgegen.SequencerInbox bridge *bridgegen.Bridge @@ -260,7 +257,7 @@ type BatchPosterOpts struct { L1Reader *headerreader.HeaderReader Inbox *InboxTracker Streamer *TransactionStreamer - VersionGetter ArbOSVersionGetter + VersionGetter execution.FullExecutionClient SyncMonitor *SyncMonitor Config BatchPosterConfigFetcher DeployInfo *chaininfo.RollupAddresses diff --git a/arbnode/node.go b/arbnode/node.go index b1e215c79..e87a6dda7 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -348,7 +348,7 @@ func StakerDataposter( func createNodeImpl( ctx context.Context, stack *node.Node, - exec *gethexec.ExecutionNode, + exec execution.FullExecutionClient, arbDb ethdb.Database, configFetcher ConfigFetcher, l2Config *params.ChainConfig, @@ -661,7 +661,7 @@ func createNodeImpl( L1Reader: l1Reader, Inbox: inboxTracker, Streamer: txStreamer, - VersionGetter: exec.ExecEngine, + VersionGetter: exec, SyncMonitor: syncMonitor, Config: func() *BatchPosterConfig { return &configFetcher.Get().BatchPoster }, DeployInfo: deployInfo, @@ -715,7 +715,7 @@ func (n *Node) OnConfigReload(_ *Config, _ *Config) error { func CreateNode( ctx context.Context, stack *node.Node, - exec *gethexec.ExecutionNode, + exec execution.FullExecutionClient, arbDb ethdb.Database, configFetcher ConfigFetcher, l2Config *params.ChainConfig, diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 1ad73febe..49e2d10e2 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -332,6 +332,9 @@ func (n *ExecutionNode) SequenceDelayedMessage(message *arbostypes.L1IncomingMes func (n *ExecutionNode) ResultAtPos(pos arbutil.MessageIndex) (*execution.MessageResult, error) { return n.ExecEngine.ResultAtPos(pos) } +func (n *ExecutionNode) ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) { + return n.ExecEngine.ArbOSVersionForMessageNumber(messageNum) +} func (n *ExecutionNode) RecordBlockCreation( ctx context.Context, diff --git a/execution/interface.go b/execution/interface.go index 6761011a7..2cbbf550a 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -69,6 +69,8 @@ type FullExecutionClient interface { // TODO: only used to get safe/finalized block numbers MessageIndexToBlockNumber(messageNum arbutil.MessageIndex) uint64 + + ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) } // not implemented in execution, used as input diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 4a62e438a..68dea4167 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -166,7 +166,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { L1Reader: builder.L2.ConsensusNode.L1Reader, Inbox: builder.L2.ConsensusNode.InboxTracker, Streamer: builder.L2.ConsensusNode.TxStreamer, - VersionGetter: builder.L2.ExecNode.ExecEngine, + VersionGetter: builder.L2.ExecNode, SyncMonitor: builder.L2.ConsensusNode.SyncMonitor, Config: func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, DeployInfo: builder.L2.ConsensusNode.DeployInfo, From 2f07c6475e82e8def1cd1bc307f9f6098d79bb9c Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Tue, 13 Feb 2024 17:12:33 -0800 Subject: [PATCH 743/775] Rename force-post-4844-blobs opt ignore-blob-price --- arbnode/batch_poster.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 3b4f36dfc..e09775ea4 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -138,7 +138,7 @@ type BatchPosterConfig struct { RedisLock redislock.SimpleCfg `koanf:"redis-lock" reload:"hot"` ExtraBatchGas uint64 `koanf:"extra-batch-gas" reload:"hot"` Post4844Blobs bool `koanf:"post-4844-blobs" reload:"hot"` - ForcePost4844Blobs bool `koanf:"force-post-4844-blobs" reload:"hot"` + IgnoreBlobPrice bool `koanf:"ignore-blob-price" reload:"hot"` ParentChainWallet genericconf.WalletConfig `koanf:"parent-chain-wallet"` L1BlockBound string `koanf:"l1-block-bound" reload:"hot"` L1BlockBoundBypass time.Duration `koanf:"l1-block-bound-bypass" reload:"hot"` @@ -188,7 +188,7 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".gas-refunder-address", DefaultBatchPosterConfig.GasRefunderAddress, "The gas refunder contract address (optional)") f.Uint64(prefix+".extra-batch-gas", DefaultBatchPosterConfig.ExtraBatchGas, "use this much more gas than estimation says is necessary to post batches") f.Bool(prefix+".post-4844-blobs", DefaultBatchPosterConfig.Post4844Blobs, "if the parent chain supports 4844 blobs and they're well priced, post EIP-4844 blobs") - f.Bool(prefix+".force-post-4844-blobs", DefaultBatchPosterConfig.ForcePost4844Blobs, "if the parent chain supports 4844 blobs and post-4844-blobs is true, post 4844 blobs even if it's not price efficient") + f.Bool(prefix+".ignore-blob-price", DefaultBatchPosterConfig.IgnoreBlobPrice, "if the parent chain supports 4844 blobs and ignore-blob-price is true, post 4844 blobs even if it's not price efficient") f.String(prefix+".redis-url", DefaultBatchPosterConfig.RedisUrl, "if non-empty, the Redis URL to store queued transactions in") f.String(prefix+".l1-block-bound", DefaultBatchPosterConfig.L1BlockBound, "only post messages to batches when they're within the max future block/timestamp as of this L1 block tag (\"safe\", \"finalized\", \"latest\", or \"ignore\" to ignore this check)") f.Duration(prefix+".l1-block-bound-bypass", DefaultBatchPosterConfig.L1BlockBoundBypass, "post batches even if not within the layer 1 future bounds if we're within this margin of the max delay") @@ -214,7 +214,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ GasRefunderAddress: "", ExtraBatchGas: 50_000, Post4844Blobs: false, - ForcePost4844Blobs: false, + IgnoreBlobPrice: false, DataPoster: dataposter.DefaultDataPosterConfig, ParentChainWallet: DefaultBatchPosterL1WalletConfig, L1BlockBound: "", @@ -244,7 +244,7 @@ var TestBatchPosterConfig = BatchPosterConfig{ GasRefunderAddress: "", ExtraBatchGas: 10_000, Post4844Blobs: true, - ForcePost4844Blobs: false, + IgnoreBlobPrice: false, DataPoster: dataposter.TestDataPosterConfig, ParentChainWallet: DefaultBatchPosterL1WalletConfig, L1BlockBound: "", @@ -964,7 +964,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) return false, err } if arbOSVersion >= 20 { - if config.ForcePost4844Blobs { + if config.IgnoreBlobPrice { use4844 = true } else { blobFeePerByte := eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*latestHeader.ExcessBlobGas, *latestHeader.BlobGasUsed)) From 5f44856897a777f44d6bb450e65f05b74cc37cf7 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Wed, 14 Feb 2024 16:31:04 -0600 Subject: [PATCH 744/775] Add option to save arbitrum blobs to disk when they are fetched --- arbnode/blob_reader.go | 47 +++++++++++++++++++++++++++++--- arbnode/blob_reader_test.go | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 arbnode/blob_reader_test.go diff --git a/arbnode/blob_reader.go b/arbnode/blob_reader.go index 142428583..772638179 100644 --- a/arbnode/blob_reader.go +++ b/arbnode/blob_reader.go @@ -10,6 +10,7 @@ import ( "io" "net/http" "net/url" + "os" "path" "github.com/ethereum/go-ethereum/common" @@ -31,18 +32,24 @@ type BlobClient struct { // The genesis time time and seconds per slot won't change so only request them once. cachedGenesisTime uint64 cachedSecondsPerSlot uint64 + + // Directory to save the fetcehd blobs + blobDirectory string } type BlobClientConfig struct { BeaconChainUrl string `koanf:"beacon-chain-url"` + BlobDirectory string `koanf:"blob-directory"` } var DefaultBlobClientConfig = BlobClientConfig{ BeaconChainUrl: "", + BlobDirectory: "", } func BlobClientAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".beacon-chain-url", DefaultBlobClientConfig.BeaconChainUrl, "Beacon Chain url to use for fetching blobs") + f.String(prefix+".blob-directory", DefaultBlobClientConfig.BlobDirectory, "Full path of the directory to save fetched blobs") } func NewBlobClient(config BlobClientConfig, ec arbutil.L1Interface) (*BlobClient, error) { @@ -50,10 +57,20 @@ func NewBlobClient(config BlobClientConfig, ec arbutil.L1Interface) (*BlobClient if err != nil { return nil, fmt.Errorf("failed to parse beacon chain URL: %w", err) } + if _, err = os.Stat(config.BlobDirectory); err != nil { + if os.IsNotExist(err) { + if err = os.MkdirAll(config.BlobDirectory, os.ModePerm); err != nil { + return nil, fmt.Errorf("error creating blob directory: %v", err) + } + } else { + return nil, fmt.Errorf("invalid blob directory path: %v", err) + } + } return &BlobClient{ - ec: ec, - beaconUrl: beaconUrl, - httpClient: &http.Client{}, + ec: ec, + beaconUrl: beaconUrl, + httpClient: &http.Client{}, + blobDirectory: config.BlobDirectory, }, nil } @@ -178,9 +195,33 @@ func (b *BlobClient) blobSidecars(ctx context.Context, slot uint64, versionedHas } } + if b.blobDirectory != "" { + if err := saveBlobDataToDisk(response, slot, b.blobDirectory); err != nil { + return nil, err + } + } + return output, nil } +func saveBlobDataToDisk(response []blobResponseItem, slot uint64, blobDirectory string) error { + filePath := path.Join(blobDirectory, fmt.Sprint(slot)) + file, err := os.Create(filePath) + if err != nil { + return fmt.Errorf("could not create file to store fetched blobs") + } + full := fullResult[[]blobResponseItem]{Data: response} + fullbytes, err := json.Marshal(full) + if err != nil { + return fmt.Errorf("unable to marshal data into bytes while attempting to store fetched blobs") + } + if _, err := file.Write(fullbytes); err != nil { + return fmt.Errorf("failed to write blob data to disk") + } + file.Close() + return nil +} + type genesisResponse struct { GenesisTime jsonapi.Uint64String `json:"genesis_time"` // don't currently care about other fields, add if needed diff --git a/arbnode/blob_reader_test.go b/arbnode/blob_reader_test.go new file mode 100644 index 000000000..287f5fee0 --- /dev/null +++ b/arbnode/blob_reader_test.go @@ -0,0 +1,53 @@ +package arbnode + +import ( + "encoding/json" + "io" + "os" + "path" + "reflect" + "testing" + + "github.com/r3labs/diff/v3" +) + +func TestSaveBlobsToDisk(t *testing.T) { + response := []blobResponseItem{{ + BlockRoot: "a", + Index: 0, + Slot: 5, + BlockParentRoot: "a0", + ProposerIndex: 9, + Blob: []byte{1}, + KzgCommitment: []byte{1}, + KzgProof: []byte{1}, + }, { + BlockRoot: "a", + Index: 1, + Slot: 5, + BlockParentRoot: "a0", + ProposerIndex: 10, + Blob: []byte{2}, + KzgCommitment: []byte{2}, + KzgProof: []byte{2}, + }} + testDir := t.TempDir() + err := saveBlobDataToDisk(response, 5, testDir) + Require(t, err) + + filePath := path.Join(testDir, "5") + file, err := os.Open(filePath) + Require(t, err) + defer file.Close() + + data, err := io.ReadAll(file) + Require(t, err) + var full fullResult[[]blobResponseItem] + err = json.Unmarshal(data, &full) + Require(t, err) + if !reflect.DeepEqual(full.Data, response) { + changelog, err := diff.Diff(full.Data, response) + Require(t, err) + Fail(t, "blob data saved to disk does not match actual blob data", changelog) + } +} From e948f92a9e6b5479bd943a2540380e8ad180a3ed Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Wed, 14 Feb 2024 16:35:38 -0600 Subject: [PATCH 745/775] refactor --- arbnode/blob_reader.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/blob_reader.go b/arbnode/blob_reader.go index 772638179..3f7364227 100644 --- a/arbnode/blob_reader.go +++ b/arbnode/blob_reader.go @@ -60,10 +60,10 @@ func NewBlobClient(config BlobClientConfig, ec arbutil.L1Interface) (*BlobClient if _, err = os.Stat(config.BlobDirectory); err != nil { if os.IsNotExist(err) { if err = os.MkdirAll(config.BlobDirectory, os.ModePerm); err != nil { - return nil, fmt.Errorf("error creating blob directory: %v", err) + return nil, fmt.Errorf("error creating blob directory: %w", err) } } else { - return nil, fmt.Errorf("invalid blob directory path: %v", err) + return nil, fmt.Errorf("invalid blob directory path: %w", err) } } return &BlobClient{ From 15deba7ec808b96e6b736fd304e03064e96485ce Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 14 Feb 2024 21:07:53 -0600 Subject: [PATCH 746/775] Error if reading authenticated batch with unknown header bits --- arbstate/das_reader.go | 13 +++++++++++++ arbstate/inbox.go | 12 ++++++++++++ 2 files changed, 25 insertions(+) diff --git a/arbstate/das_reader.go b/arbstate/das_reader.go index 46d01b7bb..ab2f8a67c 100644 --- a/arbstate/das_reader.go +++ b/arbstate/das_reader.go @@ -46,10 +46,18 @@ const BlobHashesHeaderFlag byte = L1AuthenticatedMessageHeaderFlag | 0x10 // 0x5 // BrotliMessageHeaderByte indicates that the message is brotli-compressed. const BrotliMessageHeaderByte byte = 0 +// KnownHeaderBits is all header bits with known meaning to this nitro version +const KnownHeaderBits byte = DASMessageHeaderFlag | TreeDASMessageHeaderFlag | L1AuthenticatedMessageHeaderFlag | ZeroheavyMessageHeaderFlag | BlobHashesHeaderFlag | BrotliMessageHeaderByte + +// hasBits returns true if `checking` has all `bits` func hasBits(checking byte, bits byte) bool { return (checking & bits) == bits } +func IsL1AuthenticatedMessageHeaderByte(header byte) bool { + return hasBits(header, L1AuthenticatedMessageHeaderFlag) +} + func IsDASMessageHeaderByte(header byte) bool { return hasBits(header, DASMessageHeaderFlag) } @@ -70,6 +78,11 @@ func IsBrotliMessageHeaderByte(b uint8) bool { return b == BrotliMessageHeaderByte } +// IsKnownHeaderByte returns true if the supplied header byte has any unknown bits +func IsKnownHeaderByte(b uint8) bool { + return b&^KnownHeaderBits != 0 +} + type DataAvailabilityCertificate struct { KeysetHash [32]byte DataHash [32]byte diff --git a/arbstate/inbox.go b/arbstate/inbox.go index fcb1c1ebc..dafb0700b 100644 --- a/arbstate/inbox.go +++ b/arbstate/inbox.go @@ -19,6 +19,7 @@ import ( "github.com/ethereum/go-ethereum/rlp" "github.com/offchainlabs/nitro/arbcompress" + "github.com/offchainlabs/nitro/arbos/arbosState" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbos/l1pricing" "github.com/offchainlabs/nitro/arbutil" @@ -75,6 +76,14 @@ func parseSequencerMessage(ctx context.Context, batchNum uint64, batchBlockHash } payload := data[40:] + // Stage 0: Check if our node is out of date and we don't understand this batch type + // If the parent chain sequencer inbox smart contract authenticated this batch, + // an unknown header byte must mean that this node is out of date, + // because the smart contract understands the header byte and this node doesn't. + if len(payload) > 0 && IsL1AuthenticatedMessageHeaderByte(payload[0]) && !IsKnownHeaderByte(payload[0]) { + return nil, fmt.Errorf("%w: batch has unsupported authenticated header byte 0x%02x", arbosState.ErrFatalNodeOutOfDate, payload[0]) + } + // Stage 1: Extract the payload from any data availability header. // It's important that multiple DAS strategies can't both be invoked in the same batch, // as these headers are validated by the sequencer inbox and not other DASs. @@ -116,6 +125,9 @@ func parseSequencerMessage(ctx context.Context, batchNum uint64, batchBlockHash } } + // At this point, `payload` has not been validated by the sequencer inbox at all. + // It's not safe to trust any part of the payload from this point onwards. + // Stage 2: If enabled, decode the zero heavy payload (saves gas based on calldata charging). if len(payload) > 0 && IsZeroheavyEncodedHeaderByte(payload[0]) { pl, err := io.ReadAll(io.LimitReader(zeroheavy.NewZeroheavyDecoder(bytes.NewReader(payload[1:])), int64(maxZeroheavyDecompressedLen))) From edc5b32fa50059ea9459a0b80a44cee2a1fbd7ee Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Wed, 14 Feb 2024 21:35:16 -0600 Subject: [PATCH 747/775] bug fix --- arbnode/blob_reader.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arbnode/blob_reader.go b/arbnode/blob_reader.go index 3f7364227..c2d2121be 100644 --- a/arbnode/blob_reader.go +++ b/arbnode/blob_reader.go @@ -57,13 +57,15 @@ func NewBlobClient(config BlobClientConfig, ec arbutil.L1Interface) (*BlobClient if err != nil { return nil, fmt.Errorf("failed to parse beacon chain URL: %w", err) } - if _, err = os.Stat(config.BlobDirectory); err != nil { - if os.IsNotExist(err) { - if err = os.MkdirAll(config.BlobDirectory, os.ModePerm); err != nil { - return nil, fmt.Errorf("error creating blob directory: %w", err) + if config.BlobDirectory != "" { + if _, err = os.Stat(config.BlobDirectory); err != nil { + if os.IsNotExist(err) { + if err = os.MkdirAll(config.BlobDirectory, os.ModePerm); err != nil { + return nil, fmt.Errorf("error creating blob directory: %w", err) + } + } else { + return nil, fmt.Errorf("invalid blob directory path: %w", err) } - } else { - return nil, fmt.Errorf("invalid blob directory path: %w", err) } } return &BlobClient{ From 02323c212db125f1961a53ee7e586a5eb9b3d51f Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Wed, 14 Feb 2024 23:53:03 -0600 Subject: [PATCH 748/775] Fix IsKnownHeaderByte --- arbstate/das_reader.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbstate/das_reader.go b/arbstate/das_reader.go index ab2f8a67c..f131a5360 100644 --- a/arbstate/das_reader.go +++ b/arbstate/das_reader.go @@ -78,9 +78,9 @@ func IsBrotliMessageHeaderByte(b uint8) bool { return b == BrotliMessageHeaderByte } -// IsKnownHeaderByte returns true if the supplied header byte has any unknown bits +// IsKnownHeaderByte returns true if the supplied header byte has only known bits func IsKnownHeaderByte(b uint8) bool { - return b&^KnownHeaderBits != 0 + return b&^KnownHeaderBits == 0 } type DataAvailabilityCertificate struct { From e9f33263eecca56e73ce748daa5618ee16044bb3 Mon Sep 17 00:00:00 2001 From: Tristan Wilson Date: Thu, 15 Feb 2024 19:19:16 -0800 Subject: [PATCH 749/775] Error on rpc daserver configured without bls key --- das/dasRpcServer.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/das/dasRpcServer.go b/das/dasRpcServer.go index 9fa39d195..2f1fc1fd4 100644 --- a/das/dasRpcServer.go +++ b/das/dasRpcServer.go @@ -5,6 +5,7 @@ package das import ( "context" + "errors" "fmt" "net" "net/http" @@ -44,6 +45,9 @@ func StartDASRPCServer(ctx context.Context, addr string, portNum uint64, rpcServ } func StartDASRPCServerOnListener(ctx context.Context, listener net.Listener, rpcServerTimeouts genericconf.HTTPServerTimeoutConfig, daReader DataAvailabilityServiceReader, daWriter DataAvailabilityServiceWriter, daHealthChecker DataAvailabilityServiceHealthChecker) (*http.Server, error) { + if daWriter == nil { + return nil, errors.New("No writer backend was configured for DAS RPC server. Has the BLS signing key been set up (--data-availability.key.key-dir or --data-availability.key.priv-key options)?") + } rpcServer := rpc.NewServer() err := rpcServer.RegisterName("das", &DASRPCServer{ daReader: daReader, From e9350a3047b1e90093e4e6126f5fd089055a65b0 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 16 Feb 2024 11:29:43 -0600 Subject: [PATCH 750/775] Test retryable gas estimation isn't too high --- go-ethereum | 2 +- system_tests/retryable_test.go | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/go-ethereum b/go-ethereum index efaa6d0eb..657dcf662 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit efaa6d0eb73bbb6ac4c5436d68eb5140aca6a0d2 +Subproject commit 657dcf66263e940e86f9e89325c5100899d5ab58 diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 4e7bd2c7d..be0ecc590 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -157,7 +157,10 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { ) Require(t, err, "failed to estimate retryable submission") estimate := tx.Gas() - colors.PrintBlue("estimate: ", estimate) + expectedEstimate := params.TxGas + params.TxDataNonZeroGasEIP2028*4 + if estimate != expectedEstimate { + t.Errorf("estimated retryable ticket at %v gas but expected %v", estimate, expectedEstimate) + } // submit & auto redeem the retryable using the gas estimate usertxoptsL1 := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) @@ -336,6 +339,12 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { receipt, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) + redemptionL2Gas := receipt.GasUsed - receipt.GasUsedForL1 + var maxRedemptionL2Gas uint64 = 1_000_000 + if redemptionL2Gas > maxRedemptionL2Gas { + t.Errorf("manual retryable redemption used %v gas, more than expected max %v gas", redemptionL2Gas, maxRedemptionL2Gas) + } + retryTxId := receipt.Logs[0].Topics[2] // check the receipt for the retry From 846ecf71f0f6da8662954daac38aff67c0a25358 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 12 Mar 2024 17:43:52 -0600 Subject: [PATCH 751/775] prover: limit kzg to native --- arbitrator/prover/Cargo.toml | 4 +- arbitrator/prover/src/lib.rs | 4 ++ arbitrator/prover/src/machine.rs | 18 +++++- arbitrator/prover/src/main.rs | 1 + arbitrator/prover/src/utils.rs | 3 + arbitrator/wasm-libraries/Cargo.lock | 86 +--------------------------- 6 files changed, 28 insertions(+), 88 deletions(-) diff --git a/arbitrator/prover/Cargo.toml b/arbitrator/prover/Cargo.toml index 21b1b1f14..60c5d72c7 100644 --- a/arbitrator/prover/Cargo.toml +++ b/arbitrator/prover/Cargo.toml @@ -36,7 +36,7 @@ wasmer-compiler-singlepass = { path = "../tools/wasmer/lib/compiler-singlepass", wasmparser.workspace = true num-derive = "0.4.1" num-traits = "0.2.17" -c-kzg = "0.4.0" # TODO: look into switching to rust-kzg (no crates.io release or hosted rustdoc yet) +c-kzg = { version = "0.4.0", optional = true } # TODO: look into switching to rust-kzg (no crates.io release or hosted rustdoc yet) sha2 = "0.9.9" [lib] @@ -45,6 +45,6 @@ crate-type = ["staticlib", "lib"] [features] default = ["native", "rayon", "singlepass_rayon"] -native = ["dep:wasmer", "dep:wasmer-compiler-singlepass", "dep:brotli2"] +native = ["dep:wasmer", "dep:wasmer-compiler-singlepass", "dep:brotli2", "dep:c-kzg"] singlepass_rayon = ["wasmer-compiler-singlepass?/rayon"] rayon = ["dep:rayon"] diff --git a/arbitrator/prover/src/lib.rs b/arbitrator/prover/src/lib.rs index 7776acd57..c6edf4001 100644 --- a/arbitrator/prover/src/lib.rs +++ b/arbitrator/prover/src/lib.rs @@ -5,6 +5,7 @@ pub mod binary; mod host; +#[cfg(feature = "native")] mod kzg; pub mod machine; /// cbindgen:ignore @@ -159,6 +160,7 @@ pub unsafe extern "C" fn atomic_u8_store(ptr: *mut u8, contents: u8) { /// Runs the machine while the condition variable is zero. May return early if num_steps is hit. /// Returns a c string error (freeable with libc's free) on error, or nullptr on success. #[no_mangle] +#[cfg(feature = "native")] pub unsafe extern "C" fn arbitrator_step( mach: *mut Machine, num_steps: u64, @@ -216,6 +218,7 @@ pub unsafe extern "C" fn arbitrator_add_user_wasm( /// Like arbitrator_step, but stops early if it hits a host io operation. /// Returns a c string error (freeable with libc's free) on error, or nullptr on success. #[no_mangle] +#[cfg(feature = "native")] pub unsafe extern "C" fn arbitrator_step_until_host_io( mach: *mut Machine, condition: *const u8, @@ -371,6 +374,7 @@ pub unsafe extern "C" fn arbitrator_module_root(mach: *mut Machine) -> Bytes32 { } #[no_mangle] +#[cfg(feature = "native")] pub unsafe extern "C" fn arbitrator_gen_proof(mach: *mut Machine) -> RustByteArray { let mut proof = (*mach).serialize_proof(); let ret = RustByteArray { diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index b9d939493..3203e2c9c 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -6,7 +6,6 @@ use crate::{ self, parse, ExportKind, ExportMap, FloatInstruction, Local, NameCustomSection, WasmBinary, }, host, - kzg::prove_kzg_preimage, memory::Memory, merkle::{Merkle, MerkleType}, programs::{config::CompileConfig, meter::MeteredMachine, ModuleMod, StylusData}, @@ -19,6 +18,9 @@ use crate::{ }, }; use arbutil::{math, Bytes32, Color, PreimageType}; +#[cfg(feature = "native")] +use crate::kzg::prove_kzg_preimage; +#[cfg(feature = "native")] use c_kzg::BYTES_PER_BLOB; use digest::Digest; use eyre::{bail, ensure, eyre, Result, WrapErr}; @@ -784,6 +786,7 @@ impl PreimageResolverWrapper { } } + #[cfg(feature = "native")] pub fn get(&mut self, context: u64, ty: PreimageType, hash: Bytes32) -> Option<&[u8]> { // TODO: this is unnecessarily complicated by the rust borrow checker. // This will probably be simplifiable when Polonius is shipped. @@ -799,6 +802,7 @@ impl PreimageResolverWrapper { } } + #[cfg(feature = "native")] pub fn get_const(&self, context: u64, ty: PreimageType, hash: Bytes32) -> Option { if let Some(resolved) = &self.last_resolved { if resolved.0 == hash { @@ -896,6 +900,7 @@ where } #[must_use] +#[cfg(feature = "native")] fn prove_window(items: &[T], stack_hasher: F, encoder: G) -> Vec where F: Fn(&[T]) -> Bytes32, @@ -916,6 +921,7 @@ where } #[must_use] +#[cfg(feature = "native")] fn prove_stack( items: &[T], proving_depth: usize, @@ -945,6 +951,7 @@ where // of in-between stacks ([2nd..last)). // Accepts prover function so that it can work both for proving stack and window. #[must_use] +#[cfg(feature = "native")] fn prove_multistack( cothread: bool, items: Vec<&[T]>, @@ -981,6 +988,7 @@ where } #[must_use] +#[cfg(feature = "native")] fn exec_ibin_op(a: T, b: T, op: IBinOpType) -> Option where Wrapping: ReinterpretAsSigned, @@ -1016,6 +1024,7 @@ where } #[must_use] +#[cfg(feature = "native")] fn exec_iun_op(a: T, op: IUnOpType) -> u32 where T: PrimInt, @@ -1027,6 +1036,7 @@ where } } +#[cfg(feature = "native")] fn exec_irel_op(a: T, b: T, op: IRelOpType) -> Value where T: Ord, @@ -1629,6 +1639,7 @@ impl Machine { Ok(self.value_stacks[0].clone()) } + #[cfg(feature = "native")] pub fn call_function( &mut self, module: &str, @@ -1641,6 +1652,7 @@ impl Machine { self.get_final_result() } + #[cfg(feature = "native")] pub fn call_user_func(&mut self, func: &str, args: Vec, ink: u64) -> Result> { self.set_ink(ink); self.call_function("user", func, args) @@ -1716,6 +1728,7 @@ impl Machine { Some(self.pc) } + #[cfg(feature = "native")] fn test_next_instruction(func: &Function, pc: &ProgramCounter) { let inst: usize = pc.inst.try_into().unwrap(); debug_assert!(func.code.len() > inst); @@ -1725,6 +1738,7 @@ impl Machine { self.steps } + #[cfg(feature = "native")] pub fn step_n(&mut self, n: u64) -> Result<()> { if self.is_halted() { return Ok(()); @@ -2415,6 +2429,7 @@ impl Machine { Ok(()) } + #[cfg(feature = "native")] fn host_call_hook( value_stack: &[Value], module: &Module, @@ -2639,6 +2654,7 @@ impl Machine { h.finalize().into() } + #[cfg(feature = "native")] pub fn serialize_proof(&self) -> Vec { // Could be variable, but not worth it yet const STACK_PROVING_DEPTH: usize = 3; diff --git a/arbitrator/prover/src/main.rs b/arbitrator/prover/src/main.rs index 60886eab9..785bfaff0 100644 --- a/arbitrator/prover/src/main.rs +++ b/arbitrator/prover/src/main.rs @@ -118,6 +118,7 @@ struct SimpleProfile { const INBOX_HEADER_LEN: usize = 40; // also in test-case's host-io.rs & contracts's OneStepProverHostIo.sol const DELAYED_HEADER_LEN: usize = 112; // also in test-case's host-io.rs & contracts's OneStepProverHostIo.sol +#[cfg(feature = "native")] fn main() -> Result<()> { let opts = Opts::from_args(); diff --git a/arbitrator/prover/src/utils.rs b/arbitrator/prover/src/utils.rs index d3ae4ee50..be1086519 100644 --- a/arbitrator/prover/src/utils.rs +++ b/arbitrator/prover/src/utils.rs @@ -1,10 +1,12 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE +#[cfg(feature = "native")] use crate::kzg::ETHEREUM_KZG_SETTINGS; use sha2::Sha256; use sha3::Keccak256; use arbutil::PreimageType; +#[cfg(feature = "native")] use c_kzg::{Blob, KzgCommitment}; use digest::Digest; use eyre::{eyre, Result}; @@ -170,6 +172,7 @@ pub fn split_import(qualified: &str) -> Result<(&str, &str)> { Ok((module, name)) } +#[cfg(feature = "native")] pub fn hash_preimage(preimage: &[u8], ty: PreimageType) -> Result<[u8; 32]> { match ty { PreimageType::Keccak256 => Ok(Keccak256::digest(preimage).into()), diff --git a/arbitrator/wasm-libraries/Cargo.lock b/arbitrator/wasm-libraries/Cargo.lock index 3308e9c7b..32fbfe122 100644 --- a/arbitrator/wasm-libraries/Cargo.lock +++ b/arbitrator/wasm-libraries/Cargo.lock @@ -51,7 +51,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.19", + "hermit-abi", "libc", "winapi", ] @@ -114,18 +114,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" -[[package]] -name = "blst" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" -dependencies = [ - "cc", - "glob", - "threadpool", - "zeroize", -] - [[package]] name = "brotli" version = "0.1.0" @@ -156,20 +144,6 @@ dependencies = [ "syn 1.0.107", ] -[[package]] -name = "c-kzg" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a4bc5367b6284358d2a6a6a1dc2d92ec4b86034561c3b9d3341909752fd848" -dependencies = [ - "blst", - "cc", - "glob", - "hex", - "libc", - "serde", -] - [[package]] name = "caller-env" version = "0.1.0" @@ -179,12 +153,6 @@ dependencies = [ "rand_pcg", ] -[[package]] -name = "cc" -version = "1.0.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" - [[package]] name = "cfg-if" version = "0.1.10" @@ -449,12 +417,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - [[package]] name = "hashbrown" version = "0.12.3" @@ -488,12 +450,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hex" version = "0.4.3" @@ -734,16 +690,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.9", - "libc", -] - [[package]] name = "num_enum" version = "0.7.2" @@ -864,7 +810,6 @@ version = "0.1.0" dependencies = [ "arbutil", "bincode", - "c-kzg", "derivative", "digest 0.9.0", "eyre", @@ -1248,15 +1193,6 @@ dependencies = [ "syn 1.0.107", ] -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - [[package]] name = "tiny-keccak" version = "2.0.2" @@ -1581,23 +1517,3 @@ checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" dependencies = [ "tap", ] - -[[package]] -name = "zeroize" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] From 39d2b2214cda31c039778befca188985555fcd58 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 13 Mar 2024 17:45:22 -0600 Subject: [PATCH 752/775] ipfs: rename files so compiler will ignore them, fix go.mod/sum --- .../{ipfshelper.go => ipfshelper.bkup_go} | 0 ...ervice.go => ipfs_storage_service.bkup_go} | 0 go.mod | 328 +--- go.sum | 1494 ++--------------- 4 files changed, 208 insertions(+), 1614 deletions(-) rename cmd/ipfshelper/{ipfshelper.go => ipfshelper.bkup_go} (100%) rename das/{ipfs_storage_service.go => ipfs_storage_service.bkup_go} (100%) diff --git a/cmd/ipfshelper/ipfshelper.go b/cmd/ipfshelper/ipfshelper.bkup_go similarity index 100% rename from cmd/ipfshelper/ipfshelper.go rename to cmd/ipfshelper/ipfshelper.bkup_go diff --git a/das/ipfs_storage_service.go b/das/ipfs_storage_service.bkup_go similarity index 100% rename from das/ipfs_storage_service.go rename to das/ipfs_storage_service.bkup_go diff --git a/go.mod b/go.mod index b6237daf8..530e9b241 100644 --- a/go.mod +++ b/go.mod @@ -23,39 +23,41 @@ require ( github.com/dgraph-io/badger/v3 v3.2103.2 github.com/enescakir/emoji v1.0.0 github.com/ethereum/go-ethereum v1.10.26 - github.com/gdamore/tcell/v2 v2.6.0 + github.com/fatih/structtag v1.2.0 + github.com/gdamore/tcell/v2 v2.7.1 + github.com/go-redis/redis/v8 v8.11.5 + github.com/gobwas/httphead v0.1.0 + github.com/gobwas/ws v1.2.1 + github.com/gobwas/ws-examples v0.0.0-20190625122829-a9e8908d9484 github.com/google/go-cmp v0.5.9 github.com/hashicorp/golang-lru/v2 v2.0.7 - github.com/ipfs/go-cid v0.4.1 - github.com/ipfs/go-libipfs v0.6.0 - github.com/ipfs/interface-go-ipfs-core v0.11.2 - github.com/ipfs/kubo v0.25.0 + github.com/holiman/uint256 v1.2.3 github.com/knadh/koanf v1.4.0 - github.com/libp2p/go-libp2p v0.32.2 - github.com/multiformats/go-multiaddr v0.12.0 - github.com/multiformats/go-multihash v0.2.3 + github.com/mailru/easygo v0.0.0-20190618140210-3c14a0dc985f + github.com/mitchellh/mapstructure v1.4.1 + github.com/r3labs/diff/v3 v3.0.1 + github.com/rivo/tview v0.0.0-20240307173318-e804876934a1 github.com/spf13/pflag v1.0.5 + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/wasmerio/wasmer-go v1.0.4 github.com/wealdtech/go-merkletree v1.0.0 - golang.org/x/term v0.15.0 + golang.org/x/crypto v0.16.0 + golang.org/x/sys v0.17.0 + golang.org/x/term v0.17.0 golang.org/x/tools v0.16.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) -require github.com/gofrs/flock v0.8.1 // indirect - require ( - bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc // indirect - github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect - github.com/DataDog/zstd v1.5.2 // indirect - github.com/Jorropo/jsync v1.0.1 // indirect - github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect - github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect + github.com/DataDog/zstd v1.4.5 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.4 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.11 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.10 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.4 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.11 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.1 // indirect @@ -65,273 +67,101 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.11.4 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.16.4 // indirect github.com/aws/smithy-go v1.11.2 // indirect - github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.7.0 // indirect - github.com/blang/semver/v4 v4.0.0 // indirect + github.com/bits-and-blooms/bitset v1.5.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/ceramicnetwork/go-dag-jose v0.1.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cockroachdb/errors v1.9.1 // indirect - github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/redact v1.1.3 // indirect - github.com/containerd/cgroups v1.1.0 // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cockroachdb/errors v1.8.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f // indirect + github.com/cockroachdb/redact v1.0.8 // indirect + github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.10.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect - github.com/cskr/pubsub v1.0.2 // indirect - github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/dgraph-io/badger v1.6.2 // indirect github.com/dgraph-io/ristretto v0.1.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect - github.com/elastic/gosigar v0.14.2 // indirect - github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect - github.com/flynn/noise v1.0.0 // indirect - github.com/francoispqt/gojay v1.2.13 // indirect + github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.1 // indirect github.com/gammazero/deque v0.2.1 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/gdamore/encoding v1.0.0 // indirect - github.com/getsentry/sentry-go v0.18.0 // indirect - github.com/go-logr/logr v1.3.0 // indirect - github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.5 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect - github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.3.0 // indirect - github.com/golang/glog v1.1.0 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect + github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/flatbuffers v1.12.1 // indirect - github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect github.com/h2non/filetype v1.0.6 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/ipfs-shipyard/nopfs v0.0.12-0.20231027223058-cde3b5ba964c // indirect - github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c // indirect - github.com/ipfs/bbloom v0.0.4 // indirect - github.com/ipfs/boxo v0.16.0 // indirect - github.com/ipfs/go-bitfield v1.1.0 // indirect - github.com/ipfs/go-block-format v0.2.0 // indirect - github.com/ipfs/go-blockservice v0.5.1 // indirect - github.com/ipfs/go-cidutil v0.1.0 // indirect - github.com/ipfs/go-datastore v0.6.0 // indirect - github.com/ipfs/go-ds-badger v0.3.0 // indirect - github.com/ipfs/go-ds-flatfs v0.5.1 // indirect - github.com/ipfs/go-ds-leveldb v0.5.0 // indirect - github.com/ipfs/go-ds-measure v0.2.0 // indirect - github.com/ipfs/go-fs-lock v0.0.7 // indirect - github.com/ipfs/go-ipfs-blockstore v1.3.0 // indirect - github.com/ipfs/go-ipfs-delay v0.0.1 // indirect - github.com/ipfs/go-ipfs-ds-help v1.1.0 // indirect - github.com/ipfs/go-ipfs-exchange-interface v0.2.0 // indirect - github.com/ipfs/go-ipfs-pq v0.0.3 // indirect - github.com/ipfs/go-ipfs-redirects-file v0.1.1 // indirect - github.com/ipfs/go-ipfs-util v0.0.3 // indirect - github.com/ipfs/go-ipld-cbor v0.0.6 // indirect - github.com/ipfs/go-ipld-format v0.6.0 // indirect - github.com/ipfs/go-ipld-git v0.1.1 // indirect - github.com/ipfs/go-ipld-legacy v0.2.1 // indirect - github.com/ipfs/go-log v1.0.5 // indirect - github.com/ipfs/go-log/v2 v2.5.1 // indirect - github.com/ipfs/go-merkledag v0.11.0 // indirect - github.com/ipfs/go-metrics-interface v0.0.1 // indirect - github.com/ipfs/go-path v0.3.0 // indirect - github.com/ipfs/go-peertaskqueue v0.8.1 // indirect - github.com/ipfs/go-unixfsnode v1.8.1 // indirect - github.com/ipfs/go-verifcid v0.0.2 // indirect - github.com/ipld/go-car/v2 v2.10.2-0.20230622090957-499d0c909d33 // indirect - github.com/ipld/go-codec-dagpb v1.6.0 // indirect - github.com/ipld/go-ipld-prime v0.21.0 // indirect - github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/jbenet/goprocess v0.1.4 // indirect + github.com/hashicorp/go-bexpr v0.1.10 // indirect + github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/huin/goupnp v1.3.0 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5 // indirect github.com/klauspost/compress v1.17.2 // indirect - github.com/klauspost/cpuid/v2 v2.2.6 // indirect - github.com/koron/go-ssdp v0.0.4 // indirect - github.com/kr/pretty v0.3.1 // indirect + github.com/kr/pretty v0.3.0 // indirect github.com/kr/text v0.2.0 // indirect - github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/libp2p/go-cidranger v1.1.0 // indirect - github.com/libp2p/go-doh-resolver v0.4.0 // indirect - github.com/libp2p/go-flow-metrics v0.1.0 // indirect - github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect - github.com/libp2p/go-libp2p-kad-dht v0.24.4 // indirect - github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect - github.com/libp2p/go-libp2p-pubsub v0.10.0 // indirect - github.com/libp2p/go-libp2p-pubsub-router v0.6.0 // indirect - github.com/libp2p/go-libp2p-record v0.2.0 // indirect - github.com/libp2p/go-libp2p-routing-helpers v0.7.3 // indirect - github.com/libp2p/go-libp2p-xor v0.1.0 // indirect - github.com/libp2p/go-msgio v0.3.0 // indirect - github.com/libp2p/go-nat v0.2.0 // indirect - github.com/libp2p/go-netroute v0.2.1 // indirect - github.com/libp2p/go-reuseport v0.4.0 // indirect - github.com/libp2p/go-yamux/v4 v4.0.1 // indirect - github.com/libp2p/zeroconf/v2 v2.2.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect - github.com/miekg/dns v1.1.57 // indirect - github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect - github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect - github.com/minio/sha256-simd v1.0.1 // indirect - github.com/minio/sha256-simd v1.0.1 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/mr-tron/base58 v1.2.0 // indirect - github.com/multiformats/go-base32 v0.1.0 // indirect - github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect - github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect - github.com/multiformats/go-multibase v0.2.0 // indirect - github.com/multiformats/go-multicodec v0.9.0 // indirect - github.com/multiformats/go-multistream v0.5.0 // indirect - github.com/multiformats/go-varint v0.0.7 // indirect - github.com/onsi/ginkgo/v2 v2.13.0 // indirect - github.com/opencontainers/runtime-spec v1.1.0 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/openzipkin/zipkin-go v0.4.1 // indirect - github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect - github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect - github.com/pion/datachannel v1.5.5 // indirect - github.com/pion/dtls/v2 v2.2.7 // indirect - github.com/pion/ice/v2 v2.3.6 // indirect - github.com/pion/interceptor v0.1.17 // indirect - github.com/pion/logging v0.2.2 // indirect - github.com/pion/mdns v0.0.7 // indirect - github.com/pion/randutil v0.1.0 // indirect - github.com/pion/rtcp v1.2.10 // indirect - github.com/pion/rtp v1.7.13 // indirect - github.com/pion/sctp v1.8.7 // indirect - github.com/pion/sdp/v3 v3.0.6 // indirect - github.com/pion/srtp/v2 v2.0.15 // indirect - github.com/pion/stun v0.6.0 // indirect - github.com/pion/transport/v2 v2.2.1 // indirect - github.com/pion/turn/v2 v2.1.0 // indirect - github.com/pion/webrtc/v3 v3.2.9 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opentracing/opentracing-go v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polydawn/refmt v0.89.0 // indirect - github.com/prometheus/client_golang v1.17.0 // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.45.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect - github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-20 v0.3.4 // indirect - github.com/quic-go/quic-go v0.39.4 // indirect - github.com/quic-go/webtransport-go v0.6.0 // indirect - github.com/raulk/go-watchdog v1.3.0 // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect github.com/rhnvrm/simples3 v0.6.1 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/samber/lo v1.39.0 // indirect - github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect - github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb // indirect - github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect - github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect - github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect - github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa // indirect - github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect - github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect - github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel v1.17.0 // indirect - go.opentelemetry.io/otel/exporters/jaeger v1.14.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0 // indirect - go.opentelemetry.io/otel/exporters/zipkin v1.14.0 // indirect - go.opentelemetry.io/otel/metric v1.17.0 // indirect - go.opentelemetry.io/otel/sdk v1.16.0 // indirect - go.opentelemetry.io/otel/trace v1.17.0 // indirect - go.opentelemetry.io/proto/otlp v0.19.0 // indirect - go.uber.org/atomic v1.11.0 // indirect - go.uber.org/dig v1.17.1 // indirect - go.uber.org/fx v1.20.1 // indirect - go.uber.org/mock v0.3.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/exp v0.0.0-20231127185646-65229373498e // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - gonum.org/v1/gonum v0.14.0 // indirect - google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect - google.golang.org/grpc v1.55.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/square/go-jose.v2 v2.5.1 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - lukechampine.com/blake3 v1.2.1 // indirect -) - -require ( - github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/gobwas/httphead v0.1.0 - github.com/gobwas/pool v0.2.1 // indirect - github.com/gobwas/ws v1.2.1 - github.com/gobwas/ws-examples v0.0.0-20190625122829-a9e8908d9484 - github.com/mailru/easygo v0.0.0-20190618140210-3c14a0dc985f -) - -require ( - github.com/StackExchange/wmi v1.2.1 // indirect - github.com/VictoriaMetrics/fastcache v1.6.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect - github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect - github.com/go-ole/go-ole v1.2.5 // indirect - github.com/go-redis/redis/v8 v8.11.4 - github.com/go-stack/stack v1.8.1 // indirect - github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect - github.com/google/uuid v1.4.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/hashicorp/go-bexpr v0.1.10 // indirect - github.com/hashicorp/golang-lru v1.0.2 // indirect - github.com/holiman/bloomfilter/v2 v2.0.3 // indirect - github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c - github.com/huin/goupnp v1.3.0 // indirect - github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/mitchellh/mapstructure v1.4.2 - github.com/mitchellh/pointerstructure v1.2.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.6.1 // indirect github.com/rs/cors v1.7.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + github.com/stretchr/testify v1.8.4 // indirect + github.com/supranational/blst v0.3.11 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect - golang.org/x/crypto v0.16.0 + github.com/urfave/cli/v2 v2.25.7 // indirect + github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 // indirect + go.opencensus.io v0.22.5 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.19.0 // indirect golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.15.0 golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect - gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + golang.org/x/time v0.3.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 7cf0b2664..685c98381 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,5 @@ -bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc h1:utDghgcjE8u+EBjHOgYT+dJPcnDF05KqWMBcjuJy510= -bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= @@ -34,52 +30,35 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= -github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= -github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= -github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= -github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= -github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw= +github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= -github.com/Jorropo/jsync v1.0.1 h1:6HgRolFZnsdfzRUj+ImB9og1JYOxQoReSywkHOGSaUU= -github.com/Jorropo/jsync v1.0.1/go.mod h1:jCOZj3vrBCri3bSU3ErUYvevKlnbssrXeCivybS5ABQ= +github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI+XWrX9Wf2XH0s= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 h1:iW0a5ljuFxkLGPNem5Ui+KBjFJzKg4Fv2fnxe4dvzpM= -github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h1:Y2QMoi1vgtOIfc+6DhrMOGkLoGzqSV2rKp4Sm+opsyA= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis/v2 v2.21.0 h1:CdmwIlKUWFBDS+4464GtQiQ0R1vpzOgu4Vnd74rBL7M= @@ -88,20 +67,11 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/arduino/go-paths-helper v1.2.0 h1:qDW93PR5IZUN/jzO4rCtexiwF8P4OIcOmcSgAYLZfY4= github.com/arduino/go-paths-helper v1.2.0/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2 v1.16.3/go.mod h1:ytwTPBG6fXTZLxxeeCCWj2/EMYp/xDUgX+OET6TLNNU= github.com/aws/aws-sdk-go-v2 v1.16.4 h1:swQTEQUyJF/UkEA94/Ga55miiKFoXmm/Zd67XHgmjSg= @@ -119,12 +89,10 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.4 h1:FP8gquGeGHHdfY6G5llaMQD github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.4/go.mod h1:u/s5/Z+ohUQOPXl00m2yJVyioWDECsbpXTQlaqSlufc= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.10 h1:JL7cY85hyjlgfA29MMyAlItX+JYIH9XsxgMBS7jtlqA= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.10/go.mod h1:p+ul5bLZSDRRXCZ/vePvfmZBH9akozXBJA5oMshWa5U= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.10 h1:uFWgo6mGJI1n17nbcvSc6fxVuR3xLNqvXt12JCnEcT8= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.10/go.mod h1:F+EZtuIwjlv35kRJPyBGcsA4f7bnSoz15zOQ2lJq1Z4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.11 h1:gsqHplNh1DaQunEKZISK56wlpbCg0yKxNVvGWCFuF1k= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.11/go.mod h1:tmUB6jakq5DFNcXsXOA/ZQ7/C8VnSKYkx58OI7Fh79g= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.4 h1:cnsvEKSoHN4oAN7spMMr0zhEW2MHnhAVpmqQg8E6UcM= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.4/go.mod h1:8glyUqVIM4AmeenIsPo0oVh3+NUwnsQml2OFupfQW+0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.5 h1:PLFj+M2PgIDHG//hw3T0O0KLI4itVtAjtxrZx4AHPLg= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.5/go.mod h1:fV1AaS2gFc1tM0RCb015FJ0pvWVUfJZANzjwoO4YakM= github.com/aws/aws-sdk-go-v2/internal/ini v1.2.4/go.mod h1:ZcBrrI3zBKlhGFNYWvju0I3TR93I7YIgAfy82Fh4lcQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.11 h1:6cZRymlLEIlDTEB0+5+An6Zj1CKt6rSE69tOmFeu1nk= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.11/go.mod h1:0MR+sS1b/yxsfAPvAESrw8NfwUoxMinDyw6EYR9BS2U= @@ -152,51 +120,20 @@ github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAm github.com/aws/smithy-go v1.11.2 h1:eG/N+CcUMAvsdffgMvjMKwfyDzIkjM6pfxMJ8Mzc6mE= github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= -github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= -github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= -github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= -github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= -github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= +github.com/bits-and-blooms/bitset v1.5.0 h1:NpE8frKRLGHIcEzkR+gZhiioW1+WbYV6fKwD6ZIpQT8= +github.com/bits-and-blooms/bitset v1.5.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/cavaliergopher/grab/v3 v3.0.1 h1:4z7TkBfmPjmLAAmkkAZNX/6QJ1nNFdv3SdIHXju0Fr4= github.com/cavaliergopher/grab/v3 v3.0.1/go.mod h1:1U/KNnD+Ft6JJiYoYBAimKH2XrYptb8Kl3DFGmsjpq4= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/ceramicnetwork/go-dag-jose v0.1.0 h1:yJ/HVlfKpnD3LdYP03AHyTvbm3BpPiz2oZiOeReJRdU= -github.com/ceramicnetwork/go-dag-jose v0.1.0/go.mod h1:qYA1nYt0X8u4XoMAVoOV3upUVKtrxy/I670Dg5F0wjI= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= @@ -205,100 +142,61 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/datadriven v1.0.0/go.mod h1:5Ib8Meh+jk1RlHIXej6Pzevx/NLlNvQB9pmSBZErGA4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= -github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= -github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= -github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.6.1/go.mod h1:tm6FTP5G81vwJ5lC0SizQo374JNCOPrHyXGitRJoDqM= +github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= +github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/redact v1.0.8 h1:8QG/764wK+vmEYoOlfobpe12EQcS81ukx/a4hdVMxNw= +github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 h1:IKgmqgMQlVJIZj19CdocBeSfSaiCbEBZGKODaixqtHM= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codeclysm/extract/v3 v3.0.2 h1:sB4LcE3Php7LkhZwN0n2p8GCwZe92PEQutdbGURf5xc= github.com/codeclysm/extract/v3 v3.0.2/go.mod h1:NKsw+hqua9H+Rlwy/w/3Qgt9jDonYEgB6wJu+25eOKw= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= -github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= -github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= -github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= +github.com/consensys/gnark-crypto v0.10.0 h1:zRh22SR7o4K35SoNqouS9J/TKHTyU2QWaj5ldehyXtA= +github.com/consensys/gnark-crypto v0.10.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= -github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= -github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= -github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= -github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlNV5bjgnuU= -github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= -github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= github.com/dgraph-io/badger/v3 v3.2103.2 h1:dpyM5eCJAtQCBcMCZcT4UBZchuTJgCywerHHgmxfxM8= github.com/dgraph-io/badger/v3 v3.2103.2/go.mod h1:RHo4/GmYcKKh5Lxu63wLEMHJ70Pac2JqZRYGhlyAo2M= -github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= @@ -306,62 +204,35 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= -github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= -github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/enescakir/emoji v1.0.0 h1:W+HsNql8swfCQFtioDGDHCHri8nudlK1n5p2rHCJoog= +github.com/enescakir/emoji v1.0.0/go.mod h1:Bt1EKuLnKDTYpLALApstIkAjdDrS/8IAgTkKp+WKFD0= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= -github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= +github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= -github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= -github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/gabriel-vasile/mimetype v1.4.1 h1:TRWk7se+TOjCYgRth7+1/OYLNiRNIotknkFtf/dnN7Q= -github.com/gabriel-vasile/mimetype v1.4.1/go.mod h1:05Vi0w3Y9c/lNvJOdmIwvrrAhX3rYhfQQCaf9VJcv7M= github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= @@ -369,52 +240,36 @@ github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqG github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= -github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= -github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y= -github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= -github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= -github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gdamore/tcell/v2 v2.7.1 h1:TiCcmpWHiAU7F0rA2I3S2Y4mmLmO9KHxJ7E1QhYzQbc= +github.com/gdamore/tcell/v2 v2.7.1/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg= -github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= +github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= @@ -426,38 +281,23 @@ github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/gobwas/ws-examples v0.0.0-20190625122829-a9e8908d9484 h1:XC9N1eiAyO1zg62dpOU8bex8emB/zluUtKcbLNjJxGI= github.com/gobwas/ws-examples v0.0.0-20190625122829-a9e8908d9484/go.mod h1:5nDZF4afNA1S7ZKcBXCMvDo4nuCTp1931DND7/W4aXo= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -466,7 +306,6 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= @@ -484,9 +323,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -504,20 +340,14 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= -github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= -github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -527,54 +357,24 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0= github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4= -github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/h2non/filetype v1.0.6 h1:g84/+gdkAT1hnYO+tHpCLoikm13Ju55OkN4KCb1uGEQ= github.com/h2non/filetype v1.0.6/go.mod h1:isekKqOuhMj+s/7r3rIeTErIRy4Rub5uBWHfvMusLMU= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -582,35 +382,21 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= -github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q= github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= @@ -622,251 +408,42 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= -github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/ipfs-shipyard/nopfs v0.0.12-0.20231027223058-cde3b5ba964c h1:17FO7HnKiFhO7iadu3zCgII+EblpdRmJt5qg9FqQo8Y= -github.com/ipfs-shipyard/nopfs v0.0.12-0.20231027223058-cde3b5ba964c/go.mod h1:1oj4+g/mN6JRuZiXHt5iFRG02e62wp5AKcB3gdgknbk= -github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c h1:7UynTbtdlt+w08ggb1UGLGaGjp1mMaZhoTZSctpn5Ak= -github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c/go.mod h1:6EekK/jo+TynwSE/ZOiOJd4eEvRXoavEC3vquKtv4yI= -github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0rjUI= -github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= -github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/boxo v0.16.0 h1:A9dUmef5a+mEFki6kbyG7el5gl65CiUBzrDeZxzTWKY= -github.com/ipfs/boxo v0.16.0/go.mod h1:jAgpNQn7T7BnibUeReXcKU9Ha1xmYNyOlwVEl193ow0= -github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= -github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= -github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= -github.com/ipfs/go-bitswap v0.1.2/go.mod h1:qxSWS4NXGs7jQ6zQvoPY3+NmOfHHG47mhkiLzBpJQIs= -github.com/ipfs/go-bitswap v0.5.1/go.mod h1:P+ckC87ri1xFLvk74NlXdP0Kj9RmWAh4+H78sC6Qopo= -github.com/ipfs/go-bitswap v0.11.0 h1:j1WVvhDX1yhG32NTC9xfxnqycqYIlhzEzLXG/cU1HyQ= -github.com/ipfs/go-bitswap v0.11.0/go.mod h1:05aE8H3XOU+LXpTedeAS0OZpcO1WFsj5niYQH9a1Tmk= -github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= -github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= -github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= -github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs= -github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM= -github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= -github.com/ipfs/go-blockservice v0.2.1/go.mod h1:k6SiwmgyYgs4M/qt+ww6amPeUH9EISLRBnvUurKJhi8= -github.com/ipfs/go-blockservice v0.5.1 h1:9pAtkyKAz/skdHTh0kH8VulzWp+qmSDD0aI17TYP/s0= -github.com/ipfs/go-blockservice v0.5.1/go.mod h1:VpMblFEqG67A/H2sHKAemeH9vlURVavlysbdUI632yk= -github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= -github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= -github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= -github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= -github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o= -github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= -github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= -github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= -github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= -github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q= -github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA= -github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= -github.com/ipfs/go-datastore v0.3.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= -github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= -github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= -github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= -github.com/ipfs/go-datastore v0.4.5/go.mod h1:eXTcaaiN6uOlVCLS9GjJUJtlvJfM3xk23w3fyfrmmJs= -github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= -github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk= -github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8= -github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= -github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= -github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= -github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= -github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= -github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= -github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= -github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= -github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= -github.com/ipfs/go-ds-flatfs v0.5.1 h1:ZCIO/kQOS/PSh3vcF1H6a8fkRGS7pOfwfPdx4n/KJH4= -github.com/ipfs/go-ds-flatfs v0.5.1/go.mod h1:RWTV7oZD/yZYBKdbVIFXTX2fdY2Tbvl94NsWqmoyAX4= -github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= -github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= -github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= -github.com/ipfs/go-ds-leveldb v0.4.2/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= -github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= -github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= -github.com/ipfs/go-ds-measure v0.2.0 h1:sG4goQe0KDTccHMyT45CY1XyUbxe5VwTKpg2LjApYyQ= -github.com/ipfs/go-ds-measure v0.2.0/go.mod h1:SEUD/rE2PwRa4IQEC5FuNAmjJCyYObZr9UvVh8V3JxE= -github.com/ipfs/go-fetcher v1.6.1/go.mod h1:27d/xMV8bodjVs9pugh/RCjjK2OZ68UgAMspMdingNo= -github.com/ipfs/go-fs-lock v0.0.7 h1:6BR3dajORFrFTkb5EpCUFIAypsoxpGpDSVUdFwzgL9U= -github.com/ipfs/go-fs-lock v0.0.7/go.mod h1:Js8ka+FNYmgQRLrRXzU3CB/+Csr1BwrRilEcvYrHhhc= -github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= -github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= -github.com/ipfs/go-ipfs-blockstore v0.2.1/go.mod h1:jGesd8EtCM3/zPgx+qr0/feTXGUeRai6adgwC+Q+JvE= -github.com/ipfs/go-ipfs-blockstore v1.3.0 h1:m2EXaWgwTzAfsmt5UdJ7Is6l4gJcaM/A12XwJyvYvMM= -github.com/ipfs/go-ipfs-blockstore v1.3.0/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE= -github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= -github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk= -github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= -github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8= -github.com/ipfs/go-ipfs-chunker v0.0.5/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= -github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= -github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= -github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= -github.com/ipfs/go-ipfs-ds-help v0.0.1/go.mod h1:gtP9xRaZXqIQRh1HRpp595KbBEdgqWFxefeVKOV8sxo= -github.com/ipfs/go-ipfs-ds-help v0.1.1/go.mod h1:SbBafGJuGsPI/QL3j9Fc5YPLeAu+SzOkI0gFwAg+mOs= -github.com/ipfs/go-ipfs-ds-help v1.1.0 h1:yLE2w9RAsl31LtfMt91tRZcrx+e61O5mDxFRR994w4Q= -github.com/ipfs/go-ipfs-ds-help v1.1.0/go.mod h1:YR5+6EaebOhfcqVCyqemItCLthrpVNot+rsOU/5IatU= -github.com/ipfs/go-ipfs-exchange-interface v0.0.1/go.mod h1:c8MwfHjtQjPoDyiy9cFquVtVHkO9b9Ob3FG91qJnWCM= -github.com/ipfs/go-ipfs-exchange-interface v0.1.0/go.mod h1:ych7WPlyHqFvCi/uQI48zLZuAWVP5iTQPXEfVaw5WEI= -github.com/ipfs/go-ipfs-exchange-interface v0.2.0 h1:8lMSJmKogZYNo2jjhUs0izT+dck05pqUw4mWNW9Pw6Y= -github.com/ipfs/go-ipfs-exchange-interface v0.2.0/go.mod h1:z6+RhJuDQbqKguVyslSOuVDhqF9JtTrO3eptSAiW2/Y= -github.com/ipfs/go-ipfs-exchange-offline v0.0.1/go.mod h1:WhHSFCVYX36H/anEKQboAzpUws3x7UeEGkzQc3iNkM0= -github.com/ipfs/go-ipfs-exchange-offline v0.1.1/go.mod h1:vTiBRIbzSwDD0OWm+i3xeT0mO7jG2cbJYatp3HPk5XY= -github.com/ipfs/go-ipfs-exchange-offline v0.3.0 h1:c/Dg8GDPzixGd0MC8Jh6mjOwU57uYokgWRFidfvEkuA= -github.com/ipfs/go-ipfs-exchange-offline v0.3.0/go.mod h1:MOdJ9DChbb5u37M1IcbrRB02e++Z7521fMxqCNRrz9s= -github.com/ipfs/go-ipfs-files v0.0.3/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= -github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= -github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= -github.com/ipfs/go-ipfs-pq v0.0.2/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= -github.com/ipfs/go-ipfs-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE= -github.com/ipfs/go-ipfs-pq v0.0.3/go.mod h1:btNw5hsHBpRcSSgZtiNm/SLj5gYIZ18AKtv3kERkRb4= -github.com/ipfs/go-ipfs-redirects-file v0.1.1 h1:Io++k0Vf/wK+tfnhEh63Yte1oQK5VGT2hIEYpD0Rzx8= -github.com/ipfs/go-ipfs-redirects-file v0.1.1/go.mod h1:tAwRjCV0RjLTjH8DR/AU7VYvfQECg+lpUy2Mdzv7gyk= -github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= -github.com/ipfs/go-ipfs-routing v0.2.1/go.mod h1:xiNNiwgjmLqPS1cimvAw6EyB9rkVDbiocA4yY+wRNLM= -github.com/ipfs/go-ipfs-routing v0.3.0 h1:9W/W3N+g+y4ZDeffSgqhgo7BsBSJwPMcyssET9OWevc= -github.com/ipfs/go-ipfs-routing v0.3.0/go.mod h1:dKqtTFIql7e1zYsEuWLyuOU+E0WJWW8JjbTPLParDWo= -github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= -github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= -github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0= -github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs= -github.com/ipfs/go-ipld-cbor v0.0.2/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc= -github.com/ipfs/go-ipld-cbor v0.0.3/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc= -github.com/ipfs/go-ipld-cbor v0.0.5/go.mod h1:BkCduEx3XBCO6t2Sfo5BaHzuok7hbhdMm9Oh8B2Ftq4= -github.com/ipfs/go-ipld-cbor v0.0.6 h1:pYuWHyvSpIsOOLw4Jy7NbBkCyzLDcl64Bf/LZW7eBQ0= -github.com/ipfs/go-ipld-cbor v0.0.6/go.mod h1:ssdxxaLJPXH7OjF5V4NSjBbcfh+evoR4ukuru0oPXMA= -github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms= -github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k= -github.com/ipfs/go-ipld-format v0.2.0/go.mod h1:3l3C1uKoadTPbeNfrDi+xMInYKlx2Cvg1BuydPSdzQs= -github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten1F5U= -github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg= -github.com/ipfs/go-ipld-git v0.1.1 h1:TWGnZjS0htmEmlMFEkA3ogrNCqWjIxwr16x1OsdhG+Y= -github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYDpKUkJubI= -github.com/ipfs/go-ipld-legacy v0.1.0/go.mod h1:86f5P/srAmh9GcIcWQR9lfFLZPrIyyXQeVlOWeeWEuI= -github.com/ipfs/go-ipld-legacy v0.2.1 h1:mDFtrBpmU7b//LzLSypVrXsD8QxkEWxu5qVxN99/+tk= -github.com/ipfs/go-ipld-legacy v0.2.1/go.mod h1:782MOUghNzMO2DER0FlBR94mllfdCJCkTtDtPM51otM= -github.com/ipfs/go-libipfs v0.6.0 h1:3FuckAJEm+zdHbHbf6lAyk0QUzc45LsFcGw102oBCZM= -github.com/ipfs/go-libipfs v0.6.0/go.mod h1:UjjDIuehp2GzlNP0HEr5I9GfFT7zWgst+YfpUEIThtw= -github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= -github.com/ipfs/go-log v1.0.2/go.mod h1:1MNjMxe0u6xvJZgeqbJ8vdo2TKaGwZ1a0Bpza+sr2Sk= -github.com/ipfs/go-log v1.0.3/go.mod h1:OsLySYkwIbiSUR/yBTdv1qPtcE4FW3WPWk/ewz9Ru+A= -github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= -github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= -github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= -github.com/ipfs/go-log/v2 v2.0.2/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= -github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= -github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= -github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= -github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= -github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= -github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= -github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= -github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= -github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= -github.com/ipfs/go-merkledag v0.5.1/go.mod h1:cLMZXx8J08idkp5+id62iVftUQV+HlYJ3PIhDfZsjA4= -github.com/ipfs/go-merkledag v0.11.0 h1:DgzwK5hprESOzS4O1t/wi6JDpyVQdvm9Bs59N/jqfBY= -github.com/ipfs/go-merkledag v0.11.0/go.mod h1:Q4f/1ezvBiJV0YCIXvt51W/9/kqJGH4I1LsA7+djsM4= -github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= -github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= -github.com/ipfs/go-path v0.3.0 h1:tkjga3MtpXyM5v+3EbRvOHEoo+frwi4oumw5K+KYWyA= -github.com/ipfs/go-path v0.3.0/go.mod h1:NOScsVgxfC/eIw4nz6OiGwK42PjaSJ4Y/ZFPn1Xe07I= -github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= -github.com/ipfs/go-peertaskqueue v0.7.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= -github.com/ipfs/go-peertaskqueue v0.8.1 h1:YhxAs1+wxb5jk7RvS0LHdyiILpNmRIRnZVztekOF0pg= -github.com/ipfs/go-peertaskqueue v0.8.1/go.mod h1:Oxxd3eaK279FxeydSPPVGHzbwVeHjatZ2GA8XD+KbPU= -github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= -github.com/ipfs/go-unixfs v0.4.5 h1:wj8JhxvV1G6CD7swACwSKYa+NgtdWC1RUit+gFnymDU= -github.com/ipfs/go-unixfs v0.4.5/go.mod h1:BIznJNvt/gEx/ooRMI4Us9K8+qeGO7vx1ohnbk8gjFg= -github.com/ipfs/go-unixfsnode v1.1.2/go.mod h1:5dcE2x03pyjHk4JjamXmunTMzz+VUtqvPwZjIEkfV6s= -github.com/ipfs/go-unixfsnode v1.8.1 h1:nEWQl2XL+Zoyh6u0OMzNI8mUeCKLyRgg65WDbTm/oNU= -github.com/ipfs/go-unixfsnode v1.8.1/go.mod h1:HxRu9HYHOjK6HUqFBAi++7DVoWAHn0o4v/nZ/VA+0g8= -github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= -github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs= -github.com/ipfs/go-verifcid v0.0.2/go.mod h1:40cD9x1y4OWnFXbLNJYRe7MpNvWlMn3LZAG5Wb4xnPU= -github.com/ipfs/interface-go-ipfs-core v0.11.2 h1:vI9XEm9iC4iRNcyc8N4NkMdq4BvTYLBVxZC2uEd8HwU= -github.com/ipfs/interface-go-ipfs-core v0.11.2/go.mod h1:xmnoccUXY7N/Q8AIx0vFqgW926/FAZ8+do/1NTEHKsU= -github.com/ipfs/kubo v0.25.0 h1:VKy9oOBW34xTqwi70FPRsoA3vJJBSdaYAbgIm5NmIbY= -github.com/ipfs/kubo v0.25.0/go.mod h1:ZWSvdTvD7VLqYdquESyGTAkbiqODbLwyNCuqeOtPKsQ= -github.com/ipld/go-car/v2 v2.10.2-0.20230622090957-499d0c909d33 h1:0OZwzSYWIuiKEOXd/2vm5cMcEmmGLFn+1h6lHELCm3s= -github.com/ipld/go-car/v2 v2.10.2-0.20230622090957-499d0c909d33/go.mod h1:sQEkXVM3csejlb1kCCb+vQ/pWBKX9QtvsrysMQjOgOg= -github.com/ipld/go-codec-dagpb v1.3.0/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= -github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc= -github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s= -github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= -github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= -github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= -github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E= -github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ= -github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd h1:gMlw/MhNr2Wtp5RwGdsW23cs+yCuj9k2ON7i9MiJlRo= -github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd/go.mod h1:wZ8hH8UxeryOs4kJEJaiui/s00hDSbE37OKsL47g+Sw= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= -github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= -github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= +github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= -github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= -github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs= -github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= -github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= -github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs= -github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= -github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= -github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= -github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= -github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/clock v0.0.0-20180524022203-d293bb356ca4/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA= github.com/juju/errors v0.0.0-20150916125642-1b5e39b83d18/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5 h1:rhqTjzJlm7EbkELJDKMTU7udov+Se0xZkWmugr6zGok= github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= -github.com/juju/loggo v0.0.0-20170605014607-8232ab8918d9 h1:Y+lzErDTURqeXqlqYi4YBYbDd7ycU74gW1ADt57/bgY= github.com/juju/loggo v0.0.0-20170605014607-8232ab8918d9/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/loggo v0.0.0-20180524022052-584905176618 h1:MK144iBQF9hTSwBW/9eJm034bVoG30IshVm688T2hi8= +github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/juju/retry v0.0.0-20160928201858-1998d01ba1c3/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= +github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= github.com/juju/testing v0.0.0-20200510222523-6c8c298c77a0 h1:+WWUkhnTjV6RNOxkcwk79qrjeyHEHvBzlneueBsatX4= github.com/juju/testing v0.0.0-20200510222523-6c8c298c77a0/go.mod h1:hpGvhGHPVbNBraRLZEhoQwFLMrjK8PSlO4D3nDjKYXo= github.com/juju/utils v0.0.0-20180808125547-9dfc6dbfb02b/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk= @@ -874,351 +451,75 @@ github.com/juju/version v0.0.0-20161031051906-1f41e27e54f2/go.mod h1:kE8gK5X0CIm github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= -github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= -github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= -github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= -github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= -github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kataras/golog v0.0.9/go.mod h1:12HJgwBIZFNGL0EJnMRhmvGA0PQGx8VFwrZtM4CqbAk= +github.com/kataras/iris/v12 v12.0.1/go.mod h1:udK4vLQKkdDqMGJJVd/msuMtN6hpYJhg/lSzuxjhO+U= +github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6im82hfqw= +github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= -github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knadh/koanf v1.4.0 h1:/k0Bh49SqLyLNfte9r6cvuZWrApOQhglOmhIU3L/zDw= github.com/knadh/koanf v1.4.0/go.mod h1:1cfH5223ZeZUOs8FU2UdTmaNfHpqgtjV0+NHjRO43gs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= -github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= -github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= -github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= +github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ= -github.com/libp2p/go-addr-util v0.0.2/go.mod h1:Ecd6Fb3yIuLzq4bD7VcywcVSBtefcAwnUISBM3WG15E= -github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= -github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= -github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= -github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= -github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= -github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= -github.com/libp2p/go-conn-security-multistream v0.2.0/go.mod h1:hZN4MjlNetKD3Rq5Jb/P5ohUnFLNzEAR4DLSzpn2QLU= -github.com/libp2p/go-conn-security-multistream v0.2.1/go.mod h1:cR1d8gA0Hr59Fj6NhaTpFhJZrjSYuNmhpT2r25zYR70= -github.com/libp2p/go-doh-resolver v0.4.0 h1:gUBa1f1XsPwtpE1du0O+nnZCUqtG7oYi7Bb+0S7FQqw= -github.com/libp2p/go-doh-resolver v0.4.0/go.mod h1:v1/jwsFusgsWIGX/c6vCRrnJ60x7bhTiq/fs2qt0cAg= -github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= -github.com/libp2p/go-eventbus v0.2.1/go.mod h1:jc2S4SoEVPP48H9Wpzm5aiGwUCBMfGhVhhBjyhhCJs8= -github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= -github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= -github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= -github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= -github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= -github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= -github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= -github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= -github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= -github.com/libp2p/go-libp2p v0.14.3/go.mod h1:d12V4PdKbpL0T1/gsUNN8DfgMuRPDX8bS2QxCZlwRH0= -github.com/libp2p/go-libp2p v0.32.2 h1:s8GYN4YJzgUoyeYNPdW7JZeZ5Ee31iNaIBfGYMAY4FQ= -github.com/libp2p/go-libp2p v0.32.2/go.mod h1:E0LKe+diV/ZVJVnOJby8VC5xzHF0660osg71skcxJvk= -github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= -github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= -github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= -github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= -github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= -github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI= -github.com/libp2p/go-libp2p-autonat v0.2.2/go.mod h1:HsM62HkqZmHR2k1xgX34WuWDzk/nBwNHoeyyT4IWV6A= -github.com/libp2p/go-libp2p-autonat v0.4.2/go.mod h1:YxaJlpr81FhdOv3W3BTconZPfhaYivRdf53g+S2wobk= -github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= -github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU= -github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= -github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= -github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU= -github.com/libp2p/go-libp2p-circuit v0.2.1/go.mod h1:BXPwYDN5A8z4OEY9sOfr2DUQMLQvKt/6oku45YUmjIo= -github.com/libp2p/go-libp2p-circuit v0.4.0/go.mod h1:t/ktoFIUzM6uLQ+o1G6NuBl2ANhBKN9Bc8jRIk31MoA= -github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= -github.com/libp2p/go-libp2p-core v0.0.2/go.mod h1:9dAcntw/n46XycV4RnlBq3BpgrmyUi9LuoTNdPrbUco= -github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE= -github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= -github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= -github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= -github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g= -github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= -github.com/libp2p/go-libp2p-core v0.3.1/go.mod h1:thvWy0hvaSBhnVBaW37BvzgVV68OUhgJJLAa6almrII= -github.com/libp2p/go-libp2p-core v0.4.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= -github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= -github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= -github.com/libp2p/go-libp2p-core v0.5.4/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= -github.com/libp2p/go-libp2p-core v0.5.5/go.mod h1:vj3awlOr9+GMZJFH9s4mpt9RHHgGqeHCopzbYKZdRjM= -github.com/libp2p/go-libp2p-core v0.5.6/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= -github.com/libp2p/go-libp2p-core v0.5.7/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= -github.com/libp2p/go-libp2p-core v0.6.0/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= -github.com/libp2p/go-libp2p-core v0.7.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= -github.com/libp2p/go-libp2p-core v0.8.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= -github.com/libp2p/go-libp2p-core v0.8.1/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= -github.com/libp2p/go-libp2p-core v0.8.2/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= -github.com/libp2p/go-libp2p-core v0.8.5/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= -github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= -github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g= -github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= -github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= -github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= -github.com/libp2p/go-libp2p-kad-dht v0.24.4 h1:ktNiJe7ffsJ1wX3ULpMCwXts99mPqGFSE/Qn1i8pErQ= -github.com/libp2p/go-libp2p-kad-dht v0.24.4/go.mod h1:ybWBJ5Fbvz9sSLkNtXt+2+bK0JB8+tRPvhBbRGHegRU= -github.com/libp2p/go-libp2p-kbucket v0.3.1/go.mod h1:oyjT5O7tS9CQurok++ERgc46YLwEpuGoFq9ubvoUOio= -github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0= -github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEHetYSPXOaJnOiD8i0= -github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= -github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= -github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= -github.com/libp2p/go-libp2p-mplex v0.2.2/go.mod h1:74S9eum0tVQdAfFiKxAyKzNdSuLqw5oadDq7+L/FELo= -github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek= -github.com/libp2p/go-libp2p-mplex v0.4.0/go.mod h1:yCyWJE2sc6TBTnFpjvLuEJgTSw/u+MamvzILKdX7asw= -github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= -github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= -github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= -github.com/libp2p/go-libp2p-nat v0.0.6/go.mod h1:iV59LVhB3IkFvS6S6sauVTSOrNEANnINbI/fkaLimiw= -github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= -github.com/libp2p/go-libp2p-noise v0.2.0/go.mod h1:IEbYhBBzGyvdLBoxxULL/SGbJARhUeqlO8lVSREYu2Q= -github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= -github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= -github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= -github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs= -github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnqhVnMNQZo9nkSCuAbnQ= -github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= -github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= -github.com/libp2p/go-libp2p-peerstore v0.2.6/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= -github.com/libp2p/go-libp2p-peerstore v0.2.7/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= -github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= -github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA= -github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw= -github.com/libp2p/go-libp2p-pubsub-router v0.6.0 h1:D30iKdlqDt5ZmLEYhHELCMRj8b4sFAqrUcshIUvVP/s= -github.com/libp2p/go-libp2p-pubsub-router v0.6.0/go.mod h1:FY/q0/RBTKsLA7l4vqC2cbRbOvyDotg8PJQ7j8FDudE= -github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= -github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= -github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0= -github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk= -github.com/libp2p/go-libp2p-routing-helpers v0.7.3 h1:u1LGzAMVRK9Nqq5aYDVOiq/HaB93U9WWczBzGyAC5ZY= -github.com/libp2p/go-libp2p-routing-helpers v0.7.3/go.mod h1:cN4mJAD/7zfPKXBcs9ze31JGYAZgzdABEm+q/hkswb8= -github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= -github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= -github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8= -github.com/libp2p/go-libp2p-secio v0.2.2/go.mod h1:wP3bS+m5AUnFA+OFO7Er03uO1mncHG0uVwGrwvjYlNY= -github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= -github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= -github.com/libp2p/go-libp2p-swarm v0.2.3/go.mod h1:P2VO/EpxRyDxtChXz/VPVXyTnszHvokHKRhfkEgFKNM= -github.com/libp2p/go-libp2p-swarm v0.2.8/go.mod h1:JQKMGSth4SMqonruY0a8yjlPVIkb0mdNSwckW7OYziM= -github.com/libp2p/go-libp2p-swarm v0.3.0/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= -github.com/libp2p/go-libp2p-swarm v0.5.0/go.mod h1:sU9i6BoHE0Ve5SKz3y9WfKrh8dUat6JknzUehFx8xW4= -github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= -github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= -github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= -github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= -github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= -github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= -github.com/libp2p/go-libp2p-testing v0.3.0/go.mod h1:efZkql4UZ7OVsEfaxNHZPzIehtsBXMrXnCfJIgDti5g= -github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= -github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= -github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= -github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M= -github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= -github.com/libp2p/go-libp2p-transport-upgrader v0.2.0/go.mod h1:mQcrHj4asu6ArfSoMuyojOdjx73Q47cYD7s5+gZOlns= -github.com/libp2p/go-libp2p-transport-upgrader v0.3.0/go.mod h1:i+SKzbRnvXdVbU3D1dwydnTmKRPXiAR/fyvi1dXuL4o= -github.com/libp2p/go-libp2p-transport-upgrader v0.4.2/go.mod h1:NR8ne1VwfreD5VIWIU62Agt/J18ekORFU/j1i2y8zvk= -github.com/libp2p/go-libp2p-xor v0.1.0 h1:hhQwT4uGrBcuAkUGXADuPltalOdpf9aag9kaYNT2tLA= -github.com/libp2p/go-libp2p-xor v0.1.0/go.mod h1:LSTM5yRnjGZbWNTA/hRwq2gGFrvRIbQJscoIL/u6InY= -github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= -github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI= -github.com/libp2p/go-libp2p-yamux v0.2.2/go.mod h1:lIohaR0pT6mOt0AZ0L2dFze9hds9Req3OfS+B+dv4qw= -github.com/libp2p/go-libp2p-yamux v0.2.5/go.mod h1:Zpgj6arbyQrmZ3wxSZxfBmbdnWtbZ48OpsfmQVTErwA= -github.com/libp2p/go-libp2p-yamux v0.2.7/go.mod h1:X28ENrBMU/nm4I3Nx4sZ4dgjZ6VhLEn0XhIoZ5viCwU= -github.com/libp2p/go-libp2p-yamux v0.2.8/go.mod h1:/t6tDqeuZf0INZMTgd0WxIRbtK2EzI2h7HbFm9eAKI4= -github.com/libp2p/go-libp2p-yamux v0.4.0/go.mod h1:+DWDjtFMzoAwYLVkNZftoucn7PelNoy5nm3tZ3/Zw30= -github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= -github.com/libp2p/go-libp2p-yamux v0.5.4/go.mod h1:tfrXbyaTqqSU654GTvK3ocnSZL3BuHoeTSqhcel1wsE= -github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= -github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M= -github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= -github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= -github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= -github.com/libp2p/go-mplex v0.1.1/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= -github.com/libp2p/go-mplex v0.1.2/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= -github.com/libp2p/go-mplex v0.2.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= -github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= -github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= -github.com/libp2p/go-msgio v0.0.3/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= -github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= -github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= -github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= -github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= -github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= -github.com/libp2p/go-nat v0.0.4/go.mod h1:Nmw50VAvKuk38jUBcmNh6p9lUJLoODbJRvYAa/+KSDo= -github.com/libp2p/go-nat v0.0.5/go.mod h1:B7NxsVNPZmRLvMOwiEO1scOSyjA56zxYAGv1yQgRkEU= -github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk= -github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk= -github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= -github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= -github.com/libp2p/go-netroute v0.1.5/go.mod h1:V1SR3AaECRkEQCoFFzYwVYWvYIEtlxx89+O3qcpCl4A= -github.com/libp2p/go-netroute v0.1.6/go.mod h1:AqhkMh0VuWmfgtxKPp3Oc1LdU5QSWS7wl0QLhSZqXxQ= -github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= -github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= -github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= -github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= -github.com/libp2p/go-reuseport v0.0.2/go.mod h1:SPD+5RwGC7rcnzngoYC86GjPzjSywuQyMVAheVBD9nQ= -github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= -github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= -github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= -github.com/libp2p/go-reuseport-transport v0.0.3/go.mod h1:Spv+MPft1exxARzP2Sruj2Wb5JSyHNncjf1Oi2dEbzM= -github.com/libp2p/go-reuseport-transport v0.0.4/go.mod h1:trPa7r/7TJK/d+0hdBLOCGvpQQVOU74OXbNCIMkufGw= -github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-sockaddr v0.1.1/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= -github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= -github.com/libp2p/go-stream-muxer-multistream v0.3.0/go.mod h1:yDh8abSIzmZtqtOt64gFJUXEryejzNb0lisTt+fAMJA= -github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= -github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= -github.com/libp2p/go-tcp-transport v0.2.0/go.mod h1:vX2U0CnWimU4h0SGSEsg++AzvBcroCGYw28kh94oLe0= -github.com/libp2p/go-tcp-transport v0.2.3/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= -github.com/libp2p/go-testutil v0.1.0/go.mod h1:81b2n5HypcVyrCg/MJx4Wgfp/VHojytjVe/gLzZ2Ehc= -github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo= -github.com/libp2p/go-ws-transport v0.2.0/go.mod h1:9BHJz/4Q5A9ludYWKoGCFC5gUElzlHoKzu0yY9p/klM= -github.com/libp2p/go-ws-transport v0.3.0/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= -github.com/libp2p/go-ws-transport v0.4.0/go.mod h1:EcIEKqf/7GDjth6ksuS/6p7R49V4CBY6/E7R/iyhYUA= -github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.3.0/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= -github.com/libp2p/go-yamux v1.4.0/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= -github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= -github.com/libp2p/go-yamux/v2 v2.2.0/go.mod h1:3So6P6TV6r75R9jiBpiIKgU/66lOarCZjqROGxzPpPQ= -github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ= -github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= -github.com/libp2p/zeroconf/v2 v2.2.0 h1:Cup06Jv6u81HLhIj1KasuNM/RHHrJ8T7wOTS4+Tv53Q= -github.com/libp2p/zeroconf/v2 v2.2.0/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lucas-clemente/quic-go v0.19.3/go.mod h1:ADXpNbTQjq1hIzCpB+y/k5iz4n4z4IwqoLb94Kh5Hu8= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easygo v0.0.0-20190618140210-3c14a0dc985f h1:4+gHs0jJFJ06bfN8PshnM6cHcxGjRUVRLo5jndDiKRQ= github.com/mailru/easygo v0.0.0-20190618140210-3c14a0dc985f/go.mod h1:tHCZHV8b2A90ObojrEAzY0Lb03gxUxjDHr5IJyAh4ew= -github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= -github.com/marten-seemann/qtls v0.10.0/go.mod h1:UvMd1oaYDACI99/oZUYLzMCkBXQVT0aGm99sJhbT8hs= -github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= -github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= +github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= -github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= -github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= -github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= -github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= -github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= -github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= -github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= @@ -1231,448 +532,155 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= -github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= -github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= -github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= -github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= -github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= -github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= -github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= -github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= -github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= -github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= -github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= -github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= -github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE= -github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8= -github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= -github.com/multiformats/go-multiaddr-dns v0.3.0/go.mod h1:mNzQ4eTGDg0ll1N9jKPOUogZPoJ30W8a7zk66FQPpdQ= -github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= -github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= -github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= -github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= -github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= -github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= -github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= -github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= -github.com/multiformats/go-multiaddr-net v0.1.2/go.mod h1:QsWt3XK/3hwvNxZJp92iMQKME1qHfpYmyIjFVsSOY6Y= -github.com/multiformats/go-multiaddr-net v0.1.3/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= -github.com/multiformats/go-multiaddr-net v0.1.4/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= -github.com/multiformats/go-multiaddr-net v0.1.5/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= -github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= -github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= -github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= -github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= -github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= -github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= -github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= -github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= -github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg= -github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= -github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= -github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= -github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= -github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= -github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= -github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84= -github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= -github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= -github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= -github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= -github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= -github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= -github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= -github.com/multiformats/go-multistream v0.2.2/go.mod h1:UIcnm7Zuo8HKG+HkWgfQsGL+/MIEhyTqbODbIUwSXKs= -github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE= -github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA= -github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= -github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= +github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= -github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.4.1 h1:kNd/ST2yLLWhaWrkgchya40TJabe8Hioj9udfPcEO5A= -github.com/openzipkin/zipkin-go v0.4.1/go.mod h1:qY0VqDSN1pOBN94dBc6w2GJlWLiovAyg7Qt6/I9HecM= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk= -github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8= -github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0= -github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= -github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= -github.com/pion/ice/v2 v2.3.6 h1:Jgqw36cAud47iD+N6rNX225uHvrgWtAlHfVyOQc3Heg= -github.com/pion/ice/v2 v2.3.6/go.mod h1:9/TzKDRwBVAPsC+YOrKH/e3xDrubeTRACU9/sHQarsU= -github.com/pion/interceptor v0.1.17 h1:prJtgwFh/gB8zMqGZoOgJPHivOwVAp61i2aG61Du/1w= -github.com/pion/interceptor v0.1.17/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI= -github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= -github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U= -github.com/pion/mdns v0.0.7/go.mod h1:4iP2UbeFhLI/vWju/bw6ZfwjJzk0z8DNValjGxR/dD8= -github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= -github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc= -github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I= -github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA= -github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= -github.com/pion/sctp v1.8.7 h1:JnABvFakZueGAn4KU/4PSKg+GWbF6QWbKTWZOSGJjXw= -github.com/pion/sctp v1.8.7/go.mod h1:g1Ul+ARqZq5JEmoFy87Q/4CePtKnTJ1QCL9dBBdN6AU= -github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw= -github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= -github.com/pion/srtp/v2 v2.0.15 h1:+tqRtXGsGwHC0G0IUIAzRmdkHvriF79IHVfZGfHrQoA= -github.com/pion/srtp/v2 v2.0.15/go.mod h1:b/pQOlDrbB0HEH5EUAQXzSYxikFbNcNuKmF8tM0hCtw= -github.com/pion/stun v0.4.0/go.mod h1:QPsh1/SbXASntw3zkkrIk3ZJVKz4saBY2G7S10P3wCw= -github.com/pion/stun v0.6.0 h1:JHT/2iyGDPrFWE8NNC15wnddBN8KifsEDw8swQmrEmU= -github.com/pion/stun v0.6.0/go.mod h1:HPqcfoeqQn9cuaet7AOmB5e5xkObu9DwBdurwLKO9oA= -github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40= -github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI= -github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc= -github.com/pion/transport/v2 v2.1.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ= -github.com/pion/transport/v2 v2.2.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ= -github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= -github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= -github.com/pion/turn/v2 v2.1.0 h1:5wGHSgGhJhP/RpabkUb/T9PdsAjkGLS6toYz5HNzoSI= -github.com/pion/turn/v2 v2.1.0/go.mod h1:yrT5XbXSGX1VFSF31A3c1kCNB5bBZgk/uu5LET162qs= -github.com/pion/webrtc/v3 v3.2.9 h1:U8NSjQDlZZ+Iy/hg42Q/u6mhEVSXYvKrOIZiZwYTfLc= -github.com/pion/webrtc/v3 v3.2.9/go.mod h1:gjQLMZeyN3jXBGdxGmUYCyKjOuYX/c99BDjGqmadq0A= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= -github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= -github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= -github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= -github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= -github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= -github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg= -github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= -github.com/quic-go/quic-go v0.39.4 h1:PelfiuG7wXEffUT2yceiqz5V6Pc0TA5ruOd1LcmFc1s= -github.com/quic-go/quic-go v0.39.4/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q= -github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY= -github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc= -github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= -github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/r3labs/diff/v3 v3.0.1 h1:CBKqf3XmNRHXKmdU7mZP1w7TV0pDyVCis1AUHtA4Xtg= +github.com/r3labs/diff/v3 v3.0.1/go.mod h1:f1S9bourRbiM66NskseyUdo0fTmEE0qKrikYJX63dgo= github.com/rhnvrm/simples3 v0.6.1 h1:H0DJwybR6ryQE+Odi9eqkHuzjYAeJgtGcGtuBwOhsH8= github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= -github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 h1:ZyM/+FYnpbZsFWuCohniM56kRoHRB4r5EuIzXEYkpxo= -github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703/go.mod h1:nVwGv4MP47T0jvlk7KuTTjjuSmrGO4JF0iaiNt4bufE= +github.com/rivo/tview v0.0.0-20240307173318-e804876934a1 h1:bWLHTRekAy497pE7+nXSuzXwwFHI0XauRzz6roUvY+s= +github.com/rivo/tview v0.0.0-20240307173318-e804876934a1/go.mod h1:02iFIz7K/A9jGCvrizLPvoqr4cEIx7q54RH5Qudkrss= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= -github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= -github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= -github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= -github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= -github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= -github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= -github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk= -github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk= -github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= -github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= -github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= -github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb h1:Ywfo8sUltxogBpFuMOFRrrSifO788kAFxmvVw31PtQQ= -github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb/go.mod h1:ikPs9bRWicNw3S7XpJ8sK/smGwU9WcSVU3dy9qahYBM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= -github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE= -github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= -github.com/warpfork/go-testmark v0.9.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= -github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s= -github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y= -github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= -github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= -github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= -github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= -github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/wasmerio/wasmer-go v1.0.4 h1:MnqHoOGfiQ8MMq2RF6wyCeebKOe84G88h5yv+vmxJgs= github.com/wasmerio/wasmer-go v1.0.4/go.mod h1:0gzVdSfg6pysA6QVp6iVRPTagC6Wq9pOE8J86WKb2Fk= github.com/wealdtech/go-merkletree v1.0.0 h1:DsF1xMzj5rK3pSQM6mPv8jlyJyHXhFxpnA2bwEjMMBY= github.com/wealdtech/go-merkletree v1.0.0/go.mod h1:cdil512d/8ZC7Kx3bfrDvGMQXB25NTKbsm0rFrmDax4= -github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4= -github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= -github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= -github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= -github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa h1:EyA027ZAkuaCLoxVX4r1TZMPy1d31fM6hbfQ4OU4I5o= -github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= -github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= -github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= -github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= -github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= -github.com/whyrusleeping/go-logging v0.0.1/go.mod h1:lDPYj54zutzG1XYfHAhcc7oNXEburHQBn+Iqd4yS4vE= -github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= -github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= -github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= -github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= -github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= -github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= -github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= @@ -1684,122 +692,26 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLCur2yWnJzwQEKRcAHXo6seXGuSwWw= github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= -go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= -go.opentelemetry.io/otel/exporters/jaeger v1.14.0 h1:CjbUNd4iN2hHmWekmOqZ+zSCU+dzZppG8XsV+A3oc8Q= -go.opentelemetry.io/otel/exporters/jaeger v1.14.0/go.mod h1:4Ay9kk5vELRrbg5z4cpP9EtmQRFap2Wb0woPG4lujZA= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0/go.mod h1:vLarbg68dH2Wa77g71zmKQqlQ8+8Rq3GRG31uc0WcWI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 h1:cbsD4cUcviQGXdw8+bo5x2wazq10SKz8hEbtCRPcU78= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0/go.mod h1:JgXSGah17croqhJfhByOLVY719k1emAXC8MVhCIJlRs= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0 h1:ap+y8RXX3Mu9apKVtOkM6WSFESLM8K3wNQyOU8sWHcc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0/go.mod h1:5w41DY6S9gZrbjuq6Y+753e96WfPha5IcsOSZTtullM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 h1:iqjq9LAB8aK++sKVcELezzn655JnBNdsDhghU4G/So8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0/go.mod h1:hGXzO5bhhSHZnKvrDaXB82Y9DRFour0Nz/KrBh7reWw= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0 h1:sEL90JjOO/4yhquXl5zTAkLLsZ5+MycAgX99SDsxGc8= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0/go.mod h1:oCslUcizYdpKYyS9e8srZEqM6BB8fq41VJBjLAE6z1w= -go.opentelemetry.io/otel/exporters/zipkin v1.14.0 h1:reEVE1upBF9tcujgvSqLJS0SrI7JQPaTKP4s4rymnSs= -go.opentelemetry.io/otel/exporters/zipkin v1.14.0/go.mod h1:RcjvOAcvhzcufQP8aHmzRw1gE9g/VEZufDdo2w+s4sk= -go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= -go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= -go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= -go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= -go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= -go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= -go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= -go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk= -go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg= -go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= -go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= -go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg= -go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= -go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= -golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180214000028-650f4a345ab4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1812,11 +724,10 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No= -golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1827,7 +738,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1836,43 +746,29 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1890,34 +786,21 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1933,57 +816,37 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1995,83 +858,54 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -2089,18 +923,13 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -2120,10 +949,7 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= @@ -2132,14 +958,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= -gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -2157,8 +975,6 @@ google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -2166,16 +982,11 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -2194,48 +1005,27 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -2248,9 +1038,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2260,46 +1049,30 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20160818015218-f2b6f6c918c4/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= -gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170712054546-1be3d31502d6/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2307,17 +1080,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= -lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= -lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= -pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g= -pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= From bd65bdcef1438452ae4e3111a6e74d10902d06ac Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 13 Mar 2024 17:48:58 -0600 Subject: [PATCH 753/775] fix merge errors --- arbcompress/compress_wasm.go | 4 ++-- arbitrator/jit/src/main.rs | 2 +- arbitrator/prover/test-cases/go/main.go | 7 +++++++ arbitrator/wasm-libraries/host-io/src/lib.rs | 2 +- execution/interface.go | 1 + system_tests/precompile_test.go | 2 +- wavmio/higher.go | 2 +- wavmio/raw.go | 2 +- 8 files changed, 15 insertions(+), 7 deletions(-) diff --git a/arbcompress/compress_wasm.go b/arbcompress/compress_wasm.go index 250b46705..f1139a4dc 100644 --- a/arbcompress/compress_wasm.go +++ b/arbcompress/compress_wasm.go @@ -31,14 +31,14 @@ func Decompress(input []byte, maxSize int) ([]byte, error) { return outBuf[:outLen], nil } -func compressLevel(input []byte, level uint32) ([]byte, error) { +func compressLevel(input []byte, level int) ([]byte, error) { maxOutSize := compressedBufferSizeFor(len(input)) outBuf := make([]byte, maxOutSize) outLen := uint32(len(outBuf)) status := brotliCompress( arbutil.SliceToUnsafePointer(input), uint32(len(input)), arbutil.SliceToUnsafePointer(outBuf), unsafe.Pointer(&outLen), - level, + uint32(level), WINDOW_SIZE, ) if status != BrotliSuccess { diff --git a/arbitrator/jit/src/main.rs b/arbitrator/jit/src/main.rs index c3509bad7..be93c7088 100644 --- a/arbitrator/jit/src/main.rs +++ b/arbitrator/jit/src/main.rs @@ -79,7 +79,7 @@ fn main() -> Result<()> { } }; - let memory_used = instance.exports.get_memory("mem").unwrap().view(&mut store).size().0 as u64 * 65_536; + let memory_used = instance.exports.get_memory("memory").unwrap().view(&mut store).size().0 as u64 * 65_536; let env = env.as_mut(&mut store); let user = env.process.socket.is_none(); diff --git a/arbitrator/prover/test-cases/go/main.go b/arbitrator/prover/test-cases/go/main.go index 3b21234db..0df801044 100644 --- a/arbitrator/prover/test-cases/go/main.go +++ b/arbitrator/prover/test-cases/go/main.go @@ -5,15 +5,22 @@ package main import ( "bytes" + "crypto/sha512" + "encoding/hex" "fmt" "math/big" "os" "runtime" + "sync" "time" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" merkletree "github.com/wealdtech/go-merkletree" "github.com/offchainlabs/nitro/arbcompress" + "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/wavmio" ) // MerkleSample is an example using the Merkle tree to generate and verify proofs. diff --git a/arbitrator/wasm-libraries/host-io/src/lib.rs b/arbitrator/wasm-libraries/host-io/src/lib.rs index 4e88a0b6c..c7f43c279 100644 --- a/arbitrator/wasm-libraries/host-io/src/lib.rs +++ b/arbitrator/wasm-libraries/host-io/src/lib.rs @@ -114,7 +114,7 @@ pub unsafe extern "C" fn wavmio__readDelayedInboxMessage( /// Retrieves the preimage of the given hash. #[no_mangle] -pub unsafe extern "C" fn wavmio__resolveTypedPreImage( +pub unsafe extern "C" fn wavmio__resolveTypedPreimage( preimage_type: u8, hash_ptr: GuestPtr, offset: usize, diff --git a/execution/interface.go b/execution/interface.go index 2adf8b148..7fc62a2dc 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/validator" diff --git a/system_tests/precompile_test.go b/system_tests/precompile_test.go index 0ad0f8f1e..9e829124e 100644 --- a/system_tests/precompile_test.go +++ b/system_tests/precompile_test.go @@ -68,7 +68,7 @@ func TestCustomSolidityErrors(t *testing.T) { Fatal(t, "customRevert call should have errored") } observedMessage := customError.Error() - expectedError := "Custom(1024, This spider family wards off bugs: /\\oo/\\ //\\(oo)/\\ /\\oo/\\, true)" + expectedError := "Custom(1024, This spider family wards off bugs: /\\oo/\\ //\\(oo)//\\ /\\oo/\\, true)" // The first error is server side. The second error is client side ABI decoding. expectedMessage := fmt.Sprintf("execution reverted: error %v: %v", expectedError, expectedError) if observedMessage != expectedMessage { diff --git a/wavmio/higher.go b/wavmio/higher.go index 476dabc47..0fb5516c1 100644 --- a/wavmio/higher.go +++ b/wavmio/higher.go @@ -70,7 +70,7 @@ func AdvanceInboxMessage() { func ResolveTypedPreimage(ty arbutil.PreimageType, hash common.Hash) ([]byte, error) { return readBuffer(func(offset uint32, buf unsafe.Pointer) uint32 { hashUnsafe := unsafe.Pointer(&hash[0]) - return resolveTypedPreimage(uint8(ty), hashUnsafe, offset, buf) + return resolveTypedPreimage(uint32(ty), hashUnsafe, offset, buf) }), nil } diff --git a/wavmio/raw.go b/wavmio/raw.go index 7858eea27..c09543f84 100644 --- a/wavmio/raw.go +++ b/wavmio/raw.go @@ -27,4 +27,4 @@ func readInboxMessage(msgNum uint64, offset uint32, output unsafe.Pointer) uint3 func readDelayedInboxMessage(seqNum uint64, offset uint32, output unsafe.Pointer) uint32 //go:wasmimport wavmio resolveTypedPreimage -func resolveTypedPreimage(ty uint8, hash unsafe.Pointer, offset uint32, output unsafe.Pointer) uint32 +func resolveTypedPreimage(ty uint32, hash unsafe.Pointer, offset uint32, output unsafe.Pointer) uint32 From 09d7c5fc0f2ee2dfec8aff4b08f2a38137f2fc08 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 13 Mar 2024 18:08:20 -0600 Subject: [PATCH 754/775] programs: fix calls to WasmAccountTouchCost --- arbos/programs/api.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arbos/programs/api.go b/arbos/programs/api.go index 9369cc626..68237a13d 100644 --- a/arbos/programs/api.go +++ b/arbos/programs/api.go @@ -52,6 +52,7 @@ func newApiClosures( evm := interpreter.Evm() depth := evm.Depth() db := evm.StateDB + chainConfig := evm.ChainConfig() getBytes32 := func(key common.Hash) (common.Hash, uint64) { if tracingInfo != nil { @@ -208,7 +209,7 @@ func newApiClosures( return nil } accountBalance := func(address common.Address) (common.Hash, uint64) { - cost := vm.WasmAccountTouchCost(evm.StateDB, address, false) + cost := vm.WasmAccountTouchCost(chainConfig, evm.StateDB, address, false) balance := evm.StateDB.GetBalance(address) return common.BigToHash(balance), cost } @@ -216,14 +217,14 @@ func newApiClosures( // In the future it'll be possible to know the size of a contract before loading it. // For now, require the worst case before doing the load. - cost := vm.WasmAccountTouchCost(evm.StateDB, address, true) + cost := vm.WasmAccountTouchCost(chainConfig, evm.StateDB, address, true) if gas < cost { return []byte{}, cost } return evm.StateDB.GetCode(address), cost } accountCodehash := func(address common.Address) (common.Hash, uint64) { - cost := vm.WasmAccountTouchCost(evm.StateDB, address, false) + cost := vm.WasmAccountTouchCost(chainConfig, evm.StateDB, address, false) return evm.StateDB.GetCodeHash(address), cost } addPages := func(pages uint16) uint64 { From 50ff20ca83ad2fedec4f641764be7afae284d987 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 13 Mar 2024 18:09:10 -0600 Subject: [PATCH 755/775] precompile: limit programs to latest sytlus --- arbos/arbostypes/incomingmessage.go | 1 + precompiles/precompile.go | 19 +++++++++++++++++-- precompiles/precompile_test.go | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/arbos/arbostypes/incomingmessage.go b/arbos/arbostypes/incomingmessage.go index 1dc75c3e3..3a886b436 100644 --- a/arbos/arbostypes/incomingmessage.go +++ b/arbos/arbostypes/incomingmessage.go @@ -35,6 +35,7 @@ const ( const MaxL2MessageSize = 256 * 1024 const ArbosVersion_FixRedeemGas = uint64(11) +const ArbosVersion_Stylus = uint64(20) type L1IncomingMessageHeader struct { Kind uint8 `json:"kind"` diff --git a/precompiles/precompile.go b/precompiles/precompile.go index 1673600a0..2a21ff5f8 100644 --- a/precompiles/precompile.go +++ b/precompiles/precompile.go @@ -14,6 +14,7 @@ import ( "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/arbos/arbosState" + "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbos/programs" "github.com/offchainlabs/nitro/arbos/util" templates "github.com/offchainlabs/nitro/solgen/go/precompilesgen" @@ -561,12 +562,15 @@ func Precompiles() map[addr]ArbosPrecompile { ArbWasmImpl := &ArbWasm{Address: types.ArbWasmAddress} ArbWasm := insert(MakePrecompile(templates.ArbWasmMetaData, ArbWasmImpl)) - ArbWasm.arbosVersion = 11 + ArbWasm.arbosVersion = arbostypes.ArbosVersion_Stylus programs.ProgramNotActivatedError = ArbWasmImpl.ProgramNotActivatedError programs.ProgramNeedsUpgradeError = ArbWasmImpl.ProgramNeedsUpgradeError programs.ProgramExpiredError = ArbWasmImpl.ProgramExpiredError programs.ProgramUpToDateError = ArbWasmImpl.ProgramUpToDateError programs.ProgramKeepaliveTooSoon = ArbWasmImpl.ProgramKeepaliveTooSoonError + for _, method := range ArbWasm.methods { + method.arbosVersion = arbostypes.ArbosVersion_Stylus + } ArbRetryableImpl := &ArbRetryableTx{Address: types.ArbRetryableTxAddress} ArbRetryable := insert(MakePrecompile(templates.ArbRetryableTxMetaData, ArbRetryableImpl)) @@ -603,9 +607,20 @@ func Precompiles() map[addr]ArbosPrecompile { ArbOwner.methodsByName["ReleaseL1PricerSurplusFunds"].arbosVersion = 10 ArbOwner.methodsByName["SetChainConfig"].arbosVersion = 11 ArbOwner.methodsByName["SetBrotliCompressionLevel"].arbosVersion = 20 + ArbOwner.methodsByName["SetInkPrice"].arbosVersion = arbostypes.ArbosVersion_Stylus + ArbOwner.methodsByName["SetWasmMaxStackDepth"].arbosVersion = arbostypes.ArbosVersion_Stylus + ArbOwner.methodsByName["SetWasmFreePages"].arbosVersion = arbostypes.ArbosVersion_Stylus + ArbOwner.methodsByName["SetWasmPageGas"].arbosVersion = arbostypes.ArbosVersion_Stylus + ArbOwner.methodsByName["SetWasmPageRamp"].arbosVersion = arbostypes.ArbosVersion_Stylus + ArbOwner.methodsByName["SetWasmPageLimit"].arbosVersion = arbostypes.ArbosVersion_Stylus + ArbOwner.methodsByName["SetWasmMinInitGas"].arbosVersion = arbostypes.ArbosVersion_Stylus + ArbOwner.methodsByName["SetWasmExpiryDays"].arbosVersion = arbostypes.ArbosVersion_Stylus + ArbOwner.methodsByName["SetWasmKeepaliveDays"].arbosVersion = arbostypes.ArbosVersion_Stylus insert(ownerOnly(ArbOwnerImpl.Address, ArbOwner, emitOwnerActs)) - insert(debugOnly(MakePrecompile(templates.ArbDebugMetaData, &ArbDebug{Address: hex("ff")}))) + _, arbDebug := MakePrecompile(templates.ArbDebugMetaData, &ArbDebug{Address: hex("ff")}) + arbDebug.methodsByName["Panic"].arbosVersion = arbostypes.ArbosVersion_Stylus + insert(debugOnly(arbDebug.address, arbDebug)) ArbosActs := insert(MakePrecompile(templates.ArbosActsMetaData, &ArbosActs{Address: types.ArbosAddress})) arbos.InternalTxStartBlockMethodID = ArbosActs.GetMethodID("StartBlock") diff --git a/precompiles/precompile_test.go b/precompiles/precompile_test.go index 975856bce..0bb4e4554 100644 --- a/precompiles/precompile_test.go +++ b/precompiles/precompile_test.go @@ -190,7 +190,7 @@ func TestPrecompilesPerArbosVersion(t *testing.T) { 5: 3, 10: 2, 11: 4, - 20: 8, + 20: 8 + 27, // 27 for stylus } precompiles := Precompiles() From 63cf663e6ceeb708472ec283e51b20026447994a Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 13 Mar 2024 18:09:57 -0600 Subject: [PATCH 756/775] program_test: use systest builder --- system_tests/program_test.go | 159 +++++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 63 deletions(-) diff --git a/system_tests/program_test.go b/system_tests/program_test.go index 931f24daa..da7f965f1 100644 --- a/system_tests/program_test.go +++ b/system_tests/program_test.go @@ -10,7 +10,6 @@ import ( "encoding/json" "fmt" "math/big" - "math/rand" "os" "path/filepath" "strings" @@ -27,9 +26,7 @@ import ( "github.com/ethereum/go-ethereum/eth/tracers" _ "github.com/ethereum/go-ethereum/eth/tracers/js" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbcompress" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/programs" "github.com/offchainlabs/nitro/arbos/util" "github.com/offchainlabs/nitro/arbutil" @@ -50,7 +47,9 @@ func TestProgramKeccak(t *testing.T) { } func keccakTest(t *testing.T, jit bool) { - ctx, node, _, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2client := builder.L2.Client defer cleanup() programAddress := deployWasm(t, ctx, auth, l2client, rustFile("keccak")) @@ -72,7 +71,7 @@ func keccakTest(t *testing.T, jit bool) { stylusVersion, err := arbWasm.StylusVersion(nil) Require(t, err) - statedb, err := node.Execution.Backend.ArbInterface().BlockChain().State() + statedb, err := builder.L2.ExecNode.Backend.ArbInterface().BlockChain().State() Require(t, err) codehashVersion, err := arbWasm.CodehashVersion(nil, statedb.GetCodeHash(programAddress)) Require(t, err) @@ -133,7 +132,7 @@ func keccakTest(t *testing.T, jit bool) { ensure(mock.CallKeccak(&auth, programAddress, args)) ensure(mock.CallKeccak(&auth, otherAddressSameCode, args)) - validateBlocks(t, 1, jit, ctx, node, l2client) + validateBlocks(t, 1, jit, builder) } func TestProgramActivateTwice(t *testing.T) { @@ -142,7 +141,10 @@ func TestProgramActivateTwice(t *testing.T) { } func testActivateTwice(t *testing.T, jit bool) { - ctx, node, l2info, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client defer cleanup() ensure := func(tx *types.Transaction, err error) *types.Receipt { @@ -219,7 +221,7 @@ func testActivateTwice(t *testing.T, jit bool) { tx = l2info.PrepareTxTo("Owner", &multiAddr, 1e9, oneEth, args) ensure(tx, l2client.SendTransaction(ctx, tx)) - validateBlocks(t, 7, jit, ctx, node, l2client) + validateBlocks(t, 7, jit, builder) } func TestProgramErrors(t *testing.T) { @@ -228,7 +230,10 @@ func TestProgramErrors(t *testing.T) { } func errorTest(t *testing.T, jit bool) { - ctx, node, l2info, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client defer cleanup() programAddress := deployWasm(t, ctx, auth, l2client, rustFile("fallible")) @@ -258,7 +263,7 @@ func errorTest(t *testing.T, jit bool) { Require(t, l2client.SendTransaction(ctx, tx)) EnsureTxFailed(t, ctx, l2client, tx) - validateBlocks(t, 7, jit, ctx, node, l2client) + validateBlocks(t, 7, jit, builder) } func TestProgramStorage(t *testing.T) { @@ -267,7 +272,10 @@ func TestProgramStorage(t *testing.T) { } func storageTest(t *testing.T, jit bool) { - ctx, node, l2info, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client defer cleanup() programAddress := deployWasm(t, ctx, auth, l2client, rustFile("storage")) @@ -285,7 +293,7 @@ func storageTest(t *testing.T, jit bool) { ensure(tx, l2client.SendTransaction(ctx, tx)) assertStorageAt(t, ctx, l2client, programAddress, key, value) - validateBlocks(t, 2, jit, ctx, node, l2client) + validateBlocks(t, 2, jit, builder) } func TestProgramCalls(t *testing.T) { @@ -294,7 +302,10 @@ func TestProgramCalls(t *testing.T) { } func testCalls(t *testing.T, jit bool) { - ctx, node, l2info, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client defer cleanup() callsAddr := deployWasm(t, ctx, auth, l2client, rustFile("multicall")) @@ -478,7 +489,7 @@ func testCalls(t *testing.T, jit bool) { } blocks := []uint64{10} - validateBlockRange(t, blocks, jit, ctx, node, l2client) + validateBlockRange(t, blocks, jit, builder) } func TestProgramReturnData(t *testing.T) { @@ -487,7 +498,10 @@ func TestProgramReturnData(t *testing.T) { } func testReturnData(t *testing.T, jit bool) { - ctx, node, l2info, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client defer cleanup() ensure := func(tx *types.Transaction, err error) { @@ -528,7 +542,7 @@ func testReturnData(t *testing.T, jit bool) { testReadReturnData(2, 0, 0, 0, 1) testReadReturnData(2, 0, 4, 4, 1) - validateBlocks(t, 11, jit, ctx, node, l2client) + validateBlocks(t, 11, jit, builder) } func TestProgramLogs(t *testing.T) { @@ -537,7 +551,10 @@ func TestProgramLogs(t *testing.T) { } func testLogs(t *testing.T, jit bool) { - ctx, node, l2info, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client defer cleanup() logAddr := deployWasm(t, ctx, auth, l2client, rustFile("log")) multiAddr := deployWasm(t, ctx, auth, l2client, rustFile("multicall")) @@ -601,7 +618,7 @@ func testLogs(t *testing.T, jit bool) { Fatal(t, "wrong address", receipt.Logs[0].Address) } - validateBlocks(t, 11, jit, ctx, node, l2client) + validateBlocks(t, 11, jit, builder) } func TestProgramCreate(t *testing.T) { @@ -610,7 +627,10 @@ func TestProgramCreate(t *testing.T) { } func testCreate(t *testing.T, jit bool) { - ctx, node, l2info, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client defer cleanup() createAddr := deployWasm(t, ctx, auth, l2client, rustFile("create")) activateAuth := auth @@ -694,7 +714,7 @@ func testCreate(t *testing.T, jit bool) { // validate just the opcodes blocks := []uint64{5, 6} - validateBlockRange(t, blocks, jit, ctx, node, l2client) + validateBlockRange(t, blocks, jit, builder) } func TestProgramEvmData(t *testing.T) { @@ -703,7 +723,10 @@ func TestProgramEvmData(t *testing.T) { } func testEvmData(t *testing.T, jit bool) { - ctx, node, l2info, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client defer cleanup() evmDataAddr := deployWasm(t, ctx, auth, l2client, rustFile("evm-data")) @@ -797,7 +820,7 @@ func testEvmData(t *testing.T, jit bool) { } colors.PrintGrey("trace: ", string(trace)) - validateBlocks(t, 1, jit, ctx, node, l2client) + validateBlocks(t, 1, jit, builder) } func TestProgramMemory(t *testing.T) { @@ -806,7 +829,10 @@ func TestProgramMemory(t *testing.T) { } func testMemory(t *testing.T, jit bool) { - ctx, node, l2info, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client defer cleanup() ensure := func(tx *types.Transaction, err error) *types.Receipt { @@ -913,7 +939,7 @@ func testMemory(t *testing.T, jit bool) { Fatal(t, "unexpected memory footprint", programMemoryFootprint) } - validateBlocks(t, 2, jit, ctx, node, l2client) + validateBlocks(t, 2, jit, builder) } func TestProgramActivateFails(t *testing.T) { @@ -922,7 +948,9 @@ func TestProgramActivateFails(t *testing.T) { } func testActivateFails(t *testing.T, jit bool) { - ctx, node, _, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2client := builder.L2.Client defer cleanup() arbWasm, err := precompilesgen.NewArbWasm(types.ArbWasmAddress, l2client) @@ -950,7 +978,7 @@ func testActivateFails(t *testing.T, jit bool) { blockToValidate = txRes.BlockNumber.Uint64() }) - validateBlockRange(t, []uint64{blockToValidate}, jit, ctx, node, l2client) + validateBlockRange(t, []uint64{blockToValidate}, jit, builder) } func TestProgramSdkStorage(t *testing.T) { @@ -959,7 +987,10 @@ func TestProgramSdkStorage(t *testing.T) { } func testSdkStorage(t *testing.T, jit bool) { - ctx, node, l2info, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client defer cleanup() rust := deployWasm(t, ctx, auth, l2client, rustFile("sdk-storage")) @@ -986,15 +1017,15 @@ func testSdkStorage(t *testing.T, jit bool) { colors.PrintBlue("rust ", rustCost, " sol ", solCost) // ensure txes are sequenced before checking state - waitForSequencer(t, node, receipt.BlockNumber.Uint64()) + waitForSequencer(t, builder, receipt.BlockNumber.Uint64()) - bc := node.Execution.Backend.ArbInterface().BlockChain() + bc := builder.L2.ExecNode.Backend.ArbInterface().BlockChain() statedb, err := bc.State() Require(t, err) trieHash := func(addr common.Address) common.Hash { - trie, err := statedb.StorageTrie(addr) - Require(t, err) - return trie.Hash() + stateObject := statedb.GetOrNewStateObject(addr) + return stateObject.Root() + // .StorageTrie(addr) } solTrie := trieHash(solidity) @@ -1019,7 +1050,9 @@ func testSdkStorage(t *testing.T, jit bool) { func TestProgramActivationLogs(t *testing.T) { t.Parallel() - ctx, _, _, l2client, auth, cleanup := setupProgramTest(t, true) + builder, auth, cleanup := setupProgramTest(t, true) + l2client := builder.L2.Client + ctx := builder.ctx defer cleanup() wasm, _ := readWasmFile(t, watFile("memory")) @@ -1056,44 +1089,43 @@ func TestProgramActivationLogs(t *testing.T) { } func setupProgramTest(t *testing.T, jit bool) ( - context.Context, *arbnode.Node, *BlockchainTestInfo, *ethclient.Client, bind.TransactOpts, func(), + *NodeBuilder, bind.TransactOpts, func(), ) { ctx, cancel := context.WithCancel(context.Background()) - rand.Seed(time.Now().UTC().UnixNano()) - chainConfig := params.ArbitrumDevTestChainConfig() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + + builder.nodeConfig.BlockValidator.Enable = false + builder.nodeConfig.Staker.Enable = true + builder.nodeConfig.BatchPoster.Enable = true + builder.nodeConfig.ParentChainReader.Enable = true + builder.nodeConfig.ParentChainReader.OldHeaderTimeout = 10 * time.Minute - l2config := arbnode.ConfigDefaultL1Test() - l2config.BlockValidator.Enable = false - l2config.Staker.Enable = true - l2config.BatchPoster.Enable = true - l2config.ParentChainReader.Enable = true - l2config.Sequencer.MaxRevertGasReject = 0 - l2config.ParentChainReader.OldHeaderTimeout = 10 * time.Minute valConf := valnode.TestValidationConfig valConf.UseJit = jit _, valStack := createTestValidationNode(t, ctx, &valConf) - configByValidationNode(t, l2config, valStack) + configByValidationNode(t, builder.nodeConfig, valStack) + + builder.execConfig.Sequencer.MaxRevertGasReject = 0 - l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l2config, chainConfig, nil) + builderCleanup := builder.Build(t) cleanup := func() { - requireClose(t, l1stack) - node.StopAndWait() + builderCleanup() cancel() } - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) - arbOwner, err := precompilesgen.NewArbOwner(types.ArbOwnerAddress, l2client) + arbOwner, err := precompilesgen.NewArbOwner(types.ArbOwnerAddress, builder.L2.Client) Require(t, err) - arbDebug, err := precompilesgen.NewArbDebug(types.ArbDebugAddress, l2client) + arbDebug, err := precompilesgen.NewArbDebug(types.ArbDebugAddress, builder.L2.Client) Require(t, err) ensure := func(tx *types.Transaction, err error) *types.Receipt { t.Helper() Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, l2client, tx) + receipt, err := EnsureTxSucceeded(ctx, builder.L2.Client, tx) Require(t, err) return receipt } @@ -1104,7 +1136,7 @@ func setupProgramTest(t *testing.T, jit bool) ( ensure(arbDebug.BecomeChainOwner(&auth)) ensure(arbOwner.SetInkPrice(&auth, inkPrice)) - return ctx, node, l2info, l2client, auth, cleanup + return builder, auth, cleanup } func readWasmFile(t *testing.T, file string) ([]byte, []byte) { @@ -1220,29 +1252,30 @@ func watFile(name string) string { } func validateBlocks( - t *testing.T, start uint64, jit bool, ctx context.Context, node *arbnode.Node, l2client *ethclient.Client, + t *testing.T, start uint64, jit bool, builder *NodeBuilder, ) { t.Helper() if jit || start == 0 { start = 1 } - blockHeight, err := l2client.BlockNumber(ctx) + blockHeight, err := builder.L2.Client.BlockNumber(builder.ctx) Require(t, err) blocks := []uint64{} for i := start; i <= blockHeight; i++ { blocks = append(blocks, i) } - validateBlockRange(t, blocks, jit, ctx, node, l2client) + validateBlockRange(t, blocks, jit, builder) } func validateBlockRange( t *testing.T, blocks []uint64, jit bool, - ctx context.Context, node *arbnode.Node, l2client *ethclient.Client, + builder *NodeBuilder, ) { - waitForSequencer(t, node, arbmath.MaxInt(blocks...)) - blockHeight, err := l2client.BlockNumber(ctx) + ctx := builder.ctx + waitForSequencer(t, builder, arbmath.MaxInt(blocks...)) + blockHeight, err := builder.L2.Client.BlockNumber(ctx) Require(t, err) // validate everything @@ -1259,7 +1292,7 @@ func validateBlockRange( inboxPos := arbutil.MessageIndex(block) now := time.Now() - correct, _, err := node.StatelessBlockValidator.ValidateResult(ctx, inboxPos, false, common.Hash{}) + correct, _, err := builder.L2.ConsensusNode.StatelessBlockValidator.ValidateResult(ctx, inboxPos, false, common.Hash{}) Require(t, err, "block", block) passed := formatTime(time.Since(now)) if correct { @@ -1274,15 +1307,15 @@ func validateBlockRange( } } -func waitForSequencer(t *testing.T, node *arbnode.Node, block uint64) { +func waitForSequencer(t *testing.T, builder *NodeBuilder, block uint64) { t.Helper() msgCount := arbutil.BlockNumberToMessageCount(block, 0) doUntil(t, 20*time.Millisecond, 500, func() bool { - batchCount, err := node.InboxTracker.GetBatchCount() + batchCount, err := builder.L2.ConsensusNode.InboxTracker.GetBatchCount() Require(t, err) - meta, err := node.InboxTracker.GetBatchMetadata(batchCount - 1) + meta, err := builder.L2.ConsensusNode.InboxTracker.GetBatchMetadata(batchCount - 1) Require(t, err) - msgExecuted, err := node.Execution.ExecEngine.HeadMessageNumber() + msgExecuted, err := builder.L2.ExecNode.ExecEngine.HeadMessageNumber() Require(t, err) return msgExecuted+1 >= msgCount && meta.MessageCount >= msgCount }) From 4747bf8dcda9add232af964bea189e58da249a0f Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 13 Mar 2024 19:31:36 -0600 Subject: [PATCH 757/775] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 65f616166..6160fda1d 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 65f61616648598a9909fe412f34f45533cea4133 +Subproject commit 6160fda1d05fbad2125a45c513a3724c5683dc47 From ffe5dc93d1ccebcd514a9c66737307edc23910a3 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 14 Mar 2024 13:52:40 -0600 Subject: [PATCH 758/775] add rust-src --- .github/workflows/arbitrator-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index 1206b2d0e..c875b0ef3 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -80,6 +80,7 @@ jobs: with: toolchain: "nightly" targets: 'wasm32-wasi, wasm32-unknown-unknown' + components: rust-src - name: Cache Rust intermediate build products uses: actions/cache@v3 From 5d2656a8d45723ddd208787459587959782cf168 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 14 Mar 2024 15:25:35 -0600 Subject: [PATCH 759/775] system_test: fix testEarlyExit --- system_tests/program_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/system_tests/program_test.go b/system_tests/program_test.go index e8ea65162..16d6aea5d 100644 --- a/system_tests/program_test.go +++ b/system_tests/program_test.go @@ -1094,7 +1094,9 @@ func TestProgramEarlyExit(t *testing.T) { } func testEarlyExit(t *testing.T, jit bool) { - ctx, node, _, l2client, auth, cleanup := setupProgramTest(t, jit) + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2client := builder.L2.Client defer cleanup() earlyAddress := deployWasm(t, ctx, auth, l2client, "../arbitrator/stylus/tests/exit-early/exit-early.wat") @@ -1116,7 +1118,7 @@ func testEarlyExit(t *testing.T, jit bool) { ensure(mock.CheckRevertData(&auth, earlyAddress, data, data)) ensure(mock.CheckRevertData(&auth, panicAddress, data, []byte{})) - validateBlocks(t, 8, jit, ctx, node, l2client) + validateBlocks(t, 8, jit, builder) } func setupProgramTest(t *testing.T, jit bool) ( From b51bf5641d36123ff70efa7f3261b8cb3e2ab3c0 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 14 Mar 2024 15:30:45 -0600 Subject: [PATCH 760/775] cargo fmt --- arbitrator/arbutil/src/types.rs | 3 +-- arbitrator/jit/src/machine.rs | 2 +- arbitrator/jit/src/main.rs | 10 ++++++-- arbitrator/jit/src/wavmio.rs | 15 ++++++++++-- arbitrator/prover/src/machine.rs | 40 +++++++++++++++----------------- arbitrator/prover/src/main.rs | 2 +- arbitrator/prover/src/utils.rs | 4 ++-- 7 files changed, 45 insertions(+), 31 deletions(-) diff --git a/arbitrator/arbutil/src/types.rs b/arbitrator/arbutil/src/types.rs index 4721d2a96..97b843a05 100644 --- a/arbitrator/arbutil/src/types.rs +++ b/arbitrator/arbutil/src/types.rs @@ -1,13 +1,13 @@ // Copyright 2022-2024, Offchain Labs, Inc. // For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE +use num_enum::{IntoPrimitive, TryFromPrimitive}; use serde::{Deserialize, Serialize}; use std::{ borrow::Borrow, fmt, ops::{Deref, DerefMut}, }; -use num_enum::{IntoPrimitive, TryFromPrimitive}; // These values must be kept in sync with `arbutil/preimage_type.go`, // and the if statement in `contracts/src/osp/OneStepProverHostIo.sol` (search for "UNKNOWN_PREIMAGE_TYPE"). @@ -234,4 +234,3 @@ impl From for Bytes20 { <[u8; 20]>::from(x).into() } } - diff --git a/arbitrator/jit/src/machine.rs b/arbitrator/jit/src/machine.rs index de15394cd..47f90dc10 100644 --- a/arbitrator/jit/src/machine.rs +++ b/arbitrator/jit/src/machine.rs @@ -5,7 +5,7 @@ use crate::{ arbcompress, caller_env::GoRuntimeState, program, socket, stylus_backend::CothreadHandler, wasip1_stub, wavmio, Opts, }; -use arbutil::{Bytes32, {Color}, PreimageType}; +use arbutil::{Bytes32, Color, PreimageType}; use eyre::{bail, ErrReport, Result, WrapErr}; use sha3::{Digest, Keccak256}; use std::{ diff --git a/arbitrator/jit/src/main.rs b/arbitrator/jit/src/main.rs index be93c7088..83a794316 100644 --- a/arbitrator/jit/src/main.rs +++ b/arbitrator/jit/src/main.rs @@ -57,7 +57,6 @@ fn main() -> Result<()> { let (instance, env, mut store) = machine::create(&opts, env); - let main = instance.exports.get_function("_start").unwrap(); let outcome = main.call(&mut store, &[]); let escape = match outcome { @@ -79,7 +78,14 @@ fn main() -> Result<()> { } }; - let memory_used = instance.exports.get_memory("memory").unwrap().view(&mut store).size().0 as u64 * 65_536; + let memory_used = instance + .exports + .get_memory("memory") + .unwrap() + .view(&mut store) + .size() + .0 as u64 + * 65_536; let env = env.as_mut(&mut store); let user = env.process.socket.is_none(); diff --git a/arbitrator/jit/src/wavmio.rs b/arbitrator/jit/src/wavmio.rs index f4846cb9b..ec36e4150 100644 --- a/arbitrator/jit/src/wavmio.rs +++ b/arbitrator/jit/src/wavmio.rs @@ -124,7 +124,14 @@ pub fn resolve_typed_preimage( offset: u32, out_ptr: GuestPtr, ) -> Result { - resolve_preimage_impl(env, preimage_type, hash_ptr, offset, out_ptr, "wavmio.ResolveTypedPreimage") + resolve_preimage_impl( + env, + preimage_type, + hash_ptr, + offset, + out_ptr, + "wavmio.ResolveTypedPreimage", + ) } pub fn resolve_preimage_impl( @@ -152,7 +159,11 @@ pub fn resolve_preimage_impl( let hash = mem.read_bytes32(hash_ptr); - let Some(preimage) = exec.preimages.get(&preimage_type).and_then(|m| m.get(&hash)) else { + let Some(preimage) = exec + .preimages + .get(&preimage_type) + .and_then(|m| m.get(&hash)) + else { let hash_hex = hex::encode(hash); error!("Missing requested preimage for hash {hash_hex} in {name}") }; diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index 3203e2c9c..a1ca45b43 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -1,6 +1,8 @@ // Copyright 2021-2024, Offchain Labs, Inc. // For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE +#[cfg(feature = "native")] +use crate::kzg::prove_kzg_preimage; use crate::{ binary::{ self, parse, ExportKind, ExportMap, FloatInstruction, Local, NameCustomSection, WasmBinary, @@ -19,8 +21,6 @@ use crate::{ }; use arbutil::{math, Bytes32, Color, PreimageType}; #[cfg(feature = "native")] -use crate::kzg::prove_kzg_preimage; -#[cfg(feature = "native")] use c_kzg::BYTES_PER_BLOB; use digest::Digest; use eyre::{bail, ensure, eyre, Result, WrapErr}; @@ -2293,19 +2293,20 @@ impl Machine { if offset % 32 != 0 { error!(); } - + let Some(hash) = module.memory.load_32_byte_aligned(ptr.into()) else { error!(); }; let Some(preimage) = - self.preimage_resolver.get(self.context, preimage_ty, hash) else { - eprintln!( - "{} for hash {}", - "Missing requested preimage".red(), - hash.red(), - ); - self.print_backtrace(true); - bail!("missing requested preimage for hash {}", hash); + self.preimage_resolver.get(self.context, preimage_ty, hash) + else { + eprintln!( + "{} for hash {}", + "Missing requested preimage".red(), + hash.red(), + ); + self.print_backtrace(true); + bail!("missing requested preimage for hash {}", hash); }; if preimage_ty == PreimageType::EthVersionedHash && preimage.len() != BYTES_PER_BLOB @@ -2875,12 +2876,11 @@ impl Machine { ) .expect("Invalid preimage type in ReadPreImage argument data"); let Some(preimage) = - self - .preimage_resolver + self.preimage_resolver .get_const(self.context, preimage_ty, hash) - else { - panic!("Missing requested preimage for hash {}", hash) - }; + else { + panic!("Missing requested preimage for hash {}", hash) + }; data.push(0); // preimage proof type match preimage_ty { PreimageType::Keccak256 | PreimageType::Sha2_256 => { @@ -2893,11 +2893,9 @@ impl Machine { } } } else if next_inst.opcode == Opcode::ReadInboxMessage { - let msg_idx = value_stack - .get(value_stack.len() - 3) - .unwrap() - .assume_u64(); - let inbox_identifier = argument_data_to_inbox(arg).expect("Bad inbox indentifier"); + let msg_idx = value_stack.get(value_stack.len() - 3).unwrap().assume_u64(); + let inbox_identifier = + argument_data_to_inbox(arg).expect("Bad inbox indentifier"); if let Some(msg_data) = self.inbox_contents.get(&(inbox_identifier, msg_idx)) { diff --git a/arbitrator/prover/src/main.rs b/arbitrator/prover/src/main.rs index 785bfaff0..0162a6110 100644 --- a/arbitrator/prover/src/main.rs +++ b/arbitrator/prover/src/main.rs @@ -8,7 +8,7 @@ use eyre::{eyre, Context, Result}; use fnv::{FnvHashMap as HashMap, FnvHashSet as HashSet}; use prover::{ machine::{GlobalState, InboxIdentifier, Machine, MachineStatus, PreimageResolver, ProofInfo}, - utils::{hash_preimage, file_bytes, CBytes}, + utils::{file_bytes, hash_preimage, CBytes}, wavm::Opcode, }; use std::sync::Arc; diff --git a/arbitrator/prover/src/utils.rs b/arbitrator/prover/src/utils.rs index be1086519..4045984ae 100644 --- a/arbitrator/prover/src/utils.rs +++ b/arbitrator/prover/src/utils.rs @@ -3,14 +3,14 @@ #[cfg(feature = "native")] use crate::kzg::ETHEREUM_KZG_SETTINGS; -use sha2::Sha256; -use sha3::Keccak256; use arbutil::PreimageType; #[cfg(feature = "native")] use c_kzg::{Blob, KzgCommitment}; use digest::Digest; use eyre::{eyre, Result}; use serde::{Deserialize, Serialize}; +use sha2::Sha256; +use sha3::Keccak256; use std::{borrow::Borrow, convert::TryInto, fmt, fs::File, io::Read, ops::Deref, path::Path}; use wasmparser::{TableType, ValType}; From 670e1c257813603c1855d2fc14496f7d5e857913 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 14 Mar 2024 19:06:53 -0600 Subject: [PATCH 761/775] cargo update --- arbitrator/Cargo.lock | 554 +++++++++---------- arbitrator/tools/module_roots/Cargo.lock | 652 +++++++++++++++-------- arbitrator/wasm-libraries/Cargo.lock | 339 ++++++------ 3 files changed, 883 insertions(+), 662 deletions(-) diff --git a/arbitrator/Cargo.lock b/arbitrator/Cargo.lock index 9bdae2787..e1e08c5f6 100644 --- a/arbitrator/Cargo.lock +++ b/arbitrator/Cargo.lock @@ -4,11 +4,11 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ - "gimli", + "gimli 0.28.1", ] [[package]] @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", @@ -30,18 +30,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.19" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] name = "ansi_term" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ "winapi", ] @@ -65,9 +65,9 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "atty" @@ -75,7 +75,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -88,16 +88,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", "cfg-if", "libc", "miniz_oxide", - "object 0.29.0", + "object 0.32.2", "rustc-demangle", ] @@ -187,15 +187,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "bytecheck" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ "proc-macro2", "quote", @@ -215,9 +215,9 @@ dependencies = [ [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" @@ -251,12 +251,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cfg-if" @@ -266,9 +263,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", @@ -281,9 +278,9 @@ dependencies = [ [[package]] name = "corosensei" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9847f90f32a50b0dcbd68bc23ff242798b13080b97b0569f6ed96a45ce4cf2cd" +checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" dependencies = [ "autocfg", "cfg-if", @@ -294,9 +291,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -324,7 +321,7 @@ dependencies = [ "cranelift-egraph", "cranelift-entity", "cranelift-isle", - "gimli", + "gimli 0.26.2", "log", "regalloc2", "smallvec", @@ -384,59 +381,39 @@ version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" -[[package]] -name = "crossbeam-channel" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.5" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "cfg-if", "crossbeam-utils", - "lazy_static", - "memoffset 0.6.4", - "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" -dependencies = [ - "cfg-if", - "lazy_static", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crunchy" @@ -466,12 +443,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ - "darling_core 0.20.3", - "darling_macro 0.20.3", + "darling_core 0.20.8", + "darling_macro 0.20.8", ] [[package]] @@ -490,15 +467,15 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn 2.0.45", + "syn 2.0.52", ] [[package]] @@ -514,13 +491,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ - "darling_core 0.20.3", + "darling_core 0.20.8", "quote", - "syn 2.0.45", + "syn 2.0.52", ] [[package]] @@ -589,14 +566,14 @@ checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" dependencies = [ "byteorder", "dynasm", - "memmap2 0.5.7", + "memmap2 0.5.10", ] [[package]] name = "either" -version = "1.6.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "enum-iterator" @@ -633,10 +610,10 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" dependencies = [ - "darling 0.20.3", + "darling 0.20.8", "proc-macro2", "quote", - "syn 2.0.45", + "syn 2.0.52", ] [[package]] @@ -647,9 +624,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "eyre" -version = "0.6.10" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bbb8258be8305fb0237d7b295f47bb24ff1b136a535f473baf40e70468515aa" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", @@ -669,9 +646,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -693,9 +670,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.4" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -703,9 +680,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -723,6 +700,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + [[package]] name = "glob" version = "0.3.1" @@ -762,6 +745,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hex" version = "0.4.3" @@ -776,9 +765,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -874,18 +863,18 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -904,9 +893,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "llvm-sys" @@ -933,12 +922,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "mach" @@ -951,15 +937,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" -version = "0.5.7" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" dependencies = [ "libc", ] @@ -973,15 +959,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.8.0" @@ -993,15 +970,15 @@ dependencies = [ [[package]] name = "minimal-lexical" -version = "0.1.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c835948974f68e0bd58636fc6c5b1fbff7b297e3046f11b3b3c18bbac012c6d" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -1014,13 +991,12 @@ checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] name = "nom" -version = "7.0.0" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffd9d26838a953b4af82cbeb9f1592c6798916983959be223a7124e992742c1" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", - "version_check", ] [[package]] @@ -1036,9 +1012,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ "num-bigint", "num-complex", @@ -1061,39 +1037,38 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.0" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" dependencies = [ "num-traits", ] [[package]] name = "num-derive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.45", + "syn 2.0.52", ] [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.42" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ "autocfg", "num-integer", @@ -1102,9 +1077,9 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", "num-bigint", @@ -1114,20 +1089,20 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -1149,7 +1124,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.45", + "syn 2.0.52", ] [[package]] @@ -1163,24 +1138,24 @@ dependencies = [ [[package]] name = "object" -version = "0.29.0" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "parking_lot" @@ -1207,15 +1182,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "ppv-lite86" @@ -1225,11 +1200,10 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "once_cell", "toml_edit", ] @@ -1259,9 +1233,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.74" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -1327,9 +1301,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1363,9 +1337,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -1381,27 +1355,22 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "lazy_static", - "num_cpus", ] [[package]] @@ -1427,9 +1396,21 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -1438,9 +1419,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "region" @@ -1456,21 +1437,22 @@ dependencies = [ [[package]] name = "rend" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" dependencies = [ "bytecheck", ] [[package]] name = "rkyv" -version = "0.7.42" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" +checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" dependencies = [ "bitvec", "bytecheck", + "bytes", "hashbrown 0.12.3", "indexmap 1.9.3", "ptr_meta", @@ -1483,9 +1465,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.42" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" +checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" dependencies = [ "proc-macro2", "quote", @@ -1494,9 +1476,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc_version" @@ -1507,23 +1489,17 @@ dependencies = [ "semver", ] -[[package]] -name = "rustversion" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" - [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "seahash" @@ -1533,21 +1509,21 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "self_cell" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6" +checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba" [[package]] name = "semver" -version = "1.0.13" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] @@ -1565,20 +1541,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.45", + "syn 2.0.52", ] [[package]] name = "serde_json" -version = "1.0.109" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -1587,11 +1563,10 @@ dependencies = [ [[package]] name = "serde_with" -version = "1.12.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "946fa04a8ac43ff78a1f4b811990afb9ddbdf5890b46d6dda0ba1998230138b7" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" dependencies = [ - "rustversion", "serde", "serde_with_macros", ] @@ -1656,9 +1631,9 @@ dependencies = [ [[package]] name = "shared-buffer" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cf61602ee61e2f83dd016b3e6387245291cf728ea071c378b35088125b4d995" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" dependencies = [ "bytes", "memmap2 0.6.2", @@ -1672,21 +1647,21 @@ checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slice-group-by" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "smallvec" -version = "1.10.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" dependencies = [ "serde", ] @@ -1778,9 +1753,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.45" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eae3c679c56dc214320b67a1bc04ef3dfbd6411f6443974b5e4893231298e66" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -1795,9 +1770,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.4" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "textwrap" @@ -1810,22 +1785,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.33" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.33" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] @@ -1869,9 +1844,9 @@ checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" [[package]] name = "toml_edit" -version = "0.19.12" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap 2.2.5", "toml_datetime", @@ -1880,11 +1855,10 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.34" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1892,68 +1866,68 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.22" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] name = "tracing-core" -version = "0.1.26" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] name = "typenum" -version = "1.14.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -1972,9 +1946,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" [[package]] name = "vec_map" @@ -1984,9 +1958,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasi" @@ -1996,9 +1970,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2006,16 +1980,16 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", "wasm-bindgen-shared", ] @@ -2044,9 +2018,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2054,22 +2028,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-encoder" @@ -2118,7 +2092,7 @@ dependencies = [ "enumset", "lazy_static", "leb128", - "memmap2 0.5.7", + "memmap2 0.5.10", "more-asserts", "region", "rkyv", @@ -2139,7 +2113,7 @@ dependencies = [ "cranelift-codegen", "cranelift-entity", "cranelift-frontend", - "gimli", + "gimli 0.26.2", "more-asserts", "rayon", "smallvec", @@ -2179,7 +2153,7 @@ dependencies = [ "dynasm", "dynasmrt", "enumset", - "gimli", + "gimli 0.26.2", "lazy_static", "more-asserts", "rayon", @@ -2229,7 +2203,7 @@ dependencies = [ "lazy_static", "libc", "mach", - "memoffset 0.8.0", + "memoffset", "more-asserts", "region", "scopeguard", @@ -2306,24 +2280,24 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.48.0", + "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -2333,9 +2307,9 @@ checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -2345,9 +2319,9 @@ checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -2357,9 +2331,9 @@ checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -2369,15 +2343,15 @@ checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -2387,15 +2361,15 @@ checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.4.7" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] @@ -2426,5 +2400,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.45", + "syn 2.0.52", ] diff --git a/arbitrator/tools/module_roots/Cargo.lock b/arbitrator/tools/module_roots/Cargo.lock index 93dc32748..0e83bc066 100644 --- a/arbitrator/tools/module_roots/Cargo.lock +++ b/arbitrator/tools/module_roots/Cargo.lock @@ -4,11 +4,11 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ - "gimli 0.27.2", + "gimli 0.28.1", ] [[package]] @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", @@ -41,11 +41,14 @@ dependencies = [ name = "arbutil" version = "0.1.0" dependencies = [ - "digest", + "digest 0.10.7", "eyre", "hex", "num-traits", + "num_enum", "serde", + "sha2 0.10.8", + "sha3 0.10.8", "siphasher", "tiny-keccak", "wasmparser", @@ -53,9 +56,9 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "atty" @@ -76,9 +79,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -104,6 +107,18 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -114,12 +129,33 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "block-padding" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +[[package]] +name = "blst" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + [[package]] name = "brotli-sys" version = "0.3.2" @@ -142,15 +178,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "bytecheck" -version = "0.6.10" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fe11640a23eb24562225322cd3e452b93a3d4091d62fab69c70542fcd17d1f" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -159,9 +195,9 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.6.10" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31225543cb46f81a7e224762764f4a6a0f097b1db0b175f69e8065efaa42de5" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ "proc-macro2", "quote", @@ -170,21 +206,35 @@ dependencies = [ [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "c-kzg" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94a4bc5367b6284358d2a6a6a1dc2d92ec4b86034561c3b9d3341909752fd848" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "serde", +] [[package]] name = "cc" -version = "1.0.79" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cfg-if" @@ -209,9 +259,9 @@ dependencies = [ [[package]] name = "corosensei" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9847f90f32a50b0dcbd68bc23ff242798b13080b97b0569f6ed96a45ce4cf2cd" +checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" dependencies = [ "autocfg", "cfg-if", @@ -222,9 +272,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.6" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -283,7 +333,7 @@ dependencies = [ "cranelift-entity", "fxhash", "hashbrown 0.12.3", - "indexmap", + "indexmap 1.9.3", "log", "smallvec", ] @@ -312,58 +362,39 @@ version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" -[[package]] -name = "crossbeam-channel" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crunchy" @@ -371,6 +402,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "darling" version = "0.13.4" @@ -383,12 +424,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ - "darling_core 0.20.3", - "darling_macro 0.20.3", + "darling_core 0.20.8", + "darling_macro 0.20.8", ] [[package]] @@ -407,15 +448,15 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", ] [[package]] @@ -431,13 +472,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ - "darling_core 0.20.3", + "darling_core 0.20.8", "quote", - "syn 2.0.16", + "syn 2.0.52", ] [[package]] @@ -473,6 +514,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", +] + [[package]] name = "dynasm" version = "1.2.3" @@ -501,9 +552,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "enum-iterator" @@ -540,17 +591,23 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" dependencies = [ - "darling 0.20.3", + "darling 0.20.8", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", @@ -577,6 +634,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "fxhash" version = "0.2.1" @@ -598,9 +661,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -614,15 +677,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "fallible-iterator", - "indexmap", + "indexmap 1.9.3", "stable_deref_trait", ] [[package]] name = "gimli" -version = "0.27.2" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "glob" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "hashbrown" @@ -659,12 +728,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -704,6 +770,16 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "indexmap" +version = "2.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", +] + [[package]] name = "itertools" version = "0.10.5" @@ -715,24 +791,24 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] name = "keccak" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -751,9 +827,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.141" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "lock_api" @@ -767,12 +843,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "mach" @@ -785,9 +858,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" @@ -824,9 +897,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -870,9 +943,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ "num-bigint", "num-complex", @@ -884,9 +957,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg", "num-integer", @@ -895,28 +968,38 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" dependencies = [ "num-traits", ] +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ "autocfg", "num-integer", @@ -937,28 +1020,49 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.9", "libc", ] +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "object" -version = "0.30.3" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -971,9 +1075,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "parking_lot" @@ -1006,9 +1110,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit", +] [[package]] name = "proc-macro-error" @@ -1036,9 +1149,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -1050,8 +1163,9 @@ dependencies = [ "arbutil", "bincode", "brotli2", + "c-kzg", "derivative", - "digest", + "digest 0.9.0", "eyre", "fnv", "hex", @@ -1061,13 +1175,16 @@ dependencies = [ "nom", "nom-leb128", "num", + "num-derive", + "num-traits", "parking_lot", "rayon", "rustc-demangle", "serde", "serde_json", "serde_with", - "sha3", + "sha2 0.9.9", + "sha3 0.9.1", "smallvec", "static_assertions", "structopt", @@ -1100,18 +1217,24 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rayon" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" dependencies = [ "either", "rayon-core", @@ -1119,14 +1242,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -1164,33 +1285,37 @@ dependencies = [ [[package]] name = "rend" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" dependencies = [ "bytecheck", ] [[package]] name = "rkyv" -version = "0.7.41" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21499ed91807f07ae081880aabb2ccc0235e9d88011867d984525e9a4c3cfa3e" +checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" dependencies = [ + "bitvec", "bytecheck", + "bytes", "hashbrown 0.12.3", - "indexmap", + "indexmap 1.9.3", "ptr_meta", "rend", "rkyv_derive", "seahash", + "tinyvec", + "uuid", ] [[package]] name = "rkyv_derive" -version = "0.7.41" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1c672430eb41556291981f45ca900a0239ad007242d1cb4b4167af842db666" +checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" dependencies = [ "proc-macro2", "quote", @@ -1199,21 +1324,21 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "seahash" @@ -1223,15 +1348,15 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "self_cell" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6" +checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba" [[package]] name = "serde" -version = "1.0.159" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] @@ -1249,20 +1374,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.159" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", ] [[package]] name = "serde_json" -version = "1.0.95" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -1291,23 +1416,57 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha3" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" dependencies = [ - "block-buffer", - "digest", + "block-buffer 0.9.0", + "digest 0.9.0", "keccak", "opaque-debug", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + [[package]] name = "shared-buffer" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cf61602ee61e2f83dd016b3e6387245291cf728ea071c378b35088125b4d995" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" dependencies = [ "bytes", "memmap2 0.6.2", @@ -1321,21 +1480,21 @@ checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slice-group-by" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "smallvec" -version = "1.10.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" dependencies = [ "serde", ] @@ -1401,20 +1560,26 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.16" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "target-lexicon" -version = "0.12.6" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae9980cab1db3fceee2f6c6f643d5d8de2997c58ee8d25fb0cc8a9e9e7348e5" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "textwrap" @@ -1427,22 +1592,31 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", ] [[package]] @@ -1469,13 +1643,29 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.5", + "toml_datetime", + "winnow", +] + [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1483,62 +1673,62 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "url" @@ -1551,6 +1741,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "uuid" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" + [[package]] name = "vec_map" version = "0.8.2" @@ -1571,9 +1767,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1581,16 +1777,16 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", "wasm-bindgen-shared", ] @@ -1619,9 +1815,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1629,22 +1825,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-encoder" @@ -1662,7 +1858,7 @@ dependencies = [ "bytes", "cfg-if", "derivative", - "indexmap", + "indexmap 1.9.3", "js-sys", "more-asserts", "rustc-demangle", @@ -1758,7 +1954,7 @@ dependencies = [ "bytecheck", "enum-iterator", "enumset", - "indexmap", + "indexmap 1.9.3", "more-asserts", "rkyv", "target-lexicon", @@ -1778,7 +1974,7 @@ dependencies = [ "derivative", "enum-iterator", "fnv", - "indexmap", + "indexmap 1.9.3", "lazy_static", "libc", "mach", @@ -1797,7 +1993,7 @@ version = "0.95.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ea896273ea99b15132414be1da01ab0d8836415083298ecaffbe308eaac87a" dependencies = [ - "indexmap", + "indexmap 1.9.3", "url", ] @@ -1943,3 +2139,41 @@ name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] diff --git a/arbitrator/wasm-libraries/Cargo.lock b/arbitrator/wasm-libraries/Cargo.lock index 32fbfe122..626e23319 100644 --- a/arbitrator/wasm-libraries/Cargo.lock +++ b/arbitrator/wasm-libraries/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", @@ -41,9 +41,9 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "atty" @@ -122,11 +122,17 @@ dependencies = [ "paste", ] +[[package]] +name = "bumpalo" +version = "3.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" + [[package]] name = "bytecheck" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -135,15 +141,21 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + [[package]] name = "caller-env" version = "0.1.0" @@ -182,9 +194,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -217,12 +229,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ - "darling_core 0.20.3", - "darling_macro 0.20.3", + "darling_core 0.20.8", + "darling_macro 0.20.8", ] [[package]] @@ -236,20 +248,20 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] @@ -260,18 +272,18 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core 0.13.4", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ - "darling_core 0.20.3", + "darling_core 0.20.8", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] @@ -282,7 +294,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -306,9 +318,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "enum-iterator" @@ -327,7 +339,7 @@ checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -345,10 +357,10 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" dependencies = [ - "darling 0.20.3", + "darling 0.20.8", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] @@ -359,9 +371,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "eyre" -version = "0.6.9" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", @@ -375,9 +387,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -398,9 +410,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -408,9 +420,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if 1.0.0", "libc", @@ -472,9 +484,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -488,9 +500,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", @@ -517,9 +529,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.5" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "keccak" @@ -544,15 +556,15 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -560,9 +572,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memory_units" @@ -605,9 +617,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ "num-bigint", "num-complex", @@ -619,9 +631,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg", "num-integer", @@ -630,39 +642,38 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.2" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" dependencies = [ "num-traits", ] [[package]] name = "num-derive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ "autocfg", "num-integer", @@ -683,9 +694,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -708,20 +719,20 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "parking_lot" @@ -735,15 +746,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.6" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-targets", ] [[package]] @@ -754,9 +765,9 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "proc-macro-crate" @@ -776,7 +787,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", "version_check", ] @@ -793,9 +804,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -855,14 +866,14 @@ checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -899,32 +910,33 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags", ] [[package]] name = "rend" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" dependencies = [ "bytecheck", ] [[package]] name = "rkyv" -version = "0.7.42" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" +checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" dependencies = [ "bitvec", "bytecheck", + "bytes", "hashbrown 0.12.3", - "indexmap 1.9.2", + "indexmap 1.9.3", "ptr_meta", "rend", "rkyv_derive", @@ -935,32 +947,32 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.42" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" +checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] name = "rustc-demangle" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "ryu" -version = "1.0.12" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "seahash" @@ -970,29 +982,29 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "serde" -version = "1.0.152" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 2.0.52", ] [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -1018,7 +1030,7 @@ dependencies = [ "darling 0.13.4", "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -1075,15 +1087,15 @@ checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "smallvec" -version = "1.10.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" dependencies = [ "serde", ] @@ -1127,14 +1139,14 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] name = "syn" -version = "1.0.107" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -1143,9 +1155,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -1160,9 +1172,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.5" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "textwrap" @@ -1175,22 +1187,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 2.0.52", ] [[package]] @@ -1236,48 +1248,48 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -1324,9 +1336,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" [[package]] name = "vec_map" @@ -1357,9 +1369,9 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.25.0" +version = "0.201.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eff853c4f09eec94d76af527eddad4e9de13b11d6286a1ef7134bc30135a2b7" +checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a" dependencies = [ "leb128", ] @@ -1371,7 +1383,7 @@ dependencies = [ "bytecheck", "enum-iterator", "enumset", - "indexmap 1.9.2", + "indexmap 1.9.3", "more-asserts", "rkyv", "target-lexicon", @@ -1384,16 +1396,17 @@ version = "0.95.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ea896273ea99b15132414be1da01ab0d8836415083298ecaffbe308eaac87a" dependencies = [ - "indexmap 1.9.2", + "indexmap 1.9.3", "url", ] [[package]] name = "wast" -version = "55.0.0" +version = "201.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4984d3e1406571f4930ba5cf79bd70f75f41d0e87e17506e0bd19b0e5d085f05" +checksum = "1ef6e1ef34d7da3e2b374fd2b1a9c0227aff6cad596e1b24df9b58d0f6222faa" dependencies = [ + "bumpalo", "leb128", "memchr", "unicode-width", @@ -1402,9 +1415,9 @@ dependencies = [ [[package]] name = "wat" -version = "1.0.61" +version = "1.201.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af2b53f4da14db05d32e70e9c617abdf6620c575bd5dd972b7400037b4df2091" +checksum = "453d5b37a45b98dee4f4cb68015fc73634d7883bbef1c65e6e9c78d454cf3f32" dependencies = [ "wast", ] @@ -1444,10 +1457,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.42.0" +name = "windows-targets" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -1460,45 +1473,45 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.42.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.42.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.42.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.42.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" From c6e264bb8fde91a72d8589a2d5ba243fbfc58825 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 14 Mar 2024 19:07:30 -0600 Subject: [PATCH 762/775] program_test: split race from norace --- system_tests/program_norace_test.go | 190 ++++++++++++++++++++++++++++ system_tests/program_race_test.go | 23 ++++ system_tests/program_test.go | 164 ------------------------ system_tests/stylus_test.go | 4 +- 4 files changed, 215 insertions(+), 166 deletions(-) create mode 100644 system_tests/program_norace_test.go create mode 100644 system_tests/program_race_test.go diff --git a/system_tests/program_norace_test.go b/system_tests/program_norace_test.go new file mode 100644 index 000000000..c10fb2064 --- /dev/null +++ b/system_tests/program_norace_test.go @@ -0,0 +1,190 @@ +// race detection makes things slow and miss timeouts +//go:build !race +// +build !race + +package arbtest + +import ( + "encoding/binary" + "encoding/json" + "math/big" + "strings" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/offchainlabs/nitro/arbos/util" + "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/solgen/go/mocksgen" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" + "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/colors" + "github.com/offchainlabs/nitro/util/testhelpers" +) + +// used in program test +func validateBlocks( + t *testing.T, start uint64, jit bool, builder *NodeBuilder, +) { + t.Helper() + if jit || start == 0 { + start = 1 + } + + blockHeight, err := builder.L2.Client.BlockNumber(builder.ctx) + Require(t, err) + + blocks := []uint64{} + for i := start; i <= blockHeight; i++ { + blocks = append(blocks, i) + } + validateBlockRange(t, blocks, jit, builder) +} + +// used in program test +func validateBlockRange( + t *testing.T, blocks []uint64, jit bool, + builder *NodeBuilder, +) { + ctx := builder.ctx + waitForSequencer(t, builder, arbmath.MaxInt(blocks...)) + blockHeight, err := builder.L2.Client.BlockNumber(ctx) + Require(t, err) + + // validate everything + if jit { + blocks = []uint64{} + for i := uint64(1); i <= blockHeight; i++ { + blocks = append(blocks, i) + } + } + + success := true + for _, block := range blocks { + // no classic data, so block numbers are message indicies + inboxPos := arbutil.MessageIndex(block) + + now := time.Now() + correct, _, err := builder.L2.ConsensusNode.StatelessBlockValidator.ValidateResult(ctx, inboxPos, false, common.Hash{}) + Require(t, err, "block", block) + passed := formatTime(time.Since(now)) + if correct { + colors.PrintMint("yay!! we validated block ", block, " in ", passed) + } else { + colors.PrintRed("failed to validate block ", block, " in ", passed) + } + success = success && correct + } + if !success { + Fatal(t) + } +} + +func TestProgramEvmData(t *testing.T) { + t.Parallel() + testEvmData(t, true) +} + +func testEvmData(t *testing.T, jit bool) { + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client + defer cleanup() + evmDataAddr := deployWasm(t, ctx, auth, l2client, rustFile("evm-data")) + + ensure := func(tx *types.Transaction, err error) *types.Receipt { + t.Helper() + Require(t, err) + receipt, err := EnsureTxSucceeded(ctx, l2client, tx) + Require(t, err) + return receipt + } + burnArbGas, _ := util.NewCallParser(precompilesgen.ArbosTestABI, "burnArbGas") + + _, tx, mock, err := mocksgen.DeployProgramTest(&auth, l2client) + ensure(tx, err) + + evmDataGas := uint64(1000000000) + gasToBurn := uint64(1000000) + callBurnData, err := burnArbGas(new(big.Int).SetUint64(gasToBurn)) + Require(t, err) + fundedAddr := l2info.Accounts["Faucet"].Address + ethPrecompile := common.BigToAddress(big.NewInt(1)) + arbTestAddress := types.ArbosTestAddress + + evmDataData := []byte{} + evmDataData = append(evmDataData, fundedAddr.Bytes()...) + evmDataData = append(evmDataData, ethPrecompile.Bytes()...) + evmDataData = append(evmDataData, arbTestAddress.Bytes()...) + evmDataData = append(evmDataData, evmDataAddr.Bytes()...) + evmDataData = append(evmDataData, callBurnData...) + opts := bind.CallOpts{ + From: testhelpers.RandomAddress(), + } + + result, err := mock.StaticcallEvmData(&opts, evmDataAddr, fundedAddr, evmDataGas, evmDataData) + Require(t, err) + + advance := func(count int, name string) []byte { + t.Helper() + if len(result) < count { + Fatal(t, "not enough data left", name, count, len(result)) + } + data := result[:count] + result = result[count:] + return data + } + getU32 := func(name string) uint32 { + t.Helper() + return binary.BigEndian.Uint32(advance(4, name)) + } + getU64 := func(name string) uint64 { + t.Helper() + return binary.BigEndian.Uint64(advance(8, name)) + } + + inkPrice := uint64(getU32("ink price")) + gasLeftBefore := getU64("gas left before") + inkLeftBefore := getU64("ink left before") + gasLeftAfter := getU64("gas left after") + inkLeftAfter := getU64("ink left after") + + gasUsed := gasLeftBefore - gasLeftAfter + calculatedGasUsed := (inkLeftBefore - inkLeftAfter) / inkPrice + + // Should be within 1 gas + if !arbmath.Within(gasUsed, calculatedGasUsed, 1) { + Fatal(t, "gas and ink converted to gas don't match", gasUsed, calculatedGasUsed, inkPrice) + } + + tx = l2info.PrepareTxTo("Owner", &evmDataAddr, evmDataGas, nil, evmDataData) + ensure(tx, l2client.SendTransaction(ctx, tx)) + + // test hostio tracing + js := `{ + "hostio": function(info) { this.names.push(info.name); }, + "result": function() { return this.names; }, + "fault": function() { return this.names; }, + names: [] + }` + var trace json.RawMessage + traceConfig := &tracers.TraceConfig{ + Tracer: &js, + } + rpc := l2client.Client() + err = rpc.CallContext(ctx, &trace, "debug_traceTransaction", tx.Hash(), traceConfig) + Require(t, err) + + for _, item := range []string{"user_entrypoint", "read_args", "write_result", "user_returned"} { + if !strings.Contains(string(trace), item) { + Fatal(t, "tracer missing hostio ", item, " ", trace) + } + } + colors.PrintGrey("trace: ", string(trace)) + + validateBlocks(t, 1, jit, builder) +} diff --git a/system_tests/program_race_test.go b/system_tests/program_race_test.go new file mode 100644 index 000000000..78507934d --- /dev/null +++ b/system_tests/program_race_test.go @@ -0,0 +1,23 @@ +//go:build race +// +build race + +// when running with race detection - skip block validation + +package arbtest + +import ( + "testing" +) + +// used in program test +func validateBlocks( + t *testing.T, start uint64, jit bool, builder *NodeBuilder, +) { +} + +// used in program test +func validateBlockRange( + t *testing.T, blocks []uint64, jit bool, + builder *NodeBuilder, +) { +} diff --git a/system_tests/program_test.go b/system_tests/program_test.go index 16d6aea5d..622746a51 100644 --- a/system_tests/program_test.go +++ b/system_tests/program_test.go @@ -7,7 +7,6 @@ import ( "bytes" "context" "encoding/binary" - "encoding/json" "fmt" "math/big" "os" @@ -23,7 +22,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/tracers" _ "github.com/ethereum/go-ethereum/eth/tracers/js" "github.com/ethereum/go-ethereum/ethclient" "github.com/offchainlabs/nitro/arbcompress" @@ -717,112 +715,6 @@ func testCreate(t *testing.T, jit bool) { validateBlockRange(t, blocks, jit, builder) } -func TestProgramEvmData(t *testing.T) { - t.Parallel() - testEvmData(t, true) -} - -func testEvmData(t *testing.T, jit bool) { - builder, auth, cleanup := setupProgramTest(t, jit) - ctx := builder.ctx - l2info := builder.L2Info - l2client := builder.L2.Client - defer cleanup() - evmDataAddr := deployWasm(t, ctx, auth, l2client, rustFile("evm-data")) - - ensure := func(tx *types.Transaction, err error) *types.Receipt { - t.Helper() - Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, l2client, tx) - Require(t, err) - return receipt - } - burnArbGas, _ := util.NewCallParser(precompilesgen.ArbosTestABI, "burnArbGas") - - _, tx, mock, err := mocksgen.DeployProgramTest(&auth, l2client) - ensure(tx, err) - - evmDataGas := uint64(1000000000) - gasToBurn := uint64(1000000) - callBurnData, err := burnArbGas(new(big.Int).SetUint64(gasToBurn)) - Require(t, err) - fundedAddr := l2info.Accounts["Faucet"].Address - ethPrecompile := common.BigToAddress(big.NewInt(1)) - arbTestAddress := types.ArbosTestAddress - - evmDataData := []byte{} - evmDataData = append(evmDataData, fundedAddr.Bytes()...) - evmDataData = append(evmDataData, ethPrecompile.Bytes()...) - evmDataData = append(evmDataData, arbTestAddress.Bytes()...) - evmDataData = append(evmDataData, evmDataAddr.Bytes()...) - evmDataData = append(evmDataData, callBurnData...) - opts := bind.CallOpts{ - From: testhelpers.RandomAddress(), - } - - result, err := mock.StaticcallEvmData(&opts, evmDataAddr, fundedAddr, evmDataGas, evmDataData) - Require(t, err) - - advance := func(count int, name string) []byte { - t.Helper() - if len(result) < count { - Fatal(t, "not enough data left", name, count, len(result)) - } - data := result[:count] - result = result[count:] - return data - } - getU32 := func(name string) uint32 { - t.Helper() - return binary.BigEndian.Uint32(advance(4, name)) - } - getU64 := func(name string) uint64 { - t.Helper() - return binary.BigEndian.Uint64(advance(8, name)) - } - - inkPrice := uint64(getU32("ink price")) - gasLeftBefore := getU64("gas left before") - inkLeftBefore := getU64("ink left before") - gasLeftAfter := getU64("gas left after") - inkLeftAfter := getU64("ink left after") - - gasUsed := gasLeftBefore - gasLeftAfter - calculatedGasUsed := (inkLeftBefore - inkLeftAfter) / inkPrice - - // Should be within 1 gas - if !arbmath.Within(gasUsed, calculatedGasUsed, 1) { - Fatal(t, "gas and ink converted to gas don't match", gasUsed, calculatedGasUsed, inkPrice) - } - - tx = l2info.PrepareTxTo("Owner", &evmDataAddr, evmDataGas, nil, evmDataData) - ensure(tx, l2client.SendTransaction(ctx, tx)) - - // test hostio tracing - js := `{ - "hostio": function(info) { this.names.push(info.name); }, - "result": function() { return this.names; }, - "fault": function() { return this.names; }, - names: [] - }` - var trace json.RawMessage - traceConfig := &tracers.TraceConfig{ - Tracer: &js, - } - rpc := l2client.Client() - err = rpc.CallContext(ctx, &trace, "debug_traceTransaction", tx.Hash(), traceConfig) - Require(t, err) - - for _, item := range []string{"user_entrypoint", "read_args", "write_result", "user_returned"} { - if !strings.Contains(string(trace), item) { - Fatal(t, "tracer missing hostio ", item, " ", trace) - } - } - colors.PrintGrey("trace: ", string(trace)) - - validateBlocks(t, 1, jit, builder) -} - func TestProgramMemory(t *testing.T) { t.Parallel() testMemory(t, true) @@ -1284,62 +1176,6 @@ func watFile(name string) string { return fmt.Sprintf("../arbitrator/stylus/tests/%v.wat", name) } -func validateBlocks( - t *testing.T, start uint64, jit bool, builder *NodeBuilder, -) { - t.Helper() - if jit || start == 0 { - start = 1 - } - - blockHeight, err := builder.L2.Client.BlockNumber(builder.ctx) - Require(t, err) - - blocks := []uint64{} - for i := start; i <= blockHeight; i++ { - blocks = append(blocks, i) - } - validateBlockRange(t, blocks, jit, builder) -} - -func validateBlockRange( - t *testing.T, blocks []uint64, jit bool, - builder *NodeBuilder, -) { - ctx := builder.ctx - waitForSequencer(t, builder, arbmath.MaxInt(blocks...)) - blockHeight, err := builder.L2.Client.BlockNumber(ctx) - Require(t, err) - - // validate everything - if jit { - blocks = []uint64{} - for i := uint64(1); i <= blockHeight; i++ { - blocks = append(blocks, i) - } - } - - success := true - for _, block := range blocks { - // no classic data, so block numbers are message indicies - inboxPos := arbutil.MessageIndex(block) - - now := time.Now() - correct, _, err := builder.L2.ConsensusNode.StatelessBlockValidator.ValidateResult(ctx, inboxPos, false, common.Hash{}) - Require(t, err, "block", block) - passed := formatTime(time.Since(now)) - if correct { - colors.PrintMint("yay!! we validated block ", block, " in ", passed) - } else { - colors.PrintRed("failed to validate block ", block, " in ", passed) - } - success = success && correct - } - if !success { - Fatal(t) - } -} - func waitForSequencer(t *testing.T, builder *NodeBuilder, block uint64) { t.Helper() msgCount := arbutil.BlockNumberToMessageCount(block, 0) diff --git a/system_tests/stylus_test.go b/system_tests/stylus_test.go index dd0ced205..274e0cc35 100644 --- a/system_tests/stylus_test.go +++ b/system_tests/stylus_test.go @@ -1,8 +1,8 @@ // Copyright 2023, Offchain Labs, Inc. // For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE -//go:build stylustest -// +build stylustest +//go:build stylustest && !race +// +build stylustest,!race package arbtest From 714ca9dfd4f53f73d3a5900ab0988d9fa35dbd19 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 14 Mar 2024 19:08:03 -0600 Subject: [PATCH 763/775] arbitrator ci: update SW versions --- .github/workflows/arbitrator-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index c875b0ef3..4d96338fb 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -51,7 +51,7 @@ jobs: - name: Install go uses: actions/setup-go@v4 with: - go-version: 1.20.x + go-version: 1.21.x - name: Install custom go-ethereum run: | @@ -72,6 +72,7 @@ jobs: - name: Install rust stable uses: dtolnay/rust-toolchain@stable with: + toolchain: "1.75" components: 'llvm-tools-preview, rustfmt' - name: Install rust nightly From 83d28bc9a6457ced942b80b4ea4404382db487e1 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 14 Mar 2024 20:14:23 -0600 Subject: [PATCH 764/775] arbitrator-ci: use an older nightly --- .github/workflows/arbitrator-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index 4d96338fb..11ee9ca5e 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -79,7 +79,7 @@ jobs: uses: dtolnay/rust-toolchain@nightly id: install-rust-nightly with: - toolchain: "nightly" + toolchain: "nightly-2024-02-04" targets: 'wasm32-wasi, wasm32-unknown-unknown' components: rust-src From 884051a86baa8de3d1a77acf7406d43376d6bde4 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 14 Mar 2024 20:56:48 -0600 Subject: [PATCH 765/775] Makefile: support specific nightly for stylus --- .github/workflows/arbitrator-ci.yml | 2 +- Makefile | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index 11ee9ca5e..9d4977c45 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -157,7 +157,7 @@ jobs: run: echo "$HOME/wabt-prefix/bin" >> "$GITHUB_PATH" - name: Make arbitrator libraries - run: make -j wasm-ci-build + run: make -j wasm-ci-build STYLUS_NIGHTLY_VER="+nightly-2024-02-04" - name: Clippy check run: cargo clippy --all --manifest-path arbitrator/Cargo.toml -- -D warnings diff --git a/Makefile b/Makefile index 180ce49b2..36c81dc93 100644 --- a/Makefile +++ b/Makefile @@ -107,7 +107,9 @@ stylus_lang_rust = $(wildcard $(rust_sdk)/*/src/*.rs $(rust_sdk)/*/src/*/*.rs $( stylus_lang_c = $(wildcard $(c_sdk)/*/*.c $(c_sdk)/*/*.h) stylus_lang_bf = $(wildcard arbitrator/langs/bf/src/*.* arbitrator/langs/bf/src/*.toml) -cargo_nightly = cargo +nightly build -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort +STYLUS_NIGHTLY_VER ?= "+nightly" + +cargo_nightly = cargo $(STYLUS_NIGHTLY_VER) build -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort get_stylus_test_wasm = $(stylus_test_dir)/$(1)/$(wasm32_unknown)/$(1).wasm get_stylus_test_rust = $(wildcard $(stylus_test_dir)/$(1)/*.toml $(stylus_test_dir)/$(1)/src/*.rs) $(stylus_cargo) $(stylus_lang_rust) From 99b5511506e599f6d91ed552e94a6fe50a4613e4 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 14 Mar 2024 21:29:06 -0600 Subject: [PATCH 766/775] arbitrator-ci: add rust components --- .github/workflows/arbitrator-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index 9d4977c45..85ef9e7cc 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -73,7 +73,7 @@ jobs: uses: dtolnay/rust-toolchain@stable with: toolchain: "1.75" - components: 'llvm-tools-preview, rustfmt' + components: 'llvm-tools-preview, rustfmt, clippy' - name: Install rust nightly uses: dtolnay/rust-toolchain@nightly @@ -81,7 +81,7 @@ jobs: with: toolchain: "nightly-2024-02-04" targets: 'wasm32-wasi, wasm32-unknown-unknown' - components: rust-src + components: 'rust-src, rustfmt, clippy' - name: Cache Rust intermediate build products uses: actions/cache@v3 From 0e8a25c9ae8d4fd23c553b00d644b10ebbcb4212 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 15 Mar 2024 09:14:36 -0600 Subject: [PATCH 767/775] clippy fixes --- arbitrator/jit/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbitrator/jit/src/main.rs b/arbitrator/jit/src/main.rs index 83a794316..32cf009d4 100644 --- a/arbitrator/jit/src/main.rs +++ b/arbitrator/jit/src/main.rs @@ -82,7 +82,7 @@ fn main() -> Result<()> { .exports .get_memory("memory") .unwrap() - .view(&mut store) + .view(&store) .size() .0 as u64 * 65_536; From 8432de5a08a854841085a5de937643b2c61285ac Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 15 Mar 2024 09:56:15 -0600 Subject: [PATCH 768/775] rust test fixes --- arbitrator/stylus/src/test/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbitrator/stylus/src/test/mod.rs b/arbitrator/stylus/src/test/mod.rs index 7e041422d..0f1cfd761 100644 --- a/arbitrator/stylus/src/test/mod.rs +++ b/arbitrator/stylus/src/test/mod.rs @@ -156,7 +156,7 @@ fn new_test_machine(path: &str, compile: &CompileConfig) -> Result { true, GlobalState::default(), HashMap::default(), - Arc::new(|_, _| panic!("tried to read preimage")), + Arc::new(|_, _, _| panic!("tried to read preimage")), Some(stylus_data), )?; mach.set_ink(u64::MAX); From bde60376ae4cf64b900a181864bb14bd5763a3eb Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 25 Mar 2024 16:13:05 -0600 Subject: [PATCH 769/775] cargo update --- arbitrator/Cargo.lock | 104 ++++++++++++++++----- arbitrator/stylus/tests/erc20/Cargo.lock | 1 + arbitrator/stylus/tests/storage/Cargo.lock | 7 ++ 3 files changed, 88 insertions(+), 24 deletions(-) diff --git a/arbitrator/Cargo.lock b/arbitrator/Cargo.lock index e1e08c5f6..0b9d3e1d2 100644 --- a/arbitrator/Cargo.lock +++ b/arbitrator/Cargo.lock @@ -46,12 +46,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + [[package]] name = "arbutil" version = "0.1.0" dependencies = [ "digest 0.10.7", "eyre", + "fnv", "hex", "num-traits", "num_enum", @@ -94,7 +101,7 @@ checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object 0.32.2", @@ -166,23 +173,21 @@ dependencies = [ ] [[package]] -name = "brotli-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" +name = "brotli" +version = "0.1.0" dependencies = [ - "cc", - "libc", + "lazy_static", + "num_enum", + "wasmer", + "wee_alloc", ] [[package]] -name = "brotli2" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" +name = "brotli-fuzz" +version = "0.0.0" dependencies = [ - "brotli-sys", - "libc", + "brotli", + "libfuzzer-sys", ] [[package]] @@ -243,6 +248,7 @@ dependencies = [ name = "caller-env" version = "0.1.0" dependencies = [ + "brotli", "num_enum", "rand", "rand_pcg", @@ -254,6 +260,16 @@ name = "cc" version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +dependencies = [ + "jobserver", + "libc", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" @@ -283,7 +299,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" dependencies = [ "autocfg", - "cfg-if", + "cfg-if 1.0.0", "libc", "scopeguard", "windows-sys", @@ -506,7 +522,7 @@ version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "hashbrown 0.14.3", "lock_api", "once_cell", @@ -684,7 +700,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi", ] @@ -844,6 +860,7 @@ name = "jit" version = "0.1.0" dependencies = [ "arbutil", + "brotli", "caller-env", "eyre", "hex", @@ -861,6 +878,15 @@ dependencies = [ "wasmer-compiler-llvm", ] +[[package]] +name = "jobserver" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.69" @@ -897,6 +923,17 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "libfuzzer-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] + [[package]] name = "llvm-sys" version = "150.1.3" @@ -968,6 +1005,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memory_units" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1173,7 +1216,7 @@ version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", @@ -1246,7 +1289,7 @@ version = "0.1.0" dependencies = [ "arbutil", "bincode", - "brotli2", + "brotli", "c-kzg", "derivative", "digest 0.9.0", @@ -1590,7 +1633,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", "opaque-debug", @@ -1602,7 +1645,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest 0.10.7", ] @@ -1720,6 +1763,7 @@ version = "0.1.0" dependencies = [ "arbutil", "bincode", + "brotli", "caller-env", "derivative", "eyre", @@ -1974,7 +2018,7 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -2059,7 +2103,7 @@ name = "wasmer" version = "4.2.3" dependencies = [ "bytes", - "cfg-if", + "cfg-if 1.0.0", "derivative", "indexmap 1.9.3", "js-sys", @@ -2087,7 +2131,7 @@ version = "4.2.3" dependencies = [ "backtrace", "bytes", - "cfg-if", + "cfg-if 1.0.0", "enum-iterator", "enumset", "lazy_static", @@ -2192,7 +2236,7 @@ version = "4.2.3" dependencies = [ "backtrace", "cc", - "cfg-if", + "cfg-if 1.0.0", "corosensei", "crossbeam-queue", "dashmap", @@ -2243,6 +2287,18 @@ dependencies = [ "wast", ] +[[package]] +name = "wee_alloc" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "memory_units", + "winapi", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/arbitrator/stylus/tests/erc20/Cargo.lock b/arbitrator/stylus/tests/erc20/Cargo.lock index c3e215978..2a7c1ba86 100644 --- a/arbitrator/stylus/tests/erc20/Cargo.lock +++ b/arbitrator/stylus/tests/erc20/Cargo.lock @@ -669,6 +669,7 @@ dependencies = [ "alloy-sol-types", "cfg-if 1.0.0", "derivative", + "fnv", "hex", "keccak-const", "lazy_static", diff --git a/arbitrator/stylus/tests/storage/Cargo.lock b/arbitrator/stylus/tests/storage/Cargo.lock index a686950b2..bffed4f41 100644 --- a/arbitrator/stylus/tests/storage/Cargo.lock +++ b/arbitrator/stylus/tests/storage/Cargo.lock @@ -184,6 +184,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "generic-array" version = "0.14.7" @@ -452,6 +458,7 @@ dependencies = [ "alloy-sol-types", "cfg-if", "derivative", + "fnv", "hex", "keccak-const", "lazy_static", From 6fb8939f1e73ff83cde305232b39974bb43bfdf0 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 25 Mar 2024 16:28:43 -0600 Subject: [PATCH 770/775] arbcompress: compilation fixes --- arbcompress/compress_common.go | 2 +- arbcompress/native.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arbcompress/compress_common.go b/arbcompress/compress_common.go index 0ce8db079..a61dd9a17 100644 --- a/arbcompress/compress_common.go +++ b/arbcompress/compress_common.go @@ -18,5 +18,5 @@ func compressedBufferSizeFor(length int) int { } func CompressLevel(input []byte, level int) ([]byte, error) { - return Compress(input, level, EmptyDictionary) + return Compress(input, uint32(level), EmptyDictionary) } diff --git a/arbcompress/native.go b/arbcompress/native.go index c81601932..4624d6222 100644 --- a/arbcompress/native.go +++ b/arbcompress/native.go @@ -30,7 +30,7 @@ func CompressWell(input []byte) ([]byte, error) { return Compress(input, LEVEL_WELL, EmptyDictionary) } -func Compress(input []byte, level int, dictionary Dictionary) ([]byte, error) { +func Compress(input []byte, level uint32, dictionary Dictionary) ([]byte, error) { maxSize := compressedBufferSizeFor(len(input)) output := make([]byte, maxSize) outbuf := sliceToBuffer(output) From 5e0787639690590573a6c83febdb4909feecad8f Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 25 Mar 2024 16:33:56 -0600 Subject: [PATCH 771/775] cargo fmt --- arbitrator/prover/src/machine.rs | 2 +- arbitrator/stylus/tests/erc20/Cargo.lock | 1 - arbitrator/stylus/tests/storage/Cargo.lock | 7 ------- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index d44741596..edcca779f 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -20,9 +20,9 @@ use crate::{ }, }; use arbutil::{math, Bytes32, Color, PreimageType}; +use brotli::Dictionary; #[cfg(feature = "native")] use c_kzg::BYTES_PER_BLOB; -use brotli::Dictionary; use digest::Digest; use eyre::{bail, ensure, eyre, Result, WrapErr}; use fnv::FnvHashMap as HashMap; diff --git a/arbitrator/stylus/tests/erc20/Cargo.lock b/arbitrator/stylus/tests/erc20/Cargo.lock index 2a7c1ba86..c3e215978 100644 --- a/arbitrator/stylus/tests/erc20/Cargo.lock +++ b/arbitrator/stylus/tests/erc20/Cargo.lock @@ -669,7 +669,6 @@ dependencies = [ "alloy-sol-types", "cfg-if 1.0.0", "derivative", - "fnv", "hex", "keccak-const", "lazy_static", diff --git a/arbitrator/stylus/tests/storage/Cargo.lock b/arbitrator/stylus/tests/storage/Cargo.lock index bffed4f41..a686950b2 100644 --- a/arbitrator/stylus/tests/storage/Cargo.lock +++ b/arbitrator/stylus/tests/storage/Cargo.lock @@ -184,12 +184,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "generic-array" version = "0.14.7" @@ -458,7 +452,6 @@ dependencies = [ "alloy-sol-types", "cfg-if", "derivative", - "fnv", "hex", "keccak-const", "lazy_static", From ca67357931a018377fa198f30ee0128aa76132d7 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 25 Mar 2024 17:12:08 -0600 Subject: [PATCH 772/775] clippy fix --- arbitrator/jit/src/arbcompress.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/arbitrator/jit/src/arbcompress.rs b/arbitrator/jit/src/arbcompress.rs index 0d8d14bc7..8000d51b2 100644 --- a/arbitrator/jit/src/arbcompress.rs +++ b/arbitrator/jit/src/arbcompress.rs @@ -10,6 +10,7 @@ use caller_env::{self, GuestPtr}; macro_rules! wrap { ($(fn $func_name:ident ($($arg_name:ident : $arg_type:ty),* ) -> $return_type:ty);*) => { $( + #[allow(clippy::too_many_arguments)] pub fn $func_name(mut src: WasmEnvMut, $($arg_name : $arg_type),*) -> Result<$return_type, Escape> { let (mut mem, wenv) = src.jit_env(); From 9b81b11ce94c889b8c20789c427bf8475036745e Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 22 Mar 2024 19:43:21 -0500 Subject: [PATCH 773/775] Fix test timeouts in CI --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc9480eab..4898a50e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -146,13 +146,13 @@ jobs: if: matrix.test-mode == 'defaults' run: | packages=`go list ./...` - stdbuf -oL gotestsum --format short-verbose --packages="$packages" --rerun-fails=1 --no-color=false -- ./... -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -parallel=8 > >(stdbuf -oL tee full.log | grep -vE "INFO|seal") + stdbuf -oL gotestsum --format short-verbose --packages="$packages" --rerun-fails=1 --no-color=false -- ./... -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -timeout 20m -parallel=8 > >(stdbuf -oL tee full.log | grep -vE "INFO|seal") - name: run tests with race detection if: matrix.test-mode == 'race' run: | packages=`go list ./...` - stdbuf -oL gotestsum --format short-verbose --packages="$packages" --rerun-fails=1 --no-color=false -- ./... -race -parallel=8 > >(stdbuf -oL tee full.log | grep -vE "INFO|seal") + stdbuf -oL gotestsum --format short-verbose --packages="$packages" --rerun-fails=1 --no-color=false -- ./... -race -timeout 30m -parallel=8 > >(stdbuf -oL tee full.log | grep -vE "INFO|seal") - name: run redis tests if: matrix.test-mode == 'defaults' From 377c89cac7260d57e5febb1d610fbf1f5e4ef698 Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Thu, 28 Mar 2024 15:33:13 -0600 Subject: [PATCH 774/775] diffuse self-destruct --- arbos/programs/programs.go | 4 ++++ go-ethereum | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arbos/programs/programs.go b/arbos/programs/programs.go index a10376522..a86f87be2 100644 --- a/arbos/programs/programs.go +++ b/arbos/programs/programs.go @@ -76,6 +76,10 @@ func (p Programs) ActivateProgram(evm *vm.EVM, address common.Address, debugMode burner := p.programs.Burner() time := evm.Context.Time + if statedb.HasSelfDestructed(address) { + return 0, codeHash, common.Hash{}, nil, false, errors.New("self destructed") + } + params, err := p.Params() if err != nil { return 0, codeHash, common.Hash{}, nil, false, err diff --git a/go-ethereum b/go-ethereum index 8f86e725d..846839164 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 8f86e725d972a204fb91f40bf74b93b298b8689d +Subproject commit 8468391640657b3eb9ed791d4b1c3ff3b6577a8e From 2d7eb253d11be0b90a3d363c74b0d1af3e0c264d Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Mon, 1 Apr 2024 21:50:36 -0600 Subject: [PATCH 775/775] cached data pricer & minor tweaks --- arbitrator/jit/src/machine.rs | 6 +++--- arbitrator/jit/src/main.rs | 4 +--- arbos/programs/programs.go | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/arbitrator/jit/src/machine.rs b/arbitrator/jit/src/machine.rs index 47f90dc10..f51970c6d 100644 --- a/arbitrator/jit/src/machine.rs +++ b/arbitrator/jit/src/machine.rs @@ -20,7 +20,7 @@ use std::{ use thiserror::Error; use wasmer::{ imports, CompilerConfig, Function, FunctionEnv, FunctionEnvMut, Instance, Memory, Module, - RuntimeError, Store, + Pages, RuntimeError, Store, }; use wasmer_compiler_cranelift::Cranelift; @@ -281,7 +281,7 @@ impl WasmEnv { Ok(env) } - pub fn send_results(&mut self, error: Option, memory_used: u64) { + pub fn send_results(&mut self, error: Option, memory_used: Pages) { let writer = match &mut self.process.socket { Some((writer, _)) => writer, None => return, @@ -308,7 +308,7 @@ impl WasmEnv { check!(socket::write_u64(writer, self.small_globals[1])); check!(socket::write_bytes32(writer, &self.large_globals[0])); check!(socket::write_bytes32(writer, &self.large_globals[1])); - check!(socket::write_u64(writer, memory_used)); + check!(socket::write_u64(writer, memory_used.bytes().0 as u64)); check!(writer.flush()); } } diff --git a/arbitrator/jit/src/main.rs b/arbitrator/jit/src/main.rs index 32cf009d4..e432dc215 100644 --- a/arbitrator/jit/src/main.rs +++ b/arbitrator/jit/src/main.rs @@ -83,9 +83,7 @@ fn main() -> Result<()> { .get_memory("memory") .unwrap() .view(&store) - .size() - .0 as u64 - * 65_536; + .size(); let env = env.as_mut(&mut store); let user = env.process.socket.is_none(); diff --git a/arbos/programs/programs.go b/arbos/programs/programs.go index a86f87be2..d5e6138b1 100644 --- a/arbos/programs/programs.go +++ b/arbos/programs/programs.go @@ -60,7 +60,7 @@ func Open(sto *storage.Storage) *Programs { backingStorage: sto, programs: sto.OpenSubStorage(programDataKey), moduleHashes: sto.OpenSubStorage(moduleHashesKey), - dataPricer: openDataPricer(sto.OpenSubStorage(dataPricerKey)), + dataPricer: openDataPricer(sto.OpenCachedSubStorage(dataPricerKey)), } }