From a5a37c5d5e697c4295c9cc85124543231bde2032 Mon Sep 17 00:00:00 2001 From: Cofson Date: Sun, 21 Dec 2025 17:10:17 +0100 Subject: [PATCH] Add Cryptarchia v1 Bootstrap and Synchronization specification Raw specification transcribed from source document covering: - Bootstrap Protocol for new nodes joining the network - Chain Synchronization mechanisms - Fork resolution and chain selection rules --- nomos/raw/cryptarchia-v1-bootstr-sync.md | 452 +++++++++++++++++++++++ 1 file changed, 452 insertions(+) create mode 100644 nomos/raw/cryptarchia-v1-bootstr-sync.md diff --git a/nomos/raw/cryptarchia-v1-bootstr-sync.md b/nomos/raw/cryptarchia-v1-bootstr-sync.md new file mode 100644 index 0000000..0aa5d5a --- /dev/null +++ b/nomos/raw/cryptarchia-v1-bootstr-sync.md @@ -0,0 +1,452 @@ +--- +title: CRYPTARCHIA-V1-BOOTSTRAPPING-SYNCHRONIZATION +name: Cryptarchia v1 Bootstrapping & Synchronization +status: raw +category: Standards Track +tags: nomos, cryptarchia, bootstrapping, synchronization, consensus +editor: Youngjoon Lee +contributors: + - David Rusu + - Giacomo Pasini + - Álvaro Castro-Castilla + - Daniel Sanchez Quiros +--- + +## Abstract + +This document specifies the bootstrapping and synchronization protocol +for Cryptarchia v1 consensus. +When a new node joins the network or a previously-bootstrapped node has been offline, +it MUST catch up with the most recent honest chain +by fetching missing blocks from peers before listening for new blocks. +The protocol defines mechanisms for setting fork choice rules, +downloading blocks, and handling orphan blocks +while mitigating long range attacks. + +## Semantics + +The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be +interpreted as described in RFC 2119. + +## Introduction + +When a new node joins the network or a previously-bootstrapped node has been offline +for a while, +it cannot follow the most recent honest chain solely by receiving only new blocks +because those new blocks cannot be added to the block tree +that does not have their parent block. +These nodes MUST first catch up with the most recent honest chain +by fetching missing blocks from their peers +before they start listening for new blocks. + +This document specifies a protocol for nodes to bootstrap with the honest chain +efficiently while mitigating long range attacks. +It also defines how to handle the case which the node falls behind +after the bootstrapping is complete. + +This protocol adheres to the key invariant: +We MUST never roll back blocks that are deeper than the latest immutable block +$B_\text{imm}$ in the local chain $c_{loc}$, +as defined in Cryptarchia v1 Protocol Specification. + +## Overview + +This protocol defines the bootstrapping mechanism +that covers all of the following cases: + +- From the **Genesis** block +- From the **checkpoint** block obtained from a trusted checkpoint provider +- From the **local block tree** + (with $B_\text{imm}$ newer than the Genesis and the checkpoint) + +Additionally, the protocol defines the synchronization mechanism +that handles orphan blocks while listening for new blocks +after the bootstrapping is completed. + +The protocol consists of the following key components: + +- Determining the fork choice rule (Bootstrap or Online) at startup +- Switching the fork choice rule from Bootstrap to Online +- Downloading blocks from peers + +Upon startup, a node **determines the fork choice rule**, +as defined in Setting the Fork Choice Rule. +If the Bootstrap rule is selected, it is maintained for the Prolonged Bootstrap Period, +after which the node switches to the Online rule. + +Using the fork choice rule chosen, the node **downloads blocks** +to catch up with the tip of the local chain $c_{loc}$ of each peer. + +After downloading is done, the node starts **listening for new blocks**. +Upon receiving a new block, the node validates and adds it to its local block tree. +If the ancestors of the block are missing from the local block tree, +the node downloads missing ancestors using the same mechanism as above. + +## Protocol + +### Constants + +| Constant | Name | Description | Value | +|----------|------|-------------|-------| +| $T_\text{offline}$ | Offline Grace Period | A period during which a node can be restarted without switching to the Bootstrap rule. | 20 minutes | +| $T_\text{boot}$ | Prolonged Bootstrap Period | A period during which Bootstrap fork choice rule must be continuously used after Initial Block Download is completed. This gives nodes additional time to compare their synced chain with a broader set of peers. | 24 hours | +| $s_\text{gen}$ | Density Check Slot Window | A number of slots used by density check of Bootstrap rule. This constant is defined in Cryptarchia Fork Choice Rule - Definitions. | $\lfloor\frac{k}{4f}\rfloor$ (=4h30m) | + +### Setting the Fork Choice Rule + +Upon startup, a node sets the fork choice rule to the **Bootstrap** rule +in one of the following cases. +Otherwise, the node uses the **Online** fork choice rule. + +- **A node is starting with $B_\text{imm}$ set to the Genesis block + or from a checkpoint block.** + + The node is setting its latest immutable block $B_\text{imm}$ + to the Genesis or a checkpoint, + which clearly indicates that the node intends to catch up with the subsequent blocks. + Regardless of how many subsequent blocks remain, + the node SHOULD use the Bootstrap rule to mitigate long range attacks. + +- **A node is restarting after being offline longer than $T_\text{offline}$ (20 minutes).** + + Unlike starting from Genesis or checkpoint, in the case where a node is restarted + while preserving its existing block tree, + the node MUST choose a fork choice rule depending on how long it has been offline. + + If it is certain that a node has been offline longer than the offline grace period + $T_\text{offline}$ since it last used the Online rule, + the node uses the Bootstrap rule upon startup. + Otherwise, it starts with the Online rule. + + Details of $T_\text{offline}$ are described in Offline Grace Period. + A recommended way how to measure the offline duration + is introduced in Offline Duration Measurement. + +- **A node operator set the Bootstrap rule explicitly (e.g., by `--bootstrap` flag).** + + In any case where the node operator is clearly aware that the node has fallen behind + by more than $k$ blocks, + they SHOULD be able to start the node with the Bootstrap rule. + For example, the operator may obtain the latest block height + from another trusted operator + and realize that their node has fallen significantly behind due to some issue. + +### Initial Block Download + +If peers for Initial Block Download (IBD) are configured, +a node performs IBD by downloading blocks to catch up with the tip +of the local chain $c_{loc}$ of each peer +using the fork choice rule chosen in Setting the Fork Choice Rule. + +Blocks are downloaded in parent-to-child order, +as defined in the Downloading Blocks mechanism. +This mechanism applies not only when a node starts from the Genesis block, +but also when it already has the local block tree (or a checkpoint block). + +```python +def initial_block_download(peers, local_tree): + # In real implementation, these downloadings can be run in parallel. + # Also, any optimization can be applied to minimize downloadings, + # such as grouping peers by tip. + for peer in peers: + download_blocks(local_tree, peer, target_block=None) +``` + +The downloaded blocks are validated and added to the local block tree +using the fork choice rule determined above. + +According to Cryptarchia v1 Protocol Specification - Block Header Validation, +the downloaded blocks are validated and added to the local block tree +using the fork choice rule determined above. + +If all IBD peers become unavailable before the node catches up +with at least one of the IBD peers, +the node is terminated with an error, +allowing the operator to restart the node with other IBD peers. + +If downloading is done successfully, +the node starts listening for new blocks as described in Listening for New Blocks. + +### Prolonged Bootstrap Period + +After Initial Block Download is completed, +a node MUST maintain the Bootstrap fork choice rule during the Bootstrap Period $T_\text{boot}$, +if the node chose the Bootstrap rule at Setting the Fork Choice Rule. + +The purpose of the Prolonged Bootstrap Period is giving a syncing node +additional time +to compare its synced chain with a broader set of peers. +In other words, it provides the node with an opportunity +to connect to different peers +and verify whether they are on the same chain. +If the syncing node has downloaded blocks only from peers within an isolated network, +the result of Initial Block Download may not reflect the honest chain +followed by the majority of the entire network. +To resolve such situations, the node SHOULD continue using the Bootstrap rule +while discovering additional peers, +allowing it to switch to a better chain if one is found. + +Theoretically, the Bootstrap rule should be prolonged +until the node has seen a sufficient number of blocks +beyond the $s_\text{gen}$ slot window, +which is required for the density check of the Bootstrap rule to be meaningful. +However, if the node has seen a fork longer than $k$ blocks +from its divergence block during Initial Block Download, +it means that the node has already seen more slots than $s_\text{gen}$ +with very high probability, considering the small size of $s_\text{gen} = k/(4f)$. +If the node has never seen any fork longer than $k$ blocks, +it means that all forks could have been handled by the longest chain rule, +which is part of the Bootstrap rule. +Therefore, this protocol does not explicitly wait $s_\text{gen}$ slots +after Initial Block Download. +In other words, the protocol does not use $s_\text{gen}$ +to configure the Prolonged Bootstrap Period. + +This protocol configures the Bootstrap Period to 24 hours. + +A timer MUST be started when Listening for New Blocks is started +after Initial Block Download is completed. +Once the timer is completed, the fork choice rule is switched to the Online rule. + +### Listening for New Blocks + +Once Initial Block Download is complete and Prolonged Bootstrap Period is started, +a node starts listening for new blocks relayed by its peers. + +Upon receiving a new block, +the node tries to validate and add it to its local block tree, +as defined in Cryptarchia v1 Protocol Specification - Chain Maintenance. + +If the parent of the block is missing from the local block tree, +the block cannot be fully validated and added. +These blocks are called *orphan blocks*. +To handle an orphan block, +the node downloads missing blocks from a randomly selected peer, +as described in Downloading Blocks. +If the request fails, the node MAY retry with different peers +before abandoning the orphan block. +The retry policy can be configured by implementers. + +Note that downloading missing blocks does not need to be triggered +if it is clear that the orphan block is in a fork +diverged before the latest immutable (committed) block, +as the node MUST never revert immutable blocks. + +```python +def listen_and_process_new_blocks(fork_choice: ForkChoice, + local_tree: Tree, + peers: List[Node]): + for block in listen_for_new_blocks(): + try: + # Run the chain maintenance defined in the Cryptarchia spec. + local_tree.on_block(block, fork_choice) + except InvalidBlock: + continue + except ParentNotFound: + # Ignore the orphan block proactively, + # if it's clear that the orphan block is in a fork + # behind the latest immutable block + # because immutable blocks should never be reverted. + # This check doesn't cover all cases, but the uncovered cases + # will be handled by the Cryptarchia block validation + # during the `download_blocks` below. + if block.height <= local_tree.latest_immutable_block().height: + continue + # In real implementation, downloading can be run in background + # with the retry policy. + download_blocks(local_tree, random.choice(peers), + target_block=block.id) +``` + +### Downloading Blocks + +For performing Initial Block Download and handling orphan blocks +while Listening for New Blocks, +a node sends a `DownloadBlocksRequest` to a peer, +which MUST respond with blocks in parent-to-child order. +This communication should be implemented based on Libp2p streaming. + +#### Libp2p Protocol ID + +- Mainnet: `/nomos/cryptarchia/sync/1.0.0` +- Testnet: `/nomos-testnet/cryptarchia/sync/1.0.0` + +```python +class DownloadBlocksRequest: + # Ask blocks up to the target block. + # The response may not contain the target block + # if the responder limits the number of blocks returned. + # In that case, the requester must repeat the request. + target_block: BlockId + # To allow the peer to determine the starting block to return. + known_blocks: KnownBlocks + +class KnownBlocks: + local_tip: BlockId + latest_immutable_block: BlockId + # Additional known blocks. + # A responder will reject a request if this list contains more than 5. + additional_blocks: list[BlockId] + +class DownloadBlocksResponse: + # A stream of blocks in parent-to-child order. + # The max number of blocks to be returned can be limited by implementers. + # A requester can read the stream until the stream returns "NoMoreBlock". + blocks: Stream[Block | "NoMoreBlock"] +``` + +The responding peer uses `KnownBlocks` to determine the optimal starting block +for the response stream, aiming to minimize the number of blocks to be returned. +The requesting node can include any block it believes could assist in this process +to the `KnownBlocks.additional_blocks`. +To avoid spamming responders, +the size of `KnownBlocks.additional_blocks` is limited to 5. + +The responding peer finds the latest common ancestor (i.e. LCA) +between the `target_block` and each of the known blocks. +Then, it returns a stream of blocks, starting from the highest LCA. +To mitigate malicious downloading requests, +the peer limits the number of blocks to be returned. +The detailed implementation is up to implementers, +depending on their internal architecture (e.g. storage design). + +The requesting node SHOULD repeat `DownloadBlocksRequest`s +by updating the `KnownBlocks` in order to download the next batches of blocks. +The following code shows how the requesting node can be implemented. + +```python +def download_blocks(local_tree: Tree, peer: Node, + target_block: Optional[BlockId]): + latest_downloaded: Optional[Block] = None + while True: + # Fetch the peer's tip if target is not specified. + target_block = target_block if target_block is not None else peer.tip() + # Don't start downloading if target is already in local. + if local_tree.has(target_block): + return + + req = DownloadBlocksRequest( + # If target_block is None, specify the current peer's tip + # each time when we build DownloadBlocksRequest, + # so that we can catch up with the most recent peer's tip. + target_block=target_block, + known_blocks=KnownBlocks( + local_tip=local_tree.tip().id, + latest_immutable_block=local_tree.latest_immutable_block().id, + # Provide the latest downloaded block as well + # to avoid downloading duplicate blocks + additional_blocks=[latest_downloaded.id] + if latest_downloaded is not None else [], + ) + ) + resp = send_request(peer, req) + + for block in resp.blocks(): + latest_downloaded = block + try: + # Run the chain maintenance defined in the Cryptarchia spec. + local_tree.on_block(block) + # Early stop if the target has been reached. + if block == req.target_block: + break + except: + return +``` + +If the node is continuing from a previous `DownloadBlocksRequest`, +it is important to include the latest downloaded block +to the `KnownBlocks.additional_blocks` to avoid downloading duplicate blocks. + +If the requesting node is downloading blocks up to the peer's tip $c_{loc}$ +(e.g. Initial Block Download) by repeating `DownloadBlocksRequest`s, +the $c_{loc}$ may switch between requests. +The algorithm described above also handles this case +by specifying the most recent peer's tip each time +when a `DownloadBlocksRequest` is constructed. + +### Bootstrapping from Checkpoint + +Instead of bootstrapping from the Genesis block or from the local block tree, +a node can choose to bootstrap the honest chain +starting from a checkpoint block obtained from a trusted checkpoint provider. +In this case, the node fully trusts the checkpoint provider +and considers blocks deeper than the checkpoint block as immutable +(including the checkpoint block itself). + +A trusted checkpoint provider exposes a HTTP endpoint, +allowing nodes to download the checkpoint block and the corresponding ledger state. +The details are defined in Checkpoint Provider HTTP API. + +The bootstrapping node imports the downloaded checkpoint block and ledger state +before starting bootstrapping. +The imported checkpoint block is used as the latest immutable block $B_{imm}$ +and the local chain tip $c_{loc}$. +Starting from the checkpoint block, +the same Initial Block Download is used to download blocks +up to the tip of the local chain of each peer. +As defined in Setting the Fork Choice Rule, +the Bootstrap fork choice rule MUST be used upon startup. + +If it turns out that none of the peers' local chains are connected +to the checkpoint block, +the node is terminated with an error, +allowing the node operator to select a new checkpoint. + +## Details + +### Offline Grace Period + +The offline grace period $T_\text{offline}$ is a period during which +a node can be restarted without switching to the Bootstrap rule. + +This protocol configures $T_\text{offline}$ to 20 minutes. +Here are the advantages and disadvantages of a short period: + +**Advantages:** + +- Limits chances for malicious peers to build long alternative chains + beyond the scope of the Online rule. +- Conservatively enables the Bootstrap rule to handle long forks. + +**Disadvantages:** + +- Even a short offline duration can too sensitively trigger the Bootstrap rule, + which then lasts for the long Prolonged Bootstrap Period. + +The following example explains why $T_\text{offline}$ should not be set too long: + +- A local node stopped in the following situation. + A malicious peer is building a fork which is now a little shorter ($k - d$) + than the honest chain. +- The local node has been offline shorter than $T_\text{offline}$ and just restarted. + As defined in this protocol, the Online fork choice rule is used + because the offline duration is short. +- During the offline duration, the malicious peer made its fork longer + by adding $k - d$ blocks. + Now the fork is in the same length as the honest chain. +- If the malicious peer sends the fork to the restarted node + faster than the honest peer, + the restarted node will commit to the fork because it has $k$ new blocks. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +## References + +### Normative + +- [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) + \- Key words for use in RFCs to Indicate Requirement Levels +- [Cryptarchia v1 Protocol Specification](https://nomos-tech.notion.site/Cryptarchia-v1-Protocol-Specification-21c261aa09df810cb85eff1c76e5798c) + \- Parent protocol specification +- [Cryptarchia Fork Choice Rule](https://nomos-tech.notion.site/Cryptarchia-Fork-Choice-Rule) + \- Fork choice rule specification + +### Informative + +- [Cryptarchia v1 Bootstrapping & Synchronization](https://nomos-tech.notion.site/Cryptarchia-v1-Bootstrapping-Synchronization-1fd261aa09df81ac94b5fb6a4eff32a6) + \- Original bootstrapping and synchronization documentation +- [Libp2p Streaming](https://docs.libp2p.io/) + \- Peer-to-peer networking library