can finalize successfully with external VCs! + some other cleanup
This commit is contained in:
parent
06873abde3
commit
e7febc2e2b
|
@ -26,7 +26,10 @@ proc post_v1_beacon_blocks(body: SignedBeaconBlock): bool
|
|||
|
||||
proc get_v1_validator_attestation_data(slot: Slot, committee_index: CommitteeIndex): AttestationData
|
||||
|
||||
proc get_v1_validator_aggregate_attestation(attestation_data_root: Eth2Digest): Attestation
|
||||
# TODO at the time of writing (10.06.2020) the API specifies this call to have a hash of
|
||||
# the attestation data instead of the object itself but we also need the slot.. see here:
|
||||
# https://docs.google.com/spreadsheets/d/1kVIx6GvzVLwNYbcd-Fj8YUlPf4qGrWUlS35uaTnIAVg/edit?disco=AAAAGh7r_fQ
|
||||
proc get_v1_validator_aggregate_attestation(attestation_data: AttestationData): Attestation
|
||||
|
||||
# TODO returns a bool even though in the API there is no return type - because of nim-json-rpc
|
||||
proc post_v1_validator_aggregate_and_proof(payload: SignedAggregateAndProof): bool
|
||||
|
|
|
@ -232,16 +232,6 @@ func get_beacon_proposer_index*(state: BeaconState, cache: var StateCache):
|
|||
Option[ValidatorIndex] =
|
||||
get_beacon_proposer_index(state, cache, state.slot)
|
||||
|
||||
# Not from spec
|
||||
# TODO: cache the results from this and reuse in subsequent calls to get_beacon_proposer_index
|
||||
func get_beacon_proposer_indexes_for_epoch*(state: BeaconState, epoch: Epoch,
|
||||
stateCache: var StateCache): seq[tuple[s: Slot, i: ValidatorIndex]] =
|
||||
for i in 0 ..< SLOTS_PER_EPOCH:
|
||||
let currSlot = (compute_start_slot_at_epoch(epoch).int + i).Slot
|
||||
let idx = get_beacon_proposer_index(state, stateCache, currSlot)
|
||||
if idx.isSome:
|
||||
result.add (currSlot, idx.get)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.3/specs/phase0/validator.md#validator-assignments
|
||||
func get_committee_assignment*(
|
||||
state: BeaconState, epoch: Epoch, validator_index: ValidatorIndex):
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import
|
||||
# Standard library
|
||||
tables, strutils, sequtils,
|
||||
tables, strutils,
|
||||
|
||||
# Nimble packages
|
||||
stew/[objects],
|
||||
|
@ -15,7 +15,7 @@ import
|
|||
chronicles,
|
||||
|
||||
# Local modules
|
||||
spec/[datatypes, digest, crypto, validator, beaconstate],
|
||||
spec/[datatypes, digest, crypto, validator, beaconstate, helpers],
|
||||
block_pool, ssz/merkleization,
|
||||
beacon_node_common, beacon_node_types,
|
||||
validator_duties, eth2_network,
|
||||
|
@ -25,6 +25,8 @@ import
|
|||
type
|
||||
RpcServer* = RpcHttpServer
|
||||
|
||||
logScope: topics = "valapi"
|
||||
|
||||
proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) =
|
||||
|
||||
# TODO Probably the `beacon` ones (and not `validator`) should be defined elsewhere...
|
||||
|
@ -75,9 +77,7 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) =
|
|||
node, valInfo, proposer.get()[0], graffiti, head, slot)
|
||||
|
||||
# TODO how do we handle the case when we cannot return a meaningful block? 404...
|
||||
# currently this fails often - perhaps because the block has already been
|
||||
# processed and signed with the inProcess validator...
|
||||
# doAssert(res.message.isSome())
|
||||
doAssert(res.message.isSome())
|
||||
return res.message.get(BeaconBlock()) # returning a default if empty
|
||||
|
||||
rpcServer.rpc("post_v1_beacon_blocks") do (body: SignedBeaconBlock) -> bool:
|
||||
|
@ -106,13 +106,13 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) =
|
|||
return makeAttestationData(state, slot, committee_index.uint64, blck.root)
|
||||
|
||||
rpcServer.rpc("get_v1_validator_aggregate_attestation") do (
|
||||
attestation_data_root: Eth2Digest)-> Attestation:
|
||||
attestation_data: AttestationData)-> Attestation:
|
||||
notice "== get_v1_validator_aggregate_attestation"
|
||||
# TODO look at attestation.data.beacon_block_root
|
||||
|
||||
rpcServer.rpc("post_v1_validator_aggregate_and_proof") do (
|
||||
payload: SignedAggregateAndProof) -> bool:
|
||||
notice "== post_v1_validator_aggregate_and_proof"
|
||||
# TODO is this enough?
|
||||
node.network.broadcast(node.topicAggregateAndProofs, payload)
|
||||
return true
|
||||
|
||||
|
@ -137,15 +137,15 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) =
|
|||
rpcServer.rpc("get_v1_validator_duties_proposer") do (
|
||||
epoch: Epoch) -> seq[ValidatorPubkeySlotPair]:
|
||||
notice "== get_v1_validator_duties_proposer", epoch = epoch
|
||||
discard node.updateHead() # TODO do we need this?
|
||||
var cache = get_empty_per_epoch_cache()
|
||||
result = get_beacon_proposer_indexes_for_epoch(node.blockPool.headState.data.data,
|
||||
epoch, cache).mapIt(ValidatorPubkeySlotPair(
|
||||
public_key: node.blockPool.headState.data.data.validators[it.i].pubkey,
|
||||
slot: it.s
|
||||
))
|
||||
let head = node.updateHead()
|
||||
for i in 0 ..< SLOTS_PER_EPOCH:
|
||||
let currSlot = (compute_start_slot_at_epoch(epoch).int + i).Slot
|
||||
let proposer = node.blockPool.getProposer(head, currSlot)
|
||||
if proposer.isSome():
|
||||
result.add(ValidatorPubkeySlotPair(public_key: proposer.get()[1], slot: currSlot))
|
||||
|
||||
rpcServer.rpc("post_v1_validator_beacon_committee_subscription") do (
|
||||
committee_index: CommitteeIndex, slot: Slot, aggregator: bool,
|
||||
validator_pubkey: ValidatorPubKey, slot_signature: ValidatorSig):
|
||||
notice "== post_v1_validator_beacon_committee_subscription"
|
||||
# TODO
|
||||
|
|
|
@ -25,6 +25,8 @@ import
|
|||
spec/eth2_apis/validator_callsigs_types,
|
||||
eth2_json_rpc_serialization
|
||||
|
||||
logScope: topics = "vc"
|
||||
|
||||
template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0]
|
||||
|
||||
## Generate client convenience marshalling wrappers from forward declarations
|
||||
|
@ -41,11 +43,6 @@ type
|
|||
attestationsForEpoch: Table[Slot, seq[AttesterDuties]]
|
||||
beaconGenesis: BeaconGenesisTuple
|
||||
|
||||
# TODO remove this and move to real logging once done experimenting - it's much
|
||||
# easier to distinguish such output from the one from chronicles with timestamps
|
||||
proc port_logged(vc: ValidatorClient, msg: string) =
|
||||
echo "== ", vc.config.rpcPort, " ", msg
|
||||
|
||||
proc getValidatorDutiesForEpoch(vc: ValidatorClient, epoch: Epoch) {.gcsafe, async.} =
|
||||
let proposals = await vc.client.get_v1_validator_duties_proposer(epoch)
|
||||
# update the block proposal duties this VC should do during this epoch
|
||||
|
@ -80,7 +77,12 @@ proc onSlotStart(vc: ValidatorClient, lastSlot, scheduledSlot: Slot) {.gcsafe, a
|
|||
slot = wallSlot.slot # afterGenesis == true!
|
||||
nextSlot = slot + 1
|
||||
|
||||
vc.port_logged "WAKE UP! scheduledSlot " & $scheduledSlot & " slot " & $slot
|
||||
info "Slot start",
|
||||
lastSlot = shortLog(lastSlot),
|
||||
scheduledSlot = shortLog(scheduledSlot),
|
||||
beaconTime = shortLog(beaconTime),
|
||||
portBN = vc.config.rpcPort,
|
||||
cat = "scheduling"
|
||||
|
||||
try:
|
||||
# at the start of each epoch - request all validator duties
|
||||
|
@ -138,8 +140,22 @@ proc onSlotStart(vc: ValidatorClient, lastSlot, scheduledSlot: Slot) {.gcsafe, a
|
|||
let
|
||||
nextSlotStart = saturate(vc.beaconClock.fromNow(nextSlot))
|
||||
|
||||
# it's much easier to wake up on every slot compared to scheduling the start of each
|
||||
# epoch and only the precise slots when the VC should sign/propose/attest with a key
|
||||
info "Slot end",
|
||||
slot = shortLog(slot),
|
||||
nextSlot = shortLog(nextSlot),
|
||||
portBN = vc.config.rpcPort,
|
||||
cat = "scheduling"
|
||||
|
||||
when declared(GC_fullCollect):
|
||||
# The slots in the validator client work as frames in a game: we want to make
|
||||
# sure that we're ready for the next one and don't get stuck in lengthy
|
||||
# garbage collection tasks when time is of essence in the middle of a slot -
|
||||
# while this does not guarantee that we'll never collect during a slot, it
|
||||
# makes sure that all the scratch space we used during slot tasks (logging,
|
||||
# temporary buffers etc) gets recycled for the next slot that is likely to
|
||||
# need similar amounts of memory.
|
||||
GC_fullCollect()
|
||||
|
||||
addTimer(nextSlotStart) do (p: pointer):
|
||||
asyncCheck vc.onSlotStart(slot, nextSlot)
|
||||
|
||||
|
|
Loading…
Reference in New Issue