From e8e67ec77167be7c005c1d7b3b0346e8901c7500 Mon Sep 17 00:00:00 2001 From: tersec Date: Fri, 2 Jun 2023 11:06:33 +0000 Subject: [PATCH] allow payload builder client to be function of validator/proposer (#5015) * allow payload builder client to be function of validator/proposer * fileExists has side effects on Windows and only Windows * another not-always-func --- beacon_chain/beacon_node.nim | 3 +- beacon_chain/rpc/rest_beacon_api.nim | 40 ++++++++------- beacon_chain/rpc/rest_validator_api.nim | 3 +- .../validators/keystore_management.nim | 50 +++++++++---------- beacon_chain/validators/validator_duties.nim | 5 +- 5 files changed, 54 insertions(+), 47 deletions(-) diff --git a/beacon_chain/beacon_node.nim b/beacon_chain/beacon_node.nim index 61d5b023c..eb7fcf20b 100644 --- a/beacon_chain/beacon_node.nim +++ b/beacon_chain/beacon_node.nim @@ -115,7 +115,8 @@ template rng*(node: BeaconNode): ref HmacDrbgContext = proc currentSlot*(node: BeaconNode): Slot = node.beaconClock.now.slotOrZero -proc getPayloadBuilderClient*(node: BeaconNode): RestResult[RestClientRef] = +proc getPayloadBuilderClient*( + node: BeaconNode, validator_index: uint64): RestResult[RestClientRef] = if node.config.payloadBuilderEnable: # Logging done in caller let res = RestClientRef.new(node.config.payloadBuilderUrl) diff --git a/beacon_chain/rpc/rest_beacon_api.nim b/beacon_chain/rpc/rest_beacon_api.nim index fffeeb561..3e3bbb523 100644 --- a/beacon_chain/rpc/rest_beacon_api.nim +++ b/beacon_chain/rpc/rest_beacon_api.nim @@ -886,21 +886,21 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = currentEpochFork.toString != version: return RestApiResponse.jsonError(Http400, BlockIncorrectFork) - let payloadBuilderClient = node.getPayloadBuilderClient().valueOr: - return RestApiResponse.jsonError( - Http400, "Unable to initialize payload builder client: " & $error) - case currentEpochFork of ConsensusFork.Deneb: return RestApiResponse.jsonError(Http500, $denebImplementationMissing) of ConsensusFork.Capella: - let res = - block: - let restBlock = decodeBodyJsonOrSsz( - capella_mev.SignedBlindedBeaconBlock, body).valueOr: - return RestApiResponse.jsonError(Http400, InvalidBlockObjectError, - $error) - await node.unblindAndRouteBlockMEV(payloadBuilderClient, restBlock) + let + restBlock = decodeBodyJsonOrSsz( + capella_mev.SignedBlindedBeaconBlock, body).valueOr: + return RestApiResponse.jsonError(Http400, InvalidBlockObjectError, + $error) + payloadBuilderClient = node.getPayloadBuilderClient( + restBlock.message.proposer_index).valueOr: + return RestApiResponse.jsonError( + Http400, "Unable to initialize payload builder client: " & $error) + res = await node.unblindAndRouteBlockMEV( + payloadBuilderClient, restBlock) if res.isErr(): return RestApiResponse.jsonError( @@ -910,13 +910,17 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = return RestApiResponse.jsonMsgResponse(BlockValidationSuccess) of ConsensusFork.Bellatrix: - let res = - block: - let restBlock = decodeBodyJsonOrSsz( - bellatrix_mev.SignedBlindedBeaconBlock, body).valueOr: - return RestApiResponse.jsonError(Http400, InvalidBlockObjectError, - $error) - await node.unblindAndRouteBlockMEV(payloadBuilderClient, restBlock) + let + restBlock = decodeBodyJsonOrSsz( + bellatrix_mev.SignedBlindedBeaconBlock, body).valueOr: + return RestApiResponse.jsonError(Http400, InvalidBlockObjectError, + $error) + payloadBuilderClient = node.getPayloadBuilderClient( + restBlock.message.proposer_index).valueOr: + return RestApiResponse.jsonError( + Http400, "Unable to initialize payload builder client: " & $error) + res = await node.unblindAndRouteBlockMEV( + payloadBuilderClient, restBlock) if res.isErr(): return RestApiResponse.jsonError( diff --git a/beacon_chain/rpc/rest_validator_api.nim b/beacon_chain/rpc/rest_validator_api.nim index 09cde2647..e6f5f9437 100644 --- a/beacon_chain/rpc/rest_validator_api.nim +++ b/beacon_chain/rpc/rest_validator_api.nim @@ -509,7 +509,8 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) = RestApiResponse.jsonError(Http500, InvalidAcceptError) let - payloadBuilderClient = node.getPayloadBuilderClient().valueOr: + payloadBuilderClient = node.getPayloadBuilderClient( + proposer.distinctBase).valueOr: return RestApiResponse.jsonError( Http500, "Unable to initialize payload builder client: " & $error) contextFork = node.dag.cfg.consensusForkAtEpoch(node.currentSlot.epoch) diff --git a/beacon_chain/validators/keystore_management.nim b/beacon_chain/validators/keystore_management.nim index bb0935e60..6575c52c4 100644 --- a/beacon_chain/validators/keystore_management.nim +++ b/beacon_chain/validators/keystore_management.nim @@ -92,7 +92,7 @@ const "passwords" / "10-million-password-list-top-100000.txt", minWordLen = minPasswordLen) -proc dispose*(decryptor: var MultipleKeystoresDecryptor) = +func dispose*(decryptor: var MultipleKeystoresDecryptor) = burnMem(decryptor.previouslyUsedPassword) func init*(T: type KeymanagerHost, @@ -134,8 +134,8 @@ func init*(T: type KeystoreData, pubkey: privateKey.toPubKey().toPubKey() ) -func init*(T: type KeystoreData, keystore: RemoteKeystore, - handle: FileLockHandle): Result[T, cstring] {.raises: [Defect].} = +func init(T: type KeystoreData, keystore: RemoteKeystore, + handle: FileLockHandle): Result[T, cstring] {.raises: [Defect].} = let cookedKey = keystore.pubkey.load().valueOr: return err("Invalid validator's public key") @@ -162,9 +162,9 @@ func init*(T: type KeystoreData, keystore: RemoteKeystore, remoteType: RemoteSignerType.VerifyingWeb3Signer, provenBlockProperties: keystore.provenBlockProperties) -func init*(T: type KeystoreData, cookedKey: CookedPubKey, - remotes: seq[RemoteSignerInfo], threshold: uint32, - handle: FileLockHandle): T = +func init(T: type KeystoreData, cookedKey: CookedPubKey, + remotes: seq[RemoteSignerInfo], threshold: uint32, + handle: FileLockHandle): T = KeystoreData( kind: KeystoreKind.Remote, handle: handle, @@ -178,7 +178,7 @@ func init(T: type AddValidatorFailure, status: AddValidatorStatus, msg = ""): AddValidatorFailure {.raises: [Defect].} = AddValidatorFailure(status: status, message: msg) -func toKeystoreKind*(kind: ValidatorKind): KeystoreKind {.raises: [Defect].} = +func toKeystoreKind(kind: ValidatorKind): KeystoreKind {.raises: [Defect].} = case kind of ValidatorKind.Local: KeystoreKind.Local @@ -240,7 +240,7 @@ proc checkAndCreateDataDir*(dataDir: string): bool = return true -proc checkSensitivePathPermissions*(dirFilePath: string): bool = +proc checkSensitivePathPermissions(dirFilePath: string): bool = ## If ``dirFilePath`` is file, then check if file has only ## ## - "(600) rwx------" permissions on Posix (Linux, MacOS, BSD) @@ -392,7 +392,7 @@ proc keyboardGetPassword[T](prompt: string, attempts: int, dec(remainingAttempts) err("Failed to decrypt keystore") -proc loadSecretFile*(path: string): KsResult[KeystorePass] {. +proc loadSecretFile(path: string): KsResult[KeystorePass] {. raises: [Defect].} = let res = readAllChars(path) if res.isErr(): @@ -618,7 +618,7 @@ proc removeValidator*(pool: var ValidatorPool, pool.removeValidator(publicKey) ok(res.value()) -proc checkKeyName*(keyName: string): bool = +func checkKeyName(keyName: string): bool = const keyAlphabet = {'a'..'f', 'A'..'F', '0'..'9'} if len(keyName) != KeyNameSize: return false @@ -629,7 +629,7 @@ proc checkKeyName*(keyName: string): bool = return false true -proc existsKeystore*(keystoreDir: string, keyKind: KeystoreKind): bool {. +proc existsKeystore(keystoreDir: string, keyKind: KeystoreKind): bool {. raises: [Defect].} = case keyKind of KeystoreKind.Local: @@ -637,8 +637,8 @@ proc existsKeystore*(keystoreDir: string, keyKind: KeystoreKind): bool {. of KeystoreKind.Remote: fileExists(keystoreDir / RemoteKeystoreFileName) -proc existsKeystore*(keystoreDir: string, - keysMask: set[KeystoreKind]): bool {.raises: [Defect].} = +proc existsKeystore(keystoreDir: string, + keysMask: set[KeystoreKind]): bool {.raises: [Defect].} = if KeystoreKind.Local in keysMask: if existsKeystore(keystoreDir, KeystoreKind.Local): return true @@ -820,7 +820,7 @@ type DuplicateKeystoreFile: error*: string -proc mapErrTo*[T, E](r: Result[T, E], v: static KeystoreGenerationErrorKind): +func mapErrTo*[T, E](r: Result[T, E], v: static KeystoreGenerationErrorKind): Result[T, KeystoreGenerationError] = r.mapErr(proc (e: E): KeystoreGenerationError = KeystoreGenerationError(kind: v, error: $e)) @@ -948,7 +948,7 @@ proc createLocalValidatorFiles*( success = true ok() -proc createLockedLocalValidatorFiles*( +proc createLockedLocalValidatorFiles( secretsDir, validatorsDir, keystoreDir, secretFile, passwordAsString, keystoreFile, encodedStorage: string @@ -1022,7 +1022,7 @@ proc createRemoteValidatorFiles*( success = true ok() -proc createLockedRemoteValidatorFiles*( +proc createLockedRemoteValidatorFiles( validatorsDir, keystoreDir, keystoreFile, encodedStorage: string ): Result[FileLockHandle, KeystoreGenerationError] {.raises: [Defect].} = var @@ -1089,7 +1089,7 @@ proc saveKeystore*( keystoreFile, encodedStorage) ok() -proc saveLockedKeystore*( +proc saveLockedKeystore( rng: var HmacDrbgContext, validatorsDir, secretsDir: string, signingKey: ValidatorPrivKey, @@ -1130,7 +1130,7 @@ proc saveLockedKeystore*( keystoreFile, encodedStorage) ok(lock) -proc saveKeystore*( +proc saveKeystore( validatorsDir: string, publicKey: ValidatorPubKey, urls: seq[RemoteSignerInfo], @@ -1172,7 +1172,7 @@ proc saveKeystore*( encodedStorage) ok() -proc saveLockedKeystore*( +proc saveLockedKeystore( validatorsDir: string, publicKey: ValidatorPubKey, urls: seq[RemoteSignerInfo], @@ -1222,7 +1222,7 @@ proc saveKeystore*( let remoteInfo = RemoteSignerInfo(url: url, id: 0) saveKeystore(validatorsDir, publicKey, @[remoteInfo], 1) -proc saveLockedKeystore*( +proc saveLockedKeystore( validatorsDir: string, publicKey: ValidatorPubKey, url: HttpHostUri @@ -1338,12 +1338,12 @@ func validatorKeystoreDir(host: KeymanagerHost, pubkey: ValidatorPubKey): string = host.validatorsDir.validatorKeystoreDir(pubkey) -func feeRecipientPath*(host: KeymanagerHost, - pubkey: ValidatorPubKey): string = +func feeRecipientPath(host: KeymanagerHost, + pubkey: ValidatorPubKey): string = host.validatorsDir.feeRecipientPath(pubkey) -func gasLimitPath*(host: KeymanagerHost, - pubkey: ValidatorPubKey): string = +func gasLimitPath(host: KeymanagerHost, + pubkey: ValidatorPubKey): string = host.validatorsDir.gasLimitPath(pubkey) proc removeFeeRecipientFile*(host: KeymanagerHost, @@ -1535,7 +1535,7 @@ proc generateDeposits*(cfg: RuntimeConfig, ok deposits -proc saveWallet*(wallet: Wallet, outWalletPath: string): Result[void, string] = +proc saveWallet(wallet: Wallet, outWalletPath: string): Result[void, string] = let walletDir = splitFile(outWalletPath).dir var encodedWallet: string try: diff --git a/beacon_chain/validators/validator_duties.nim b/beacon_chain/validators/validator_duties.nim index 1dc710f2a..288e28749 100644 --- a/beacon_chain/validators/validator_duties.nim +++ b/beacon_chain/validators/validator_duties.nim @@ -793,7 +793,8 @@ proc proposeBlockAux( # Collect bids var payloadBuilderClient: RestClientRef - let payloadBuilderClientMaybe = node.getPayloadBuilderClient() + let payloadBuilderClientMaybe = node.getPayloadBuilderClient( + validator_index.distinctBase) if payloadBuilderClientMaybe.isErr: warn "Unable to initialize payload builder client while proposing block", err = payloadBuilderClientMaybe.error @@ -1399,7 +1400,7 @@ proc registerValidators*(node: BeaconNode, epoch: Epoch) {.async.} = const HttpOk = 200 - let payloadBuilderClient = node.getPayloadBuilderClient().valueOr: + let payloadBuilderClient = node.getPayloadBuilderClient(0).valueOr: debug "Unable to initialize payload builder client while registering validators", err = error return