github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/model/flow/sealing_segment.md (about) 1 # Sealing Segment 2 3 The `SealingSegment` is a section of the finalized chain. It is part of the data need to 4 initialize a new node to join the network. Informally, the `SealingSegment` is continuous section 5 of recently finalized blocks that is long enough for the new node to execute its business logic. 6 7 ## History length covered by the Sealing Segment 8 9 The `SealingSegment` is created from a `protocol.Snapshot` via the method `SealingSegment`. 10 Lets denote the block that the `protocol.Snapshot` refers to as `head`. Per convention, 11 `head` must be a finalized block. 12 13 ### Part 1: from `head` back to the latest sealed block 14 15 The SealingSegment is a chain segment such that the last block (greatest height) 16 is this snapshot's reference block (i.e. `head`) and the first (least height) is the most 17 recently sealed block as of this snapshot. 18 In other words, the most recently incorporated seal as of the highest block 19 references the lowest block. The highest block does not need to contain this seal. 20 * Example 1: block `E` seals `A` 21 ``` 22 A <- B <- C <- D <- E(SA) 23 ``` 24 Here, `SA` denotes the seal for block `A`. 25 In the sealing segment's last block (`E`) has a seal for block `A`, which is the first block of the sealing segment. 26 27 * Example 2: `E` contains no seals, but latest seal prior to `E` seals `A` 28 ``` 29 A <- B <- C <- D(SA) <- E 30 ``` 31 * Example 3: `E` contains multiple seals 32 ``` 33 B <- C <- D <- E(SA, SB) 34 ``` 35 36 Per convention, the blocks from Part 1, go into the slice `SealingSegment.Blocks`: 37 ```golang 38 type SealingSegment struct { 39 // Blocks contain the chain [block sealed by `head`] <- ... <- [`head`] in ascending height order. 40 Blocks []*Block 41 42 ⋮ 43 } 44 ``` 45 46 **Minimality Requirement for `SealingSegment.Blocks`**: 47 In example 3, note that block `B` is the highest sealed block as of `E`. Therefore, the 48 lowest block in `SealingSegment.Blocks` must be `B`. Essentially, this is a minimality 49 requirement for the history: it shouldn't be longer than necessary. So 50 extending the chain segment above to `A <- B <- C <- D <- E(SA, SB)` would 51 be an invalid value for field `SealingSegment.Blocks`. 52 53 ### Part 2: `ExtraBlocks` 54 55 In addition, the `SealingSegment` contains the field `ExtraBlocks`: 56 57 ```golang 58 // ExtraBlocks [optional] holds ancestors of `Blocks` in ascending height order. These blocks 59 // are connecting to `Blocks[0]` (the lowest block of sealing segment). Formally, let `l` 60 // be the length of `ExtraBlocks`, then ExtraBlocks[l-1] is the _parent_ of `Blocks[0]`. 61 // These extra blocks are included in order to ensure that a newly bootstrapped node 62 // knows about all entities which might be referenced by blocks which extend from 63 // the sealing segment. 64 // ExtraBlocks are stored separately from Blocks, because not all node roles need 65 // the same amount of history. Blocks represents the minimal possible required history; 66 // ExtraBlocks represents additional role-required history. 67 ExtraBlocks []*Block 68 ``` 69 70 **In case `head` contains multiple seals, we need _all_ the sealed blocks**, for the following reason: 71 * All nodes locally maintain a copy of the protocol state. A service event may change the state of the protocol state. 72 * For Byzantine resilience, we don't want protocol-state changes to take effect immediately. Therefore, we process 73 system events only after receiving a QC for the block. 74 75 Now let us consider the situation where a newly initialized node comes online and processes the first child of `head`. 76 Lets reuse the example from above, where our head was block `E` and we are now processing the child `X` 77 ``` 78 A <- B <- C <- D <- E(SA, SB) <- X 79 ├═══════════┤ ├───────────────────────┤ new 80 ExtraBlocks Blocks block 81 ``` 82 `X` carries the QC for `E`, hence the protocol-state changes in `E` take effect for `X`. Therefore, when processing `X`, 83 we go through the seals in `E` and look through the sealed execution results for service events. 84 * As the service events are order-sensitive, we need to process the seals in the correct order, which is by increasing height 85 of the sealed block. The seals don't contain the block's height information, hence we need to resolve the block. 86 87 **Extended history to check for duplicated collection guarantees in blocks** is required by nodes that _validate_ block 88 payloads (e.g. consensus nodes). Also Access Nodes require these blocks. Collections expire after `flow.DefaultTransactionExpiry` blocks. 89 Hence, we desire a history of `flow.DefaultTransactionExpiry` blocks. However, there is the edge case of a recent spork (or genesis), 90 where the history is simply less that `flow.DefaultTransactionExpiry`. 91 92 ### Formal definition 93 94 The descriptions from the previous section can be formalized as follows 95 96 * (i) The highest sealed block as of `head` needs to be included in the sealing segment. 97 This is relevant if `head` does not contain any seals. 98 * (ii) All blocks that are sealed by `head`. This is relevant if `head` contains _multiple_ seals. 99 * (iii) The sealing segment should contain the history back to (including): 100 ``` 101 limitHeight := max(blockSealedAtHead.Height - flow.DefaultTransactionExpiry, SporkRootBlockHeight) 102 ``` 103 where blockSealedAtHead is the block sealed by `head` block. 104 Note that all three conditions have to be satisfied by a sealing segment. Therefore, it must contain the longest history 105 required by any of the three conditions. The 'Spork Root Block' is the cutoff. 106 107 Per convention, we include the blocks for (i) in the `SealingSegment.Blocks`, while the 108 additional blocks for (ii) and optionally (iii) are contained in as `SealingSegment.ExtraBlocks`. 109 110 111 Condition (i) and (ii) are necessary for the sealing segment for _any node_. In contrast, (iii) is 112 necessary to bootstrap nodes that _validate_ block payloads (e.g. consensus nodes), to verify that 113 collection guarantees are not duplicated (collections expire after `flow.DefaultTransactionExpiry` blocks). 114 115 ## Special case: Root Sealing Segment 116 117 The spork is initialized with a single 'spork root block'. A root sealing segment is a sealing segment containing root block: 118 * the root block is a self-sealing block with an empty payload 119 * the root block must be the first block (least height) in the segment 120 * no blocks in the segment may contain any seals (by the minimality requirement) 121 * it is possible (but not necessary) for root sealing segments to contain _only_ the root block 122 123 Examples: 124 * Example 1: one self-sealing root block 125 ``` 126 ROOT 127 ``` 128 The above sealing segment is the form of sealing segments within root snapshots, 129 for example those snapshots used to bootstrap a new network, or spork. 130 * Example 2: one self-sealing root block followed by any number of seal-less blocks 131 ``` 132 ROOT <- A <- B 133 ``` 134 All non-root sealing segments contain more than one block. 135 Sealing segments are in ascending height order. 136 137 In addition to storing the blocks within the sealing segment, as defined above, 138 the `SealingSegment` structure also stores any resources which are referenced 139 by blocks in the segment, but not included in the payloads of blocks within 140 the segment. In particular: 141 * results referenced by receipts within segment payloads 142 * results referenced by seals within segment payloads 143 * seals which represent the latest state commitment as of a segment block 144 145 ## Outlook 146 147 In its current state, the sealing segment has been evolving driven by different needs. Most likely, there is some room for simplifications 148 and other improvements. However, an important aspect of the sealing segment is to allow newly-joining nodes to build an internal representation 149 of the protocol state, in particular the identity table. There are large changes coming around when we move to the dynamic identity table. 150 Therefore, we accept that the Sealing Segment currently has some technical debt and unnecessary complexity. Once we have implemented the 151 dynamic identity table, we will have a much more solidified understanding of the data in the sealing segment. 152