Skip to main content

Constraints API: Builder

Overview

The Builder API is the way for proposers to communicate with builders in the PBS pipeline. The constraints-API adds the following new responsibilities:

  • Proposers should be able to submit constraints through the builder API
  • Proposers should be able to delegate constraint submission rights to another entity
  • Proposers should be able to get bids with proofs of constraint validity

Endpoints

constraints namespace

This namespace defines endpoints that should be called by either the validator, or an entity that the validator has delegated constraint submission rights to.

/constraints/v1/builder/constraints

Endpoint for submitting a batch of signed constraints.

  • Method: POST
  • Response: Empty
  • Headers:
    • Content-Type: application/json
  • Body: JSON object of type List[SignedConstraints, MAX_CONSTRAINTS_PER_SLOT]

Schema

# A signed "bundle" of constraints.
class SignedConstraints(Container):
message: ConstraintsMessage
signature: BLSSignature

# A "bundle" of constraints for a specific slot.
class ConstraintsMessage(Container):
validator_index: uint64,
slot: uint64
top: boolean,
transactions: List[Bytes, MAX_CONSTRAINTS_PER_SLOT]

Description

In the SignedConstraints object, the signature field represents the BLS signature on the SSZ hash tree root of the ConstraintsMessage object. The signature must come from either the validator signing key, or a delegated key (see below).

Explanation of other fields:

  • validator_index: the validatorIndex associated to the signing key. Used for checking the signature against.
  • slot: the target slot for which these constraints are valid.
  • top: boolean value indicating whether these constraints are only valid on the top of the block. Per slot, only 1 top-of-block bundle is valid.
  • transactions: the list of EIP-2718 RLP-encoded transactions. In case of a type 3 transaction, must contain the blob data.
Example body
// Example: 2 inclusion constraints where the transactions can be placed anywhere in the block

[
{
"message": {
"validatorIndex": 97,
"slot": 987432,
"top": false,
"transactions": [
"0x02f876018204db8405f5e100850218711a00825208949d22816f6611cfcb0cde5076c5f4e4a269e79bef8904563918244f40000080c080a0ee840d80915c9b506537909a5a6cf1ca2c5b47140d6585adab6ec0faf75fdcb7a07692785c5cb43c7cf02b800f",
]
},
"signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" // BLS validator signature
},
{
"message": {
"validatorIndex": 97,
"slot": 987432,
"top": false,
"constraints": [
"0x02f876018204dbd40c45bf2105dd18711a0082d208949da2816f6611bcab0cde5076c5f4e4a269e79bef8904563918244f40111180c080a0ee840d80915c9b506537909a5a6cf1ca2c5b47140d6585adab6ec0faf75fdcb7a07692785c5cb43c7cf02b800f"
]
},
"signature": "0x1b68ac14b663c9fc5b50984123ec9534bbd9cceda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" // BLS validator signature
}
]

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

[
{
"message": {
"validatorIndex": 97,
"slot": 987432,
"top": true,
"transactions": [
"0x02f876018204db8405f5e100850218711a00825208949d22816f6611cfcb0cde5076c5f4e4a269e79bef8904563918244f40000080c080a0ee840d80915c9b506537909a5a6cf1ca2c5b47140d6585adab6ec0faf75fdcb7a07692785c5cb43c7cf02b800f",
"0x02f876018204dbd405f5e12285f218711a0082d208949da2816f6611bcab0cde5076c5f4e4a269e79bef8904563918244f40111180c080a0ee840d80915c9b506537909a5a6cf1ca2c5b47140d6585adab6ec0faf75fdcb7a07692785c5cb43c7cf02b800f"
]
},
"signature": "0x1b68ac14b663c9fc5b50984123ec9534bbd9cceda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" // 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,
"top": false,
"constraints": [
"0x02f876018204db8405f5e100850218711a00825208949d22816f6611cfcb0cde5076c5f4e4a269e79bef8904563918244f40000080c080a0ee840d80915c9b506537909a5a6cf1ca2c5b47140d6585adab6ec0faf75fdcb7a07692785c5cb43c7cf02b800f",
"0x02f876018204dbd405f5e12285f218711a0082d208949da2816f6611bcab0cde5076c5f4e4a269e79bef8904563918244f40111180c080a0ee840d80915c9b506537909a5a6cf1ca2c5b47140d6585adab6ec0faf75fdcb7a07692785c5cb43c7cf02b800f"
]
},
"signature": "0x..." // BLS validator signature
}
]

