github.com/koko1123/flow-go-1@v0.29.6/state/fork/Readme.md (about) 1 # Traversing a Fork 2 3 Generally, when traversing a fork (in either direction), there are two distinct blocks: 4 * the `head` of the fork that should be traversed 5 * the `lowestBlock` in that fork, that should be included in the traversal 6 7 The traversal the walks `head <--> lowestBlock` (in either direction). 8 9 There are a variety of ways to precisely specify `head` and `lowestBlock`: 10 * At least one block, `head` or `lowestBlock`, must be specified by its ID 11 to unambiguously identify the fork that should be traversed. 12 * The other block an either be specified by ID or height. 13 * If both `head` and `lowestBlock` are specified by their ID, 14 they must both be on the same fork. 15 16 ### Convention 17 18 **For the core traversal algorithms, we use the following conventions:** 19 1. The `head` of the fork that should be traversed is specified by its `ID` 20 2. The `lowestBlock` is specified by its height: `lowestHeightToVisit`. 21 3. If `head.Height < lowestHeightToVisit`, no blocks are visited and the 22 traversal returns immediately (without error). 23 24 This design is inspired by a `for` loop. For example, lets consider the case where we start 25 at the fork `head` and traverse backwards until we reach a block with height `lowestHeightToVisit`: 26 ```golang 27 for block := head; block.Height >= lowestHeightToVisit; block = block.Parent { 28 visit(block) 29 } 30 ``` 31 32 For the core traversal algorithms, the parametrization of `head` [type `flow.ID`], 33 `lowestHeightToVisit` [type `uint64`], and direction is beneficial, as there are no inconsistent parameter sets. 34 (There is the edge-case of the root block, which we ignore in this high-level discussion) 35 36 37 38 39 ### Terminals 40 41 Higher-level algorithms that want to collect specific data from a fork have a variety of 42 different termination conditions, such as: 43 * walk backwards up to (_including_) the block with ID `xyz` or _excluding_ the block with ID `xyz` 44 45 To provide higher-level primitives for terminating the fork traversal, we include 46 `Terminals`. Essentially, a `Terminal` converts a high-level condition for the `lowestBlock` 47 to a suitable parametrization for the core traversal algorithm: 48 49 * The height `lowestHeightToVisit` of the lowest block that should be visited. 50 * A consistency check `ConfirmTerminalReached` for the lowest visited block. 51 This check is predominantly useful 52 in case both `head` and `lowestBlock` are specified by their ID. It allows to enforce that 53 `head` and `lowestBlock` are both on the same fork and error otherwise. 54 55 However, the precise implementation of `ConfirmTerminalReached` is left to the Terminal. 56 Other, more elaborate conditions are possible.