From f69b272850747ef5e31ce76caee192caa21eff9a Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Thu, 25 Nov 2021 19:41:54 +0100 Subject: [PATCH] Keep cooked pubkeys in cache (#3122) Turning uncompressed pubkeys into cooked ones is fast, but unnecessary - this should avoid a little work for every signature validation we do by pre-loading them at startup. --- beacon_chain/beacon_chain_db.nim | 24 +++++++++++++----------- beacon_chain/spec/datatypes/base.nim | 10 +++++++--- beacon_chain/statediff.nim | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/beacon_chain/beacon_chain_db.nim b/beacon_chain/beacon_chain_db.nim index 853d967597..bf33b6a568 100644 --- a/beacon_chain/beacon_chain_db.nim +++ b/beacon_chain/beacon_chain_db.nim @@ -83,7 +83,7 @@ type # immutableValidatorsDb only stores the total count; it's a proxy for SQL # queries. - immutableValidatorsDb*: DbSeq[ImmutableValidatorData2] + immutableValidatorsDb*: DbSeq[ImmutableValidatorDataDb2] immutableValidators*: seq[ImmutableValidatorData2] checkpoint*: proc() {.gcsafe, raises: [Defect].} @@ -257,13 +257,13 @@ proc get*[T](s: DbSeq[T], idx: int64): T = let found = queryRes.expectDb() if not found: panic() -proc loadImmutableValidators(vals: DbSeq[ImmutableValidatorData]): seq[ImmutableValidatorData] = +proc loadImmutableValidators(vals: DbSeq[ImmutableValidatorDataDb2]): seq[ImmutableValidatorData2] = + result = newSeqOfCap[ImmutableValidatorData2](vals.len()) for i in 0 ..< vals.len: - result.add vals.get(i) - -proc loadImmutableValidators(vals: DbSeq[ImmutableValidatorData2]): seq[ImmutableValidatorData2] = - for i in 0 ..< vals.len: - result.add vals.get(i) + let tmp = vals.get(i) + result.add ImmutableValidatorData2( + pubkey: tmp.pubkey.loadValid(), + withdrawal_credentials: tmp.withdrawal_credentials) proc new*(T: type BeaconChainDB, dir: string, @@ -299,7 +299,7 @@ proc new*(T: type BeaconChainDB, genesisDepositsSeq = DbSeq[DepositData].init(db, "genesis_deposits").expectDb() immutableValidatorsDb = - DbSeq[ImmutableValidatorData2].init(db, "immutable_validators2").expectDb() + DbSeq[ImmutableValidatorDataDb2].init(db, "immutable_validators2").expectDb() # V1 - expected-to-be small rows get without rowid optimizations keyValues = kvStore db.openKvStore("key_values", true).expectDb() @@ -325,7 +325,7 @@ proc new*(T: type BeaconChainDB, len = immutableValidatorsDb1.len() while immutableValidatorsDb.len() < immutableValidatorsDb1.len(): let val = immutableValidatorsDb1.get(immutableValidatorsDb.len()) - immutableValidatorsDb.add(ImmutableValidatorData2( + immutableValidatorsDb.add(ImmutableValidatorDataDb2( pubkey: val.pubkey.loadValid().toUncompressed(), withdrawal_credentials: val.withdrawal_credentials )) @@ -505,7 +505,9 @@ proc updateImmutableValidators*( while db.immutableValidators.len() < numValidators: let immutableValidator = getImmutableValidatorData(validators[db.immutableValidators.len()]) - db.immutableValidatorsDb.add immutableValidator + db.immutableValidatorsDb.add ImmutableValidatorDataDb2( + pubkey: immutableValidator.pubkey.toUncompressed(), + withdrawal_credentials: immutableValidator.withdrawal_credentials) db.immutableValidators.add immutableValidator template toBeaconStateNoImmutableValidators(state: phase0.BeaconState): @@ -657,7 +659,7 @@ proc getStateOnlyMutableValidators( assign( dstValidator.pubkey, - immutableValidators[i].pubkey.loadValid().toPubKey()) + immutableValidators[i].pubkey.toPubKey()) assign( dstValidator.withdrawal_credentials, immutableValidators[i].withdrawal_credentials) diff --git a/beacon_chain/spec/datatypes/base.nim b/beacon_chain/spec/datatypes/base.nim index 56840c0e21..47f1082980 100644 --- a/beacon_chain/spec/datatypes/base.nim +++ b/beacon_chain/spec/datatypes/base.nim @@ -282,10 +282,14 @@ type # Non-spec type that represents the immutable part of a validator - an # uncompressed key serialization is used to speed up loading from database - ImmutableValidatorData2* = object + ImmutableValidatorDataDb2* = object pubkey*: UncompressedPubKey withdrawal_credentials*: Eth2Digest + ImmutableValidatorData2* = object + pubkey*: CookedPubKey + withdrawal_credentials*: Eth2Digest + # https://github.com/ethereum/consensus-specs/blob/v1.1.5/specs/phase0/beacon-chain.md#validator Validator* = object pubkey*: ValidatorPubKey @@ -520,7 +524,7 @@ func getImmutableValidatorData*(validator: Validator): ImmutableValidatorData2 = doAssert cookedKey.isSome, "Cannot parse validator key: " & toHex(validator.pubkey) ImmutableValidatorData2( - pubkey: cookedKey.get().toUncompressed(), + pubkey: cookedKey.get(), withdrawal_credentials: validator.withdrawal_credentials) # TODO when https://github.com/nim-lang/Nim/issues/14440 lands in Status's Nim, @@ -875,7 +879,7 @@ proc load*( if validators.lenu64() <= index.uint64: none(CookedPubKey) else: - some(validators[index.int].pubkey.loadValid()) + some(validators[index.int].pubkey) template hash*(header: BeaconBlockHeader): Hash = hash(header.state_root) diff --git a/beacon_chain/statediff.nim b/beacon_chain/statediff.nim index 8852c67563..dc952a89ba 100644 --- a/beacon_chain/statediff.nim +++ b/beacon_chain/statediff.nim @@ -32,7 +32,7 @@ func applyValidatorIdentities( hl: auto) = for item in hl: if not validators.add Validator( - pubkey: item.pubkey.loadValid().toPubKey(), + pubkey: item.pubkey.toPubKey(), withdrawal_credentials: item.withdrawal_credentials): raiseAssert "cannot readd"