Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/workflows/_go-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ on:
run-pebble-b:
required: false
type: boolean
run-experimental:
required: false
type: boolean

jobs:
go-tests:
Expand Down Expand Up @@ -296,6 +299,14 @@ jobs:
${{ github.workspace }}/.github/workflows/gotestsum.sh --timeout 90m --test_database_engine pebble
--junitfile test-results/junit-pebble-b.xml --skip '^Test[A-N]' --reduce-parallelism

# --------------------- EXPERIMENTAL MODE ---------------------

- name: run experimental tooling tests
if: inputs.run-experimental
run: >-
${{ github.workspace }}/.github/workflows/gotestsum.sh
--tags benchsequencer --run TestExperimental --timeout 60m --cover

# --------------------- PROCESS JUNIT LOGS ---------------------

- name: Process JUnit XML logs
Expand Down
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ all: build build-replay-env test-gen-proofs
@touch .make/all

.PHONY: build
build: $(patsubst %,$(output_root)/bin/%, nitro deploy relay daprovider anytrustserver autonomous-auctioneer bidder-client anytrusttool blobtool el-proxy mockexternalsigner seq-coordinator-invalidate nitro-val seq-coordinator-manager dbconv genesis-generator transaction-filterer)
build: $(patsubst %,$(output_root)/bin/%, nitro deploy relay daprovider anytrustserver autonomous-auctioneer bidder-client anytrusttool blobtool el-proxy mockexternalsigner seq-coordinator-invalidate nitro-val seq-coordinator-manager dbconv genesis-generator transaction-filterer nitro-experimental)
@printf $(done)

.PHONY: build-node-deps
Expand Down Expand Up @@ -249,6 +249,11 @@ test-go-redis: test-go-deps
.github/workflows/gotestsum.sh --timeout 120m --run TestRedis --nolog -- --test_redis=redis://localhost:6379/0
@printf $(done)

.PHONY: test-go-experimental
test-go-experimental: test-go-deps
.github/workflows/gotestsum.sh --timeout 120m --run TestExperimental --tags benchsequencer --nolog
@printf $(done)

.PHONY: test-gen-proofs
test-gen-proofs: \
$(arbitrator_test_wasms) \
Expand Down Expand Up @@ -313,6 +318,10 @@ check-license-headers:
$(output_root)/bin/nitro: $(DEP_PREDICATE) build-node-deps
go build $(GOLANG_PARAMS) -o $@ "$(CURDIR)/cmd/nitro"

# nitro built with experimental tooling enabled
$(output_root)/bin/nitro-experimental: $(DEP_PREDICATE) build-node-deps
go build $(GOLANG_PARAMS) --tags benchsequencer -o $@ "$(CURDIR)/cmd/nitro"
Comment thread
gligneul marked this conversation as resolved.
Outdated

$(output_root)/bin/deploy: $(DEP_PREDICATE) build-node-deps
go build $(GOLANG_PARAMS) -o $@ "$(CURDIR)/cmd/deploy"

Expand Down
2 changes: 2 additions & 0 deletions changelog/kolbyml-nit-4481.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### Internal
Comment thread
gligneul marked this conversation as resolved.
- Add bench sequencer RPC, config, and tests behind the benchsequencer build tag.
2 changes: 1 addition & 1 deletion cmd/util/confighelpers/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ func devFlagArgs() []string {
"--init.empty=false",
"--http.port", "8547",
"--http.addr", "127.0.0.1",
"--http.api=net,web3,eth,arb,arbdebug,debug",
"--http.api=net,web3,eth,arb,arbdebug,debug,benchseq",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thinking out loud - in Rust, I'd definitely recommend:

#[cfg(feature = "experimental")]
"--http.api=net,web3,eth,arb,arbdebug,debug,benchseq",
#[cfg(not(feature = "experimental"))]
"--http.api=net,web3,eth,arb,arbdebug,debug",

but in Go, I'm wondering if we should somehow tag-gate this api, so that user's won't see unsupported api in the list

"--node.transaction-streamer.track-block-metadata-from=1",
}
return args
Expand Down
90 changes: 90 additions & 0 deletions execution/gethexec/bench_sequencer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//go:build benchsequencer

