Skip to content

[#455] Task 4: internalize_action merkle-proof check drives 'completed' vs 'unproven' #459

@sgbett

Description

@sgbett

Part of #455.

Summary

Fix internalize_action so the stored wallet-action status reflects whether the BEEF actually carries a merkle proof for the subject transaction. If proof present → 'completed'. If absent → 'unproven'. This mirrors the TS reference (storage/methods/internalizeAction.ts:301provenTx ? 'completed' : 'unproven').

Scope

  • gem/bsv-wallet/lib/bsv/wallet_interface/wallet_client.rbinternalize_action (line ~288-308)

Changes

  • Use the existing helper beef.find_bump(tx.txid) (see gem/bsv-sdk/lib/bsv/transaction/beef.rb:258). Returns MerklePath if a BUMP is indexed for that txid, nil otherwise.
  • Replace line ~306:
    store_action(tx, args, status: 'completed')
    with:
    has_proof = !beef.find_bump(tx.txid).nil?
    store_action(tx, args, status: has_proof ? 'completed' : 'unproven')

Alternative considered but NOT preferred: tx.merkle_path.nil? ? 'unproven' : 'completed'. This depends on find_atomic_transaction wiring the merkle_path on the subject tx, which varies between atomic vs plain BEEF paths. find_bump is format-agnostic and safer.

Acceptance criteria

  • Internalize a BEEF where the subject tx has a merged BUMP → action status 'completed'.
  • Internalize a plain BEEF (raw tx, no BUMP for subject) → action status 'unproven'.
  • { accepted: true } return value unchanged.
  • store_proofs_from_beef still called — any proofs present in the BEEF are persisted regardless of the subject-tx proof status (regression).
  • Atomic BEEF carrying subject proof → 'completed' (the atomic format sets subject_txid; find_bump(subject_txid) returns the BUMP).

Edge cases

  • Non-atomic BEEF with subject lacking a BUMP but ancestor txs have BUMPs — subject status must be 'unproven'. find_bump(subject.txid) must not return an ancestor's BUMP; it keys on txid specifically (verify against the helper's behaviour).
  • Atomic BEEF (subject_txid set)find_atomic_transaction wires ancestry; find_bump(tx.txid) checks specifically for the subject's proof.
  • Subject tx extracted via fallback (non-atomic, last transaction) — same logic applies.
  • BEEF with a FORMAT_TXID_ONLY entry for the subject (proof-only, no raw tx) — shouldn't happen for incoming internalize; if it does, find_bump returns the BUMP if indexed, so status is 'completed'. Edge, but correct behaviour.

Test scenarios

  • internalize with proven BEEF (merged BUMP for subject) → action status 'completed'
  • internalize with unproven BEEF (raw tx, no BUMP) → action status 'unproven'
  • internalize with BEEF where ancestor has BUMP but subject does not → action status 'unproven'
  • internalize with Atomic BEEF carrying subject proof → action status 'completed'
  • proofs from BEEF are still stored in proof_store in both cases (regression)
  • { accepted: true } returned in both cases (regression)

Files modified

  • gem/bsv-wallet/lib/bsv/wallet_interface/wallet_client.rb
  • gem/bsv-wallet/spec/bsv/wallet_interface/wallet_client_spec.rb (Task 5 owns broader spec migration; direct test additions for internalize_action land here)

Sequencing

Independent of Tasks 1-3. Can be developed in parallel. Lands alongside them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    gem:walletbsv-wallet companion gemlayer:walletBSV::Wallet moduletaskImplementation task

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions