You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
All asset lock creation flows should use a single shared code path with deterministic HD-derived keys and built-in recovery for broken/rejected transactions. Currently there are multiple independent implementations with inconsistent error handling and key management.
Background
PR #790 (fix/deterministic-asset-lock-keys) introduced deterministic HD key derivation for generic asset lock transactions, replacing OsRng-generated keys that caused permanent fund loss when Platform rejected a state transition after Core had already broadcast the asset lock. It also introduced broadcast_and_commit_asset_lock() as a shared helper for the broadcast → track → UTXO cleanup sequence.
However, several asset lock flows still have their own inline implementations, and recovery from broken transactions is incomplete.
Problem
1. Multiple divergent asset lock paths
The codebase has at least 4 separate asset lock creation flows:
But there's no UI or backend flow to actually recover — the user must manually "Search for Asset Locks" and hope the system finds them
Proposed Solution
Phase 1: Unify all asset lock paths through broadcast_and_commit_asset_lock()
Refactor fund_platform_address_from_wallet_utxos.rs and shielded/bundle.rs to use broadcast_and_commit_asset_lock() instead of inline broadcast + UTXO cleanup. This ensures:
Summary
All asset lock creation flows should use a single shared code path with deterministic HD-derived keys and built-in recovery for broken/rejected transactions. Currently there are multiple independent implementations with inconsistent error handling and key management.
Background
PR #790 (
fix/deterministic-asset-lock-keys) introduced deterministic HD key derivation for generic asset lock transactions, replacingOsRng-generated keys that caused permanent fund loss when Platform rejected a state transition after Core had already broadcast the asset lock. It also introducedbroadcast_and_commit_asset_lock()as a shared helper for the broadcast → track → UTXO cleanup sequence.However, several asset lock flows still have their own inline implementations, and recovery from broken transactions is incomplete.
Problem
1. Multiple divergent asset lock paths
The codebase has at least 4 separate asset lock creation flows:
create_asset_lock.rsregistration_asset_lock_transaction()— HD-derived ✅broadcast_and_commit_asset_lock()✅create_asset_lock.rstop_up_asset_lock_transaction()— HD-derived ✅broadcast_and_commit_asset_lock()✅fund_platform_address_from_wallet_utxos.rsgeneric_asset_lock_transaction()— HD-derived ✅ (PR #790)shielded/bundle.rs(shield_from_asset_lock)generic_asset_lock_transaction()— HD-derived ✅ (PR #790)2. Inconsistent broadcast + commit sequence
broadcast_and_commit_asset_lock()(introduced in PR #790 for identity flows) handles:transactions_waiting_for_finalityThe platform address funding and shielded flows do this sequence inline with subtle differences:
fund_platform_address_from_wallet_utxos.rsdoes UTXO cleanup but doesn't register intransactions_waiting_for_finalitybefore broadcastshield_from_asset_lockinbundle.rsdoes register in finality tracking but has its own error recovery3. No transaction recovery mechanism
When a transaction fails after broadcast (Platform rejects, timeout, nonce mismatch):
Proposed Solution
Phase 1: Unify all asset lock paths through
broadcast_and_commit_asset_lock()Refactor
fund_platform_address_from_wallet_utxos.rsandshielded/bundle.rsto usebroadcast_and_commit_asset_lock()instead of inline broadcast + UTXO cleanup. This ensures:transactions_waiting_for_finalitytrackingPhase 2: Add asset lock recovery flow
When a Platform state transition fails after the asset lock is broadcast:
(txid, derivation_path, amount, intended_purpose)to afailed_asset_locksDB tablePhase 3: Unify key derivation paths (DIP-9 compliance)
PR #790 noted TODO items about DIP-9 compliance:
m/9'/ct'/5'/0'/index'but DIP-9 assigns sub-feature 1'm/9'/ct'/5'/identity_index'/top_up_index'but DIP-9 assigns sub-feature 2'This needs a migration strategy:
Acceptance Criteria
broadcast_and_commit_asset_lock()(or equivalent shared helper)OsRng) — already done in PR fix(wallet): use deterministic HD key for generic asset lock transactions #790Related
🤖 Co-authored by Claudius the Magnificent AI Agent