[POC BDK] Introduce modular trait-based watch-only wallet architecture#950
Draft
moisesPompilio wants to merge 5 commits intogetfloresta:masterfrom
Draft
[POC BDK] Introduce modular trait-based watch-only wallet architecture#950moisesPompilio wants to merge 5 commits intogetfloresta:masterfrom
moisesPompilio wants to merge 5 commits intogetfloresta:masterfrom
Conversation
…anagement The provider layer establishes a new abstraction for managing all descriptor-related operations in the watch-only wallet. It centralizes responsibility for tracking wallet state across descriptors, including address derivation, transaction indexing, and balance calculations. The provider serves as the single source of truth for descriptor-scoped information, isolating this logic from higher-level wallet coordination. Key responsibilities: - Manage descriptor persistence and retrieval - Track generated and observed addresses per descriptor - Index transactions associated with each descriptor - Maintain UTXO sets and output tracking - Calculate balances on a per-descriptor basis - Process blockchain events (blocks, mempool) and emit descriptor-specific events - Added `WalletProvider` trait defining the provider interface - Introduced `WalletProviderEvent` enum for event-driven transaction notifications - Defined `WalletProviderError` for comprehensive error handling - Implemented feature-gated BDK provider backend via `bdk-provider` feature test(provider): add comprehensive provider unit tests Established test coverage for the provider interface, validating core descriptor and transaction management operations. Test scenarios: - Descriptor lifecycle (persist, retrieve, list, deduplicate) - Transaction indexing and querying by descriptor - Balance calculations with confirmation requirements - Address generation and management - UTXO tracking and spend status filtering - Mempool and block event processing - Edge cases (empty wallets, nonexistent descriptors, duplicate operations) - Script buffer management and local output tracking
…sistence The repository layer establishes a higher-level persistence abstraction for the watch-only wallet, centralizing all data storage operations. It manages wallet metadata, descriptor configurations, transaction indexing, and script tracking—providing a clean interface between the wallet service and the underlying database backend. Core responsibilities: - Persist wallet names and lifecycle management - Store descriptors associated with each wallet with their metadata (active status, change flag, labels) - Maintain descriptor configurations and derivation information - Index and retrieve transactions for Electrum protocol support - Track script buffers and derive addresses for transaction monitoring - Provide auxiliary transaction data structures needed for Electrum responses Implementation: - Added SQLiteRepository backed by rusqlite with migration-based schema initialization - Designed comprehensive WalletPersist trait defining the repository interface - Implemented wallet CRUD operations supporting multi-wallet environments - Created database schema with normalized tables for wallets, descriptors, transactions, and script buffers - Established foreign key constraints for data integrity Test coverage: - Wallet creation, listing, and deletion operations - Descriptor lifecycle (persist, retrieve, update, deduplication) - Multi-wallet descriptor management and isolation - Transaction indexing and querying - Script buffer operations and state tracking - Edge cases and error conditions Dependencies: - rusqlite: SQLite driver for Rust - refinery: Database migration management
…n and lifecycle management The wallet service establishes the coordination layer between the provider, repository, and metadata layers, orchestrating wallet operations and managing the complete wallet lifecycle. It serves as the primary interface for wallet clients (such as Electrum servers), translating high-level operations into coordinated calls across the underlying layers while maintaining consistent wallet state. Architecture & Responsibilities: *Provider Integration:* - Queries descriptor-specific transaction data and balance information - Retrieves address generation and UTXOs for each descriptor - Processes blockchain events and emits descriptor-scoped notifications *Repository Integration:* - Persists wallet metadata (name, creation, deletion) - Stores descriptor configurations with metadata (active flag, change flag, labels) - Maintains transaction index for Electrum protocol responses - Tracks script buffers and historical transaction data *Metadata Management:* - Maintains in-memory wallet state and descriptor registry - Administers descriptor lifecycle (add, activate, deactivate, replace) - Handles descriptor state transitions when adding new descriptors - Enforces single active descriptor per category (external/change) *Core Operations:* - Wallet creation and loading from persistent storage - Descriptor management with automatic deactivation of replaced descriptors - Block and mempool transaction processing with event propagation - Balance calculations aggregating across descriptors - Transaction history and proof retrieval for Electrum clients - Address generation delegated to active descriptors Implementation: - Implemented `Wallet` trait defining the complete service interface - Multi-layered error handling with service-specific error types - RwLock-based concurrency for thread-safe metadata access - Deterministic descriptor ID generation via SHA256 hashing
- Add architecture overview with three-layer design explanation - Include Mermaid class diagram showing trait relationships - Add sequence diagram for block processing data flow - Provide practical usage examples (wallet creation, descriptors, blocks, queries) - Document feature flags (bdk-provider, sqlite) and combinations - Detail error types, concurrency model, and development guidelines - All content in English with clear code examples
Collaborator
Author
|
In this case, what is in service.rs will basically replace everything from lib.rs, however I didn't put it there so the code can still compile in case someone wants to test something |
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description and Notes
This PR introduces a proof of concept for integrating BDK into Floresta by restructuring the watch-only wallet architecture into a more modular and specialized design.
The new architecture splits responsibilities across three main layers:
Wallet): provides the high-level API and coordinates wallet operationsIt also adds shared models used for communication between layers, such as richer balance structures that expose more detailed information like
trusted,used, anduntrustedvalues.All layers communicate through traits, which makes the architecture more flexible and extensible. This allows multiple implementations for the same layer, for example:
For testing, the idea is to build an integration-test architecture around the traits themselves. I already started this approach in the provider layer, and in the service layer I left some usage examples to illustrate the intended behavior. The goal is to validate that the expected behavior of the
repository,provider, andservicetraits remains consistent regardless of the concrete implementation being used.With this approach, implementation-specific code should not need to duplicate unit tests for the core behavior already defined by the traits. Instead, concrete implementations would only need tests for auxiliary or internal helper functions that are specific to that implementation, similar to what is already done in the provider layer. This helps ensure that, no matter which Floresta implementation is plugged in, the same rules and expectations apply across the board.
In addition, this PR includes a short documentation update in
crates/floresta-watch-only/README.mdto explain how the new design works.Notes for reviewers:
How to verify the changes you have done?