Skip to content

Commit 87052eb

Browse files
authored
implement getBlindedBlock REST API (#5829)
1 parent 45b4b46 commit 87052eb

10 files changed

+546
-5
lines changed

AllTests-mainnet.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ OK: 7/7 Fail: 0/7 Skip: 0/7
7474
+ basics OK
7575
```
7676
OK: 2/2 Fail: 0/2 Skip: 0/2
77+
## Blinded block conversions
78+
```diff
79+
+ Bellatrix toSignedBlindedBlock OK
80+
+ Capella toSignedBlindedBlock OK
81+
+ Deneb toSignedBlindedBlock OK
82+
```
83+
OK: 3/3 Fail: 0/3 Skip: 0/3
7784
## Block pool altair processing [Preset: mainnet]
7885
```diff
7986
+ Invalid signatures [Preset: mainnet] OK
@@ -979,4 +986,4 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
979986
OK: 9/9 Fail: 0/9 Skip: 0/9
980987

981988
---TOTAL---
982-
OK: 664/669 Fail: 0/669 Skip: 5/669
989+
OK: 667/672 Fail: 0/672 Skip: 5/672

beacon_chain/rpc/rest_beacon_api.nim

+43-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import
1414
../beacon_node,
1515
../consensus_object_pools/[blockchain_dag, spec_cache, validator_change_pool],
1616
../spec/[deposit_snapshots, eth2_merkleization, forks, network, validator],
17-
../spec/datatypes/[phase0, altair, deneb],
17+
../spec/mev/bellatrix_mev,
1818
../validators/message_router_mev
1919

2020
export rest_utils
@@ -1012,6 +1012,48 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
10121012

10131013
RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
10141014

1015+
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.4.2#/Beacon/getBlindedBlock
1016+
# https://github.com/ethereum/beacon-APIs/blob/v2.4.2/apis/beacon/blocks/blinded_block.yaml
1017+
router.api2(MethodGet, "/eth/v1/beacon/blinded_blocks/{block_id}") do (
1018+
block_id: BlockIdent) -> RestApiResponse:
1019+
let
1020+
blockIdent = block_id.valueOr:
1021+
return RestApiResponse.jsonError(Http400, InvalidBlockIdValueError,
1022+
$error)
1023+
bid = node.getBlockId(blockIdent).valueOr:
1024+
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
1025+
contentType =
1026+
block:
1027+
let res = preferredContentType(jsonMediaType,
1028+
sszMediaType)
1029+
if res.isErr():
1030+
return RestApiResponse.jsonError(Http406, ContentNotAcceptableError)
1031+
res.get()
1032+
bdata = node.dag.getForkedBlock(bid).valueOr:
1033+
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
1034+
1035+
template respondSszOrJson(
1036+
signedMaybeBlindedBlck: auto, consensusFork: ConsensusFork): untyped =
1037+
if contentType == sszMediaType:
1038+
RestApiResponse.sszResponse(
1039+
signedMaybeBlindedBlck,
1040+
[("eth-consensus-version", consensusFork.toString())])
1041+
elif contentType == jsonMediaType:
1042+
RestApiResponse.jsonResponseBlock(
1043+
signedMaybeBlindedBlck,
1044+
consensusFork,
1045+
node.getBlockOptimistic(bdata),
1046+
node.dag.isFinalized(bid)
1047+
)
1048+
else:
1049+
RestApiResponse.jsonError(Http500, InvalidAcceptError)
1050+
1051+
withBlck(bdata.asSigned()):
1052+
when consensusFork <= ConsensusFork.Altair:
1053+
respondSszOrJson(forkyBlck, consensusFork)
1054+
else:
1055+
respondSszOrJson(toSignedBlindedBeaconBlock(forkyBlck), consensusFork)
1056+
10151057
# https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlindedBlock
10161058
# https://github.com/ethereum/beacon-APIs/blob/v2.4.0/apis/beacon/blocks/blinded_blocks.yaml
10171059
router.api(MethodPost, "/eth/v1/beacon/blinded_blocks") do (

beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim

+28
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ RestJson.useDefaultSerializationFor(
204204
bellatrix.ExecutionPayload,
205205
bellatrix.ExecutionPayloadHeader,
206206
bellatrix.SignedBeaconBlock,
207+
bellatrix_mev.BlindedBeaconBlockBody,
207208
bellatrix_mev.BlindedBeaconBlock,
208209
bellatrix_mev.SignedBlindedBeaconBlock,
209210
capella.BeaconBlock,
@@ -561,6 +562,33 @@ proc jsonResponse*(t: typedesc[RestApiResponse], data: auto): RestApiResponse =
561562
default
562563
RestApiResponse.response(res, Http200, "application/json")
563564

565+
proc jsonResponseBlock*(t: typedesc[RestApiResponse],
566+
data: ForkySignedBlindedBeaconBlock,
567+
consensusFork: ConsensusFork,
568+
execOpt: Opt[bool],
569+
finalized: bool): RestApiResponse =
570+
let
571+
headers = [("eth-consensus-version", consensusFork.toString())]
572+
res =
573+
block:
574+
var default: seq[byte]
575+
try:
576+
var stream = memoryOutput()
577+
var writer = JsonWriter[RestJson].init(stream)
578+
writer.beginRecord()
579+
writer.writeField("version", consensusFork.toString())
580+
if execOpt.isSome():
581+
writer.writeField("execution_optimistic", execOpt.get())
582+
writer.writeField("finalized", finalized)
583+
writer.writeField("data", data)
584+
writer.endRecord()
585+
stream.getOutput(seq[byte])
586+
except SerializationError:
587+
default
588+
except IOError:
589+
default
590+
RestApiResponse.response(res, Http200, "application/json", headers = headers)
591+
564592
proc jsonResponseBlock*(t: typedesc[RestApiResponse],
565593
data: ForkedSignedBeaconBlock,
566594
execOpt: Opt[bool],

beacon_chain/spec/forks.nim

+5-2
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,9 @@ type
202202
ForkySignedBlindedBeaconBlock* =
203203
phase0.SignedBeaconBlock |
204204
altair.SignedBeaconBlock |
205-
capella_mev.SignedBlindedBeaconBlock
205+
bellatrix_mev.SignedBlindedBeaconBlock |
206+
capella_mev.SignedBlindedBeaconBlock |
207+
deneb_mev.SignedBlindedBeaconBlock
206208

207209
ForkedSignedBlindedBeaconBlock* = object
208210
case kind*: ConsensusFork
@@ -318,7 +320,8 @@ template kind*(
318320
bellatrix.TrustedBeaconBlockBody |
319321
bellatrix.SigVerifiedSignedBeaconBlock |
320322
bellatrix.MsgTrustedSignedBeaconBlock |
321-
bellatrix.TrustedSignedBeaconBlock]): ConsensusFork =
323+
bellatrix.TrustedSignedBeaconBlock] |
324+
bellatrix_mev.SignedBlindedBeaconBlock): ConsensusFork =
322325
ConsensusFork.Bellatrix
323326

324327
template kind*(

beacon_chain/spec/mev/bellatrix_mev.nim

+63-1
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,36 @@
77

88
{.push raises: [].}
99

10-
from ../datatypes/base import Eth1Data
10+
import ".."/datatypes/altair
11+
from ".."/datatypes/bellatrix import ExecutionPayloadHeader
12+
from ".."/eth2_merkleization import hash_tree_root
1113

1214
type
15+
# https://github.com/ethereum/builder-specs/blob/v0.4.0/specs/bellatrix/builder.md#blindedbeaconblockbody
16+
BlindedBeaconBlockBody* = object
17+
randao_reveal*: ValidatorSig
18+
eth1_data*: Eth1Data
19+
graffiti*: GraffitiBytes
20+
proposer_slashings*: List[ProposerSlashing, Limit MAX_PROPOSER_SLASHINGS]
21+
attester_slashings*: List[AttesterSlashing, Limit MAX_ATTESTER_SLASHINGS]
22+
attestations*: List[Attestation, Limit MAX_ATTESTATIONS]
23+
deposits*: List[Deposit, Limit MAX_DEPOSITS]
24+
voluntary_exits*: List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS]
25+
sync_aggregate*: SyncAggregate
26+
execution_payload_header*: bellatrix.ExecutionPayloadHeader
27+
28+
# https://github.com/ethereum/builder-specs/blob/v0.4.0/specs/bellatrix/builder.md#blindedbeaconblock
1329
BlindedBeaconBlock* = object
30+
slot*: Slot
31+
proposer_index*: uint64
32+
parent_root*: Eth2Digest
33+
state_root*: Eth2Digest
34+
body*: BlindedBeaconBlockBody
35+
36+
# https://github.com/ethereum/builder-specs/blob/v0.4.0/specs/bellatrix/builder.md#signedblindedbeaconblock
1437
SignedBlindedBeaconBlock* = object
38+
message*: BlindedBeaconBlock
39+
signature*: ValidatorSig
1540

1641
func shortLog*(v: BlindedBeaconBlock): auto =
1742
(
@@ -40,3 +65,40 @@ func shortLog*(v: SignedBlindedBeaconBlock): auto =
4065
blck: shortLog(default(BlindedBeaconBlock)),
4166
signature: ""
4267
)
68+
69+
func toSignedBlindedBeaconBlock*(blck: bellatrix.SignedBeaconBlock):
70+
SignedBlindedBeaconBlock =
71+
SignedBlindedBeaconBlock(
72+
message: BlindedBeaconBlock(
73+
slot: blck.message.slot,
74+
proposer_index: blck.message.proposer_index,
75+
parent_root: blck.message.parent_root,
76+
state_root: blck.message.state_root,
77+
body: BlindedBeaconBlockBody(
78+
randao_reveal: blck.message.body.randao_reveal,
79+
eth1_data: blck.message.body.eth1_data,
80+
graffiti: blck.message.body.graffiti,
81+
proposer_slashings: blck.message.body.proposer_slashings,
82+
attester_slashings: blck.message.body.attester_slashings,
83+
attestations: blck.message.body.attestations,
84+
deposits: blck.message.body.deposits,
85+
voluntary_exits: blck.message.body.voluntary_exits,
86+
sync_aggregate: blck.message.body.sync_aggregate,
87+
execution_payload_header: ExecutionPayloadHeader(
88+
parent_hash: blck.message.body.execution_payload.parent_hash,
89+
fee_recipient: blck.message.body.execution_payload.fee_recipient,
90+
state_root: blck.message.body.execution_payload.state_root,
91+
receipts_root: blck.message.body.execution_payload.receipts_root,
92+
logs_bloom: blck.message.body.execution_payload.logs_bloom,
93+
prev_randao: blck.message.body.execution_payload.prev_randao,
94+
block_number: blck.message.body.execution_payload.block_number,
95+
gas_limit: blck.message.body.execution_payload.gas_limit,
96+
gas_used: blck.message.body.execution_payload.gas_used,
97+
timestamp: blck.message.body.execution_payload.timestamp,
98+
extra_data: blck.message.body.execution_payload.extra_data,
99+
base_fee_per_gas:
100+
blck.message.body.execution_payload.base_fee_per_gas,
101+
block_hash: blck.message.body.execution_payload.block_hash,
102+
transactions_root:
103+
hash_tree_root(blck.message.body.execution_payload.transactions)))),
104+
signature: blck.signature)

beacon_chain/spec/mev/capella_mev.nim

+41
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import ".."/datatypes/[altair, capella]
1111
from stew/byteutils import to0xHex
1212

1313
from ../datatypes/bellatrix import ExecutionAddress
14+
from ../eth2_merkleization import hash_tree_root
1415

1516
type
1617
# https://github.com/ethereum/builder-specs/blob/v0.4.0/specs/bellatrix/builder.md#validatorregistrationv1
@@ -116,3 +117,43 @@ func shortLog*(v: SignedBlindedBeaconBlock): auto =
116117
blck: shortLog(v.message),
117118
signature: shortLog(v.signature)
118119
)
120+
121+
func toSignedBlindedBeaconBlock*(blck: capella.SignedBeaconBlock):
122+
SignedBlindedBeaconBlock =
123+
SignedBlindedBeaconBlock(
124+
message: BlindedBeaconBlock(
125+
slot: blck.message.slot,
126+
proposer_index: blck.message.proposer_index,
127+
parent_root: blck.message.parent_root,
128+
state_root: blck.message.state_root,
129+
body: BlindedBeaconBlockBody(
130+
randao_reveal: blck.message.body.randao_reveal,
131+
eth1_data: blck.message.body.eth1_data,
132+
graffiti: blck.message.body.graffiti,
133+
proposer_slashings: blck.message.body.proposer_slashings,
134+
attester_slashings: blck.message.body.attester_slashings,
135+
attestations: blck.message.body.attestations,
136+
deposits: blck.message.body.deposits,
137+
voluntary_exits: blck.message.body.voluntary_exits,
138+
sync_aggregate: blck.message.body.sync_aggregate,
139+
execution_payload_header: ExecutionPayloadHeader(
140+
parent_hash: blck.message.body.execution_payload.parent_hash,
141+
fee_recipient: blck.message.body.execution_payload.fee_recipient,
142+
state_root: blck.message.body.execution_payload.state_root,
143+
receipts_root: blck.message.body.execution_payload.receipts_root,
144+
logs_bloom: blck.message.body.execution_payload.logs_bloom,
145+
prev_randao: blck.message.body.execution_payload.prev_randao,
146+
block_number: blck.message.body.execution_payload.block_number,
147+
gas_limit: blck.message.body.execution_payload.gas_limit,
148+
gas_used: blck.message.body.execution_payload.gas_used,
149+
timestamp: blck.message.body.execution_payload.timestamp,
150+
extra_data: blck.message.body.execution_payload.extra_data,
151+
base_fee_per_gas:
152+
blck.message.body.execution_payload.base_fee_per_gas,
153+
block_hash: blck.message.body.execution_payload.block_hash,
154+
transactions_root:
155+
hash_tree_root(blck.message.body.execution_payload.transactions),
156+
withdrawals_root:
157+
hash_tree_root(blck.message.body.execution_payload.withdrawals)),
158+
bls_to_execution_changes: blck.message.body.bls_to_execution_changes)),
159+
signature: blck.signature)

