Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Express lane timeboost remove express lane calling sequencer #2762

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/nitro/nitro.go
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,8 @@ func mainImpl() int {
if execNodeConfig.Sequencer.Enable && execNodeConfig.Sequencer.Timeboost.Enable {
execNode.Sequencer.StartExpressLane(
ctx,
execNode.Backend.APIBackend(),
execNode.FilterSystem,
common.HexToAddress(execNodeConfig.Sequencer.Timeboost.AuctionContractAddress),
common.HexToAddress(execNodeConfig.Sequencer.Timeboost.AuctioneerAddress))
}
Expand Down
88 changes: 81 additions & 7 deletions execution/gethexec/express_lane_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,25 @@
import (
"context"
"fmt"
"math"
"math/big"
"sync"
"time"

"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"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/lru"
"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/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/offchainlabs/nitro/solgen/go/express_lane_auctiongen"
"github.com/offchainlabs/nitro/timeboost"
"github.com/offchainlabs/nitro/util/arbmath"
Expand All @@ -35,29 +41,97 @@
stopwaiter.StopWaiter
sync.RWMutex
auctionContractAddr common.Address
apiBackend *arbitrum.APIBackend
initialTimestamp time.Time
roundDuration time.Duration
auctionClosing time.Duration
chainConfig *params.ChainConfig
logs chan []*types.Log
seqClient *ethclient.Client
auctionContract *express_lane_auctiongen.ExpressLaneAuction
roundControl *lru.Cache[uint64, *expressLaneControl]
messagesBySequenceNumber map[uint64]*timeboost.ExpressLaneSubmission
}

type contractAdapter struct {
*filters.FilterAPI
bind.ContractTransactor // We leave this member unset as it is not used.

apiBackend *arbitrum.APIBackend
}

func (a *contractAdapter) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) {
logPointers, err := a.GetLogs(ctx, filters.FilterCriteria(q))
if err != nil {
return nil, err
}
logs := make([]types.Log, 0, len(logPointers))
for _, log := range logPointers {
logs = append(logs, *log)
}
return logs, nil
}

func (a *contractAdapter) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) {
panic("contractAdapter doesn't implement SubscribeFilterLogs - shouldn't be needed")
}

func (a *contractAdapter) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
panic("contractAdapter doesn't implement CodeAt - shouldn't be needed")
}

func (a *contractAdapter) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
var num rpc.BlockNumber = rpc.LatestBlockNumber
if blockNumber != nil {
num = rpc.BlockNumber(blockNumber.Int64())
}

state, header, err := a.apiBackend.StateAndHeaderByNumber(ctx, num)
if err != nil {
return nil, err
}

msg := &core.Message{
From: call.From,
To: call.To,
Value: big.NewInt(0),
GasLimit: math.MaxUint64,
GasPrice: big.NewInt(0),
GasFeeCap: big.NewInt(0),
GasTipCap: big.NewInt(0),
Data: call.Data,
AccessList: call.AccessList,
SkipAccountChecks: true,
TxRunMode: core.MessageEthcallMode, // Indicate this is an eth_call
SkipL1Charging: true, // Skip L1 data fees
}

evm := a.apiBackend.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, nil)
gp := new(core.GasPool).AddGas(math.MaxUint64)
result, err := core.ApplyMessage(evm, msg, gp)
if err != nil {
return nil, err
}

return result.ReturnData, nil
}

