Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework lowest block height in storage #2789

Conversation

Fraser999
Copy link
Contributor

@Fraser999 Fraser999 commented Mar 25, 2022

This PR replaces the disjoint sequence tracking in storage with a persisted lowest_contiguous_block_height variable. The value represents the lowest block from which the node has contiguous blocks (and corresponding global state) to the current chain tip.

It is updated after node startup when the chain synchronization has retrieved the trusted block. In sync-to-genesis mode, the value is set to 0 and in fast-sync mode, it is set to the height of the trusted block the most recent block.

The value is only actually changed and written to the DB if:

  • it doesn't previously exist, or
  • the new height is lower than the current one, or
  • the new height is higher than the highest block stored at node startup (before chain sync commenced)

A new AvailableBlockRange struct was added to avoid using (u64, u64) to represent the range. It is more explicit in the code and in the JSON-RPC error response:

"error": {
  "code": -32001,
  "message": "block at height 1314 not stored on this node",
  "data": {
    "available_block_range": {
      "low": 75,
      "high": 112
    }
  }
}

Closes #2779.

node/src/components/chain_synchronizer/operations.rs Outdated Show resolved Hide resolved
pub(super) fn highest_contiguous_block_height_range(low: u64, high: u64) -> Self {
ErrorData::HighestContiguousBlockHeightRange((low, high))
}
HighestContiguousBlockHeightRange(ContiguousBlockRange),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we now have a single range, it no longer needs to be called Highest (also in the comment).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, I'll rename to AvailableBlockRange.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in b834b44.

node/src/components/chain_synchronizer/operations.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@rafal-ch rafal-ch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

node/CHANGELOG.md Outdated Show resolved Hide resolved
Copy link
Contributor

@goral09 goral09 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comments but no blockers.

node/src/components/chain_synchronizer/operations.rs Outdated Show resolved Hide resolved
@@ -36,7 +36,7 @@ All notable changes to this project will be documented in this file. The format
* Connection handshake timeouts can now be configured via the `handshake_timeout` variable (they were hardcoded at 20 seconds before).
* `Key::SystemContractRegistry` is now readable and can be queried via the RPC.
* Requests for data from a peer are now de-prioritized over networking messages necessary for consensus and chain advancement.
* JSON-RPC responses which fail to provide requested data will now also include an indication of that node's highest contiguous block height range, i.e. the block heights for which it holds all global state
* JSON-RPC responses which fail to provide requested data will now also include an indication of that node's available block range, i.e. the block heights for which it holds all global state. For nodes running with `[node.sync_to_genesis]` set to true, the range will be the full blockchain, otherwise the range will start at a block near the tip of the chain when the node started running.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* JSON-RPC responses which fail to provide requested data will now also include an indication of that node's available block range, i.e. the block heights for which it holds all global state. For nodes running with `[node.sync_to_genesis]` set to true, the range will be the full blockchain, otherwise the range will start at a block near the tip of the chain when the node started running.
* JSON-RPC responses which fail to provide requested data will now also include an indication of that node's available block range, i.e. the block heights for which it holds all global state. For nodes running with `[node.sync_to_genesis]` set to true, the range will be the full blockchain, otherwise the range will start at a block near the tip of the chain when the node started running.

😎

Copy link
Contributor Author

@Fraser999 Fraser999 Mar 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have conflicts to sort out in the changelog which I plan to do once #2788 also merges. I'll fix this when I do that :)

let low = self.lowest_available_block_height;
match AvailableBlockRange::new(low, high) {
Ok(range) => range,
Err(error) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only possible error here is when high is actually lower than low. Maybe it makes sense here to flip them? It seems to be harmless and maybe the problem would "work itself out" until the next query (if the index and/or lowest_available_block_height get updated).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd rather leave as is. It's really pointing to a bug in our core logic if that actually arises (but not something worth stopping the node over). So the default range [MAX, MAX] being returned to the client is probably a better indication that something is very wrong server side than asking for e.g. block 150 and getting back an error saying the server's available blocks are 100 -> 200.

// We should update the value if
// * it wasn't already stored, or
// * the new value is lower than the available range at startup, or
// * the new value is 2 or more higher than (after pruning due to hard-reset) the available
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: maybe it's worth including an explanation why is that a problem since it may not be obvious to the reader. I.e. just write that there would be a single-block gap in the sequence where we might not have the Global State.

@Fraser999
Copy link
Contributor Author

bors merge

@casperlabs-bors-ng
Copy link
Contributor

Build succeeded:

@casperlabs-bors-ng casperlabs-bors-ng bot merged commit 4e6367f into casper-network:dev Mar 25, 2022
@Fraser999 Fraser999 deleted the 2779-change-lowest-cont-block-height branch March 25, 2022 22:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Change LowestContiguousBlockHeight in storage to represent the lowest block previously used as a trusted hash
3 participants