2022-06-09 08:50:36 +00:00
|
|
|
# beacon_chain
|
2023-05-02 11:54:44 +00:00
|
|
|
# Copyright (c) 2022-2023 Status Research & Development GmbH
|
2022-06-09 08:50:36 +00:00
|
|
|
# Licensed and distributed under either of
|
|
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
|
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
|
2022-05-10 10:03:40 +00:00
|
|
|
import
|
2022-06-09 08:50:36 +00:00
|
|
|
std/sets,
|
2022-07-29 08:36:20 +00:00
|
|
|
metrics, chronicles,
|
2022-05-10 10:03:40 +00:00
|
|
|
../spec/datatypes/[phase0, altair, bellatrix],
|
2022-08-19 10:30:07 +00:00
|
|
|
../spec/eth2_apis/rest_types,
|
|
|
|
../validators/activity_metrics,
|
|
|
|
"."/[common, api, block_service]
|
2022-05-10 10:03:40 +00:00
|
|
|
|
2022-07-14 21:11:25 +00:00
|
|
|
const
|
|
|
|
ServiceName = "sync_committee_service"
|
|
|
|
|
|
|
|
logScope: service = ServiceName
|
2022-07-13 14:43:57 +00:00
|
|
|
|
2022-05-10 10:03:40 +00:00
|
|
|
type
|
|
|
|
ContributionItem* = object
|
|
|
|
aggregator_index: uint64
|
|
|
|
selection_proof: ValidatorSig
|
|
|
|
validator: AttachedValidator
|
|
|
|
subcommitteeIdx: SyncSubcommitteeIndex
|
|
|
|
|
|
|
|
proc serveSyncCommitteeMessage*(service: SyncCommitteeServiceRef,
|
2022-07-13 14:43:57 +00:00
|
|
|
slot: Slot, beaconBlockRoot: Eth2Digest,
|
2022-11-24 07:46:35 +00:00
|
|
|
duty: SyncCommitteeDuty): Future[bool] {.
|
2022-07-13 14:43:57 +00:00
|
|
|
async.} =
|
2022-05-10 10:03:40 +00:00
|
|
|
let
|
|
|
|
vc = service.client
|
|
|
|
fork = vc.forkAtEpoch(slot.epoch)
|
|
|
|
genesisValidatorsRoot = vc.beaconGenesis.genesis_validators_root
|
2022-11-24 07:46:35 +00:00
|
|
|
vindex = duty.validator_index
|
2022-07-13 14:43:57 +00:00
|
|
|
subcommitteeIdx = getSubcommitteeIndex(
|
2022-11-24 07:46:35 +00:00
|
|
|
duty.validator_sync_committee_index)
|
2023-02-20 11:28:56 +00:00
|
|
|
validator = vc.getValidatorForDuties(
|
|
|
|
duty.pubkey, slot, slashingSafe = true).valueOr: return false
|
2022-05-10 10:03:40 +00:00
|
|
|
message =
|
|
|
|
block:
|
2022-06-29 16:53:59 +00:00
|
|
|
let res = await getSyncCommitteeMessage(validator, fork,
|
|
|
|
genesisValidatorsRoot,
|
|
|
|
slot, beaconBlockRoot)
|
2022-05-10 10:03:40 +00:00
|
|
|
if res.isErr():
|
2023-03-03 20:20:01 +00:00
|
|
|
warn "Unable to sign committee message using remote signer",
|
|
|
|
validator = shortLog(validator), slot = slot,
|
|
|
|
block_root = shortLog(beaconBlockRoot)
|
2022-05-10 10:03:40 +00:00
|
|
|
return
|
|
|
|
res.get()
|
|
|
|
|
|
|
|
debug "Sending sync committee message", message = shortLog(message),
|
|
|
|
validator = shortLog(validator), validator_index = vindex,
|
|
|
|
delay = vc.getDelay(message.slot.sync_committee_message_deadline())
|
|
|
|
|
|
|
|
let res =
|
|
|
|
try:
|
2022-09-29 07:57:14 +00:00
|
|
|
await vc.submitPoolSyncCommitteeSignature(message, ApiStrategyKind.First)
|
2023-02-23 00:11:00 +00:00
|
|
|
except ValidatorApiError as exc:
|
2023-03-03 20:20:01 +00:00
|
|
|
warn "Unable to publish sync committee message",
|
|
|
|
message = shortLog(message),
|
|
|
|
validator = shortLog(validator),
|
|
|
|
validator_index = vindex,
|
|
|
|
reason = exc.getFailureReason()
|
2022-05-10 10:03:40 +00:00
|
|
|
return false
|
2022-07-13 14:43:57 +00:00
|
|
|
except CancelledError:
|
|
|
|
debug "Publish sync committee message request was interrupted"
|
|
|
|
return false
|
2022-05-10 10:03:40 +00:00
|
|
|
except CatchableError as exc:
|
|
|
|
error "Unexpected error occurred while publishing sync committee message",
|
|
|
|
message = shortLog(message),
|
|
|
|
validator = shortLog(validator),
|
|
|
|
validator_index = vindex,
|
|
|
|
err_name = exc.name, err_msg = exc.msg
|
|
|
|
return false
|
|
|
|
|
|
|
|
let delay = vc.getDelay(message.slot.sync_committee_message_deadline())
|
|
|
|
if res:
|
2022-07-29 08:36:20 +00:00
|
|
|
beacon_sync_committee_messages_sent.inc()
|
|
|
|
beacon_sync_committee_message_sent_delay.observe(delay.toFloatSeconds())
|
2022-05-10 10:03:40 +00:00
|
|
|
notice "Sync committee message published",
|
|
|
|
message = shortLog(message),
|
|
|
|
validator = shortLog(validator),
|
|
|
|
validator_index = vindex,
|
|
|
|
delay = delay
|
|
|
|
else:
|
|
|
|
warn "Sync committee message was not accepted by beacon node",
|
|
|
|
message = shortLog(message),
|
|
|
|
validator = shortLog(validator),
|
|
|
|
validator_index = vindex, delay = delay
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
|
|
|
proc produceAndPublishSyncCommitteeMessages(service: SyncCommitteeServiceRef,
|
|
|
|
slot: Slot,
|
|
|
|
beaconBlockRoot: Eth2Digest,
|
2022-11-24 07:46:35 +00:00
|
|
|
duties: seq[SyncCommitteeDuty])
|
|
|
|
{.async.} =
|
2022-05-10 10:03:40 +00:00
|
|
|
let vc = service.client
|
|
|
|
|
|
|
|
let pendingSyncCommitteeMessages =
|
|
|
|
block:
|
|
|
|
var res: seq[Future[bool]]
|
|
|
|
for duty in duties:
|
2022-11-24 07:46:35 +00:00
|
|
|
debug "Serving sync message duty", duty, epoch = slot.epoch()
|
2022-05-10 10:03:40 +00:00
|
|
|
res.add(service.serveSyncCommitteeMessage(slot,
|
|
|
|
beaconBlockRoot,
|
|
|
|
duty))
|
|
|
|
res
|
|
|
|
|
|
|
|
let statistics =
|
|
|
|
block:
|
|
|
|
var errored, succeed, failed = 0
|
|
|
|
try:
|
|
|
|
await allFutures(pendingSyncCommitteeMessages)
|
|
|
|
except CancelledError as exc:
|
|
|
|
for fut in pendingSyncCommitteeMessages:
|
|
|
|
if not(fut.finished()):
|
|
|
|
fut.cancel()
|
|
|
|
await allFutures(pendingSyncCommitteeMessages)
|
|
|
|
raise exc
|
|
|
|
|
|
|
|
for future in pendingSyncCommitteeMessages:
|
2023-06-01 08:04:30 +00:00
|
|
|
if future.completed():
|
2022-05-10 10:03:40 +00:00
|
|
|
if future.read():
|
|
|
|
inc(succeed)
|
|
|
|
else:
|
|
|
|
inc(failed)
|
|
|
|
else:
|
|
|
|
inc(errored)
|
|
|
|
(succeed, errored, failed)
|
|
|
|
|
|
|
|
let delay = vc.getDelay(slot.attestation_deadline())
|
2022-07-13 14:43:57 +00:00
|
|
|
debug "Sync committee message statistics",
|
|
|
|
total = len(pendingSyncCommitteeMessages),
|
2022-05-10 10:03:40 +00:00
|
|
|
succeed = statistics[0], failed_to_deliver = statistics[1],
|
|
|
|
not_accepted = statistics[2], delay = delay, slot = slot,
|
|
|
|
duties_count = len(duties)
|
|
|
|
|
|
|
|
proc serveContributionAndProof*(service: SyncCommitteeServiceRef,
|
|
|
|
proof: ContributionAndProof,
|
2022-07-13 14:43:57 +00:00
|
|
|
validator: AttachedValidator): Future[bool] {.
|
|
|
|
async.} =
|
2022-05-10 10:03:40 +00:00
|
|
|
let
|
|
|
|
vc = service.client
|
|
|
|
slot = proof.contribution.slot
|
|
|
|
validatorIdx = validator.index.get()
|
|
|
|
genesisRoot = vc.beaconGenesis.genesis_validators_root
|
|
|
|
fork = vc.forkAtEpoch(slot.epoch)
|
|
|
|
|
|
|
|
let signature =
|
|
|
|
block:
|
2022-06-29 16:53:59 +00:00
|
|
|
let res = await validator.getContributionAndProofSignature(
|
|
|
|
fork, genesisRoot, proof)
|
2022-05-10 10:03:40 +00:00
|
|
|
if res.isErr():
|
2023-03-03 20:20:01 +00:00
|
|
|
warn "Unable to sign sync committee contribution using remote signer",
|
|
|
|
validator = shortLog(validator),
|
|
|
|
contribution = shortLog(proof.contribution),
|
|
|
|
error_msg = res.error()
|
2022-05-10 10:03:40 +00:00
|
|
|
return false
|
|
|
|
res.get()
|
|
|
|
debug "Sending sync contribution",
|
2022-06-29 16:53:59 +00:00
|
|
|
contribution = shortLog(proof.contribution),
|
2022-05-10 10:03:40 +00:00
|
|
|
validator = shortLog(validator), validator_index = validatorIdx,
|
|
|
|
delay = vc.getDelay(slot.sync_contribution_deadline())
|
|
|
|
|
|
|
|
let restSignedProof = RestSignedContributionAndProof.init(
|
2022-06-29 16:53:59 +00:00
|
|
|
proof, signature)
|
2022-05-10 10:03:40 +00:00
|
|
|
|
|
|
|
let res =
|
|
|
|
try:
|
2022-09-29 07:57:14 +00:00
|
|
|
await vc.publishContributionAndProofs(@[restSignedProof],
|
|
|
|
ApiStrategyKind.First)
|
2023-02-23 00:11:00 +00:00
|
|
|
except ValidatorApiError as exc:
|
2023-03-03 20:20:01 +00:00
|
|
|
warn "Unable to publish sync contribution",
|
|
|
|
contribution = shortLog(proof.contribution),
|
|
|
|
validator = shortLog(validator),
|
|
|
|
validator_index = validatorIdx,
|
|
|
|
err_msg = exc.msg,
|
|
|
|
reason = exc.getFailureReason()
|
2022-05-10 10:03:40 +00:00
|
|
|
false
|
2022-07-13 14:43:57 +00:00
|
|
|
except CancelledError:
|
|
|
|
debug "Publish sync contribution request was interrupted"
|
|
|
|
return false
|
2022-05-10 10:03:40 +00:00
|
|
|
except CatchableError as err:
|
|
|
|
error "Unexpected error occurred while publishing sync contribution",
|
2022-06-29 16:53:59 +00:00
|
|
|
contribution = shortLog(proof.contribution),
|
2022-05-10 10:03:40 +00:00
|
|
|
validator = shortLog(validator),
|
|
|
|
err_name = err.name, err_msg = err.msg
|
|
|
|
false
|
|
|
|
|
|
|
|
if res:
|
2022-07-29 08:36:20 +00:00
|
|
|
beacon_sync_committee_contributions_sent.inc()
|
2022-05-10 10:03:40 +00:00
|
|
|
notice "Sync contribution published",
|
|
|
|
validator = shortLog(validator),
|
|
|
|
validator_index = validatorIdx
|
|
|
|
else:
|
|
|
|
warn "Sync contribution was not accepted by beacon node",
|
2022-06-29 16:53:59 +00:00
|
|
|
contribution = shortLog(proof.contribution),
|
2022-05-10 10:03:40 +00:00
|
|
|
validator = shortLog(validator),
|
|
|
|
validator_index = validatorIdx
|
|
|
|
return res
|
|
|
|
|
|
|
|
proc produceAndPublishContributions(service: SyncCommitteeServiceRef,
|
|
|
|
slot: Slot,
|
|
|
|
beaconBlockRoot: Eth2Digest,
|
2022-11-24 07:46:35 +00:00
|
|
|
duties: seq[SyncCommitteeDuty]) {.async.} =
|
2022-05-10 10:03:40 +00:00
|
|
|
let
|
|
|
|
vc = service.client
|
2022-11-24 07:46:35 +00:00
|
|
|
epoch = slot.epoch
|
|
|
|
fork = vc.forkAtEpoch(epoch)
|
|
|
|
|
|
|
|
var slotSignatureReqs: seq[Future[SignatureResult]]
|
|
|
|
var validators: seq[(AttachedValidator, SyncSubcommitteeIndex)]
|
|
|
|
|
|
|
|
for duty in duties:
|
|
|
|
let
|
2023-02-20 11:28:56 +00:00
|
|
|
validator = vc.getValidatorForDuties(duty.pubkey, slot).valueOr:
|
|
|
|
continue
|
2022-11-24 07:46:35 +00:00
|
|
|
subCommitteeIdx =
|
|
|
|
getSubcommitteeIndex(duty.validator_sync_committee_index)
|
|
|
|
future = validator.getSyncCommitteeSelectionProof(
|
|
|
|
fork,
|
|
|
|
vc.beaconGenesis.genesis_validators_root,
|
|
|
|
slot,
|
|
|
|
subCommitteeIdx)
|
|
|
|
|
|
|
|
slotSignatureReqs.add(future)
|
|
|
|
validators.add((validator, subCommitteeIdx))
|
2022-05-10 10:03:40 +00:00
|
|
|
|
2022-11-24 07:46:35 +00:00
|
|
|
try:
|
|
|
|
await allFutures(slotSignatureReqs)
|
|
|
|
except CancelledError as exc:
|
|
|
|
var pendingCancel: seq[Future[void]]
|
|
|
|
for future in slotSignatureReqs:
|
|
|
|
if not(future.finished()):
|
|
|
|
pendingCancel.add(future.cancelAndWait())
|
|
|
|
await allFutures(pendingCancel)
|
|
|
|
raise exc
|
|
|
|
|
|
|
|
var
|
|
|
|
contributionsFuts: array[SYNC_COMMITTEE_SUBNET_COUNT,
|
|
|
|
Future[SyncCommitteeContribution]]
|
|
|
|
|
|
|
|
let validatorContributions = block:
|
|
|
|
var res: seq[ContributionItem]
|
|
|
|
for idx, fut in slotSignatureReqs:
|
2023-06-01 08:04:30 +00:00
|
|
|
if fut.completed:
|
2022-11-24 07:46:35 +00:00
|
|
|
let
|
|
|
|
sigRes = fut.read
|
|
|
|
validator = validators[idx][0]
|
|
|
|
subCommitteeIdx = validators[idx][1]
|
2023-03-03 20:20:01 +00:00
|
|
|
if sigRes.isErr():
|
|
|
|
warn "Unable to create slot signature using remote signer",
|
|
|
|
validator = shortLog(validator),
|
|
|
|
error_msg = sigRes.error()
|
2022-11-24 07:46:35 +00:00
|
|
|
elif validator.index.isSome and
|
|
|
|
is_sync_committee_aggregator(sigRes.get):
|
|
|
|
res.add ContributionItem(
|
|
|
|
aggregator_index: uint64(validator.index.get),
|
|
|
|
selection_proof: sigRes.get,
|
|
|
|
validator: validator,
|
|
|
|
subcommitteeIdx: subCommitteeIdx)
|
|
|
|
|
|
|
|
if isNil(contributionsFuts[subCommitteeIdx]):
|
|
|
|
contributionsFuts[int subCommitteeIdx] =
|
|
|
|
vc.produceSyncCommitteeContribution(
|
|
|
|
slot,
|
|
|
|
subCommitteeIdx,
|
|
|
|
beaconBlockRoot,
|
|
|
|
ApiStrategyKind.Best)
|
|
|
|
res
|
|
|
|
|
|
|
|
if len(validatorContributions) > 0:
|
2022-05-10 10:03:40 +00:00
|
|
|
let pendingAggregates =
|
|
|
|
block:
|
|
|
|
var res: seq[Future[bool]]
|
2022-11-24 07:46:35 +00:00
|
|
|
for item in validatorContributions:
|
2022-05-10 10:03:40 +00:00
|
|
|
let aggContribution =
|
|
|
|
try:
|
2022-11-24 07:46:35 +00:00
|
|
|
await contributionsFuts[item.subcommitteeIdx]
|
2023-02-23 00:11:00 +00:00
|
|
|
except ValidatorApiError as exc:
|
2023-03-03 20:20:01 +00:00
|
|
|
warn "Unable to get sync message contribution data", slot = slot,
|
|
|
|
beaconBlockRoot = shortLog(beaconBlockRoot),
|
|
|
|
reason = exc.getFailureReason()
|
2022-05-10 10:03:40 +00:00
|
|
|
return
|
2022-07-13 14:43:57 +00:00
|
|
|
except CancelledError:
|
|
|
|
debug "Request for sync message contribution was interrupted"
|
|
|
|
return
|
2022-05-10 10:03:40 +00:00
|
|
|
except CatchableError as exc:
|
2022-07-13 14:43:57 +00:00
|
|
|
error "Unexpected error occurred while getting sync message "&
|
|
|
|
"contribution", slot = slot,
|
|
|
|
beaconBlockRoot = shortLog(beaconBlockRoot),
|
2022-05-10 10:03:40 +00:00
|
|
|
err_name = exc.name, err_msg = exc.msg
|
|
|
|
return
|
|
|
|
|
|
|
|
let proof = ContributionAndProof(
|
|
|
|
aggregator_index: item.aggregator_index,
|
|
|
|
contribution: aggContribution,
|
|
|
|
selection_proof: item.selection_proof
|
|
|
|
)
|
|
|
|
res.add(service.serveContributionAndProof(proof, item.validator))
|
|
|
|
res
|
|
|
|
|
|
|
|
let statistics =
|
|
|
|
block:
|
|
|
|
var errored, succeed, failed = 0
|
|
|
|
try:
|
|
|
|
await allFutures(pendingAggregates)
|
|
|
|
except CancelledError as err:
|
|
|
|
for fut in pendingAggregates:
|
|
|
|
if not(fut.finished()):
|
|
|
|
fut.cancel()
|
|
|
|
await allFutures(pendingAggregates)
|
|
|
|
raise err
|
|
|
|
|
|
|
|
for future in pendingAggregates:
|
2023-06-01 08:04:30 +00:00
|
|
|
if future.completed():
|
2022-05-10 10:03:40 +00:00
|
|
|
if future.read():
|
|
|
|
inc(succeed)
|
|
|
|
else:
|
|
|
|
inc(failed)
|
|
|
|
else:
|
|
|
|
inc(errored)
|
|
|
|
(succeed, errored, failed)
|
|
|
|
|
|
|
|
let delay = vc.getDelay(slot.aggregate_deadline())
|
2022-07-13 14:43:57 +00:00
|
|
|
debug "Sync message contribution statistics",
|
|
|
|
total = len(pendingAggregates),
|
2022-05-10 10:03:40 +00:00
|
|
|
succeed = statistics[0], failed_to_deliver = statistics[1],
|
|
|
|
not_accepted = statistics[2], delay = delay, slot = slot
|
|
|
|
|
|
|
|
else:
|
|
|
|
debug "No contribution and proofs scheduled for slot", slot = slot
|
|
|
|
|
|
|
|
proc publishSyncMessagesAndContributions(service: SyncCommitteeServiceRef,
|
|
|
|
slot: Slot,
|
2022-11-29 10:52:21 +00:00
|
|
|
duties: seq[SyncCommitteeDuty]) {.
|
|
|
|
async.} =
|
|
|
|
let vc = service.client
|
2022-05-10 10:03:40 +00:00
|
|
|
|
2022-11-29 10:52:21 +00:00
|
|
|
await vc.waitForBlockPublished(slot, syncCommitteeMessageSlotOffset)
|
2022-05-10 10:03:40 +00:00
|
|
|
|
|
|
|
block:
|
|
|
|
let delay = vc.getDelay(slot.sync_committee_message_deadline())
|
|
|
|
debug "Producing sync committee messages", delay = delay, slot = slot,
|
|
|
|
duties_count = len(duties)
|
2022-07-13 14:43:57 +00:00
|
|
|
|
2022-05-10 10:03:40 +00:00
|
|
|
let beaconBlockRoot =
|
|
|
|
block:
|
|
|
|
try:
|
2022-09-29 07:57:14 +00:00
|
|
|
let res = await vc.getHeadBlockRoot(ApiStrategyKind.First)
|
2023-02-15 14:09:31 +00:00
|
|
|
if res.execution_optimistic.isNone():
|
|
|
|
## The `execution_optimistic` is missing from the response, we assume
|
|
|
|
## that the BN is unaware optimistic sync, so we consider the BN
|
|
|
|
## to be synchronized with the network.
|
|
|
|
## TODO (cheatfate): This should be removed when VC will be able to
|
|
|
|
## handle getSpec() API call with fork constants.
|
|
|
|
res.data.root
|
|
|
|
else:
|
|
|
|
if res.execution_optimistic.get():
|
2023-05-02 11:54:44 +00:00
|
|
|
notice "Execution client not in sync", slot = slot
|
2023-02-15 14:09:31 +00:00
|
|
|
return
|
|
|
|
res.data.root
|
2022-07-13 14:43:57 +00:00
|
|
|
except ValidatorApiError as exc:
|
2023-03-03 20:20:01 +00:00
|
|
|
warn "Unable to retrieve head block's root to sign", reason = exc.msg,
|
|
|
|
reason = exc.getFailureReason()
|
2022-07-13 14:43:57 +00:00
|
|
|
return
|
|
|
|
except CancelledError:
|
|
|
|
debug "Block root request was interrupted"
|
|
|
|
return
|
2022-05-10 10:03:40 +00:00
|
|
|
except CatchableError as exc:
|
2022-07-13 14:43:57 +00:00
|
|
|
error "Unexpected error while requesting sync message block root",
|
|
|
|
err_name = exc.name, err_msg = exc.msg, slot = slot
|
2022-05-10 10:03:40 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
try:
|
|
|
|
await service.produceAndPublishSyncCommitteeMessages(slot,
|
|
|
|
beaconBlockRoot,
|
|
|
|
duties)
|
2023-02-23 00:11:00 +00:00
|
|
|
except ValidatorApiError as exc:
|
2023-03-03 20:20:01 +00:00
|
|
|
warn "Unable to proceed sync committee messages", slot = slot,
|
|
|
|
duties_count = len(duties), reason = exc.getFailureReason()
|
2022-05-10 10:03:40 +00:00
|
|
|
return
|
2022-07-13 14:43:57 +00:00
|
|
|
except CancelledError:
|
|
|
|
debug "Sync committee producing process was interrupted"
|
|
|
|
return
|
2022-05-10 10:03:40 +00:00
|
|
|
except CatchableError as exc:
|
|
|
|
error "Unexpected error while producing sync committee messages",
|
|
|
|
slot = slot,
|
|
|
|
duties_count = len(duties),
|
|
|
|
err_name = exc.name, err_msg = exc.msg
|
|
|
|
return
|
|
|
|
|
|
|
|
let contributionTime =
|
|
|
|
# chronos.Duration subtraction cannot return a negative value; in such
|
|
|
|
# case it will return `ZeroDuration`.
|
|
|
|
vc.beaconClock.durationToNextSlot() - OneThirdDuration
|
|
|
|
if contributionTime != ZeroDuration:
|
|
|
|
await sleepAsync(contributionTime)
|
|
|
|
|
|
|
|
block:
|
|
|
|
let delay = vc.getDelay(slot.sync_contribution_deadline())
|
|
|
|
debug "Producing contribution and proofs", delay = delay
|
|
|
|
await service.produceAndPublishContributions(slot, beaconBlockRoot, duties)
|
|
|
|
|
2023-04-17 21:31:54 +00:00
|
|
|
proc processSyncCommitteeTasks(service: SyncCommitteeServiceRef,
|
2023-05-04 08:26:01 +00:00
|
|
|
slot: Slot) {.async.} =
|
2022-10-21 14:53:30 +00:00
|
|
|
let
|
|
|
|
vc = service.client
|
|
|
|
duties = vc.getSyncCommitteeDutiesForSlot(slot + 1)
|
2023-04-17 21:31:54 +00:00
|
|
|
timeout = vc.beaconClock.durationToNextSlot()
|
2022-05-10 10:03:40 +00:00
|
|
|
|
2023-04-17 21:31:54 +00:00
|
|
|
try:
|
|
|
|
await service.publishSyncMessagesAndContributions(slot,
|
|
|
|
duties).wait(timeout)
|
|
|
|
except AsyncTimeoutError:
|
|
|
|
warn "Unable to publish sync committee messages and contributions in time",
|
|
|
|
slot = slot, timeout = timeout
|
|
|
|
except CancelledError as exc:
|
|
|
|
debug "Sync committee publish task has been interrupted"
|
|
|
|
raise exc
|
|
|
|
except CatchableError as exc:
|
|
|
|
error "Unexpected error encountered while processing sync committee tasks",
|
|
|
|
error_name = exc.name, error_message = exc.msg
|
2022-05-10 10:03:40 +00:00
|
|
|
|
|
|
|
proc mainLoop(service: SyncCommitteeServiceRef) {.async.} =
|
|
|
|
let vc = service.client
|
|
|
|
service.state = ServiceState.Running
|
2022-07-13 14:43:57 +00:00
|
|
|
debug "Service started"
|
|
|
|
|
2023-04-17 21:31:54 +00:00
|
|
|
debug "Sync committee processing loop is waiting for initialization"
|
|
|
|
try:
|
|
|
|
await allFutures(
|
|
|
|
vc.preGenesisEvent.wait(),
|
|
|
|
vc.genesisEvent.wait(),
|
|
|
|
vc.indicesAvailable.wait(),
|
|
|
|
vc.forksAvailable.wait()
|
|
|
|
)
|
|
|
|
except CancelledError:
|
|
|
|
debug "Service interrupted"
|
|
|
|
return
|
|
|
|
except CatchableError as exc:
|
|
|
|
warn "Service crashed with unexpected error", err_name = exc.name,
|
|
|
|
err_msg = exc.msg
|
|
|
|
return
|
|
|
|
|
|
|
|
doAssert(len(vc.forks) > 0, "Fork schedule must not be empty at this point")
|
2022-11-24 22:19:58 +00:00
|
|
|
|
2023-04-17 21:31:54 +00:00
|
|
|
var currentSlot: Opt[Slot]
|
2022-07-13 14:43:57 +00:00
|
|
|
while true:
|
|
|
|
# This loop could look much more nicer/better, when
|
|
|
|
# https://github.com/nim-lang/Nim/issues/19911 will be fixed, so it could
|
|
|
|
# become safe to combine loops, breaks and exception handlers.
|
|
|
|
let breakLoop =
|
|
|
|
try:
|
2023-04-17 21:31:54 +00:00
|
|
|
let
|
|
|
|
# We use zero offset here, because we do waiting in
|
|
|
|
# waitForBlockPublished(syncCommitteeMessageSlotOffset).
|
|
|
|
slot = await vc.checkedWaitForNextSlot(currentSlot, ZeroTimeDiff,
|
|
|
|
false)
|
|
|
|
if slot.isNone():
|
|
|
|
debug "System time adjusted backwards significantly, exiting"
|
|
|
|
true
|
|
|
|
else:
|
|
|
|
currentSlot = slot
|
|
|
|
await service.processSyncCommitteeTasks(currentSlot.get())
|
|
|
|
false
|
2022-07-13 14:43:57 +00:00
|
|
|
except CancelledError:
|
|
|
|
debug "Service interrupted"
|
|
|
|
true
|
|
|
|
except CatchableError as exc:
|
|
|
|
warn "Service crashed with unexpected error", err_name = exc.name,
|
|
|
|
err_msg = exc.msg
|
|
|
|
true
|
|
|
|
|
|
|
|
if breakLoop:
|
|
|
|
break
|
2022-05-10 10:03:40 +00:00
|
|
|
|
|
|
|
proc init*(t: typedesc[SyncCommitteeServiceRef],
|
|
|
|
vc: ValidatorClientRef): Future[SyncCommitteeServiceRef] {.async.} =
|
2022-07-14 21:11:25 +00:00
|
|
|
logScope: service = ServiceName
|
2022-11-03 19:23:33 +00:00
|
|
|
let res = SyncCommitteeServiceRef(name: ServiceName, client: vc,
|
|
|
|
state: ServiceState.Initialized)
|
2022-07-14 21:11:25 +00:00
|
|
|
debug "Initializing service"
|
2022-05-10 10:03:40 +00:00
|
|
|
return res
|
|
|
|
|
|
|
|
proc start*(service: SyncCommitteeServiceRef) =
|
|
|
|
service.lifeFut = mainLoop(service)
|