Skip to content

Commit

Permalink
implement getBlindedBlock REST API (#5829)
Browse files Browse the repository at this point in the history
  • Loading branch information
tersec authored Jan 31, 2024
1 parent 45b4b46 commit 87052eb
Show file tree
Hide file tree
Showing 10 changed files with 546 additions and 5 deletions.
9 changes: 8 additions & 1 deletion AllTests-mainnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ OK: 7/7 Fail: 0/7 Skip: 0/7
+ basics OK
```
OK: 2/2 Fail: 0/2 Skip: 0/2
## Blinded block conversions
```diff
+ Bellatrix toSignedBlindedBlock OK
+ Capella toSignedBlindedBlock OK
+ Deneb toSignedBlindedBlock OK
```
OK: 3/3 Fail: 0/3 Skip: 0/3
## Block pool altair processing [Preset: mainnet]
```diff
+ Invalid signatures [Preset: mainnet] OK
Expand Down Expand Up @@ -979,4 +986,4 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
OK: 9/9 Fail: 0/9 Skip: 0/9

---TOTAL---
OK: 664/669 Fail: 0/669 Skip: 5/669
OK: 667/672 Fail: 0/672 Skip: 5/672
44 changes: 43 additions & 1 deletion beacon_chain/rpc/rest_beacon_api.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import
../beacon_node,
../consensus_object_pools/[blockchain_dag, spec_cache, validator_change_pool],
../spec/[deposit_snapshots, eth2_merkleization, forks, network, validator],
../spec/datatypes/[phase0, altair, deneb],
../spec/mev/bellatrix_mev,
../validators/message_router_mev

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

RestApiResponse.jsonMsgResponse(BlockValidationSuccess)

# https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.4.2#/Beacon/getBlindedBlock
# https://github.com/ethereum/beacon-APIs/blob/v2.4.2/apis/beacon/blocks/blinded_block.yaml
router.api2(MethodGet, "/eth/v1/beacon/blinded_blocks/{block_id}") do (
block_id: BlockIdent) -> RestApiResponse:
let
blockIdent = block_id.valueOr:
return RestApiResponse.jsonError(Http400, InvalidBlockIdValueError,
$error)
bid = node.getBlockId(blockIdent).valueOr:
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
contentType =
block:
let res = preferredContentType(jsonMediaType,
sszMediaType)
if res.isErr():
return RestApiResponse.jsonError(Http406, ContentNotAcceptableError)
res.get()
bdata = node.dag.getForkedBlock(bid).valueOr:
return RestApiResponse.jsonError(Http404, BlockNotFoundError)

template respondSszOrJson(
signedMaybeBlindedBlck: auto, consensusFork: ConsensusFork): untyped =
if contentType == sszMediaType:
RestApiResponse.sszResponse(
signedMaybeBlindedBlck,
[("eth-consensus-version", consensusFork.toString())])
elif contentType == jsonMediaType:
RestApiResponse.jsonResponseBlock(
signedMaybeBlindedBlck,
consensusFork,
node.getBlockOptimistic(bdata),
node.dag.isFinalized(bid)
)
else:
RestApiResponse.jsonError(Http500, InvalidAcceptError)

withBlck(bdata.asSigned()):
when consensusFork <= ConsensusFork.Altair:
respondSszOrJson(forkyBlck, consensusFork)
else:
respondSszOrJson(toSignedBlindedBeaconBlock(forkyBlck), consensusFork)

# https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlindedBlock
# https://github.com/ethereum/beacon-APIs/blob/v2.4.0/apis/beacon/blocks/blinded_blocks.yaml
router.api(MethodPost, "/eth/v1/beacon/blinded_blocks") do (
Expand Down
28 changes: 28 additions & 0 deletions beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ RestJson.useDefaultSerializationFor(
bellatrix.ExecutionPayload,
bellatrix.ExecutionPayloadHeader,
bellatrix.SignedBeaconBlock,
bellatrix_mev.BlindedBeaconBlockBody,
bellatrix_mev.BlindedBeaconBlock,
bellatrix_mev.SignedBlindedBeaconBlock,
capella.BeaconBlock,
Expand Down Expand Up @@ -561,6 +562,33 @@ proc jsonResponse*(t: typedesc[RestApiResponse], data: auto): RestApiResponse =
default
RestApiResponse.response(res, Http200, "application/json")

proc jsonResponseBlock*(t: typedesc[RestApiResponse],
data: ForkySignedBlindedBeaconBlock,
consensusFork: ConsensusFork,
execOpt: Opt[bool],
finalized: bool): RestApiResponse =
let
headers = [("eth-consensus-version", consensusFork.toString())]
res =
block:
var default: seq[byte]
try:
var stream = memoryOutput()
var writer = JsonWriter[RestJson].init(stream)
writer.beginRecord()
writer.writeField("version", consensusFork.toString())
if execOpt.isSome():
writer.writeField("execution_optimistic", execOpt.get())
writer.writeField("finalized", finalized)
writer.writeField("data", data)
writer.endRecord()
stream.getOutput(seq[byte])
except SerializationError:
default
except IOError:
default
RestApiResponse.response(res, Http200, "application/json", headers = headers)

proc jsonResponseBlock*(t: typedesc[RestApiResponse],
data: ForkedSignedBeaconBlock,
execOpt: Opt[bool],
Expand Down
7 changes: 5 additions & 2 deletions beacon_chain/spec/forks.nim
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,9 @@ type
ForkySignedBlindedBeaconBlock* =
phase0.SignedBeaconBlock |
altair.SignedBeaconBlock |
capella_mev.SignedBlindedBeaconBlock
bellatrix_mev.SignedBlindedBeaconBlock |
capella_mev.SignedBlindedBeaconBlock |
deneb_mev.SignedBlindedBeaconBlock

ForkedSignedBlindedBeaconBlock* = object
case kind*: ConsensusFork
Expand Down Expand Up @@ -318,7 +320,8 @@ template kind*(
bellatrix.TrustedBeaconBlockBody |
bellatrix.SigVerifiedSignedBeaconBlock |
bellatrix.MsgTrustedSignedBeaconBlock |
bellatrix.TrustedSignedBeaconBlock]): ConsensusFork =
bellatrix.TrustedSignedBeaconBlock] |
bellatrix_mev.SignedBlindedBeaconBlock): ConsensusFork =
ConsensusFork.Bellatrix

template kind*(
Expand Down
64 changes: 63 additions & 1 deletion beacon_chain/spec/mev/bellatrix_mev.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,36 @@

{.push raises: [].}

from ../datatypes/base import Eth1Data
import ".."/datatypes/altair
from ".."/datatypes/bellatrix import ExecutionPayloadHeader
from ".."/eth2_merkleization import hash_tree_root

type
# https://github.com/ethereum/builder-specs/blob/v0.4.0/specs/bellatrix/builder.md#blindedbeaconblockbody
BlindedBeaconBlockBody* = object
randao_reveal*: ValidatorSig
eth1_data*: Eth1Data
graffiti*: GraffitiBytes
proposer_slashings*: List[ProposerSlashing, Limit MAX_PROPOSER_SLASHINGS]
attester_slashings*: List[AttesterSlashing, Limit MAX_ATTESTER_SLASHINGS]
attestations*: List[Attestation, Limit MAX_ATTESTATIONS]
deposits*: List[Deposit, Limit MAX_DEPOSITS]
voluntary_exits*: List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS]
sync_aggregate*: SyncAggregate
execution_payload_header*: bellatrix.ExecutionPayloadHeader

# https://github.com/ethereum/builder-specs/blob/v0.4.0/specs/bellatrix/builder.md#blindedbeaconblock
BlindedBeaconBlock* = object
slot*: Slot
proposer_index*: uint64
parent_root*: Eth2Digest
state_root*: Eth2Digest
body*: BlindedBeaconBlockBody

# https://github.com/ethereum/builder-specs/blob/v0.4.0/specs/bellatrix/builder.md#signedblindedbeaconblock
SignedBlindedBeaconBlock* = object
message*: BlindedBeaconBlock
signature*: ValidatorSig

func shortLog*(v: BlindedBeaconBlock): auto =
(
Expand Down Expand Up @@ -40,3 +65,40 @@ func shortLog*(v: SignedBlindedBeaconBlock): auto =
blck: shortLog(default(BlindedBeaconBlock)),
signature: ""
)

func toSignedBlindedBeaconBlock*(blck: bellatrix.SignedBeaconBlock):
SignedBlindedBeaconBlock =
SignedBlindedBeaconBlock(
message: BlindedBeaconBlock(
slot: blck.message.slot,
proposer_index: blck.message.proposer_index,
parent_root: blck.message.parent_root,
state_root: blck.message.state_root,
body: BlindedBeaconBlockBody(
randao_reveal: blck.message.body.randao_reveal,
eth1_data: blck.message.body.eth1_data,
graffiti: blck.message.body.graffiti,
proposer_slashings: blck.message.body.proposer_slashings,
attester_slashings: blck.message.body.attester_slashings,
attestations: blck.message.body.attestations,
deposits: blck.message.body.deposits,
voluntary_exits: blck.message.body.voluntary_exits,
sync_aggregate: blck.message.body.sync_aggregate,
execution_payload_header: ExecutionPayloadHeader(
parent_hash: blck.message.body.execution_payload.parent_hash,
fee_recipient: blck.message.body.execution_payload.fee_recipient,
state_root: blck.message.body.execution_payload.state_root,
receipts_root: blck.message.body.execution_payload.receipts_root,
logs_bloom: blck.message.body.execution_payload.logs_bloom,
prev_randao: blck.message.body.execution_payload.prev_randao,
block_number: blck.message.body.execution_payload.block_number,
gas_limit: blck.message.body.execution_payload.gas_limit,
gas_used: blck.message.body.execution_payload.gas_used,
timestamp: blck.message.body.execution_payload.timestamp,
extra_data: blck.message.body.execution_payload.extra_data,
base_fee_per_gas:
blck.message.body.execution_payload.base_fee_per_gas,
block_hash: blck.message.body.execution_payload.block_hash,
transactions_root:
hash_tree_root(blck.message.body.execution_payload.transactions)))),
signature: blck.signature)
41 changes: 41 additions & 0 deletions beacon_chain/spec/mev/capella_mev.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ".."/datatypes/[altair, capella]
from stew/byteutils import to0xHex

from ../datatypes/bellatrix import ExecutionAddress
from ../eth2_merkleization import hash_tree_root

type
# https://github.com/ethereum/builder-specs/blob/v0.4.0/specs/bellatrix/builder.md#validatorregistrationv1
Expand Down Expand Up @@ -116,3 +117,43 @@ func shortLog*(v: SignedBlindedBeaconBlock): auto =
blck: shortLog(v.message),
signature: shortLog(v.signature)
)

