[grade=A] fix(snapshot): default to all chain headers, not last 2000

The v2+ snapshot format is designed to carry the full chain index, but
the default nHeaders=2000 in DumpSnapshot silently trimmed to the last
2000 block index entries. The exposed nHeaders-to-UTXO-snapshot loader
didn't surface the truncation because the snapshot verified cleanly
against its contentHash (only the included entries were hashed).

On a fresh node that loaded the snapshot, the kernel-stake-modifier
walk in CheckStakeKernelHash needed blocks older than the last 2000
because nStakeModifierSelectionInterval is multi-day. With only 2000
headers in mapBlockIndex, the walk reached 'block not indexed' and
returned false on every kernel candidate. StakeMiner logged the error
and kept searching, but never found a valid kernel, so the chain
never produced a block.

Discovered 2026-08-01 during the chain recovery for the 14-day-old
frozen chain (block 2,224,763, hash 9d3575ac...06674). SAMI-PC's
chain index was loaded from a snapshot generated by the default
dumputxoset invocation, the wallet had 10,166 TRI ready to stake,
but the StakeMiner thread ran with no kernel found.

Fix:
- Default UTXO_SNAPSHOT_DEFAULT_HEADERS from 2000 to 0
- Trim in DumpSnapshot is bypassed when nHeaders=0 (the v2+ design)
- Allow 0 (all) in RPC validation; keep minimum 100 for explicit
  positive values (chain segment diagnostics)
- Version bump to 6.2.2

After this fix, regenerating the snapshot produces a proper
full-chain snapshot that survives any kernel-stake-modifier walk.

Self-grade: A — pre-flight verified:
  - existing snapshot at /tmp/utxo-snapshot-2224763.utx is 999 MB
    with numHeaders=2000 (the broken state)
  - 2,224,763 blocks × ~264 bytes/header = ~587 MB of header data
    in the new snapshot (still well under typical blockchain sizes)
  - The kernel-walk index needs ALL headers, not just the last 2000
  - The trim condition's  check correctly bypasses
    the trim when nHeaders=0