/constraints/v1/builder/delegate

Endpoint for delegating constraint submission rights to another BLS key.

  • Method: POST
  • Response: Empty
  • Headers:
    • Content-Type: application/json
  • Body: JSON object of type SignedDelegation

Schema

# A signed delegation
class SignedDelegation(Container):
message: Delegation
signature: BLSSignature

# A delegation from a proposer to a BLS public key
class Delegation(Container):
validator_index: uint64,
pubkey: BLSPubkey

Description

The signature field is the BLS signature from the specified validator_index over the hash tree root of the Delegation object.

Example body
{
"message": {
"validatorIndex": 91,
"pukey": "0xa20322c78fb784ba5e0d9d67ccf71e96c7efa0ea49fda73d62e58f70aab2703b0edc3ea8547c655021858f98437ee790" # BLS public key of the delegatee
},
"signature": "0x1b68ac14b663c9fc5b50984123ec9534bbd9cceda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
}

/constraints/v1/builder/revoke

Endpoint for revoking constraint submission rights from another BLS key.

  • Method: POST
  • Response: Empty
  • Headers: Content-Type: application/json
  • Body: JSON object of type SignedRevocation

Schema

# A signed revocation
class SignedRevocation(Container):
message: Revocation,
signature: BLSSignature

# A revocation from a proposer for a BLS public key
class Revocation(Container):
validator_index: uint64,
pubkey: BLSPubkey

Description

The signature field is the BLS signature from the specified validator_index over the hash tree root of the Revocation object.

Example body
{
"message": {
"validatorIndex": 91,
"pukey": "0xa20322c78fb784ba5e0d9d67ccf71e96c7efa0ea49fda73d62e58f70aab2703b0edc3ea8547c655021858f98437ee790" # BLS public key of the delegatee to be revoked
},
"signature": "0x1b68ac14b663c9fc5b50984123ec9534bbd9cceda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
}

eth namespace

We also add an endpoint to the existing eth namespace for dealing with proofs when a proposer requests a bid with header from the builder.

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

Endpoint for requesting a builder bid with constraint proofs.

  • Method: GET
  • Response: VersionedSignedBuilderBidWithProofs
  • Parameters:
    • slot: string (regex [0-9]+)
    • parent_hash: string (regex 0x[a-fA-F0-9]+)
    • pubkey: string (regex 0x[a-fA-F0-9]+)
  • Body: Empty

Schema

class VersionedSignedBuilderBidWithProofs:
... # All regular fields from VersionedSignedBuilderBid, additionally
proofs: InclusionProofs

# An SSZ Merkle Multiproof for proving inclusion against the transactions_root
class InclusionProofs(Container):
transaction_hashes: List[Bytes32, MAX_CONSTRAINTS_PER_SLOT]
generalized_indeces: List[uint64, MAX_CONSTRAINTS_PER_SLOT]
merkle_hashes: List[List[Bytes32], MAX_CONSTRAINTS_PER_SLOT]

Description

VersionedSignedBuilderBid is from the original specs. VersionedSignedBuilderBidWithProofs just adds a field for proofs of inclusion. Note that InclusionProofs is a Merkle multiproof, as defined in the consensus specs.

Example response
{
"version": "deneb",
"data": {
"message": {
"bid": {
"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",
"blob_gas_used": "1",
"excess_blob_gas": "1",
"block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
"transactions_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
"withdrawals_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
},
"blob_kzg_commitments": [
"0xa94170080872584e54a1cf092d845703b13907f2e6b3b1c0ad573b910530499e3bcd48c6378846b80d2bfa58c81cf3d5"
],
"value": "1",
"pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a",
}
},
"proofs": {
"transaction_hashes": ["0x1234...", "0x456..."],
"generalized_indeces": [4, 5],
"merkle_hashes": ["0x5097...", "0x932587..."]
},
"signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
}
}