VC: Deprecate fallback path to produceBlockV2, use produceBlockV3 always. (#6300)

* Remove fallback path to publishBlockV2(), use publishBlockV3().

* Update AllTests.md.
This commit is contained in:
Eugene Kabanov 2024-05-22 01:03:38 +03:00 committed by GitHub
parent d7c5bc0397
commit 34853ca155
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 13 additions and 486 deletions

View File

@ -1030,4 +1030,4 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
OK: 9/9 Fail: 0/9 Skip: 0/9
---TOTAL---
OK: 686/691 Fail: 0/691 Skip: 5/691
OK: 687/692 Fail: 0/692 Skip: 5/692

View File

@ -2022,97 +2022,6 @@ proc publishContributionAndProofs*(
raise (ref ValidatorApiError)(
msg: "Failed to publish sync committee contribution", data: failures)
proc produceBlockV2*(
vc: ValidatorClientRef,
slot: Slot,
randao_reveal: ValidatorSig,
graffiti: GraffitiBytes,
strategy: ApiStrategyKind
): Future[ProduceBlockResponseV2] {.async.} =
const
RequestName = "produceBlockV2"
var failures: seq[ApiNodeFailure]
case strategy
of ApiStrategyKind.First, ApiStrategyKind.Best:
let res = vc.firstSuccessParallel(
RestPlainResponse,
ProduceBlockResponseV2,
SlotDuration,
ViableNodeStatus,
{BeaconNodeRole.BlockProposalData},
produceBlockV2Plain(it, slot, randao_reveal, graffiti)):
if apiResponse.isErr():
handleCommunicationError()
ApiResponse[ProduceBlockResponseV2].err(apiResponse.error)
else:
let response = apiResponse.get()
case response.status:
of 200:
let
version = response.headers.getString("eth-consensus-version")
res = decodeBytes(ProduceBlockResponseV2, response.data,
response.contentType, version)
if res.isErr():
handleUnexpectedData()
ApiResponse[ProduceBlockResponseV2].err($res.error)
else:
ApiResponse[ProduceBlockResponseV2].ok(res.get())
of 400:
handle400()
ApiResponse[ProduceBlockResponseV2].err(ResponseInvalidError)
of 500:
handle500()
ApiResponse[ProduceBlockResponseV2].err(ResponseInternalError)
of 503:
handle503()
ApiResponse[ProduceBlockResponseV2].err(ResponseNoSyncError)
else:
handleUnexpectedCode()
ApiResponse[ProduceBlockResponseV2].err(ResponseUnexpectedError)
if res.isErr():
raise (ref ValidatorApiError)(msg: res.error, data: failures)
return res.get()
of ApiStrategyKind.Priority:
vc.firstSuccessSequential(
RestPlainResponse,
SlotDuration,
ViableNodeStatus,
{BeaconNodeRole.BlockProposalData},
produceBlockV2Plain(it, slot, randao_reveal, graffiti)):
if apiResponse.isErr():
handleCommunicationError()
false
else:
let response = apiResponse.get()
case response.status:
of 200:
let
version = response.headers.getString("eth-consensus-version")
res = decodeBytes(ProduceBlockResponseV2, response.data,
response.contentType, version)
if res.isOk(): return res.get()
handleUnexpectedData()
false
of 400:
handle400()
false
of 500:
handle500()
false
of 503:
handle503()
false
else:
handleUnexpectedCode()
false
raise (ref ValidatorApiError)(
msg: "Failed to produce block", data: failures)
proc produceBlockV3*(
vc: ValidatorClientRef,
slot: Slot,
@ -2161,24 +2070,15 @@ proc produceBlockV3*(
ApiResponse[ProduceBlockResponseV3].ok(res.get())
of 400:
handle400()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
ApiResponse[ProduceBlockResponseV3].err(ResponseInvalidError)
of 404:
# TODO (cheatfate): Remove this handler when produceBlockV2 support
# will be dropped.
handle400()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
ApiResponse[ProduceBlockResponseV3].err(ResponseInvalidError)
of 500:
handle500()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
ApiResponse[ProduceBlockResponseV3].err(ResponseInternalError)
of 503:
handle503()
ApiResponse[ProduceBlockResponseV3].err(ResponseNoSyncError)
else:
handleUnexpectedCode()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
ApiResponse[ProduceBlockResponseV3].err(ResponseUnexpectedError)
if res.isErr():
@ -2216,24 +2116,15 @@ proc produceBlockV3*(
false
of 400:
handle400()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
false
of 404:
# TODO (cheatfate): Remove this handler when produceBlockV2 support
# will be dropped.
handle400()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
false
of 500:
handle500()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
false
of 503:
handle503()
false
else:
handleUnexpectedCode()
node.features.incl(RestBeaconNodeFeature.NoProduceBlockV3)
false
raise (ref ValidatorApiError)(

View File

@ -49,114 +49,6 @@ func shortLog(v: ForkedMaybeBlindedBeaconBlock): auto =
proc proposeBlock(vc: ValidatorClientRef, slot: Slot,
proposerKey: ValidatorPubKey) {.async.}
proc produceBlock(
vc: ValidatorClientRef,
currentSlot, slot: Slot,
randao_reveal: ValidatorSig,
graffiti: GraffitiBytes,
validator: AttachedValidator
): Future[Opt[PreparedBeaconBlock]] {.async.} =
logScope:
slot = slot
wall_slot = currentSlot
validator = validatorLog(validator)
let
produceBlockResponse =
try:
await vc.produceBlockV2(slot, randao_reveal, graffiti,
ApiStrategyKind.Best)
except ValidatorApiError as exc:
warn "Unable to retrieve block data", reason = exc.getFailureReason()
return Opt.none(PreparedBeaconBlock)
except CancelledError as exc:
debug "Block data production has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while getting block data",
error_name = exc.name, error_msg = exc.msg
return Opt.none(PreparedBeaconBlock)
case produceBlockResponse.kind
of ConsensusFork.Phase0:
let blck = produceBlockResponse.phase0Data
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.none(deneb.KzgProofs),
blobsOpt: Opt.none(deneb.Blobs)))
of ConsensusFork.Altair:
let blck = produceBlockResponse.altairData
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.none(deneb.KzgProofs),
blobsOpt: Opt.none(deneb.Blobs)))
of ConsensusFork.Bellatrix:
let blck = produceBlockResponse.bellatrixData
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.none(deneb.KzgProofs),
blobsOpt: Opt.none(deneb.Blobs)))
of ConsensusFork.Capella:
let blck = produceBlockResponse.capellaData
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.none(deneb.KzgProofs),
blobsOpt: Opt.none(deneb.Blobs)))
of ConsensusFork.Deneb:
let
blck = produceBlockResponse.denebData.`block`
kzgProofs = produceBlockResponse.denebData.kzg_proofs
blobs = produceBlockResponse.denebData.blobs
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.some(kzgProofs),
blobsOpt: Opt.some(blobs)))
of ConsensusFork.Electra:
let
blck = produceBlockResponse.electraData.`block`
kzgProofs = produceBlockResponse.electraData.kzg_proofs
blobs = produceBlockResponse.electraData.blobs
return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck),
data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.some(kzgProofs),
blobsOpt: Opt.some(blobs)))
proc produceBlindedBlock(
vc: ValidatorClientRef,
currentSlot, slot: Slot,
randao_reveal: ValidatorSig,
graffiti: GraffitiBytes,
validator: AttachedValidator
): Future[Opt[PreparedBlindedBeaconBlock]] {.async.} =
logScope:
slot = slot
wall_slot = currentSlot
validator = validatorLog(validator)
let
beaconBlock =
try:
await vc.produceBlindedBlock(slot, randao_reveal, graffiti,
ApiStrategyKind.Best)
except ValidatorApiError as exc:
warn "Unable to retrieve blinded block data", error_msg = exc.msg,
reason = exc.getFailureReason()
return Opt.none(PreparedBlindedBeaconBlock)
except CancelledError as exc:
debug "Blinded block data production has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while getting blinded block data",
error_name = exc.name, error_msg = exc.msg
return Opt.none(PreparedBlindedBeaconBlock)
blockRoot = withBlck(beaconBlock): hash_tree_root(forkyBlck)
return Opt.some(
PreparedBlindedBeaconBlock(blockRoot: blockRoot, data: beaconBlock))
proc lazyWait[T](fut: Future[T]) {.async.} =
try:
discard await fut
except CatchableError:
discard
proc prepareRandao(vc: ValidatorClientRef, slot: Slot,
proposerKey: ValidatorPubKey) {.async.} =
if slot == GENESIS_SLOT:
@ -209,21 +101,9 @@ proc spawnProposalTask(vc: ValidatorClientRef,
duty: duty
)
proc isProduceBlockV3Supported(vc: ValidatorClientRef): bool =
let
# Both `statuses` and `roles` should be set to values which are used in
# api.produceBlockV3() call.
statuses = ViableNodeStatus
roles = {BeaconNodeRole.BlockProposalData}
for node in vc.filterNodes(statuses, roles):
if RestBeaconNodeFeature.NoProduceBlockV3 notin node.features:
return true
false
proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
fork: Fork, randaoReveal: ValidatorSig,
validator: AttachedValidator): Future[bool] {.async.} =
validator: AttachedValidator) {.async.} =
let
genesisRoot = vc.beaconGenesis.genesis_validators_root
graffiti =
@ -247,14 +127,14 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
ApiStrategyKind.Best)
except ValidatorApiError as exc:
warn "Unable to retrieve block data", reason = exc.getFailureReason()
return false
return
except CancelledError as exc:
debug "Block data production has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while getting block data",
error_name = exc.name, error_msg = exc.msg
return false
return
withForkyMaybeBlindedBlck(maybeBlock):
when isBlinded:
@ -282,7 +162,7 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
if notSlashable.isErr():
warn "Slashing protection activated for blinded block proposal"
return false
return
let signature =
try:
@ -292,7 +172,7 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
if res.isErr():
warn "Unable to sign blinded block proposal using remote signer",
reason = res.error()
return false
return
res.get()
except CancelledError as exc:
debug "Blinded block signature process has been interrupted"
@ -300,7 +180,7 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
except CatchableError as exc:
error "An unexpected error occurred while signing blinded block",
error_name = exc.name, error_msg = exc.msg
return false
return
let
signedBlock =
@ -313,7 +193,7 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
except ValidatorApiError as exc:
warn "Unable to publish blinded block",
reason = exc.getFailureReason()
return false
return
except CancelledError as exc:
debug "Blinded block publication has been interrupted"
raise exc
@ -321,17 +201,15 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
error "An unexpected error occurred while publishing blinded " &
"block",
error_name = exc.name, error_msg = exc.msg
return false
return
if res:
let delay = vc.getDelay(slot.block_deadline())
beacon_blocks_sent.inc()
beacon_blocks_sent_delay.observe(delay.toFloatSeconds())
notice "Blinded block published", delay = delay
true
else:
warn "Blinded block was not accepted by beacon node"
false
else:
let
blockRoot = hash_tree_root(
@ -367,7 +245,7 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
if notSlashable.isErr():
warn "Slashing protection activated for block proposal"
return false
return
let
signature =
@ -377,7 +255,7 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
if res.isErr():
warn "Unable to sign block proposal using remote signer",
reason = res.error()
return false
return
res.get()
except CancelledError as exc:
debug "Block signature process has been interrupted"
@ -385,240 +263,12 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
except CatchableError as exc:
error "An unexpected error occurred while signing block",
error_name = exc.name, error_msg = exc.msg
return false
return
signedBlockContents =
RestPublishedSignedBlockContents.init(
forkyMaybeBlindedBlck, blockRoot, signature)
res =
try:
debug "Sending block"
await vc.publishBlock(signedBlockContents, ApiStrategyKind.First)
except ValidatorApiError as exc:
warn "Unable to publish block", reason = exc.getFailureReason()
return false
except CancelledError as exc:
debug "Block publication has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while publishing block",
error_name = exc.name, error_msg = exc.msg
return false
if res:
let delay = vc.getDelay(slot.block_deadline())
beacon_blocks_sent.inc()
beacon_blocks_sent_delay.observe(delay.toFloatSeconds())
notice "Block published", delay = delay
true
else:
warn "Block was not accepted by beacon node"
false
proc publishBlockV2(vc: ValidatorClientRef, currentSlot, slot: Slot,
fork: Fork, randaoReveal: ValidatorSig,
validator: AttachedValidator) {.async.} =
let
genesisRoot = vc.beaconGenesis.genesis_validators_root
graffiti = vc.getGraffitiBytes(validator)
vindex = validator.index.get()
logScope:
validator = validatorLog(validator)
validator_index = vindex
slot = slot
wall_slot = currentSlot
var beaconBlocks =
block:
let blindedBlockFut =
if vc.config.payloadBuilderEnable:
vc.produceBlindedBlock(currentSlot, slot, randaoReveal, graffiti,
validator)
else:
nil
let normalBlockFut = vc.produceBlock(currentSlot, slot, randaoReveal,
graffiti, validator)
let blindedBlock =
if isNil(blindedBlockFut):
Opt.none(PreparedBlindedBeaconBlock)
else:
try:
await blindedBlockFut
except CancelledError as exc:
if not(normalBlockFut.finished()):
await normalBlockFut.cancelAndWait()
raise exc
except CatchableError:
# This should not happen, because all the exceptions are handled.
Opt.none(PreparedBlindedBeaconBlock)
let normalBlock =
if blindedBlock.isNone():
try:
await normalBlockFut
except CancelledError as exc:
raise exc
except CatchableError:
# This should not happen, because all the exceptions are handled.
Opt.none(PreparedBeaconBlock)
else:
if not(normalBlockFut.finished()):
asyncSpawn lazyWait(normalBlockFut)
Opt.none(PreparedBeaconBlock)
if blindedBlock.isNone() and normalBlock.isNone():
return
(blindedBlock: blindedBlock, normalBlock: normalBlock)
if beaconBlocks.blindedBlock.isSome():
let
preparedBlock = beaconBlocks.blindedBlock.get()
signingRoot = compute_block_signing_root(fork, genesisRoot, slot,
preparedBlock.blockRoot)
notSlashable = vc.attachedValidators[]
.slashingProtection
.registerBlock(vindex, validator.pubkey, slot, signingRoot)
logScope:
blck = shortLog(preparedBlock.data)
block_root = shortLog(preparedBlock.blockRoot)
signing_root = shortLog(signingRoot)
if notSlashable.isOk():
let
signature =
try:
let res = await validator.getBlockSignature(fork, genesisRoot,
slot,
preparedBlock.blockRoot,
preparedBlock.data)
if res.isErr():
warn "Unable to sign blinded block proposal using remote signer",
reason = res.error()
return
res.get()
except CancelledError as exc:
debug "Blinded block signature process has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while signing blinded block",
error_name = exc.name, error_msg = exc.msg
return
logScope:
signature = shortLog(signature)
let
signedBlock = ForkedSignedBlindedBeaconBlock.init(preparedBlock.data,
preparedBlock.blockRoot, signature)
res =
try:
debug "Sending blinded block"
await vc.publishBlindedBlock(signedBlock, ApiStrategyKind.First)
except ValidatorApiError as exc:
warn "Unable to publish blinded block",
reason = exc.getFailureReason()
return
except CancelledError as exc:
debug "Blinded block publication has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while publishing blinded block",
error_name = exc.name, error_msg = exc.msg
return
if res:
let delay = vc.getDelay(slot.block_deadline())
beacon_blocks_sent.inc()
beacon_blocks_sent_delay.observe(delay.toFloatSeconds())
notice "Blinded block published", delay = delay
else:
warn "Blinded block was not accepted by beacon node"
else:
warn "Slashing protection activated for blinded block proposal"
else:
let
preparedBlock = beaconBlocks.normalBlock.get()
signingRoot = compute_block_signing_root(fork, genesisRoot, slot,
preparedBlock.blockRoot)
notSlashable = vc.attachedValidators[]
.slashingProtection
.registerBlock(vindex, validator.pubkey, slot, signingRoot)
logScope:
blck = shortLog(preparedBlock.data)
block_root = shortLog(preparedBlock.blockRoot)
signing_root = shortLog(signingRoot)
if notSlashable.isOk():
let
signature =
try:
let res = await validator.getBlockSignature(fork,
genesisRoot, slot,
preparedBlock.blockRoot,
preparedBlock.data)
if res.isErr():
warn "Unable to sign block proposal using remote signer",
reason = res.error()
return
res.get()
except CancelledError as exc:
debug "Block signature process has been interrupted"
raise exc
except CatchableError as exc:
error "An unexpected error occurred while signing block",
error_name = exc.name, error_msg = exc.msg
return
signedBlockContents =
case preparedBlock.data.kind
of ConsensusFork.Phase0:
RestPublishedSignedBlockContents(kind: ConsensusFork.Phase0,
phase0Data: phase0.SignedBeaconBlock(
message: preparedBlock.data.phase0Data,
root: preparedBlock.blockRoot,
signature: signature))
of ConsensusFork.Altair:
RestPublishedSignedBlockContents(kind: ConsensusFork.Altair,
altairData: altair.SignedBeaconBlock(
message: preparedBlock.data.altairData,
root: preparedBlock.blockRoot,
signature: signature))
of ConsensusFork.Bellatrix:
RestPublishedSignedBlockContents(kind: ConsensusFork.Bellatrix,
bellatrixData: bellatrix.SignedBeaconBlock(
message: preparedBlock.data.bellatrixData,
root: preparedBlock.blockRoot,
signature: signature))
of ConsensusFork.Capella:
RestPublishedSignedBlockContents(kind: ConsensusFork.Capella,
capellaData: capella.SignedBeaconBlock(
message: preparedBlock.data.capellaData,
root: preparedBlock.blockRoot,
signature: signature))
of ConsensusFork.Deneb:
RestPublishedSignedBlockContents(kind: ConsensusFork.Deneb,
denebData: DenebSignedBlockContents(
signed_block: deneb.SignedBeaconBlock(
message: preparedBlock.data.denebData,
root: preparedBlock.blockRoot,
signature: signature),
kzg_proofs: preparedBlock.kzgProofsOpt.get,
blobs: preparedBlock.blobsOpt.get))
of ConsensusFork.Electra:
RestPublishedSignedBlockContents(kind: ConsensusFork.Electra,
electraData: ElectraSignedBlockContents(
signed_block: electra.SignedBeaconBlock(
message: preparedBlock.data.electraData,
root: preparedBlock.blockRoot,
signature: signature),
kzg_proofs: preparedBlock.kzgProofsOpt.get,
blobs: preparedBlock.blobsOpt.get))
res =
try:
debug "Sending block"
@ -641,8 +291,6 @@ proc publishBlockV2(vc: ValidatorClientRef, currentSlot, slot: Slot,
notice "Block published", delay = delay
else:
warn "Block was not accepted by beacon node"
else:
warn "Slashing protection activated for block proposal"
proc publishBlock(vc: ValidatorClientRef, currentSlot, slot: Slot,
validator: AttachedValidator) {.async.} =
@ -677,18 +325,7 @@ proc publishBlock(vc: ValidatorClientRef, currentSlot, slot: Slot,
error_name = exc.name, error_msg = exc.msg
return
# TODO (cheatfate): This branch should be removed as soon as `produceBlockV2`
# call will be fully deprecated.
if vc.isProduceBlockV3Supported():
# We call `V3` first, if call fails and `isProduceBlockV3Supported()`
# did not find any nodes which support `V3` we try to call `V2`.
let res =
await vc.publishBlockV3(currentSlot, slot, fork, randaoReveal, validator)
if not(res) and not(vc.isProduceBlockV3Supported()):
notice "Block production using V3 failed, trying V2"
await vc.publishBlockV2(currentSlot, slot, fork, randaoReveal, validator)
else:
await vc.publishBlockV2(currentSlot, slot, fork, randaoReveal, validator)
await vc.publishBlockV3(currentSlot, slot, fork, randaoReveal, validator)
proc proposeBlock(vc: ValidatorClientRef, slot: Slot,
proposerKey: ValidatorPubKey) {.async.} =

View File

@ -117,7 +117,6 @@ type
RestBeaconNodeFeature* {.pure.} = enum
NoNimbusExtensions, ## BN does not support Nimbus Extensions
NoProduceBlockV3 ## BN does not support produceBlockV3 call
TimeOffset* = object
value: int64