Skip to content

K0 Fix A: wallet ringsize-2 privacy warning + PrivacyWarning RPC field (fixes #79) - #80

Closed
liqdmetal wants to merge 2 commits into
DEROFDN:community-devfrom
liqdmetal:fix/k0-ringsize-warning
Closed

K0 Fix A: wallet ringsize-2 privacy warning + PrivacyWarning RPC field (fixes #79)#80
liqdmetal wants to merge 2 commits into
DEROFDN:community-devfrom
liqdmetal:fix/k0-ringsize-warning

Conversation

@liqdmetal

@liqdmetal liqdmetal commented Aug 22, 2026

Copy link
Copy Markdown

Summary

Mainnet measurement (50k-block scan) shows ~57% of transactions ship at ringsize 2, where the ring IS the two participants (sender+receiver, zero decoys) and the signer is recoverable on-chain by design. This is the wallet/API half of the fix: warn loudly and surface it to callers when a tx would expose the sender. No consensus change — ships immediately.

Why ringsize 2 exposes the signer

At ringsize 2 the ring is [sender, receiver]; the proof parity bit selects one of the two positions and, because sender/receiver are placed at opposite parity, the parity bit identifies the sender uniquely. Extract_signer (blockchain/transaction_execute.go) recovers it.

This PR (Fix A)

  • walletapi/wallet_memory.goLastRingSizeWarning field (not persisted)
  • walletapi/wallet_transfer.goTransferPayload0 sets the warning when ringsize resolves to 2 (or < 4)
  • rpc/wallet_rpc.goTransfer_Result.PrivacyWarning surfaces it to programmatic callers
  • walletapi/rpcserver/rpc_transfer.go — wire PrivacyWarning into the result
  • cmd/dero-wallet-cli/prompt.go — burn path prints the warning and requires explicit confirmation
  • walletapi/k0_guard_test.go — 5 tests

Warn, do not force: SC entrypoints calling SIGNER() still require ringsize 2; forcing a higher ring would break owner-gated contracts until a signature-check intrinsic (K0 Fix C) lands. Consensus enforcement (Fix B: min-ring-4 floor) is a separate hard fork and intentionally NOT in this PR.

Why it matters

  • ringsize-2 txs are a silent privacy footgun for every wallet user and programmatic caller
  • no migration burden, no fork, no wallet-file change

Follow-ups (not this PR)

  • Fix B1: consensus min-ring-4 floor for NORMAL/BURN txs (hard fork)
  • Fix C: verify_sig intrinsic so owner-gated contracts can authorize at ringsize >= 4

Branch: fix/k0-ringsize-warning in the fork liqdmetal/derohe-improvements-by-liqdmetal. Includes a build-manifest fix (go.mod/go.sum) because the current tree does not build from a fresh clone (3-line go.mod, no vendor/modules.txt).


Related PRs in this K0/DVM series

PR What Consensus Role
#80 Fix A — wallet ringsize-2 warning + PrivacyWarning RPC none (ships now) the non-consensus wallet/API half
#82 Fix B1 — consensus min-ring-4 floor for NORMAL/BURN hard fork the consensus enforcement
#84 DVM v9verify_sig, hash_to_point, pedersen_commit/verify_commit, asset_balance, ec_add hard fork (VM surface) foundation for Fix C (anonymous owner auth at ringsize ≥ 4)

Ordering: Fix A (#80) merges immediately. Fix B1 (#82) bans ringsize-2 NORMAL/BURN; SC_TX stays exempt while owner-gated contracts need SIGNER(). DVM v9 (#84) removes that exemption via verify_sig; then Fix B2 (registry uses_signer) closes the loop.

… field (Fix A)

RingSize-2 txs expose the signer on-chain by design (Extract_signer,
blockchain/transaction_execute.go). This is the wallet/API half of the
K0 privacy fix (no consensus change — ships immediately):

- walletapi/wallet_memory.go: LastRingSizeWarning field (not persisted)
- walletapi/wallet_transfer.go: TransferPayload0 sets the warning when
  ringsize resolves to 2 (<4 for smaller warnings)
- rpc/wallet_rpc.go: Transfer_Result.PrivacyWarning surfaces it to
  programmatic callers
- walletapi/rpcserver/rpc_transfer.go: wire PrivacyWarning into result
- cmd/dero-wallet-cli/prompt.go: burn path prints the warning and
  requires explicit confirmation
- walletapi/k0_guard_test.go: 5 tests (rings-2 warning, ring-4 clean,
  SC-invoke ringsize-2 still builds, RPC field present)

Warn, do not force: SC entrypoints that call SIGNER() still require
ringsize 2 today; forcing a higher ring would break owner-gated
contracts until the signature-check intrinsic (K0 Fix C) lands.

Consensus enforcement (Fix B: min-ring-4 floor) is a separate hard fork
and deliberately NOT included here.
@liqdmetal

Copy link
Copy Markdown
Author

Related PRs in this K0/DVM series

These are part of one coordinated package, deliberately split into independent, reviewable threads:

PR What Consensus Role
#80 Fix A — wallet ringsize-2 warning + PrivacyWarning RPC none (ships now) the non-consensus wallet/API half
#82 Fix B1 — consensus min-ring-4 floor for NORMAL/BURN hard fork the consensus enforcement
#84 DVM v9verify_sig, hash_to_point, pedersen_commit/verify_commit, asset_balance, ec_add hard fork (VM surface) the foundation for Fix C (anonymous owner auth at ringsize ≥ 4, replacing the last ringsize-2 need)

Ordering logic:

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
liqdmetal force-pushed the fix/k0-ringsize-warning branch from cb9c414 to 525a00f Compare August 23, 2026 03:26
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.
@liqdmetal

Copy link
Copy Markdown
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.

@liqdmetal liqdmetal closed this Aug 24, 2026
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