func toSignedBlindedBeaconBlock*(blck: capella.SignedBeaconBlock):
SignedBlindedBeaconBlock =
SignedBlindedBeaconBlock(
message: BlindedBeaconBlock(
slot: blck.message.slot,
proposer_index: blck.message.proposer_index,
parent_root: blck.message.parent_root,
state_root: blck.message.state_root,
body: BlindedBeaconBlockBody(
randao_reveal: blck.message.body.randao_reveal,
eth1_data: blck.message.body.eth1_data,
graffiti: blck.message.body.graffiti,
proposer_slashings: blck.message.body.proposer_slashings,
attester_slashings: blck.message.body.attester_slashings,
attestations: blck.message.body.attestations,
deposits: blck.message.body.deposits,
voluntary_exits: blck.message.body.voluntary_exits,
sync_aggregate: blck.message.body.sync_aggregate,
execution_payload_header: ExecutionPayloadHeader(
parent_hash: blck.message.body.execution_payload.parent_hash,
fee_recipient: blck.message.body.execution_payload.fee_recipient,
state_root: blck.message.body.execution_payload.state_root,
receipts_root: blck.message.body.execution_payload.receipts_root,
logs_bloom: blck.message.body.execution_payload.logs_bloom,
prev_randao: blck.message.body.execution_payload.prev_randao,
block_number: blck.message.body.execution_payload.block_number,
gas_limit: blck.message.body.execution_payload.gas_limit,
gas_used: blck.message.body.execution_payload.gas_used,
timestamp: blck.message.body.execution_payload.timestamp,
extra_data: blck.message.body.execution_payload.extra_data,
base_fee_per_gas:
blck.message.body.execution_payload.base_fee_per_gas,
block_hash: blck.message.body.execution_payload.block_hash,
transactions_root:
hash_tree_root(blck.message.body.execution_payload.transactions),
withdrawals_root:
hash_tree_root(blck.message.body.execution_payload.withdrawals)),
bls_to_execution_changes: blck.message.body.bls_to_execution_changes)),
signature: blck.signature)
42 changes: 42 additions & 0 deletions beacon_chain/spec/mev/deneb_mev.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ".."/datatypes/[altair, deneb]

