— DigiSwarm, DGB AI dev team · PR: release/v9.26.4 → develop
What you get: you can now run a full-validating DigiByte node — including everything DigiDollar will need — on about 2 GB of disk instead of ~42 GB.
How: add one line to digibyte.conf:
prune=2000
Who should care: mining pools and anyone who found the v9.26.3 disk/RAM footprint too heavy. Pools upgrade once — this node works today, and carries straight through DigiDollar activation with no further upgrade.
What changes if you don't set prune=: nothing. Your node behaves exactly
like v9.26.3.
What we changed in consensus: one narrowly scoped rule. Redemption collateral classification is now gated on the DigiDollar activation floor (a pre-floor coin can never be vault collateral), which is what makes a pruned node accept and reject exactly the same blocks as a full node. The pre-release mainnet scan found no existing coins the rule affects. The Groestl algolock and the DigiDollar activation schedule are untouched.
Since v9.26.3, a DigiDollar node required txindex=1 (a full transaction index)
plus all ~12 years of block history. That's ~38 GB of blocks + ~4 GB of index,
growing forever — and it made -prune impossible, because prune and txindex are
mutually exclusive. Pools asked for something lighter. This release delivers it
without touching consensus.
DigiDollar coins can only be created after DigiDollar activates, and activation cannot happen before block 23,627,520 on mainnet. So any block DigiDollar validation will ever need to look at sits between that height and the tip of the chain. Everything below that height is plain DGB history that DigiDollar never needs — which means it is safe to delete, forever.
Three small pieces of wiring, all opt-in behind -prune:
-
A prune lock at the activation floor. At startup the node registers a "digidollar" prune lock at height 23,627,520, using the same battle-tested Bitcoin Core mechanism that indexes use. Every prune operation — the automatic size-target pruning and the manual
pruneblockchainRPC — is clamped below that height. A pruned node physically cannot delete a DigiDollar-era block, even if you ask it to. (src/node/chainstate.cpp~line 156) -
DigiDollar no longer needs txindex under prune. When validation needs the details of a spent DigiDollar output (its amount and lock term), it reads the creating transaction directly out of the retained block at the coin's height, instead of asking the transaction index. Every lookup path fails closed: if data can't be found, the transaction/block is rejected — the node never accepts something it couldn't verify. (
src/init.cpp~914,src/digidollar/health.cppScanUTXOSet) -
A startup safety guard. If a pruned data directory is somehow missing a DigiDollar-era block (e.g. it was pruned by different software under different rules), the node refuses to start and asks for
-reindex— it will never run DigiDollar validation on incomplete data. (src/node/chainstate.cpp~line 184)
Side effects handled: the DigiDollar stats index (which syncs from genesis) is
auto-disabled under prune, and getdigidollarstats falls back to a live UTXO
scan that reports the same totals and position count; pruned nodes advertise
NODE_NETWORK_LIMITED like any pruned Bitcoin-lineage node.
- Consensus, except the redeem collateral floor gate. Mint/transfer rules, oracle bundle rules, lock tiers — all byte-identical. The one change is in redemption collateral classification (the activation-floor gate above).
- The Groestl algolock — untouched, and its boundary tests still pass (accept at the boundary, reject after, reindex-safe).
- DigiDollar activation (BIP9 bit 23) — untouched; all activation tests pass.
- Default node behavior — without
prune=, txindex still defaults ON and the node is exactly v9.26.3. Settingprune=together with an explicittxindex=1still errors, as before.
Upgrading an existing v9.26.3 node (the pool path):
-
Stop the node.
-
In
digibyte.conf: addprune=2000, and remove anytxindex=1line (with no txindex line present, v9.26.4 turns it off automatically under prune). -
Swap in the v9.26.4 binaries and start. The node prunes in place — no resync, no reindex. The first start takes a few extra minutes (one-time) while old blocks are marked pruned. Confirm in
debug.log:DigiDollar: pruning enabled; retaining all blocks at/above height 23627520 (DigiDollar activation floor)
Fresh node: same config; it syncs and prunes as it goes.
Notes: prune=N is a disk target in MiB (minimum 550; 2000 gives headroom).
prune=1 = manual mode (prune only via the pruneblockchain RPC). Wallets and
getblocktemplate mining work normally. To return to an archival node later:
remove prune=, set txindex=1, restart with -reindex.
- Unit tests: 3,404 cases green, including the new
dd_chain_prune_does_not_require_txindex. - Full functional suite: 380 tests green via
test_runner.py --jobs=8, including all Groestl algolock and DigiDollar activation tests. The extended pruning suite (feature_pruning.py,feature_index_prune.py,wallet_pruning.py) was run green as well — which surfaced and fixed a latent v9.26.3 issue where-prune=-1reported the wrong startup error. - New 14-phase functional test (
test/functional/feature_digidollar_pruning.py), written test-first (TDD). It proves, on real nodes:- a pruned node (no txindex) boots, crosses BIP9 DigiDollar activation, and mines a DigiDollar block that a full node accepts;
- a full mint → send (self and cross-node) → redeem lifecycle on the pruned node;
- pruning deletes pre-activation history while the DD-era window survives, and the prune lock is the binding constraint (prune-to-tip gets clamped);
- a fresh pruned node cold-syncs the entire DD-era chain over P2P and reaches identical DigiDollar state;
- a full node migrates in place to pruned (the exact pool upgrade path, automatic prune mode) and stays in parity;
- reorgs across DigiDollar blocks on the pruned node reconcile exactly;
- an offline pruned miner that mined its own stale chain (with a DD mint on it!) while the network advanced past the 288-block window abandons the stale chain on reconnect and returns to exact parity;
- a pruned datadir cannot silently become a full node again (dropping
-prunerequires-reindex); - a deliberately damaged datadir triggers the startup guard, and the guard's
prescribed
-reindexrecovery restores full parity; - a truncated/partially-restored DD-era block file (which passes the
index-flag guard) is caught by the fail-closed startup reconstruction and
refuses to start — then recovers with
-reindex.
- Live mainnet validation (full record:
V9.26.4_MAINNET_VALIDATION.md): we ran the release Qt binary against a copy of a synced mainnet datadir withprune=2000and no txindex, on the live network:- the prune lock registered at 23,627,520 while DigiDollar is still signaling (mainnet tip is already past the floor, so the retained window is live today);
- disk fell 38 GB → 2.1 GB; a deliberate
pruneblockchainabove the floor was clamped to 23,511,221 and the floor block stayed readable — final footprint 0.21 GB; - the node kept validating live mainnet blocks while pruned, and a restart passed the data-availability guard and booted normally in ~2 minutes.
Three independent deep audits ran against this branch: pruned-miner operational edge cases, guard-bypass attempts, and fuzz-surface review. Headline results:
- No wrong-chain path exists. In every traced scenario where a pruned node
lacks data (deep reorg beyond retained blocks, damaged files, unreadable
history) it halts loudly — FatalError, startup refusal, or clean RPC
errors — with
-reindexas the recovery. There is no code path where missing pruned data causes it to accept or follow an invalid or lower-work chain. - Reorg capacity: before the tip reaches the activation floor, a pruned node can disconnect up to 288 blocks (~72 min) like any Bitcoin-lineage pruned node; once the tip passes the floor (mainnet: already true) capacity becomes the whole retained window — ~147,000 blocks (~25 days) today, and growing. Deeper-than-retained reorgs halt the node; they cannot mislead it.
- Guard-bypass attempts all blocked:
-txindex=1+prune,-reindex-chainstate+prune, dropping-pruneon a pruned datadir, conf-section mistakes, regtest knobs on mainnet (impossible — regtest-only args), assumeutxo ordering, and thepruneblockchainRPC racing the lock registration. - Two real gaps found and FIXED in this branch:
- A truncated or partially-restored DD-era block file passes the startup
guard (it checks index flags; whole-file deletion is already caught at
index load) and previously let the startup health/price reconstruction
continue silently with partial data — consensus-relevant DCA/volatility
state could diverge. Now
LoadPricesFromChainand the health seed fail closed: the node refuses to start with the "block data is incomplete… restart with -reindex" guidance, pinned by test phase F14 (written RED-first against the old binary, GREEN after the fix). - The final consensus audit found that
ValidateCollateralReleaseAmountclassified a redeem's collateral input (and positive-value fee inputs) via a block lookup with no activation-floor gate — unlike its siblingSpendsDigiDollarCollateralVault. Because that lookup reads a block a pruned node may have pruned (pre-floor), a full node could flag a deliberately pre-planted, DD-mint-shaped pre-floor coin as collateral while a pruned node could not → an attacker-crafted pruned-vs-full split on a redeem. Fixed: a coin below the activation floor can never be real collateral, so both sites now reject/ignore pre-floor coins before the lookup, on every node. Only pre-floor coins are affected; no legitimate redeem changes. Pinned by unit testredteam_t2_06d(asserts a pruned node's failing lookup reaches the identical verdict).
- A truncated or partially-restored DD-era block file passes the startup
guard (it checks index flags; whole-file deletion is already caught at
index load) and previously let the startup health/price reconstruction
continue silently with partial data — consensus-relevant DCA/volatility
state could diverge. Now
- Cross-version compatibility: a pruned v9.26.4 node speaks the same
protocol as v9.26.3/v9.26.2/v8.22 peers;
NODE_NETWORK_LIMITED(service bit 1024) predates both lineages, deep block requests are refused-and-disconnected (never banned), and the Groestl algolock is enforced from headers/heights only — pruning cannot affect it.
Operational guidance for pools (from the audit):
- After a multi-hour outage, restart the node before resuming mining; a
restart correctly holds
getblocktemplateuntil the node is back in sync (a node that stayed up through an outage can briefly serve stale templates — an upstream Bitcoin Core behavior, orphan-risk only, never consensus). -reindexon a pruned node redownloads from the network — it needs connectivity. Keep one archival node (or a datadir snapshot) in your fleet.- Watch
getblockchaininfo:headers == blocksis the cheap "safe to mine" check.
# Build
./autogen.sh && ./configure && make -j$(nproc)
# Unit tests (all, then the targeted suite)
./src/test/test_digibyte
./src/test/test_digibyte --run_test=digidollar_txindex_tests
# The headline functional test (14 phases, ~2 min)
test/functional/feature_digidollar_pruning.py
# Full functional suite
test/functional/test_runner.py --jobs=8
# Optional live mainnet spot-check (non-destructive — uses a COPY):
# 1. stop your node; copy ~/.digibyte/{blocks,chainstate} to a test datadir
# 2. test datadir digibyte.conf: prune=2000 / server=1 / rpcport=14022 / port=12124
# 3. start digibyted/Qt with -datadir=<test dir>, then:
# - debug.log must show the "retaining all blocks at/above height 23627520" line
# - getblockchaininfo -> pruned:true
# - pruneblockchain <tip-height> -> returns a height BELOW 23627520 (the clamp)
# - getblock $(getblockhash 23627520) -> still works
# 4. your real datadir is untouched; delete the copy when doneWhy testnet matters: DigiDollar is already ACTIVE on testnet26 (activated at height 599/600). That makes it the only live, multi-node network where a pruned node operates in the exact situation mainnet will be in after activation — real DD positions in the UTXO set, real oracle data — which regtest can only simulate.
Config gotcha (important): testnet options go under the [test] section of
digibyte.conf. If your existing [test] section contains txindex=1 (it
often does — it was required before v9.26.4), you must remove it before
adding prune=550, or the node will refuse to start with "Prune mode is
incompatible with -txindex."
What we ran (2026-07-02, live testnet26): a pruned v9.26.4 node
(prune=550, no txindex, no indexes) from a copied testnet26 datadir, alongside
a full v9.26.4 node (txindex + stats index) — separate ports, same live network:
- The pruned node logged
DigiDollar: pruning enabled; retaining all blocks at/above height 600, synced to the live tip with 6 peers, and reportedstatus: activefor the deployment. Being ~3 weeks behind at start, this also exercised the offline-node catch-up on a chain where DigiDollar is live. getdigidollarstatson the pruned node (UTXO-scan fallback, no index, 47 ms) returned the real network state — $4,720.77 DD supply, 18 active positions, 6.63M DGB collateral, 337% health, oracle price available — and resolving each vault's exact amount used the block-db read path on real testnet blocks.- Full-vs-pruned parity, live: identical tips (66,983) and identical
total_dd_supply/total_collateral_dgb/active_positions/health_percentagebetween the pruned node's scan and the full node's stats index. New network blocks arriving during the test were validated by both. - Floor block 600 readable on the pruned node;
NODE_NETWORK_LIMITEDadvertised;getindexinfoempty.
Remaining testnet steps (need a funded testnet wallet / miner):
- Mint, send, and redeem DigiDollar from the pruned node's wallet; confirm the full node accepts every block and stats stay in parity. (Regtest phases F4/lifecycle cover this logic; testnet re-checks it against the real oracle roster.)
- Mine testnet blocks with the pruned node's
getblocktemplate(needs the team's miner rig pointed at the pruned node). - Restart the pruned node after those operations; confirm the guard passes and stats still match.
| Document | Content |
|---|---|
V9.26.4_PRUNING_PLAN.md |
Design + full TDD test plan |
V9.26.4_PRUNING_EXPLAINER.md |
Short shareable community explainer |
V9.26.4_MAINNET_VALIDATION.md |
The live mainnet test record |
doc/release-notes/release-notes-9.26.4.md |
Operator-facing release notes & limitations |
Fine print: pruned nodes don't serve deep history to new peers (archival nodes
still do that); getrawtransaction for pre-DigiDollar history needs an archival
node; and after activation the retained DigiDollar-era window grows with the
chain — prune=N deletes the 12 years of history, it isn't a permanent size cap.