Skip to content

Commit 0dbf6e7

Browse files
committed
Add ability to filter keys provided by dynamic remote web3signer.
1 parent 3ac0432 commit 0dbf6e7

File tree

8 files changed

+80
-51
lines changed

8 files changed

+80
-51
lines changed

beacon_chain/beacon_node.nim

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
# Everything needed to run a full Beacon Node
99

1010
import
11-
std/osproc,
11+
std/[osproc, sets],
1212

1313
# Nimble packages
1414
chronos, presto, bearssl/rand,
@@ -30,7 +30,7 @@ import
3030
./rpc/state_ttl_cache
3131

3232
export
33-
osproc, chronos, presto, action_tracker,
33+
osproc, sets, chronos, presto, action_tracker,
3434
beacon_clock, beacon_chain_db, conf, light_client,
3535
attestation_pool, sync_committee_msg_pool, validator_change_pool,
3636
eth2_network, el_manager, request_manager, sync_manager,
@@ -78,6 +78,7 @@ type
7878
keymanagerHost*: ref KeymanagerHost
7979
keymanagerServer*: RestServerRef
8080
keystoreCache*: KeystoreCacheRef
81+
keysFilter*: HashSet[ValidatorPubKey]
8182
eventBus*: EventBus
8283
vcProcess*: Process
8384
requestManager*: RequestManager

beacon_chain/conf.nim

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ type
187187
name: "web3-signer-update-interval"
188188
defaultValue: 3600 .}: Natural
189189

190+
web3SignersKeyFilter* {.
191+
desc: "Validator keys which will be used with remote Web3Signer"
192+
name: "web3-signer-key" .}: seq[ValidatorPubKey]
193+
190194
secretsDirFlag* {.
191195
desc: "A directory containing validator keystore passwords"
192196
name: "secrets-dir" .}: Option[InputDir]
@@ -938,6 +942,10 @@ type
938942
desc: "Remote Web3Signer URL that will be used as a source of validators"
939943
name: "web3-signer-url" .}: seq[Uri]
940944

945+
web3SignersKeyFilter* {.
946+
desc: "Validator keys which will be used with remote Web3Signer"
947+
name: "web3-signer-key" .}: seq[ValidatorPubKey]
948+
941949
secretsDirFlag* {.
942950
desc: "A directory containing validator keystore passwords"
943951
name: "secrets-dir" .}: Option[InputDir]

beacon_chain/nimbus_beacon_node.nim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,8 @@ proc init*(T: type BeaconNode,
818818
beaconClock: beaconClock,
819819
validatorMonitor: validatorMonitor,
820820
stateTtlCache: stateTtlCache,
821-
dynamicFeeRecipientsStore: newClone(DynamicFeeRecipientsStore.init()))
821+
dynamicFeeRecipientsStore: newClone(DynamicFeeRecipientsStore.init()),
822+
keysFilter: toHashSet(config.web3SignersKeyFilter))
822823

823824
node.initLightClient(
824825
rng, cfg, dag.forkDigests, getBeaconTime, dag.genesis_validators_root)

beacon_chain/nimbus_validator_client.nim

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,29 @@ proc initGenesis(vc: ValidatorClientRef): Future[RestGenesis] {.async.} =
9898
dec(counter)
9999
return melem
100100

101-
proc addValidatorsFromWeb3Signer(vc: ValidatorClientRef, web3signerUrl: Web3SignerUrl) {.async.} =
102-
let res = await queryValidatorsSource(web3signerUrl)
103-
if res.isOk():
104-
let dynamicKeystores = res.get()
105-
for keystore in dynamicKeystores:
106-
vc.addValidator(keystore)
101+
proc addValidatorsFromWeb3Signer(vc: ValidatorClientRef,
102+
web3signerUrl: Web3SignerUrl) {.async.} =
103+
let keystores =
104+
try:
105+
let res = await queryValidatorsSource(web3signerUrl)
106+
if res.isErr():
107+
# Error is already reported via log warning.
108+
default(seq[KeystoreData])
109+
else:
110+
res.get()
111+
except CatchableError as exc:
112+
warn "Unexpected error happens while polling validator's source",
113+
error = $exc.name, reason = $exc.msg
114+
default(seq[KeystoreData])
115+
116+
proc addValidatorProc(data: KeystoreData) =
117+
vc.addValidator(data)
118+
119+
debug "Web3Signer has been polled for validators",
120+
keystores_found = len(keystores),
121+
web3signer_url = web3signerUrl.url
122+
vc.attachedValidators.updateDynamicValidators(
123+
web3signerUrl, keystores, vc.keysFilter, addValidatorProc)
107124

