feat: add multi-address type support for on-chain wallet#45
feat: add multi-address type support for on-chain wallet#45ben-kaufman wants to merge 1 commit intomainfrom
Conversation
|
acked the concept & description discussed with Spiral and with Ben in private next step: Ben is exploring a more "fork-friendly" alternative |
|
Caution Sharing here some interesting concepts that I didn't double-check but if they're not slop we might have to address this in the new implementation. Review SummaryPR adds multi-address type support (Legacy/NestedSegwit/NativeSegwit/Taproot) via multiple BDK wallet instances per node. +6296/-975 lines across 32 files. The architecture is fundamentally sound but has several critical issues that must be addressed before merge. CRITICAL ISSUES (Must Fix)1. Backwards-Incompatible Persistence Namespace Change (Data Loss Risk)Files: The persistence macro now appends address type suffixes to secondary namespaces:
Impact: Existing users upgrading to this version will have their wallet data stored under the OLD namespace (without suffix). The new code looks in the NEW namespace (with Required fix: Add migration logic that:
2. Incorrect UTXO Weight Calculation in Coin SelectionFile:
let descriptor = primary_wallet.public_descriptor(utxo.keychain);
let satisfaction_weight = descriptor.max_weight_to_satisfy()...For non-primary UTXOs (e.g., Legacy UTXOs when primary is NativeSegwit), Required fix: Look up the correct wallet for each UTXO (by finding which wallet owns the outpoint) and use that wallet's descriptor for weight calculation. 3. Fee Calculation Bug for Cross-Wallet Transactions in Payment StoreFile: let total_fee = primary_wallet.calculate_fee(&tx).unwrap_or(Amount::ZERO).to_sat();BDK's Required fix: Calculate fees by iterating all wallets and summing input values, similar to how 4.
|
|
@ben-kaufman I drafted the PR until the next iteration. |
Multi-Address Type Support for On-Chain Wallet
Summary
Adds comprehensive multi-address type support, allowing a single LDK Node to manage multiple Bitcoin address types (Legacy, NestedSegwit, NativeSegwit, Taproot) simultaneously:
AddressTypeenum with Legacy, NestedSegwit, NativeSegwit, and Taproot variantsConfig.address_typefor new addresses and change outputsConfig.address_types_to_monitorfor migration scenariosNode::get_balance_for_address_type()OnchainPayment::new_address_for_type()Motivation
Many Bitcoin wallets need to support multiple address types simultaneously:
API Changes
Configuration
New configuration options in
Config:address_type: AddressType- Primary address type for new addresses and change outputs (default: NativeSegwit)address_types_to_monitor: Vec<AddressType>- Additional address types to monitor (default: empty)Builder Methods
Builder::set_address_type(AddressType)- Set the primary address typeBuilder::set_address_types_to_monitor(Vec<AddressType>)- Set additional types to monitorNode Methods
Node::get_balance_for_address_type(AddressType)- Get balance for a specific address typeNode::list_monitored_address_types()- List all monitored address types (primary + monitored)OnchainPayment Methods
OnchainPayment::new_address_for_type(AddressType)- Get address for specific typeNew Types
AddressTypeenum:Legacy,NestedSegwit,NativeSegwit,TaprootAddressTypeBalance/OnchainBalanceForType- Balance info for a specific address typeImplementation Details
Multi-Wallet Architecture
Internally manages multiple BDK wallet instances (one per address type) with unified coordination:
Chain Source Updates
All chain backends (Esplora, Electrum, Bitcoind) updated to:
Wallet Persistence
Test Plan
test_multi_wallet_setup- Basic multi-wallet configurationtest_multi_wallet_balance_aggregation- Balance aggregation across typestest_multi_wallet_get_address_balance- Per-type balance queriestest_cross_wallet_spending- Spending from multiple wallet typestest_cross_wallet_spending_three_types- Three wallet types in one txtest_multi_wallet_send_operation- Send with multi-wallet configtest_multi_wallet_send_all- Send all with aggregated UTXOstest_send_all_drains_all_wallets- Verify all wallets are drainedtest_multi_wallet_utxo_selection- UTXO selection across typestest_rbf_single_wallet_input_with_multi_wallet_config- Single-wallet RBFtest_rbf_cross_wallet_transaction- Cross-wallet RBFtest_rbf_additional_inputs_fee_rate_correctness- Fee rate with added inputstest_cpfp_for_cross_wallet_transaction- Cross-wallet CPFPtest_multi_wallet_persistence_across_restart- Persistence verificationtest_new_address_for_type- Address generation per typetest_new_address_for_unmonitored_type- Error for unmonitored typestest_all_address_types_as_primary- Each type as primarytest_sync_updates_all_wallet_balances- Sync updates all typesBreaking Changes
None. The default configuration (
address_types_to_monitor = []) maintains existing single-wallet behavior.Files Changed
src/config.rsAddressTypeenum and config optionssrc/builder.rssrc/wallet/mod.rssrc/wallet/persist.rssrc/chain/mod.rssrc/chain/esplora.rssrc/chain/electrum.rssrc/chain/bitcoind.rssrc/payment/onchain.rsnew_address_for_type()src/lib.rssrc/balance.rsAddressTypeBalancestructsrc/io/utils.rsbindings/ldk_node.udltests/multi_wallet_tests.rs