-
Notifications
You must be signed in to change notification settings - Fork 467
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
Implement Express Lane Timeboost #2561
Open
rauljordan
wants to merge
197
commits into
master
Choose a base branch
from
express-lane-timeboost
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
+6,505
−41
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Updated auctioneer with research spec
…o into express-lane-timeboost
…ress-lane-timeboost-eip-712
Previously we were not clearing cached tx from the previous round controller on transfer and therefore were trying to re-send old messages upon transfer. This manifested as nonce failures. This PR also makes updates to round control atomic with resetting the seen messages.
…ly-submission-grace
…ress-lane-timeboost-eip-712
…ly-submission-grace
…ly-submission-grace Add early timeboost submission grace period
…-712 Use EIP712 signing scheme for bids
Co-authored-by: Ganesh Vanahalli <[email protected]>
ganeshvanahalli
requested changes
Dec 13, 2024
if roundInfo.controller == setExpressLaneIterator.Event.NewExpressLaneController { | ||
log.Warn("SetExpressLaneController: Previous and New ExpressLaneControllers are the same, not transferring control.", | ||
"round", round, | ||
"previous", setExpressLaneIterator.Event.PreviousExpressLaneController, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggested change
"previous", setExpressLaneIterator.Event.PreviousExpressLaneController, | |
"previous", roundInfo.controller, |
Co-authored-by: Ganesh Vanahalli <[email protected]>
The logic for the calculations of "when does the next round start?", "what round is it?", "is the auction closed?", was spread throughout the code and required passing around multiple separate variables that all come from the RoundTimingInfo from the ExpressLaneAuction contract and should never change. This commit adds a domain specific RoundTimingInfo that validates these fields on construction and consolidates the aforementioned calculations. This commit also contanis a fix for auctionCloseTicker, now roundTicker. It used to assume the initial Offset timestamp fetched from the ExpressLaneAuction contract would always start on a minute boundary, and the round length would be a minute which is not always the case. This commit changes it to be called roundTicker and it now uses standard methods on the new RoundTimingInfo which take into account all possibilities for initial offset and round duration.
…actor-fix-time Refactor RoundTimingInfo, fix auctionCloseTicker
…ansfer Timeboost-test: Express lane control transfer
Co-authored-by: Ganesh Vanahalli <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
s
Automatically added by the CLA bot if the creator of a PR is registered as having signed the CLA.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Background
At the time of writing, the Arbitrum sequencer is centralized and offers a first-come, first-serve transaction ordering policy. Txs have a current delay of approximately 250ms, which is the time the sequencer takes to produce an ordered list of txs to emit in the form of an L2 block. The current policy does not handle MEV that occurs naturally on L2, and leads to latency races offline to get faster access to the sequencer ingress server.
A new policy has been proposed, known as Express Lane Timeboost, which allows participants to bid for the rights of priority sequencing using their funds instead of hardware. In “rounds” that start at each minute mark, participants can submits bids to participate in a sealed, second-price auction for control of the next round’s “express lane”. During a round, all non-express lane txs get their first arrival timestamp delayed by some amount of time (250ms), while the express lane controller does not. The express lane controller can also choose to transfer their rights in a round.
The sequencer itself does not need to manage auctions, but simply needs to know the current round number and the address of the express lane controller for that round. From there, it can delay non-express lane txs by a nominal amount required by the protocol and validate that a tx should go through the express lane.
This PR contains the complete implementation of the system with all its components. The smart contract changes are contained within OffchainLabs/nitro-contracts/tree/express-lane-auction-all-merged.
Basic Readings
To read more about timeboost, see the AIP, the research specification, and design doc although the design doc is not fully updated yet.
Reviewing
Recommend to look at the basic readings, then look at
system_tests/timeboost_test.go
to understand how it all fits together. Then, look at bid validator and auctioneer. Finally, the sequencer changes.Features
Sequencer Changes
The changes to the sequencer hot path are quite simple. In a nutshell, if a transaction is received, it checks the following:
If timeboost is enabled AND there is an express lane controller set AND it is not coming from the express lane, it delays the tx's first arrival timestamp by some amount (250ms).
To determine if a transaction is a valid express lane tx, the sequencer runs a background thread called the
expressLaneService
, which is scraping events from the ExpressLaneAuction.sol smart contract. Express lane transactions arrive via a different sequencer endpoint than the normal one, calledtimeboost_sendExpressLaneTransaction
. The message looks as follows:The submission itself contains a tx payload, which MAY not be from the express lane controller. As long as the submission is signed by the controller, that is sufficient. Submissions have a specific nonce, called a sequence, to ensure that submissions are processed in order. This is different from the inner nonce of the payload tx. The sequencer keeps a queue of submissions and ensures it processes them in order. That is, if a submission N is received before N-1, it will get queued for submission once N arrives.
Bid Validator Architecture
Bids are limited to 5 bids per sender, but there are no limits to the number of bidders in a single round. To alleviate potential scaling concerns, we adopt a simple architecture of separating the bid validators from the auctioneer. The bid validators filter out invalid items and publish validated results to a Redis stream. In a simplified diagram, here's what it will look like:
Dependencies Added
Notes
There are several parts of this implementation that are likely not ideal:
Chicken and the egg problem in sequencer
Cannot start sequencer without express lane, but cannot deploy auction for express lane without starting sequencer. To solve this in tests, we have a separate func called
StartExpressLaneService
in the sequencer. In prod, we don’t have this issue because we can deploy the contracts before we upgrade the sequencer to timeboost, but what to do about tests?Janky prioritizing of auction resolution txs
The sequencer exposes an authenticated endpoint
auctioneer_submitAuctionResolutionTransaction
over the JWT Auth RPC for the auctioneer to use. When the auctioneer is ready to resolve an auction, it submits a tx to this endpoint, which the sequencer verifies for integrity. Then, the sequencer does the following:it immediately tries to put the item in the queue and create block. It also sets the tx as a property of the sequencer struct, and in the
createBlock
func, if this field is not nil, it gets put at the top of the queue. This is a bit janky in how it works and perhaps inefficient. Is there another way to prioritize a tx in the sequencer?Sequencer opens an http connection to itself
The sequencer has a thread called
expressLaneService
which reads events from the auction smart contracts on L2 to determine express lane controllers. Because the sequencer does not havefiltersystem
API access, we instead open an RPC client against itself so we can create anethclient
to read logs and data from onchain. This doesn't seem idealReferences