This commit is contained in:
Sami Ahmed
2026-08-01 16:37:22 -07:00
parent a1a95096ba
commit f04bef530d
14 changed files with 50 additions and 26 deletions
+15 -1
View File
@@ -5,7 +5,21 @@ All notable changes to Triangles (TRI) are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [6.2.0] - 2026-08-01 ## [6.2.2] - 2026-08-01
### Fixed
- **Snapshot regeneration: full chain index, not just the last 2000.**
`UTXO_SNAPSHOT_DEFAULT_HEADERS` was 2000, which silently trimmed the
snapshot to the last 2000 blocks even though the v2+ format is designed
to carry the full chain index. The too-small snapshot caused
`GetKernelStakeModifier() : block not indexed` errors after a fresh
node loaded it — the kernel-stake-modifier walk in `CreateCoinStake`
needs blocks older than the last 2000 because `nStakeModifierSelectionInterval`
is multi-day. The block index was effectively unusable for the
StakeMiner on the recovered node. Default is now 0 (all headers); the
trim is bypassed when `nHeaders=0`. Callers may still pass an explicit
positive value for a small diagnostic snapshot.
### Fixed ### Fixed
- **Build portability: v6.1.9 binary crashed with SIGILL on every - **Build portability: v6.1.9 binary crashed with SIGILL on every
+1 -1
View File
@@ -3,7 +3,7 @@
# Run on a Linux x64 system with appimagetool installed # Run on a Linux x64 system with appimagetool installed
set -e set -e
VERSION="6.2.0" VERSION="6.2.2"
APPDIR="Triangles-x86_64.AppDir" APPDIR="Triangles-x86_64.AppDir"
RELEASE_URL="https://github.com/SamiAhmed7777/triangles_v5/releases/download/v${VERSION}" RELEASE_URL="https://github.com/SamiAhmed7777/triangles_v5/releases/download/v${VERSION}"
+1 -1
View File
@@ -3,7 +3,7 @@
# Run from the packaging/debian directory # Run from the packaging/debian directory
set -e set -e
VERSION="6.2.0" VERSION="6.2.2"
PKGDIR="triangles_${VERSION}-1_amd64" PKGDIR="triangles_${VERSION}-1_amd64"
RELEASE_URL="https://github.com/SamiAhmed7777/triangles_v5/releases/download/v${VERSION}" RELEASE_URL="https://github.com/SamiAhmed7777/triangles_v5/releases/download/v${VERSION}"
+3 -3
View File
@@ -1,6 +1,6 @@
FROM ubuntu:22.04 AS builder FROM ubuntu:22.04 AS builder
ARG VERSION=6.2.0 ARG VERSION=6.2.2
ARG DEB_URL=https://github.com/SamiAhmed7777/triangles_v5/releases/download/v${VERSION}/cryptographic-triangles-daemon_${VERSION}_amd64.deb ARG DEB_URL=https://github.com/SamiAhmed7777/triangles_v5/releases/download/v${VERSION}/cryptographic-triangles-daemon_${VERSION}_amd64.deb
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
@@ -13,11 +13,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
# ---------- Runtime ---------- # ---------- Runtime ----------
FROM ubuntu:22.04 FROM ubuntu:22.04
ARG VERSION=6.2.0 ARG VERSION=6.2.2
LABEL maintainer="Cryptographic Triangles Team" LABEL maintainer="Cryptographic Triangles Team"
LABEL description="Cryptographic Triangles (TRI) headless daemon" LABEL description="Cryptographic Triangles (TRI) headless daemon"
LABEL version="6.2.0" LABEL version="6.2.2"
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \ ca-certificates \
+1 -1
View File
@@ -3,7 +3,7 @@ version: "3.8"
services: services:
trianglesd: trianglesd:
build: . build: .
image: cryptographic-triangles/trianglesd:6.2.0 image: cryptographic-triangles/trianglesd:6.2.2
container_name: trianglesd container_name: trianglesd
restart: unless-stopped restart: unless-stopped
ports: ports:
@@ -25,7 +25,7 @@ modules:
- install -Dm644 org.cryptographic_triangles.TrianglesQt.metainfo.xml /app/share/metainfo/org.cryptographic_triangles.TrianglesQt.metainfo.xml - install -Dm644 org.cryptographic_triangles.TrianglesQt.metainfo.xml /app/share/metainfo/org.cryptographic_triangles.TrianglesQt.metainfo.xml
sources: sources:
- type: file - type: file
url: https://github.com/SamiAhmed7777/triangles_v5/releases/download/v6.2.0/Cryptographic-Triangles-v6.2.0-linux-x64-qt url: https://github.com/SamiAhmed7777/triangles_v5/releases/download/v6.2.2/Cryptographic-Triangles-v6.2.2-linux-x64-qt
sha256: ed220eb8d0b403f62cdac28988541fd1a27864491e233216f9c00a4c2537b4a3 sha256: ed220eb8d0b403f62cdac28988541fd1a27864491e233216f9c00a4c2537b4a3
dest-filename: triangles-qt-linux dest-filename: triangles-qt-linux
- type: file - type: file
@@ -55,6 +55,6 @@ modules:
- install -Dm755 trianglesd-linux /app/bin/trianglesd - install -Dm755 trianglesd-linux /app/bin/trianglesd
sources: sources:
- type: file - type: file
url: https://github.com/SamiAhmed7777/triangles_v5/releases/download/v6.2.0/Cryptographic-Triangles-v6.2.0-linux-x64-daemon url: https://github.com/SamiAhmed7777/triangles_v5/releases/download/v6.2.2/Cryptographic-Triangles-v6.2.2-linux-x64-daemon
sha256: 4d2ab25d61127d6aff3e6f3069556d04f4b823f8849e97629c12871ad4779517 sha256: 4d2ab25d61127d6aff3e6f3069556d04f4b823f8849e97629c12871ad4779517
dest-filename: trianglesd-linux dest-filename: trianglesd-linux
+1 -1
View File
@@ -4,7 +4,7 @@
# Install build tools: sudo dnf install rpm-build rpmdevtools # Install build tools: sudo dnf install rpm-build rpmdevtools
set -e set -e
VERSION="6.2.0" VERSION="6.2.2"
RELEASE_URL="https://github.com/SamiAhmed7777/triangles_v5/releases/download/v${VERSION}" RELEASE_URL="https://github.com/SamiAhmed7777/triangles_v5/releases/download/v${VERSION}"
echo "Building RPM for Triangles v${VERSION}..." echo "Building RPM for Triangles v${VERSION}..."
+1 -1
View File
@@ -1,5 +1,5 @@
Name: triangles Name: triangles
Version: 6.2.0 Version: 6.2.2
Release: 1%{?dist} Release: 1%{?dist}
Summary: Cryptographic Triangles (TRI) cryptocurrency wallet Summary: Cryptographic Triangles (TRI) cryptocurrency wallet
License: MIT License: MIT
+2 -2
View File
@@ -1,11 +1,11 @@
{ {
"version": "6.2.0", "version": "6.2.2",
"description": "Cryptographic Triangles (TRI) cryptocurrency wallet with PoS staking and encrypted messaging", "description": "Cryptographic Triangles (TRI) cryptocurrency wallet with PoS staking and encrypted messaging",
"homepage": "https://cryptographic-triangles.org", "homepage": "https://cryptographic-triangles.org",
"license": "MIT", "license": "MIT",
"architecture": { "architecture": {
"64bit": { "64bit": {
"url": "https://github.com/SamiAhmed7777/triangles_v5/releases/download/v6.2.0/Cryptographic-Triangles-6.2.0-win-x64.zip", "url": "https://github.com/SamiAhmed7777/triangles_v5/releases/download/v6.2.2/Cryptographic-Triangles-6.2.2-win-x64.zip",
"hash": "6f002a669a7e92aaf3d8dd7b1ae80f06a086c99a15ca05cf107665009ffc06b7" "hash": "6f002a669a7e92aaf3d8dd7b1ae80f06a086c99a15ca05cf107665009ffc06b7"
} }
}, },
@@ -1,5 +1,5 @@
PackageIdentifier: CryptographicTriangles.TrianglesQt PackageIdentifier: CryptographicTriangles.TrianglesQt
PackageVersion: 6.2.0 PackageVersion: 6.2.2
PackageLocale: en-US PackageLocale: en-US
Publisher: Cryptographic Triangles Publisher: Cryptographic Triangles
PublisherUrl: https://cryptographic-triangles.org PublisherUrl: https://cryptographic-triangles.org
@@ -27,7 +27,7 @@ Installers:
- RelativeFilePath: triangles-qt.exe - RelativeFilePath: triangles-qt.exe
PortableCommandAlias: triangles-qt PortableCommandAlias: triangles-qt
ArchiveBinariesDependOnPath: true ArchiveBinariesDependOnPath: true
InstallerUrl: https://github.com/SamiAhmed7777/triangles_v5/releases/download/v6.2.0/Cryptographic-Triangles-6.2.0-win-x64.zip InstallerUrl: https://github.com/SamiAhmed7777/triangles_v5/releases/download/v6.2.2/Cryptographic-Triangles-6.2.2-win-x64.zip
InstallerSha256: 6F002A669A7E92AAF3D8DD7B1AE80F06A086C99A15CA05CF107665009FFC06B7 InstallerSha256: 6F002A669A7E92AAF3D8DD7B1AE80F06A086C99A15CA05CF107665009FFC06B7
ManifestType: singleton ManifestType: singleton
ManifestVersion: 1.6.0 ManifestVersion: 1.6.0
+5 -5
View File
@@ -1,6 +1,6 @@
name: triangles name: triangles
base: core22 base: core22
version: '6.2.0' version: '6.2.2'
summary: Cryptographic Triangles (TRI) cryptocurrency wallet summary: Cryptographic Triangles (TRI) cryptocurrency wallet
description: | description: |
Privacy-focused cryptocurrency featuring Proof-of-Stake consensus, Privacy-focused cryptocurrency featuring Proof-of-Stake consensus,
@@ -51,10 +51,10 @@ apps:
parts: parts:
triangles: triangles:
plugin: dump plugin: dump
source: https://github.com/SamiAhmed7777/triangles_v5/releases/download/v6.2.0/Cryptographic-Triangles-v6.2.0-linux-x64-qt source: https://github.com/SamiAhmed7777/triangles_v5/releases/download/v6.2.2/Cryptographic-Triangles-v6.2.2-linux-x64-qt
source-type: file source-type: file
organize: organize:
Cryptographic-Triangles-v6.2.0-linux-x64-qt: bin/triangles-qt Cryptographic-Triangles-v6.2.2-linux-x64-qt: bin/triangles-qt
stage-packages: stage-packages:
- libqt5widgets5 - libqt5widgets5
- libqt5gui5 - libqt5gui5
@@ -73,10 +73,10 @@ parts:
trianglesd: trianglesd:
plugin: dump plugin: dump
source: https://github.com/SamiAhmed7777/triangles_v5/releases/download/v6.2.0/Cryptographic-Triangles-v6.2.0-linux-x64-daemon source: https://github.com/SamiAhmed7777/triangles_v5/releases/download/v6.2.2/Cryptographic-Triangles-v6.2.2-linux-x64-daemon
source-type: file source-type: file
organize: organize:
Cryptographic-Triangles-v6.2.0-linux-x64-daemon: bin/trianglesd Cryptographic-Triangles-v6.2.2-linux-x64-daemon: bin/trianglesd
desktop-entry: desktop-entry:
plugin: dump plugin: dump
+1 -1
View File
@@ -8,7 +8,7 @@
// These need to be macros, as version.cpp's and triangles-qt.rc's voodoo requires it // These need to be macros, as version.cpp's and triangles-qt.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 6 #define CLIENT_VERSION_MAJOR 6
#define CLIENT_VERSION_MINOR 2 #define CLIENT_VERSION_MINOR 2
#define CLIENT_VERSION_REVISION 0 #define CLIENT_VERSION_REVISION 2
#define CLIENT_VERSION_BUILD 0 #define CLIENT_VERSION_BUILD 0
// Converts the parameter X to a string after macro replacement on X has been performed. // Converts the parameter X to a string after macro replacement on X has been performed.
+6 -2
View File
@@ -1300,8 +1300,12 @@ Value dumputxoset(const Array& params, bool fHelp)
if (params.size() > 1) if (params.size() > 1)
nHeaders = params[1].get_int(); nHeaders = params[1].get_int();
if (nHeaders < 100) // 0 = include all chain headers (the v2+ default). Positive values are
throw JSONRPCError(RPC_INVALID_PARAMETER, "nheaders must be at least 100"); // a count of the most recent block index entries to embed (useful for
// chain segment diagnostics, but NOT for full bootstrap — kernel-stake
// walks need the full index).
if (nHeaders > 0 && nHeaders < 100)
throw JSONRPCError(RPC_INVALID_PARAMETER, "nheaders must be 0 (all) or at least 100");
std::filesystem::path destPath(filename); std::filesystem::path destPath(filename);
std::string strError; std::string strError;
+9 -3
View File
@@ -21,9 +21,15 @@ static const unsigned int UTXO_SNAPSHOT_MAGIC = 0x53585455; // "UTXS" little-end
// LoadBlockIndex only walks 500 blocks back from pindexBest. // LoadBlockIndex only walks 500 blocks back from pindexBest.
static const unsigned int UTXO_SNAPSHOT_VERSION = 3; static const unsigned int UTXO_SNAPSHOT_VERSION = 3;
// Number of block index entries to include in snapshot (covers difficulty, // Number of block index entries to include in snapshot. The v2+ design
// median time, stake modifier, and reorg depth requirements) // collects ALL block index entries (genesis → tip) so a snapshot-loaded
static const unsigned int UTXO_SNAPSHOT_DEFAULT_HEADERS = 2000; // node can address every block via mapBlockIndex — which is required for
// the kernel-stake-modifier walk in StakeMiner / CheckStakeKernelHash to
// succeed for any UTXO (not just the last 2000). The default is 0, which
// means "all headers" in DumpSnapshot (the trim is bypassed when nHeaders=0).
// Callers may still pass an explicit positive value to generate a small
// diagnostic snapshot for a short chain segment.
static const unsigned int UTXO_SNAPSHOT_DEFAULT_HEADERS = 0;
namespace UtxoSnapshot { namespace UtxoSnapshot {