json-rpc: fix crashes on altair+ blocks in certain operations (#2983)

For the v2 interfaces, REST is recommeded instead
This commit is contained in:
Jacek Sieka 2021-10-13 12:20:18 +02:00 committed by GitHub
parent 1f51331dd3
commit 1da4192f3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 40 additions and 32 deletions

View File

@ -384,19 +384,21 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {.
blockId: string) -> blockId: string) ->
tuple[canonical: bool, header: SignedBeaconBlockHeader]: tuple[canonical: bool, header: SignedBeaconBlockHeader]:
let bd = node.getBlockDataFromBlockId(blockId) let bd = node.getBlockDataFromBlockId(blockId)
# TODO check for Altair blocks and fail, because /v1/ return withBlck(bd.data):
let tsbb = bd.data.phase0Block static: doAssert blck.signature is TrustedSig and
static: doAssert tsbb.signature is TrustedSig and sizeof(ValidatorSig) == sizeof(blck.signature)
sizeof(ValidatorSig) == sizeof(tsbb.signature) (
result.header.signature = cast[ValidatorSig](tsbb.signature) canonical: bd.refs.isAncestorOf(node.dag.head),
header: SignedBeaconBlockHeader(
result.header.message.slot = tsbb.message.slot message: BeaconBlockHeader(
result.header.message.proposer_index = tsbb.message.proposer_index slot: blck.message.slot,
result.header.message.parent_root = tsbb.message.parent_root proposer_index: blck.message.proposer_index,
result.header.message.state_root = tsbb.message.state_root parent_root: blck.message.parent_root,
result.header.message.body_root = tsbb.message.body.hash_tree_root() state_root: blck.message.state_root,
body_root: blck.message.body.hash_tree_root()
result.canonical = bd.refs.isAncestorOf(node.dag.head) )
)
)
rpcServer.rpc("post_v1_beacon_blocks") do (blck: phase0.SignedBeaconBlock) -> int: rpcServer.rpc("post_v1_beacon_blocks") do (blck: phase0.SignedBeaconBlock) -> int:
if not(node.syncManager.inProgress): if not(node.syncManager.inProgress):
@ -404,8 +406,6 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {.
"Beacon node is currently syncing, try again later.") "Beacon node is currently syncing, try again later.")
let head = node.dag.head let head = node.dag.head
if head.slot >= blck.message.slot: if head.slot >= blck.message.slot:
# TODO altair-transition, but not immediate testnet-priority to detect
# Altair and fail, since /v1/ doesn't support Altair
node.network.broadcastBeaconBlock(ForkedSignedBeaconBlock.init(blck)) node.network.broadcastBeaconBlock(ForkedSignedBeaconBlock.init(blck))
# The block failed validation, but was successfully broadcast anyway. # The block failed validation, but was successfully broadcast anyway.
# It was not integrated into the beacon node's database. # It was not integrated into the beacon node's database.
@ -415,7 +415,6 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {.
node, head, AttachedValidator(), node, head, AttachedValidator(),
ForkedSignedBeaconBlock.init(blck)) ForkedSignedBeaconBlock.init(blck))
if res == head: if res == head:
# TODO altair-transition, but not immediate testnet-priority
node.network.broadcastBeaconBlock(ForkedSignedBeaconBlock.init(blck)) node.network.broadcastBeaconBlock(ForkedSignedBeaconBlock.init(blck))
# The block failed validation, but was successfully broadcast anyway. # The block failed validation, but was successfully broadcast anyway.
# It was not integrated into the beacon node''s database. # It was not integrated into the beacon node''s database.
@ -427,18 +426,21 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {.
rpcServer.rpc("get_v1_beacon_blocks_blockId") do ( rpcServer.rpc("get_v1_beacon_blocks_blockId") do (
blockId: string) -> phase0.TrustedSignedBeaconBlock: blockId: string) -> phase0.TrustedSignedBeaconBlock:
# TODO detect Altair and fail: /v1/ APIs don't support Altair let blck = node.getBlockDataFromBlockId(blockId).data
return node.getBlockDataFromBlockId(blockId).data.phase0Block if blck.kind == BeaconBlockFork.Phase0:
return blck.phase0Block
else:
raiseNoAltairSupport()
rpcServer.rpc("get_v1_beacon_blocks_blockId_root") do ( rpcServer.rpc("get_v1_beacon_blocks_blockId_root") do (
blockId: string) -> Eth2Digest: blockId: string) -> Eth2Digest:
# TODO detect Altair and fail: /v1/ APIs don't support Altair return withBlck(node.getBlockDataFromBlockId(blockId).data):
return node.getBlockDataFromBlockId(blockId).data.phase0Block.message.state_root blck.message.state_root
rpcServer.rpc("get_v1_beacon_blocks_blockId_attestations") do ( rpcServer.rpc("get_v1_beacon_blocks_blockId_attestations") do (
blockId: string) -> seq[TrustedAttestation]: blockId: string) -> seq[TrustedAttestation]:
# TODO detect Altair and fail: /v1/ APIs don't support Altair return withBlck(node.getBlockDataFromBlockId(blockId).data):
return node.getBlockDataFromBlockId(blockId).data.phase0Block.message.body.attestations.asSeq blck.message.body.attestations.asSeq
rpcServer.rpc("get_v1_beacon_pool_attestations") do ( rpcServer.rpc("get_v1_beacon_pool_attestations") do (
slot: Option[uint64], committee_index: Option[uint64]) -> slot: Option[uint64], committee_index: Option[uint64]) ->

View File

@ -26,7 +26,10 @@ proc installDebugApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {.
rpcServer.rpc("get_v1_debug_beacon_states_stateId") do ( rpcServer.rpc("get_v1_debug_beacon_states_stateId") do (
stateId: string) -> phase0.BeaconState: stateId: string) -> phase0.BeaconState:
withStateForStateId(stateId): withStateForStateId(stateId):
return stateData.data.hbsPhase0.data if stateData.data.beaconStateFork == forkPhase0:
return stateData.data.hbsPhase0.data
else:
raiseNoAltairSupport()
rpcServer.rpc("get_v1_debug_beacon_heads") do () -> seq[tuple[root: Eth2Digest, slot: Slot]]: rpcServer.rpc("get_v1_debug_beacon_heads") do () -> seq[tuple[root: Eth2Digest, slot: Slot]]:
return node.dag.heads.mapIt((it.root, it.slot)) return node.dag.heads.mapIt((it.root, it.slot))

View File

@ -16,7 +16,11 @@ import
../spec/[forks, helpers], ../spec/[forks, helpers],
../spec/eth2_apis/[rpc_types, eth2_json_rpc_serialization] ../spec/eth2_apis/[rpc_types, eth2_json_rpc_serialization]
export rpc_types, eth2_json_rpc_serialization, blockchain_dag export forks, rpc_types, eth2_json_rpc_serialization, blockchain_dag
template raiseNoAltairSupport*() =
raise (ref ValueError)(msg:
"The JSON-RPC interface does not support certain Altair operations due to changes in block structure - see https://nimbus.guide/rest-api.html for full altair support")
template withStateForStateId*(stateId: string, body: untyped): untyped = template withStateForStateId*(stateId: string, body: untyped): untyped =
let let

View File

@ -50,9 +50,8 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {.
case blck.kind case blck.kind
of BeaconBlockFork.Phase0: of BeaconBlockFork.Phase0:
return blck.phase0Block return blck.phase0Block
of BeaconBlockFork.Altair, BeaconBlockFork.Merge: else:
raise newException(CatchableError, raiseNoAltairSupport()
"could not retrieve block for altair or merge blocks")
rpcServer.rpc("post_v1_validator_block") do (body: phase0.SignedBeaconBlock) -> bool: rpcServer.rpc("post_v1_validator_block") do (body: phase0.SignedBeaconBlock) -> bool:
debug "post_v1_validator_block", debug "post_v1_validator_block",

View File

@ -275,7 +275,7 @@ type
TrustedBeaconBlockBody* = object TrustedBeaconBlockBody* = object
## A full verified block ## A full verified block
randao_reveal*: ValidatorSig randao_reveal*: TrustedSig
eth1_data*: Eth1Data ##\ eth1_data*: Eth1Data ##\
## Eth1 data vote ## Eth1 data vote
@ -283,11 +283,11 @@ type
## Arbitrary data ## Arbitrary data
# Operations # Operations
proposer_slashings*: List[ProposerSlashing, Limit MAX_PROPOSER_SLASHINGS] proposer_slashings*: List[TrustedProposerSlashing, Limit MAX_PROPOSER_SLASHINGS]
attester_slashings*: List[AttesterSlashing, Limit MAX_ATTESTER_SLASHINGS] attester_slashings*: List[TrustedAttesterSlashing, Limit MAX_ATTESTER_SLASHINGS]
attestations*: List[Attestation, Limit MAX_ATTESTATIONS] attestations*: List[TrustedAttestation, Limit MAX_ATTESTATIONS]
deposits*: List[Deposit, Limit MAX_DEPOSITS] deposits*: List[Deposit, Limit MAX_DEPOSITS]
voluntary_exits*: List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS] voluntary_exits*: List[TrustedSignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS]
sync_aggregate*: SyncAggregate sync_aggregate*: SyncAggregate
# Execution # Execution