reduce redundant zero initialization for LC data objects (#5479)

Directly initialize `ForkedLightClientObj` instead of separately first
 setting the `kind` (initializing everything to zero) and then assigning
the forky data after that.
This commit is contained in:
Etan Kissling 2023-10-04 18:11:45 +02:00 committed by GitHub
parent 37967ba03b
commit 297c768816
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 91 additions and 106 deletions

View File

@ -504,10 +504,8 @@ proc getBestUpdate*(
withAll(LightClientDataFork):
when lcDataFork > LightClientDataFork.None:
if update[0] == ord(lcDataFork).int64:
var obj = ForkedLightClientUpdate(kind: lcDataFork)
obj.forky(lcDataFork) = SSZ.decode(
update[1], lcDataFork.LightClientUpdate)
return obj
return ForkedLightClientUpdate.init(SSZ.decode(
update[1], lcDataFork.LightClientUpdate))
warn "Unsupported LC data store kind", store = "bestUpdates",
period, kind = update[0]
return default(ForkedLightClientUpdate)

View File

@ -175,8 +175,8 @@ proc updateLightClientFromDag*(node: BeaconNode) =
withBlck(bdata):
const lcDataFork = lcDataForkAtConsensusFork(consensusFork)
when lcDataFork > LightClientDataFork.None:
header = ForkedLightClientHeader(kind: lcDataFork)
header.forky(lcDataFork) = forkyBlck.toLightClientHeader(lcDataFork)
header = ForkedLightClientHeader.init(
forkyBlck.toLightClientHeader(lcDataFork))
else: raiseAssert "Unreachable"
let current_sync_committee = block:
let tmpState = assignClone(node.dag.headState)

View File

@ -367,15 +367,16 @@ proc initLightClientUpdateForPeriod(
withStateAndBlck(updatedState, bdata):
when consensusFork >= ConsensusFork.Altair:
const lcDataFork = lcDataForkAtConsensusFork(consensusFork)
update = ForkedLightClientUpdate(kind: lcDataFork)
template forkyUpdate: untyped = update.forky(lcDataFork)
forkyUpdate.attested_header = forkyBlck.toLightClientHeader(lcDataFork)
forkyUpdate.next_sync_committee = forkyState.data.next_sync_committee
forkyUpdate.next_sync_committee_branch =
forkyState.data.build_proof(altair.NEXT_SYNC_COMMITTEE_INDEX).get
if finalizedBid.slot != FAR_FUTURE_SLOT:
forkyUpdate.finality_branch =
forkyState.data.build_proof(altair.FINALIZED_ROOT_INDEX).get
update = ForkedLightClientUpdate.init(lcDataFork.LightClientUpdate(
attested_header: forkyBlck.toLightClientHeader(lcDataFork),
next_sync_committee: forkyState.data.next_sync_committee,
next_sync_committee_branch:
forkyState.data.build_proof(altair.NEXT_SYNC_COMMITTEE_INDEX).get,
finality_branch:
if finalizedBid.slot != FAR_FUTURE_SLOT:
forkyState.data.build_proof(altair.FINALIZED_ROOT_INDEX).get
else:
default(FinalityBranch)))
else: raiseAssert "Unreachable"
do:
dag.handleUnexpectedLightClientError(attestedBid.slot)
@ -974,18 +975,16 @@ proc getLightClientBootstrap(
# Construct `LightClientBootstrap` from cached data
const lcDataFork = typeof(header).kind
var bootstrap = ForkedLightClientBootstrap(kind: lcDataFork)
template forkyBootstrap: untyped = bootstrap.forky(lcDataFork)
forkyBootstrap.header = header
forkyBootstrap.current_sync_committee =
dag.lcDataStore.db.getSyncCommittee(period).valueOr:
debug "LC bootstrap unavailable: Sync committee not cached", period
return default(ForkedLightClientBootstrap)
forkyBootstrap.current_sync_committee_branch =
dag.lcDataStore.db.getCurrentSyncCommitteeBranch(slot).valueOr:
debug "LC bootstrap unavailable: Sync committee branch not cached", slot
return default(ForkedLightClientBootstrap)
bootstrap
ForkedLightClientBootstrap.init(lcDataFork.LightClientBootstrap(
header: header,
current_sync_committee: (block:
dag.lcDataStore.db.getSyncCommittee(period).valueOr:
debug "LC bootstrap unavailable: Sync committee not cached", period
return default(ForkedLightClientBootstrap)),
current_sync_committee_branch: (block:
dag.lcDataStore.db.getCurrentSyncCommitteeBranch(slot).valueOr:
debug "LC bootstrap unavailable: Committee branch not cached", slot
return default(ForkedLightClientBootstrap))))
proc getLightClientBootstrap*(
dag: ChainDAGRef,

View File

@ -230,8 +230,7 @@ proc processObject(
if initRes.isErr:
err(initRes.error)
else:
self.store[] = ForkedLightClientStore(kind: lcDataFork)
self.store[].forky(lcDataFork) = initRes.get
self.store[] = ForkedLightClientStore.init(initRes.get)
ok()
elif forkyObject is SomeForkyLightClientUpdate:
if self.store[].kind == LightClientDataFork.None:
@ -306,16 +305,12 @@ template withReportedProgress(
var
oldFinalized = withForkyStore(self.store[]):
when lcDataFork > LightClientDataFork.None:
var header = ForkedLightClientHeader(kind: lcDataFork)
header.forky(lcDataFork) = forkyStore.finalized_header
header
ForkedLightClientHeader.init(forkyStore.finalized_header)
else:
default(ForkedLightClientHeader)
oldOptimistic = withForkyStore(self.store[]):
when lcDataFork > LightClientDataFork.None:
var header = ForkedLightClientHeader(kind: lcDataFork)
header.forky(lcDataFork) = forkyStore.optimistic_header
header
ForkedLightClientHeader.init(forkyStore.optimistic_header)
else:
default(ForkedLightClientHeader)
@ -424,12 +419,11 @@ proc resetToFinalizedHeader*(
discard withReportedProgress:
withForkyHeader(header):
when lcDataFork > LightClientDataFork.None:
self.store[] = ForkedLightClientStore(kind: lcDataFork)
template forkyStore: untyped = self.store[].forky(lcDataFork)
forkyStore = lcDataFork.LightClientStore(
self.store[] = ForkedLightClientStore.init(lcDataFork.LightClientStore(
finalized_header: forkyHeader,
current_sync_committee: current_sync_committee,
optimistic_header: forkyHeader)
optimistic_header: forkyHeader))
template forkyStore: untyped = self.store[].forky(lcDataFork)
debug "LC reset to finalized header",
finalizedSlot = forkyStore.finalized_header.beacon.slot,
optimisticSlot = forkyStore.optimistic_header.beacon.slot

View File

@ -56,9 +56,7 @@ func finalizedHeader*(
lightClient: LightClient): ForkedLightClientHeader =
withForkyStore(lightClient.store[]):
when lcDataFork > LightClientDataFork.None:
var header = ForkedLightClientHeader(kind: lcDataFork)
header.forky(lcDataFork) = forkyStore.finalized_header
header
ForkedLightClientHeader.init(forkyStore.finalized_header)
else:
default(ForkedLightClientHeader)
@ -66,9 +64,7 @@ func optimisticHeader*(
lightClient: LightClient): ForkedLightClientHeader =
withForkyStore(lightClient.store[]):
when lcDataFork > LightClientDataFork.None:
var header = ForkedLightClientHeader(kind: lcDataFork)
header.forky(lcDataFork) = forkyStore.optimistic_header
header
ForkedLightClientHeader.init(forkyStore.optimistic_header)
else:
default(ForkedLightClientHeader)
@ -294,9 +290,7 @@ proc installMessageValidators*(
(ValidationResult.Reject, cstring "Invalid context fork"))
return ValidationResult.Reject
const lcDataFork = T.kind
var obj = T.Forked(kind: lcDataFork)
obj.forky(lcDataFork) = msg
let obj = T.Forked.init(msg)
var
ignoreErrors {.noinit.}: array[2, ValidationError]

View File

@ -152,10 +152,8 @@ proc getLatestFinalizedHeader*(
withAll(LightClientDataFork):
when lcDataFork > LightClientDataFork.None:
if header[0] == ord(lcDataFork).int64:
var obj = ForkedLightClientHeader(kind: lcDataFork)
obj.forky(lcDataFork) = SSZ.decode(
header[1], lcDataFork.LightClientHeader)
return obj
return ForkedLightClientHeader.init(SSZ.decode(
header[1], lcDataFork.LightClientHeader))
warn "Unsupported LC store kind", store = "headers",
key, kind = header[0]
return default(ForkedLightClientHeader)

View File

@ -2108,13 +2108,12 @@ proc readValue*[T: SomeForkedLightClientObject](
withLcDataFork(lcDataForkAtConsensusFork(version.get)):
when lcDataFork > LightClientDataFork.None:
value = T(kind: lcDataFork)
try:
value.forky(lcDataFork) = RestJson.decode(
value = T.init(RestJson.decode(
string(data.get()),
T.Forky(lcDataFork),
requireAllFields = true,
allowUnknownFields = true)
allowUnknownFields = true))
except SerializationError:
reader.raiseUnexpectedValue("Incorrect format (" & $lcDataFork & ")")
else:

View File

@ -46,8 +46,7 @@ func decodeSszLightClientObject[T: SomeForkedLightClientObject](
try:
withLcDataFork(lcDataForkAtConsensusFork(consensusFork)):
when lcDataFork > LightClientDataFork.None:
var obj = T(kind: lcDataFork)
obj.forky(lcDataFork) = SSZ.decode(data, T.Forky(lcDataFork))
var obj = T.init(SSZ.decode(data, T.Forky(lcDataFork)))
obj.checkForkConsistency(cfg, consensusFork)
obj
else:
@ -136,10 +135,9 @@ proc decodeSszLightClientObjects[S: seq[SomeForkedLightClientObject]](
withLcDataFork(lcDataForkAtConsensusFork(consensusFork)):
when lcDataFork > LightClientDataFork.None:
type T = typeof(res[0])
var obj = T(kind: lcDataFork)
obj.forky(lcDataFork) = SSZ.decode(
var obj = T.init(SSZ.decode(
data.toOpenArray(begin + contextLen, after - 1),
T.Forky(lcDataFork))
T.Forky(lcDataFork)))
obj.checkForkConsistency(cfg, consensusFork)
res.add obj
else:

View File

@ -461,6 +461,42 @@ template withForkyStore*(
const lcDataFork {.inject, used.} = LightClientDataFork.None
body
func init*(
x: typedesc[
ForkedLightClientHeader |
SomeForkedLightClientObject |
ForkedLightClientStore],
forkyData:
ForkyLightClientHeader |
SomeForkyLightClientObject |
ForkyLightClientStore): auto =
type ResultType = typeof(forkyData).Forked
static: doAssert ResultType is x
const kind = typeof(forkyData).kind
when kind == LightClientDataFork.Deneb:
ResultType(kind: kind, denebData: forkyData)
elif kind == LightClientDataFork.Capella:
ResultType(kind: kind, capellaData: forkyData)
elif kind == LightClientDataFork.Altair:
ResultType(kind: kind, altairData: forkyData)
else:
static: raiseAssert "Unreachable"
template forky*(
x:
ForkedLightClientHeader |
SomeForkedLightClientObject |
ForkedLightClientStore,
kind: static LightClientDataFork): untyped =
when kind == LightClientDataFork.Deneb:
x.denebData
elif kind == LightClientDataFork.Capella:
x.capellaData
elif kind == LightClientDataFork.Altair:
x.altairData
else:
static: raiseAssert "Unreachable"
func toFull*(
update: SomeForkyLightClientUpdate): auto =
type ResultType = typeof(update).kind.LightClientUpdate
@ -486,10 +522,7 @@ func toFull*(
else:
withForkyObject(update):
when lcDataFork > LightClientDataFork.None:
var res = ForkedLightClientUpdate(kind: lcDataFork)
template forkyRes: untyped = res.forky(lcDataFork)
forkyRes = forkyObject.toFull()
res
ForkedLightClientUpdate.init(forkyObject.toFull())
else:
default(ForkedLightClientUpdate)
@ -518,10 +551,7 @@ func toFinality*(
else:
withForkyObject(update):
when lcDataFork > LightClientDataFork.None:
var res = ForkedLightClientFinalityUpdate(kind: lcDataFork)
template forkyRes: untyped = res.forky(lcDataFork)
forkyRes = forkyObject.toFinality()
res
ForkedLightClientFinalityUpdate.init(forkyObject.toFinality())
else:
default(ForkedLightClientFinalityUpdate)
@ -543,10 +573,7 @@ func toOptimistic*(
else:
withForkyObject(update):
when lcDataFork > LightClientDataFork.None:
var res = ForkedLightClientOptimisticUpdate(kind: lcDataFork)
template forkyRes: untyped = res.forky(lcDataFork)
forkyRes = forkyObject.toOptimistic()
res
ForkedLightClientOptimisticUpdate.init(forkyObject.toOptimistic())
else:
default(ForkedLightClientOptimisticUpdate)
@ -581,21 +608,6 @@ func matches*[A, B: SomeForkedLightClientUpdate](a: A, b: B): bool =
else:
true
template forky*(
x:
ForkedLightClientHeader |
SomeForkedLightClientObject |
ForkedLightClientStore,
kind: static LightClientDataFork): untyped =
when kind == LightClientDataFork.Deneb:
x.denebData
elif kind == LightClientDataFork.Capella:
x.capellaData
elif kind == LightClientDataFork.Altair:
x.altairData
else:
static: raiseAssert "Unreachable"
func migrateToDataFork*(
x: var ForkedLightClientHeader,
newKind: static LightClientDataFork) =

View File

@ -153,9 +153,7 @@ proc readChunkPayload*(
if contextFork !=
peer.network.cfg.consensusForkAtEpoch(res.get.contextEpoch):
return neterr InvalidContextBytes
var obj = ok MsgType(kind: lcDataFork)
obj.get.forky(lcDataFork) = res.get
return obj
return ok MsgType.init(res.get)
else:
return err(res.error)
else:

View File

@ -220,9 +220,8 @@ proc doTrustedNodeSync*(
quit 1
bootstrap.migrateToDataFork(lcDataFork)
var storeRes =
initialize_light_client_store(
trustedBlockRoot, bootstrap.forky(lcDataFork), cfg)
var storeRes = initialize_light_client_store(
trustedBlockRoot, bootstrap.forky(lcDataFork), cfg)
if storeRes.isErr:
error "`initialize_light_client_store` failed", err = storeRes.error
quit 1

View File

@ -94,10 +94,9 @@ proc loadSteps(path: string, fork_digests: ForkDigests): seq[TestStep] =
var update {.noinit.}: ForkedLightClientUpdate
withLcDataFork(lcDataForkAtConsensusFork(update_consensus_fork)):
when lcDataFork > LightClientDataFork.None:
update = ForkedLightClientUpdate(kind: lcDataFork)
update.forky(lcDataFork) = parseTest(
update = ForkedLightClientUpdate.init(parseTest(
path/update_filename & ".ssz_snappy", SSZ,
lcDataFork.LightClientUpdate)
lcDataFork.LightClientUpdate))
else: raiseAssert "Unreachable update fork " & $update_fork_digest
result.add TestStep(
@ -177,10 +176,9 @@ proc runTest(suiteName, path: string) =
var bootstrap {.noinit.}: ForkedLightClientBootstrap
withLcDataFork(lcDataForkAtConsensusFork(bootstrap_consensus_fork)):
when lcDataFork > LightClientDataFork.None:
bootstrap = ForkedLightClientBootstrap(kind: lcDataFork)
bootstrap.forky(lcDataFork) = parseTest(
bootstrap = ForkedLightClientBootstrap.init(parseTest(
path/"bootstrap.ssz_snappy", SSZ,
lcDataFork.LightClientBootstrap)
lcDataFork.LightClientBootstrap))
else:
raiseAssert "Unknown bootstrap fork " & $meta.bootstrap_fork_digest
bootstrap
@ -194,10 +192,9 @@ proc runTest(suiteName, path: string) =
var store {.noinit.}: ForkedLightClientStore
withLcDataFork(lcDataForkAtConsensusFork(store_consensus_fork)):
when lcDataFork > LightClientDataFork.None:
store = ForkedLightClientStore(kind: lcDataFork)
bootstrap[].migrateToDataFork(lcDataFork)
store.forky(lcDataFork) = initialize_light_client_store(
meta.trusted_block_root, bootstrap[].forky(lcDataFork), cfg).get
store = ForkedLightClientStore.init(initialize_light_client_store(
meta.trusted_block_root, bootstrap[].forky(lcDataFork), cfg).get)
else: raiseAssert "Unreachable store fork " & $meta.store_fork_digest
store

View File

@ -148,8 +148,7 @@ suite "Light client" & preset():
var storeRes = newClone(initialize_light_client_store(
trusted_block_root, forkyBootstrap, cfg))
check storeRes[].isOk
store = (ref ForkedLightClientStore)(kind: lcDataFork)[]
store.forky(lcDataFork) = storeRes[].get
store = newClone(ForkedLightClientStore.init(storeRes[].get))[]
# Sync to latest sync committee period
var numIterations = 0

View File

@ -284,8 +284,8 @@ suite "Light client processor" & preset():
var oldFinalized {.noinit.}: ForkedLightClientHeader
withForkyStore(store[]):
when lcDataFork > LightClientDataFork.None:
oldFinalized = ForkedLightClientHeader(kind: lcDataFork)
oldFinalized.forky(lcDataFork) = forkyStore.finalized_header
oldFinalized = ForkedLightClientHeader.init(
forkyStore.finalized_header)
else: raiseAssert "Unreachable"
let finalityUpdate = dag.getLightClientFinalityUpdate()
check finalityUpdate.kind > LightClientDataFork.None