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