mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-03 11:45:18 +00:00
* Update docs references from master to main Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update DOCS_README to reflect current reality Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update vuepress config with current versions and updated discussions link Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update generated docs versions Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update docs build to use temp folder instead of home Signed-off-by: Thane Thomson <connect@thanethomson.com> * Document build-docs Makefile target Signed-off-by: Thane Thomson <connect@thanethomson.com> * Add serve-docs Makefile target to serve local build of docs Signed-off-by: Thane Thomson <connect@thanethomson.com> * Ensure 404 page is copied during docs build Signed-off-by: Thane Thomson <connect@thanethomson.com> * Redirect /master/ to /main/ Signed-off-by: Thane Thomson <connect@thanethomson.com> * Attempt to resolve #7908 Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update OpenAPI references from master to main Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update CHANGELOG references from master to main Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update Docker readme references from master to main Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update UPGRADING references from master to main Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update package-specific documentation references from master to main Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update spec references from master to main Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update all code comment references to docs site from master to main Signed-off-by: Thane Thomson <connect@thanethomson.com> * Build v0.34.x as "latest" Signed-off-by: Thane Thomson <connect@thanethomson.com> * Explicitly mark v0.34 docs as latest in version selector Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update all links from docs.tendermint.com/main to docs.tendermint.com/latest Signed-off-by: Thane Thomson <connect@thanethomson.com> * ci: Redeploy docs on pushes to v0.34.x Signed-off-by: Thane Thomson <connect@thanethomson.com> * Temporarily copy spec directory into docs while building Signed-off-by: Thane Thomson <connect@thanethomson.com> * Add nav link to main and clearly mark as unstable Signed-off-by: Thane Thomson <connect@thanethomson.com> * Revert to only publishing docs in nav for v0.34 and v0.33 with no latest Signed-off-by: Thane Thomson <connect@thanethomson.com> * Link to docs.tendermint.com/v0.34 from RFCs Signed-off-by: Thane Thomson <connect@thanethomson.com> * Rather just use main for all docs.tendermint.com references on main branch Signed-off-by: Thane Thomson <connect@thanethomson.com> * Rename GitHub tree links from master to main Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update link for ABCI Rust client Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update github links from master to main Signed-off-by: Thane Thomson <connect@thanethomson.com> * Update badges in root readme Signed-off-by: Thane Thomson <connect@thanethomson.com> * Remove codecov badge since we do not use it any more Signed-off-by: Thane Thomson <connect@thanethomson.com> * Remove Java and Kotlin tutorials Signed-off-by: Thane Thomson <connect@thanethomson.com> * Remove specs from docs build Signed-off-by: Thane Thomson <connect@thanethomson.com> * Migrate spec links to GitHub repo from docs site Signed-off-by: Thane Thomson <connect@thanethomson.com> * Remove references to non-existent PEX reactor spec Signed-off-by: Thane Thomson <connect@thanethomson.com> * Fix linting badge in README Signed-off-by: Thane Thomson <connect@thanethomson.com> Signed-off-by: Thane Thomson <connect@thanethomson.com>
204 lines
7.2 KiB
Markdown
204 lines
7.2 KiB
Markdown
# ADR 080: ReverseSync - fetching historical data
|
|
|
|
## Changelog
|
|
|
|
- 2021-02-11: Migrate to tendermint repo (Originally [RFC 005](https://github.com/tendermint/spec/pull/224))
|
|
- 2021-04-19: Use P2P to gossip necessary data for reverse sync.
|
|
- 2021-03-03: Simplify proposal to the state sync case.
|
|
- 2021-02-17: Add notes on asynchronicity of processes.
|
|
- 2020-12-10: Rename backfill blocks to reverse sync.
|
|
- 2020-11-25: Initial draft.
|
|
|
|
## Author(s)
|
|
|
|
- Callum Waters (@cmwaters)
|
|
|
|
## Context
|
|
|
|
Two new features: [Block pruning](https://github.com/tendermint/tendermint/issues/3652)
|
|
and [State sync](https://github.com/tendermint/tendermint/blob/main/docs/architecture/adr-042-state-sync.md)
|
|
meant nodes no longer needed a complete history of the blockchain. This
|
|
introduced some challenges of its own which were covered and subsequently
|
|
tackled with [RFC-001](https://github.com/tendermint/tendermint/blob/main/docs/architecture/adr-077-block-retention.md).
|
|
The RFC allowed applications to set a block retention height; an upper bound on
|
|
what blocks would be pruned. However nodes who state sync past this upper bound
|
|
(which is necessary as snapshots must be saved within the trusting period for
|
|
the assisting light client to verify) have no means of backfilling the blocks
|
|
to meet the retention limit. This could be a problem as nodes who state sync and
|
|
then eventually switch to consensus (or fast sync) may not have the block and
|
|
validator history to verify evidence causing them to panic if they see 2/3
|
|
commit on what the node believes to be an invalid block.
|
|
|
|
Thus, this RFC sets out to instil a minimum block history invariant amongst
|
|
honest nodes.
|
|
|
|
## Proposal
|
|
|
|
A backfill mechanism can simply be defined as an algorithm for fetching,
|
|
verifying and storing, headers and validator sets of a height prior to the
|
|
current base of the node's blockchain. In matching the terminology used for
|
|
other data retrieving protocols (i.e. fast sync and state sync), we
|
|
call this method **ReverseSync**.
|
|
|
|
We will define the mechanism in four sections:
|
|
|
|
- Usage
|
|
- Design
|
|
- Verification
|
|
- Termination
|
|
|
|
### Usage
|
|
|
|
For now, we focus purely on the case of a state syncing node, whom after
|
|
syncing to a height will need to verify historical data in order to be capable
|
|
of processing new blocks. We can denote the earliest height that the node will
|
|
need to verify and store in order to be able to verify any evidence that might
|
|
arise as the `max_historical_height`/`time`. Both height and time are necessary
|
|
as this maps to the BFT time used for evidence expiration. After acquiring
|
|
`State`, we calculate these parameters as:
|
|
|
|
```go
|
|
max_historical_height = max(state.InitialHeight, state.LastBlockHeight - state.ConsensusParams.EvidenceAgeHeight)
|
|
max_historical_time = max(GenesisTime, state.LastBlockTime.Sub(state.ConsensusParams.EvidenceAgeTime))
|
|
```
|
|
|
|
Before starting either fast sync or consensus, we then run the following
|
|
synchronous process:
|
|
|
|
```go
|
|
func ReverseSync(max_historical_height int64, max_historical_time time.Time) error
|
|
```
|
|
|
|
Where we fetch and verify blocks until a block `A` where
|
|
`A.Height <= max_historical_height` and `A.Time <= max_historical_time`.
|
|
|
|
Upon successfully reverse syncing, a node can now safely continue. As this
|
|
feature is only used as part of state sync, one can think of this as merely an
|
|
extension to it.
|
|
|
|
In the future we may want to extend this functionality to allow nodes to fetch
|
|
historical blocks for reasons of accountability or data accessibility.
|
|
|
|
### Design
|
|
|
|
This section will provide a high level overview of some of the more important
|
|
characteristics of the design, saving the more tedious details as an ADR.
|
|
|
|
#### P2P
|
|
|
|
Implementation of this RFC will require the addition of a new channel and two
|
|
new messages.
|
|
|
|
```proto
|
|
message LightBlockRequest {
|
|
uint64 height = 1;
|
|
}
|
|
```
|
|
|
|
```proto
|
|
message LightBlockResponse {
|
|
Header header = 1;
|
|
Commit commit = 2;
|
|
ValidatorSet validator_set = 3;
|
|
}
|
|
```
|
|
|
|
The P2P path may also enable P2P networked light clients and a state sync that
|
|
also doesn't need to rely on RPC.
|
|
|
|
### Verification
|
|
|
|
ReverseSync is used to fetch the following data structures:
|
|
|
|
- `Header`
|
|
- `Commit`
|
|
- `ValidatorSet`
|
|
|
|
Nodes will also need to be able to verify these. This can be achieved by first
|
|
retrieving the header at the base height from the block store. From this trusted
|
|
header, the node hashes each of the three data structures and checks that they are correct.
|
|
|
|
1. The trusted header's last block ID matches the hash of the new header
|
|
|
|
```go
|
|
header[height].LastBlockID == hash(header[height-1])
|
|
```
|
|
|
|
2. The trusted header's last commit hash matches the hash of the new commit
|
|
|
|
```go
|
|
header[height].LastCommitHash == hash(commit[height-1])
|
|
```
|
|
|
|
3. Given that the node now trusts the new header, check that the header's validator set
|
|
hash matches the hash of the validator set
|
|
|
|
```go
|
|
header[height-1].ValidatorsHash == hash(validatorSet[height-1])
|
|
```
|
|
|
|
### Termination
|
|
|
|
ReverseSync draws a lot of parallels with fast sync. An important consideration
|
|
for fast sync that also extends to ReverseSync is termination. ReverseSync will
|
|
finish it's task when one of the following conditions have been met:
|
|
|
|
1. It reaches a block `A` where `A.Height <= max_historical_height` and
|
|
`A.Time <= max_historical_time`.
|
|
2. None of it's peers reports to have the block at the height below the
|
|
processes current block.
|
|
3. A global timeout.
|
|
|
|
This implies that we can't guarantee adequate history and thus the term
|
|
"invariant" can't be used in the strictest sense. In the case that the first
|
|
condition isn't met, the node will log an error and optimistically attempt
|
|
to continue with either fast sync or consensus.
|
|
|
|
## Alternative Solutions
|
|
|
|
The need for a minimum block history invariant stems purely from the need to
|
|
validate evidence (although there may be some application relevant needs as
|
|
well). Because of this, an alternative, could be to simply trust whatever the
|
|
2/3+ majority has agreed upon and in the case where a node is at the head of the
|
|
blockchain, you simply abstain from voting.
|
|
|
|
As it stands, if 2/3+ vote on evidence you can't verify, in the same manner if
|
|
2/3+ vote on a header that a node sees as invalid (perhaps due to a different
|
|
app hash), the node will halt.
|
|
|
|
Another alternative is the method with which the relevant data is retrieved.
|
|
Instead of introducing new messages to the P2P layer, RPC could have been used
|
|
instead.
|
|
|
|
The aforementioned data is already available via the following RPC endpoints:
|
|
`/commit` for `Header`'s' and `/validators` for `ValidatorSet`'s'. It was
|
|
decided predominantly due to the instability of the current RPC infrastructure
|
|
that P2P be used instead.
|
|
|
|
## Status
|
|
|
|
Proposed
|
|
|
|
## Consequences
|
|
|
|
### Positive
|
|
|
|
- Ensures a minimum block history invariant for honest nodes. This will allow
|
|
nodes to verify evidence.
|
|
|
|
### Negative
|
|
|
|
- Statesync will be slower as more processing is required.
|
|
|
|
### Neutral
|
|
|
|
- By having validator sets served through p2p, this would make it easier to
|
|
extend p2p support to light clients and state sync.
|
|
- In the future, it may also be possible to extend this feature to allow for
|
|
nodes to freely fetch and verify prior blocks
|
|
|
|
## References
|
|
|
|
- [RFC-001: Block retention](https://github.com/tendermint/tendermint/blob/main/docs/architecture/adr-077-block-retention.md)
|
|
- [Original issue](https://github.com/tendermint/tendermint/issues/4629)
|