diff --git a/beacon_chain/extras.nim b/beacon_chain/extras.nim index c3674df39..f31d5ecdb 100644 --- a/beacon_chain/extras.nim +++ b/beacon_chain/extras.nim @@ -27,6 +27,9 @@ type ## Skip verification of BLS signatures in block processing. ## Predominantly intended for use in testing, e.g. to allow extra coverage. ## Also useful to avoid unnecessary work when replaying known, good blocks. + skipRandaoVerification ##\ + ## Skip verification of the proposer's randao reveal in block processing, but do ensure + ## that they set the randao reveal to the point at infinity. skipStateRootValidation ##\ ## Skip verification of block state root. strictVerification ##\ diff --git a/beacon_chain/rpc/rest_constants.nim b/beacon_chain/rpc/rest_constants.nim index f1cbe9e13..ca470f020 100644 --- a/beacon_chain/rpc/rest_constants.nim +++ b/beacon_chain/rpc/rest_constants.nim @@ -90,6 +90,8 @@ const "Missing `randao_reveal` value" InvalidRandaoRevealValue* = "Invalid randao reveal value" + InvalidSkipRandaoVerificationValue* = + "Invalid skip_randao_verification value" InvalidGraffitiBytesValue* = "Invalid graffiti bytes value" InvalidEpochValueError* = diff --git a/beacon_chain/rpc/rest_validator_api.nim b/beacon_chain/rpc/rest_validator_api.nim index 8dfa0f869..025cbc890 100644 --- a/beacon_chain/rpc/rest_validator_api.nim +++ b/beacon_chain/rpc/rest_validator_api.nim @@ -369,7 +369,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) = # https://ethereum.github.io/beacon-APIs/#/Validator/produceBlockV2 router.api(MethodGet, "/eth/v2/validator/blocks/{slot}") do ( slot: Slot, randao_reveal: Option[ValidatorSig], - graffiti: Option[GraffitiBytes]) -> RestApiResponse: + graffiti: Option[GraffitiBytes], skip_randao_verification: Option[string]) -> RestApiResponse: let message = block: let qslot = block: @@ -387,6 +387,15 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) = return RestApiResponse.jsonError(Http400, InvalidSlotValueError, "Slot cannot be in the future") res + let qskip_randao_verification = + if skip_randao_verification.isNone(): + false + else: + let res = skip_randao_verification.get() + if res.isErr() or res.get() != "": + return RestApiResponse.jsonError(Http400, + InvalidSkipRandaoVerificationValue) + true let qrandao = if randao_reveal.isNone(): return RestApiResponse.jsonError(Http400, MissingRandaoRevealValue) @@ -418,7 +427,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) = if proposer.isNone(): return RestApiResponse.jsonError(Http400, ProposerNotFoundError) let res = await makeBeaconBlockForHeadAndSlot( - node, qrandao, proposer.get(), qgraffiti, qhead, qslot) + node, qrandao, proposer.get(), qgraffiti, qhead, qslot, qskip_randao_verification) if res.isErr(): return RestApiResponse.jsonError(Http400, res.error()) res.get() diff --git a/beacon_chain/spec/state_transition_block.nim b/beacon_chain/spec/state_transition_block.nim index 0c8f6f43a..b14df6827 100644 --- a/beacon_chain/spec/state_transition_block.nim +++ b/beacon_chain/spec/state_transition_block.nim @@ -88,7 +88,10 @@ proc process_randao( let epoch = state.get_current_epoch() - if skipBlsValidation notin flags: + if skipRandaoVerification in flags: + if body.randao_reveal.toRaw != ValidatorSig.infinity.toRaw: + return err("process_randao: expected point-at-infinity for skipRandaoVerification") + elif skipBlsValidation notin flags: let proposer_pubkey = state.validators.item(proposer_index.get).pubkey if not verify_epoch_signature( diff --git a/beacon_chain/validators/validator_duties.nim b/beacon_chain/validators/validator_duties.nim index 68501b27b..2f9114668 100644 --- a/beacon_chain/validators/validator_duties.nim +++ b/beacon_chain/validators/validator_duties.nim @@ -446,6 +446,7 @@ proc makeBeaconBlockForHeadAndSlot*( node: BeaconNode, randao_reveal: ValidatorSig, validator_index: ValidatorIndex, graffiti: GraffitiBytes, head: BlockRef, slot: Slot, + skip_randao_verification_bool: bool = false, execution_payload: Opt[ExecutionPayload] = Opt.none(ExecutionPayload), transactions_root: Opt[Eth2Digest] = Opt.none(Eth2Digest), execution_payload_root: Opt[Eth2Digest] = Opt.none(Eth2Digest)): @@ -521,6 +522,7 @@ proc makeBeaconBlockForHeadAndSlot*( effectiveExecutionPayload, noRollback, # Temporary state - no need for rollback cache, + verificationFlags = if skip_randao_verification_bool: {skipRandaoVerification} else: {}, transactions_root = if transactions_root.isSome: Opt.some transactions_root.get