Skip to content

Return txid for already-known raw broadcasts #122

Description

@piotr-iohk

Return txid for already-known raw broadcasts

Problem

trezor_sign_tx_from_psbt returns a valid serialized signed transaction but normally leaves TrezorSignedTx.txid unset. This matches the current contract: the txid is populated only when signing also pushes the transaction.

The native apps broadcast separately and retain the signed transaction after an ambiguous network failure. If Electrum accepted the first broadcast but its response was lost, retrying can return an “already known”, “already in mempool”, or “already in blockchain” error. The apps then cannot complete transfer bookkeeping because they do not have the txid.

Requiring TrezorSignedTx.txid at signing time is not valid and breaks normal hardware signing.

Proposed change

Update broadcast_raw_tx in src/modules/onchain/implementation.rs:

  1. Decode and deserialize the signed transaction as it already does.
  2. Compute its canonical txid with bitcoin::Transaction::compute_txid().
  3. Return the computed txid after a successful Electrum broadcast.
  4. Treat only explicit duplicate/already-accepted Electrum responses as success and return the computed txid.
  5. Preserve existing errors for invalid transaction data, connectivity failures, task failures, and unrelated broadcast rejection.

Keep TrezorSignedTx.txid optional and preserve its existing contract. Do not implement Bitcoin transaction parsing independently in Swift or Kotlin.

Error classification

Extract duplicate-response classification into a focused helper. Cover the Electrum messages currently handled by the apps:

  • already in block chain
  • already in blockchain
  • already in mempool
  • already-in-block-chain
  • already-in-mempool
  • txn-already-known
  • transaction already exists

Classification must be case-insensitive and must not convert unrelated relay-policy or invalid-transaction errors into success.

Tests

  • A valid legacy transaction returns its canonical txid.
  • A valid SegWit transaction returns txid, not wtxid.
  • Each supported already-known response returns the locally computed txid.
  • Connectivity and unrelated broadcast errors remain failures.
  • Invalid hex and invalid serialized transactions retain their typed errors.

Acceptance criteria

  • Retrying an already-accepted raw transaction returns the same txid as the original broadcast.
  • Native apps can complete Blocktank funding bookkeeping without relying on TrezorSignedTx.txid.
  • No FFI API shape change is required.
  • Rust tests, Clippy, and formatting pass.

Consumer follow-up

After releasing Bitkit Core:

  1. Update the Core dependency in bitkit-ios and bitkit-android.
  2. Remove app-level already-known error parsing and signer-provided txid recovery.
  3. Keep regression tests where Trezor signing returns txid = nil and broadcast retry still completes.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

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