Skip to content

chainparams: add assumeutxo snapshot at height 967,000 - #3

Open
mblowes wants to merge 1 commit into
ecash-com:betanetfrom
mbdrivechains:betanet-assumeutxo-967000
Open

mblowes wants to merge 1 commit into
ecash-com:betanetfrom
mbdrivechains:betanet-assumeutxo-967000

Conversation

@mblowes

@mblowes mblowes commented Sep 29, 2026 •

Copy link
Copy Markdown

Adds an assumeutxo entry at height 967,000, so a new node syncs from 967,000 instead of 935,000.

Why 967,000. It is below every eCash fork height in use: betanet forks at 967,680 and mainnet at 973,728. Up to that height, eCash's chain is Bitcoin's.

  • The UTXO set at 967,000 is Bitcoin's, and the same file serves betanet and mainnet. Only the 4 network-magic bytes in the file header differ (offset 7).
  • The snapshot base stays below the BIP300 activation height, so the enforcer does not wait for background validation (a base at or above activation does).

Effect. Measured on an 8-vCPU, 16 GB VPS (dbcache=8000), a fresh betanet node from nothing:

Step Time
Headers past 967,000 28 min
Load the 967,000 snapshot 15½ min
967,000 to betanet's tip (970,647, across the fork) 11 min
Total to the tip ~55 min

From the 935,000 snapshot the same node has 35,647 blocks to validate instead of 3,647. Mainnet's fork at 973,728 is 6,728 blocks above 967,000.

The entry (in CMainParams, the same list as the 935,000 entry):

{
    .height = 967'000,
    .hash_serialized = AssumeutxoHash{uint256{"a21b5fd649fb0eaca424bb191e43bbdbb804289f2594e44dbd5c2093bf07182b"}},
    .m_chain_tx_count = 1439155532,
    .blockhash = uint256{"00000000000000000000a6b2523780117f2257d82718a1f43d793d6a058fa294"},
},

How it was made (repeatable):

  1. eCash's CI betanet bitcoind (ca64033c13) started from the existing 935,000 snapshot and synced past 967,000.
  2. With the network off, bitcoin-cli -named dumptxoutset path=<file> rollback=967000 rewound to 967,000, dumped, and moved forward again. The values above are its output (165,199,284 coins). (-stopatheight alone overshoots: blocks already downloaded are connected while the node shuts down.)
  3. Block 967,000 has the same hash on betanet and on Bitcoin (00000000000000000000a6b2523780117f2257d82718a1f43d793d6a058fa294). So did block 967,679, the last block before betanet's fork.

How to check it without trusting us: on a Bitcoin Core node (v28 or later) that validated the chain from genesis, run bitcoin-cli -named dumptxoutset path=<file> rollback=967000. The node rewinds to 967,000 for the dump (network off), then returns to its tip. The txoutset_hash it reports must equal hash_serialized above, and nchaintx must equal m_chain_tx_count. (gettxoutsetinfo cannot report this hash for a past block, even with -coinstatsindex: that index only gives MuHash.) Any node that loads the file re-hashes the whole UTXO set against the compiled entry, so a tampered file cannot load.

Checked independently (2026-10-01): a separate machine ran the official Bitcoin Core 31.1 release (sha256 checked against SHA256SUMS, 11 good builder signatures) and validated Bitcoin mainnet from genesis, with no snapshot and the default assumevalid. With the network off, dumptxoutset rollback=967000 reported txoutset_hash a21b5fd649fb0eaca424bb191e43bbdbb804289f2594e44dbd5c2093bf07182b, nchaintx 1,439,155,532 and base 00000000000000000000a6b2523780117f2257d82718a1f43d793d6a058fa294, all equal to the entry. Block 967,000's hash and chain transaction count also match a fully validated Bitcoin Core 29.0 node.

Tested (2026-09-29): a fresh betanet node built from this branch, with an empty data directory:

  • loaded the 967,000 file (coins_loaded 165199284), checked against the compiled entry;
  • synced across betanet's fork to the tip (970,647); block 967,680 matched betanet's fork block (00000000000000030101ba5cfea54b22becc79f95dc6040beb76e01dd9d04042);
  • ran the enforcer (--network-preset=betanet) alongside: at the tip 4 minutes later;
  • ran a FreeBank node on top, which synced to the FreeBank seed's tip in 5 minutes.

One thing to know: until background validation of the old history finishes, -txindex covers only the background chainstate, so /rest/tx/<txid> answers 404 for transactions after the snapshot. Look-ups by block (/rest/block/<hash>) work.

The file: we host a betanet copy at https://pub-77f0535533b1480dacd9d5992d0c1831.r2.dev/utxo-967000-betanet.dat (sha256 da1e9b5de3fd21f5883e136184e6f24f5ec5348b7e3f36db3242b676666eed3b, 9,441,693,688 bytes). A mainnet copy is the same file with the header magic set to mainnet's, once mainnet's magic is published. We are happy to hand either file over for hosting wherever you prefer.

The change is one standalone commit. We are happy to rebase it onto whichever branch mainnet is cut from.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Gqbnw5hYV8j1ekU6P4GgYT

Below betanet's fork (967,680) and mainnet's (973,728), so the UTXO set is Bitcoin's and one
file serves both networks (only the 4 network-magic bytes in the header differ).
Values from dumptxoutset on this branch's parent (betanet ca64033) at height 967,000.
@mblowes

mblowes commented Oct 1, 2026

Copy link
Copy Markdown
Author

The UTXO set hash is now checked on a node validated from genesis (official Bitcoin Core 31.1, Bitcoin mainnet, no snapshot): it matches the entry. Details in the description under "Checked independently".

This branch has not been deployed

No deployments
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.

1 participant