108125
proc initValidators(vc: ValidatorClientRef): Future[bool] {.async.} =
109126
info "Loading validators", validatorsDir = vc.config.validatorsDir()
@@ -283,6 +300,7 @@ proc new*(T: type ValidatorClientRef,
283300
doppelExit: newAsyncEvent(),
284301
indicesAvailable: newAsyncEvent(),
285302
dynamicFeeRecipientsStore: newClone(DynamicFeeRecipientsStore.init()),
303+
keysFilter: toHashSet(config.web3SignersKeyFilter),
286304
sigintHandleFut: waitSignal(SIGINT),
287305
sigtermHandleFut: waitSignal(SIGTERM),
288306
keystoreCache: KeystoreCacheRef.init()
@@ -300,6 +318,7 @@ proc new*(T: type ValidatorClientRef,
300318
indicesAvailable: newAsyncEvent(),
301319
doppelExit: newAsyncEvent(),
302320
dynamicFeeRecipientsStore: newClone(DynamicFeeRecipientsStore.init()),
321+
keysFilter: toHashSet(config.web3SignersKeyFilter),
303322
sigintHandleFut: newFuture[void]("sigint_placeholder"),
304323
sigtermHandleFut: newFuture[void]("sigterm_placeholder"),
305324
keystoreCache: KeystoreCacheRef.init()

beacon_chain/validator_client/common.nim

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ type
233233
rootsSeen*: Table[Eth2Digest, Slot]
234234
processingDelay*: Opt[Duration]
235235
finalizedEpoch*: Opt[Epoch]
236+
keysFilter*: HashSet[ValidatorPubKey]
236237
rng*: ref HmacDrbgContext
237238

238239
ApiStrategyKind* {.pure.} = enum
@@ -911,24 +912,6 @@ proc getSubcommitteeIndex*(index: IndexInSyncCommittee): SyncSubcommitteeIndex =
911912
proc currentSlot*(vc: ValidatorClientRef): Slot =
912913
vc.beaconClock.now().slotOrZero()
913914

914-
proc addValidator*(vc: ValidatorClientRef, keystore: KeystoreData) =
915-
let
916-
withdrawalAddress =
917-
if vc.keymanagerHost.isNil:
918-
Opt.none Eth1Address
919-
else:
920-
vc.keymanagerHost[].getValidatorWithdrawalAddress(keystore.pubkey)
921-
perValidatorDefaultFeeRecipient = getPerValidatorDefaultFeeRecipient(
922-
vc.config.defaultFeeRecipient, withdrawalAddress)
923-
feeRecipient = vc.config.validatorsDir.getSuggestedFeeRecipient(
924-
keystore.pubkey, perValidatorDefaultFeeRecipient).valueOr(
925-
perValidatorDefaultFeeRecipient)
926-
gasLimit = vc.config.validatorsDir.getSuggestedGasLimit(
927-
keystore.pubkey, vc.config.suggestedGasLimit).valueOr(
928-
vc.config.suggestedGasLimit)
929-
930-
discard vc.attachedValidators[].addValidator(keystore, feeRecipient, gasLimit)
931-
932915
proc removeValidator*(vc: ValidatorClientRef,
933916
pubkey: ValidatorPubKey) {.async.} =
934917
let validator = vc.attachedValidators[].getValidator(pubkey).valueOr:
@@ -961,6 +944,19 @@ proc getGasLimit(vc: ValidatorClientRef,
961944
getGasLimit(vc.config.validatorsDir, vc.config.suggestedGasLimit,
962945
validator.pubkey)
963946

947+
proc addValidator*(vc: ValidatorClientRef, keystore: KeystoreData) =
948+
let
949+
currentEpoch = vc.beaconClock.now().slotOrZero().epoch()
950+
feeRecipient = getFeeRecipient(
951+
vc.dynamicFeeRecipientsStore, keystore.pubkey, Opt.none(ValidatorIndex),
952+
Opt.none(Validator), vc.config.defaultFeeRecipient(),
953+
vc.config.validatorsDir(), currentEpoch)
954+
gasLimit =
955+
getGasLimit(vc.config.validatorsDir, vc.config.suggestedGasLimit,
956+
keystore.pubkey)
957+
958+
discard vc.attachedValidators[].addValidator(keystore, feeRecipient, gasLimit)
959+
964960
proc prepareProposersList*(vc: ValidatorClientRef,
965961
epoch: Epoch): seq[PrepareBeaconProposer] =
966962
var res: seq[PrepareBeaconProposer]

beacon_chain/validator_client/duties_service.nim

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -649,9 +649,9 @@ proc dynamicValidatorsLoop*(service: DutiesServiceRef,
649649
debug "Web3Signer has been polled for validators",
650650
keystores_found = len(keystores),
651651
web3signer_url = web3signerUrl.url
652-
vc.attachedValidators.updateDynamicValidators(web3signerUrl,
653-
keystores,
654-
addValidatorProc)
652+
vc.attachedValidators.updateDynamicValidators(
653+
web3signerUrl, keystores, vc.keysFilter,
654+
addValidatorProc)
655655
seconds(intervalInSeconds)
656656
else:
657657
seconds(5)

beacon_chain/validators/beacon_validators.nim

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ proc getValidator*(validators: auto,
105105
Opt.some ValidatorAndIndex(index: ValidatorIndex(idx),
106106
validator: validators[idx])
107107

108-
proc addValidatorsFromWeb3Signer(node: BeaconNode, web3signerUrl: Web3SignerUrl, epoch: Epoch) {.async.} =
108+
proc addValidatorsFromWeb3Signer(node: BeaconNode, web3signerUrl: Web3SignerUrl,
109+
epoch: Epoch) {.async.} =
109110
let dynamicStores =
110111
try:
111112
let res = await queryValidatorsSource(web3signerUrl)
@@ -119,22 +120,22 @@ proc addValidatorsFromWeb3Signer(node: BeaconNode, web3signerUrl: Web3SignerUrl,
119120
error = $exc.name, reason = $exc.msg
120121
default(seq[KeystoreData])
121122

122-
for keystore in dynamicStores:
123+
proc addValidatorProc(keystore: KeystoreData) =
123124
let
124-
data =
125-
withState(node.dag.headState):
126-
getValidator(forkyState.data.validators.asSeq(), keystore.pubkey)
127-
index =
128-
if data.isSome():
129-
Opt.some(data.get().index)
130-
else:
131-
Opt.none(ValidatorIndex)
125+
epoch = node.currentSlot().epoch
126+
index = Opt.none(ValidatorIndex)
132127
feeRecipient =
133128
node.consensusManager[].getFeeRecipient(keystore.pubkey, index, epoch)
134-
gasLimit = node.consensusManager[].getGasLimit(keystore.pubkey)
135-
v = node.attachedValidators[].addValidator(keystore, feeRecipient,
136-
gasLimit)
137-
v.updateValidator(data)
129+
gasLimit =
130+
node.consensusManager[].getGasLimit(keystore.pubkey)
131+
discard node.attachedValidators[].addValidator(keystore, feeRecipient,
132+
gasLimit)
133+
134+
debug "Validators source has been polled for validators",
135+
keystores_found = len(dynamicStores),
136+
web3signer_url = web3signerUrl.url
137+
node.attachedValidators.updateDynamicValidators(
138+
web3signerUrl, dynamicStores, node.keysFilter, addValidatorProc)
138139

139140
proc addValidators*(node: BeaconNode) {.async.} =
140141
info "Loading validators", validatorsDir = node.config.validatorsDir(),
@@ -198,9 +199,8 @@ proc pollForDynamicValidators*(node: BeaconNode,
198199
debug "Validators source has been polled for validators",
199200
keystores_found = len(keystores),
200201
web3signer_url = web3signerUrl.url
201-
node.attachedValidators.updateDynamicValidators(web3signerUrl,
202-
keystores,
203-
addValidatorProc)
202+
node.attachedValidators.updateDynamicValidators(
203+
web3signerUrl, keystores, node.keysFilter, addValidatorProc)
204204
seconds(intervalInSeconds)
205205
else:
206206
# In case of error we going to repeat our call with much smaller

beacon_chain/validators/validator_pool.nim

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
{.push raises: [].}
99

1010
import
11-
std/[tables, json, streams, sequtils, uri],
11+
std/[tables, sets, json, streams, sequtils, uri],
1212
chronos, chronicles, metrics,
1313
json_serialization/std/net,
1414
presto/client,
@@ -391,13 +391,15 @@ func triggersDoppelganger*(
391391
proc updateDynamicValidators*(pool: ref ValidatorPool,
392392
web3signerUrl: Web3SignerUrl,
393393
keystores: openArray[KeystoreData],
394+
keysFilter: HashSet[ValidatorPubKey],
394395
addProc: AddValidatorProc) =
395396
var
396397
keystoresTable: Table[ValidatorPubKey, Opt[KeystoreData]]
397398
deleteValidators: seq[ValidatorPubKey]
398399

399400
for keystore in keystores:
400-
keystoresTable[keystore.pubkey] = Opt.some(keystore)
401+
if (len(keysFilter) == 0) or (keystore.pubkey in keysFilter):
402+
keystoresTable[keystore.pubkey] = Opt.some(keystore)
401403

402404
# We preserve `Local` and `Remote` keystores which are not from dynamic set,
403405
# and also we removing all the dynamic keystores which are not part of new
@@ -421,8 +423,10 @@ proc updateDynamicValidators*(pool: ref ValidatorPool,
421423
pool[].removeValidator(pubkey)
422424

423425
# Adding new dynamic keystores.
424-
for keystore in keystores.items():
425-
let res = pool[].getValidator(keystore.pubkey)
426+
for value in keystoresTable.values():
427+
let
428+
keystore = value.get()
429+
res = pool[].getValidator(keystore.pubkey)
426430
if res.isSome():
427431
let validator = res.get()
428432
if validator.kind != ValidatorKind.Remote or

0 commit comments

Comments
 (0)