Code Monkey home page Code Monkey logo

bolt's Introduction

BOLT

Docs Twitter Discord

Important

Bolt is an implementation of permissionless proposer commitments through PBS. In its essence, it consists in a light fork of the current MEV-Boost stack that allows users to request preconfirmations from proposers, and then adds a way for proposers to commit to transaction inclusion in a way that is easily verifiable.

How it works

The flow of Bolt can be summarized in the following steps:

  1. Users submit transactions to an RPC endpoint that will forward them to the proposer opted-in to Bolt in the consensus lookahead window.
  2. The proposer can accept this request and turn it into a "constraint" on the block that it is going to propose. This constraint acts as guarantee of inclusion of the transaction in the block, also known as a preconfirmation.
  3. Builders subscribe to proposer constraints in real time through a new relay streaming endpoint to keep informed about the preconfirmations.
  4. Builders build valid blocks that adhere to all constraints, and append inclusion proofs together with the bids to the relay.
  5. When it's time to propose a block, the proposer will fetch the best valid bid from the relay, and verify its inclusion proofs locally before signing the header.
  6. If the constraints are respected, the proposer can propose the payload as usual by sending the signed header back to the relay. If not, the proposer can self-build a payload and propose it directly instead.

The following diagram illustrates the flow:

sequenceDiagram
    participant Beacon Node as beacon node
    participant Bolt Sidecar as bolt-sidecar
    participant MEV-Boost as mev-boost
    participant PBS Relay as pbs relay

    Beacon Node->>Bolt Sidecar: /eth/v1/builder/header
    Note over Beacon Node, Bolt Sidecar: when it's time, the proposer's beacon node will ask for an externally built payload

    Bolt Sidecar->>MEV-Boost: /eth/v1/builder/header
    MEV-Boost->>PBS Relay: /eth/v1/builder/header_with_proofs
    PBS Relay->>MEV-Boost: ExecutionPayloadHeader + InclusionProofs
    MEV-Boost->>Bolt Sidecar: ExecutionPayloadHeader + InclusionProofs

    alt Inclusion proofs sent by the relay are VALID
        Bolt Sidecar->>Beacon Node: ExecutionPayloadHeader
        Bolt Sidecar->>MEV-Boost: /eth/v1/builder/blinded-blocks
        MEV-Boost->>PBS Relay: /eth/v1/builder/blinded-blocks
        Note over MEV-Boost, PBS Relay: the relay can now broadcast the full payload.
    else Inclusion proofs sent by the relay are INVALID
        PBS Relay->>MEV-Boost: nil response
        Bolt Sidecar->>Beacon Node: bolt-sidecar will generate a fallback ExecutionPayload that follows all constraints committed to by the proposer.
        Bolt Sidecar->>MEV-Boost: /eth/v1/builder/blinded-blocks
        MEV-Boost->>PBS Relay: /eth/v1/builder/blinded-blocks
        PBS Relay->>Beacon Node: ExecutionPayload
        Note over Beacon Node, Bolt Sidecar: after receiving the payload, the beacon node will broadcast it to the beacon chain p2p network.
    end
Loading

Scope of this repository

This repository contains all the necessary components to illustrate the flow described above. It can be thought of a reference implementation. In particular, the core components are:

  • Bolt Sidecar: New validator software (akin to mev-boost) that handles the receipt of preconfirmation requests from users, translates them into constraints, and forwards them to relays. Additionally, it handles the fallback logic to produce a block locally when relays send invalid inclusion proofs.
  • Builder: A fork of the Flashbots builder that subscribes to new constraints from relays, builds blocks that respect them, and includes the necessary proofs of inclusion in the bid submitted to relays.
  • Relay: A fork of the Flashbots relay that receives constraints from proposers, and forwards them to builders. It also receives bids with proofs of inclusion from builders, verifies them and forwards the best bid to proposers for block proposal.
  • MEV-Boost: A fork of the Flashbots MEV-Boost sidecar that includes new API endpoints to proxy requests from the Bolt Sidecar to the connected relays.
  • Bolt Contracts: A set of smart contracts for peripheral functionality such as proposer registration and permissionless dispute resolution for attributable faults.

Additionally, this repository contains the necessary scripts to spin up a Kurtosis devnet with all the components running, and a simple web demo to showcase the preconfirmation flow.

Devnet and demo app

We are using a full Kurtosis devnet stack, with custom Docker images for the core components outlined above. The exact version of the Ethereum-package used in our devnet can be seen here.

Requirements and setup

8GB of RAM and a modern laptop CPU are recommended to run the devnet efficiently, but it should work on most machines. Please Open an issue if you encounter any problems.

Make sure you have the following requirements on your machine:

Warning

The Kurtosis CLI version tested is 0.88.16. Some issues may arise if you are using a different version. Please make sure to install the correct version.

Then, clone this repository and navigate to the root directory of the project:

git clone [email protected]:chainbound/bolt.git && cd bolt

Running the devnet and demo

Running the devnet and demo is straightforward once you have the requirements installed. Just run the following commands in your terminal:

# build all necessary docker images locally first
just build-images

# spin up the kurtosis devnet on your machine
just up

# run the web demo servers.
just demo

The web demo will be available on your browser at http://localhost:3000.

Stopping the devnet and demo

The demo app will remain open until you press Ctrl+C in the terminal where you ran the just demo command.

To stop the devnet, run the following command:

# if you want to simply stop all running containers
just down

# if you want to remove all the data and stop the Kurtosis engine
just clean

Warning

Remember to shut down the devnet environment when you are done with it, as it consumes significant resources (CPU & RAM) on your machine.

License

MIT. Forked repositories have their own licenses.

bolt's People

Contributors

merklefruit avatar thedevbirb avatar mempirate avatar namn-grg avatar fmosterts avatar mksh avatar

Stargazers

Eugene Pshenichnyy avatar Dhruv Bodani avatar rms rob avatar jn avatar Matt Ma avatar Jeff avatar Léa Narzis  avatar Agnish Ghosh avatar  avatar Sileo avatar Bilal Mir avatar Sek Fook avatar dora avatar Jacob D. Castro avatar leo avatar  avatar Ghilia Weldesselasie avatar prames avatar  avatar Paramet Kongjaroen avatar vanbeethoven.eth avatar Chen Kai avatar  avatar Paul Gebheim avatar Jack McPherson avatar Eray avatar Shun Kakinoki avatar  avatar  avatar  avatar  avatar  avatar

Watchers

Lucian avatar  avatar  avatar

bolt's Issues

feat(commitments-api): Bolt RPC component

This issue is to track responsibilities and specs for the Bolt RPC component.

  • Bolt RPC is an optional proxy to route commitment requests from users to the correct proposer in the lookahead
  • On top of being great for improving the UX, it also sits in the perfect spot to fulfil the role of "challenger agent"

