Skip to content

Responder-side prevout amount validation against a chain view (#414 amount half) #502

Description

@kwsantiago

Follow-up to #414. PR #500 ships the destination-validation half (responder re-derives the expected sweep destination from the persisted NEW descriptor and refuses to sign if it differs).

The amount-validation half is still open. Responders trust the proposer's witness_utxo.value_sats verbatim. Because the BIP-341 sighash commits to prevout amounts, an understated input value defeats:

  • The 1/MAX_SWEEP_FEE_FRACTION cap in request_descriptor_migration_sweep.
  • The absolute fee cap inside RecoveryTxBuilder.

A proposer who declares 10000 sats when the on-chain UTXO is actually 100000 sats produces a sighash that signs to a fee far above what the caps would have allowed if computed honestly. Result: fee-griefing / value loss to whoever sees the broadcast first.

What it needs

A chain-view check on the responder side. The responder must independently fetch the prevout amount (and ideally script) before signing instead of accepting the proposer's claim.

Options for the chain view (in order of operational complexity):

  1. esplora/blockstream HTTP client — small, no node required, depends on a public service.
  2. bitcoind JSON-RPC — host runs a node, lowest trust.
  3. electrum protocol — middle ground, more reliable than HTTP.

PR #500 leaves a TODO marker at the destination-check site (keep-cli/src/commands/wallet.rs, keep-desktop/src/app/wallet.rs) noting where the amount check should fire.

Acceptance

  • Before any PSBT signing on the recovery path, the responder verifies each input's witness_utxo.value_sats against the live chain view.
  • A divergence aborts the signing with a clear error.
  • Operator can configure the chain endpoint (KEEP_CHAIN_URL env var or similar).
  • Test against a regtest harness.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghardp2PrioritysecuritySecurity-related issueswdcWallet Descriptor Coordination

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions