refactor BN engine/builder block selection to work as REST block v3 backend
This commit is contained in:
parent
93d82e2892
commit
87777cf158
|
@ -97,6 +97,11 @@ type
|
||||||
blobsBundleOpt: Opt[BlobsBundle]], string]
|
blobsBundleOpt: Opt[BlobsBundle]], string]
|
||||||
BlindedBlockResult[SBBB] =
|
BlindedBlockResult[SBBB] =
|
||||||
Result[tuple[blindedBlckPart: SBBB, blockValue: UInt256], string]
|
Result[tuple[blindedBlckPart: SBBB, blockValue: UInt256], string]
|
||||||
|
BlockProposalBidFutures[SBBB] = object
|
||||||
|
engineBidAvailable: bool
|
||||||
|
engineBlockFut: Future[ForkedBlockResult]
|
||||||
|
builderBidAvailable: bool
|
||||||
|
payloadBuilderBidFut: Future[BlindedBlockResult[SBBB]]
|
||||||
|
|
||||||
proc getValidator*(validators: auto,
|
proc getValidator*(validators: auto,
|
||||||
pubkey: ValidatorPubKey): Opt[ValidatorAndIndex] =
|
pubkey: ValidatorPubKey): Opt[ValidatorAndIndex] =
|
||||||
|
@ -800,22 +805,13 @@ proc makeBlindedBeaconBlockForHeadAndSlot*[
|
||||||
else:
|
else:
|
||||||
return err("Attempt to create pre-Bellatrix blinded block")
|
return err("Attempt to create pre-Bellatrix blinded block")
|
||||||
|
|
||||||
proc proposeBlockAux(
|
proc collectBidFutures(
|
||||||
SBBB: typedesc, EPS: typedesc, node: BeaconNode,
|
SBBB: typedesc, EPS: typedesc, node: BeaconNode,
|
||||||
validator: AttachedValidator, validator_index: ValidatorIndex,
|
payloadBuilderClient: RestClientRef, validator: AttachedValidator,
|
||||||
head: BlockRef, slot: Slot, randao: ValidatorSig, fork: Fork,
|
validator_index: ValidatorIndex, head: BlockRef, slot: Slot,
|
||||||
genesis_validators_root: Eth2Digest,
|
randao: ValidatorSig): Future[BlockProposalBidFutures[SBBB]] {.async.} =
|
||||||
localBlockValueBoost: uint8): Future[BlockRef] {.async.} =
|
|
||||||
# Collect bids
|
|
||||||
var payloadBuilderClient: RestClientRef
|
|
||||||
|
|
||||||
let payloadBuilderClientMaybe = node.getPayloadBuilderClient(
|
|
||||||
validator_index.distinctBase)
|
|
||||||
if payloadBuilderClientMaybe.isOk:
|
|
||||||
payloadBuilderClient = payloadBuilderClientMaybe.get
|
|
||||||
|
|
||||||
let usePayloadBuilder =
|
let usePayloadBuilder =
|
||||||
if payloadBuilderClientMaybe.isOk:
|
if not payloadBuilderClient.isNil:
|
||||||
withState(node.dag.headState):
|
withState(node.dag.headState):
|
||||||
# Head slot, not proposal slot, matters here
|
# Head slot, not proposal slot, matters here
|
||||||
# TODO it might make some sense to allow use of builder API if local
|
# TODO it might make some sense to allow use of builder API if local
|
||||||
|
@ -886,26 +882,50 @@ proc proposeBlockAux(
|
||||||
err = engineBlockFut.error.msg
|
err = engineBlockFut.error.msg
|
||||||
false
|
false
|
||||||
|
|
||||||
template builderBetterBid(builderValue: UInt256, engineValue: Wei): bool =
|
return BlockProposalBidFutures[SBBB](
|
||||||
# Scale down to ensure no overflows; if lower few bits would have been
|
engineBidAvailable: engineBidAvailable,
|
||||||
# otherwise decisive, was close enough not to matter. Calibrate to let
|
engineBlockFut: engineBlockFut,
|
||||||
# uint8-range percentages avoid overflowing.
|
builderBidAvailable: builderBidAvailable,
|
||||||
const scalingBits = 10
|
payloadBuilderBidFut: payloadBuilderBidFut)
|
||||||
static: doAssert 1 shl scalingBits >
|
|
||||||
high(typeof(localBlockValueBoost)).uint16 + 100
|
func builderBetterBid(
|
||||||
let
|
localBlockValueBoost: uint8, builderValue: UInt256, engineValue: Wei): bool =
|
||||||
scaledBuilderValue = (builderValue shr scalingBits) * 100
|
# Scale down to ensure no overflows; if lower few bits would have been
|
||||||
scaledEngineValue = engineValue shr scalingBits
|
# otherwise decisive, was close enough not to matter. Calibrate to let
|
||||||
scaledBuilderValue >
|
# uint8-range percentages avoid overflowing.
|
||||||
scaledEngineValue * (localBlockValueBoost.uint16 + 100).u256
|
const scalingBits = 10
|
||||||
|
static: doAssert 1 shl scalingBits >
|
||||||
|
high(typeof(localBlockValueBoost)).uint16 + 100
|
||||||
|
let
|
||||||
|
scaledBuilderValue = (builderValue shr scalingBits) * 100
|
||||||
|
scaledEngineValue = engineValue shr scalingBits
|
||||||
|
scaledBuilderValue >
|
||||||
|
scaledEngineValue * (localBlockValueBoost.uint16 + 100).u256
|
||||||
|
|
||||||
|
proc proposeBlockAux(
|
||||||
|
SBBB: typedesc, EPS: typedesc, node: BeaconNode,
|
||||||
|
validator: AttachedValidator, validator_index: ValidatorIndex,
|
||||||
|
head: BlockRef, slot: Slot, randao: ValidatorSig, fork: Fork,
|
||||||
|
genesis_validators_root: Eth2Digest,
|
||||||
|
localBlockValueBoost: uint8): Future[BlockRef] {.async.} =
|
||||||
|
var payloadBuilderClient: RestClientRef
|
||||||
|
let payloadBuilderClientMaybe = node.getPayloadBuilderClient(
|
||||||
|
validator_index.distinctBase)
|
||||||
|
if payloadBuilderClientMaybe.isOk:
|
||||||
|
payloadBuilderClient = payloadBuilderClientMaybe.get
|
||||||
|
|
||||||
|
let collectedBids = await collectBidFutures(
|
||||||
|
SBBB, EPS, node, payloadBuilderClient, validator, validator_index, head,
|
||||||
|
slot, randao)
|
||||||
|
|
||||||
let useBuilderBlock =
|
let useBuilderBlock =
|
||||||
if builderBidAvailable:
|
if collectedBids.builderBidAvailable:
|
||||||
(not engineBidAvailable) or builderBetterBid(
|
(not collectedBids.engineBidAvailable) or builderBetterBid(
|
||||||
payloadBuilderBidFut.read.get().blockValue,
|
localBlockValueBoost,
|
||||||
engineBlockFut.read.get().blockValue)
|
collectedBids.payloadBuilderBidFut.read.get().blockValue,
|
||||||
|
collectedBids.engineBlockFut.read.get().blockValue)
|
||||||
else:
|
else:
|
||||||
if not engineBidAvailable:
|
if not collectedBids.engineBidAvailable:
|
||||||
return head # errors logged in router
|
return head # errors logged in router
|
||||||
false
|
false
|
||||||
|
|
||||||
|
@ -913,7 +933,7 @@ proc proposeBlockAux(
|
||||||
let
|
let
|
||||||
blindedBlock = (await blindedBlockCheckSlashingAndSign(
|
blindedBlock = (await blindedBlockCheckSlashingAndSign(
|
||||||
node, slot, validator, validator_index,
|
node, slot, validator, validator_index,
|
||||||
payloadBuilderBidFut.read.get.blindedBlckPart)).valueOr:
|
collectedBids.payloadBuilderBidFut.read.get.blindedBlckPart)).valueOr:
|
||||||
return head
|
return head
|
||||||
# Before proposeBlockMEV, can fall back to EL; after, cannot without
|
# Before proposeBlockMEV, can fall back to EL; after, cannot without
|
||||||
# risking slashing.
|
# risking slashing.
|
||||||
|
@ -929,7 +949,7 @@ proc proposeBlockAux(
|
||||||
beacon_block_builder_missed_without_fallback.inc()
|
beacon_block_builder_missed_without_fallback.inc()
|
||||||
return head
|
return head
|
||||||
|
|
||||||
var forkedBlck = engineBlockFut.read.get().blck
|
var forkedBlck = collectedBids.engineBlockFut.read.get().blck
|
||||||
|
|
||||||
withBlck(forkedBlck):
|
withBlck(forkedBlck):
|
||||||
let
|
let
|
||||||
|
@ -944,7 +964,7 @@ proc proposeBlockAux(
|
||||||
let blobSidecarsOpt =
|
let blobSidecarsOpt =
|
||||||
when blck is deneb.BeaconBlock:
|
when blck is deneb.BeaconBlock:
|
||||||
var sidecars: seq[BlobSidecar]
|
var sidecars: seq[BlobSidecar]
|
||||||
let bundle = engineBlockFut.read.get().blobsBundleOpt.get()
|
let bundle = collectedBids.engineBlockFut.read.get().blobsBundleOpt.get
|
||||||
let (blobs, kzgs, proofs) = (bundle.blobs, bundle.kzgs, bundle.proofs)
|
let (blobs, kzgs, proofs) = (bundle.blobs, bundle.kzgs, bundle.proofs)
|
||||||
for i in 0..<blobs.len:
|
for i in 0..<blobs.len:
|
||||||
var sidecar = BlobSidecar(
|
var sidecar = BlobSidecar(
|
||||||
|
|
Loading…
Reference in New Issue