@@ -103,17 +103,14 @@ type
103103 # # +-------+
104104 # #
105105 closed = 0 # no session
106- notified # client app was offered a new session
107106 collecting # may append session headers
108107 ready # `ante` has a parent on the `FC` module
109108 orphan # no way to link into `FC` module
110109 locked # done with session headers, read-only state
111110
112- HeaderChainNotifyCB * =
113- proc (hdrNum: BlockNumber , finHash: Hash32 ) {.gcsafe , raises : [].}
114- # # Call back function telling a client app that a new chain was initialised.
115- # # The hash passed as argument is from the finaliser and must be resolved
116- # # as header argument in `startSession()`.
111+ HeaderChainNotifyCB * = proc () {.gcsafe , raises : [].}
112+ # # Call back function telling a client app that a new session was
113+ # # initialised and has started.
117114
118115 HeaderChainRef * = ref object
119116 # # Module descriptor
@@ -269,6 +266,18 @@ proc tryFcParent(hc: HeaderChainRef; hdr: Header): HeaderChainMode =
269266 # The block number of `hdr` must not go below the `base`. It cannot be
270267 # handled even if it has a parent on the block chain (but not on the
271268 # `FC` module.)
269+ #
270+ # Rationale:
271+ # This situataion might arise by means of `CL` requests via RPC updating
272+ # the `base` concurrently to a syncer client. This can only happen if the
273+ # base is near the canonical head. Which in turn means that the header
274+ # chain is short.
275+ #
276+ # Reversing the antecedent (above `base`) is avoided. This goes with the
277+ # argument that completely re-syncing a short header chain is worth it
278+ # comparing additional administrative costs (for a syncer client of that
279+ # module) of handling backward moves of the antecedent.
280+ #
272281 if hdr.number <= baseNum:
273282 return orphan # beyond reach
274283
@@ -278,10 +287,10 @@ proc tryFcParent(hc: HeaderChainRef; hdr: Header): HeaderChainMode =
278287 # `hdr` could have a parent on the `FC` module which obviously failed
279288 # (i.e. `base` is not parent of `hdr`.)
280289 if hc.session.finHeader.number <= baseNum:
281- # So `finalised` is ancestor of, or equal to `base`. In any case,
282- # `hdr` has no parent on the canonical branch up to `base`. So it is
283- # on another branch.
284- return orphan # on the wrong branch
290+ # So, if resolved at all then `finalised` is ancestor of, or equal to
291+ # `base`. In any case, ` hdr` has no parent on the canonical branch up
292+ # to `base`. So it is on another branch.
293+ return orphan # maybe on the wrong branch
285294
286295 # Now `base` and `finalised` (and all ancestors of either) are on the
287296 # the canonical branch of the DAG generated by the `CL` logic.
@@ -312,14 +321,16 @@ proc headUpdateFromCL(hc: HeaderChainRef; h: Header; f: Hash32) =
312321 if hc.session.mode == closed:
313322 # Set new session environment
314323 hc.session = HccSession ( # start new session
315- mode: notified ,
324+ mode: collecting ,
316325 ante: h,
317326 head: h,
318327 headHash: h.computeBlockHash (),
319328 finHash: f)
320329
321- # Inform client app about that a new session is available.
322- hc.notify (h.number, f)
330+ hc.kvt.putHeader (h.number, encodePayload h)
331+
332+ # Inform client app about that a new session has started.
333+ hc.notify ()
323334
324335 # For logging and metrics
325336 hc.session.consHeadNum = h.number
@@ -334,40 +345,13 @@ func state*(hc: HeaderChainRef): HeaderChainMode =
334345 # # Requested system state for running function:
335346 # # ::
336347 # # closed -- *internal*
337- # # notified -- accept()
338348 # # collecting -- put()
339349 # # ready -- complete()
340350 # # orphan -- n/a
341351 # # locked -- importBlock() from FC module
342352 # #
343353 hc.session.mode
344354
345- proc accept * (hc: HeaderChainRef ; fin: Header ): bool =
346- # # Accept and activate session.
347- # #
348- # # Required system state is to run this function is `notified`.
349- # #
350- if hc.state == notified and
351- hc.baseNum < fin.number and
352- fin.number <= hc.session.head.number:
353-
354- let finHash = fin.computeBlockHash ()
355- if hc.session.finHash != finHash:
356- return false
357-
358- hc.session.finHeader = fin
359- hc.kvt.putHeader (hc.session.head.number, encodePayload hc.session.head)
360-
361- # TODO : syncer and also ForkedCache should not start session
362- # using finalizedHash, as evident from hive test
363- # the FCU head can have block number bigger than finalized block.
364- # Syncer and ForkedCache should only deal with FCU headHash.
365- # TODO : move notifyBlockHashAndNumber call to fcPutHeader
366- # where one of the headers should also the finalized header.
367- hc.chain.notifyBlockHashAndNumber (finHash, fin.number)
368-
369- hc.session.mode = collecting
370- return true
371355
372356proc clear * (hc: HeaderChainRef ) =
373357 # # Clear and flush current header chain cache session. This applies to an
@@ -493,6 +477,14 @@ proc put*(
493477 return err (" Argument rev[] exceeds chain head " &
494478 hc.session.head.bnStr)
495479
480+ # Check whether the `FC` module has changed and the current antecedent
481+ # already is the end of it.
482+ block :
483+ let newMode = hc.tryFcParent (hc.session.ante)
484+ if newMode in {ready,orphan}:
485+ hc.session.mode = newMode
486+ return ok ()
487+
496488 # Start at the entry that is parent to `ante` (if any)
497489 let offset = ((lastNumber + 1 ) - hc.session.ante.number).int
498490 if offset < rev.len:
@@ -524,12 +516,18 @@ proc put*(
524516 return err (" Parent hash mismatch for rev[" & $ n & " ].number=" &
525517 bn.bnStr)
526518
527- # Check whether the current header matches the `finalised` one. If so,
528- # headers/hashes must match.
529- if hc.session.finHeader.number == bn:
530- if hc.session.finHash != hash:
531- raiseAssert RaisePfx & " finaliser not on header chain: " & bn.bnStr &
532- " hash=" & hc.session.finHash.short & " expected=" & hash.short
519+ # Resolve finaliser if possible.
520+ if hc.session.finHash == hash:
521+ hc.session.finHeader = hdr
522+
523+ # Ackn: moved here from `accept()`
524+ # TODO : syncer and also ForkedCache should not start session
525+ # using finalizedHash, as evident from hive test
526+ # the FCU head can have block number bigger than finalized block.
527+ # Syncer and ForkedCache should only deal with FCU headHash.
528+ # TODO : move notifyBlockHashAndNumber call to fcPutHeader
529+ # where one of the headers should also the finalized header.
530+ hc.chain.notifyBlockHashAndNumber (hash, bn)
533531
534532 # Check whether `hdr` has a parent on the `FC` module.
535533 let newMode = hc.tryFcParent (hdr)
@@ -570,6 +568,9 @@ proc commit*(hc: HeaderChainRef): Result[void,string] =
570568
571569 let baseNum = hc.baseNum
572570 if baseNum < hc.session.finHeader.number:
571+ #
572+ # So the `finalised` hash was resolved (otherwise it would have a zero
573+ # block number.)
573574 #
574575 # There are two segments of the canonical chain, `base..finalised` and
575576 # `ante..finalised` (the latter possibly degraded) which both share at
0 commit comments