A service to monitor a set of relayers in the external builder network on Ethereum.
Work in progress. Not ready for use yet.
Go v1.19+
Requires a consensus client that implements the dev version of the standard beacon node APIs. This includes the standard set and the RANDAO endpoint.
Every other required information is given in the configuration, e.g. config.example.yaml
.
$ go run ./cmd/relay-monitor/main.go -config config.example.yaml
The monitor is structured as a series of components that ingest data and produce a live stream of fault data for each configured relay.
The collector
gathers data from either connected validators or relays it is configured to scan.
- validator registrations
- bids from relays
- auction transcript (bid + signed blinded beacon block) from connected proposers
- execution payload (conditional on auction transcript)
- signed beacon block (collected from a consensus client)
The analyzer
component derives faults from the collected data.
Each slot of the consensus protocol has a unique analysis which tries to derive any configured faults based on the observed data at a given time.
It is defined as set of rules (defined in Go for now) that should be re-evaluated when any dependent piece of data is collected.
The current fault count for each relay summarizing their behavior is maintained by the monitor and exposed via API.
Expose the registerValidator
endpoint from the builder-specs
APIs to accept SignedValidatorRegistrationsV1
from connected proposers.
See the definition from the builder specs for more information.
Accept complete transcripts from proposers to verify the proposer's leg of the auction was performed correctly.
This endpoint accepts the JSON encoding of the signed builder bid under a top-level key "bid"
and the signed blinded beacon block under a top-level key "acceptance"
. Encodings follow the JSON definition given in the builder-specs.
This endpoint returns HTTP 200 OK upon success and HTTP 4XX otherwise.
Example request:
{
"bid": {
"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",
"pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a"
},
"signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
}
},
"acceptance": {
"message": {
"slot": "1",
"proposer_index": "1",
"parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
"state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
"body": {
... fields omitted ...
"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"
}
}
},
"signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505"
}
}
Exposes a summary of faults per relay.
This response contains a map of relay public key to a mapping of observed fault counts. The response also contains the start and end epochs the observation window spans.
The types of faults and their meaning can be found here: https://hackmd.io/A2uex3QFSfiaJJ9BKxw-XA?view#behavior-faults
Query param: start
, an unsigned 64-bit integer indicating the lower bound for an epoch to provide fault data for
Query param: end
, an unsigned 64-bit integer indicating the upper bound for an epoch to provide fault data for.
Query param: window
, an unsigned 64-bit integer indicating the size of the window to provide fault data for
NOTE: if only start
(or end
) is provided then the response will only span the window
size amount of epochs after (or before) the given parameter. the window
parameter can optionally be specified as a query param or a default of 256
will be used if the query param is missing.
NOTE: if neither parameter is provided, the response will be 256
epochs behind from the current epoch, inclusive.
GET /monitor/v1/faults?start=100
{
"span": {
"start_epoch": "100",
"end_epoch": "356",
},
"data": {
"0x845bd072b7cd566f02faeb0a4033ce9399e42839ced64e8b2adcfc859ed1e8e1a5a293336a49feac6d9a5edb779be53a": {
"stats": {
"total_bids": 1153,
"malformed_bids": 0,
"consensus_invalid_bids": 1,
"payment_invalid_bids": 12,
"ignored_preferences_bids": 5,
"malformed_payloads": 0,
"consensus_invalid_payloads": 1,
"unavailable_payloads": 10
},
"meta": {
"endpoint": "builder-relay-sepolia.flashbots.net"
}
}
}
}