K0 Fix B1: consensus min-ring-4 floor for NORMAL/BURN txs (fixes #81) - #82
Closed
liqdmetal wants to merge 4 commits into
Closed
K0 Fix B1: consensus min-ring-4 floor for NORMAL/BURN txs (fixes #81)#82liqdmetal wants to merge 4 commits into
liqdmetal wants to merge 4 commits into
Conversation
…hard fork) From K0_MIN_RING4_HEIGHT onward, NORMAL/BURN transactions with ringsize < 4 are rejected by consensus. Ringsize-2 txs expose the signer on-chain by design (Extract_signer); the privacy floor of 4 = sender + receiver + 2 decoys is the smallest meaningful anonymity set. - config/config.go: K0_MIN_RING4_HEIGHT (mainnet 7,600,000 post-HF3; testnet 0 = apply at genesis) - blockchain/transaction_verify.go: k0RingSizeFloorReject() — NORMAL/BURN ringsize < 4 rejected post-gate; SC_TX/coinbase/registration/premine exempt (owner-gated SC calls still need ringsize 2 until the verify_sig migration, K0 Fix C) - blockchain/k0_ringsize_test.go: 3 tests (post-gate reject, SC_TX exemption, pre-fork unaffected) Mainnet baseline driving this: ~57% of txs ship at ringsize 2. This is the hard-fork half of the K0 fix; the wallet warning (Fix A) is the non-consensus half (separate PR). Also carries the build-manifest fix (go.mod/go.sum): the current tree does not build from a fresh clone (3-line go.mod, no vendor/modules.txt, unresolvable jrpc2/readline pins).
Author
Related PRs in this K0/DVM seriesThese are part of one coordinated package, deliberately split into independent, reviewable threads:
Ordering logic:
|
This was referenced Aug 22, 2026
liqdmetal
added a commit
to liqdmetal/derohe-improvements-by-liqdmetal
that referenced
this pull request
Aug 23, 2026
…T auto-detect) The consensus half of closing the ringsize-2 loophole for SC calls: a ringsize-2 SC_TX exposes the signer by design (the ring IS sender+receiver, parity selects the sender). This makes ringsize 2 structurally impossible for contracts that don't need it. Design (k0-fix-design.md Fix B2): - SC_META_DATA gains a NoSigner bit (high bit of the Type byte). The 33-byte wire format is UNCHANGED, so existing metadata stays valid and existing contracts default to uses_signer=true (preserving behavior). - At install (transaction_execute.go), the parsed contract AST is scanned for SIGNER() calls (dvm.ContractUsesSigner). No SIGNER() -> NoSigner bit set. Contract authors need no changes. - Consensus enforcement (transaction_verify.go): SC_TX + ringsize 2 + NoSigner-marked contract -> rejected with a clear error. Contracts that genuinely call SIGNER() keep ringsize 2 (owner-gated entrypoints) until the verify_sig migration (K0 Fix C, DVM v9 PR DEROFDN#84) removes that need. Tests (dvm/k0_b2_test.go): - TestContractUsesSigner: detects SIGNER(), no false positive - TestSCMetaNoSignerBit: bit set/clear, 33-byte round-trip, private+NoSigner coexistence Composes with the K0 package: Fix A (DEROFDN#80) warns, Fix B1 (DEROFDN#82) bans ringsize-2 NORMAL/BURN, Fix B2 bans ringsize-2 SC_TX for NoSigner contracts, Fix C (DEROFDN#84 verify_sig) removes the last legitimate ringsize-2 need. Also carries the build-manifest fix (go.mod/go.sum).
liqdmetal
force-pushed
the
fix/k0-min-ring4
branch
from
August 23, 2026 03:26
3dcb711 to
929f241
Compare
Regenerates vendor/ via go mod tidy + go mod vendor (adds missing vendor/modules.txt) so the tree builds from a fresh clone without -mod=mod. Deps unchanged.
community-dev base calls l.Operation.KickReader(), which no published chzyer/readline implements (v1.5.1) -> wallet-cli fails to compile from a fresh clone. Replace with the same UI shim used on the main fork branch: _ = l.Operation (read-unblock helper, wallet-only, not consensus).
This was referenced Aug 23, 2026
1. Fork-boundary bypass: the floor keyed off tx.Height (attacker-settable, walletapi/transaction_build.go:37). TX_VALIDITY_HEIGHT=11 lets a tx reference a block up to 11 back, so right after the floor activates a ring-2 NORMAL tx pinned to a pre-fork block dodged the gate. Now keyed off the current chain tip (chain.Get_Height()). 2. SC_TX type-lie bypass: TransactionType is an attacker-set header field (transaction.go:316), and process_transaction_sc treats SC_TX with no SCACTION as a no-op (transaction_execute.go:267,291). A ring-2 NORMAL transfer stamped SC_TX dodged the SC_TX exemption for free. Now any SC_TX that does not carry SCACTION in SCDATA is re-stamped NORMAL and meets the floor. Wargame regression tests pin both bypasses.
liqdmetal
added a commit
to liqdmetal/derohe-improvements-by-liqdmetal
that referenced
this pull request
Aug 23, 2026
…EIGHT) The B2 SC rules were gated on MAJOR_HF3_HEIGHT (7,504,640) while the B1 floor (PR DEROFDN#82) activates at K0_MIN_RING4_HEIGHT (7,600,000) — a ~95k-block window where B2 would reject ring-2 SC installs/calls while ring-2 NORMAL txs were still legal. Both now share K0_MIN_RING4_HEIGHT (mainnet 7,600,000 post-HF3, testnet 0), so the floor and the SC-signer rules turn on together at one activation height.
This was referenced Aug 24, 2026
Author
|
Superseded by PR #121 (the consolidated K0 privacy package). Closing in its favour — same code, but as one reviewable 17-file PR with no vendored-dependency noise. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Hard-fork proposal: from a fixed height, reject NORMAL/BURN transactions with ringsize < 4 at consensus. Ringsize-2 txs expose the signer on-chain by design — the ring is just [sender, receiver] and the proof's parity bit identifies the sender uniquely (
Extract_signer). Mainnet baseline: ~57% of txs ship at ringsize 2.The privacy floor of 4 (sender + receiver + 2 decoys) is the smallest meaningful anonymity set.
This PR (Fix B1)
config/config.go—K0_MIN_RING4_HEIGHT(mainnet 7,600,000 post-HF3; testnet 0 = apply at genesis)blockchain/transaction_verify.go—K0RingSizeFloorReject(): NORMAL/BURN ringsize < 4 rejected post-gate, keyed off the current chain tip at verification timeblockchain/k0_ringsize_test.go— 3 rule tests (post-gate reject, SC_TX exemption, pre-fork unaffected)blockchain/wargame_k0_bypass_test.go+wargame_k0_sctxtype_test.go— 4 wargame regression tests pinning the two hardening fixes belowExemptions: SC_TX / coinbase / registration / premine. SC owner-gated calls still require ringsize 2 today because they use
SIGNER()— forcing a higher ring would break them until theverify_sigintrinsic (K0 Fix C) lands. This is explicit in the code comments.Hardening (wargame findings, now in the code)
Two bypasses were found and closed before this PR shipped:
tx.Height, which is attacker-settable (walletapi/transaction_build.go:37). SinceTX_VALIDITY_HEIGHT = 11lets a tx reference a block up to 11 back, a ring-2 NORMAL tx pinned to a pre-fork block would dodge the gate for the first ~11 blocks after activation. The floor now keys offchain.Get_Height()at verification time — the window is closed.TransactionTypeis an attacker-set header field (transaction.go:316), andprocess_transaction_sctreats an SC_TX with noSCACTIONin SCDATA as a no-op (transaction_execute.go:267,291). A ring-2 NORMAL transfer stampedSC_TXused to dodge the SC_TX exemption for free. Now any SC_TX that does not carrySCACTIONis re-stamped NORMAL and meets the floor.Both are pinned by wargame regression tests (
TestWargame_K0FloorNoPreForkDodge,TestWargame_K0FloorSC_TXTypeLieBypass, plus the execute-path no-op case).Design notes
value > dustcarve-out.hardfork_fixes.go) covers pre-fork txs only, so no conflict — verified.FEE_PER_KB × (len/16 + mult)); privacy has a price, documented.Relationship to the other K0 PRs
uses_signer) — follow-up: ringsize 2 only for genuinely owner-gated SC entrypoints.verify_sigintrinsic) — lets owner-gated contracts authorize at ringsize ≥ 4, removing the last ringsize-2 need.This PR is deliberately scoped to the consensus floor only.
Branch:
fix/k0-min-ring4in the forkliqdmetal/derohe-improvements-by-liqdmetal. Carries the build fixes: re-vendored modules (vendor/modules.txtpresent) and theKickReaderremoval, so the tree builds from a fresh clone.