Constraints API: Builder
- Original API docs: https://ethereum.github.io/builder-specs
- Updated API docs: https://chainbound.github.io/builder-specs
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
: thevalidatorIndex
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
(regex0x[a-fA-F0-9]+
)pubkey
:string
(regex0x[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"
}
}