docs: add guide for running dev chain from existing data#5125
Conversation
There was a problem hiding this comment.
Pull request overview
Adds documentation for running a local dev chain using an existing mainnet/testnet data directory, with guidance intended to avoid GenesisMismatch by importing the original chain spec and running with spec-check override flags.
Changes:
- Add a new step-by-step guide:
docs/devnet-from-existing-data.md. - Document importing a source chain spec into
specs/dev.tomland adjusting PoW settings for local use. - Document first-run flags to reconcile stored vs configured chain spec hashes.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Download the source chain spec file that matches your copied data: | ||
|
|
||
| - Mainnet: https://github.com/nervosnetwork/ckb/blob/develop/resource/specs/mainnet.toml | ||
| - Testnet: https://github.com/nervosnetwork/ckb/blob/develop/resource/specs/testnet.toml | ||
|
|
||
| For example: | ||
|
|
||
| ```shell | ||
| curl -L -o mainnet.toml \ | ||
| https://raw.githubusercontent.com/nervosnetwork/ckb/develop/resource/specs/mainnet.toml |
There was a problem hiding this comment.
The guide says to download a chain spec that “matches your copied data”, but the links/curl example fetch from the develop branch. If the copied data was produced by a released CKB version, develop’s spec may differ and can reintroduce GenesisMismatch/consensus mismatches. Recommend instructing users to fetch the spec from the exact CKB release tag/commit that generated the data (or otherwise pin the URL to a known tag) rather than develop.
| Download the source chain spec file that matches your copied data: | |
| - Mainnet: https://github.com/nervosnetwork/ckb/blob/develop/resource/specs/mainnet.toml | |
| - Testnet: https://github.com/nervosnetwork/ckb/blob/develop/resource/specs/testnet.toml | |
| For example: | |
| ```shell | |
| curl -L -o mainnet.toml \ | |
| https://raw.githubusercontent.com/nervosnetwork/ckb/develop/resource/specs/mainnet.toml | |
| Download the source chain spec file **from the exact CKB version tag or commit that | |
| produced your copied data directory** (for example, the version of the node that | |
| originally used this data directory). | |
| Replace `<CKB_TAG>` below with that version tag/commit: | |
| - Mainnet: https://github.com/nervosnetwork/ckb/blob/<CKB_TAG>/resource/specs/mainnet.toml | |
| - Testnet: https://github.com/nervosnetwork/ckb/blob/<CKB_TAG>/resource/specs/testnet.toml | |
| For example: | |
| ```shell | |
| # Example: if your original node ran v0.114.0, use <CKB_TAG>=v0.114.0 | |
| curl -L -o mainnet.toml \ | |
| https://raw.githubusercontent.com/nervosnetwork/ckb/<CKB_TAG>/resource/specs/mainnet.toml |
| ## 4. Update `specs/dev.toml` | ||
|
|
||
| Set `Dummy` PoW for local development and keep `genesis_epoch_length` unchanged: | ||
|
|
||
| ```toml | ||
| [params] | ||
| genesis_epoch_length = 1743 | ||
| initial_primary_epoch_reward = 1_917_808_21917808 | ||
| secondary_epoch_reward = 613_698_63013698 | ||
| max_block_cycles = 10_000_000_000 | ||
| cellbase_maturity = 0 | ||
| primary_epoch_reward_halving_interval = 8760 | ||
| epoch_duration_target = 14400 | ||
| permanent_difficulty_in_dummy = true | ||
|
|
There was a problem hiding this comment.
Step 4 hard-codes genesis_epoch_length = 1743 while also saying to keep it “unchanged”. This value matches the bundled mainnet spec (resource/specs/mainnet.toml), but the bundled testnet spec does not set genesis_epoch_length (so it falls back to the default), meaning 1743 is likely incorrect when using testnet data and can make existing blocks invalid. Suggest updating the instructions to keep the imported spec’s genesis_epoch_length (whatever it is for that chain/version) and avoid hard-coding mainnet-specific values here (or explicitly provide separate mainnet vs testnet values).
| ## 5. First Run Requires Spec-Check Flags | ||
|
|
||
| The copied database still records the original chain spec hash, so first startup | ||
| must include: | ||
|
|
||
| ```shell | ||
| ckb run --skip-spec-check --overwrite-spec | ||
| ``` |
There was a problem hiding this comment.
The doc says the first run “must include” --skip-spec-check --overwrite-spec, but --overwrite-spec alone is sufficient to bypass the mismatch and update the stored chain spec hash (the launcher checks overwrite-spec before skip-spec-check). Consider changing wording to recommend --overwrite-spec (optionally mentioning what --skip-spec-check does), to avoid implying both are required or encouraging use of --skip-spec-check without overwriting.
## What Address [this Copilot review comment on #5125](#5125 (comment)) about the testnet path of `docs/devnet-from-existing-data.md`. ## Why Following the original step 4 verbatim against a testnet datadir fails at startup with: ``` chainspec error: ChainSpec: genesis hash mismatch, expected: 0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606 actual: 0xeaf926b9... ``` Root cause: the original guide hard-codes `genesis_epoch_length = 1743`, which is mainnet's launch value. The bundled `resource/specs/testnet.toml` has no `[params]` section, so testnet was launched with the default `genesis_epoch_length = 1000`. `genesis_epoch_length` participates in the genesis cellbase reward calculation and therefore changes the genesis block hash; setting it to `1743` for testnet produces a different genesis hash and the node refuses to start. ## What changed `docs/devnet-from-existing-data.md`: - Split step 4 into separate **Mainnet** and **Testnet** variants of the `[params]` block. - Mainnet variant keeps `genesis_epoch_length = 1743`. - Testnet variant omits `genesis_epoch_length` so it falls back to the consensus default `1000`. - Add a callout explaining why this field matters (genesis hash). - Drop the unrelated reward / cycle / epoch fields that were already equal to the consensus defaults in [`spec/src/consensus.rs`](../blob/develop/spec/src/consensus.rs). - Keep `cellbase_maturity = 0` and `permanent_difficulty_in_dummy = true` and add brief explanations for both (they are intentional non-default overrides for local Dummy-PoW development). ## How verified Locally with `ckb v0.206.0 (2c91814 2026-05-06)` on macOS (aarch64), against a freshly synced datadir for each chain (using `cp -R` per step 1): | | mainnet | testnet | |---|---|---| | `ckb init --chain dev --import-spec` | Genesis Hash `0x92b197aa…450d0e5` ✅ | Genesis Hash `0x10639e08…0aae3f9606` ✅ | | `ckb run --skip-spec-check --overwrite-spec` | recognized tip 5504, no `GenesisMismatch`, syncing ✅ | recognized tip 31647, no `GenesisMismatch`, syncing ✅ | Also confirmed that the original (pre-PR) doc reproduces the testnet failure.
What problem does this PR solve?
Problem Summary:
Document how to run
devchain using existing mainnet/testnet data and avoidGenesisMismatch.What is changed and how it works?
What's Changed:
docs/devnet-from-existing-data.md.Related changes
Check List
Tests
Side effects