Skip to content

pocx: render bech32 P2WPKH addresses in user-facing account/signer messages#2

Merged
JohnnyFFM merged 1 commit into
pocx-nightlyfrom
fix/bech32-error-messages
May 10, 2026
Merged

pocx: render bech32 P2WPKH addresses in user-facing account/signer messages#2
JohnnyFFM merged 1 commit into
pocx-nightlyfrom
fix/bech32-error-messages

Conversation

@JohnnyFFM
Copy link
Copy Markdown
Collaborator

Summary

Operator-facing log lines and JSON-RPC errors that referenced a plot or the effective signer printed the 20-byte hash160 as raw 40-char hex, forcing operators to manually re-encode the value to map it back to the pocx1q… form their wallet / get_assignment / the rest of the chain tooling display. This PR renders those identifiers via EncodeDestination(WitnessV0KeyHash{…}) — same pattern already used in get_assignment (src/pocx/rpc/assignments.cpp:104-108).

Address HRP follows the active chain, so testnet/regtest produce tpocx1… / rpocx1… respectively.

The hex form is still computed and passed to wallet lookup APIs (interfaces::Wallet::haveAccountKey, signPoCXBlock, pocx::mining::HaveAccountKey), so the wallet-check contract is unchanged — only the human-facing strings are reformatted.

Refs PoC-Consortium/bitcoin-pocx#3

Touched messages

src/pocx/rpc/mining.cpp (submit_nonce):

  • log "Plot %s has assignment, checking key for effective signer: %s"
  • JSONRPCError(RPC_WALLET_UNLOCK_NEEDED) "Wallet holding key for effective signer %s is locked…"
  • JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY) "No private key available for effective signer %s (plot: %s)"

src/pocx/mining/scheduler.cpp:

  • log "[Scheduler] Trying %zu wallet(s) for effective signer %s"

src/pocx/mining/block_builder.cpp:

  • log "[BlockBuilder] Building block for account %s (…)"
  • log "[BlockBuilder] Plot: %s, Effective signer: %s at height %d"

src/pocx/mining/wallet_signing.cpp:

  • "Account ID: %s -> CKeyID: %s" → "Signing for account %s" (the original printed the same hash twice in different reversed-hex forms; collapsed to one bech32 line)
  • log "No ScriptPubKeyMan found that can sign for account %s"

Before / after

Before:

No private key available for effective signer 1234567890abcdef1234567890abcdef12345678 (plot: deadbeef…12345678)

After (mainnet):

No private key available for effective signer pocx1qzg6…<bech32> (plot: pocx1qmm…<bech32>)

(testnet → tpocx1…, regtest → rpocx1….)

Test plan

  • Build locally (cmake --build build).
  • Functional check on regtest: load a wallet that does not hold the key for a plot's effective signer, call submit_nonce, confirm the error string contains rpocx1… for both identifiers.
  • Repeat the locked-wallet path: encrypt the wallet, call submit_nonce for a plot it does hold, confirm the RPC_WALLET_UNLOCK_NEEDED error contains rpocx1….
  • Trigger the scheduler / block-builder / wallet-signing log lines (regtest forge cycle) and confirm they show bech32.
  • Spot-check on testnet (tpocx1…) and mainnet (pocx1…) if available.

…ssages

Operator-facing log lines and JSON-RPC errors that referenced a plot or
the effective signer printed the 20-byte hash160 as raw 40-char hex,
forcing operators to manually re-encode the value to map it back to the
pocx1q... form their wallet, get_assignment, and the rest of the chain
tooling display.

Render those identifiers via EncodeDestination(WitnessV0KeyHash{...}),
mirroring the pattern already used in get_assignment
(src/pocx/rpc/assignments.cpp). Address HRP follows the active chain, so
testnet/regtest produce tpocx1.../rpocx1... respectively.

The hex form is still computed and passed to wallet lookup APIs
(interfaces::Wallet::haveAccountKey, signPoCXBlock,
pocx::mining::HaveAccountKey), so the wallet-check contract is unchanged
- only the human-facing strings are reformatted.

Touched messages:
- src/pocx/rpc/mining.cpp (submit_nonce):
  * "Plot %s has assignment, checking key for effective signer: %s" log
  * "Wallet holding key for effective signer %s is locked..."
    JSONRPCError(RPC_WALLET_UNLOCK_NEEDED)
  * "No private key available for effective signer %s (plot: %s)"
    JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY)
- src/pocx/mining/scheduler.cpp:
  * "[Scheduler] Trying %zu wallet(s) for effective signer %s" log
- src/pocx/mining/block_builder.cpp:
  * "[BlockBuilder] Building block for account %s (...)" log
  * "[BlockBuilder] Plot: %s, Effective signer: %s at height %d" log
- src/pocx/mining/wallet_signing.cpp:
  * "Account ID: %s -> CKeyID: %s" -> "Signing for account %s"
    (the original printed the same hash twice in different reversed-hex
    forms; collapsed to a single bech32 line)
  * "No ScriptPubKeyMan found that can sign for account %s" log