package gethexec

import (
"context"

"github.com/ethereum/go-ethereum/log"
"github.com/offchainlabs/nitro/util/containers"
"github.com/offchainlabs/nitro/util/stopwaiter"
"github.com/spf13/pflag"
)

func BenchSequencerConfigAddOptions(prefix string, f *pflag.FlagSet) {
f.Bool(prefix+".enable", BenchSequencerConfigDefault.Enable, "enables transaction indexer")
Comment thread
gligneul marked this conversation as resolved.
Outdated
}

func (c *BenchSequencerConfig) Validate() error {
if c.Enable {
log.Warn("DANGER! BenchSequencer enabled")
}
return nil
}

func NewBenchSequencer(sequencer *Sequencer) (TransactionPublisher, interface{}) {
benchSequencer := &BenchSequencer{
Sequencer: sequencer,
semaphore: make(chan struct{}, 1),
}
return benchSequencer, NewBenchSequencerAPI(benchSequencer)
}

type BenchSequencer struct {
*Sequencer
semaphore chan struct{}
}

func (s *BenchSequencer) Start(ctx context.Context) error {
// override Sequencer.Start to not start the inner sequencer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

if we don't start the inner sequencer, how can createBlock succeed? shouldn't we run the logic from sequencer.go:Start() at some point?

s.StopWaiter.Start(ctx, s)
s.semaphore <- struct{}{}
return nil
}

func (s *BenchSequencer) TxQueueLength(includeRetryTxQueue bool) int {
if includeRetryTxQueue {
return len(s.Sequencer.txQueue) + s.Sequencer.txRetryQueue.Len()
}
return len(s.Sequencer.txQueue)
}

func (s *BenchSequencer) TxRetryQueueLength() int {
return s.Sequencer.txRetryQueue.Len()
}
Comment on lines +48 to +57

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

should we make reads somehow synchronized / mutexed? I'm not sure if we can have some race condition here


func (s *BenchSequencer) CreateBlock() containers.PromiseInterface[bool] {
return stopwaiter.LaunchPromiseThread[bool](s, func(ctx context.Context) (bool, error) {
select {
// createBlock can't be run in parallel
case <-s.semaphore:
defer func() {
// release semaphore, also in case of panic
s.semaphore <- struct{}{}
}()
return s.createBlock(ctx), nil
case <-ctx.Done():
return false, ctx.Err()
}
})
}

type BenchSequencerAPI struct {
benchSequencer *BenchSequencer
}

func (a *BenchSequencerAPI) TxQueueLength(includeRetryTxQueue bool) int {
return a.benchSequencer.TxQueueLength(includeRetryTxQueue)
}

func (a *BenchSequencerAPI) TxRetryQueueLength() int {
return a.benchSequencer.TxRetryQueueLength()
}

func (a *BenchSequencerAPI) CreateBlock(ctx context.Context) (bool, error) {
return a.benchSequencer.CreateBlock().Await(ctx)
}

func NewBenchSequencerAPI(benchSequencer *BenchSequencer) *BenchSequencerAPI {
return &BenchSequencerAPI{benchSequencer: benchSequencer}
}
12 changes: 12 additions & 0 deletions execution/gethexec/bench_sequencer_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// DANGER! this file is included in all builds
// DANGER! do not place any of the experimental logic and features here

package gethexec

type BenchSequencerConfig struct {
Enable bool `koanf:"enable"`
}

var BenchSequencerConfigDefault = BenchSequencerConfig{
Enable: false,
}
25 changes: 25 additions & 0 deletions execution/gethexec/bench_sequencer_stub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//go:build !benchsequencer

package gethexec

import (
"github.com/spf13/pflag"

"github.com/ethereum/go-ethereum/log"
)

func BenchSequencerConfigAddOptions(_ string, _ *pflag.FlagSet) {
// don't add any options
}

func (c *BenchSequencerConfig) Validate() error {
if c.Enable {
log.Warn("BenchSequencer is not supported in this build")
}
return nil
}

