-
Notifications
You must be signed in to change notification settings - Fork 197
Open
Labels
PreserveStale Bot repellentStale Bot repellentProtocolTeam: Issues assigned to the Protocol Pillar.Team: Issues assigned to the Protocol Pillar.S-AccessTech Debt
Description
At the moment, the storage API naively returns any data it finds in the database (when queried with the appropriate key). For example:
- store.Headers will return any block header by its ID if that header is found in the database
- Lets take a look at how we currently bootstrap nodes:
- the sealing segment contains a section of a finalized fork (blocks
B
tohead
in the documentation below):flow-go/model/flow/sealing_segment.go
Lines 11 to 25 in 4c04c46
// SealingSegment is a continuous segment of recently finalized blocks that contains enough history // for a new node to execute its business logic normally. It is part of the data need to initialize // a new node to join the network. // DETAILED SPECIFICATION: ./sealing_segment.md // // ├═══════════┤ ├───────────────────────┤ // ExtraBlocks ^ Blocks ^ // B head // // Lets denote the highest block in the sealing segment as `head`. Per convention, `head` must be a // finalized block. Consider the chain of blocks leading up to `head` (included). The highest block // in chain leading up to `head` that is sealed, we denote as B. // In other words, head is the last finalized block, and B is the last sealed block, // block at height (B.Height + 1) is not sealed. type SealingSegment struct { - Block
B
(which isSealingSegment.Blocks[0]
) will be set as the node's root block (👉 code). For the node's root block and above, the protocol state guarantees that all indices are populated. - The challenge is that consensus might require information below the node's root block. This information is provided by
ExtraBlocks
, as explained here (see sealing_segment.md for further details):flow-go/model/flow/sealing_segment.go
Lines 33 to 41 in 4c04c46
// ExtraBlocks [optional] holds ancestors of `Blocks` in ascending height order. // Formally, ExtraBlocks contains at least the additional history to satisfy conditions // (see sealing_segment.md for details): // (ii) All blocks that are sealed by `head`. This is relevant if `head` contains _multiple_ seals. // (iii) The sealing segment holds the history of all non-expired collection guarantees, i.e. // limitHeight := max(blockSealedAtHead.Height - flow.DefaultTransactionExpiry, SporkRootBlockHeight) // where blockSealedAtHead is the block sealed by `head` block. // (Potentially longer history is permitted) ExtraBlocks []*Proposal - It is important to emphasize that we store these extra blocks in the database (👉 code):
These blocks are ancestors of
segment.Blocks
, i.e. below the history cut-off. Therefore, we only persist the extra blocks and index them by height, while all the other indices are omitted, as they would potentially reference non-existent data.
- the sealing segment contains a section of a finalized fork (blocks
In summary,
- It is currently possible to query blocks and some other information for blocks below the node's root block. However, this information is not complete.
- This induces a consistency problem for the Access Node. For example, a client can query by height blocks some blocks that are below the node's root block. But when asked about the children of such block, the Access Node will respond with "this block has no known children" (👉 code). But how can that be, the Access Node knows the finalized block at that height (?) From the client's perspective, this doesn't make sense.
We have discussed this in slack here.
Suggestion
by @peterargue
- For some storage abstractions (like store.Headers), we could add a wrapper that checks whether the data object is below the node's root block. For headers, this is just a simple height or view comparison.
- we could error in case a header is below the node's root block
- we probably need to add additional methods for querying data below the node's root block for the very few places in the code where this is actually intended
- However, for other data types such as
Payloads
, this check is not trivial and requires pulling additional data.
Metadata
Metadata
Assignees
Labels
PreserveStale Bot repellentStale Bot repellentProtocolTeam: Issues assigned to the Protocol Pillar.Team: Issues assigned to the Protocol Pillar.S-AccessTech Debt