Skip to content

feat(key-wallet-ffi): typed special-transaction payload on FFITransactionRecord (expose ProRegTx service IP) #875

Description

@QuantumExplorer

Motivation

When a wallet's provider owner/voting key matches a ProRegTx during compact-filter sync (works since #863/#864, part of #861), consumers need the transaction's special payload data — most importantly the masternode's service_address (IP:port), but also proTxHash linkage, collateral outpoint, and the owner/voting/operator keys — to display anything useful about the masternode ("this key was used by the masternode at 54.148.58.128:9999"). The legacy DashSync SDK exposed this via DSLocalMasternode (built from DSProviderRegistrationTransaction.ipAddress/port); the Rust SDK currently cannot.

Current state

FFITransactionRecord (key-wallet-ffi/src/managed_account.rs) has no typed payload field. The only way to recover payload data is to consensus-decode the raw tx_data bytes on the consumer side — verified working (the service IP sits in those bytes), but it forces every binding (Swift/Kotlin) to reimplement DIP-2/DIP-3 payload parsing.

Worse, every other FFI conversion path explicitly drops the payload when reconstructing a transaction:

  • key-wallet-ffi/src/transaction.rs:280special_transaction_payload: None
  • key-wallet-ffi/src/tx_decode.rs:361special_transaction_payload: None
  • key-wallet-ffi/src/managed_account.rs:2350special_transaction_payload: None

And with keep-finalized-transactions off (the default in mobile builds), a chainlocked-at-first-sight historical ProRegTx's full record is dropped right after processing (managed_core_keys_account.rs, drop_finalized_transaction), so even the raw-bytes escape hatch disappears for the very transactions masternode-key discovery cares about.

Proposal

Add a typed, FFI-safe specialized-payload representation to FFITransactionRecord:

  1. A tagged union (e.g. FFISpecialTransactionPayload with a payload_type discriminant matching the DIP-2 tx types) covering at least:
    • ProviderRegistration: version, masternode type, collateral outpoint, service address (string form + raw ip/port), owner/voting key hashes, operator pubkey, operator reward, payout script, platform node id/ports
    • ProviderUpdateService: proTxHash, new service address, operator payout script
    • ProviderUpdateRegistrar: proTxHash, voting key hash, operator pubkey, payout script
    • ProviderUpdateRevocation: proTxHash, reason
    • (AssetLock/AssetUnlock/Coinbase payloads can follow the same shape later)
  2. Populate it in FFITransactionRecord construction from the stored TransactionRecord's special_transaction_payload, and stop hardcoding special_transaction_payload: None in the three conversion paths above where the source payload is available.
  3. Ensure the payload (or at least the provider-relevant fields) survives drop_finalized_transaction for transactions that matched a provider key account, so the data remains queryable without keep-finalized-transactions.

Item 3 overlaps with the broader "local masternode surface" idea (a persistent DashSync-DSLocalMasternode-style struct, plus monitoring proTxHash in the filter query for follow-on ProUpServTx IP updates — the pending remainder of #861). This issue is scoped to the FFI record shape; the local-masternode registry can build on it.

Acceptance

  • FFITransactionRecord for a stored ProRegTx exposes a typed payload including service_address without the consumer decoding tx_data.
  • The three special_transaction_payload: None sites populate the payload when the source has one.
  • Round-trip test: record a mainnet-shape ProRegTx (e.g. owner/voting hash160 70993555a01f7e8d6179d6135b5c56809d2d1d36, service 54.148.58.128:9999) → FFI record exposes those fields.

Metadata

Metadata

Assignees

No one assigned

    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