func NewBenchSequencer(sequencer *Sequencer) (TransactionPublisher, interface{}) {
// do nothing
return sequencer, nil
}
37 changes: 37 additions & 0 deletions execution/gethexec/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ type Config struct {
RPCServer rpcserver.Config `koanf:"rpc-server"`
ConsensusRPCClient rpcclient.ClientConfig `koanf:"consensus-rpc-client" reload:"hot"`
AddressFilter addressfilter.Config `koanf:"address-filter" reload:"hot"`
Dangerous DangerousConfig `koanf:"dangerous"`

forwardingTarget string
}
Expand Down Expand Up @@ -173,6 +174,9 @@ func (c *Config) Validate() error {
if err := c.AddressFilter.Validate(); err != nil {
return fmt.Errorf("error validating addressfilter config: %w", err)
}
if err := c.Dangerous.Validate(); err != nil {
return err

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

just for consistency, you can add context for the error, as the checks above do

}
return nil
}

Expand All @@ -197,6 +201,7 @@ func ConfigAddOptions(prefix string, f *pflag.FlagSet) {
rpcserver.ConfigAddOptions(prefix+".rpc-server", "execution", f)
rpcclient.RPCClientAddOptions(prefix+".consensus-rpc-client", f, &ConfigDefault.ConsensusRPCClient)
addressfilter.ConfigAddOptions(prefix+".address-filter", f)
DangerousConfigAddOptions(prefix+".dangerous", f)
}

