2021-03-26 06:52:01 +00:00
|
|
|
# beacon_chain
|
2022-01-29 01:05:39 +00:00
|
|
|
# Copyright (c) 2018-2022 Status Research & Development GmbH
|
2021-03-26 06:52:01 +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.
|
|
|
|
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
|
2018-11-23 23:58:49 +00:00
|
|
|
import
|
2022-05-10 00:32:12 +00:00
|
|
|
std/[options, tables, json, streams, sequtils, uri],
|
2020-11-27 22:16:13 +00:00
|
|
|
chronos, chronicles, metrics,
|
2021-10-19 14:09:26 +00:00
|
|
|
json_serialization/std/net,
|
2021-11-30 01:20:21 +00:00
|
|
|
presto, presto/client,
|
|
|
|
|
|
|
|
../spec/[keystore, signatures, helpers, crypto],
|
2021-08-17 08:07:17 +00:00
|
|
|
../spec/datatypes/[phase0, altair],
|
2021-11-30 01:20:21 +00:00
|
|
|
../spec/eth2_apis/[rest_types, eth2_rest_serialization,
|
|
|
|
rest_remote_signer_calls],
|
2021-03-02 10:27:45 +00:00
|
|
|
./slashing_protection
|
2020-11-27 22:16:13 +00:00
|
|
|
|
2021-10-19 14:09:26 +00:00
|
|
|
export
|
2021-11-30 01:20:21 +00:00
|
|
|
streams, options, keystore, phase0, altair, tables, uri, crypto,
|
2022-02-11 20:40:49 +00:00
|
|
|
rest_types, eth2_rest_serialization, rest_remote_signer_calls,
|
|
|
|
slashing_protection
|
2021-10-19 14:09:26 +00:00
|
|
|
|
2020-11-27 22:16:13 +00:00
|
|
|
declareGauge validators,
|
|
|
|
"Number of validators attached to the beacon node"
|
2018-11-23 23:58:49 +00:00
|
|
|
|
2021-10-19 14:09:26 +00:00
|
|
|
type
|
|
|
|
ValidatorKind* {.pure.} = enum
|
|
|
|
Local, Remote
|
|
|
|
|
2021-11-30 01:20:21 +00:00
|
|
|
ValidatorConnection* = RestClientRef
|
2021-10-19 14:09:26 +00:00
|
|
|
|
|
|
|
AttachedValidator* = ref object
|
2021-12-22 12:37:31 +00:00
|
|
|
pubkey*: ValidatorPubKey
|
|
|
|
data*: KeystoreData
|
2021-10-19 14:09:26 +00:00
|
|
|
case kind*: ValidatorKind
|
|
|
|
of ValidatorKind.Local:
|
2021-11-30 01:20:21 +00:00
|
|
|
discard
|
2021-10-19 14:09:26 +00:00
|
|
|
of ValidatorKind.Remote:
|
2022-05-10 00:32:12 +00:00
|
|
|
clients*: seq[(RestClientRef, RemoteSignerInfo)]
|
|
|
|
threshold*: uint32
|
2021-10-19 14:09:26 +00:00
|
|
|
|
|
|
|
# The index at which this validator has been observed in the chain -
|
|
|
|
# it does not change as long as there are no reorgs on eth1 - however, the
|
|
|
|
# index might not be valid in all eth2 histories, so it should not be
|
|
|
|
# assumed that a valid index is stored here!
|
|
|
|
index*: Option[ValidatorIndex]
|
|
|
|
|
|
|
|
# Cache the latest slot signature - the slot signature is used to determine
|
|
|
|
# if the validator will be aggregating (in the near future)
|
|
|
|
slotSignature*: Option[tuple[slot: Slot, signature: ValidatorSig]]
|
|
|
|
|
2021-11-30 01:20:21 +00:00
|
|
|
SignResponse* = Web3SignerDataResponse
|
|
|
|
|
|
|
|
SignatureResult* = Result[ValidatorSig, string]
|
|
|
|
AttestationResult* = Result[Attestation, string]
|
|
|
|
SyncCommitteeMessageResult* = Result[SyncCommitteeMessage, string]
|
|
|
|
|
2021-10-19 14:09:26 +00:00
|
|
|
ValidatorPool* = object
|
|
|
|
validators*: Table[ValidatorPubKey, AttachedValidator]
|
|
|
|
slashingProtection*: SlashingProtectionDB
|
|
|
|
|
2021-11-30 01:20:21 +00:00
|
|
|
func shortLog*(v: AttachedValidator): string =
|
|
|
|
case v.kind
|
|
|
|
of ValidatorKind.Local:
|
2021-12-22 12:37:31 +00:00
|
|
|
shortLog(v.pubkey)
|
2021-11-30 01:20:21 +00:00
|
|
|
of ValidatorKind.Remote:
|
2022-05-10 00:32:12 +00:00
|
|
|
shortLog(v.pubkey)
|
2021-10-19 14:09:26 +00:00
|
|
|
|
2020-09-16 11:30:03 +00:00
|
|
|
func init*(T: type ValidatorPool,
|
|
|
|
slashingProtectionDB: SlashingProtectionDB): T =
|
|
|
|
## Initialize the validator pool and the slashing protection service
|
2021-02-09 15:23:06 +00:00
|
|
|
## `genesis_validators_root` is used as an unique ID for the
|
2020-09-16 11:30:03 +00:00
|
|
|
## blockchain
|
|
|
|
## `backend` is the KeyValue Store backend
|
2021-07-13 11:15:07 +00:00
|
|
|
T(slashingProtection: slashingProtectionDB)
|
2018-11-23 23:58:49 +00:00
|
|
|
|
2018-12-19 12:58:53 +00:00
|
|
|
template count*(pool: ValidatorPool): int =
|
2021-07-13 11:15:07 +00:00
|
|
|
len(pool.validators)
|
2018-12-19 12:58:53 +00:00
|
|
|
|
2021-12-22 12:37:31 +00:00
|
|
|
proc addLocalValidator*(pool: var ValidatorPool, item: KeystoreData,
|
2020-11-27 23:34:25 +00:00
|
|
|
index: Option[ValidatorIndex]) =
|
2022-05-10 00:32:12 +00:00
|
|
|
doAssert item.kind == KeystoreKind.Local
|
2021-12-22 12:37:31 +00:00
|
|
|
let pubkey = item.pubkey
|
|
|
|
let v = AttachedValidator(kind: ValidatorKind.Local, pubkey: pubkey,
|
2021-10-04 19:08:31 +00:00
|
|
|
index: index, data: item)
|
2021-12-22 12:37:31 +00:00
|
|
|
pool.validators[pubkey] = v
|
|
|
|
notice "Local validator attached", pubkey, validator = shortLog(v)
|
2021-07-13 11:15:07 +00:00
|
|
|
validators.set(pool.count().int64)
|
2019-04-06 07:46:07 +00:00
|
|
|
|
2021-12-22 12:37:31 +00:00
|
|
|
proc addLocalValidator*(pool: var ValidatorPool, item: KeystoreData) =
|
2021-10-04 19:08:31 +00:00
|
|
|
addLocalValidator(pool, item, none[ValidatorIndex]())
|
2020-11-27 22:16:13 +00:00
|
|
|
|
2021-12-22 12:37:31 +00:00
|
|
|
proc addRemoteValidator*(pool: var ValidatorPool, item: KeystoreData,
|
2022-05-10 00:32:12 +00:00
|
|
|
clients: seq[(RestClientRef, RemoteSignerInfo)], index: Option[ValidatorIndex]) =
|
|
|
|
doAssert item.kind == KeystoreKind.Remote
|
2021-12-22 12:37:31 +00:00
|
|
|
let pubkey = item.pubkey
|
|
|
|
let v = AttachedValidator(kind: ValidatorKind.Remote, pubkey: pubkey,
|
2022-05-10 00:32:12 +00:00
|
|
|
index: index, data: item, clients: clients)
|
2021-12-22 12:37:31 +00:00
|
|
|
pool.validators[pubkey] = v
|
|
|
|
notice "Remote validator attached", pubkey, validator = shortLog(v),
|
2022-05-10 00:32:12 +00:00
|
|
|
remote_signer = $item.remotes
|
2020-11-27 22:16:13 +00:00
|
|
|
validators.set(pool.count().int64)
|
|
|
|
|
2020-08-10 13:21:31 +00:00
|
|
|
proc getValidator*(pool: ValidatorPool,
|
2018-11-29 01:08:34 +00:00
|
|
|
validatorKey: ValidatorPubKey): AttachedValidator =
|
performance fixes (#2259)
* performance fixes
* don't mark tree cache as dirty on read-only List accesses
* store only blob in memory for keys and signatures, parse blob lazily
* compare public keys by blob instead of parsing / converting to raw
* compare Eth2Digest using non-constant-time comparison
* avoid some unnecessary validator copying
This branch will in particular speed up deposit processing which has
been slowing down block replay.
Pre (mainnet, 1600 blocks):
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3450.269, 0.000, 3450.269, 3450.269, 1, Initialize DB
0.417, 0.822, 0.036, 21.098, 1400, Load block from database
16.521, 0.000, 16.521, 16.521, 1, Load state from database
27.906, 50.846, 8.104, 1507.633, 1350, Apply block
52.617, 37.029, 20.640, 135.938, 50, Apply epoch block
```
Post:
```
3502.715, 0.000, 3502.715, 3502.715, 1, Initialize DB
0.080, 0.560, 0.035, 21.015, 1400, Load block from database
17.595, 0.000, 17.595, 17.595, 1, Load state from database
15.706, 11.028, 8.300, 107.537, 1350, Apply block
33.217, 12.622, 17.331, 60.580, 50, Apply epoch block
```
* more perf fixes
* load EpochRef cache into StateCache more aggressively
* point out security concern with public key cache
* reuse proposer index from state when processing block
* avoid genericAssign in a few more places
* don't parse key when signature is unparseable
* fix `==` overload for Eth2Digest
* preallocate validator list when getting active validators
* speed up proposer index calculation a little bit
* reuse cache when replaying blocks in ncli_db
* avoid a few more copying loops
```
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3279.158, 0.000, 3279.158, 3279.158, 1, Initialize DB
0.072, 0.357, 0.035, 13.400, 1400, Load block from database
17.295, 0.000, 17.295, 17.295, 1, Load state from database
5.918, 9.896, 0.198, 98.028, 1350, Apply block
15.888, 10.951, 7.902, 39.535, 50, Apply epoch block
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
* clear full balance cache before processing rewards and penalties
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3947.901, 0.000, 3947.901, 3947.901, 1, Initialize DB
0.124, 0.506, 0.026, 202.370, 363345, Load block from database
97.614, 0.000, 97.614, 97.614, 1, Load state from database
0.186, 0.188, 0.012, 99.561, 357262, Advance slot, non-epoch
14.161, 5.966, 1.099, 395.511, 11524, Advance slot, epoch
1.372, 4.170, 0.017, 276.401, 363345, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
2021-01-25 12:04:18 +00:00
|
|
|
pool.validators.getOrDefault(validatorKey)
|
2018-11-23 23:58:49 +00:00
|
|
|
|
2021-12-22 12:37:31 +00:00
|
|
|
proc contains*(pool: ValidatorPool, pubkey: ValidatorPubKey): bool =
|
|
|
|
## Returns ``true`` if validator with key ``pubkey`` present in ``pool``.
|
|
|
|
pool.validators.contains(pubkey)
|
2021-07-13 11:15:07 +00:00
|
|
|
|
2021-12-22 12:37:31 +00:00
|
|
|
proc removeValidator*(pool: var ValidatorPool, pubkey: ValidatorPubKey) =
|
|
|
|
## Delete validator with public key ``pubkey`` from ``pool``.
|
|
|
|
let validator = pool.validators.getOrDefault(pubkey)
|
2021-10-04 19:08:31 +00:00
|
|
|
if not(isNil(validator)):
|
2021-12-22 12:37:31 +00:00
|
|
|
pool.validators.del(pubkey)
|
2022-02-07 20:36:09 +00:00
|
|
|
case validator.kind
|
|
|
|
of ValidatorKind.Local:
|
|
|
|
notice "Local validator detached", pubkey, validator = shortLog(validator)
|
|
|
|
of ValidatorKind.Remote:
|
|
|
|
notice "Remote validator detached", pubkey,
|
|
|
|
validator = shortLog(validator)
|
2021-10-04 19:08:31 +00:00
|
|
|
validators.set(pool.count().int64)
|
2021-07-13 11:15:07 +00:00
|
|
|
|
2021-12-22 12:37:31 +00:00
|
|
|
proc updateValidator*(pool: var ValidatorPool, pubkey: ValidatorPubKey,
|
2021-07-13 11:15:07 +00:00
|
|
|
index: ValidatorIndex) =
|
2021-12-22 12:37:31 +00:00
|
|
|
## Set validator ``index`` to validator with public key ``pubkey`` stored
|
2021-07-13 11:15:07 +00:00
|
|
|
## in ``pool``.
|
2021-12-22 12:37:31 +00:00
|
|
|
## This procedure will not raise if validator with public key ``pubkey`` is
|
2021-07-13 11:15:07 +00:00
|
|
|
## not present in the pool.
|
|
|
|
var v: AttachedValidator
|
2021-12-22 12:37:31 +00:00
|
|
|
if pool.validators.pop(pubkey, v):
|
2021-07-13 11:15:07 +00:00
|
|
|
v.index = some(index)
|
2021-12-22 12:37:31 +00:00
|
|
|
pool.validators[pubkey] = v
|
2021-07-13 11:15:07 +00:00
|
|
|
|
|
|
|
iterator publicKeys*(pool: ValidatorPool): ValidatorPubKey =
|
|
|
|
for item in pool.validators.keys():
|
|
|
|
yield item
|
|
|
|
|
|
|
|
iterator indices*(pool: ValidatorPool): ValidatorIndex =
|
|
|
|
for item in pool.validators.values():
|
|
|
|
if item.index.isSome():
|
|
|
|
yield item.index.get()
|
|
|
|
|
|
|
|
iterator items*(pool: ValidatorPool): AttachedValidator =
|
|
|
|
for item in pool.validators.values():
|
|
|
|
yield item
|
|
|
|
|
2022-05-10 00:32:12 +00:00
|
|
|
proc signWithDistributedKey(v: AttachedValidator,
|
|
|
|
request: Web3SignerRequest): Future[SignatureResult]
|
|
|
|
{.async.} =
|
|
|
|
doAssert v.data.threshold <= uint32(v.clients.len)
|
|
|
|
|
|
|
|
let signatureReqs = mapIt(v.clients, it[0].signData(it[1].pubkey, request))
|
|
|
|
await allFutures(signatureReqs)
|
|
|
|
|
|
|
|
var shares: seq[SignatureShare]
|
|
|
|
var neededShares = v.data.threshold
|
|
|
|
|
|
|
|
for i, req in signatureReqs:
|
|
|
|
template shareInfo: untyped = v.clients[i][1]
|
|
|
|
if req.done and req.read.isOk:
|
|
|
|
shares.add req.read.get.toSignatureShare(shareInfo.id)
|
|
|
|
neededShares = neededShares - 1
|
|
|
|
else:
|
|
|
|
warn "Failed to obtain signature from remote signer",
|
|
|
|
pubkey = shareInfo.pubkey,
|
|
|
|
signerUrl = $(v.clients[i][0].address)
|
|
|
|
|
|
|
|
if neededShares == 0:
|
|
|
|
let recovered = shares.recoverSignature()
|
|
|
|
return SignatureResult.ok recovered.toValidatorSig
|
|
|
|
|
|
|
|
return SignatureResult.err "Not enough shares to recover the signature"
|
|
|
|
|
|
|
|
proc signWithSingleKey(v: AttachedValidator,
|
|
|
|
request: Web3SignerRequest): Future[SignatureResult]
|
|
|
|
{.async.} =
|
|
|
|
doAssert v.clients.len == 1
|
|
|
|
let (client, info) = v.clients[0]
|
|
|
|
let res = await client.signData(info.pubkey, request)
|
|
|
|
if res.isErr:
|
|
|
|
return SignatureResult.err res.error
|
|
|
|
else:
|
|
|
|
return SignatureResult.ok res.get.toValidatorSig
|
|
|
|
|
|
|
|
proc signData(v: AttachedValidator,
|
|
|
|
request: Web3SignerRequest): Future[SignatureResult]
|
|
|
|
{.async.} =
|
|
|
|
return
|
|
|
|
case v.kind
|
|
|
|
of ValidatorKind.Local:
|
|
|
|
SignatureResult.err "Invalid validator kind"
|
|
|
|
of ValidatorKind.Remote:
|
|
|
|
if v.clients.len == 1:
|
|
|
|
await v.signWithSingleKey(request)
|
|
|
|
else:
|
|
|
|
await v.signWithDistributedKey(request)
|
|
|
|
|
2021-11-30 01:20:21 +00:00
|
|
|
proc signWithRemoteValidator*(v: AttachedValidator, fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest,
|
2022-05-10 00:32:12 +00:00
|
|
|
blck: ForkedBeaconBlock): Future[SignatureResult]
|
|
|
|
{.async.} =
|
2022-05-17 16:55:03 +00:00
|
|
|
let request = Web3SignerRequest.init(fork, genesis_validators_root, blck.Web3SignerForkedBeaconBlock)
|
2021-11-30 01:20:21 +00:00
|
|
|
debug "Signing block proposal using remote signer",
|
|
|
|
validator = shortLog(v)
|
2022-05-10 00:32:12 +00:00
|
|
|
return await v.signData(request)
|
2021-11-30 01:20:21 +00:00
|
|
|
|
|
|
|
proc signWithRemoteValidator*(v: AttachedValidator, fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest,
|
2022-05-10 00:32:12 +00:00
|
|
|
adata: AttestationData): Future[SignatureResult]
|
|
|
|
{.async.} =
|
2021-11-30 01:20:21 +00:00
|
|
|
let request = Web3SignerRequest.init(fork, genesis_validators_root, adata)
|
|
|
|
debug "Signing block proposal using remote signer",
|
|
|
|
validator = shortLog(v)
|
2022-05-10 00:32:12 +00:00
|
|
|
return await v.signData(request)
|
2021-11-30 01:20:21 +00:00
|
|
|
|
|
|
|
proc signWithRemoteValidator*(v: AttachedValidator, fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest,
|
2022-05-10 00:32:12 +00:00
|
|
|
epoch: Epoch): Future[SignatureResult]
|
|
|
|
{.async.} =
|
2021-11-30 01:20:21 +00:00
|
|
|
let request = Web3SignerRequest.init(fork, genesis_validators_root, epoch)
|
|
|
|
debug "Generating randao reveal signature using remote signer",
|
|
|
|
validator = shortLog(v)
|
2022-05-10 00:32:12 +00:00
|
|
|
return await v.signData(request)
|
2021-11-30 01:20:21 +00:00
|
|
|
|
|
|
|
proc signWithRemoteValidator*(v: AttachedValidator, fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest,
|
2022-05-10 00:32:12 +00:00
|
|
|
proof: AggregateAndProof): Future[SignatureResult]
|
|
|
|
{.async.} =
|
2021-11-30 01:20:21 +00:00
|
|
|
let request = Web3SignerRequest.init(fork, genesis_validators_root, proof)
|
|
|
|
debug "Signing aggregate and proof using remote signer",
|
|
|
|
validator = shortLog(v)
|
2022-05-10 00:32:12 +00:00
|
|
|
return await v.signData(request)
|
2021-11-30 01:20:21 +00:00
|
|
|
|
|
|
|
proc signWithRemoteValidator*(v: AttachedValidator, fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest,
|
2022-05-10 00:32:12 +00:00
|
|
|
slot: Slot): Future[SignatureResult]
|
|
|
|
{.async.} =
|
2021-11-30 01:20:21 +00:00
|
|
|
let request = Web3SignerRequest.init(fork, genesis_validators_root, slot)
|
|
|
|
debug "Signing aggregate slot using remote signer",
|
|
|
|
validator = shortLog(v)
|
2022-05-10 00:32:12 +00:00
|
|
|
return await v.signData(request)
|
2021-11-30 01:20:21 +00:00
|
|
|
|
|
|
|
proc signWithRemoteValidator*(v: AttachedValidator, fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest,
|
|
|
|
slot: Slot,
|
2022-05-10 00:32:12 +00:00
|
|
|
blockRoot: Eth2Digest): Future[SignatureResult]
|
|
|
|
{.async.} =
|
2021-11-30 01:20:21 +00:00
|
|
|
let request = Web3SignerRequest.init(fork, genesis_validators_root, blockRoot,
|
|
|
|
slot)
|
|
|
|
debug "Signing sync committee message using remote signer",
|
|
|
|
validator = shortLog(v)
|
2022-05-10 00:32:12 +00:00
|
|
|
return await v.signData(request)
|
2021-11-30 01:20:21 +00:00
|
|
|
|
|
|
|
proc signWithRemoteValidator*(v: AttachedValidator, fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest,
|
|
|
|
slot: Slot,
|
2022-05-10 10:03:40 +00:00
|
|
|
subcommittee: SyncSubcommitteeIndex): Future[SignatureResult]
|
2022-05-10 00:32:12 +00:00
|
|
|
{.async.} =
|
2021-11-30 01:20:21 +00:00
|
|
|
let request = Web3SignerRequest.init(
|
|
|
|
fork, genesis_validators_root,
|
2022-05-10 10:03:40 +00:00
|
|
|
SyncAggregatorSelectionData(slot: slot, subcommittee_index: uint64 subcommittee)
|
2021-11-30 01:20:21 +00:00
|
|
|
)
|
|
|
|
debug "Signing sync aggregator selection data using remote signer",
|
|
|
|
validator = shortLog(v)
|
2022-05-10 00:32:12 +00:00
|
|
|
return await v.signData(request)
|
2021-11-30 01:20:21 +00:00
|
|
|
|
|
|
|
proc signWithRemoteValidator*(v: AttachedValidator, fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest,
|
|
|
|
contribution: ContributionAndProof
|
2022-05-10 00:32:12 +00:00
|
|
|
): Future[SignatureResult] {.async.} =
|
2021-11-30 01:20:21 +00:00
|
|
|
let request = Web3SignerRequest.init(
|
|
|
|
fork, genesis_validators_root, contribution
|
|
|
|
)
|
|
|
|
debug "Signing sync contribution and proof message using remote signer",
|
|
|
|
validator = shortLog(v)
|
2022-05-10 00:32:12 +00:00
|
|
|
return await v.signData(request)
|
2020-09-01 13:44:40 +00:00
|
|
|
|
2022-03-02 10:00:21 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/validator.md#signature
|
2020-03-30 11:31:44 +00:00
|
|
|
proc signBlockProposal*(v: AttachedValidator, fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest, slot: Slot,
|
2021-11-30 01:20:21 +00:00
|
|
|
blockRoot: Eth2Digest, blck: ForkedBeaconBlock
|
2022-05-10 00:32:12 +00:00
|
|
|
): Future[SignatureResult] {.async.} =
|
2021-10-04 19:08:31 +00:00
|
|
|
return
|
|
|
|
case v.kind
|
|
|
|
of ValidatorKind.Local:
|
2021-11-30 01:20:21 +00:00
|
|
|
SignatureResult.ok(
|
|
|
|
get_block_signature(fork, genesis_validators_root, slot, blockRoot,
|
|
|
|
v.data.privateKey).toValidatorSig()
|
|
|
|
)
|
2021-10-04 19:08:31 +00:00
|
|
|
of ValidatorKind.Remote:
|
2022-05-10 00:32:12 +00:00
|
|
|
await signWithRemoteValidator(v, fork, genesis_validators_root,
|
2021-11-30 01:20:21 +00:00
|
|
|
blck)
|
2018-11-23 23:58:49 +00:00
|
|
|
|
|
|
|
proc signAttestation*(v: AttachedValidator,
|
2021-05-10 07:13:36 +00:00
|
|
|
data: AttestationData,
|
2022-05-10 00:32:12 +00:00
|
|
|
fork: Fork, genesis_validators_root: Eth2Digest
|
|
|
|
): Future[SignatureResult] {.async.} =
|
2021-07-13 11:15:07 +00:00
|
|
|
return
|
2021-10-04 19:08:31 +00:00
|
|
|
case v.kind
|
|
|
|
of ValidatorKind.Local:
|
2021-11-30 01:20:21 +00:00
|
|
|
SignatureResult.ok(
|
|
|
|
get_attestation_signature(fork, genesis_validators_root, data,
|
|
|
|
v.data.privateKey).toValidatorSig()
|
|
|
|
)
|
2021-10-04 19:08:31 +00:00
|
|
|
of ValidatorKind.Remote:
|
2022-05-10 00:32:12 +00:00
|
|
|
await signWithRemoteValidator(v, fork, genesis_validators_root, data)
|
2018-11-23 23:58:49 +00:00
|
|
|
|
2020-06-05 09:57:40 +00:00
|
|
|
proc produceAndSignAttestation*(validator: AttachedValidator,
|
|
|
|
attestationData: AttestationData,
|
2020-11-16 16:10:51 +00:00
|
|
|
committeeLen: int, indexInCommittee: Natural,
|
2021-07-13 11:15:07 +00:00
|
|
|
fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest):
|
2021-11-30 01:20:21 +00:00
|
|
|
Future[AttestationResult] {.async.} =
|
2021-07-13 11:15:07 +00:00
|
|
|
let validatorSignature =
|
2021-11-30 01:20:21 +00:00
|
|
|
block:
|
|
|
|
let res = await validator.signAttestation(attestationData, fork,
|
|
|
|
genesis_validators_root)
|
|
|
|
if res.isErr():
|
|
|
|
return AttestationResult.err(res.error())
|
|
|
|
res.get()
|
2020-06-05 09:57:40 +00:00
|
|
|
|
|
|
|
var aggregationBits = CommitteeValidatorsBits.init(committeeLen)
|
|
|
|
aggregationBits.setBit indexInCommittee
|
|
|
|
|
2021-11-30 01:20:21 +00:00
|
|
|
return AttestationResult.ok(
|
|
|
|
Attestation(data: attestationData, signature: validatorSignature,
|
|
|
|
aggregation_bits: aggregationBits)
|
|
|
|
)
|
2020-06-05 09:57:40 +00:00
|
|
|
|
2020-04-15 02:41:22 +00:00
|
|
|
proc signAggregateAndProof*(v: AttachedValidator,
|
|
|
|
aggregate_and_proof: AggregateAndProof,
|
2020-09-01 13:44:40 +00:00
|
|
|
fork: Fork, genesis_validators_root: Eth2Digest):
|
2021-11-30 01:20:21 +00:00
|
|
|
Future[SignatureResult] {.async.} =
|
2021-07-13 11:15:07 +00:00
|
|
|
return
|
2021-10-04 19:08:31 +00:00
|
|
|
case v.kind
|
|
|
|
of ValidatorKind.Local:
|
2021-11-30 01:20:21 +00:00
|
|
|
SignatureResult.ok(
|
|
|
|
get_aggregate_and_proof_signature(fork, genesis_validators_root,
|
|
|
|
aggregate_and_proof,
|
|
|
|
v.data.privateKey).toValidatorSig()
|
|
|
|
)
|
2021-10-04 19:08:31 +00:00
|
|
|
of ValidatorKind.Remote:
|
2022-05-10 00:32:12 +00:00
|
|
|
await signWithRemoteValidator(v, fork, genesis_validators_root,
|
2021-11-30 01:20:21 +00:00
|
|
|
aggregate_and_proof)
|
2020-04-15 02:41:22 +00:00
|
|
|
|
2022-03-02 10:00:21 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/validator.md#prepare-sync-committee-message
|
2021-08-17 08:07:17 +00:00
|
|
|
proc signSyncCommitteeMessage*(v: AttachedValidator,
|
2021-12-09 12:56:54 +00:00
|
|
|
fork: Fork,
|
2021-08-17 08:07:17 +00:00
|
|
|
genesis_validators_root: Eth2Digest,
|
2021-12-09 12:56:54 +00:00
|
|
|
slot: Slot,
|
|
|
|
beacon_block_root: Eth2Digest
|
2021-11-30 01:20:21 +00:00
|
|
|
): Future[SyncCommitteeMessageResult] {.async.} =
|
2021-10-04 19:08:31 +00:00
|
|
|
let signature =
|
|
|
|
case v.kind
|
|
|
|
of ValidatorKind.Local:
|
2022-05-10 00:32:12 +00:00
|
|
|
SignatureResult.ok(get_sync_committee_message_signature(
|
2021-12-09 12:56:54 +00:00
|
|
|
fork, genesis_validators_root, slot, beacon_block_root,
|
2022-05-10 00:32:12 +00:00
|
|
|
v.data.privateKey).toValidatorSig())
|
2021-10-04 19:08:31 +00:00
|
|
|
of ValidatorKind.Remote:
|
2022-05-10 00:32:12 +00:00
|
|
|
await signWithRemoteValidator(v, fork, genesis_validators_root,
|
2021-12-09 12:56:54 +00:00
|
|
|
slot, beacon_block_root)
|
2022-05-10 00:32:12 +00:00
|
|
|
|
|
|
|
if signature.isErr:
|
|
|
|
return SyncCommitteeMessageResult.err("Failed to obtain signature")
|
2021-08-17 08:07:17 +00:00
|
|
|
|
2021-11-30 01:20:21 +00:00
|
|
|
return
|
|
|
|
SyncCommitteeMessageResult.ok(
|
|
|
|
SyncCommitteeMessage(
|
|
|
|
slot: slot,
|
2021-12-09 12:56:54 +00:00
|
|
|
beacon_block_root: beacon_block_root,
|
2021-11-30 01:20:21 +00:00
|
|
|
validator_index: uint64(v.index.get()),
|
2022-05-10 00:32:12 +00:00
|
|
|
signature: signature.get()
|
2021-11-30 01:20:21 +00:00
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2022-03-02 10:00:21 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/validator.md#aggregation-selection
|
2021-11-30 01:20:21 +00:00
|
|
|
proc getSyncCommitteeSelectionProof*(v: AttachedValidator,
|
|
|
|
fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest,
|
|
|
|
slot: Slot,
|
2022-05-10 10:03:40 +00:00
|
|
|
subcommittee_index: SyncSubcommitteeIndex
|
2021-11-30 01:20:21 +00:00
|
|
|
): Future[SignatureResult] {.async.} =
|
2021-10-04 19:08:31 +00:00
|
|
|
return
|
|
|
|
case v.kind
|
|
|
|
of ValidatorKind.Local:
|
2021-12-09 12:56:54 +00:00
|
|
|
SignatureResult.ok(get_sync_committee_selection_proof(
|
|
|
|
fork, genesis_validators_root, slot, subcommittee_index,
|
|
|
|
v.data.privateKey).toValidatorSig())
|
2021-10-04 19:08:31 +00:00
|
|
|
of ValidatorKind.Remote:
|
2022-05-10 00:32:12 +00:00
|
|
|
await signWithRemoteValidator(v, fork, genesis_validators_root,
|
2021-11-30 01:20:21 +00:00
|
|
|
slot, subcommittee_index)
|
|
|
|
|
2022-03-02 10:00:21 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/validator.md#signature
|
2021-11-30 01:20:21 +00:00
|
|
|
proc sign*(v: AttachedValidator, msg: ref SignedContributionAndProof,
|
|
|
|
fork: Fork, genesis_validators_root: Eth2Digest
|
|
|
|
): Future[SignatureResult] {.async.} =
|
2022-05-10 00:32:12 +00:00
|
|
|
let signature =
|
2021-10-04 19:08:31 +00:00
|
|
|
case v.kind
|
|
|
|
of ValidatorKind.Local:
|
2022-05-10 00:32:12 +00:00
|
|
|
SignatureResult.ok(get_contribution_and_proof_signature(
|
|
|
|
fork, genesis_validators_root, msg.message, v.data.privateKey).toValidatorSig())
|
2021-10-04 19:08:31 +00:00
|
|
|
of ValidatorKind.Remote:
|
2022-05-10 00:32:12 +00:00
|
|
|
await signWithRemoteValidator(v, fork, genesis_validators_root,
|
2021-11-30 01:20:21 +00:00
|
|
|
msg.message)
|
2022-05-10 00:32:12 +00:00
|
|
|
|
|
|
|
if signature.isOk:
|
|
|
|
msg.signature = signature.get()
|
|
|
|
|
|
|
|
return signature
|
2021-08-17 08:07:17 +00:00
|
|
|
|
2022-03-02 10:00:21 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/validator.md#randao-reveal
|
2020-03-30 11:31:44 +00:00
|
|
|
func genRandaoReveal*(k: ValidatorPrivKey, fork: Fork,
|
2021-07-13 11:15:07 +00:00
|
|
|
genesis_validators_root: Eth2Digest,
|
|
|
|
slot: Slot): CookedSig =
|
2022-01-11 10:01:54 +00:00
|
|
|
get_epoch_signature(fork, genesis_validators_root, slot.epoch, k)
|
2019-02-07 20:13:10 +00:00
|
|
|
|
2020-09-01 13:44:40 +00:00
|
|
|
proc genRandaoReveal*(v: AttachedValidator, fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest, slot: Slot):
|
2021-11-30 01:20:21 +00:00
|
|
|
Future[SignatureResult] {.async.} =
|
2021-07-13 11:15:07 +00:00
|
|
|
return
|
2021-10-04 19:08:31 +00:00
|
|
|
case v.kind
|
|
|
|
of ValidatorKind.Local:
|
2021-11-30 01:20:21 +00:00
|
|
|
SignatureResult.ok(genRandaoReveal(v.data.privateKey, fork,
|
|
|
|
genesis_validators_root,
|
|
|
|
slot).toValidatorSig())
|
2021-10-04 19:08:31 +00:00
|
|
|
of ValidatorKind.Remote:
|
2022-05-10 00:32:12 +00:00
|
|
|
await signWithRemoteValidator(v, fork, genesis_validators_root,
|
2022-01-11 10:01:54 +00:00
|
|
|
slot.epoch())
|
2020-09-01 13:44:40 +00:00
|
|
|
|
|
|
|
proc getSlotSig*(v: AttachedValidator, fork: Fork,
|
|
|
|
genesis_validators_root: Eth2Digest, slot: Slot
|
2021-11-30 01:20:21 +00:00
|
|
|
): Future[SignatureResult] {.async.} =
|
2022-05-10 00:32:12 +00:00
|
|
|
if v.slotSignature.isSome and v.slotSignature.get.slot == slot:
|
|
|
|
return SignatureResult.ok(v.slotSignature.get.signature)
|
2021-10-18 09:11:44 +00:00
|
|
|
|
|
|
|
let signature =
|
2021-10-04 19:08:31 +00:00
|
|
|
case v.kind
|
|
|
|
of ValidatorKind.Local:
|
2022-05-10 00:32:12 +00:00
|
|
|
SignatureResult.ok(get_slot_signature(fork, genesis_validators_root, slot,
|
|
|
|
v.data.privateKey).toValidatorSig())
|
2021-10-04 19:08:31 +00:00
|
|
|
of ValidatorKind.Remote:
|
2022-05-10 00:32:12 +00:00
|
|
|
await signWithRemoteValidator(v, fork, genesis_validators_root, slot)
|
|
|
|
|
|
|
|
if signature.isErr:
|
|
|
|
return signature
|
2021-11-30 01:20:21 +00:00
|
|
|
|
2022-05-10 00:32:12 +00:00
|
|
|
v.slotSignature = some((slot, signature.get))
|
|
|
|
return signature
|