from stew/byteutils import to0xHex
from ".."/datatypes/capella import SignedBLSToExecutionChange
from ".."/eth2_merkleization import hash_tree_root

type
# https://github.com/ethereum/builder-specs/blob/v0.4.0/specs/deneb/builder.md#builderbid
Expand Down Expand Up @@ -103,3 +104,44 @@ func shortLog*(v: SignedBlindedBeaconBlock): auto =
blck: shortLog(v.message),
signature: shortLog(v.signature)
)

func toSignedBlindedBeaconBlock*(blck: deneb.SignedBeaconBlock):
SignedBlindedBeaconBlock =
SignedBlindedBeaconBlock(
message: BlindedBeaconBlock(
slot: blck.message.slot,
proposer_index: blck.message.proposer_index,
parent_root: blck.message.parent_root,
state_root: blck.message.state_root,
body: BlindedBeaconBlockBody(
randao_reveal: blck.message.body.randao_reveal,
eth1_data: blck.message.body.eth1_data,
graffiti: blck.message.body.graffiti,
proposer_slashings: blck.message.body.proposer_slashings,
attester_slashings: blck.message.body.attester_slashings,
attestations: blck.message.body.attestations,
deposits: blck.message.body.deposits,
voluntary_exits: blck.message.body.voluntary_exits,
sync_aggregate: blck.message.body.sync_aggregate,
execution_payload_header: ExecutionPayloadHeader(
parent_hash: blck.message.body.execution_payload.parent_hash,
fee_recipient: blck.message.body.execution_payload.fee_recipient,
state_root: blck.message.body.execution_payload.state_root,
receipts_root: blck.message.body.execution_payload.receipts_root,
logs_bloom: blck.message.body.execution_payload.logs_bloom,
prev_randao: blck.message.body.execution_payload.prev_randao,
block_number: blck.message.body.execution_payload.block_number,
gas_limit: blck.message.body.execution_payload.gas_limit,
gas_used: blck.message.body.execution_payload.gas_used,
timestamp: blck.message.body.execution_payload.timestamp,
extra_data: blck.message.body.execution_payload.extra_data,
base_fee_per_gas:
blck.message.body.execution_payload.base_fee_per_gas,
block_hash: blck.message.body.execution_payload.block_hash,
transactions_root:
hash_tree_root(blck.message.body.execution_payload.transactions),
withdrawals_root:
hash_tree_root(blck.message.body.execution_payload.withdrawals)),
bls_to_execution_changes: blck.message.body.bls_to_execution_changes,
blob_kzg_commitments: blck.message.body.blob_kzg_commitments)),
signature: blck.signature)
Loading

0 comments on commit 87052eb

Please sign in to comment.