Skip to content

nmc(P1b): wire AuxPow::check_proof chain-merkle leg (step 1) + KATs - #180

Merged
frstrtr merged 2 commits into
masterfrom
nmc/p1b-check-proof-chain-leg
Jun 19, 2026
Merged

nmc(P1b): wire AuxPow::check_proof chain-merkle leg (step 1) + KATs#180
frstrtr merged 2 commits into
masterfrom
nmc/p1b-check-proof-chain-leg

Conversation

@frstrtr

@frstrtr frstrtr commented Jun 19, 2026

Copy link
Copy Markdown
Owner

P1b — AuxPow::check_proof chain-merkle leg (step 1)

Builds on P1a (PR #178, aux_merkle_root primitive). Wires step 1 of the 4-step AuxPow verification: reconstruct the merged-mining merkle root from the aux (NMC) block hash through chain_merkle_branch/chain_merkle_index via aux_merkle_root().

Safety

New CheckResult::INCOMPLETE state. A structurally-consistent chain-merkle walk returns INCOMPLETE, never VALID — steps 2 (MM-marker commitment + chain_id/slot binding), 3 (parent-coinbase tx-merkle leg, needs witness-stripped BTC coinbase txid), 4 (parent PoW vs target) are NOT built. NMC still MUST NOT block-validate off this leaf. Malformed slot indices (negative / wider than branch depth) return INVALID.

Tests

4 new KATs (NmcAuxCheckProof) pin the INCOMPLETE-vs-INVALID boundary. 9/9 PASS (5 P1a + 4 P1b), build green. Test target name unchanged → CI --target allowlist needs no edit. nmc_coin linked (AuxPow ctor pulls MutableTransaction).

Fence

NMC-local only; btc tree consumed READ-ONLY. Merge gated (I do not self-merge).

Next (P1c)

step 3 parent-coinbase tx-merkle leg — requires pinning the witness-stripped BTC coinbase txid serialization params (separate slice + KAT).

frstrtr added 2 commits June 19, 2026 00:11
Lands aux_merkle_root() in nmc::coin (header_chain.hpp): the merge-mining
merkle-branch walk that AuxPow::check_proof() will consume for step-1
(chain-merkle-root, aux block hash -> merged-mining root) and step-3
(parent tx-merkle-root, coinbase txid -> parent block merkle root).

Byte-faithful port of legacy libcoind/data.cpp check_merkle_link() -- the
same SSOT btc/ltc use -- kept NMC-LOCAL per coin fence #4 (only core/*
Hash + PackStream; no btc/ltc include). Per-level index bit selects LEFT vs
RIGHT sibling, folded with SHA256d of the 64-byte concatenation; an index
that does not fit branch.size() bits is rejected.

check_proof() stays a P-DEFER stub: marker-scan, parent tx-merkle recompute
and parent PoW are the next sub-slice, so NMC still MUST NOT block-validate
off this leaf.

Test: nmc_auxpow_merkle_test (gtest) pins the walk with INDEPENDENTLY
derived expected roots (empty-branch identity, left/right sibling order,
two-step per-level fold, index-overflow guard). Registered in both
test/CMakeLists.txt and the build.yml --target allowlist. 5/5 PASS, exit 0.
check_proof() reconstructs the merged-mining merkle root from the aux
block hash through chain_merkle_branch/chain_merkle_index via the P1a
aux_merkle_root() primitive. New INCOMPLETE CheckResult state: a
structurally-consistent chain-merkle walk returns INCOMPLETE (never
VALID) because step 2 (MM-marker commitment + chain_id/slot binding),
step 3 (parent-coinbase tx-merkle leg) and step 4 (parent PoW) are not
built yet -- NMC still MUST NOT block-validate off this leaf. Malformed
slot indices (negative, or wider than branch depth) return INVALID.

4 KATs pin the INCOMPLETE-vs-INVALID boundary so the leg cannot silently
regress into asserting VALID. nmc_coin linked into the test (AuxPow ctor
pulls MutableTransaction). 9/9 PASS. NMC-local, btc tree READ-ONLY.
@frstrtr
frstrtr merged commit 2dded36 into master Jun 19, 2026
16 checks passed
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