mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-01-11 06:46:10 +00:00
add hooks for observing LC progress (#4401)
For Fluffy injection, add observer callbacks that get called whenever new light client data is sucecssfully processed. ``` proc onLightClientObject( lightClient: LightClient, obj: SomeLightClientObject) = info "New LC object", obj lightClient.bootstrapObserver = proc(lightClient: LightClient, obj: altair.LightClientBootstrap) = lightClient.onLightClientObject(obj) lightClient.updateObserver = proc(lightClient: LightClient, obj: altair.LightClientUpdate) = lightClient.onLightClientObject(obj) lightClient.finalityUpdateObserver = proc(lightClient: LightClient, obj: altair.LightClientFinalityUpdate) = lightClient.onLightClientObject(obj) lightClient.optimisticUpdateObserver = proc(lightClient: LightClient, obj: altair.LightClientOptimisticUpdate) = lightClient.onLightClientObject(obj) ```
This commit is contained in:
parent
dee5af58d6
commit
bbf1d6030c
@ -31,11 +31,24 @@ declareHistogram light_client_store_object_duration_seconds,
|
|||||||
"storeObject() duration", buckets = [0.25, 0.5, 1, 2, 4, 8, Inf]
|
"storeObject() duration", buckets = [0.25, 0.5, 1, 2, 4, 8, Inf]
|
||||||
|
|
||||||
type
|
type
|
||||||
|
Nothing = object
|
||||||
|
|
||||||
GetTrustedBlockRootCallback* =
|
GetTrustedBlockRootCallback* =
|
||||||
proc(): Option[Eth2Digest] {.gcsafe, raises: [Defect].}
|
proc(): Option[Eth2Digest] {.gcsafe, raises: [Defect].}
|
||||||
VoidCallback* =
|
VoidCallback* =
|
||||||
proc() {.gcsafe, raises: [Defect].}
|
proc() {.gcsafe, raises: [Defect].}
|
||||||
|
|
||||||
|
ValueObserver[V] =
|
||||||
|
proc(v: V) {.gcsafe, raises: [Defect].}
|
||||||
|
BootstrapObserver* =
|
||||||
|
ValueObserver[altair.LightClientBootstrap]
|
||||||
|
UpdateObserver* =
|
||||||
|
ValueObserver[altair.LightClientUpdate]
|
||||||
|
FinalityUpdateObserver* =
|
||||||
|
ValueObserver[altair.LightClientFinalityUpdate]
|
||||||
|
OptimisticUpdateObserver* =
|
||||||
|
ValueObserver[altair.LightClientOptimisticUpdate]
|
||||||
|
|
||||||
LightClientFinalizationMode* {.pure.} = enum
|
LightClientFinalizationMode* {.pure.} = enum
|
||||||
Strict
|
Strict
|
||||||
## Only finalize light client data that:
|
## Only finalize light client data that:
|
||||||
@ -91,6 +104,10 @@ type
|
|||||||
getBeaconTime: GetBeaconTimeFn
|
getBeaconTime: GetBeaconTimeFn
|
||||||
getTrustedBlockRoot: GetTrustedBlockRootCallback
|
getTrustedBlockRoot: GetTrustedBlockRootCallback
|
||||||
onStoreInitialized, onFinalizedHeader, onOptimisticHeader: VoidCallback
|
onStoreInitialized, onFinalizedHeader, onOptimisticHeader: VoidCallback
|
||||||
|
bootstrapObserver: BootstrapObserver
|
||||||
|
updateObserver: UpdateObserver
|
||||||
|
finalityUpdateObserver: FinalityUpdateObserver
|
||||||
|
optimisticUpdateObserver: OptimisticUpdateObserver
|
||||||
|
|
||||||
cfg: RuntimeConfig
|
cfg: RuntimeConfig
|
||||||
genesis_validators_root: Eth2Digest
|
genesis_validators_root: Eth2Digest
|
||||||
@ -127,7 +144,11 @@ proc new*(
|
|||||||
getTrustedBlockRoot: GetTrustedBlockRootCallback,
|
getTrustedBlockRoot: GetTrustedBlockRootCallback,
|
||||||
onStoreInitialized: VoidCallback = nil,
|
onStoreInitialized: VoidCallback = nil,
|
||||||
onFinalizedHeader: VoidCallback = nil,
|
onFinalizedHeader: VoidCallback = nil,
|
||||||
onOptimisticHeader: VoidCallback = nil
|
onOptimisticHeader: VoidCallback = nil,
|
||||||
|
bootstrapObserver: BootstrapObserver = nil,
|
||||||
|
updateObserver: UpdateObserver = nil,
|
||||||
|
finalityUpdateObserver: FinalityUpdateObserver = nil,
|
||||||
|
optimisticUpdateObserver: OptimisticUpdateObserver = nil
|
||||||
): ref LightClientProcessor =
|
): ref LightClientProcessor =
|
||||||
(ref LightClientProcessor)(
|
(ref LightClientProcessor)(
|
||||||
dumpEnabled: dumpEnabled,
|
dumpEnabled: dumpEnabled,
|
||||||
@ -139,6 +160,10 @@ proc new*(
|
|||||||
onStoreInitialized: onStoreInitialized,
|
onStoreInitialized: onStoreInitialized,
|
||||||
onFinalizedHeader: onFinalizedHeader,
|
onFinalizedHeader: onFinalizedHeader,
|
||||||
onOptimisticHeader: onOptimisticHeader,
|
onOptimisticHeader: onOptimisticHeader,
|
||||||
|
bootstrapObserver: bootstrapObserver,
|
||||||
|
updateObserver: updateObserver,
|
||||||
|
finalityUpdateObserver: finalityUpdateObserver,
|
||||||
|
optimisticUpdateObserver: optimisticUpdateObserver,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
genesis_validators_root: genesis_validators_root,
|
genesis_validators_root: genesis_validators_root,
|
||||||
finalizationMode: finalizationMode)
|
finalizationMode: finalizationMode)
|
||||||
@ -252,10 +277,16 @@ proc processObject(
|
|||||||
|
|
||||||
res
|
res
|
||||||
|
|
||||||
template withReportedProgress(expectFinalityUpdate: bool, body: untyped): bool =
|
template withReportedProgress(
|
||||||
|
obj: SomeLightClientObject | Nothing, body: untyped): bool =
|
||||||
block:
|
block:
|
||||||
let
|
let
|
||||||
previousWasInitialized = store[].isSome
|
previousWasInitialized = store[].isSome
|
||||||
|
previousNextCommitteeKnown =
|
||||||
|
if store[].isSome:
|
||||||
|
store[].get.is_next_sync_committee_known
|
||||||
|
else:
|
||||||
|
false
|
||||||
previousFinalized =
|
previousFinalized =
|
||||||
if store[].isSome:
|
if store[].isSome:
|
||||||
store[].get.finalized_header
|
store[].get.finalized_header
|
||||||
@ -269,29 +300,55 @@ template withReportedProgress(expectFinalityUpdate: bool, body: untyped): bool =
|
|||||||
|
|
||||||
body
|
body
|
||||||
|
|
||||||
var didProgress = false
|
var
|
||||||
|
didProgress = false
|
||||||
|
didSignificantProgress = false
|
||||||
|
|
||||||
if store[].isSome != previousWasInitialized:
|
if store[].isSome != previousWasInitialized:
|
||||||
didProgress = true
|
didProgress = true
|
||||||
|
didSignificantProgress = true
|
||||||
if self.onStoreInitialized != nil:
|
if self.onStoreInitialized != nil:
|
||||||
self.onStoreInitialized()
|
self.onStoreInitialized()
|
||||||
self.onStoreInitialized = nil
|
self.onStoreInitialized = nil
|
||||||
|
|
||||||
|
if store[].isSome:
|
||||||
if store[].get.optimistic_header != previousOptimistic:
|
if store[].get.optimistic_header != previousOptimistic:
|
||||||
when not expectFinalityUpdate:
|
|
||||||
didProgress = true
|
didProgress = true
|
||||||
|
when obj isnot SomeLightClientUpdateWithFinality:
|
||||||
|
didSignificantProgress = true
|
||||||
if self.onOptimisticHeader != nil:
|
if self.onOptimisticHeader != nil:
|
||||||
self.onOptimisticHeader()
|
self.onOptimisticHeader()
|
||||||
|
|
||||||
if store[].get.finalized_header != previousFinalized:
|
if store[].get.finalized_header != previousFinalized:
|
||||||
didProgress = true
|
didProgress = true
|
||||||
|
didSignificantProgress = true
|
||||||
if self.onFinalizedHeader != nil:
|
if self.onFinalizedHeader != nil:
|
||||||
self.onFinalizedHeader()
|
self.onFinalizedHeader()
|
||||||
|
|
||||||
didProgress
|
if store[].get.is_next_sync_committee_known != previousNextCommitteeKnown:
|
||||||
|
didProgress = true
|
||||||
|
|
||||||
|
if didProgress:
|
||||||
|
when obj is Nothing:
|
||||||
|
discard
|
||||||
|
elif obj is altair.LightClientBootstrap:
|
||||||
|
if self.bootstrapObserver != nil:
|
||||||
|
self.bootstrapObserver(obj)
|
||||||
|
elif obj is altair.LightClientUpdate:
|
||||||
|
if self.updateObserver != nil:
|
||||||
|
self.updateObserver(obj)
|
||||||
|
elif obj is altair.LightClientFinalityUpdate:
|
||||||
|
if self.finalityUpdateObserver != nil:
|
||||||
|
self.finalityUpdateObserver(obj)
|
||||||
|
elif obj is altair.LightClientOptimisticUpdate:
|
||||||
|
if self.optimisticUpdateObserver != nil:
|
||||||
|
self.optimisticUpdateObserver(obj)
|
||||||
|
else: raiseAssert "Unreachable"
|
||||||
|
|
||||||
|
didSignificantProgress
|
||||||
|
|
||||||
template withReportedProgress(body: untyped): bool =
|
template withReportedProgress(body: untyped): bool =
|
||||||
withReportedProgress(false, body)
|
withReportedProgress(Nothing(), body)
|
||||||
|
|
||||||
proc storeObject*(
|
proc storeObject*(
|
||||||
self: var LightClientProcessor,
|
self: var LightClientProcessor,
|
||||||
@ -304,8 +361,8 @@ proc storeObject*(
|
|||||||
startTick = Moment.now()
|
startTick = Moment.now()
|
||||||
store = self.store
|
store = self.store
|
||||||
|
|
||||||
didProgress =
|
didSignificantProgress =
|
||||||
withReportedProgress(obj is SomeLightClientUpdateWithFinality):
|
withReportedProgress(obj):
|
||||||
? self.processObject(obj, wallTime)
|
? self.processObject(obj, wallTime)
|
||||||
|
|
||||||
let
|
let
|
||||||
@ -328,7 +385,7 @@ proc storeObject*(
|
|||||||
kind = typeof(obj).name,
|
kind = typeof(obj).name,
|
||||||
objectSlot = objSlot,
|
objectSlot = objSlot,
|
||||||
storeObjectDur
|
storeObjectDur
|
||||||
ok didProgress
|
ok didSignificantProgress
|
||||||
|
|
||||||
proc resetToFinalizedHeader*(
|
proc resetToFinalizedHeader*(
|
||||||
self: var LightClientProcessor,
|
self: var LightClientProcessor,
|
||||||
@ -393,8 +450,8 @@ func toValidationError(
|
|||||||
wallTime: BeaconTime,
|
wallTime: BeaconTime,
|
||||||
obj: SomeLightClientObject): Result[void, ValidationError] =
|
obj: SomeLightClientObject): Result[void, ValidationError] =
|
||||||
if r.isOk:
|
if r.isOk:
|
||||||
let didProgress = r.get
|
let didSignificantProgress = r.get
|
||||||
if didProgress:
|
if didSignificantProgress:
|
||||||
let
|
let
|
||||||
signature_slot = obj.signature_slot
|
signature_slot = obj.signature_slot
|
||||||
currentTime = wallTime + MAXIMUM_GOSSIP_CLOCK_DISPARITY
|
currentTime = wallTime + MAXIMUM_GOSSIP_CLOCK_DISPARITY
|
||||||
|
@ -29,6 +29,17 @@ type
|
|||||||
proc(lightClient: LightClient, header: BeaconBlockHeader) {.
|
proc(lightClient: LightClient, header: BeaconBlockHeader) {.
|
||||||
gcsafe, raises: [Defect].}
|
gcsafe, raises: [Defect].}
|
||||||
|
|
||||||
|
LightClientValueObserver[V] =
|
||||||
|
proc(lightClient: LightClient, v: V) {.gcsafe, raises: [Defect].}
|
||||||
|
LightClientBootstrapObserver* =
|
||||||
|
LightClientValueObserver[altair.LightClientBootstrap]
|
||||||
|
LightClientUpdateObserver* =
|
||||||
|
LightClientValueObserver[altair.LightClientUpdate]
|
||||||
|
LightClientFinalityUpdateObserver* =
|
||||||
|
LightClientValueObserver[altair.LightClientFinalityUpdate]
|
||||||
|
LightClientOptimisticUpdateObserver* =
|
||||||
|
LightClientValueObserver[altair.LightClientOptimisticUpdate]
|
||||||
|
|
||||||
LightClient* = ref object
|
LightClient* = ref object
|
||||||
network: Eth2Node
|
network: Eth2Node
|
||||||
cfg: RuntimeConfig
|
cfg: RuntimeConfig
|
||||||
@ -39,6 +50,10 @@ type
|
|||||||
manager: LightClientManager
|
manager: LightClientManager
|
||||||
gossipState: GossipState
|
gossipState: GossipState
|
||||||
onFinalizedHeader*, onOptimisticHeader*: LightClientHeaderCallback
|
onFinalizedHeader*, onOptimisticHeader*: LightClientHeaderCallback
|
||||||
|
bootstrapObserver*: LightClientBootstrapObserver
|
||||||
|
updateObserver*: LightClientUpdateObserver
|
||||||
|
finalityUpdateObserver*: LightClientFinalityUpdateObserver
|
||||||
|
optimisticUpdateObserver*: LightClientOptimisticUpdateObserver
|
||||||
trustedBlockRoot*: Option[Eth2Digest]
|
trustedBlockRoot*: Option[Eth2Digest]
|
||||||
|
|
||||||
func finalizedHeader*(lightClient: LightClient): Opt[BeaconBlockHeader] =
|
func finalizedHeader*(lightClient: LightClient): Opt[BeaconBlockHeader] =
|
||||||
@ -94,11 +109,28 @@ proc createLightClient(
|
|||||||
lightClient.onOptimisticHeader(
|
lightClient.onOptimisticHeader(
|
||||||
lightClient, lightClient.optimisticHeader.get)
|
lightClient, lightClient.optimisticHeader.get)
|
||||||
|
|
||||||
|
proc bootstrapObserver(obj: altair.LightClientBootstrap) =
|
||||||
|
if lightClient.bootstrapObserver != nil:
|
||||||
|
lightClient.bootstrapObserver(lightClient, obj)
|
||||||
|
|
||||||
|
proc updateObserver(obj: altair.LightClientUpdate) =
|
||||||
|
if lightClient.updateObserver != nil:
|
||||||
|
lightClient.updateObserver(lightClient, obj)
|
||||||
|
|
||||||
|
proc finalityObserver(obj: altair.LightClientFinalityUpdate) =
|
||||||
|
if lightClient.finalityUpdateObserver != nil:
|
||||||
|
lightClient.finalityUpdateObserver(lightClient, obj)
|
||||||
|
|
||||||
|
proc optimisticObserver(obj: altair.LightClientOptimisticUpdate) =
|
||||||
|
if lightClient.optimisticUpdateObserver != nil:
|
||||||
|
lightClient.optimisticUpdateObserver(lightClient, obj)
|
||||||
|
|
||||||
lightClient.processor = LightClientProcessor.new(
|
lightClient.processor = LightClientProcessor.new(
|
||||||
dumpEnabled, dumpDirInvalid, dumpDirIncoming,
|
dumpEnabled, dumpDirInvalid, dumpDirIncoming,
|
||||||
cfg, genesis_validators_root, finalizationMode,
|
cfg, genesis_validators_root, finalizationMode,
|
||||||
lightClient.store, getBeaconTime, getTrustedBlockRoot,
|
lightClient.store, getBeaconTime, getTrustedBlockRoot,
|
||||||
onStoreInitialized, onFinalizedHeader, onOptimisticHeader)
|
onStoreInitialized, onFinalizedHeader, onOptimisticHeader,
|
||||||
|
bootstrapObserver, updateObserver, finalityObserver, optimisticObserver)
|
||||||
|
|
||||||
proc lightClientVerifier(obj: SomeLightClientObject):
|
proc lightClientVerifier(obj: SomeLightClientObject):
|
||||||
Future[Result[void, VerifierError]] =
|
Future[Result[void, VerifierError]] =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user