Here is a brief outline of the implementation steps necessary for what outlined above:

  • rpc: build a simple proxy server to forward requests from users to proposers
  • rpc: integrate with the Bolt registry to know to which proposer requests should be forwarded.
  • rpc: figure out how we the ip advertisement / discovery should work
    (related to #47)
  • challenge: add a signing backend able to send transactions for proving faults
  • challenge: add listener component to track all pending commitment challenges and detect liveness & safety faults
  • challenge: add simulation component to simulate challenge games locally before sending transactions onchain
  • challenge: add challenge tracking component to keep an updated view of pending & resolved dispute games

Use different key-pair for running the sidecar

In the first version of Bolt the sidecar will operate with an ECDSA private key, such that we can easily bind to an Ethereum address that we call BasedProposer in Bolt. This is useful for many reasons:

  • It's easier to handle all on-chain bonding, staking and payments
  • Exposing the validator's private identity is bad security practice

However, the downside is that validators normally operate with BLS12_381 private keys in the beacon chain. In our registry (where we perform the Bolt opt-in) we must somehow bind the validator identity with an ECDSA key.

To do this, we can:

  1. sign a message of this type with the BLS key:
    { "address":"0xc2B6a65d53117005eC36cB7e624484D18467b37F",  "message": "opt-in request for BOLT" }
  2. in the registry, verify the BLS signature against the BLS pubkey derived from a beacon-chain oracle. This verification should happen inside a function call for which the msg.sender is the Ethereum address that was signed in step 1.
  3. if the signature is valid, check that msg.sender matches the one in step 1.
  4. if true, update the basedProposers mapping in the registry to hold this new value.

Tasklist (to be updated)

  • Create a mapping in the registry between sidecar public keys and validator public keys (or indexes)
  • Enforce validator to specify an alternative public key before registering
  • Modify the POST constraints endpoint on the relay to authenticate via this public key. Constraints are already signed there fore we only need to check is the corresponding public key is known and associated to a validator

Submit constraints only after the commitment deadline

As we can see in the main sidecar loop here

Some(ApiEvent { request, response_tx }) = api_events_rx.recv() => {
tracing::info!("Received commitment request: {:?}", request);
let validator_index = match consensus_state.validate_request(&request) {
Ok(index) => index,
Err(e) => {
tracing::error!("Failed to validate request: {:?}", e);
let _ = response_tx.send(Err(ApiError::Custom(e.to_string())));
continue;
}
};
if let Err(e) = execution_state
.try_commit(&request)
.await
{
tracing::error!("Failed to commit request: {:?}", e);
let _ = response_tx.send(Err(ApiError::Custom(e.to_string())));
continue;
}
// TODO: match when we have more request types
let CommitmentRequest::Inclusion(request) = request;
tracing::info!(
tx_hash = %request.tx.hash(),
"Validation against execution state passed"
);
// parse the request into constraints and sign them with the sidecar signer
let message = ConstraintsMessage::build(validator_index, request.slot, request);
let signature = signer.sign(&message.digest())?.to_string();
let signed_constraints = vec![SignedConstraints { message, signature }];
// TODO: fix retry logic
let max_retries = 5;
let mut i = 0;
'inner: while let Err(e) = mevboost_client
.submit_constraints(&signed_constraints)
.await
{
tracing::error!(err = ?e, "Error submitting constraints, retrying...");
tokio::time::sleep(Duration::from_millis(100)).await;
i+=1;
if i >= max_retries {
break 'inner
}
}

constraints are submitted immediately to MEV-Boost after quick checks on protocol rules (nonce, balance, base fee). In turn, this constraints are then forwarded to relays and pulled from builders.

This is actually not desirable behaviour because a pre-confirmation could be invalidated if, in the slot where the pre-confirmation will be executed, the user has an higher nonce or an insufficient balance.
In such case the proposer won't be slashed because it can prove on-chain what happened, however the builder won't be able to produce a bid with all the proofs which will be discarded by MEV-Boost, leading to a sub-optimal locally built block.

In order to solve this, pre-confirmations should be cached by their slot and when a new head comes we should check again their validity. Lastly, constraints should be submitted only after the commit deadline for a given slot is crossed.

Add proofs verification to relay

When the relay receives a new builder bid it should verify its inclusion proofs before saving it. This is needed since we lower the chances the proposer receives an invalid block and has to resort to a locally built one

Discussion: simulation & local block building

Context

Simulation

Some simulation & validation is required to consider a preconfirmation. At minimum, they need to be valid according to the protocol rules:

  • Enough balance to pay for gas usage + specified gas price
  • Correct basefee (> block basefee)
  • Correct nonce

This is simple enough for a standalone transaction: we just request all necessary values from the execution client over JSON-RPC and match those against the received transaction.

Once we commit to a transaction, we need to keep track of any relevant variable state: the nonce and the balance. This is because essentially we've already executed the transaction, and any subsequent transactions need to be valid given the modified nonce and balance. This means that the sidecar should build some sort of proto-block template that keeps track of nonce and balance per account, and should check each new transaction against the post-state of that proto-block.

⚠️ Note on type 3 transactions: for type 3 transaction preconfs there is the additional requirement that there can only be an absolute maximum of 6 blobs per block.

Local building

For non-PBS proposers or in the case mev-boost fails, we need a way to fall back to a locally built block that adheres to any commitments given.

We can point our beacon node builder API to the sidecar instead of mev-boost, and the sidecar will act like a proxy for mev-boost (if configured) and a local block builder. Non-mev-boost users can configure the sidecar to not proxy requests to mev-boost.

Minimum viable block (easy)

Since the sidecar always keeps a (valid) block template, we can just use that when a payload is requested in a local block building situation. If there were no commitments made, we just don't return a block which will force the beacon node to get one from the execution client over the engine API.1

What's important here is that we respond in time with a payload so that the beacon node won't fall back to the execution client, which would break commitments. This delay is defined in the specs as BUILDER_PROPOSAL_DELAY_TOLERANCE=1s.2

Better block (hard)

Another potential option would be to have our sidecar communicate with the execution client through the engine API to request a block (this already is hard because it requires access to the payloadId which is something that only the beacon node has AFAIK).3

Once we have that block, we can modify it to include our commitments with some naive algorithm that takes into consideration the block value and block validity. We then derive the header once more and send it to the beacon node, who will take care of the rest.

The second option would obviously be much better for local builders but is much more complex.

Footnotes

  1. https://github.com/ethereum/builder-specs/blob/main/specs/bellatrix/validator.md#relation-to-local-block-building

  2. https://github.com/ethereum/builder-specs/blob/982af908707113de373e62babee113782e6bb6cd/specs/bellatrix/validator.md#constants

  3. https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#request-2

Remove contract dependencies

We currently rely on the following dependencies:

It would be nice if the Challenger didn't have any third party dependency in Bolt, as it means it's more ergonomic to deploy on devnets and testnets. This issue is to keep track of dependencies and eventually decide on the best strategy to remove them.

Move proof verification logic to the sidecar

When the builder submits a bid with proofs of transaction inclusion, the relay propagates them and they're verified inside our mev-boost fork. However, since the sidecar is the entrypoint from the builder api and a proxy for mev-boost it makes sense to move proof verification there, and keep the mev-boost fork as light as possible.

On-chain proof challenge game for commitment verification

Currently, it's easier and more efficient to use a single-shot challenge for verifying constraints:

  1. A challenger (ideally permissioless, so anyone holding a signed BOLT proposer commitment) creates a new Challenge
  2. When an event is emitted, the targeted BOLT proposer (via its sidecar) should respond by sending a transaction to prove the inclusion in his committed block. We can set a 7 day deadline to this response.
  • Challengers will need to post a small ETH bond, so that there is no incentive to spam the network with challenges as the proposers get refunds for the gas required for responding to these challenges truthfully.
  • Failure to respond in time to the challenge will be considered the same as a fault.
  • For now, there is no slashing implemented, but an event can be emitted to signal a proposer fault.

Challenge game overview

  • alice: user that creates a challenge
  • bob: proposer opted in BOLT as a preconfirmer
  1. alice submits a challenge with: bob's signed preconfirmation commitment as well as the unsigned message containing the transaction hash over which the commitment was made (depending on what the exact commitment will look like, TBD)
  2. the challenge() function will:
    1. verify that the signed commitment resolves back to bob's pubkey via ECDSA recovery
    2. verify that bob is registered in BOLT's on-chain registry (#15)
    3. verify that bob was scheduled as proposer for the slot specified in the signed preconfirmation
    4. emit an event
  3. at this point bob needs to defend by calling resolveChallenge():
    1. verify that there is an active challenge against him
    2. verify the the actual inclusion commitment

In terms of the commitment verification step, there are a few dependencies:

  1. we need an oracle for historical transactions roots. After Dencun this is possible thanks to the BEACON_ROOTS contract. Relic Protocol have already done the work to provide an oracle for all block header contents that's easily provable on-chain.
  2. ideally the transactions-root and beacon-root of the target block should be stored in the challenge contract's storage, so they don't get wiped after a while. The beacons root contract only keeps the 8191 most recent roots in a buffer (about 1 day).
  3. once we have this info, bob will still need to provide 3 things: the hash_tree_root of the included transaction, the index in the block of the transaction, and the ssz proof. Verification will entail checking that the proof + the given hash tree root hash to the correct transactions_root saved in the contract beforehand.
  4. additionally, the hash_tree_root will also need to be checked against the raw RLP signed transaction that was preconfirmed

Allow testing sidecar functionalities without spinning up the devnet

At the moment to test the sidecar it is necessary to spin up the kurtosis devnet which, along with building docker images, takes a considerable amount of time, resulting in a slow feedback loop.
Ideally, it'd be better to be able to test some sidecar functionalities with just the standalone process. This requires a refactoring of the sidecar which includes various mocked components, such as beacon node, execution node, mev-boost.

fallback block building logic

For this PoC we'd like to have the sidecar and mev-boost as close as possible to a final design. As such, we need to take into account locally built blocks in case the builder does not provide proofs of inclusion. This logic should be implemented in the Bolt sidecar. For simplicity, the locally built block can just contain the pre-confirmed transactions

Modify constraint information flow

Context

Currently, the block builder polls the constraints directly from the proposer by communicating with the sidecar. Ideally, there's not too much pull-based communication on the proposer side for DoS concerns. We can change the flow like so:

  1. Proposer pushes constraints to relay
  2. Builder pulls constraints from the relay

This decreases load and DoS vectors on the proposer sidecar.

Successful execution preconfs and use cases using `receipts_root`

For inclusion preconfirmations we're leveraging the transactions_root field of the execution block header along with Merkle proofs.
In order to prove successful execution of a transaction (or a bundle) we could do the same but with the receipts_root of the receipt MPT. The flow will look as follows:

  • Users ask for transaction inclusion with successful execution
  • Proposer signs commitments and those get propagated up to the builder level
  • The builder provides Merkle proof of inclusion of the transaction at index i (it is already like this) along with the i-th receipt data and a MPT Merkle proof of inclusion
  • The proposer then checks that both proofs are valid and that the receipts data shows a successful execution.

The receipt also contains all the logs emitted by the transaction. We should explore what use cases this unlocks!

Blob tx spammer via CLI

At the moment we've a transaction spammer to test preconfirmations which can be run from the CLI. It'd be helpful to have extend it to support random blob transactions.
Ideally, along with the just send-preconf we could have another command called just blob-preconf (renaming those two is perfectly fine) that sends the type 3 tx

Document the entire BOLT flow

Add documentation for BOLT with the current goals:

  • small intro to the project and what are the goals of this proof of concept
  • detailed changelog for every component (excluding the web-demo)
  • update general README

Sidecar: Telemetry & Metrics

Bolt-sidecar telemetry

Support min-bid

Context

  • Depends on a better local building algorithm compatible with PCs as described in #59

We should support the min-bid parameter for mev-boost.

Decide the value of the constant `MAX_CONSTRAINTS_PER_SLOT`

In order to encode constraints using SSZ we need to provide a maximum length to list. Regarding constraints, I decided for now to just set it to MAX_CONSTRAINTS_PER_SLOT = 256 but this is up to discussion whether this value is reasonable or not.

Other than changing the value in the codebase and in the SSZ encoding functions, we should also define this constant value in the specs website

Sidecar StateDriver

The responsibilities of the sidecar main loop are starting to grow as we develop the fallback block building and consensus state container. Right now the main loop is exposed in the executable bin/sidecar.rs, but ideally that file should just contain initialization code and not business logic.

To clean this up, we will create a StateDriver component with the following responsibilities:

  1. subscribe to the latest head updates from the HeadTracker
  2. run function with an infinite loop:
    • await for a new head event to be emitted
    • try to update the execution_state with its update_head() method
    • try to update the consensus_state with its update_head() method
    • in the future: handle reorgs as well

Sidecar: invalidate past state

Block templates should be cleared once a new head for that slot has been received from the CL.
Furthermore, tracked nonces should be only reset if a preconfirmed transaction was successfully included in a block.

// TODO: invalidate any state that we don't need anymore (will be based on block template)

State diffs are not used for validating new preconfirmation requests

The validation of incoming preconfirmation requests is currently flawed because the nonce and balance checks are performed against the current account state (from the latest known head) but without considering prior preconfirmations (i.e., the state diffs). To solve this, we should check against both the account state and the state diffs.

Example:
We're at slot $N$ and I make two preconfirmation requests for slot $N+2$. The validation of the second preconfirmation is successful because it is not considering the temporary state difference generated from the first request.

Support blobs in MEV-Boost/Relay/Builder forks

There is already an issue to support blobs in the Bolt sidecar: #105. However, some work is also needed in the rest of the pipeline to make sure the builder is able to create bid with pre-confirmed blob transaction.

Ideally, this should be done by not making any breaking change to the specs.

Tasks

Specify authorization schema for builders

Builders need to authenticate when subscribing to SSE events emitted from relays. Right now in the codebase we're using a string like this:

"BOLT \"<signature>\",{\"publicKey\":\"<builder_pub_key>\",\"slot\":<slot>}"

where signature refers to the JSON-stringified object appearing the in the authentication message.
However, we should discuss more about it and update the specs.

The rationale for this schema is to have a simple one that included the builder public key, a nonce-like number to avoid replay attacks and a signature

On-chain registry

BOLT should have an on-chain registry smart contract with the following functionality:

  1. Keep track of currently opted-in proposers, identified by (at least) their pubkey
  2. Ability to add a proposer with a transaction sent by a proposer's private key. this can be a simple transaction for simplicity but could also resort to more complex delegation methods later on.
  3. Ability for a proposer to opt out with a 1 day cooldown
  4. Ability for other contracts to read information about opted-in proposers
  5. Events emitted on proposer status changes

Sidecar: check user balance and nonce before sending commitments

In the context of the recent proposal of account abstraction it may be possible that a transaction changes the balance of an EOA without increasing its nonce, since it can be originated by another entity.
As such, in the sidecar we should:

  • wait for the right slot before sending the commitments and
  • check both balance and nonce according to the current state

bug(sidecar): validate `chain_id` when accepting a commitment request

when sending a transaction built with the wrong chain_id, the sidecar throws this error:

2024-07-05T14:38:09.150194Z ERROR bolt_sidecar: CRITICAL: Error while building local payload at 
slot deadline for 101886 err=InvalidEngineHint("{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"status\":\"INVALID\",
\"latestValidHash\":\"0x92ffd66bbf1e791b2680f6f2b9f7b84abba3cded05eb419fda9dde6f3085c4cd\",\
"validationError\":\"could not apply tx 0 [0x9f654551aa0d7f63fff3267b9deb39b6d8b74e389db9592b951419753991a534]: 
invalid chain id for signer: have 3151908 want 7014190335\"}}\n")

we should add a check in ExecutionState::try_commit to validate the chain_id according to the configured ChainConfig.

Implement hash tree root for `ConstraintsMessage`

In our fork of Flashbots' relay we added an endpoint to submit signed constraints (https://chainbound.github.io/bolt-docs/api/constraints-api#relayv1builderconstraints), with the underlying message of type ConstraintsMessage.
Right now, we verify signatures using the SSZ encoding as digest; we should use the hash tree root of such container instead, as done with other containers in the consensus specs.

Tasks

Meta: Bolt Registration & Authentication

Docs reference: https://chainbound.github.io/bolt-docs/architecture#opt-in-procedure-for-proposers

Bolt Opt-in for Proposers (ECDSA version)

Ethereum validators will have the option to opt-in to the Bolt protocol by registering with the Bolt Registry smart contract.
The registration process is as follows:

  1. The Proposer signs a message with their withdrawal address private key 1 to signify that they are requesting to opt-in. The message will need to contain the Ethereum address that the proposer intends to use as signer to authenticate individual preconfirmation requests. This way, the proposer in Bolt will have a separate identity from its validator private keys for added security.
  2. The Proposer sends a transaction to the Registry, requesting to opt-in into Bolt. The transaction must be sent from the same address that was specified in the signed message, which must be passed in the transaction's data. This way, the ownership of this new ECDSA key-pair is proven on-chain.
  3. Once opted-in, the Proposer must add some form of collateral to guarantee economic credibility behind its preconfirmations. The specific method in which this is achieved in Bolt is left as an open point for now.

Commitment signing

Technically, we don't need to use a specific signing scheme or signature type to produce commitments.
However, here are a couple factors that we want to keep in mind while making this decision:

  • we care about verifiability on the EVM
    • the Ethereum protocol already supports secp256k1 natively and already has a Ecrecover precompile.
    • bls12_381 signatures are used in the consensus layer, but they won't be verified on the EVM until Pectra
    • other types of signatures (e.g. ed25519) are never used in Ethereum and as such aren't the first choice
  • we care about signing speed (somewhat)
    • unless signing takes way more time than expected, then this isn't really a huge priority: we anticipate network phisical latency will be the main source of latency anyway

Footnotes

  1. One alternative for node operators is to use the private key that they authenticate with on shared security protocols.

Usage of `ValidatorIndex` inside Bolt Sidecar

Our current API definitions for constraints contain the validatorIndex of the validator that is opted-in to Bolt and has signed that specific preconfirmation request.

This means that we have to deal with this when generating the constraints, which happens inside Bolt sidecar.
Right now, this value is set to 0 always here: https://github.com/chainbound/bolt/pull/53/files#diff-709413e7867c3101338b843ff608b31b209deb676433b25160302d6819deafffR124

This issue is to keep track of this dangling data point and to brainstorm solutions. Some questions:

  • should bolt sidecar work with >1 validators connected? if so, how do we figure out which validator to sign commitments with
  • are there DDoS attacks that benefit from knowing the validatorIndex bound to some bolt sidecar?

Meta: reconsider `constraint` interface

Context

Our current constraint interface is not very flexible. We should think about a schema that can support more logic, like what would be necessary to lock state or partial block building etc. Perhaps gmev-boost could serve as inspiration here?

Goals

The constraint interface should be as simple as possible, while still allowing a lot of expressivity. We won't have many chances to iterate on this, so it should be future proof.

Specification

builder-API

Original specs: https://ethereum.github.io/builder-specs/

Responsibilities

  • Proposer should be able to submit constraints through the builder API
  • Proposers should be able to get bids with proofs of constraint validity

/eth/v1/builder/constraints

  • Method: POST
  • Parameters: None
  • Body:
// Example: 2 inclusion constraints where the transactions can be placed anywhere in the block

[
  {
    "message": {
      "validatorIndex": 97,
      "slot": 987432,
      "constraints": [
        { "tx": "0xabc", "index": null }
      ] 
    },
    "signature": "0x..." // BLS validator signature
  },
  {
    "message": {
      "validatorIndex": 97,
      "slot": 987432,
      "constraints": [
        { "tx": "0xdef", "index": null }
      ] 
    },
    "signature": "0x..." // BLS validator signature
  }
]

// Example: a bundle of 2 transactions executed at the top of the block

[
  {
    "message": {
      "validatorIndex": 97,
      "slot": 987432,
      "constraints": [
        { "tx": "0xabc", "index": 0 },
        { "tx": "0xdef", "index": 1 }
      ] 
    },
    "signature": "0x..." // BLS validator signature
  }
]

// Example: a bundle of 2 transactions that must be executed atomically, but have no constraints
// on the position in the block

[
  {
    "message": {
      "validatorIndex": 97,
      "slot": 987432,
      "constraints": [
        { "tx": "0xabc", "index": null },
        { "tx": "0xdef", "index": null }
      ] 
    },
    "signature": "0x..." // BLS validator signature
  }
]
  • Response: Empty

/eth/v1/builder/header_with_proofs/{slot}/{parent_hash}/{pubkey}

  • Method: GET
  • Parameters: slot (path), parent_hash (path), pubkey (path)
  • Body: Empty
  • Response:
{
  "version": "bellatrix",
  "data": {
    "message": {
      "header": {
        "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09",
        "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "receipts_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "prev_randao": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "block_number": "1",
        "gas_limit": "1",
        "gas_used": "1",
        "timestamp": "1",
        "extra_data": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "base_fee_per_gas": "1",
        "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "transactions_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
      },
      "value": "1",
      "constraint_proofs": {
        "indeces": [ 1 ],
        "hashes": [ "0xabc", "0xdef" ]
      }, // The constraint proofs are SSZ Merkle multiproofs
      "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a"
    },
    "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
  }
}

relay-API

Original specs: https://flashbots.github.io/relay-specs/

Responsibilities

  • Communicate constraints to builders in a timely manner
  • Implement updated block submission endpoint with proofs

/relay/v1/builder/constraints

  • Method: GET
  • Parameters: backfill (query)
  • Body: Empty
  • Response: Stream with items:
{
    "message": {
      "validatorIndex": 97,
      "slot": 987432,
      "constraints": [
        { "tx": "0xdef", "index": null }
      ] 
    },
    "signature": "0x..." // BLS validator signature
  }

/relay/v1/builder/blocks_with_proofs

  • Method: POST
  • Parameters: cancellations (query)
  • Body:
Click to see Body
{
  "message": {
    "slot": "1",
    "proposer_index": "1",
    "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
    "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
    "body": {
      "randao_reveal": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505",
      "eth1_data": {
        "deposit_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "deposit_count": "1",
        "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
      },
      "graffiti": "0xdeadbeefc0ffeedeadbeefc0ffeedeadbeefc0ffeedeadbeefc0ffeedeadbeef",
      "proposer_slashings": [
        {
          "signed_header_1": {
            "message": {
              "slot": "1",
              "proposer_index": "1",
              "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
              "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
              "body_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
            },
            "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
          },
          "signed_header_2": {
            "message": {
              "slot": "1",
              "proposer_index": "1",
              "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
              "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
              "body_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
            },
            "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
          }
        }
      ],
      "attester_slashings": [
        {
          "attestation_1": {
            "attesting_indices": [
              "1"
            ],
            "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505",
            "data": {
              "slot": "1",
              "index": "1",
              "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
              "source": {
                "epoch": "1",
                "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
              },
              "target": {
                "epoch": "1",
                "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
              }
            }
          },
          "attestation_2": {
            "attesting_indices": [
              "1"
            ],
            "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505",
            "data": {
              "slot": "1",
              "index": "1",
              "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
              "source": {
                "epoch": "1",
                "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
              },
              "target": {
                "epoch": "1",
                "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
              }
            }
          }
        }
      ],
      "attestations": [
        {
          "aggregation_bits": "0x01",
          "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505",
          "data": {
            "slot": "1",
            "index": "1",
            "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
            "source": {
              "epoch": "1",
              "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
            },
            "target": {
              "epoch": "1",
              "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
            }
          }
        }
      ],
      "deposits": [
        {
          "proof": [
            "0xeeffb6c21a01d3abf09cd6c56e5d48f5ea0fc3bb0de906e3beea3e73776329cb",
            "0x601c3b24a99d023224d50811bed19449890febb719a31d09ac414c4632f3c0ba",
            ...
          ],
          "data": {
            "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a",
            "withdrawal_credentials": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
            "amount": "1",
            "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
          }
        }
      ],
      "voluntary_exits": [
        {
          "message": {
            "epoch": "1",
            "validator_index": "1"
          },
          "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
        }
      ],
      "sync_aggregate": {
        "sync_committee_bits": "0x01",
        "sync_committee_signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
      },
      "execution_payload_header": {
        "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09",
        "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "receipts_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "prev_randao": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "block_number": "1",
        "gas_limit": "1",
        "gas_used": "1",
        "timestamp": "1",
        "extra_data": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "base_fee_per_gas": "1",
        "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
        "transactions_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
      }
      "constraint_proofs": {
        "indeces": [ 1 ],
        "hashes": [ "0xabc", "0xdef" ]
      }, // The constraint proofs are SSZ Merkle multiproofs
    }
  },
  "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
}
  • Response: Empty

Don't decode constraints when sealing blocks

As noted by @merklefruit in #46 (comment), in the builder we decode the constraint when running the building job. This is not ideal since RLP decoding takes some time and moreover it can be done when we receive the constraints in the first place.

Sidecar: `ConsensusState` container

Context

Just like we have execution state to validate commitment requests against, we should have a consensus state container. This consensus state will be used to validate commitments against the consensus state. The module should live in src/state/consensus.rs.

The consensus state should have access to a beacon client that it can use to query the beacon chain with. Just like ExecutionState, it should have a fn update_head(&mut self, head: ChainHead) that it will use to update its internal state with. We will have a separate HeadTracker actor that will initiate these update calls.

The validate_request method

To validate a request, we need to

  • Check if the target slot is one of our proposer slots (need access to a live lookahead + the registry)
  • Check if the request hasn't passed the slot deadline (i.e. timestamp of prev update + some configurable deadline like 6s)

If validate_request passes, we can continue validation on the execution state.

Handle two or more pre-confirmations at the same slot in the demo

There is an edge case in the frontend demo where sending two pre-confirmations rapidly in the same slot can cause the second one to fail with NonceTooLow error.
This is due to fact the nonce is obtained from the provider i.e. the execution state, which hasn't processed the pre-confirmed transaction yet, and as such the nonce of same transaction is the same of the first one.

In order to solve this, in the frontend we should increment the nonce of the account upon receiving the commitment from the sidecar

Restore BLS signature check on constraints for devnet

For the devnet is not trivial to send constraints from the sidecar signed by the right BLS secret key. This is because we should fetch the assigned validator for the slot we want to send a preconf on and retrieve it's secret key and sign the message.
In order to do this, we should follow some steps:

This is the result I've obtained with such mnemonic and derivation path:

Path                Public Key                                                                                          Secret Key
m/12381/3600/0/0/0	aaf6c1251e73fb600624937760fef218aace5b253bf068ed45398aeb29d821e4d2899343ddcbbe37cb3f6cf500dff26c	0dce41fa73ae9f6bdfd51df4d422d75eee174553dba5fd450c4437e4ed3fc903
m/12381/3600/1/0/0	8aa5bbee21e98c7b9e7a4c8ea45aa99f89e22992fa4fc2d73869d77da4cc8a05b25b61931ff521986677dd7f7159e8e6	3219c83a76e82682c3e706902ca85777e703a06c9f0a82a5dfa6164f527c1ea6
m/12381/3600/2/0/0	996323af7e545fb6363ace53f1538c7ddc3eb0d985b2479da3ee4ace10cbc393b518bf02d1a2ddb2f5bdf09b473933ea	215768a626159445ba0d8a1afab729c5724e75aa020a480580cbf86dd2ae4d47
m/12381/3600/3/0/0	a1584dfe1573df8ec88c7b74d76726b4821bfe84bf886dd3c0e3f74c2ea18aa62ca44c871fb1c63971fccf6937e6501f	10c3db5c5bdca44958bc765e040a5cae3439551cfb4651df442cbe499b12ee69
m/12381/3600/4/0/0	ac69ae9e6c385a368df71d11ac68f45f05e005306df3c2bf98ed3577708256bd97f8c09d3f72115444077a9bb711d8d1	5d6534de54d1e4112f45da73f11d265361669bf1f96816f111e67e4665a4c2ad
m/12381/3600/5/0/0	a54fe5c26059ed60b4f0b66ef7b0bf167580504525f83c169507dc812816df41b1da6128341c23977300dffd32a32f41	41f692b9306a699ce01ba5b13fd04776ef5898e0ab09f06e37ba22abe43e403e
m/12381/3600/6/0/0	ad9222dec71ff8ee6bc0426ffe7b5e66f96738225db281dd20027a1556d089fdebd040abfbc2041d6c1a0d8fdcfce183	2799191f62a8c55708b2deab69a995d4be56e3fa736318533341ca5476df3087
m/12381/3600/7/0/0	87231421a08ed28e7d357e2b37a26a458155c8d822d829344bd1029e5d175b5edfaa78f16f784f724a2caef124944c4f	1c511df0a39ec614499b08cf284d2d1d1aec3c231809c1c5688a4daab09f7752
m/12381/3600/8/0/0	b72cb106b7bc1ecae219e0ae1830a509ed18a042b56a2779f4033419de69ba8ae8017090caed1f5377bfa68506157360	506f148597da5e2cfd570709dea00c629e5dc1a21068cf2f11dd3bfc367d7396
m/12381/3600/9/0/0	b27ad13afc8ff30e087797b344c8382bb0a84447549f1b0274059ddd652276e7b148ba8808a10cc45746762957d4efbe	564d2ac37d9764fd6e57d55e0c18b0e13aa604220d5a625c11a682c4012a7c85
m/12381/3600/10/0/0	aaddb0cb69ca18f14aed7054e98a24df0ff606aeff919d489f7884fd1bd183bcb46ea54bc363146e1a88db36dc20a7a4	42b6a18c8fea7a7ae32ec398a8c773a5655d0706f7431e546ee3f5125623a9c7
m/12381/3600/11/0/0	996d10c3026b9344532b06c70a596f972a1e779a1f6106d3da9f6ba376bbf7ec82d2f52629e5dbf3f7d03b00f6b862af	67c9273b1e701a2552492cdc812bd7b4fb8da18d269b33fad08353979fcfacca
m/12381/3600/12/0/0	91709ee06497b9ac049325853d64947290189a8c2322e3a500d91e23ea02dc158b6db63ae558b3b7670357a151cd6071	1ec2684216f3e173c6357e4885087eeae29b22ac2f3324eb3a8d46fb83ee9439
m/12381/3600/13/0/0	a03c2a82374e04b2e0594c4ce14fb3f225b46f13188f0d8002a523c7dcfb939ae4856053c2c9c695374d7c3685df1ca5	3713f2b1a851a9f0ae7790cedb75c20ac3374e9d0e87ae348758178eaaba1833
m/12381/3600/14/0/0	ab72cbc6575c3179680a58c0ecd5de46d2678ccbafc016746348ee5688edcb21b4e15bd37c70c508e3ea73103c2d566b	37ac433279406eaae9381391578fbb79a52f27884cc59f9957062d36e0e49f2f
m/12381/3600/15/0/0	afa10af166a0dbf3a25ff86cd6f8e44cccc818c5e70cd70e4e98e226b158f3563450b3fb184d2649adbb11e53080d1ca	2307b98643e0aa2087da182efd19beddec032a600fc6e32f8274649233b29597
m/12381/3600/16/0/0	abd12678c73463ecea5867a80caf256d5c5e6ba53ff188b143a4d5be83365ad257edf39eaa1ba8753c4cdf4c632ff99e	6ba6e27a754f7c10dc0a7f4a2effcefea2333a163ef4fdbd2cdc603d0bababa9
m/12381/3600/17/0/0	a35c6004f387430c3797ab0157af7b824c8fe106241c7cdeb897d900c0f9e4bb945ff2a6b88cbd10e35ec48aaa554ecb	594b085495f43172b7df9da34b3b545f3fac51c44f9c1eaf757cef61fc341229
m/12381/3600/18/0/0	8a8bb292bcc481070d3afdbbc8789e2ab4b29c9603936e6d85f5ff71e23fc5b6d61009f0fa636b5d5b2dc309d39e3d75	16a1ec185cf2c157111868bf129c2c525393606dcaef5892e83177f8c6ae3f0d
m/12381/3600/19/0/0	ae940a07850cf904b44f31cbf0e44824bae5ec36dcfdb7fad858f2a39dba38de82ca12b0ae939a34fce7a02e4b9789f8	04f7e7237d440de0c93ea31e17a0d4f6f2e59f6bf1ce794bb1f64c8d418f5024
m/12381/3600/20/0/0	a75ca9447dca3a3745ada36731187ddd1f6a152cf15d7446b785eab381e5c8562c1202a6e7a24080bc6b619a161113db	6936bdabd457531685f11ee671d5215c89f7a8e1cc41d5096f04dcdbf5d50078
m/12381/3600/21/0/0	84a687ffdf21a0ad754d0164d1e2c03035613ab76359e7f5cf51ea4a425a6ee026725ec0a0dbd336f7dab759596f0bf8	25251ccac071e264192f836d787515fcc7f03d0a929bb07f2723f7e6870a6446
m/12381/3600/22/0/0	96947de9e6068c22a7716656a2755a9551b0b66c2d1a741bf84a088fe1e840e992dc39861bf8ba3e8d5b6d21e8f57e64	56e3a0b3904203f8a76ee01cefe12bbe729f15a77fbb7a28de2482d5a72ee58b
m/12381/3600/23/0/0	b570dde8ee80512e3d031caf22e775c60f7f5a6cbdeb3e52e24cf8c867d38569a53dd19cdc36a03a1bbb3a8d94b03670	0356278d0cf6339858409684fb20f1a71ad45c9d67fde52590e9753d8891ae6a
m/12381/3600/24/0/0	ae5302796cfeca685eaf37ffd5baeb32121f2f07415bee26cc0051ee513ff3932d2c365e3d9f87b0949a5980445cb64c	15007626ca62829654a0b352cfd25dab874b7b23a81e3d525dffdb0b872ebada
m/12381/3600/25/0/0	8de5a6200cebb09b2198e69fed84bcd512ec5cf317c5f1ee99aad03d2a9a8564bf3807c08da2664222268d59c34a06e4	0701010ffc10a5b5770e9b913ef7e254c78137ac42e15aafc4c748a3eb9631f2
m/12381/3600/26/0/0	a1d9840eda3036fbf63eeea40146e4548553e6e1b2a653ab349b376f31b367c40d71fb59ff8e94b91daa99c262ec8b52	26481214fd7b9eb031540e159d614dd24988f36d385431954e3a60e67abb0583
m/12381/3600/27/0/0	8419cf00f2783c430dc861a710984d0429d3b3a7f6db849b4f5c05e0d87339704c5c7f5eede6adfc8776d666587b5932	1761b055dd11d5d2e0a944bd980c94586473d43bf7acc34d8675b9d61b951650
m/12381/3600/28/0/0	8d46e9aa0c1986056e407efc7013b7f271027d3c98ce96667faa98074ab0588a61681faf78644c11819a459a95689dab	164e3c2a47a794904f1a719e0396f74b2af7fa62c9f7255a3feca6293783ccc5
m/12381/3600/29/0/0	930743bfc7e18d3bd7351eaa74f477505268c1e4e1fd1ca3ccccdefb2595517343bbb8f5589c435c3c39323a4c0080f8	0b78b00d212e825c8e4fc61ea12cd947263b279964f1aa6e1dd7ba8e6b1fe6f0
m/12381/3600/30/0/0	81ea9f74ef7d935b807474e38954ae3934856219a23e074954b2e860c5a3c400f9aedb42cd27cb4ceb697ca36d1e58cb	4bf3d116cb5948a8c18ffc368139be028b8a714a5196acf04e7c3179866abe94
m/12381/3600/31/0/0	a804e4fa8d1391a9d078aa93985a12503b84ce4f6f1f9e70ab7fca421e1cf972538666299d4c1bfc39327b469b2db7a8	3cb934196410d6311fd486b674ec7fd484b7c8e69e75ae3441f8b02977334a02
m/12381/3600/32/0/0	ab40dc1cfe273ad0da700c64f8fc94f91db253ca3acf20e336d9bd09de67eec5c7d3506285d83c7bb6a08d64b77e5f2d	46317e3565ea8cc6077b10140b40d8d1615bf77fabf63e4846adabb4897f635e
m/12381/3600/33/0/0	8dfa86c051edd28c3554a30e40531c898e5936ad3002711616ddd1b27054bc39caedd505a200c3d23a1c3f6b26c50ae9	51090951fb358f1ef9ecbaa3488d1f65d8fdfb01cc23f973c576958b59d4ad17
m/12381/3600/34/0/0	81fa222737fe818b43f55f209f42adaee135b2801d02709617fc88c2871852358260ace97cf323e761b5cc18bc7325b3	5ee73aec8a277856aa03cc22723f0f3f4eea3fe9264626a56b9280e0b477381e
m/12381/3600/35/0/0	a4ee6d37dc259cbb5237e4265429a9fd8ab5643af81628cc101e0d8b4a333ef2618a37df89ea3f92b5ea4333d8cda393	65299bf45233c1612373c11f4125d1466082f7b606fd6b8670304ad0f5417e4f
m/12381/3600/36/0/0	a759f6bcca8f35fcaadc406cc4b828c016c0ed23882987a79f52f2933b5cedefe24e31df6fd0d38e8a802dbafd750d01	639d180491e6f43c052c3b152377b384ff066ab5add3bce60325bcbe91af83e2
m/12381/3600/37/0/0	8d028a021c5c31a1aa1e18eda74cfaf0fba1c454c17c2e0fc730dd07a19d0c77f7a905d54017292f3e800ca06b6977cd	013ec1b0c454af972d3d91355a249e10c02452ff23347f8cbdcf6e138ffddad0
m/12381/3600/38/0/0	a2e2d8384fc87a512ee34eb43405fd82572c9d7cd96e155a382cda284e8df9eb7189c25b7473d89c63ea4e6080e10ff8	1c27df84e65e392554a8114f203cbc48b678fda6f6f00b7d8ca673e729f32cd7
m/12381/3600/39/0/0	81b676591b823270a3284ace7d81cbce2d6cdce55bb0e053874d7e3a08f729453009d3e662ec3130379f43c0f3210b6d	64fc5f1ae34cc39e9040eb82aca3ab48dc417103f1ec58de2465a61210ce1829
m/12381/3600/40/0/0	b5e898a1fc06d51c695712928f44646d15451340d1b3e480a40f03250160bc07d3b6691ec94361dd524d59d9df7f76d3	671acbcebab815b62bedbde19cead6ef5e461ee61614fecb2dbe57973f31c6f8
m/12381/3600/41/0/0	84dc37ca3cd621d3da0fbdd11ca84021e0cd81a73d772dd6fcf19775b72eb64af4e573213378ccee0915dde92ac83ba6	7351d0604a8c8e8c50abff8f1553e3e51df1e2f1b4efb19a50967208b792edf7
m/12381/3600/42/0/0	84d08d58c31bcd3cddf93e13d6f50203897384afa34644bff1135efe8e01c81c6a91ca6c234bb1e51ca32e41b828aaf9	4271a97a890b1787de0d71cff0c3997278a2d22a782c5aa121667f7bad6d7890
m/12381/3600/43/0/0	b2225575d5e70da1257db7a0d1222c5041b52aac61cf161e8fc8126a3fdf5eb4f0867d98dfe272199c36cf8f02661b3d	4fb86aefb885955648f1fda95e5b71984295f70969677fd01ccd9b96f58c5946
m/12381/3600/44/0/0	a8fa3584a92b079c8c73ed1553e5e161a0b21325fc2fc4e24a892354a899c7fc0bfb436a97a7ed1fc71bccda438ea715	25eb860618a76ad46b4882f6fc6ef95f47eaa43138bb94958d4181ae9dc72f8a
m/12381/3600/45/0/0	9918433b8f0bc5e126da3fdef8d7b71456492dae6d2d07f2e10c7a7f852046f84ed0ce6d3bfec42200670db27dcf3037	2ecaf6744ed1da2c0e71068680c378a0c2fa330631eed90105aa9f8adfaa1581
m/12381/3600/46/0/0	b24391aa97bfff29adc935d06a2b6d583433caf82f92de1980e0192d3b270323bdbf24b86dc61520a40c419dde3df4b3	44c6751f5a6dc614d840fe53ebd0b9e1014dd13fea75e87307a2d999271d034a
m/12381/3600/47/0/0	a62c0205fb22df8535c0b70076486e69dfa908feddae79e4a94a9d47b97ed190d228e1c6217e84a59882bb992dacae30	70bc8e191a00c33423b282ab04ed2bee1499e8c4fe9b942533832e5fe0d29d09
m/12381/3600/48/0/0	b63f327df68581cdc02a66c1c65e906a06a1a3a8d7a6e38f7b6da944e8e6cc2db85fced5327d8c12945ceb33018272ca	2167a9d2ca497a252e4982c7b9af0053967d327787f250770fe1eea4c3612b92
m/12381/3600/49/0/0	8aec5129a518010912215e1887191da94be419b4e75904c2ea745e2d253d707c088fa5b2c46dade1d162affe9f7ab17b	502daba547d289a1a69aa6b5b3453be8e0be0e3f05fb45753c868f7d8785fac8
m/12381/3600/50/0/0	8725b32751419f22a54485790f8187d1ba52d84a31ad45738a93777fcd1ccbec1652229923f82f37793ce0fc2763fb4c	21923a5596b251ece444052f64f824e6f65fda76d77777c6a1bb80c7900c3416
m/12381/3600/51/0/0	ab64f900c770e2b99de6b86b4390bbd1579bd48dccec55800adbcf52e006f22128e9971bbf3a92cc0105b0974849935a	2595d4027e0e692c433602b212114fd41f0d65bfc84cd72fc661dd5f74bf14ac
m/12381/3600/52/0/0	a0485d71f1f5e177f7d5bc9d98c5248a6a2d0de4554c2eaf02abae48f5a3e273b2ee7765784cf2a4cb7df84f617177c9	4bc7d7298849bb0e687e52cbd52e578aa276d6b7df71c8b4517d6d85fc0b8fb3
m/12381/3600/53/0/0	b09cb155daf2022afd18114a352e506a84065c80573cb0c7c310cbe92e2706cdcf91f74bbd9e464f74e3d831386d5033	1416992bba3c7f83c358dbc4b28e119e94e0f355a9a815e80c9ec7c9d7352fb5
m/12381/3600/54/0/0	99d83a0ba33161d8c6bbe80929fd9046d4dfdac43477ff85fea5bae925e6c179ad28eb338375ee2417acbd6576ee670a	0f8cba1cfdc29ea8f12ba30581d59f762e3caafbf8a5e90fd7e77db78a7aafa1
m/12381/3600/55/0/0	958c2692b86b4d20eaea3bb45e9447ebbc5b93ccaf8d21ef659d0cefedf5c4371b31b460ae40e8243682bde505abac1e	6021ad4a17385ce6d6c5c968419b57bd738e0d94013766868decbe264d89a546
m/12381/3600/56/0/0	8d8985e5dd341c9035b37bf7391c5944c28131b47c7d5359d18fca598010ba9a63e27c55e6b421a807038c320564db17	6f3be09081f61b1caad50fa10542b8d362f73f0bde54b8e4c0dcb2f114f2d8e5
m/12381/3600/57/0/0	af89ab00a0eab1131645292a9cfba583a69a1e3ac58b210e262494853e67385aeb50d4af428bdd577b9399daa96d8b20	464c18a1f816feaa067317c1f703d549020b7ccdba8e44ddec466dd6d2e74d3c
m/12381/3600/58/0/0	896a51e0b0de0f29029af38b796db1f1e6d0f9f9085ade40a313a60cb723fa3d58f6587175570086c4fbf0fe5331f1c8	664a3cfe5a033652734be0dab8f4955016297670a8dce8e01ddbed43661bab48
m/12381/3600/59/0/0	9763dde1b8028136a3ffd6dafd1f450e2cafb2819c7fa901f7c6e9cde8f2897ee7e9a45da6947fde1ad0d3836188eab5	0a7d6376dbc4e979b7e512d91392d7e5db086e7d7ef08e44951053783c6bf952
m/12381/3600/60/0/0	8fda66b8607af873f4c2c8218dd3ffc7940d411047eb199b5cd010156af4845d21dd2e65b0e44cfffb5e78271e9bb29d	15a1aefd115b951a56d69187af39289b7ba83b02db139aa00b346b54c6b57a34
m/12381/3600/61/0/0	86e014747c7922ccfc2b9d4bf6c1ecf0dc800197037858d0b85ab1944b4c3c14b95e0ed325bc42a6f467bc47ec27bc7b	6f60c024912a42f0cce65e3da61533d50a5a27e47843b9b987a767ff2f8ddcd8
m/12381/3600/62/0/0	8c0d15baa72bfcd317e9b9402ca9bb6e7ae1db35ffce7faccae0bd19b3c8e5de7d5524aef0377770b3a90626627a9304	298f0e21eeb8151e213c48cb2f6891217a6b04353367577d7a770add304635eb
m/12381/3600/63/0/0	af61f263addfb41c46d66e60ecfb598a5942f648f58718b6b4e4c92019fdb12328efbff98703134bcf28e9c1fab4bb60	4e68934eb46cc31a0d4f36a973b2d8d691c5b39331fa832c9e161df3f92c96a4
m/12381/3600/64/0/0	8de7ec501d574152f52a962bf588573df2fc3563fd0c6077651208ed20f24f3d8572425706b343117b48bdca56808416	6e41cbdecaa079687f9f079e7bb7e72bbeece904bbda93a9784f6589216b43da
m/12381/3600/65/0/0	b97ecbcfe8c52b9bcdca9e75da13c5650b751b037c570934ea6b6441ff32de6566c50dafc0557e63105b2ee7e8cbb39e	37ca160591713ba3f60b658983c552563129808cc8b077cc1bdadb1ba8c0a702
m/12381/3600/66/0/0	ac30aacd9e91cb0727c34ca6b40fbfd4d255b998471e25c443cf6cf777d6bb823a58e162958f32c3c5ca80453387a5d2	39f198045535d76ba4355b5d3e5f7b4c65433eba9b03ab06b6a3dada056fb787
m/12381/3600/67/0/0	b43ccb05317c2b666470ab251e987d6bf31f5ead6b5edac5fe007dd334ae6ce1a92e24c19e5ab387cd8fa253b63bb78c	11f69328a09f9457efdeb3efda8cb794496aac76d809b360f60f606f3df78e3b
m/12381/3600/68/0/0	966c488d807b3208bb1b10a1af422bac8d363c8015cda4e24d214549ced019cd3dd575545dd887461cae3f70d95cb061	5c668fd11c08f031e83769483242eeaf966b85ce327723c0ffda925e911d92eb
m/12381/3600/69/0/0	b3faeebfbebd085b9123ae0e09af9cd15d3b1db6a25f3e82d8b48b68e53522b41b342a3a3c8b008897df356048862d98	09c60193fc77c7847d28807e1d8494da9a4cf70858b12cf145ffe878747a4116
m/12381/3600/70/0/0	b8c6663371dc37bf083134dea26a20115ccc52b7c15a662bcfa33435e4ade14c6bc9714a5cdee492530accf8a327b2aa	6a9679157bf1e0fabff9994b5e57a7b356cf9e5b82809d2b500bf975b2760d94
m/12381/3600/71/0/0	a39731d5cb52838d02d4ff897ab908c0f76a9ef837f9288c634ed3091a1f69d5347dc65cd2c8009a5207a369a4c6bdae	569da263d0e17b649306109719c6478ff8624056f3a1a281b367c53064d16b06
m/12381/3600/72/0/0	b97dbe4add8aefd96c575ae9de19d1ac590bb7d92f23a9e4e113f7271c2243cf689e7645879efbb546d58ec44f5263d6	2d1325b9d35b6a4888e9e15f8865cead9bc4f9e3a28f39e557876497366fa793
m/12381/3600/73/0/0	95833097520df43a5cb013e97f80041a7a0b7d84a4ec79e2f16baeeb6edfbcf62ede97becfde73883831bb65e1415dc0	488789495440fdc333e03984e6e91e2e5d04fb96ed4f6d742b6ac363f9544a54
m/12381/3600/74/0/0	aee3fbc60f939c125877a4f4529517edcf114fdb83715f9f4041eccebb91323ce8c4784ff87815c38752517b3d2e2725	18feb2f9705fe4140545ffbb9043898ba969cf4c2d216ca4a56051cd68607606
m/12381/3600/75/0/0	92b68717b3b88b77716884d492966713d902eb35196cf71faf1fb5625327ddbdebae94786c77dde207b5666ffa6dff98	64bb40657b4bc16d396f8d7eb315d9a991d15d1c94aa43dc1b3b4cac8362f4da
m/12381/3600/76/0/0	91da49dbfb1a4a339ee8e1b902bf18302c3ca948da1dacfecfe9934d231013544dbd97689c2996f22b456f7e408a138c	1695d28c9703ef5d6ab453ce927346e53e73320be1971895cd5ab45f7cbf8376
m/12381/3600/77/0/0	93d491d7211af181ccab8353567ad10c065a6e991c9b70def7215c62fa3bf843a177e18b00580deead4b5678f46d4d39	26e04599f5bf9f34c8c2b615af71234e3f30cad9292c3bbd1406abfe9ea30fa6
m/12381/3600/78/0/0	8890da2859ccb2afd0742c1c791075104d7acc207b6fa478bb1f94fd6665ac75e5dff4d2cac0f81e4168448bc3a4c90d	4ee2379690b3a2fb0ed4a94e043d0adf1eb76c0b38d7a719745f683b38c402c0
m/12381/3600/79/0/0	b320e188ef282109ba8dc3d2573f9edc33831c1025a29844c86e7fc60a25627e507964725ec8dbeccfcbaa12e7fb5e1a	4998c922b40d095a087f4ef406fe6e5cf65fb5fb60bb0c1caeb9571b9c734ab3
m/12381/3600/80/0/0	a90dab71ad924fec01a579727736fd9a19a147bf57ef471255527b55a4702cfd54bb0300623c506823e723e7c30cf4dd	491c5f0eddd9502a483099da067b4a46f69c0b92621f9d5b0dd0b4ba2cf4e78e
m/12381/3600/81/0/0	95d7b5b39931578c673a6ffdcd5b3618ddf08b40909fd0ee04a74c70aae4e88c55a43d5b71cdf40c514195a7805019b3	23edc83686dd91af9b86692eec6786791ee79293795b0c6cf6623aef3632e307
m/12381/3600/82/0/0	978eb7a3aee4238207d1e78684a6769e3d71f1a3b9e42ac53c347c97e15eec3ac0082abf65ad9cfd126c687c51436cc1	12dd79f8bdd688f34d9e5b607bfc5060ad191c8ef526bf952901e60643f87564
m/12381/3600/83/0/0	98213294b82bc66ee39e95a678472fb41df846ec2863c5be53e1fd56b6ff0fe1bfd5b2bd8c534dd97acbe597ad119cc7	49aef0344f63592182d5f2b1543753623fd59bd68d788f40d96c44eee6389673

Restore SSZ encoding for publishing blocks

As of #10 (comment), we should try to restore the functionality of SSZ enconding for publishing blocks and check if it is compatible with the other relay changes made. It has been probably done by mistake in the first iterations of this PoC.

Switch to SSZ Merkle Multiproofs

In the process of defining Bolt specs we've decided to leverage SSZ Merkle Multiproofs (consensus specs here since they require less space and they're probably faster to compute as well, however the initial implementation consists of an array of single merkle proofs instead.

This shouldn't be too much work but it is a sensible part and requires changes over the whole stack: mev-boost, relay and builder.

Kurtosis devnet scenarios

Context

We want to showcase Bolt functionality in a couple of happy and not-so-happy scenarios. This issue will track the progress of each.

Scenarios

Create and host `forkdiff` pages for each forked PBS component

Overview

Forkdiff by Protolambda is a fantastic tool to visualize diffs between two git remotes, along with detailed explanations for each change.

We should host forkdiff views (maybe all on the same website, hosted as separate HTML pages?) for these components:

  • flashbots builder
  • flashbots mev-boost
  • flashbots mev-boost-relay

Finalize `constraint` schema

Context

The current constraint schema and API spec deviates a bit from what we originally had in mind in the following ways

  • The constraint_proofs field should be a part of message when submitting a block and forwarding a signed header. The signature should be over the whole message field.
  • Naming should be consistent over all components, i.e. constraint_proofs

Typing

We should also make the schema more future proof by supporting typed constraints and proofs. For inclusion proofs, this could look like:

{
    "type": 0, // type for inclusion proofs
    "data": {
        "generalized_indexes": [
            4,
            5
        ],
        "merkle_hashes": [
            "0x5097...",
            "0x932587..."
        ]
    }   
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.