Skip to content

Commit

Permalink
Fix cache invalidation issue in VC.
Browse files Browse the repository at this point in the history
  • Loading branch information
cheatfate committed Feb 7, 2025
1 parent ccf1022 commit caac6ac
Showing 1 changed file with 42 additions and 49 deletions.
91 changes: 42 additions & 49 deletions beacon_chain/validator_client/common.nim
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,6 @@ type
beaconGenesis*: RestGenesis
proposerTasks*: Table[Slot, seq[ProposerTask]]
dynamicFeeRecipientsStore*: ref DynamicFeeRecipientsStore
validatorsRegCache*: Table[ValidatorPubKey, SignedValidatorRegistrationV1]
blocksSeen*: Table[Slot, BlockDataItem]
rootsSeen*: Table[Eth2Digest, Slot]
processingDelay*: Opt[Duration]
Expand Down Expand Up @@ -1059,68 +1058,61 @@ proc isExpired(vc: ValidatorClientRef,
EPOCHS_BETWEEN_VALIDATOR_REGISTRATION

proc getValidatorRegistration(
vc: ValidatorClientRef,
validator: AttachedValidator,
timestamp: Time,
fork: Fork
): Result[PendingValidatorRegistration, RegistrationKind] =
vc: ValidatorClientRef,
validator: AttachedValidator,
timestamp: Time,
fork: Fork
): Result[PendingValidatorRegistration, RegistrationKind] =
if validator.index.isNone():
debug "Validator registration missing validator index",
validator = validatorLog(validator)
return err(RegistrationKind.MissingIndex)

let
cached = vc.validatorsRegCache.getOrDefault(validator.pubkey)
currentSlot =
block:
let res = vc.beaconClock.toSlot(timestamp)
if not(res.afterGenesis):
return err(RegistrationKind.IncorrectTime)
res.slot

if cached.isDefault() or vc.isExpired(cached, currentSlot):
if not cached.isDefault():
# Want to send it to relay, but not recompute perfectly fine cache
return ok(PendingValidatorRegistration(registration: cached, future: nil))
if validator.externalBuilderRegistration.isSome():
let cached = validator.externalBuilderRegistration.get()
if not(vc.isExpired(cached, currentSlot)):
return err(RegistrationKind.Cached)

let
feeRecipient = vc.getFeeRecipient(validator, currentSlot.epoch())
gasLimit = vc.getGasLimit(validator)
var registration =
SignedValidatorRegistrationV1(
message: ValidatorRegistrationV1(
fee_recipient: ExecutionAddress(data: distinctBase(feeRecipient)),
gas_limit: gasLimit,
timestamp: uint64(timestamp.toUnix()),
pubkey: validator.pubkey
)
let
feeRecipient = vc.getFeeRecipient(validator, currentSlot.epoch())
gasLimit = vc.getGasLimit(validator)

var registration =
SignedValidatorRegistrationV1(
message: ValidatorRegistrationV1(
fee_recipient: ExecutionAddress(data: distinctBase(feeRecipient)),
gas_limit: gasLimit,
timestamp: uint64(timestamp.toUnix()),
pubkey: validator.pubkey
)

let sigfut = validator.getBuilderSignature(fork, registration.message)
if sigfut.finished():
# This is short-path if we able to create signature locally.
if not(sigfut.completed()):
let exc = sigfut.error()
debug "Got unexpected exception while signing validator registration",
validator = validatorLog(validator), error = exc.name,
reason = exc.msg
return err(RegistrationKind.ErrorSignature)
let sigres = sigfut.value()
if sigres.isErr():
debug "Failed to get signature for validator registration",
validator = validatorLog(validator), reason = sigres.error()
return err(RegistrationKind.NoSignature)
registration.signature = sigres.get()
# Updating cache table with new signed registration data
vc.validatorsRegCache[registration.message.pubkey] = registration
ok(PendingValidatorRegistration(registration: registration, future: nil))
else:
# Remote signature service involved, cache will be updated later.
ok(PendingValidatorRegistration(registration: registration,
future: sigfut))
)

let sigfut = validator.getBuilderSignature(fork, registration.message)
if sigfut.finished():
# This is short-path if we able to create signature locally.
if not(sigfut.completed()):
let exc = sigfut.error()
debug "Got unexpected exception while signing validator registration",
validator = validatorLog(validator), error = exc.name,
reason = exc.msg
return err(RegistrationKind.ErrorSignature)

registration.signature = sigfut.value().valueOr:
debug "Failed to get signature for validator registration",
validator = validatorLog(validator), reason = error
return err(RegistrationKind.NoSignature)

ok(PendingValidatorRegistration(registration: registration, future: nil))
else:
# Returning cached result.
err(RegistrationKind.Cached)
ok(PendingValidatorRegistration(registration: registration, future: sigfut))

proc prepareRegistrationList*(
vc: ValidatorClientRef,
Expand All @@ -1131,6 +1123,7 @@ proc prepareRegistrationList*(

var
messages: seq[SignedValidatorRegistrationV1]
validators: seq[AttachedValidator]
futures: seq[Future[SignatureResult]]
registrations: seq[SignedValidatorRegistrationV1]
total = vc.attachedValidators[].count()
Expand All @@ -1151,6 +1144,7 @@ proc prepareRegistrationList*(
registrations.add(preg.registration)
else:
messages.add(preg.registration)
validators.add(validator)
futures.add(preg.future)
else:
case res.error()
Expand All @@ -1174,8 +1168,7 @@ proc prepareRegistrationList*(
var reg = messages[index]
reg.signature = sres.get()
registrations.add(reg)
# Updating cache table
vc.validatorsRegCache[reg.message.pubkey] = reg
validators[index].externalBuilderRegistration = Opt.some(reg)
inc(succeed)
else:
inc(bad)
Expand Down

0 comments on commit caac6ac

Please sign in to comment.