Refs PoC-Consortium/bitcoin-pocx#3
@JohnnyFFM JohnnyFFM merged commit b9ec67d into pocx-nightly May 10, 2026
12 of 28 checks passed
@JohnnyFFM JohnnyFFM deleted the fix/bech32-error-messages branch May 10, 2026 13:03
JohnnyFFM added a commit that referenced this pull request May 10, 2026
…ssages (#2)

Operator-facing log lines and JSON-RPC errors that referenced a plot or
the effective signer printed the 20-byte hash160 as raw 40-char hex,
forcing operators to manually re-encode the value to map it back to the
pocx1q... form their wallet, get_assignment, and the rest of the chain
tooling display.

Render those identifiers via EncodeDestination(WitnessV0KeyHash{...}),
mirroring the pattern already used in get_assignment
(src/pocx/rpc/assignments.cpp). Address HRP follows the active chain, so
testnet/regtest produce tpocx1.../rpocx1... respectively.

The hex form is still computed and passed to wallet lookup APIs
(interfaces::Wallet::haveAccountKey, signPoCXBlock,
pocx::mining::HaveAccountKey), so the wallet-check contract is unchanged
- only the human-facing strings are reformatted.

Touched messages:
- src/pocx/rpc/mining.cpp (submit_nonce):
  * "Plot %s has assignment, checking key for effective signer: %s" log
  * "Wallet holding key for effective signer %s is locked..."
    JSONRPCError(RPC_WALLET_UNLOCK_NEEDED)
  * "No private key available for effective signer %s (plot: %s)"
    JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY)
- src/pocx/mining/scheduler.cpp:
  * "[Scheduler] Trying %zu wallet(s) for effective signer %s" log
- src/pocx/mining/block_builder.cpp:
  * "[BlockBuilder] Building block for account %s (...)" log
  * "[BlockBuilder] Plot: %s, Effective signer: %s at height %d" log
- src/pocx/mining/wallet_signing.cpp:
  * "Account ID: %s -> CKeyID: %s" -> "Signing for account %s"
    (the original printed the same hash twice in different reversed-hex
    forms; collapsed to a single bech32 line)
  * "No ScriptPubKeyMan found that can sign for account %s" log

Refs PoC-Consortium/bitcoin-pocx#3
JohnnyFFM added a commit that referenced this pull request May 10, 2026
…ssages (#2)

Operator-facing log lines and JSON-RPC errors that referenced a plot or
the effective signer printed the 20-byte hash160 as raw 40-char hex,
forcing operators to manually re-encode the value to map it back to the
pocx1q... form their wallet, get_assignment, and the rest of the chain
tooling display.

Render those identifiers via EncodeDestination(WitnessV0KeyHash{...}),
mirroring the pattern already used in get_assignment
(src/pocx/rpc/assignments.cpp). Address HRP follows the active chain, so
testnet/regtest produce tpocx1.../rpocx1... respectively.

The hex form is still computed and passed to wallet lookup APIs
(interfaces::Wallet::haveAccountKey, signPoCXBlock,
pocx::mining::HaveAccountKey), so the wallet-check contract is unchanged
- only the human-facing strings are reformatted.

Touched messages:
- src/pocx/rpc/mining.cpp (submit_nonce):
  * "Plot %s has assignment, checking key for effective signer: %s" log
  * "Wallet holding key for effective signer %s is locked..."
    JSONRPCError(RPC_WALLET_UNLOCK_NEEDED)
  * "No private key available for effective signer %s (plot: %s)"
    JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY)
- src/pocx/mining/scheduler.cpp:
  * "[Scheduler] Trying %zu wallet(s) for effective signer %s" log
- src/pocx/mining/block_builder.cpp:
  * "[BlockBuilder] Building block for account %s (...)" log
  * "[BlockBuilder] Plot: %s, Effective signer: %s at height %d" log
- src/pocx/mining/wallet_signing.cpp:
  * "Account ID: %s -> CKeyID: %s" -> "Signing for account %s"
    (the original printed the same hash twice in different reversed-hex
    forms; collapsed to a single bech32 line)
  * "No ScriptPubKeyMan found that can sign for account %s" log

Refs PoC-Consortium/bitcoin-pocx#3
JohnnyFFM added a commit to PoC-Consortium/bitcoin-pocx that referenced this pull request May 15, 2026
Add scripts/mining/test-regtest-submitnonce-key-gate-v2.sh covering every
branch of the receive-path probe (HaveAccountKey) plus the multi-wallet
iteration semantics:

  A  Absent     watch-only descriptor; expect -5 + bech32 + no raw-hex regression
  B  Locked     encrypted+locked privkey; expect -13 + walletpassphrase hint
  C  Available  unlocked privkey; expect exit 0 + raw_quality/poc_time
  D  Multi      Locked + Available, Locked loaded first
                (probe must traverse past Locked to pick Available)
  E  Multi      Available + Locked, Available loaded first
                (later Locked must not downgrade an earlier Available)

D + E together prove the {Locked, Available} probe outcome is order-
independent, ruling out "break on first Locked" and "Locked overrides
later" regressions. Each case loads its wallets in isolation and unloads
between cases so the probe state under test is unambiguous.

Regression guards for:
  #4 (PR PoC-Consortium/bitcoin#3) - Absent/Locked split
  #3 (PR PoC-Consortium/bitcoin#2) - bech32 rendering

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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