beacon_chain/spec/mev/deneb_mev.nim

+42
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import ".."/datatypes/[altair, deneb]
1111

1212
from stew/byteutils import to0xHex
1313
from ".."/datatypes/capella import SignedBLSToExecutionChange
14+
from ".."/eth2_merkleization import hash_tree_root
1415

1516
type
1617
# https://github.com/ethereum/builder-specs/blob/v0.4.0/specs/deneb/builder.md#builderbid
@@ -103,3 +104,44 @@ func shortLog*(v: SignedBlindedBeaconBlock): auto =
103104
blck: shortLog(v.message),
104105
signature: shortLog(v.signature)
105106
)
107+
108+
func toSignedBlindedBeaconBlock*(blck: deneb.SignedBeaconBlock):
109+
SignedBlindedBeaconBlock =
110+
SignedBlindedBeaconBlock(
111+
message: BlindedBeaconBlock(
112+
slot: blck.message.slot,
113+
proposer_index: blck.message.proposer_index,
114+
parent_root: blck.message.parent_root,
115+
state_root: blck.message.state_root,
116+
body: BlindedBeaconBlockBody(
117+
randao_reveal: blck.message.body.randao_reveal,
118+
eth1_data: blck.message.body.eth1_data,
119+
graffiti: blck.message.body.graffiti,
120+
proposer_slashings: blck.message.body.proposer_slashings,
121+
attester_slashings: blck.message.body.attester_slashings,
122+
attestations: blck.message.body.attestations,
123+
deposits: blck.message.body.deposits,
124+
voluntary_exits: blck.message.body.voluntary_exits,
125+
sync_aggregate: blck.message.body.sync_aggregate,
126+
execution_payload_header: ExecutionPayloadHeader(
127+
parent_hash: blck.message.body.execution_payload.parent_hash,
128+
fee_recipient: blck.message.body.execution_payload.fee_recipient,
129+
state_root: blck.message.body.execution_payload.state_root,
130+
receipts_root: blck.message.body.execution_payload.receipts_root,
131+
logs_bloom: blck.message.body.execution_payload.logs_bloom,
132+
prev_randao: blck.message.body.execution_payload.prev_randao,
133+
block_number: blck.message.body.execution_payload.block_number,
134+
gas_limit: blck.message.body.execution_payload.gas_limit,
135+
gas_used: blck.message.body.execution_payload.gas_used,
136+
timestamp: blck.message.body.execution_payload.timestamp,
137+
extra_data: blck.message.body.execution_payload.extra_data,
138+
base_fee_per_gas:
139+
blck.message.body.execution_payload.base_fee_per_gas,
140+
block_hash: blck.message.body.execution_payload.block_hash,
141+
transactions_root:
142+
hash_tree_root(blck.message.body.execution_payload.transactions),
143+
withdrawals_root:
144+
hash_tree_root(blck.message.body.execution_payload.withdrawals)),
145+
bls_to_execution_changes: blck.message.body.bls_to_execution_changes,
146+
blob_kzg_commitments: blck.message.body.blob_kzg_commitments)),
147+
signature: blck.signature)

0 commit comments

Comments
 (0)