69 lines
2.6 KiB
Nim
69 lines
2.6 KiB
Nim
import
|
|
std/[strutils, parseutils],
|
|
stew/byteutils,
|
|
../beacon_node_common, ../validator_duties,
|
|
../block_pools/[block_pools_types, chain_dag],
|
|
../spec/[datatypes, digest, helpers]
|
|
|
|
export chain_dag
|
|
|
|
template withStateForStateId*(stateId: string, body: untyped): untyped =
|
|
# TODO this can be optimized for the "head" case since that should be most common
|
|
node.chainDag.withState(node.chainDag.tmpState,
|
|
node.stateIdToBlockSlot(stateId)):
|
|
body
|
|
|
|
proc toBlockSlot*(blckRef: BlockRef): BlockSlot =
|
|
blckRef.atSlot(blckRef.slot)
|
|
|
|
proc parseRoot*(str: string): Eth2Digest =
|
|
return Eth2Digest(data: hexToByteArray[32](str))
|
|
|
|
func checkEpochToSlotOverflow*(epoch: Epoch) =
|
|
const maxEpoch = compute_epoch_at_slot(not 0'u64)
|
|
if epoch >= maxEpoch:
|
|
raise newException(
|
|
ValueError, "Requesting epoch for which slot would overflow")
|
|
|
|
proc doChecksAndGetCurrentHead*(node: BeaconNode, slot: Slot): BlockRef =
|
|
result = node.chainDag.head
|
|
if not node.isSynced(result):
|
|
raise newException(CatchableError, "Cannot fulfill request until node is synced")
|
|
# TODO for now we limit the requests arbitrarily by up to 2 epochs into the future
|
|
if result.slot + uint64(2 * SLOTS_PER_EPOCH) < slot:
|
|
raise newException(CatchableError, "Requesting way ahead of the current head")
|
|
|
|
proc doChecksAndGetCurrentHead*(node: BeaconNode, epoch: Epoch): BlockRef =
|
|
checkEpochToSlotOverflow(epoch)
|
|
node.doChecksAndGetCurrentHead(epoch.compute_start_slot_at_epoch)
|
|
|
|
proc getBlockSlotFromString*(node: BeaconNode, slot: string): BlockSlot =
|
|
if slot.len == 0:
|
|
raise newException(ValueError, "Empty slot number not allowed")
|
|
var parsed: BiggestUInt
|
|
if parseBiggestUInt(slot, parsed) != slot.len:
|
|
raise newException(ValueError, "Not a valid slot number")
|
|
let head = node.doChecksAndGetCurrentHead(parsed.Slot)
|
|
return head.atSlot(parsed.Slot)
|
|
|
|
proc stateIdToBlockSlot*(node: BeaconNode, stateId: string): BlockSlot =
|
|
result = case stateId:
|
|
of "head":
|
|
node.chainDag.head.toBlockSlot()
|
|
of "genesis":
|
|
node.chainDag.getGenesisBlockSlot()
|
|
of "finalized":
|
|
node.chainDag.finalizedHead
|
|
of "justified":
|
|
node.chainDag.head.atEpochStart(
|
|
node.chainDag.headState.data.data.current_justified_checkpoint.epoch)
|
|
else:
|
|
if stateId.startsWith("0x"):
|
|
let blckRoot = parseRoot(stateId)
|
|
let blckRef = node.chainDag.getRef(blckRoot)
|
|
if blckRef.isNil:
|
|
raise newException(CatchableError, "Block not found")
|
|
blckRef.toBlockSlot()
|
|
else:
|
|
node.getBlockSlotFromString(stateId)
|