Add Deneb beacon API types (#5060)

* Add Deneb beacon API types

- Introduce the `ProduceBlockResponseV2` type for handling responses to `GET /eth/v2/validator/blocks/{slot}` (https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Validator/produceBlockV2)

- Introduce the `RestPublishedSignedBlockContents` type for handling the request body to `POST /eth/v1/beacon/blocks` (https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/ValidatorRequiredApi/publishBlock)

And a few other small changes towards Deneb block production support.

* Address review feedback

* Post-rebase fixes
This commit is contained in:
henridf 2023-06-19 10:56:52 +02:00 committed by GitHub
parent 4da9517f25
commit 0f8866d672
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 394 additions and 29 deletions

View File

@ -89,9 +89,6 @@ const
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/shanghai.md#request-2
GETPAYLOAD_TIMEOUT = 1.seconds
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/experimental/blob-extension.md#request-2
GETBLOBS_TIMEOUT = 1.seconds
connectionStateChangeHysteresisThreshold = 15
## How many unsuccesful/successful requests we must see
## before declaring the connection as degraded/restored
@ -909,12 +906,7 @@ proc getPayload*(m: ELManager,
randomData, suggestedFeeRecipient, engineApiWithdrawals)
let
timeout = when PayloadType is deneb.ExecutionPayloadForSigning:
# TODO We should follow the spec and track the timeouts of
# the individual engine API calls inside `getPayloadFromSingleEL`.
GETPAYLOAD_TIMEOUT + GETBLOBS_TIMEOUT
else:
GETPAYLOAD_TIMEOUT
timeout = GETPAYLOAD_TIMEOUT
deadline = sleepAsync(timeout)
requests = m.elConnections.mapIt(it.getPayloadFromSingleEL(
EngineApiResponseType(PayloadType),

View File

@ -837,13 +837,13 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
body = contentBody.get()
version = request.headers.getString("eth-consensus-version")
var
restBlock = decodeBody(RestPublishedSignedBeaconBlock, body,
restBlock = decodeBody(RestPublishedSignedBlockContents, body,
version).valueOr:
return RestApiResponse.jsonError(Http400, InvalidBlockObjectError,
$error)
forked = ForkedSignedBeaconBlock(restBlock)
forked = ForkedSignedBeaconBlock.init(restBlock)
if forked.kind != node.dag.cfg.consensusForkAtEpoch(
if restBlock.kind != node.dag.cfg.consensusForkAtEpoch(
getForkedBlockField(forked, slot).epoch):
doAssert strictVerification notin node.dag.updateFlags
return RestApiResponse.jsonError(Http400, InvalidBlockObjectError)
@ -861,6 +861,9 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
# TODO
# Add POST /eth/v2/beacon/blocks
# 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 (

View File

@ -162,7 +162,7 @@ type
RestBlockTypes* = phase0.BeaconBlock | altair.BeaconBlock |
bellatrix.BeaconBlock | capella.BeaconBlock |
deneb.BeaconBlock | bellatrix_mev.BlindedBeaconBlock |
DenebBlockContents | bellatrix_mev.BlindedBeaconBlock |
capella_mev.BlindedBeaconBlock
{.push raises: [].}
@ -1037,6 +1037,82 @@ proc readValue*[BlockType: ForkedBeaconBlock](
reader.raiseUnexpectedValue("Incorrect deneb block format")
value = ForkedBeaconBlock.init(res.get()).BlockType
proc readValue*[BlockType: ProduceBlockResponseV2](
reader: var JsonReader[RestJson],
value: var BlockType) {.raises: [IOError, SerializationError, Defect].} =
var
version: Option[ConsensusFork]
data: Option[JsonString]
prepareForkedBlockReading(reader, version, data, "ProduceBlockResponseV2")
case version.get():
of ConsensusFork.Phase0:
let res =
try:
some(RestJson.decode(string(data.get()),
phase0.BeaconBlock,
requireAllFields = true,
allowUnknownFields = true))
except SerializationError:
none[phase0.BeaconBlock]()
if res.isNone():
reader.raiseUnexpectedValue("Incorrect phase0 block format")
value = ProduceBlockResponseV2(kind: ConsensusFork.Phase0,
phase0Data: res.get())
of ConsensusFork.Altair:
let res =
try:
some(RestJson.decode(string(data.get()),
altair.BeaconBlock,
requireAllFields = true,
allowUnknownFields = true))
except SerializationError:
none[altair.BeaconBlock]()
if res.isNone():
reader.raiseUnexpectedValue("Incorrect altair block format")
value = ProduceBlockResponseV2(kind: ConsensusFork.Altair,
altairData: res.get())
of ConsensusFork.Bellatrix:
let res =
try:
some(RestJson.decode(string(data.get()),
bellatrix.BeaconBlock,
requireAllFields = true,
allowUnknownFields = true))
except SerializationError:
none[bellatrix.BeaconBlock]()
if res.isNone():
reader.raiseUnexpectedValue("Incorrect bellatrix block format")
value = ProduceBlockResponseV2(kind: ConsensusFork.Bellatrix,
bellatrixData: res.get())
of ConsensusFork.Capella:
let res =
try:
some(RestJson.decode(string(data.get()),
capella.BeaconBlock,
requireAllFields = true,
allowUnknownFields = true))
except SerializationError:
none[capella.BeaconBlock]()
if res.isNone():
reader.raiseUnexpectedValue("Incorrect capella block format")
value = ProduceBlockResponseV2(kind: ConsensusFork.Capella,
capellaData: res.get())
of ConsensusFork.Deneb:
let res =
try:
some(RestJson.decode(string(data.get()),
DenebBlockContents,
requireAllFields = true,
allowUnknownFields = true))
except SerializationError:
none[DenebBlockContents]()
if res.isNone():
reader.raiseUnexpectedValue("Incorrect deneb block format")
value = ProduceBlockResponseV2(kind: ConsensusFork.Deneb,
denebData: res.get())
proc readValue*[BlockType: ForkedBlindedBeaconBlock](
reader: var JsonReader[RestJson],
value: var BlockType
@ -1268,6 +1344,7 @@ proc readValue*(reader: var JsonReader[RestJson],
sync_aggregate: Option[SyncAggregate]
execution_payload: Option[RestExecutionPayload]
bls_to_execution_changes: Option[SignedBLSToExecutionChangeList]
blob_kzg_commitments: Option[KzgCommitments]
for fieldName in readObjectFields(reader):
case fieldName
@ -1332,6 +1409,11 @@ proc readValue*(reader: var JsonReader[RestJson],
reader.raiseUnexpectedField("Multiple `bls_to_execution_changes` fields found",
"RestPublishedBeaconBlockBody")
bls_to_execution_changes = some(reader.readValue(SignedBLSToExecutionChangeList))
of "blob_kzg_commitments_changes":
if blob_kzg_commitments.isSome():
reader.raiseUnexpectedField("Multiple `blob_kzg_commitments` fields found",
"RestPublishedBeaconBlockBody")
blob_kzg_commitments = some(reader.readValue(KzgCommitments))
else:
unrecognizedFieldWarning()
@ -1354,6 +1436,10 @@ proc readValue*(reader: var JsonReader[RestJson],
let bodyKind =
if execution_payload.isSome() and
execution_payload.get().data_gas_used.isSome() and
blob_kzg_commitments.isSome():
ConsensusFork.Deneb
elif execution_payload.isSome() and
execution_payload.get().withdrawals.isSome() and
bls_to_execution_changes.isSome() and
sync_aggregate.isSome():
@ -1624,6 +1710,129 @@ proc readValue*(reader: var JsonReader[RestJson],
)
)
proc readValue*(reader: var JsonReader[RestJson],
value: var RestPublishedSignedBlockContents) {.
raises: [IOError, SerializationError, Defect].} =
var signature: Option[ValidatorSig]
var message: Option[RestPublishedBeaconBlock]
var signed_message: Option[RestPublishedSignedBeaconBlock]
var signed_block_data: Option[JsonString]
var signed_blob_sidecars: Option[List[SignedBlobSidecar,
Limit MAX_BLOBS_PER_BLOCK]]
# Pre-Deneb, there were always the same two top-level fields
# ('signature' and 'message'). For Deneb, there's a different set of
# a top-level fields: 'signed_block' 'signed_blob_sidecars'. The
# former is the same as the pre-Deneb object.
for fieldName in readObjectFields(reader):
case fieldName
of "message":
if message.isSome():
reader.raiseUnexpectedField("Multiple `message` fields found",
"RestPublishedSignedBlockContents")
message = some(reader.readValue(RestPublishedBeaconBlock))
of "signature":
if signature.isSome():
reader.raiseUnexpectedField("Multiple `signature` fields found",
"RestPublishedSignedBlockContents")
signature = some(reader.readValue(ValidatorSig))
of "signed_block":
if signed_block_data.isSome():
reader.raiseUnexpectedField("Multiple `signed_block` fields found",
"RestPublishedSignedBlockContents")
signed_block_data = some(reader.readValue(JsonString))
if message.isSome() or signature.isSome():
reader.raiseUnexpectedField(
"Found `signed_block` field alongside message or signature fields",
"RestPublishedSignedBlockContents")
signed_message =
try:
some(RestJson.decode(string(signed_block_data.get()),
RestPublishedSignedBeaconBlock,
requireAllFields = true,
allowUnknownFields = true))
except SerializationError:
none[RestPublishedSignedBeaconBlock]()
if signed_message.isNone():
reader.raiseUnexpectedValue("Incorrect signed_block format")
let blck = ForkedSignedBeaconBlock(signed_message.get())
message = some(RestPublishedBeaconBlock(
case blck.kind
of ConsensusFork.Phase0, ConsensusFork.Altair, ConsensusFork.Bellatrix,
ConsensusFork.Capella:
reader.raiseUnexpectedValue("Incorrect signed_block format")
of ConsensusFork.Deneb:
ForkedBeaconBlock.init(blck.denebData.message)
))
signature = some(forks.signature(
ForkedSignedBeaconBlock(signed_message.get())))
of "signed_blob_sidecars":
if signed_blob_sidecars.isSome():
reader.raiseUnexpectedField(
"Multiple `signed_blob_sidecars` fields found",
"RestPublishedSignedBlockContents")
if signature.isSome():
reader.raiseUnexpectedField(
"Found `signed_block` field alongside message or signature fields",
"RestPublishedSignedBlockContents")
signed_blob_sidecars = some(reader.readValue(
List[SignedBlobSidecar, Limit MAX_BLOBS_PER_BLOCK]))
else:
unrecognizedFieldWarning()
if signature.isNone():
reader.raiseUnexpectedValue("Field `signature` is missing")
if message.isNone():
reader.raiseUnexpectedValue("Field `message` is missing")
let blck = ForkedBeaconBlock(message.get())
case blck.kind
of ConsensusFork.Phase0:
value = RestPublishedSignedBlockContents(
kind: ConsensusFork.Phase0,
phase0Data: phase0.SignedBeaconBlock(
message: blck.phase0Data,
signature: signature.get()
)
)
of ConsensusFork.Altair:
value = RestPublishedSignedBlockContents(
kind: ConsensusFork.Altair,
altairData: altair.SignedBeaconBlock(
message: blck.altairData,
signature: signature.get()
)
)
of ConsensusFork.Bellatrix:
value = RestPublishedSignedBlockContents(
kind: ConsensusFork.Bellatrix,
bellatrixData: bellatrix.SignedBeaconBlock(
message: blck.bellatrixData,
signature: signature.get()
)
)
of ConsensusFork.Capella:
value = RestPublishedSignedBlockContents(
kind: ConsensusFork.Capella,
capellaData: capella.SignedBeaconBlock(
message: blck.capellaData,
signature: signature.get()
)
)
of ConsensusFork.Deneb:
value = RestPublishedSignedBlockContents(
kind: ConsensusFork.Deneb,
denebData: DenebSignedBlockContents(
signed_block: deneb.SignedBeaconBlock(
message: blck.denebData,
signature: signature.get()
),
signed_blob_sidecars: signed_blob_sidecars.get()
)
)
## ForkedSignedBeaconBlock
proc readValue*(reader: var JsonReader[RestJson],
value: var ForkedSignedBeaconBlock) {.
@ -2859,6 +3068,81 @@ proc decodeBody*(
else:
return err("Unsupported or invalid content media type")
proc decodeBody*(
t: typedesc[RestPublishedSignedBlockContents],
body: ContentBody,
version: string
): Result[RestPublishedSignedBlockContents, cstring] =
if body.contentType == ApplicationJsonMediaType:
let data =
try:
RestJson.decode(body.data, RestPublishedSignedBlockContents,
requireAllFields = true,
allowUnknownFields = true)
except SerializationError as exc:
debug "Failed to deserialize REST JSON data",
err = exc.formatMsg("<data>"),
data = string.fromBytes(body.data)
return err("Unable to deserialize data")
except CatchableError:
return err("Unexpected deserialization error")
ok(data)
elif body.contentType == OctetStreamMediaType:
let consensusFork = ? ConsensusFork.decodeString(version)
case consensusFork
of ConsensusFork.Phase0:
let blck =
try:
SSZ.decode(body.data, phase0.SignedBeaconBlock)
except SerializationError:
return err("Unable to deserialize data")
except CatchableError:
return err("Unexpected deserialization error")
ok(RestPublishedSignedBlockContents(
kind: ConsensusFork.Phase0, phase0Data: blck))
of ConsensusFork.Altair:
let blck =
try:
SSZ.decode(body.data, altair.SignedBeaconBlock)
except SerializationError:
return err("Unable to deserialize data")
except CatchableError:
return err("Unexpected deserialization error")
ok(RestPublishedSignedBlockContents(
kind: ConsensusFork.Altair, altairData: blck))
of ConsensusFork.Bellatrix:
let blck =
try:
SSZ.decode(body.data, bellatrix.SignedBeaconBlock)
except SerializationError:
return err("Unable to deserialize data")
except CatchableError:
return err("Unexpected deserialization error")
ok(RestPublishedSignedBlockContents(
kind: ConsensusFork.Bellatrix, bellatrixData: blck))
of ConsensusFork.Capella:
let blck =
try:
SSZ.decode(body.data, capella.SignedBeaconBlock)
except SerializationError:
return err("Unable to deserialize data")
except CatchableError:
return err("Unexpected deserialization error")
ok(RestPublishedSignedBlockContents(
kind: ConsensusFork.Capella, capellaData: blck))
of ConsensusFork.Deneb:
let blckContents =
try:
SSZ.decode(body.data, DenebSignedBlockContents)
except SerializationError:
return err("Unable to deserialize data")
except CatchableError:
return err("Unexpected deserialization error")
ok(RestPublishedSignedBlockContents(
kind: ConsensusFork.Deneb, denebData: blckContents))
else:
return err("Unsupported or invalid content media type")
proc decodeBody*[T](t: typedesc[T],
body: ContentBody): Result[T, cstring] =
if body.contentType != ApplicationJsonMediaType:
@ -3010,20 +3294,25 @@ proc decodeBytes*[T: DecodeConsensysTypes](
return err("Invalid or Unsupported consensus version")
case fork
of ConsensusFork.Deneb:
let blck = ? readSszResBytes(deneb.BeaconBlock, value)
ok(ProduceBlockResponseV2(ForkedBeaconBlock.init(blck)))
let blckContents = ? readSszResBytes(DenebBlockContents, value)
ok(ProduceBlockResponseV2(kind: ConsensusFork.Deneb,
denebData: blckContents))
of ConsensusFork.Capella:
let blck = ? readSszResBytes(capella.BeaconBlock, value)
ok(ProduceBlockResponseV2(ForkedBeaconBlock.init(blck)))
ok(ProduceBlockResponseV2(kind: ConsensusFork.Capella,
capellaData: blck))
of ConsensusFork.Bellatrix:
let blck = ? readSszResBytes(bellatrix.BeaconBlock, value)
ok(ProduceBlockResponseV2(ForkedBeaconBlock.init(blck)))
ok(ProduceBlockResponseV2(kind: ConsensusFork.Bellatrix,
bellatrixData: blck))
of ConsensusFork.Altair:
let blck = ? readSszResBytes(altair.BeaconBlock, value)
ok(ProduceBlockResponseV2(ForkedBeaconBlock.init(blck)))
ok(ProduceBlockResponseV2(kind: ConsensusFork.Altair,
altairData: blck))
of ConsensusFork.Phase0:
let blck = ? readSszResBytes(phase0.BeaconBlock, value)
ok(ProduceBlockResponseV2(ForkedBeaconBlock.init(blck)))
ok(ProduceBlockResponseV2(kind: ConsensusFork.Phase0,
phase0Data: blck))
elif t is ProduceBlindedBlockResponse:
let fork = decodeEthConsensusVersion(consensusVersion).valueOr:
return err("Invalid or Unsupported consensus version")

View File

@ -303,6 +303,9 @@ type
transactions*: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
withdrawals*: Option[List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]]
## [New in Capella]
data_gas_used*: Option[uint64] ## [New in Deneb]
excess_data_gas*: Option[uint64] ## [New in Deneb]
PrepareBeaconProposer* = object
validator_index*: ValidatorIndex
@ -310,6 +313,18 @@ type
RestPublishedSignedBeaconBlock* = distinct ForkedSignedBeaconBlock
DenebSignedBlockContents* = object
signed_block*: deneb.SignedBeaconBlock
signed_blob_sidecars*: List[SignedBlobSidecar, Limit MAX_BLOBS_PER_BLOCK]
RestPublishedSignedBlockContents* = object
case kind*: ConsensusFork
of ConsensusFork.Phase0: phase0Data*: phase0.SignedBeaconBlock
of ConsensusFork.Altair: altairData*: altair.SignedBeaconBlock
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.SignedBeaconBlock
of ConsensusFork.Capella: capellaData*: capella.SignedBeaconBlock
of ConsensusFork.Deneb: denebData*: DenebSignedBlockContents
RestPublishedBeaconBlock* = distinct ForkedBeaconBlock
RestPublishedBeaconBlockBody* = object
@ -320,6 +335,18 @@ type
of ConsensusFork.Capella: capellaBody*: capella.BeaconBlockBody
of ConsensusFork.Deneb: denebBody*: deneb.BeaconBlockBody
DenebBlockContents* = object
`block`*: deneb.BeaconBlock
blob_sidecars*: List[SignedBlobSidecar, Limit MAX_BLOBS_PER_BLOCK]
ProduceBlockResponseV2* = object
case kind*: ConsensusFork
of ConsensusFork.Phase0: phase0Data*: phase0.BeaconBlock
of ConsensusFork.Altair: altairData*: altair.BeaconBlock
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.BeaconBlock
of ConsensusFork.Capella: capellaData*: capella.BeaconBlock
of ConsensusFork.Deneb: denebData*: DenebBlockContents
RestSpec* = object
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.1/presets/mainnet/phase0.yaml
MAX_COMMITTEES_PER_SLOT*: uint64
@ -676,7 +703,6 @@ type
GetVersionResponse* = DataEnclosedObject[RestNodeVersion]
GetEpochSyncCommitteesResponse* = DataEnclosedObject[RestEpochSyncCommittee]
ProduceAttestationDataResponse* = DataEnclosedObject[AttestationData]
ProduceBlockResponseV2* = ForkedBeaconBlock
ProduceBlindedBlockResponse* = ForkedBlindedBeaconBlock
ProduceSyncCommitteeContributionResponse* = DataEnclosedObject[SyncCommitteeContribution]
SubmitBlindedBlockResponseBellatrix* = DataEnclosedObject[bellatrix.ExecutionPayload]
@ -720,6 +746,21 @@ type
func `==`*(a, b: RestValidatorIndex): bool =
uint64(a) == uint64(b)
func init*(T: type ForkedSignedBeaconBlock,
contents: RestPublishedSignedBlockContents): T =
return
case contents.kind
of ConsensusFork.Phase0:
ForkedSignedBeaconBlock.init(contents.phase0Data)
of ConsensusFork.Altair:
ForkedSignedBeaconBlock.init(contents.altairData)
of ConsensusFork.Bellatrix:
ForkedSignedBeaconBlock.init(contents.bellatrixData)
of ConsensusFork.Capella:
ForkedSignedBeaconBlock.init(contents.capellaData)
of ConsensusFork.Deneb:
ForkedSignedBeaconBlock.init(contents.denebData.signed_block)
func init*(t: typedesc[StateIdent], v: StateIdentType): StateIdent =
StateIdent(kind: StateQueryKind.Named, value: v)

View File

@ -41,7 +41,7 @@ proc produceBlock(
wall_slot = currentSlot
validator = shortLog(validator)
let
beaconBlock =
produceBlockResponse =
try:
await vc.produceBlockV2(slot, randao_reveal, graffiti,
ApiStrategyKind.Best)
@ -55,9 +55,30 @@ proc produceBlock(
error "An unexpected error occurred while getting block data",
error_name = exc.name, error_msg = exc.msg
return Opt.none(PreparedBeaconBlock)
blockRoot = withBlck(beaconBlock): hash_tree_root(blck)
case produceBlockResponse.kind
of ConsensusFork.Phase0:
let blck = produceBlockResponse.phase0Data
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck)))
of ConsensusFork.Altair:
let blck = produceBlockResponse.altairData
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck)))
of ConsensusFork.Bellatrix:
let blck = produceBlockResponse.bellatrixData
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck)))
of ConsensusFork.Capella:
let blck = produceBlockResponse.capellaData
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck)))
of ConsensusFork.Deneb:
debugRaiseAssert $denebImplementationMissing
# TODO return blobs as well
let blck = produceBlockResponse.denebData.`block`
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck)))
return Opt.some(PreparedBeaconBlock(blockRoot: blockRoot, data: beaconBlock))
proc produceBlindedBlock(
vc: ValidatorClientRef,

View File

@ -93,6 +93,9 @@ proc routeSignedBeaconBlock*(
let res = validateBeaconBlock(
router[].dag, router[].quarantine, blck, wallTime, {})
# TODO blob gossip validation
debugRaiseAssert $denebImplementationMissing
if not res.isGoodForSending():
warn "Block failed validation",
blockRoot = shortLog(blck.root), blck = shortLog(blck.message),

View File

@ -64,7 +64,7 @@ const
AltairBlock = "{\"version\":\"altair\",\"data\":{\"slot\":\"5297696\",\"proposer_index\":\"153094\",\"parent_root\":\"0xe6106533af9be918120ead7440a8006c7f123cc3cb7daf1f11d951864abea014\",\"state_root\":\"0xf86196d34500ca25d1f4e7431d4d52f6f85540bcaf97dd0d2ad9ecdb3eebcdf0\",\"body\":{\"randao_reveal\":\"0xa7efee3d5ddceb60810b23e3b5d39734696418f41dfd13a0851c7be7a72acbdceaa61e1db27513801917d72519d1c1040ccfed829faf06abe06d9964949554bf4369134b66de715ea49eb4fecf3e2b7e646f1764a1993e31e53dbc6557929c12\",\"eth1_data\":{\"deposit_root\":\"0x8ec87d7219a3c873fff3bfe206b4f923d1b471ce4ff9d6d6ecc162ef07825e14\",\"deposit_count\":\"259476\",\"block_hash\":\"0x877b6f8332c7397251ff3f0c5cecec105ff7d4cb78251b47f91fd15a86a565ab\"},\"graffiti\":\"\",\"proposer_slashings\":[],\"attester_slashings\":[],\"attestations\":[],\"deposits\":[],\"voluntary_exits\":[],\"sync_aggregate\":{\"sync_committee_bits\":\"0x733dfda7f5ffde5ade73367fcbf7fffeef7fe43777ffdffab9dbad6f7eed5fff9bfec4affdefbfaddf35bf5efbff9ffff9dfd7dbf97fbfcdfaddfeffbf95f75f\",\"sync_committee_signature\":\"0x81fdf76e797f81b0116a1c1ae5200b613c8041115223cd89e8bd5477aab13de6097a9ebf42b130c59527bbb4c96811b809353a17c717549f82d4bd336068ef0b99b1feebd4d2432a69fa77fac12b78f1fcc9d7b59edbeb381adf10b15bc4a520\"}}}}"
BellatrixBlock = "{\"version\":\"bellatrix\",\"data\":{\"slot\":\"5297696\",\"proposer_index\":\"153094\",\"parent_root\":\"0xe6106533af9be918120ead7440a8006c7f123cc3cb7daf1f11d951864abea014\",\"state_root\":\"0xf86196d34500ca25d1f4e7431d4d52f6f85540bcaf97dd0d2ad9ecdb3eebcdf0\",\"body\":{\"randao_reveal\":\"0xa7efee3d5ddceb60810b23e3b5d39734696418f41dfd13a0851c7be7a72acbdceaa61e1db27513801917d72519d1c1040ccfed829faf06abe06d9964949554bf4369134b66de715ea49eb4fecf3e2b7e646f1764a1993e31e53dbc6557929c12\",\"eth1_data\":{\"deposit_root\":\"0x8ec87d7219a3c873fff3bfe206b4f923d1b471ce4ff9d6d6ecc162ef07825e14\",\"deposit_count\":\"259476\",\"block_hash\":\"0x877b6f8332c7397251ff3f0c5cecec105ff7d4cb78251b47f91fd15a86a565ab\"},\"graffiti\":\"\",\"proposer_slashings\":[],\"attester_slashings\":[],\"attestations\":[],\"deposits\":[],\"voluntary_exits\":[],\"sync_aggregate\":{\"sync_committee_bits\":\"0x733dfda7f5ffde5ade73367fcbf7fffeef7fe43777ffdffab9dbad6f7eed5fff9bfec4affdefbfaddf35bf5efbff9ffff9dfd7dbf97fbfcdfaddfeffbf95f75f\",\"sync_committee_signature\":\"0x81fdf76e797f81b0116a1c1ae5200b613c8041115223cd89e8bd5477aab13de6097a9ebf42b130c59527bbb4c96811b809353a17c717549f82d4bd336068ef0b99b1feebd4d2432a69fa77fac12b78f1fcc9d7b59edbeb381adf10b15bc4a520\"},\"execution_payload\":{\"parent_hash\":\"0x14c2242a8cfbce559e84c391f5f16d10d7719751b8558873012dc88ae5a193e8\",\"fee_recipient\":\"$1\",\"state_root\":\"0xdf8d96b2c292736d39e72e25802c2744d34d3d3c616de5b362425cab01f72fa5\",\"receipts_root\":\"0x4938a2bf640846d213b156a1a853548b369cd02917fa63d8766ab665d7930bac\",\"logs_bloom\":\"0x298610600038408c201080013832408850a00bc8f801920121840030a015310010e2a0e0108628110552062811441c84802f43825c4fc82140b036c58025a28800054c80a44025c052090a0f2c209a0400058040019ea0008e589084078048050880930113a2894082e0112408b088382402a851621042212aa40018a408d07e178c68691486411aa9a2809043b000a04c040000065a030028018540b04b1820271d00821b00c29059095022322c10a530060223240416140190056608200063c82248274ba8f0098e402041cd9f451031481a1010b8220824833520490221071898802d206348449116812280014a10a2d1c210100a30010802490f0a221849\",\"prev_randao\":\"0xc061711e135cd40531ec3ee29d17d3824c0e5f80d07f721e792ab83240aa0ab5\",\"block_number\":\"8737497\",\"gas_limit\":\"30000000\",\"gas_used\":\"16367052\",\"timestamp\":\"1680080352\",\"extra_data\":\"0xd883010b05846765746888676f312e32302e32856c696e7578\",\"base_fee_per_gas\":\"231613172261\",\"block_hash\":\"0x5aa9fd22a9238925adb2b038fd6eafc77adabf554051db5bc16ae5168a52eff6\",\"transactions\":[],\"withdrawals\":[]}}}}"
CapellaBlock = "{\"version\":\"capella\",\"data\":{\"slot\":\"5297696\",\"proposer_index\":\"153094\",\"parent_root\":\"0xe6106533af9be918120ead7440a8006c7f123cc3cb7daf1f11d951864abea014\",\"state_root\":\"0xf86196d34500ca25d1f4e7431d4d52f6f85540bcaf97dd0d2ad9ecdb3eebcdf0\",\"body\":{\"randao_reveal\":\"0xa7efee3d5ddceb60810b23e3b5d39734696418f41dfd13a0851c7be7a72acbdceaa61e1db27513801917d72519d1c1040ccfed829faf06abe06d9964949554bf4369134b66de715ea49eb4fecf3e2b7e646f1764a1993e31e53dbc6557929c12\",\"eth1_data\":{\"deposit_root\":\"0x8ec87d7219a3c873fff3bfe206b4f923d1b471ce4ff9d6d6ecc162ef07825e14\",\"deposit_count\":\"259476\",\"block_hash\":\"0x877b6f8332c7397251ff3f0c5cecec105ff7d4cb78251b47f91fd15a86a565ab\"},\"graffiti\":\"\",\"proposer_slashings\":[],\"attester_slashings\":[],\"attestations\":[],\"deposits\":[],\"voluntary_exits\":[],\"sync_aggregate\":{\"sync_committee_bits\":\"0x733dfda7f5ffde5ade73367fcbf7fffeef7fe43777ffdffab9dbad6f7eed5fff9bfec4affdefbfaddf35bf5efbff9ffff9dfd7dbf97fbfcdfaddfeffbf95f75f\",\"sync_committee_signature\":\"0x81fdf76e797f81b0116a1c1ae5200b613c8041115223cd89e8bd5477aab13de6097a9ebf42b130c59527bbb4c96811b809353a17c717549f82d4bd336068ef0b99b1feebd4d2432a69fa77fac12b78f1fcc9d7b59edbeb381adf10b15bc4a520\"},\"execution_payload\":{\"parent_hash\":\"0x14c2242a8cfbce559e84c391f5f16d10d7719751b8558873012dc88ae5a193e8\",\"fee_recipient\":\"$1\",\"state_root\":\"0xdf8d96b2c292736d39e72e25802c2744d34d3d3c616de5b362425cab01f72fa5\",\"receipts_root\":\"0x4938a2bf640846d213b156a1a853548b369cd02917fa63d8766ab665d7930bac\",\"logs_bloom\":\"0x298610600038408c201080013832408850a00bc8f801920121840030a015310010e2a0e0108628110552062811441c84802f43825c4fc82140b036c58025a28800054c80a44025c052090a0f2c209a0400058040019ea0008e589084078048050880930113a2894082e0112408b088382402a851621042212aa40018a408d07e178c68691486411aa9a2809043b000a04c040000065a030028018540b04b1820271d00821b00c29059095022322c10a530060223240416140190056608200063c82248274ba8f0098e402041cd9f451031481a1010b8220824833520490221071898802d206348449116812280014a10a2d1c210100a30010802490f0a221849\",\"prev_randao\":\"0xc061711e135cd40531ec3ee29d17d3824c0e5f80d07f721e792ab83240aa0ab5\",\"block_number\":\"8737497\",\"gas_limit\":\"30000000\",\"gas_used\":\"16367052\",\"timestamp\":\"1680080352\",\"extra_data\":\"0xd883010b05846765746888676f312e32302e32856c696e7578\",\"base_fee_per_gas\":\"231613172261\",\"block_hash\":\"0x5aa9fd22a9238925adb2b038fd6eafc77adabf554051db5bc16ae5168a52eff6\",\"transactions\":[],\"withdrawals\":[]},\"bls_to_execution_changes\":[]}}}"
DenebBlock = "{\"version\":\"deneb\",\"data\":{\"slot\":\"5297696\",\"proposer_index\":\"153094\",\"parent_root\":\"0xe6106533af9be918120ead7440a8006c7f123cc3cb7daf1f11d951864abea014\",\"state_root\":\"0xf86196d34500ca25d1f4e7431d4d52f6f85540bcaf97dd0d2ad9ecdb3eebcdf0\",\"body\":{\"randao_reveal\":\"0xa7efee3d5ddceb60810b23e3b5d39734696418f41dfd13a0851c7be7a72acbdceaa61e1db27513801917d72519d1c1040ccfed829faf06abe06d9964949554bf4369134b66de715ea49eb4fecf3e2b7e646f1764a1993e31e53dbc6557929c12\",\"eth1_data\":{\"deposit_root\":\"0x8ec87d7219a3c873fff3bfe206b4f923d1b471ce4ff9d6d6ecc162ef07825e14\",\"deposit_count\":\"259476\",\"block_hash\":\"0x877b6f8332c7397251ff3f0c5cecec105ff7d4cb78251b47f91fd15a86a565ab\"},\"graffiti\":\"\",\"proposer_slashings\":[],\"attester_slashings\":[],\"attestations\":[],\"deposits\":[],\"voluntary_exits\":[],\"sync_aggregate\":{\"sync_committee_bits\":\"0x733dfda7f5ffde5ade73367fcbf7fffeef7fe43777ffdffab9dbad6f7eed5fff9bfec4affdefbfaddf35bf5efbff9ffff9dfd7dbf97fbfcdfaddfeffbf95f75f\",\"sync_committee_signature\":\"0x81fdf76e797f81b0116a1c1ae5200b613c8041115223cd89e8bd5477aab13de6097a9ebf42b130c59527bbb4c96811b809353a17c717549f82d4bd336068ef0b99b1feebd4d2432a69fa77fac12b78f1fcc9d7b59edbeb381adf10b15bc4a520\"},\"execution_payload\":{\"parent_hash\":\"0x14c2242a8cfbce559e84c391f5f16d10d7719751b8558873012dc88ae5a193e8\",\"fee_recipient\":\"$1\",\"state_root\":\"0xdf8d96b2c292736d39e72e25802c2744d34d3d3c616de5b362425cab01f72fa5\",\"receipts_root\":\"0x4938a2bf640846d213b156a1a853548b369cd02917fa63d8766ab665d7930bac\",\"logs_bloom\":\"0x298610600038408c201080013832408850a00bc8f801920121840030a015310010e2a0e0108628110552062811441c84802f43825c4fc82140b036c58025a28800054c80a44025c052090a0f2c209a0400058040019ea0008e589084078048050880930113a2894082e0112408b088382402a851621042212aa40018a408d07e178c68691486411aa9a2809043b000a04c040000065a030028018540b04b1820271d00821b00c29059095022322c10a530060223240416140190056608200063c82248274ba8f0098e402041cd9f451031481a1010b8220824833520490221071898802d206348449116812280014a10a2d1c210100a30010802490f0a221849\",\"prev_randao\":\"0xc061711e135cd40531ec3ee29d17d3824c0e5f80d07f721e792ab83240aa0ab5\",\"block_number\":\"8737497\",\"gas_limit\":\"30000000\",\"gas_used\":\"16367052\",\"timestamp\":\"1680080352\",\"extra_data\":\"0xd883010b05846765746888676f312e32302e32856c696e7578\",\"base_fee_per_gas\":\"231613172261\",\"block_hash\":\"0x5aa9fd22a9238925adb2b038fd6eafc77adabf554051db5bc16ae5168a52eff6\",\"transactions\":[],\"withdrawals\":[],\"data_gas_used\":\"2316131761\",\"excess_data_gas\":\"231613172261\"},\"bls_to_execution_changes\":[],\"blob_kzg_commitments\":[]}}}"
DenebBlockContents = "{\"version\":\"deneb\",\"data\":{\"block\":{\"slot\":\"5297696\",\"proposer_index\":\"153094\",\"parent_root\":\"0xe6106533af9be918120ead7440a8006c7f123cc3cb7daf1f11d951864abea014\",\"state_root\":\"0xf86196d34500ca25d1f4e7431d4d52f6f85540bcaf97dd0d2ad9ecdb3eebcdf0\",\"body\":{\"randao_reveal\":\"0xa7efee3d5ddceb60810b23e3b5d39734696418f41dfd13a0851c7be7a72acbdceaa61e1db27513801917d72519d1c1040ccfed829faf06abe06d9964949554bf4369134b66de715ea49eb4fecf3e2b7e646f1764a1993e31e53dbc6557929c12\",\"eth1_data\":{\"deposit_root\":\"0x8ec87d7219a3c873fff3bfe206b4f923d1b471ce4ff9d6d6ecc162ef07825e14\",\"deposit_count\":\"259476\",\"block_hash\":\"0x877b6f8332c7397251ff3f0c5cecec105ff7d4cb78251b47f91fd15a86a565ab\"},\"graffiti\":\"\",\"proposer_slashings\":[],\"attester_slashings\":[],\"attestations\":[],\"deposits\":[],\"voluntary_exits\":[],\"sync_aggregate\":{\"sync_committee_bits\":\"0x733dfda7f5ffde5ade73367fcbf7fffeef7fe43777ffdffab9dbad6f7eed5fff9bfec4affdefbfaddf35bf5efbff9ffff9dfd7dbf97fbfcdfaddfeffbf95f75f\",\"sync_committee_signature\":\"0x81fdf76e797f81b0116a1c1ae5200b613c8041115223cd89e8bd5477aab13de6097a9ebf42b130c59527bbb4c96811b809353a17c717549f82d4bd336068ef0b99b1feebd4d2432a69fa77fac12b78f1fcc9d7b59edbeb381adf10b15bc4a520\"},\"execution_payload\":{\"parent_hash\":\"0x14c2242a8cfbce559e84c391f5f16d10d7719751b8558873012dc88ae5a193e8\",\"fee_recipient\":\"$1\",\"state_root\":\"0xdf8d96b2c292736d39e72e25802c2744d34d3d3c616de5b362425cab01f72fa5\",\"receipts_root\":\"0x4938a2bf640846d213b156a1a853548b369cd02917fa63d8766ab665d7930bac\",\"logs_bloom\":\"0x298610600038408c201080013832408850a00bc8f801920121840030a015310010e2a0e0108628110552062811441c84802f43825c4fc82140b036c58025a28800054c80a44025c052090a0f2c209a0400058040019ea0008e589084078048050880930113a2894082e0112408b088382402a851621042212aa40018a408d07e178c68691486411aa9a2809043b000a04c040000065a030028018540b04b1820271d00821b00c29059095022322c10a530060223240416140190056608200063c82248274ba8f0098e402041cd9f451031481a1010b8220824833520490221071898802d206348449116812280014a10a2d1c210100a30010802490f0a221849\",\"prev_randao\":\"0xc061711e135cd40531ec3ee29d17d3824c0e5f80d07f721e792ab83240aa0ab5\",\"block_number\":\"8737497\",\"gas_limit\":\"30000000\",\"gas_used\":\"16367052\",\"timestamp\":\"1680080352\",\"extra_data\":\"0xd883010b05846765746888676f312e32302e32856c696e7578\",\"base_fee_per_gas\":\"231613172261\",\"block_hash\":\"0x5aa9fd22a9238925adb2b038fd6eafc77adabf554051db5bc16ae5168a52eff6\",\"transactions\":[],\"withdrawals\":[],\"data_gas_used\":\"2316131761\",\"excess_data_gas\":\"231613172261\"},\"bls_to_execution_changes\":[],\"blob_kzg_commitments\":[]}},\"blob_sidecars\":[]}}"
SigningNodeAddress = "127.0.0.1"
defaultSigningNodePort = 35333
@ -79,6 +79,20 @@ proc getNodePort(basePort: int, rt: RemoteSignerType): int =
of RemoteSignerType.VerifyingWeb3Signer:
basePort + 1
func init(T: type ForkedBeaconBlock, contents: ProduceBlockResponseV2): T =
case contents.kind
of ConsensusFork.Phase0:
return ForkedBeaconBlock.init(contents.phase0Data)
of ConsensusFork.Altair:
return ForkedBeaconBlock.init(contents.altairData)
of ConsensusFork.Bellatrix:
return ForkedBeaconBlock.init(contents.bellatrixData)
of ConsensusFork.Capella:
return ForkedBeaconBlock.init(contents.capellaData)
of ConsensusFork.Deneb:
return ForkedBeaconBlock.init(contents.denebData.block)
proc getBlock(fork: ConsensusFork,
feeRecipient = SigningExpectedFeeRecipient): ForkedBeaconBlock =
let
@ -88,14 +102,16 @@ proc getBlock(fork: ConsensusFork,
of ConsensusFork.Altair: AltairBlock
of ConsensusFork.Bellatrix: BellatrixBlock % [feeRecipient]
of ConsensusFork.Capella: CapellaBlock % [feeRecipient]
of ConsensusFork.Deneb: DenebBlock % [feeRecipient]
of ConsensusFork.Deneb: DenebBlockContents % [feeRecipient]
contentType = ContentTypeData(
mediaType: MediaType.init("application/json"))
decodeBytes(ProduceBlockResponseV2,
blckData.toOpenArrayByte(0, len(blckData) - 1),
Opt.some(contentType),
$fork).tryGet()
let b = decodeBytes(ProduceBlockResponseV2,
blckData.toOpenArrayByte(0, len(blckData) - 1),
Opt.some(contentType),
$fork).tryGet()
ForkedBeaconBlock.init(b)
proc init(t: typedesc[Web3SignerForkedBeaconBlock],
forked: ForkedBeaconBlock): Web3SignerForkedBeaconBlock =