Make new sync committee code compilable.
This commit is contained in:
parent
9fac6b3809
commit
77657974bb
|
@ -20,10 +20,6 @@ export
|
||||||
options, eth2_rest_serialization, blockchain_dag, presto, rest_types,
|
options, eth2_rest_serialization, blockchain_dag, presto, rest_types,
|
||||||
rest_constants
|
rest_constants
|
||||||
|
|
||||||
type
|
|
||||||
ValidatorIndexError* {.pure.} = enum
|
|
||||||
UnsupportedValue, TooHighValue
|
|
||||||
|
|
||||||
func match(data: openArray[char], charset: set[char]): int =
|
func match(data: openArray[char], charset: set[char]): int =
|
||||||
for ch in data:
|
for ch in data:
|
||||||
if ch notin charset:
|
if ch notin charset:
|
||||||
|
@ -203,26 +199,6 @@ template strData*(body: ContentBody): string =
|
||||||
bind fromBytes
|
bind fromBytes
|
||||||
string.fromBytes(body.data)
|
string.fromBytes(body.data)
|
||||||
|
|
||||||
func toValidatorIndex*(value: RestValidatorIndex): Result[ValidatorIndex,
|
|
||||||
ValidatorIndexError] =
|
|
||||||
when sizeof(ValidatorIndex) == 4:
|
|
||||||
if uint64(value) < VALIDATOR_REGISTRY_LIMIT:
|
|
||||||
# On x86 platform Nim allows only `int32` indexes, so all the indexes in
|
|
||||||
# range `2^31 <= x < 2^32` are not supported.
|
|
||||||
if uint64(value) <= uint64(high(int32)):
|
|
||||||
ok(ValidatorIndex(value))
|
|
||||||
else:
|
|
||||||
err(ValidatorIndexError.UnsupportedValue)
|
|
||||||
else:
|
|
||||||
err(ValidatorIndexError.TooHighValue)
|
|
||||||
elif sizeof(ValidatorIndex) == 8:
|
|
||||||
if uint64(value) < VALIDATOR_REGISTRY_LIMIT:
|
|
||||||
ok(ValidatorIndex(value))
|
|
||||||
else:
|
|
||||||
err(ValidatorIndexError.TooHighValue)
|
|
||||||
else:
|
|
||||||
doAssert(false, "ValidatorIndex type size is incorrect")
|
|
||||||
|
|
||||||
func syncCommitteeParticipants*(forkedState: ForkedHashedBeaconState,
|
func syncCommitteeParticipants*(forkedState: ForkedHashedBeaconState,
|
||||||
epoch: Epoch
|
epoch: Epoch
|
||||||
): Result[seq[ValidatorPubKey], cstring] =
|
): Result[seq[ValidatorPubKey], cstring] =
|
||||||
|
|
|
@ -68,6 +68,9 @@ type
|
||||||
ValidatorQueryKind* {.pure.} = enum
|
ValidatorQueryKind* {.pure.} = enum
|
||||||
Index, Key
|
Index, Key
|
||||||
|
|
||||||
|
ValidatorIndexError* {.pure.} = enum
|
||||||
|
UnsupportedValue, TooHighValue
|
||||||
|
|
||||||
ValidatorIdent* = object
|
ValidatorIdent* = object
|
||||||
case kind*: ValidatorQueryKind
|
case kind*: ValidatorQueryKind
|
||||||
of ValidatorQueryKind.Index:
|
of ValidatorQueryKind.Index:
|
||||||
|
@ -1009,3 +1012,23 @@ func init*(t: typedesc[RestSignedContributionAndProof],
|
||||||
message.contribution
|
message.contribution
|
||||||
),
|
),
|
||||||
signature: signature)
|
signature: signature)
|
||||||
|
|
||||||
|
func toValidatorIndex*(value: RestValidatorIndex): Result[ValidatorIndex,
|
||||||
|
ValidatorIndexError] =
|
||||||
|
when sizeof(ValidatorIndex) == 4:
|
||||||
|
if uint64(value) < VALIDATOR_REGISTRY_LIMIT:
|
||||||
|
# On x86 platform Nim allows only `int32` indexes, so all the indexes in
|
||||||
|
# range `2^31 <= x < 2^32` are not supported.
|
||||||
|
if uint64(value) <= uint64(high(int32)):
|
||||||
|
ok(ValidatorIndex(value))
|
||||||
|
else:
|
||||||
|
err(ValidatorIndexError.UnsupportedValue)
|
||||||
|
else:
|
||||||
|
err(ValidatorIndexError.TooHighValue)
|
||||||
|
elif sizeof(ValidatorIndex) == 8:
|
||||||
|
if uint64(value) < VALIDATOR_REGISTRY_LIMIT:
|
||||||
|
ok(ValidatorIndex(value))
|
||||||
|
else:
|
||||||
|
err(ValidatorIndexError.TooHighValue)
|
||||||
|
else:
|
||||||
|
doAssert(false, "ValidatorIndex type size is incorrect")
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[tables, os, sets, sequtils, strutils, uri],
|
std/[tables, os, sets, sequtils, strutils, uri, algorithm],
|
||||||
stew/[base10, results, byteutils],
|
stew/[base10, results, byteutils],
|
||||||
bearssl/rand, chronos, presto, presto/client as presto_client,
|
bearssl/rand, chronos, presto, presto/client as presto_client,
|
||||||
chronicles, confutils,
|
chronicles, confutils,
|
||||||
|
@ -60,6 +60,8 @@ type
|
||||||
client*: ValidatorClientRef
|
client*: ValidatorClientRef
|
||||||
|
|
||||||
DutiesServiceRef* = ref object of ClientServiceRef
|
DutiesServiceRef* = ref object of ClientServiceRef
|
||||||
|
pollingAttesterDutiesTask*: Future[void]
|
||||||
|
pollingSyncDutiesTask*: Future[void]
|
||||||
|
|
||||||
FallbackServiceRef* = ref object of ClientServiceRef
|
FallbackServiceRef* = ref object of ClientServiceRef
|
||||||
changesEvent*: AsyncEvent
|
changesEvent*: AsyncEvent
|
||||||
|
@ -81,10 +83,14 @@ type
|
||||||
data*: RestAttesterDuty
|
data*: RestAttesterDuty
|
||||||
slotSig*: Opt[ValidatorSig]
|
slotSig*: Opt[ValidatorSig]
|
||||||
|
|
||||||
SyncCommitteeDuty* = object
|
SyncCommitteeDuty* = RestSyncCommitteeDuty
|
||||||
pubkey*: ValidatorPubKey
|
|
||||||
validator_index*: ValidatorIndex
|
SlotProofsArray* = array[SLOTS_PER_EPOCH, Opt[ValidatorSig]]
|
||||||
validator_sync_committee_index*: IndexInSyncCommittee
|
|
||||||
|
SyncDutyAndProof* = object
|
||||||
|
epoch*: Epoch
|
||||||
|
data*: SyncCommitteeDuty
|
||||||
|
slotSigs*: Table[SyncSubcommitteeIndex, SlotProofsArray]
|
||||||
|
|
||||||
SyncCommitteeSubscriptionInfo* = object
|
SyncCommitteeSubscriptionInfo* = object
|
||||||
validator_index*: ValidatorIndex
|
validator_index*: ValidatorIndex
|
||||||
|
@ -122,7 +128,7 @@ type
|
||||||
duties*: Table[Epoch, DutyAndProof]
|
duties*: Table[Epoch, DutyAndProof]
|
||||||
|
|
||||||
EpochSyncDuties* = object
|
EpochSyncDuties* = object
|
||||||
duties*: Table[Epoch, SyncCommitteeDuty]
|
duties*: Table[Epoch, SyncDutyAndProof]
|
||||||
|
|
||||||
RestBeaconNodeStatus* {.pure.} = enum
|
RestBeaconNodeStatus* {.pure.} = enum
|
||||||
Offline, ## BN is offline.
|
Offline, ## BN is offline.
|
||||||
|
@ -211,6 +217,7 @@ type
|
||||||
|
|
||||||
const
|
const
|
||||||
DefaultDutyAndProof* = DutyAndProof(epoch: FAR_FUTURE_EPOCH)
|
DefaultDutyAndProof* = DutyAndProof(epoch: FAR_FUTURE_EPOCH)
|
||||||
|
DefaultSyncDutyAndProof* = SyncDutyAndProof(epoch: FAR_FUTURE_EPOCH)
|
||||||
SlotDuration* = int64(SECONDS_PER_SLOT).seconds
|
SlotDuration* = int64(SECONDS_PER_SLOT).seconds
|
||||||
OneThirdDuration* = int64(SECONDS_PER_SLOT).seconds div INTERVALS_PER_SLOT
|
OneThirdDuration* = int64(SECONDS_PER_SLOT).seconds div INTERVALS_PER_SLOT
|
||||||
AllBeaconNodeRoles* = {
|
AllBeaconNodeRoles* = {
|
||||||
|
@ -394,7 +401,7 @@ chronicles.expandIt(RestAttesterDuty):
|
||||||
chronicles.expandIt(SyncCommitteeDuty):
|
chronicles.expandIt(SyncCommitteeDuty):
|
||||||
pubkey = shortLog(it.pubkey)
|
pubkey = shortLog(it.pubkey)
|
||||||
validator_index = it.validator_index
|
validator_index = it.validator_index
|
||||||
validator_sync_committee_index = it.validator_sync_committee_index
|
validator_sync_committee_indices = it.validator_sync_committee_indices
|
||||||
|
|
||||||
proc checkConfig*(info: RestSpecVC): bool =
|
proc checkConfig*(info: RestSpecVC): bool =
|
||||||
# /!\ Keep in sync with `spec/eth2_apis/rest_types.nim` > `RestSpecVC`.
|
# /!\ Keep in sync with `spec/eth2_apis/rest_types.nim` > `RestSpecVC`.
|
||||||
|
@ -500,11 +507,14 @@ proc stop*(csr: ClientServiceRef) {.async.} =
|
||||||
csr.state = ServiceState.Closed
|
csr.state = ServiceState.Closed
|
||||||
debug "Service stopped", service = csr.name
|
debug "Service stopped", service = csr.name
|
||||||
|
|
||||||
proc isDefault*(dap: DutyAndProof): bool =
|
func isDefault*(dap: DutyAndProof): bool =
|
||||||
dap.epoch == Epoch(0xFFFF_FFFF_FFFF_FFFF'u64)
|
dap.epoch == FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
proc isDefault*(prd: ProposedData): bool =
|
func isDefault*(prd: ProposedData): bool =
|
||||||
prd.epoch == Epoch(0xFFFF_FFFF_FFFF_FFFF'u64)
|
prd.epoch == FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
|
func isDefault*(sdap: SyncDutyAndProof): bool =
|
||||||
|
sdap.epoch == FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
proc parseRoles*(data: string): Result[set[BeaconNodeRole], cstring] =
|
proc parseRoles*(data: string): Result[set[BeaconNodeRole], cstring] =
|
||||||
var res: set[BeaconNodeRole]
|
var res: set[BeaconNodeRole]
|
||||||
|
@ -622,6 +632,10 @@ proc init*(t: typedesc[DutyAndProof], epoch: Epoch, dependentRoot: Eth2Digest,
|
||||||
DutyAndProof(epoch: epoch, dependentRoot: dependentRoot, data: duty,
|
DutyAndProof(epoch: epoch, dependentRoot: dependentRoot, data: duty,
|
||||||
slotSig: slotSig)
|
slotSig: slotSig)
|
||||||
|
|
||||||
|
proc init*(t: typedesc[SyncDutyAndProof], epoch: Epoch,
|
||||||
|
duty: SyncCommitteeDuty): SyncDutyAndProof =
|
||||||
|
SyncDutyAndProof(epoch: epoch, data: duty)
|
||||||
|
|
||||||
proc init*(t: typedesc[ProposedData], epoch: Epoch, dependentRoot: Eth2Digest,
|
proc init*(t: typedesc[ProposedData], epoch: Epoch, dependentRoot: Eth2Digest,
|
||||||
data: openArray[ProposerTask]): ProposedData =
|
data: openArray[ProposerTask]): ProposedData =
|
||||||
ProposedData(epoch: epoch, dependentRoot: dependentRoot, duties: @data)
|
ProposedData(epoch: epoch, dependentRoot: dependentRoot, duties: @data)
|
||||||
|
@ -638,17 +652,16 @@ proc getAttesterDutiesForSlot*(vc: ValidatorClientRef,
|
||||||
## Returns all `DutyAndProof` for the given `slot`.
|
## Returns all `DutyAndProof` for the given `slot`.
|
||||||
var res: seq[DutyAndProof]
|
var res: seq[DutyAndProof]
|
||||||
let epoch = slot.epoch()
|
let epoch = slot.epoch()
|
||||||
for key, item in vc.attesters:
|
for key, item in mpairs(vc.attesters):
|
||||||
let duty = item.duties.getOrDefault(epoch, DefaultDutyAndProof)
|
item.duties.withValue(epoch, duty):
|
||||||
if not(duty.isDefault()):
|
if duty[].data.slot == slot:
|
||||||
if duty.data.slot == slot:
|
res.add(duty[])
|
||||||
res.add(duty)
|
|
||||||
res
|
res
|
||||||
|
|
||||||
proc getSyncCommitteeDutiesForSlot*(vc: ValidatorClientRef,
|
proc getSyncCommitteeDutiesForSlot*(vc: ValidatorClientRef,
|
||||||
slot: Slot): seq[SyncCommitteeDuty] =
|
slot: Slot): seq[SyncDutyAndProof] =
|
||||||
## Returns all `SyncCommitteeDuty` for the given `slot`.
|
## Returns all `SyncDutyAndProof` for the given `slot`.
|
||||||
var res: seq[SyncCommitteeDuty]
|
var res: seq[SyncDutyAndProof]
|
||||||
let epoch = slot.epoch()
|
let epoch = slot.epoch()
|
||||||
for key, item in mpairs(vc.syncCommitteeDuties):
|
for key, item in mpairs(vc.syncCommitteeDuties):
|
||||||
item.duties.withValue(epoch, duty):
|
item.duties.withValue(epoch, duty):
|
||||||
|
@ -698,24 +711,26 @@ iterator attesterDutiesForEpoch*(vc: ValidatorClientRef,
|
||||||
if not(isDefault(epochDuties)):
|
if not(isDefault(epochDuties)):
|
||||||
yield epochDuties
|
yield epochDuties
|
||||||
|
|
||||||
|
iterator syncDutiesForEpoch*(vc: ValidatorClientRef,
|
||||||
|
epoch: Epoch): SyncDutyAndProof =
|
||||||
|
for key, item in vc.syncCommitteeDuties:
|
||||||
|
let epochDuties = item.duties.getOrDefault(epoch)
|
||||||
|
if not(isDefault(epochDuties)):
|
||||||
|
yield epochDuties
|
||||||
|
|
||||||
proc syncMembersSubscriptionInfoForEpoch*(
|
proc syncMembersSubscriptionInfoForEpoch*(
|
||||||
vc: ValidatorClientRef,
|
vc: ValidatorClientRef,
|
||||||
epoch: Epoch): seq[SyncCommitteeSubscriptionInfo] =
|
epoch: Epoch
|
||||||
|
): seq[SyncCommitteeSubscriptionInfo] =
|
||||||
var res: seq[SyncCommitteeSubscriptionInfo]
|
var res: seq[SyncCommitteeSubscriptionInfo]
|
||||||
for key, item in mpairs(vc.syncCommitteeDuties):
|
for mitem in mvalues(vc.syncCommitteeDuties):
|
||||||
var cur: SyncCommitteeSubscriptionInfo
|
mitem.duties.withValue(epoch, epochDuties):
|
||||||
var initialized = false
|
res.add(
|
||||||
|
SyncCommitteeSubscriptionInfo(
|
||||||
item.duties.withValue(epoch, epochDuties):
|
validator_index:
|
||||||
if not initialized:
|
epochDuties[].data.validator_index,
|
||||||
cur.validator_index = epochDuties.validator_index
|
validator_sync_committee_indices:
|
||||||
initialized = true
|
epochDuties[].data.validator_sync_committee_indices))
|
||||||
cur.validator_sync_committee_indices.add(
|
|
||||||
epochDuties.validator_sync_committee_index)
|
|
||||||
|
|
||||||
if initialized:
|
|
||||||
res.add cur
|
|
||||||
|
|
||||||
res
|
res
|
||||||
|
|
||||||
proc getDelay*(vc: ValidatorClientRef, deadline: BeaconTime): TimeDiff =
|
proc getDelay*(vc: ValidatorClientRef, deadline: BeaconTime): TimeDiff =
|
||||||
|
@ -851,19 +866,6 @@ proc isExpired*(vc: ValidatorClientRef,
|
||||||
else:
|
else:
|
||||||
true
|
true
|
||||||
|
|
||||||
func getSelections*(
|
|
||||||
daps: openArray[DutyAndProof]
|
|
||||||
): seq[RestBeaconCommitteeSelection] =
|
|
||||||
var res: seq[RestBeaconCommitteeSelection]
|
|
||||||
for item in daps:
|
|
||||||
if item.slotSig.isSome():
|
|
||||||
res.add(RestBeaconCommitteeSelection(
|
|
||||||
validator_index: RestValidatorIndex(item.data.validator_index),
|
|
||||||
slot: item.data.slot,
|
|
||||||
selection_proof: item.slotSig.get()
|
|
||||||
))
|
|
||||||
res
|
|
||||||
|
|
||||||
proc getValidatorRegistration(
|
proc getValidatorRegistration(
|
||||||
vc: ValidatorClientRef,
|
vc: ValidatorClientRef,
|
||||||
validator: AttachedValidator,
|
validator: AttachedValidator,
|
||||||
|
@ -1097,3 +1099,29 @@ proc checkedWaitForNextSlot*(vc: ValidatorClientRef, curSlot: Opt[Slot],
|
||||||
nextSlot = currentSlot + 1
|
nextSlot = currentSlot + 1
|
||||||
|
|
||||||
vc.checkedWaitForSlot(nextSlot, offset, showLogs)
|
vc.checkedWaitForSlot(nextSlot, offset, showLogs)
|
||||||
|
|
||||||
|
func cmpUnsorted*[T](a, b: openArray[T]): bool =
|
||||||
|
if len(a) != len(b): return false
|
||||||
|
return
|
||||||
|
case len(a)
|
||||||
|
of 0:
|
||||||
|
true
|
||||||
|
of 1:
|
||||||
|
a[0] == b[0]
|
||||||
|
of 2:
|
||||||
|
((a[0] == b[0]) and (a[1] == b[1])) or
|
||||||
|
((a[0] == b[1]) and (a[1] == b[0]))
|
||||||
|
else:
|
||||||
|
let asorted = sorted(a)
|
||||||
|
let bsorted = sorted(b)
|
||||||
|
for index, item in asorted.pairs():
|
||||||
|
if item != bsorted[index]:
|
||||||
|
return false
|
||||||
|
true
|
||||||
|
|
||||||
|
func `==`*(a, b: SyncDutyAndProof): bool =
|
||||||
|
(a.epoch == b.epoch) and
|
||||||
|
(a.data.pubkey == b.data.pubkey) and
|
||||||
|
(a.data.validator_index == b.data.validator_index) and
|
||||||
|
cmpUnsorted(a.data.validator_sync_committee_indices,
|
||||||
|
b.data.validator_sync_committee_indices)
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import std/[sets, sequtils]
|
import std/[sets, sequtils, algorithm]
|
||||||
import chronicles
|
import chronicles
|
||||||
import common, api, block_service
|
import common, api, block_service
|
||||||
|
|
||||||
|
@ -20,6 +20,22 @@ type
|
||||||
AttesterLoop, ProposerLoop, IndicesLoop, SyncCommitteeLoop,
|
AttesterLoop, ProposerLoop, IndicesLoop, SyncCommitteeLoop,
|
||||||
ProposerPreparationLoop, ValidatorRegisterLoop
|
ProposerPreparationLoop, ValidatorRegisterLoop
|
||||||
|
|
||||||
|
SyncIndexTable = Table[SyncSubcommitteeIndex, SlotProofsArray]
|
||||||
|
|
||||||
|
SyncValidatorAndDuty = object
|
||||||
|
validator: AttachedValidator
|
||||||
|
duty: SyncDutyAndProof
|
||||||
|
|
||||||
|
AttestationSlotRequest = object
|
||||||
|
validator: AttachedValidator
|
||||||
|
slot: Slot
|
||||||
|
|
||||||
|
SyncSlotRequest = object
|
||||||
|
validator: AttachedValidator
|
||||||
|
slot: Slot
|
||||||
|
validatorSyncCommitteeIndex: IndexInSyncCommittee
|
||||||
|
validatorSubCommitteeIndex: SyncSubcommitteeIndex
|
||||||
|
|
||||||
chronicles.formatIt(DutiesServiceLoop):
|
chronicles.formatIt(DutiesServiceLoop):
|
||||||
case it
|
case it
|
||||||
of AttesterLoop: "attester_loop"
|
of AttesterLoop: "attester_loop"
|
||||||
|
@ -29,6 +45,9 @@ chronicles.formatIt(DutiesServiceLoop):
|
||||||
of ProposerPreparationLoop: "proposer_prepare_loop"
|
of ProposerPreparationLoop: "proposer_prepare_loop"
|
||||||
of ValidatorRegisterLoop: "validator_register_loop"
|
of ValidatorRegisterLoop: "validator_register_loop"
|
||||||
|
|
||||||
|
proc cmp(x, y: AttestationSlotRequest): int =
|
||||||
|
if x.slot == y.slot: 0 elif x.slot < y.slot: -1 else: 1
|
||||||
|
|
||||||
proc checkDuty(duty: RestAttesterDuty): bool =
|
proc checkDuty(duty: RestAttesterDuty): bool =
|
||||||
(duty.committee_length <= MAX_VALIDATORS_PER_COMMITTEE) and
|
(duty.committee_length <= MAX_VALIDATORS_PER_COMMITTEE) and
|
||||||
(uint64(duty.committee_index) < MAX_COMMITTEES_PER_SLOT) and
|
(uint64(duty.committee_index) < MAX_COMMITTEES_PER_SLOT) and
|
||||||
|
@ -109,6 +128,147 @@ proc pollForValidatorIndices*(service: DutiesServiceRef) {.async.} =
|
||||||
updated_validators = updated
|
updated_validators = updated
|
||||||
vc.indicesAvailable.fire()
|
vc.indicesAvailable.fire()
|
||||||
|
|
||||||
|
proc fillAttestationSlotSignatures*(
|
||||||
|
service: DutiesServiceRef,
|
||||||
|
epochPeriods: seq[Epoch]
|
||||||
|
) {.async.} =
|
||||||
|
let
|
||||||
|
vc = service.client
|
||||||
|
genesisRoot = vc.beaconGenesis.genesis_validators_root
|
||||||
|
requests =
|
||||||
|
block:
|
||||||
|
var res: seq[AttestationSlotRequest]
|
||||||
|
for epoch in epochPeriods:
|
||||||
|
for duty in vc.attesterDutiesForEpoch(epoch):
|
||||||
|
if duty.slotSig.isNone():
|
||||||
|
let validator =
|
||||||
|
vc.attachedValidators[].
|
||||||
|
getValidator(duty.data.pubkey).valueOr:
|
||||||
|
continue
|
||||||
|
res.add(AttestationSlotRequest(
|
||||||
|
validator: validator,
|
||||||
|
slot: duty.data.slot
|
||||||
|
))
|
||||||
|
# We make requests sorted by slot number.
|
||||||
|
sorted(res, cmp, order = SortOrder.Ascending)
|
||||||
|
pendingRequests =
|
||||||
|
block:
|
||||||
|
var res: seq[Future[SignatureResult]]
|
||||||
|
for request in requests:
|
||||||
|
let fork = vc.forkAtEpoch(request.slot.epoch())
|
||||||
|
res.add(request.validator.getSlotSignature(fork, genesisRoot,
|
||||||
|
request.slot))
|
||||||
|
res
|
||||||
|
|
||||||
|
try:
|
||||||
|
# TODO (cheatfate): Here we waiting for all signatures, but when remote
|
||||||
|
# signer is used we could try different approach.
|
||||||
|
await allFutures(pendingRequests)
|
||||||
|
except CancelledError as exc:
|
||||||
|
var pending: seq[Future[void]]
|
||||||
|
for future in pendingRequests:
|
||||||
|
if not(future.finished()): pending.add(future.cancelAndWait())
|
||||||
|
await allFutures(pending)
|
||||||
|
raise exc
|
||||||
|
|
||||||
|
for index, fut in pendingRequests.pairs():
|
||||||
|
let
|
||||||
|
request = requests[index]
|
||||||
|
signature =
|
||||||
|
if fut.done():
|
||||||
|
let sres = fut.read()
|
||||||
|
if sres.isErr():
|
||||||
|
warn "Unable to create slot signature using remote signer",
|
||||||
|
reason = sres.error(), epoch = request.slot.epoch(),
|
||||||
|
slot = request.slot
|
||||||
|
Opt.none(ValidatorSig)
|
||||||
|
else:
|
||||||
|
Opt.some(sres.get())
|
||||||
|
else:
|
||||||
|
Opt.none(ValidatorSig)
|
||||||
|
|
||||||
|
vc.attesters.withValue(request.validator.pubkey, map):
|
||||||
|
map[].duties.withValue(request.slot.epoch(), dap):
|
||||||
|
dap[].slotSig = signature
|
||||||
|
|
||||||
|
if vc.config.distributedEnabled:
|
||||||
|
var indexToKey: Table[ValidatorIndex, Opt[ValidatorPubKey]]
|
||||||
|
let selections =
|
||||||
|
block:
|
||||||
|
var sres: seq[RestBeaconCommitteeSelection]
|
||||||
|
for epoch in epochPeriods:
|
||||||
|
for duty in vc.attesterDutiesForEpoch(epoch):
|
||||||
|
# We only use duties which has slot signature filled, because
|
||||||
|
# middleware needs it to create aggregated signature.
|
||||||
|
if duty.slotSig.isSome():
|
||||||
|
let
|
||||||
|
validator = vc.attachedValidators[].getValidator(
|
||||||
|
duty.data.pubkey).valueOr:
|
||||||
|
continue
|
||||||
|
vindex = validator.index.valueOr:
|
||||||
|
continue
|
||||||
|
indexToKey[vindex] = Opt.some(validator.pubkey)
|
||||||
|
sres.add(RestBeaconCommitteeSelection(
|
||||||
|
validator_index: RestValidatorIndex(vindex),
|
||||||
|
slot: duty.data.slot,
|
||||||
|
selection_proof: duty.slotSig.get()
|
||||||
|
))
|
||||||
|
sres
|
||||||
|
|
||||||
|
if len(selections) == 0: return
|
||||||
|
|
||||||
|
let sresponse =
|
||||||
|
try:
|
||||||
|
# Query middleware for aggregated signatures.
|
||||||
|
await vc.submitBeaconCommitteeSelections(selections,
|
||||||
|
ApiStrategyKind.Best)
|
||||||
|
except ValidatorApiError as exc:
|
||||||
|
warn "Unable to submit beacon committee selections",
|
||||||
|
reason = exc.getFailureReason()
|
||||||
|
return
|
||||||
|
except CancelledError as exc:
|
||||||
|
debug "Beacon committee selections processing was interrupted"
|
||||||
|
raise exc
|
||||||
|
except CatchableError as exc:
|
||||||
|
error "Unexpected error occured while trying to submit beacon " &
|
||||||
|
"committee selections", reason = exc.msg, error = exc.name
|
||||||
|
return
|
||||||
|
|
||||||
|
for selection in sresponse.data:
|
||||||
|
let
|
||||||
|
vindex = selection.validator_index.toValidatorIndex().valueOr:
|
||||||
|
warn "Invalid validator_index value encountered while processing " &
|
||||||
|
"beacon committee selections",
|
||||||
|
validator_index = uint64(selection.validator_index),
|
||||||
|
reason = $error
|
||||||
|
continue
|
||||||
|
selectionProof = selection.selection_proof.load().valueOr:
|
||||||
|
warn "Invalid signature encountered while processing " &
|
||||||
|
"beacon committee selections",
|
||||||
|
validator_index = vindex,
|
||||||
|
slot = selection.slot,
|
||||||
|
selection_proof = shortLog(selection.selection_proof)
|
||||||
|
continue
|
||||||
|
validator =
|
||||||
|
block:
|
||||||
|
# Selections operating using validator indices, so we should check
|
||||||
|
# if we have such validator index in our validator's pool and it
|
||||||
|
# still in place (not removed using keystore manager).
|
||||||
|
let key = indexToKey.getOrDefault(vindex)
|
||||||
|
if key.isNone():
|
||||||
|
warn "Non-existing validator encountered while processing " &
|
||||||
|
"beacon committee selections",
|
||||||
|
validator_index = vindex,
|
||||||
|
slot = selection.slot,
|
||||||
|
selection_proof = shortLog(selection.selection_proof)
|
||||||
|
continue
|
||||||
|
vc.attachedValidators[].getValidator(key.get()).valueOr:
|
||||||
|
continue
|
||||||
|
|
||||||
|
vc.attesters.withValue(validator.pubkey, map):
|
||||||
|
map[].duties.withValue(selection.slot.epoch(), dap):
|
||||||
|
dap[].slotSig = Opt.some(selectionProof.toValidatorSig())
|
||||||
|
|
||||||
proc pollForAttesterDuties*(service: DutiesServiceRef,
|
proc pollForAttesterDuties*(service: DutiesServiceRef,
|
||||||
epoch: Epoch): Future[int] {.async.} =
|
epoch: Epoch): Future[int] {.async.} =
|
||||||
let vc = service.client
|
let vc = service.client
|
||||||
|
@ -118,7 +278,7 @@ proc pollForAttesterDuties*(service: DutiesServiceRef,
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
var duties: seq[RestAttesterDuty]
|
var duties: seq[RestAttesterDuty]
|
||||||
var currentRoot: Option[Eth2Digest]
|
var currentRoot: Opt[Eth2Digest]
|
||||||
|
|
||||||
var offset = 0
|
var offset = 0
|
||||||
while offset < len(validatorIndices):
|
while offset < len(validatorIndices):
|
||||||
|
@ -151,7 +311,7 @@ proc pollForAttesterDuties*(service: DutiesServiceRef,
|
||||||
|
|
||||||
if currentRoot.isNone():
|
if currentRoot.isNone():
|
||||||
# First request
|
# First request
|
||||||
currentRoot = some(res.dependent_root)
|
currentRoot = Opt.some(res.dependent_root)
|
||||||
else:
|
else:
|
||||||
if currentRoot.get() != res.dependent_root:
|
if currentRoot.get() != res.dependent_root:
|
||||||
# `dependent_root` must be equal for all requests/response, if it got
|
# `dependent_root` must be equal for all requests/response, if it got
|
||||||
|
@ -159,7 +319,7 @@ proc pollForAttesterDuties*(service: DutiesServiceRef,
|
||||||
# should re-request all queries again.
|
# should re-request all queries again.
|
||||||
offset = 0
|
offset = 0
|
||||||
duties.setLen(0)
|
duties.setLen(0)
|
||||||
currentRoot = none[Eth2Digest]()
|
currentRoot = Opt.none(Eth2Digest)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for item in res.data:
|
for item in res.data:
|
||||||
|
@ -194,108 +354,11 @@ proc pollForAttesterDuties*(service: DutiesServiceRef,
|
||||||
res.add((epoch, duty))
|
res.add((epoch, duty))
|
||||||
res
|
res
|
||||||
|
|
||||||
if len(addOrReplaceItems) > 0:
|
for item in addOrReplaceItems:
|
||||||
var pendingRequests: seq[Future[SignatureResult]]
|
let dap = DutyAndProof.init(item.epoch, currentRoot.get(), item.duty,
|
||||||
var validators: seq[AttachedValidator]
|
Opt.none(ValidatorSig))
|
||||||
for item in addOrReplaceItems:
|
vc.attesters.mgetOrPut(dap.data.pubkey,
|
||||||
let
|
default(EpochDuties)).duties[dap.epoch] = dap
|
||||||
validator =
|
|
||||||
vc.attachedValidators[].getValidator(item.duty.pubkey).valueOr:
|
|
||||||
continue
|
|
||||||
fork = vc.forkAtEpoch(item.duty.slot.epoch)
|
|
||||||
future = validator.getSlotSignature(fork, genesisRoot, item.duty.slot)
|
|
||||||
pendingRequests.add(future)
|
|
||||||
validators.add(validator)
|
|
||||||
|
|
||||||
try:
|
|
||||||
await allFutures(pendingRequests)
|
|
||||||
except CancelledError as exc:
|
|
||||||
var pendingCancel: seq[Future[void]]
|
|
||||||
for future in pendingRequests:
|
|
||||||
if not(future.finished()):
|
|
||||||
pendingCancel.add(future.cancelAndWait())
|
|
||||||
await allFutures(pendingCancel)
|
|
||||||
raise exc
|
|
||||||
|
|
||||||
let daps =
|
|
||||||
block:
|
|
||||||
var res: seq[DutyAndProof]
|
|
||||||
for index, fut in pendingRequests:
|
|
||||||
let
|
|
||||||
item = addOrReplaceItems[index]
|
|
||||||
dap =
|
|
||||||
if fut.done():
|
|
||||||
let sigRes = fut.read()
|
|
||||||
if sigRes.isErr():
|
|
||||||
warn "Unable to create slot signature using remote signer",
|
|
||||||
validator = shortLog(validators[index]),
|
|
||||||
error_msg = sigRes.error()
|
|
||||||
DutyAndProof.init(item.epoch, currentRoot.get(), item.duty,
|
|
||||||
none[ValidatorSig]())
|
|
||||||
else:
|
|
||||||
DutyAndProof.init(item.epoch, currentRoot.get(), item.duty,
|
|
||||||
some(sigRes.get()))
|
|
||||||
else:
|
|
||||||
DutyAndProof.init(item.epoch, currentRoot.get(), item.duty,
|
|
||||||
none[ValidatorSig]())
|
|
||||||
res.add(dap)
|
|
||||||
res
|
|
||||||
|
|
||||||
for item in daps:
|
|
||||||
# Update VC attesters registry with current version of DutyAndProof.
|
|
||||||
vc.attesters.mgetOrPut(item.data.pubkey,
|
|
||||||
default(EpochDuties)).duties[item.epoch] = item
|
|
||||||
|
|
||||||
if vc.config.distributedEnabled:
|
|
||||||
let selections = daps.getSelections()
|
|
||||||
if len(selections) == 0:
|
|
||||||
return len(addOrReplaceItems)
|
|
||||||
|
|
||||||
let sresponse =
|
|
||||||
try:
|
|
||||||
# Query middleware for aggregated signatures.
|
|
||||||
await vc.submitBeaconCommitteeSelections(selections,
|
|
||||||
ApiStrategyKind.Best)
|
|
||||||
except ValidatorApiError as exc:
|
|
||||||
warn "Unable to submit beacon committee selections", epoch = epoch,
|
|
||||||
reason = exc.getFailureReason()
|
|
||||||
return 0
|
|
||||||
except CancelledError as exc:
|
|
||||||
debug "Beacon committee selections processing was interrupted"
|
|
||||||
raise exc
|
|
||||||
except CatchableError as exc:
|
|
||||||
error "Unexpected error occured while trying to submit beacon " &
|
|
||||||
"committee selections", epoch = epoch, err_name = exc.name,
|
|
||||||
err_msg = exc.msg
|
|
||||||
return 0
|
|
||||||
|
|
||||||
for selection in sresponse.data:
|
|
||||||
let selectionProof = selection.selection_proof.load().valueOr:
|
|
||||||
warn "Invalid signature encountered while processing beacon " &
|
|
||||||
"committee selections",
|
|
||||||
validator_index = ValidatorIndex(selection.validator_index),
|
|
||||||
slot = selection.slot,
|
|
||||||
selection_proof = shortLog(selection.selection_proof)
|
|
||||||
continue
|
|
||||||
|
|
||||||
let dres =
|
|
||||||
block:
|
|
||||||
var res: Opt[DutyAndProof]
|
|
||||||
for dap in daps:
|
|
||||||
if (uint64(dap.data.validator_index) ==
|
|
||||||
uint64(selection.validator_index)) and
|
|
||||||
(dap.data.slot == selection.slot):
|
|
||||||
var ndap = dap
|
|
||||||
ndap.slotSig = some(selection.selection_proof)
|
|
||||||
res = Opt.some(ndap)
|
|
||||||
break
|
|
||||||
res
|
|
||||||
|
|
||||||
if dres.isSome():
|
|
||||||
# Update VC attesters registry with new aggregated DutyAndProof.
|
|
||||||
let dap = dres.get()
|
|
||||||
vc.attesters.mgetOrPut(
|
|
||||||
dap.data.pubkey, default(EpochDuties)).duties[dap.epoch] = dap
|
|
||||||
|
|
||||||
return len(addOrReplaceItems)
|
return len(addOrReplaceItems)
|
||||||
|
|
||||||
|
@ -312,6 +375,174 @@ proc pruneSyncCommitteeDuties*(service: DutiesServiceRef, slot: Slot) =
|
||||||
newSyncCommitteeDuties[key] = currentPeriodDuties
|
newSyncCommitteeDuties[key] = currentPeriodDuties
|
||||||
vc.syncCommitteeDuties = newSyncCommitteeDuties
|
vc.syncCommitteeDuties = newSyncCommitteeDuties
|
||||||
|
|
||||||
|
proc fillSyncSlotSignatures*(
|
||||||
|
service: DutiesServiceRef,
|
||||||
|
epochPeriods: seq[Epoch]
|
||||||
|
) {.async.} =
|
||||||
|
let
|
||||||
|
vc = service.client
|
||||||
|
genesisRoot = vc.beaconGenesis.genesis_validators_root
|
||||||
|
validatorDuties =
|
||||||
|
block:
|
||||||
|
var res: seq[SyncValidatorAndDuty]
|
||||||
|
for epoch in epochPeriods:
|
||||||
|
for duty in vc.syncDutiesForEpoch(epoch):
|
||||||
|
if len(duty.slotSigs) == 0:
|
||||||
|
let validator = vc.attachedValidators[].getValidator(
|
||||||
|
duty.data.pubkey).valueOr:
|
||||||
|
continue
|
||||||
|
res.add(
|
||||||
|
SyncValidatorAndDuty(
|
||||||
|
validator: validator,
|
||||||
|
duty: duty))
|
||||||
|
res
|
||||||
|
(pendingRequests, pendingIds) =
|
||||||
|
block:
|
||||||
|
var
|
||||||
|
sres: seq[Future[SignatureResult]]
|
||||||
|
ires: seq[SyncSlotRequest]
|
||||||
|
for epoch in epochPeriods:
|
||||||
|
let fork = vc.forkAtEpoch(epoch)
|
||||||
|
for slot in epoch.slots():
|
||||||
|
for item in validatorDuties:
|
||||||
|
for syncCommitteeIndex in
|
||||||
|
item.duty.data.validator_sync_committee_indices:
|
||||||
|
let subCommitteeIndex = getSubcommitteeIndex(syncCommitteeIndex)
|
||||||
|
sres.add(
|
||||||
|
item.validator.getSyncCommitteeSelectionProof(
|
||||||
|
fork, genesisRoot, slot, subCommitteeIndex))
|
||||||
|
ires.add(
|
||||||
|
SyncSlotRequest(
|
||||||
|
validator: item.validator,
|
||||||
|
slot: slot,
|
||||||
|
validatorSyncCommitteeIndex: syncCommitteeIndex,
|
||||||
|
validatorSubCommitteeIndex: subCommitteeIndex))
|
||||||
|
(sres, ires)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# TODO (cheatfate): Here we waiting for all signature requests, but we could
|
||||||
|
# perform waiting slot by slot, so all the tasks from early slot could
|
||||||
|
# start working without delays.
|
||||||
|
await allFutures(pendingRequests)
|
||||||
|
except CancelledError as exc:
|
||||||
|
var pending: seq[Future[void]]
|
||||||
|
for future in pendingRequests:
|
||||||
|
if not(future.finished()): pending.add(future.cancelAndWait())
|
||||||
|
await allFutures(pending)
|
||||||
|
raise exc
|
||||||
|
|
||||||
|
for index, fut in pendingRequests.pairs():
|
||||||
|
let
|
||||||
|
pid = pendingIds[index]
|
||||||
|
epoch = pid.slot.epoch()
|
||||||
|
slotIndex = pid.slot - epoch.start_slot()
|
||||||
|
signature =
|
||||||
|
if fut.done():
|
||||||
|
let sres = fut.read()
|
||||||
|
if sres.isErr():
|
||||||
|
warn "Unable to create slot proof using remote signer",
|
||||||
|
reason = sres.error(), epoch = epoch,
|
||||||
|
slot = pid.slot, slot_index = slotIndex,
|
||||||
|
validator = shortLog(pid.validator)
|
||||||
|
Opt.none(ValidatorSig)
|
||||||
|
else:
|
||||||
|
Opt.some(sres.get())
|
||||||
|
else:
|
||||||
|
Opt.none(ValidatorSig)
|
||||||
|
|
||||||
|
vc.syncCommitteeDuties.withValue(pid.validator.pubkey, map):
|
||||||
|
map[].duties.withValue(epoch, sdap):
|
||||||
|
sdap[].slotSigs.withValue(pid.validatorSubCommitteeIndex, proofs):
|
||||||
|
proofs[][slotIndex] = signature
|
||||||
|
|
||||||
|
if vc.config.distributedEnabled:
|
||||||
|
var indexToKey: Table[ValidatorIndex, Opt[ValidatorPubKey]]
|
||||||
|
|
||||||
|
let selections =
|
||||||
|
block:
|
||||||
|
var sres: seq[RestSyncCommitteeSelection]
|
||||||
|
for epoch in epochPeriods:
|
||||||
|
for duty in vc.syncDutiesForEpoch(epoch):
|
||||||
|
let
|
||||||
|
validator = vc.attachedValidators[].getValidator(
|
||||||
|
duty.data.pubkey).valueOr:
|
||||||
|
continue
|
||||||
|
vindex = validator.index.valueOr:
|
||||||
|
continue
|
||||||
|
startSlot = duty.epoch.start_slot()
|
||||||
|
indexToKey[vindex] = Opt.some(validator.pubkey)
|
||||||
|
for subCommitteeIndex, proofs in duty.slotSigs.pairs():
|
||||||
|
for slotIndex, selection_proof in proofs.pairs():
|
||||||
|
if selection_proof.isNone(): continue
|
||||||
|
sres.add(RestSyncCommitteeSelection(
|
||||||
|
validator_index: RestValidatorIndex(vindex),
|
||||||
|
slot: startSlot + slotIndex,
|
||||||
|
subcommittee_index: uint64(subCommitteeIndex),
|
||||||
|
selection_proof: selection_proof.get()
|
||||||
|
))
|
||||||
|
sres
|
||||||
|
|
||||||
|
if len(selections) == 0: return
|
||||||
|
|
||||||
|
let sresponse =
|
||||||
|
try:
|
||||||
|
# Query middleware for aggregated signatures.
|
||||||
|
await vc.submitSyncCommitteeSelections(selections,
|
||||||
|
ApiStrategyKind.Best)
|
||||||
|
except ValidatorApiError as exc:
|
||||||
|
warn "Unable to submit sync committee selections",
|
||||||
|
reason = exc.getFailureReason()
|
||||||
|
return
|
||||||
|
except CancelledError as exc:
|
||||||
|
debug "Beacon committee selections processing was interrupted"
|
||||||
|
raise exc
|
||||||
|
except CatchableError as exc:
|
||||||
|
error "Unexpected error occured while trying to submit sync " &
|
||||||
|
"committee selections", reason = exc.msg, error = exc.name
|
||||||
|
return
|
||||||
|
|
||||||
|
for selection in sresponse.data:
|
||||||
|
let
|
||||||
|
vindex = selection.validator_index.toValidatorIndex().valueOr:
|
||||||
|
warn "Invalid validator_index value encountered while processing " &
|
||||||
|
"sync committee selections",
|
||||||
|
validator_index = uint64(selection.validator_index),
|
||||||
|
reason = $error
|
||||||
|
continue
|
||||||
|
selectionProof = selection.selection_proof.load().valueOr:
|
||||||
|
warn "Invalid signature encountered while processing " &
|
||||||
|
"sync committee selections",
|
||||||
|
validator_index = vindex,
|
||||||
|
slot = selection.slot,
|
||||||
|
subcommittee_index = selection.subcommittee_index,
|
||||||
|
selection_proof = shortLog(selection.selection_proof)
|
||||||
|
continue
|
||||||
|
epoch = selection.slot.epoch()
|
||||||
|
slotIndex = selection.slot - epoch.start_slot()
|
||||||
|
# Position in our slot_proofs array
|
||||||
|
subCommitteeIndex = SyncSubcommitteeIndex(selection.subcommittee_index)
|
||||||
|
validator =
|
||||||
|
block:
|
||||||
|
# Selections operating using validator indices, so we should check
|
||||||
|
# if we have such validator index in our validator's pool and it
|
||||||
|
# still in place (not removed using keystore manager).
|
||||||
|
let key = indexToKey.getOrDefault(vindex)
|
||||||
|
if key.isNone():
|
||||||
|
warn "Non-existing validator encountered while processing " &
|
||||||
|
"sync committee selections",
|
||||||
|
validator_index = vindex,
|
||||||
|
slot = selection.slot,
|
||||||
|
subcommittee_index = selection.subcommittee_index,
|
||||||
|
selection_proof = shortLog(selection.selection_proof)
|
||||||
|
continue
|
||||||
|
vc.attachedValidators[].getValidator(key.get()).valueOr:
|
||||||
|
continue
|
||||||
|
|
||||||
|
vc.syncCommitteeDuties.withValue(validator.pubkey, map):
|
||||||
|
map[].duties.withValue(epoch, sdap):
|
||||||
|
sdap[].slotSigs.withValue(subCommitteeIndex, proofs):
|
||||||
|
proofs[][slotIndex] = Opt.some(selectionProof.toValidatorSig())
|
||||||
|
|
||||||
proc pollForSyncCommitteeDuties*(service: DutiesServiceRef,
|
proc pollForSyncCommitteeDuties*(service: DutiesServiceRef,
|
||||||
epoch: Epoch): Future[int] {.async.} =
|
epoch: Epoch): Future[int] {.async.} =
|
||||||
let vc = service.client
|
let vc = service.client
|
||||||
|
@ -351,45 +582,30 @@ proc pollForSyncCommitteeDuties*(service: DutiesServiceRef,
|
||||||
remainingItems -= arraySize
|
remainingItems -= arraySize
|
||||||
|
|
||||||
let
|
let
|
||||||
relevantDuties =
|
relevantSdaps = filteredDuties.mapIt(SyncDutyAndProof.init(epoch, it))
|
||||||
block:
|
|
||||||
var res: seq[SyncCommitteeDuty]
|
|
||||||
for duty in filteredDuties:
|
|
||||||
for validatorSyncCommitteeIndex in
|
|
||||||
duty.validator_sync_committee_indices:
|
|
||||||
res.add(SyncCommitteeDuty(
|
|
||||||
pubkey: duty.pubkey,
|
|
||||||
validator_index: duty.validator_index,
|
|
||||||
validator_sync_committee_index: validatorSyncCommitteeIndex))
|
|
||||||
res
|
|
||||||
|
|
||||||
fork = vc.forkAtEpoch(epoch)
|
fork = vc.forkAtEpoch(epoch)
|
||||||
|
|
||||||
let addOrReplaceItems =
|
addOrReplaceItems =
|
||||||
block:
|
block:
|
||||||
var alreadyWarned = false
|
var
|
||||||
var res: seq[tuple[epoch: Epoch, duty: SyncCommitteeDuty]]
|
alreadyWarned = false
|
||||||
for duty in relevantDuties:
|
res: seq[tuple[epoch: Epoch, duty: SyncDutyAndProof]]
|
||||||
var dutyFound = false
|
for sdap in relevantSdaps:
|
||||||
|
var dutyFound = false
|
||||||
vc.syncCommitteeDuties.withValue(duty.pubkey, map):
|
vc.syncCommitteeDuties.withValue(sdap.data.pubkey, map):
|
||||||
map.duties.withValue(epoch, epochDuty):
|
map.duties.withValue(epoch, epochDuty):
|
||||||
if epochDuty[] != duty:
|
if epochDuty[] != sdap:
|
||||||
dutyFound = true
|
dutyFound = true
|
||||||
|
if dutyFound and not(alreadyWarned):
|
||||||
if dutyFound and not alreadyWarned:
|
info "Sync committee duties re-organization", sdap, epoch
|
||||||
info "Sync committee duties re-organization", duty, epoch
|
alreadyWarned = true
|
||||||
alreadyWarned = true
|
res.add((epoch, sdap))
|
||||||
|
res
|
||||||
res.add((epoch, duty))
|
|
||||||
res
|
|
||||||
|
|
||||||
if len(addOrReplaceItems) > 0:
|
if len(addOrReplaceItems) > 0:
|
||||||
for epoch, duty in items(addOrReplaceItems):
|
for epoch, sdap in items(addOrReplaceItems):
|
||||||
var validatorDuties =
|
vc.syncCommitteeDuties.mgetOrPut(sdap.data.pubkey,
|
||||||
vc.syncCommitteeDuties.getOrDefault(duty.pubkey)
|
default(EpochSyncDuties)).duties[epoch] = sdap
|
||||||
validatorDuties.duties[epoch] = duty
|
|
||||||
vc.syncCommitteeDuties[duty.pubkey] = validatorDuties
|
|
||||||
|
|
||||||
return len(addOrReplaceItems)
|
return len(addOrReplaceItems)
|
||||||
|
|
||||||
|
@ -431,6 +647,8 @@ proc pollForAttesterDuties*(service: DutiesServiceRef) {.async.} =
|
||||||
if (counts[0].count == 0) and (counts[1].count == 0):
|
if (counts[0].count == 0) and (counts[1].count == 0):
|
||||||
debug "No new attester's duties received", slot = currentSlot
|
debug "No new attester's duties received", slot = currentSlot
|
||||||
|
|
||||||
|
await service.fillAttestationSlotSignatures(@[currentEpoch, nextEpoch])
|
||||||
|
|
||||||
let subscriptions =
|
let subscriptions =
|
||||||
block:
|
block:
|
||||||
var res: seq[RestCommitteeSubscription]
|
var res: seq[RestCommitteeSubscription]
|
||||||
|
@ -490,22 +708,26 @@ proc pollForSyncCommitteeDuties*(service: DutiesServiceRef) {.async.} =
|
||||||
)
|
)
|
||||||
res
|
res
|
||||||
|
|
||||||
(counts, total) =
|
(counts, epochs, total) =
|
||||||
block:
|
block:
|
||||||
var res: seq[tuple[epoch: Epoch, period: SyncCommitteePeriod,
|
var res: seq[tuple[epoch: Epoch, period: SyncCommitteePeriod,
|
||||||
count: int]]
|
count: int]]
|
||||||
|
var periods: seq[Epoch]
|
||||||
var total = 0
|
var total = 0
|
||||||
if len(dutyPeriods) > 0:
|
if len(dutyPeriods) > 0:
|
||||||
for (epoch, period) in dutyPeriods:
|
for (epoch, period) in dutyPeriods:
|
||||||
let count = await service.pollForSyncCommitteeDuties(epoch)
|
let count = await service.pollForSyncCommitteeDuties(epoch)
|
||||||
res.add((epoch: epoch, period: period, count: count))
|
res.add((epoch: epoch, period: period, count: count))
|
||||||
|
periods.add(epoch)
|
||||||
total += count
|
total += count
|
||||||
(res, total)
|
(res, periods, total)
|
||||||
|
|
||||||
if total == 0:
|
if total == 0:
|
||||||
debug "No new sync committee member's duties received",
|
debug "No new sync committee member's duties received",
|
||||||
slot = currentSlot
|
slot = currentSlot
|
||||||
|
|
||||||
|
await service.fillSyncSlotSignatures(epochs)
|
||||||
|
|
||||||
let subscriptions =
|
let subscriptions =
|
||||||
block:
|
block:
|
||||||
var res: seq[RestSyncCommitteeSubscription]
|
var res: seq[RestSyncCommitteeSubscription]
|
||||||
|
@ -668,8 +890,13 @@ proc attesterDutiesLoop(service: DutiesServiceRef) {.async.} =
|
||||||
)
|
)
|
||||||
doAssert(len(vc.forks) > 0, "Fork schedule must not be empty at this point")
|
doAssert(len(vc.forks) > 0, "Fork schedule must not be empty at this point")
|
||||||
while true:
|
while true:
|
||||||
await service.pollForAttesterDuties()
|
|
||||||
await service.waitForNextSlot(AttesterLoop)
|
await service.waitForNextSlot(AttesterLoop)
|
||||||
|
# Cleaning up previous attestation duties task.
|
||||||
|
if not(isNil(service.pollingAttesterDutiesTask)) and
|
||||||
|
not(service.pollingAttesterDutiesTask.finished()):
|
||||||
|
await cancelAndWait(service.pollingAttesterDutiesTask)
|
||||||
|
# Spawning new attestation duties task.
|
||||||
|
service.pollingAttesterDutiesTask = service.pollForAttesterDuties()
|
||||||
|
|
||||||
proc proposerDutiesLoop(service: DutiesServiceRef) {.async.} =
|
proc proposerDutiesLoop(service: DutiesServiceRef) {.async.} =
|
||||||
let vc = service.client
|
let vc = service.client
|
||||||
|
@ -727,8 +954,13 @@ proc syncCommitteeDutiesLoop(service: DutiesServiceRef) {.async.} =
|
||||||
)
|
)
|
||||||
doAssert(len(vc.forks) > 0, "Fork schedule must not be empty at this point")
|
doAssert(len(vc.forks) > 0, "Fork schedule must not be empty at this point")
|
||||||
while true:
|
while true:
|
||||||
await service.pollForSyncCommitteeDuties()
|
|
||||||
await service.waitForNextSlot(SyncCommitteeLoop)
|
await service.waitForNextSlot(SyncCommitteeLoop)
|
||||||
|
# Cleaning up previous attestation duties task.
|
||||||
|
if not(isNil(service.pollingSyncDutiesTask)) and
|
||||||
|
not(service.pollingSyncDutiesTask.finished()):
|
||||||
|
await cancelAndWait(service.pollingSyncDutiesTask)
|
||||||
|
# Spawning new attestation duties task.
|
||||||
|
service.pollingSyncDutiesTask = service.pollForAttesterDuties()
|
||||||
|
|
||||||
template checkAndRestart(serviceLoop: DutiesServiceLoop,
|
template checkAndRestart(serviceLoop: DutiesServiceLoop,
|
||||||
future: Future[void], body: untyped): untyped =
|
future: Future[void], body: untyped): untyped =
|
||||||
|
@ -803,6 +1035,12 @@ proc mainLoop(service: DutiesServiceRef) {.async.} =
|
||||||
pending.add(prepareFut.cancelAndWait())
|
pending.add(prepareFut.cancelAndWait())
|
||||||
if not(isNil(registerFut)) and not(registerFut.finished()):
|
if not(isNil(registerFut)) and not(registerFut.finished()):
|
||||||
pending.add(registerFut.cancelAndWait())
|
pending.add(registerFut.cancelAndWait())
|
||||||
|
if not(isNil(service.pollingAttesterDutiesTask)) and
|
||||||
|
not(service.pollingAttesterDutiesTask.finished()):
|
||||||
|
pending.add(service.pollingAttesterDutiesTask.cancelAndWait())
|
||||||
|
if not(isNil(service.pollingSyncDutiesTask)) and
|
||||||
|
not(service.pollingSyncDutiesTask.finished()):
|
||||||
|
pending.add(service.pollingSyncDutiesTask.cancelAndWait())
|
||||||
await allFutures(pending)
|
await allFutures(pending)
|
||||||
true
|
true
|
||||||
except CatchableError as exc:
|
except CatchableError as exc:
|
||||||
|
|
|
@ -25,19 +25,27 @@ type
|
||||||
validator: AttachedValidator
|
validator: AttachedValidator
|
||||||
subcommitteeIdx: SyncSubcommitteeIndex
|
subcommitteeIdx: SyncSubcommitteeIndex
|
||||||
|
|
||||||
|
ValidatorAndSig* = object
|
||||||
|
validator: AttachedValidator
|
||||||
|
signature: ValidatorSig
|
||||||
|
|
||||||
proc serveSyncCommitteeMessage*(service: SyncCommitteeServiceRef,
|
proc serveSyncCommitteeMessage*(service: SyncCommitteeServiceRef,
|
||||||
slot: Slot, beaconBlockRoot: Eth2Digest,
|
slot: Slot, beaconBlockRoot: Eth2Digest,
|
||||||
duty: SyncCommitteeDuty): Future[bool] {.
|
duty: SyncCommitteeDuty,
|
||||||
|
index: IndexInSyncCommittee): Future[bool] {.
|
||||||
async.} =
|
async.} =
|
||||||
let
|
let
|
||||||
vc = service.client
|
vc = service.client
|
||||||
fork = vc.forkAtEpoch(slot.epoch)
|
fork = vc.forkAtEpoch(slot.epoch)
|
||||||
genesisValidatorsRoot = vc.beaconGenesis.genesis_validators_root
|
genesisValidatorsRoot = vc.beaconGenesis.genesis_validators_root
|
||||||
vindex = duty.validator_index
|
|
||||||
subcommitteeIdx = getSubcommitteeIndex(
|
|
||||||
duty.validator_sync_committee_index)
|
|
||||||
validator = vc.getValidatorForDuties(
|
validator = vc.getValidatorForDuties(
|
||||||
duty.pubkey, slot, slashingSafe = true).valueOr: return false
|
duty.pubkey, slot, slashingSafe = true).valueOr: return false
|
||||||
|
subcommitteeIdx = getSubcommitteeIndex(index)
|
||||||
|
|
||||||
|
logScope:
|
||||||
|
validator = shortLog(validator)
|
||||||
|
|
||||||
|
let
|
||||||
message =
|
message =
|
||||||
block:
|
block:
|
||||||
let res = await getSyncCommitteeMessage(validator, fork,
|
let res = await getSyncCommitteeMessage(validator, fork,
|
||||||
|
@ -50,8 +58,8 @@ proc serveSyncCommitteeMessage*(service: SyncCommitteeServiceRef,
|
||||||
return
|
return
|
||||||
res.get()
|
res.get()
|
||||||
|
|
||||||
debug "Sending sync committee message", message = shortLog(message),
|
debug "Sending sync committee message",
|
||||||
validator = shortLog(validator), validator_index = vindex,
|
message = shortLog(message),
|
||||||
delay = vc.getDelay(message.slot.sync_committee_message_deadline())
|
delay = vc.getDelay(message.slot.sync_committee_message_deadline())
|
||||||
|
|
||||||
let res =
|
let res =
|
||||||
|
@ -60,18 +68,14 @@ proc serveSyncCommitteeMessage*(service: SyncCommitteeServiceRef,
|
||||||
except ValidatorApiError as exc:
|
except ValidatorApiError as exc:
|
||||||
warn "Unable to publish sync committee message",
|
warn "Unable to publish sync committee message",
|
||||||
message = shortLog(message),
|
message = shortLog(message),
|
||||||
validator = shortLog(validator),
|
|
||||||
validator_index = vindex,
|
|
||||||
reason = exc.getFailureReason()
|
reason = exc.getFailureReason()
|
||||||
return false
|
return false
|
||||||
except CancelledError:
|
except CancelledError as exc:
|
||||||
debug "Publish sync committee message request was interrupted"
|
debug "Publish sync committee message request was interrupted"
|
||||||
return false
|
raise exc
|
||||||
except CatchableError as exc:
|
except CatchableError as exc:
|
||||||
error "Unexpected error occurred while publishing sync committee message",
|
error "Unexpected error occurred while publishing sync committee message",
|
||||||
message = shortLog(message),
|
message = shortLog(message),
|
||||||
validator = shortLog(validator),
|
|
||||||
validator_index = vindex,
|
|
||||||
err_name = exc.name, err_msg = exc.msg
|
err_name = exc.name, err_msg = exc.msg
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
@ -81,32 +85,32 @@ proc serveSyncCommitteeMessage*(service: SyncCommitteeServiceRef,
|
||||||
beacon_sync_committee_message_sent_delay.observe(delay.toFloatSeconds())
|
beacon_sync_committee_message_sent_delay.observe(delay.toFloatSeconds())
|
||||||
notice "Sync committee message published",
|
notice "Sync committee message published",
|
||||||
message = shortLog(message),
|
message = shortLog(message),
|
||||||
validator = shortLog(validator),
|
|
||||||
validator_index = vindex,
|
|
||||||
delay = delay
|
delay = delay
|
||||||
else:
|
else:
|
||||||
warn "Sync committee message was not accepted by beacon node",
|
warn "Sync committee message was not accepted by beacon node",
|
||||||
message = shortLog(message),
|
message = shortLog(message),
|
||||||
validator = shortLog(validator),
|
delay = delay
|
||||||
validator_index = vindex, delay = delay
|
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
proc produceAndPublishSyncCommitteeMessages(service: SyncCommitteeServiceRef,
|
proc produceAndPublishSyncCommitteeMessages(service: SyncCommitteeServiceRef,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
beaconBlockRoot: Eth2Digest,
|
beaconBlockRoot: Eth2Digest,
|
||||||
duties: seq[SyncCommitteeDuty])
|
duties: seq[SyncDutyAndProof])
|
||||||
{.async.} =
|
{.async.} =
|
||||||
let vc = service.client
|
let vc = service.client
|
||||||
|
|
||||||
let pendingSyncCommitteeMessages =
|
let pendingSyncCommitteeMessages =
|
||||||
block:
|
block:
|
||||||
var res: seq[Future[bool]]
|
var res: seq[Future[bool]]
|
||||||
for duty in duties:
|
for sdap in duties:
|
||||||
|
let duty = sdap.data
|
||||||
debug "Serving sync message duty", duty, epoch = slot.epoch()
|
debug "Serving sync message duty", duty, epoch = slot.epoch()
|
||||||
res.add(service.serveSyncCommitteeMessage(slot,
|
for syncCommitteeIndex in duty.validator_sync_committee_indices:
|
||||||
beaconBlockRoot,
|
res.add(service.serveSyncCommitteeMessage(slot,
|
||||||
duty))
|
beaconBlockRoot,
|
||||||
|
duty,
|
||||||
|
syncCommitteeIndex))
|
||||||
res
|
res
|
||||||
|
|
||||||
let statistics =
|
let statistics =
|
||||||
|
@ -180,9 +184,9 @@ proc serveContributionAndProof*(service: SyncCommitteeServiceRef,
|
||||||
err_msg = exc.msg,
|
err_msg = exc.msg,
|
||||||
reason = exc.getFailureReason()
|
reason = exc.getFailureReason()
|
||||||
false
|
false
|
||||||
except CancelledError:
|
except CancelledError as exc:
|
||||||
debug "Publish sync contribution request was interrupted"
|
debug "Publish sync contribution request was interrupted"
|
||||||
return false
|
raise exc
|
||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
error "Unexpected error occurred while publishing sync contribution",
|
error "Unexpected error occurred while publishing sync contribution",
|
||||||
contribution = shortLog(proof.contribution),
|
contribution = shortLog(proof.contribution),
|
||||||
|
@ -205,73 +209,61 @@ proc serveContributionAndProof*(service: SyncCommitteeServiceRef,
|
||||||
proc produceAndPublishContributions(service: SyncCommitteeServiceRef,
|
proc produceAndPublishContributions(service: SyncCommitteeServiceRef,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
beaconBlockRoot: Eth2Digest,
|
beaconBlockRoot: Eth2Digest,
|
||||||
duties: seq[SyncCommitteeDuty]) {.async.} =
|
duties: seq[SyncDutyAndProof]) {.async.} =
|
||||||
let
|
let
|
||||||
vc = service.client
|
vc = service.client
|
||||||
epoch = slot.epoch
|
epoch = slot.epoch()
|
||||||
fork = vc.forkAtEpoch(epoch)
|
fork = vc.forkAtEpoch(epoch)
|
||||||
|
|
||||||
var slotSignatureReqs: seq[Future[SignatureResult]]
|
var
|
||||||
var validators: seq[(AttachedValidator, SyncSubcommitteeIndex)]
|
contributionFuts: array[SYNC_COMMITTEE_SUBNET_COUNT,
|
||||||
|
Future[SyncCommitteeContribution]]
|
||||||
|
|
||||||
for duty in duties:
|
let validatorContributions =
|
||||||
let
|
block:
|
||||||
validator = vc.getValidatorForDuties(duty.pubkey, slot).valueOr:
|
var res: seq[ContributionItem]
|
||||||
continue
|
for sdap in duties:
|
||||||
subCommitteeIdx =
|
let duty = sdap.data
|
||||||
getSubcommitteeIndex(duty.validator_sync_committee_index)
|
for syncCommitteeIndex in duty.validator_sync_committee_indices:
|
||||||
future = validator.getSyncCommitteeSelectionProof(
|
let
|
||||||
fork,
|
subCommitteeIndex = getSubcommitteeIndex(syncCommitteeIndex)
|
||||||
vc.beaconGenesis.genesis_validators_root,
|
slotIndex = slot - slot.epoch().start_slot()
|
||||||
slot,
|
signature =
|
||||||
subCommitteeIdx)
|
block:
|
||||||
|
let signatures = sdap.slotSigs.getOrDefault(subCommitteeIndex)
|
||||||
|
if signatures[slotIndex].isNone():
|
||||||
|
continue
|
||||||
|
signatures[slotIndex].get()
|
||||||
|
validator = vc.getValidatorForDuties(duty.pubkey, slot).valueOr:
|
||||||
|
continue
|
||||||
|
vindex = validator.index.valueOr:
|
||||||
|
continue
|
||||||
|
if is_sync_committee_aggregator(signature):
|
||||||
|
res.add(ContributionItem(
|
||||||
|
aggregator_index: uint64(vindex),
|
||||||
|
selection_proof: signature,
|
||||||
|
validator: validator,
|
||||||
|
subcommitteeIdx: subCommitteeIndex
|
||||||
|
))
|
||||||
|
if isNil(contributionFuts[int(subCommitteeIndex)]):
|
||||||
|
contributionFuts[int(subCommitteeIndex)] =
|
||||||
|
vc.produceSyncCommitteeContribution(
|
||||||
|
slot, subCommitteeIndex, beaconBlockRoot,
|
||||||
|
ApiStrategyKind.Best)
|
||||||
|
res
|
||||||
|
|
||||||
slotSignatureReqs.add(future)
|
let pendingFutures = contributionFuts.filterIt(not(isNil(it)))
|
||||||
validators.add((validator, subCommitteeIdx))
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await allFutures(slotSignatureReqs)
|
await allFutures(pendingFutures)
|
||||||
except CancelledError as exc:
|
except CancelledError as exc:
|
||||||
var pendingCancel: seq[Future[void]]
|
var pending: seq[Future[void]]
|
||||||
for future in slotSignatureReqs:
|
for fut in pendingFutures:
|
||||||
if not(future.finished()):
|
if not(fut.finished()):
|
||||||
pendingCancel.add(future.cancelAndWait())
|
pending.add(fut.cancelAndWait())
|
||||||
await allFutures(pendingCancel)
|
await allFutures(pending)
|
||||||
raise exc
|
raise exc
|
||||||
|
|
||||||
var
|
|
||||||
contributionsFuts: array[SYNC_COMMITTEE_SUBNET_COUNT,
|
|
||||||
Future[SyncCommitteeContribution]]
|
|
||||||
|
|
||||||
let validatorContributions = block:
|
|
||||||
var res: seq[ContributionItem]
|
|
||||||
for idx, fut in slotSignatureReqs:
|
|
||||||
if fut.completed:
|
|
||||||
let
|
|
||||||
sigRes = fut.read
|
|
||||||
validator = validators[idx][0]
|
|
||||||
subCommitteeIdx = validators[idx][1]
|
|
||||||
if sigRes.isErr():
|
|
||||||
warn "Unable to create slot signature using remote signer",
|
|
||||||
validator = shortLog(validator),
|
|
||||||
error_msg = sigRes.error()
|
|
||||||
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:
|
if len(validatorContributions) > 0:
|
||||||
let pendingAggregates =
|
let pendingAggregates =
|
||||||
block:
|
block:
|
||||||
|
@ -279,22 +271,21 @@ proc produceAndPublishContributions(service: SyncCommitteeServiceRef,
|
||||||
for item in validatorContributions:
|
for item in validatorContributions:
|
||||||
let aggContribution =
|
let aggContribution =
|
||||||
try:
|
try:
|
||||||
await contributionsFuts[item.subcommitteeIdx]
|
contributionFuts[item.subcommitteeIdx].read()
|
||||||
except ValidatorApiError as exc:
|
except ValidatorApiError as exc:
|
||||||
warn "Unable to get sync message contribution data", slot = slot,
|
warn "Unable to get sync message contribution data", slot = slot,
|
||||||
beaconBlockRoot = shortLog(beaconBlockRoot),
|
beaconBlockRoot = shortLog(beaconBlockRoot),
|
||||||
reason = exc.getFailureReason()
|
reason = exc.getFailureReason()
|
||||||
return
|
continue
|
||||||
except CancelledError:
|
except CancelledError as exc:
|
||||||
debug "Request for sync message contribution was interrupted"
|
debug "Request for sync message contribution was interrupted"
|
||||||
return
|
raise exc
|
||||||
except CatchableError as exc:
|
except CatchableError as exc:
|
||||||
error "Unexpected error occurred while getting sync message "&
|
error "Unexpected error occurred while getting sync message "&
|
||||||
"contribution", slot = slot,
|
"contribution", slot = slot,
|
||||||
beaconBlockRoot = shortLog(beaconBlockRoot),
|
beaconBlockRoot = shortLog(beaconBlockRoot),
|
||||||
err_name = exc.name, err_msg = exc.msg
|
err_name = exc.name, err_msg = exc.msg
|
||||||
return
|
continue
|
||||||
|
|
||||||
let proof = ContributionAndProof(
|
let proof = ContributionAndProof(
|
||||||
aggregator_index: item.aggregator_index,
|
aggregator_index: item.aggregator_index,
|
||||||
contribution: aggContribution,
|
contribution: aggContribution,
|
||||||
|
@ -308,12 +299,12 @@ proc produceAndPublishContributions(service: SyncCommitteeServiceRef,
|
||||||
var errored, succeed, failed = 0
|
var errored, succeed, failed = 0
|
||||||
try:
|
try:
|
||||||
await allFutures(pendingAggregates)
|
await allFutures(pendingAggregates)
|
||||||
except CancelledError as err:
|
except CancelledError as exc:
|
||||||
for fut in pendingAggregates:
|
for fut in pendingAggregates:
|
||||||
if not(fut.finished()):
|
if not(fut.finished()):
|
||||||
fut.cancel()
|
fut.cancel()
|
||||||
await allFutures(pendingAggregates)
|
await allFutures(pendingAggregates)
|
||||||
raise err
|
raise exc
|
||||||
|
|
||||||
for future in pendingAggregates:
|
for future in pendingAggregates:
|
||||||
if future.completed():
|
if future.completed():
|
||||||
|
@ -336,7 +327,7 @@ proc produceAndPublishContributions(service: SyncCommitteeServiceRef,
|
||||||
|
|
||||||
proc publishSyncMessagesAndContributions(service: SyncCommitteeServiceRef,
|
proc publishSyncMessagesAndContributions(service: SyncCommitteeServiceRef,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
duties: seq[SyncCommitteeDuty]) {.
|
duties: seq[SyncDutyAndProof]) {.
|
||||||
async.} =
|
async.} =
|
||||||
let vc = service.client
|
let vc = service.client
|
||||||
|
|
||||||
|
@ -367,9 +358,9 @@ proc publishSyncMessagesAndContributions(service: SyncCommitteeServiceRef,
|
||||||
warn "Unable to retrieve head block's root to sign", reason = exc.msg,
|
warn "Unable to retrieve head block's root to sign", reason = exc.msg,
|
||||||
reason = exc.getFailureReason()
|
reason = exc.getFailureReason()
|
||||||
return
|
return
|
||||||
except CancelledError:
|
except CancelledError as exc:
|
||||||
debug "Block root request was interrupted"
|
debug "Block root request was interrupted"
|
||||||
return
|
raise exc
|
||||||
except CatchableError as exc:
|
except CatchableError as exc:
|
||||||
error "Unexpected error while requesting sync message block root",
|
error "Unexpected error while requesting sync message block root",
|
||||||
err_name = exc.name, err_msg = exc.msg, slot = slot
|
err_name = exc.name, err_msg = exc.msg, slot = slot
|
||||||
|
@ -383,9 +374,9 @@ proc publishSyncMessagesAndContributions(service: SyncCommitteeServiceRef,
|
||||||
warn "Unable to proceed sync committee messages", slot = slot,
|
warn "Unable to proceed sync committee messages", slot = slot,
|
||||||
duties_count = len(duties), reason = exc.getFailureReason()
|
duties_count = len(duties), reason = exc.getFailureReason()
|
||||||
return
|
return
|
||||||
except CancelledError:
|
except CancelledError as exc:
|
||||||
debug "Sync committee producing process was interrupted"
|
debug "Sync committee producing process was interrupted"
|
||||||
return
|
raise exc
|
||||||
except CatchableError as exc:
|
except CatchableError as exc:
|
||||||
error "Unexpected error while producing sync committee messages",
|
error "Unexpected error while producing sync committee messages",
|
||||||
slot = slot,
|
slot = slot,
|
||||||
|
|
Loading…
Reference in New Issue