type LiveTracingConfig struct {
Expand All @@ -214,6 +219,25 @@ func LiveTracingConfigAddOptions(prefix string, f *pflag.FlagSet) {
f.String(prefix+".json-config", DefaultLiveTracingConfig.JSONConfig, "(experimental) Tracer configuration in JSON format")
}

type DangerousConfig struct {
BenchSequencer BenchSequencerConfig `koanf:"bench-sequencer"`
}

var DefaultDangerousConfig = DangerousConfig{
BenchSequencer: BenchSequencerConfigDefault,
}

func DangerousConfigAddOptions(prefix string, f *pflag.FlagSet) {
BenchSequencerConfigAddOptions(prefix+".bench-sequencer", f)
}

func (c *DangerousConfig) Validate() error {
if err := c.BenchSequencer.Validate(); err != nil {
return err
}
return nil
Comment on lines +229 to +232

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

maybe for now:

Suggested change
if err := c.BenchmarkingSequencer.Validate(); err != nil {
return err
}
return nil
return c.BenchmarkingSequencer.Validate()

}

var ConfigDefault = Config{
RPC: arbitrum.DefaultConfig,
TxIndexer: DefaultTxIndexerConfig,
Expand Down Expand Up @@ -244,6 +268,7 @@ var ConfigDefault = Config{
WebsocketMessageSizeLimit: 256 * 1024 * 1024,
},

Dangerous: DefaultDangerousConfig,
AddressFilter: addressfilter.DefaultConfig,
}

Expand Down Expand Up @@ -309,13 +334,17 @@ func CreateExecutionNode(
log.Warn("sequencer enabled without l1 client")
}

var benchSequencerService interface{}
if config.Sequencer.Enable {
seqConfigFetcher := func() *SequencerConfig { return &configFetcher.Get().Sequencer }
sequencer, err = NewSequencer(execEngine, parentChainReader, seqConfigFetcher, parentChainID)
if err != nil {
return nil, err
}
txPublisher = sequencer
if config.Dangerous.BenchSequencer.Enable {
txPublisher, benchSequencerService = NewBenchSequencer(sequencer)
}
} else {
if config.Forwarder.RedisUrl != "" {
txPublisher = NewRedisTxForwarder(config.forwardingTarget, &config.Forwarder)
Expand Down Expand Up @@ -447,6 +476,14 @@ func CreateExecutionNode(
})
}

if benchSequencerService != nil {
apis = append(apis, rpc.API{
Namespace: "benchseq",
Service: benchSequencerService,
Public: false,
})
}

stack.RegisterAPIs(apis)

return execNode, nil
Expand Down
16 changes: 8 additions & 8 deletions execution/gethexec/sequencer.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ type SequencerConfig struct {
ExpectedSurplusHardThreshold string `koanf:"expected-surplus-hard-threshold" reload:"hot"`
EnableProfiling bool `koanf:"enable-profiling" reload:"hot"`
Timeboost TimeboostConfig `koanf:"timeboost"`
Dangerous DangerousConfig `koanf:"dangerous"`
Dangerous SequencerDangerousConfig `koanf:"dangerous"`
EventFilter eventfilter.EventFilterConfig `koanf:"event-filter"`
expectedSurplusSoftThreshold int
expectedSurplusHardThreshold int
}

type DangerousConfig struct {
type SequencerDangerousConfig struct {
DisableSeqInboxMaxDataSizeCheck bool `koanf:"disable-seq-inbox-max-data-size-check"`
DisableBlobBaseFeeCheck bool `koanf:"disable-blob-base-fee-check"`
}
Expand Down Expand Up @@ -215,11 +215,11 @@ var DefaultSequencerConfig = SequencerConfig{
ExpectedSurplusHardThreshold: "default",
EnableProfiling: false,
Timeboost: DefaultTimeboostConfig,
Dangerous: DefaultDangerousConfig,
Dangerous: DefaultSequencerDangerousConfig,
EventFilter: eventfilter.DefaultEventFilterConfig,
}

var DefaultDangerousConfig = DangerousConfig{
var DefaultSequencerDangerousConfig = SequencerDangerousConfig{
DisableSeqInboxMaxDataSizeCheck: false,
}

Expand All @@ -233,7 +233,7 @@ func SequencerConfigAddOptions(prefix string, f *pflag.FlagSet) {
AddOptionsForSequencerForwarderConfig(prefix+".forwarder", f)
TimeboostAddOptions(prefix+".timeboost", f)

DangerousAddOptions(prefix+".dangerous", f)
SequencerDangerousAddOptions(prefix+".dangerous", f)
EventFilterAddOptions(prefix+".event-filter", f)
f.Int(prefix+".queue-size", DefaultSequencerConfig.QueueSize, "size of the pending tx queue")
f.Duration(prefix+".queue-timeout", DefaultSequencerConfig.QueueTimeout, "maximum amount of time transaction can wait in queue")
Expand All @@ -260,9 +260,9 @@ func TimeboostAddOptions(prefix string, f *pflag.FlagSet) {
f.Uint64(prefix+".queue-timeout-in-blocks", DefaultTimeboostConfig.QueueTimeoutInBlocks, "maximum amount of time (measured in blocks) that Express Lane transactions can wait in the sequencer's queue")
}

func DangerousAddOptions(prefix string, f *pflag.FlagSet) {
f.Bool(prefix+".disable-seq-inbox-max-data-size-check", DefaultDangerousConfig.DisableSeqInboxMaxDataSizeCheck, "DANGEROUS! disables nitro checks on sequencer MaxTxDataSize against the sequencer inbox MaxDataSize")
f.Bool(prefix+".disable-blob-base-fee-check", DefaultDangerousConfig.DisableBlobBaseFeeCheck, "DANGEROUS! disables nitro checks on sequencer for blob base fee")
func SequencerDangerousAddOptions(prefix string, f *pflag.FlagSet) {
f.Bool(prefix+".disable-seq-inbox-max-data-size-check", DefaultSequencerDangerousConfig.DisableSeqInboxMaxDataSizeCheck, "DANGEROUS! disables nitro checks on sequencer MaxTxDataSize against the sequencer inbox MaxDataSize")
f.Bool(prefix+".disable-blob-base-fee-check", DefaultSequencerDangerousConfig.DisableBlobBaseFeeCheck, "DANGEROUS! disables nitro checks on sequencer for blob base fee")
}

func EventFilterAddOptions(prefix string, f *pflag.FlagSet) {
Expand Down
2 changes: 1 addition & 1 deletion go-ethereum
Loading
Loading