|
| 1 | +# v9.26.4 Mainnet Prune Validation — Live Test Record |
| 2 | + |
| 3 | +Date: 2026-07-02 (UTC) · Binary: `DigiByte version v9.26.4 (release build)` from |
| 4 | +branch `release/v9.26.4` · Host: Jared's workstation, live mainnet P2P. |
| 5 | + |
| 6 | +## Purpose |
| 7 | + |
| 8 | +Prove on **real mainnet data** — not just regtest — that a v9.26.4 node with |
| 9 | +`prune=N` and **no txindex**: |
| 10 | + |
| 11 | +1. boots, registers the DigiDollar prune lock at the activation floor |
| 12 | + (23,627,520), and prunes the ~12-year pre-DigiDollar history; |
| 13 | +2. keeps validating and following the live chain while pruned; |
| 14 | +3. can never prune a DigiDollar-era block, even when explicitly asked to; |
| 15 | +4. reports correct DigiDollar deployment state pre-activation. |
| 16 | + |
| 17 | +Context: mainnet tip was ~23,774,300 during the test — already **past** the |
| 18 | +minimum activation height (23,627,520) while DigiDollar BIP9 is still |
| 19 | +signaling (`status: started`). So the retained DigiDollar-era window is live |
| 20 | +and real: the lock protects blocks that exist today. |
| 21 | + |
| 22 | +## Setup (repeatable) |
| 23 | + |
| 24 | +```bash |
| 25 | +# 1. Cleanly stop the primary node (Qt has no mainnet RPC in this config): |
| 26 | +kill -TERM <qt-pid> # wait for "Shutdown: done" in ~/.digibyte/debug.log |
| 27 | + |
| 28 | +# 2. Copy chain data to a disposable test datadir (~39 GB, a few minutes). |
| 29 | +# The untouched ~/.digibyte is the pristine backup — re-copy to reset the |
| 30 | +# test bed for reindex/rescan experiments at any time. |
| 31 | +mkdir -p ~/.digibyte-prunetest |
| 32 | +cp -a ~/.digibyte/blocks ~/.digibyte-prunetest/blocks |
| 33 | +cp -a ~/.digibyte/chainstate ~/.digibyte-prunetest/chainstate |
| 34 | +# deliberately NOT copied: indexes/ (txindex + DD stats index — the pruned |
| 35 | +# node must not need them) and wallets/ (test runs walletless). |
| 36 | + |
| 37 | +# 3. Test-node config (~/.digibyte-prunetest/digibyte.conf) — distinct ports |
| 38 | +# so it can coexist with the primary node: |
| 39 | +# prune=2000 |
| 40 | +# server=1 |
| 41 | +# rpcport=14022 |
| 42 | +# port=12124 |
| 43 | +# rpcbind=127.0.0.1 |
| 44 | +# rpcallowip=127.0.0.1 |
| 45 | +# dbcache=1024 |
| 46 | +# # no txindex line on purpose: prune must auto-disable the default txindex |
| 47 | + |
| 48 | +# 4. Launch the release Qt against it: |
| 49 | +DISPLAY=:1 src/qt/digibyte-qt -datadir=$HOME/.digibyte-prunetest -splash=0 |
| 50 | + |
| 51 | +# 5. Query it: |
| 52 | +src/digibyte-cli -datadir=$HOME/.digibyte-prunetest -rpcport=14022 <cmd> |
| 53 | +``` |
| 54 | + |
| 55 | +## Observed results |
| 56 | + |
| 57 | +### Startup (debug.log) |
| 58 | + |
| 59 | +``` |
| 60 | +DigiByte version v9.26.4 (release build) |
| 61 | +InitParameterInteraction: parameter interaction: -prune set -> setting -txindex=0 |
| 62 | +InitParameterInteraction: parameter interaction: -prune set -> setting -digidollarstatsindex=0 |
| 63 | +Prune configured to target 2000 MiB on disk for block and undo files. |
| 64 | +DigiDollar: pruning enabled; retaining all blocks at/above height 23627520 (DigiDollar activation floor) |
| 65 | +Oracle: DigiDollar not yet active (BIP9) at height 23774290, skipping price loading |
| 66 | +``` |
| 67 | + |
| 68 | +All four wiring points fired on mainnet: txindex softset off, DD stats index |
| 69 | +softset off, prune lock registered at the activation floor, and the |
| 70 | +BIP9-gated oracle startup skip. Startup includes one long single-core step |
| 71 | +(~8 minutes) after "Pruning blockstore…": the DigiDollar health seeding scan |
| 72 | +over the ~24M-entry mainnet UTXO set (present since v9.26.3; not |
| 73 | +prune-specific). |
| 74 | + |
| 75 | +### Pruned steady state |
| 76 | + |
| 77 | +| Check | Result | |
| 78 | +|---|---| |
| 79 | +| `getblockchaininfo.pruned` | `true` | |
| 80 | +| Disk (`size_on_disk`) after initial prune | **2.07 GB** (from 38 GB blocks + 4.2 GB indexes) | |
| 81 | +| First `pruneheight` | 21,195,663 — below the floor, because the 2000 MiB size target was satisfied before the lock had to bind | |
| 82 | +| Chain following | tip advanced live with the network while pruned (23,774,274 → 23,774,383+) | |
| 83 | +| `getnetworkinfo.localservicesnames` | `['WITNESS', 'NETWORK_LIMITED']` — no `NODE_NETWORK`, correct for a pruned node | |
| 84 | +| `getindexinfo` | `{}` — no txindex, nothing else | |
| 85 | +| `getdigidollardeploymentinfo` | `status: started`, bit 23, `min_activation_height: 23627520`, live signaling tally (4,130 of 28,224 threshold at test time), MuSig2 session telemetry present | |
| 86 | + |
| 87 | +### The DigiDollar prune lock, proven on mainnet |
| 88 | + |
| 89 | +``` |
| 90 | +$ digibyte-cli pruneblockchain 23774000 # deliberately above the floor |
| 91 | +23511221 # clamped — refused to cross the lock |
| 92 | +``` |
| 93 | + |
| 94 | +- Requested prune height 23,774,000 (near tip, far **above** the floor). |
| 95 | +- Actual prune stopped at **23,511,221** — the last whole block-file boundary |
| 96 | + below the lock (`floor − PRUNE_LOCK_BUFFER − 1` = 23,627,509; the block file |
| 97 | + containing the floor spans ~116k blocks and is retained whole). |
| 98 | +- Floor block 23,627,520: **still readable** (`getblock` succeeds). |
| 99 | +- Block 23,000,000 (below the floor): pruned, `getblock` errors cleanly. |
| 100 | +- Disk after the aggressive prune: **0.21 GB**. |
| 101 | + |
| 102 | +This is the release guarantee in one command: a pruned v9.26.4 node **cannot** |
| 103 | +be talked into deleting a DigiDollar-era block — automatic pruning and the |
| 104 | +`pruneblockchain` RPC both clamp below the activation floor. |
| 105 | + |
| 106 | +### getdigidollarstats on a pruned mainnet node |
| 107 | + |
| 108 | +Pre-activation it returns instantly with `DigiDollar is not yet active on |
| 109 | +this blockchain` — the standard activation gate at the top of every |
| 110 | +DigiDollar RPC. The no-index UTXO-scan fallback (and its "don't poll it |
| 111 | +tightly" caveat from the release notes) only comes into play after |
| 112 | +activation. |
| 113 | + |
| 114 | +### First-prune cost, and restart with m_have_pruned=true |
| 115 | + |
| 116 | +- The **first** prune of a 23.7M-block chain took ~8 minutes of one core |
| 117 | + between "Pruning blockstore…" and "Done loading": pruning ~21 million |
| 118 | + blocks marks each one's block-index entry as data-less and flushes that to |
| 119 | + LevelDB once. (The primary node's unpruned startups show no such gap, and |
| 120 | + neither does the pruned node afterward.) |
| 121 | +- **Restart after pruning**: total boot ~112 s (block-index load, same as an |
| 122 | + unpruned node), "Pruning blockstore… → Done loading" in the same second. |
| 123 | + The data-availability guard (`CheckBlockDataAvailability` from tip down to |
| 124 | + the floor, `m_have_pruned=true`) ran against the pruned datadir, found the |
| 125 | + DigiDollar-era window intact, and booted normally with the prune lock |
| 126 | + re-registered. (The refuse-to-start path for a *damaged* window is pinned |
| 127 | + by `feature_digidollar_pruning.py` F9 on regtest — it cannot be triggered |
| 128 | + with a v9.26.4 binary because the lock prevents creating the damage.) |
| 129 | + |
| 130 | +## Reset / reindex / rescan procedure |
| 131 | + |
| 132 | +- **Reset the test bed** (fresh un-pruned copy): stop test Qt, then |
| 133 | + `rm -rf ~/.digibyte-prunetest/{blocks,chainstate}` and re-copy from |
| 134 | + `~/.digibyte` (the pristine backup). ~3 minutes. |
| 135 | +- **Reindex test**: with the copy in place, start with `-reindex` to rebuild |
| 136 | + the chainstate from local block files. On a *pruned* copy, `-reindex` |
| 137 | + re-downloads missing history from the network and re-prunes (this is the |
| 138 | + recovery path the startup guard prescribes; exercised end-to-end in |
| 139 | + `feature_digidollar_pruning.py` F9 on regtest). |
| 140 | +- **Rescan test**: wallet rescans work within the retained window and fail |
| 141 | + cleanly with "Can't rescan beyond pruned data" below it (pinned in |
| 142 | + `feature_digidollar_pruning.py` F6). |
| 143 | +- The primary node's datadir `~/.digibyte` was never modified by this test. |
| 144 | + |
| 145 | +## Re-validation on the tagged binary (consensus fix included) |
| 146 | + |
| 147 | +Re-run on the recompiled `v9.26.4` tag (`c3c785443f`, which adds the redeem |
| 148 | +collateral floor gate) against a fresh 42 GB copy of `~/.digibyte` |
| 149 | +(`~/.dgb-mainprune`, `prune=2000`, no txindex): |
| 150 | + |
| 151 | +- **Boot:** both softsets fired; `DigiDollar: pruning enabled; retaining all |
| 152 | + blocks at/above height 23627520`; DigiDollar status `started` (mainnet not yet |
| 153 | + active); `pruned=true`; services `['WITNESS','NETWORK_LIMITED']`; `getindexinfo` |
| 154 | + empty. Initial prune to the 2000 MiB target: `size_on_disk` 1.77 GB. |
| 155 | +- **Clamp:** `pruneblockchain(23778861)` returned **23,511,221** (below the |
| 156 | + floor), floor block 23,627,520 remained readable, block 23,000,000 was gone |
| 157 | + (`error -1`), and `size_on_disk` fell to **209,887,284 bytes (0.21 GB)**. |
| 158 | +- **Restart:** the data-availability guard passed, `pruned=true`, the floor block |
| 159 | + was still available, and the node resumed syncing the live chain. |
| 160 | + |
| 161 | +Identical to the original run — the consensus change does not affect mainnet |
| 162 | +(DigiDollar is not active yet, so no redeem path runs) and does not change the |
| 163 | +prune/lock/guard mechanics. |
| 164 | + |
| 165 | +## Verdict |
| 166 | + |
| 167 | +Every mainnet observation — on both the pre-fix and the tagged binary — matched |
| 168 | +the regtest functional suite (`feature_digidollar_pruning.py`, 15 phases), the |
| 169 | +live testnet26 battery, and the code review. The pool config in the release |
| 170 | +notes (`prune=2000`, no txindex) runs today on mainnet, keeps the full |
| 171 | +DigiDollar-era window, and will carry a pool through DigiDollar activation |
| 172 | +without a further upgrade. |
0 commit comments