func newExpressLaneService(
apiBackend *arbitrum.APIBackend,
filterSystem *filters.FilterSystem,
auctionContractAddr common.Address,
sequencerClient *ethclient.Client,
bc *core.BlockChain,
) (*expressLaneService, error) {
chainConfig := bc.Config()
auctionContract, err := express_lane_auctiongen.NewExpressLaneAuction(auctionContractAddr, sequencerClient)

var contractBackend bind.ContractBackend = &contractAdapter{filters.NewFilterAPI(filterSystem, false), nil, apiBackend}

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (defaults)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (defaults)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (defaults)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (defaults)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (race)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (race)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (race)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (race)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (challenge)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (challenge)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (challenge)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (challenge)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (stylus)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (stylus)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (stylus)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (stylus)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (long)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (long)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (long)

too many arguments in call to filters.NewFilterAPI

Check failure on line 126 in execution/gethexec/express_lane_service.go

View workflow job for this annotation

GitHub Actions / Go Tests (long)

too many arguments in call to filters.NewFilterAPI

auctionContract, err := express_lane_auctiongen.NewExpressLaneAuction(auctionContractAddr, contractBackend)
if err != nil {
return nil, err
}

retries := 0

pending:
roundTimingInfo, err := auctionContract.RoundTimingInfo(&bind.CallOpts{})
if err != nil {
Expand All @@ -76,13 +150,13 @@
auctionClosingDuration := arbmath.SaturatingCast[time.Duration](roundTimingInfo.AuctionClosingSeconds) * time.Second
return &expressLaneService{
auctionContract: auctionContract,
apiBackend: apiBackend,
chainConfig: chainConfig,
initialTimestamp: initialTimestamp,
auctionClosing: auctionClosingDuration,
roundControl: lru.NewCache[uint64, *expressLaneControl](8), // Keep 8 rounds cached.
auctionContractAddr: auctionContractAddr,
roundDuration: roundDuration,
seqClient: sequencerClient,
logs: make(chan []*types.Log, 10_000),
messagesBySequenceNumber: make(map[uint64]*timeboost.ExpressLaneSubmission),
}, nil
Expand Down Expand Up @@ -121,7 +195,7 @@
log.Info("Monitoring express lane auction contract")
// Monitor for auction resolutions from the auction manager smart contract
// and set the express lane controller for the upcoming round accordingly.
latestBlock, err := es.seqClient.HeaderByNumber(ctx, nil)
latestBlock, err := es.apiBackend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
if err != nil {
// TODO: Should not be a crit.
log.Crit("Could not get latest header", "err", err)
Expand All @@ -132,7 +206,7 @@
case <-ctx.Done():
return
case <-time.After(time.Millisecond * 250):
latestBlock, err := es.seqClient.HeaderByNumber(ctx, nil)
latestBlock, err := es.apiBackend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
if err != nil {
log.Crit("Could not get latest header", "err", err)
}
Expand Down
16 changes: 4 additions & 12 deletions execution/gethexec/sequencer.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,10 @@ import (
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/offchainlabs/nitro/arbos"
"github.com/offchainlabs/nitro/arbos/arbosState"
"github.com/offchainlabs/nitro/arbos/arbostypes"
Expand Down Expand Up @@ -89,15 +88,13 @@ type TimeboostConfig struct {
AuctionContractAddress string `koanf:"auction-contract-address"`
AuctioneerAddress string `koanf:"auctioneer-address"`
ExpressLaneAdvantage time.Duration `koanf:"express-lane-advantage"`
SequencerHTTPEndpoint string `koanf:"sequencer-http-endpoint"`
}

var DefaultTimeboostConfig = TimeboostConfig{
Enable: false,
AuctionContractAddress: "",
AuctioneerAddress: "",
ExpressLaneAdvantage: time.Millisecond * 200,
SequencerHTTPEndpoint: "http://localhost:8547",
}

func (c *SequencerConfig) Validate() error {
Expand Down Expand Up @@ -190,7 +187,6 @@ func TimeboostAddOptions(prefix string, f *flag.FlagSet) {
f.String(prefix+".auction-contract-address", DefaultTimeboostConfig.AuctionContractAddress, "Address of the proxy pointing to the ExpressLaneAuction contract")
f.String(prefix+".auctioneer-address", DefaultTimeboostConfig.AuctioneerAddress, "Address of the Timeboost Autonomous Auctioneer")
f.Duration(prefix+".express-lane-advantage", DefaultTimeboostConfig.ExpressLaneAdvantage, "specify the express lane advantage")
f.String(prefix+".sequencer-http-endpoint", DefaultTimeboostConfig.SequencerHTTPEndpoint, "this sequencer's http endpoint")
}

type txQueueItem struct {
Expand Down Expand Up @@ -1242,19 +1238,15 @@ func (s *Sequencer) Start(ctxIn context.Context) error {
return nil
}

func (s *Sequencer) StartExpressLane(ctx context.Context, auctionContractAddr common.Address, auctioneerAddr common.Address) {
func (s *Sequencer) StartExpressLane(ctx context.Context, apiBackend *arbitrum.APIBackend, filterSystem *filters.FilterSystem, auctionContractAddr common.Address, auctioneerAddr common.Address) {
if !s.config().Timeboost.Enable {
log.Crit("Timeboost is not enabled, but StartExpressLane was called")
}
rpcClient, err := rpc.DialContext(ctx, s.config().Timeboost.SequencerHTTPEndpoint)
if err != nil {
log.Crit("Failed to connect to sequencer RPC client", "err", err)
}
seqClient := ethclient.NewClient(rpcClient)

els, err := newExpressLaneService(
apiBackend,
filterSystem,
auctionContractAddr,
seqClient,
s.execEngine.bc,
)
if err != nil {
Expand Down
7 changes: 3 additions & 4 deletions system_tests/timeboost_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,8 @@ func setupExpressLaneAuction(
builderSeq.nodeConfig.Feed.Output = *newBroadcasterConfigTest()
builderSeq.execConfig.Sequencer.Enable = true
builderSeq.execConfig.Sequencer.Timeboost = gethexec.TimeboostConfig{
Enable: false, // We need to start without timeboost initially to create the auction contract
ExpressLaneAdvantage: time.Second * 5,
SequencerHTTPEndpoint: fmt.Sprintf("http://localhost:%d", seqPort),
Enable: false, // We need to start without timeboost initially to create the auction contract
ExpressLaneAdvantage: time.Second * 5,
}
cleanupSeq := builderSeq.Build(t)
seqInfo, seqNode, seqClient := builderSeq.L2Info, builderSeq.L2.ConsensusNode, builderSeq.L2.Client
Expand Down Expand Up @@ -414,7 +413,7 @@ func setupExpressLaneAuction(
// This is hacky- we are manually starting the ExpressLaneService here instead of letting it be started
// by the sequencer. This is due to needing to deploy the auction contract first.
builderSeq.execConfig.Sequencer.Timeboost.Enable = true
builderSeq.L2.ExecNode.Sequencer.StartExpressLane(ctx, proxyAddr, seqInfo.GetAddress("AuctionContract"))
builderSeq.L2.ExecNode.Sequencer.StartExpressLane(ctx, builderSeq.L2.ExecNode.Backend.APIBackend(), builderSeq.L2.ExecNode.FilterSystem, proxyAddr, seqInfo.GetAddress("AuctionContract"))
t.Log("Started express lane service in sequencer")

// Set up an autonomous auction contract service that runs in the background in this test.
Expand Down
3 changes: 2 additions & 1 deletion timeboost/bidder_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ func NewBidderClient(
configFetcher BidderClientConfigFetcher,
) (*BidderClient, error) {
cfg := configFetcher()
_, _ = cfg.BidGwei, cfg.DepositGwei
_ = cfg.BidGwei // These fields are used from cmd/bidder-client
_ = cfg.DepositGwei // this marks them as used for the linter.
if cfg.AuctionContractAddress == "" {
return nil, fmt.Errorf("auction contract address cannot be empty")
}
Expand Down
Loading