Skip to content

feat(key-wallet): add BlockchainIdentities account type#554

Open
lklimek wants to merge 8 commits intov0.42-devfrom
feat/blockchain-identities-account-type
Open

feat(key-wallet): add BlockchainIdentities account type#554
lklimek wants to merge 8 commits intov0.42-devfrom
feat/blockchain-identities-account-type

Conversation

@lklimek
Copy link
Copy Markdown
Contributor

@lklimek lklimek commented Mar 16, 2026

Summary

Adds four concrete BlockchainIdentities account type variants so SPV monitors identity authentication addresses at m/9'/coinType'/5'/subfeature'/index (DIP-9). Previously these addresses were invisible to bloom filters because they weren't created by WalletAccountCreationOptions::Default.

New Variants

Variant Subfeature Path
BlockchainIdentitiesECDSA 0 m/9'/coinType'/5'/0'/index
BlockchainIdentitiesECDSAHash160 1 m/9'/coinType'/5'/1'/index
BlockchainIdentitiesBLS 2 m/9'/coinType'/5'/2'/index
BlockchainIdentitiesBLSHash160 3 m/9'/coinType'/5'/3'/index

Design

Follows the established crate convention of concrete dedicated variants (like ProviderVotingKeys, ProviderOwnerKeys, etc.) rather than a parameterized BlockchainIdentities { subfeature: u32 }. Each variant gets its own Option<Account> field in collections.

  • key-wallet (10 files): AccountType, ManagedAccountType, AccountTypeToCheck, CoreAccountTypeMatch, AccountCollection, ManagedAccountCollection, transaction routing, wallet helper, unit tests
  • key-wallet-ffi (5 files): FFIAccountType values 16–19, account lookup, managed account conversion, transaction checking, C header
  • All use AddressPoolType::Absent (non-hardened leaf) with DEFAULT_SPECIAL_GAP_LIMIT
  • Added to TransactionType::Standard routing so SPV detects UTXOs at these addresses
  • All share DerivationPathReference::BlockchainIdentities

Closes #553

User Story

As a Dash Evo Tool user, I want my identity authentication addresses to be automatically monitored by the SPV client so that I receive transaction notifications for funds sent to those addresses without manually bootstrapping them outside the SDK.

Test Plan

  • Unit tests verify derivation paths for all 4 variants on testnet and mainnet
  • cargo check --workspace --all-features — clean
  • cargo test -p key-wallet -p key-wallet-ffi — all pass
  • cargo clippy --workspace --all-features — no warnings
  • Integration: verify monitored_addresses() includes BlockchainIdentities addresses
  • DET follow-up: add spv_account_metadata() match arm (dash-evo-tool#692)

🤖 Co-authored by Claudius the Magnificent AI Agent

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for four new blockchain identity account types: ECDSA, ECDSA Hash160, BLS, and BLS Hash160. These accounts are now integrated into address pool management, transaction routing, and checking workflows.
    • Default wallet creation now includes these new blockchain identity accounts.
  • Tests

    • Updated integration tests to reflect expanded default account initialization.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 16, 2026

📝 Walkthrough

Walkthrough

This pull request adds four new BlockchainIdentities account type variants (ECDSA, ECDSA_HASH160, BLS, BLS_HASH160) across the key-wallet and key-wallet-ffi crates. These variants derive authentication keys at m/9'/coinType'/5'/subfeature' with non-hardened leaf indices. Changes systematically extend account management, address pooling, transaction checking, and FFI infrastructure to recognize these new account types without altering existing behavior.

Changes

Cohort / File(s) Summary
Core Account Type Definitions
key-wallet/src/account/account_type.rs, key-wallet/src/account/mod.rs
Added four BlockchainIdentities variants to AccountType with subfeature indices 0–3; implemented derivation paths (m/9'/coinType'/5'/subfeature'), path references, and index returns; added unit tests validating path structure and field correctness for Testnet/Mainnet.
Account Collections & Storage
key-wallet/src/account/account_collection.rs, key-wallet/src/managed_account/managed_account_collection.rs
Extended AccountCollection and ManagedAccountCollection with four optional blockchain identity fields; updated insertion, presence checks, retrieval (get_by_type, _mut), iteration (all_accounts), and state management (is_empty, clear).
Managed Account Type Layer
key-wallet/src/managed_account/managed_account_type.rs, key-wallet/src/managed_account/mod.rs
Added four ManagedAccountType variants carrying AddressPool; extended index, address pool accessors (address_pools, address_pools_mut), type conversion, and address resolution methods to recognize new variants; updated single-pool methods for next-address derivation and gap-limit queries.
Transaction Checking & Routing
key-wallet/src/transaction_checking/account_checker.rs, key-wallet/src/transaction_checking/transaction_router/mod.rs
Extended CoreAccountTypeMatch with four blockchain identity variants carrying involved_addresses; added AccountTypeToCheck variants; updated collection check dispatch, address matching, and Standard-transaction routing to include new types; modified find_address_account to recognize blockchain identity addresses.
Transaction Checking Tests
key-wallet/src/transaction_checking/transaction_router/tests/identity_transactions.rs
Renamed and updated test_normal_payment_to_identity_address_not_detected to verify that normal payments to identity registration addresses are now detected via BlockchainIdentitiesECDSAHash160 when using the shared-path pattern.
Wallet Helper & Default Account Creation
key-wallet/src/wallet/helper.rs
Added creation of four BlockchainIdentities accounts (subfeatures 0–3) to both create_special_purpose_accounts() and create_special_purpose_accounts_with_passphrase(); extended extended_public_key_for_account_type() to return xpubs from new collection fields.
FFI Type Mappings
key-wallet-ffi/src/types.rs
Added four FFIAccountType enum variants (16–19); implemented bidirectional conversion between FFI and Rust AccountType via to_account_type() and from_account_type().
FFI Account & Address Pool Access
key-wallet-ffi/src/managed_account.rs, key-wallet-ffi/src/address_pool.rs
Extended managed_wallet_get_account() to route new blockchain identity variants to collection fields; added account-type and address-pool getters handling the four new variants; updated address-used marking to include blockchain identity collections.
FFI Transaction Checking
key-wallet-ffi/src/transaction_checking.rs
Extended managed_wallet_check_transaction() to construct FFIAccountMatch entries for four blockchain identity variants, populating account type (16–19), zero indices, received/sent counts, and address-count fields from involved_addresses.
Integration Tests
key-wallet-manager/tests/integration_test.rs
Updated test_account_management expected account count from 12 to 16, reflecting the addition of four default blockchain identity accounts.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • xdustinface

Poem

🐰 Hop, hop! Four new accounts now appear,
ECDSA, Hash160, BLS so clear,
For identity keys that need a new home,
m/9' paths where the addresses roam,
No blooms left hidden—we bloom them all! 🌸

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely summarizes the main change: adding BlockchainIdentities account type support to key-wallet.
Linked Issues check ✅ Passed All primary coding requirements from issue #553 are met: BlockchainIdentities account type variants added to AccountType with correct derivation paths (m/9'/coinType'/5'/subfeature'), ManagedAccountType extended with four variants using AddressPoolType::Absent, accounts created in Default wallet setup, AccountTypeToCheck routing implemented, and comprehensive changes across FFI layer.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #553 objectives. The integration test update reflects the expected increase in default accounts (11→15), and the identity_transactions.rs test change correctly validates the new BlockchainIdentitiesECDSAHash160 routing behavior.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/blockchain-identities-account-type

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new BlockchainIdentities account type to the key-wallet crate so that identity authentication addresses at m/9'/coinType'/5'/subfeature'/index are automatically monitored by SPV bloom filters. Previously these addresses were only bootstrapped externally by Dash Evo Tool.

Changes:

  • New BlockchainIdentities { subfeature: u32 } variant added across AccountType, ManagedAccountType, AccountTypeToCheck, CoreAccountTypeMatch, AccountCollection, and ManagedAccountCollection, with accounts for subfeatures 0–3 created during default wallet setup.
  • FFI support via FFIAccountType::BlockchainIdentities (value 16) with corresponding match arms in all FFI functions.
  • Transaction routing updated to check BlockchainIdentities accounts for TransactionType::Standard, enabling SPV detection of UTXOs sent to these addresses.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
key-wallet/src/account/account_type.rs New BlockchainIdentities variant with derivation path, path reference, and type conversions
key-wallet/src/account/account_collection.rs BTreeMap<u32, Account> storage for blockchain identity accounts
key-wallet/src/account/mod.rs Unit tests for derivation paths on testnet and mainnet
key-wallet/src/managed_account/managed_account_type.rs ManagedAccountType::BlockchainIdentities with AddressPoolType::Absent
key-wallet/src/managed_account/managed_account_collection.rs Collection management, creation, and iteration for blockchain identity accounts
key-wallet/src/managed_account/mod.rs Pattern match additions for address pool access
key-wallet/src/transaction_checking/transaction_router/mod.rs AccountTypeToCheck::BlockchainIdentities and inclusion in Standard tx checks
key-wallet/src/transaction_checking/account_checker.rs CoreAccountTypeMatch::BlockchainIdentities and indexed account checking
key-wallet/src/transaction_checking/transaction_router/tests/identity_transactions.rs Updated test expectations for shared-path detection
key-wallet/src/wallet/helper.rs Account creation in default setup and xpub retrieval
key-wallet-ffi/src/types.rs FFI enum value 16 and conversions
key-wallet-ffi/src/transaction_checking.rs FFI match arm for transaction check results
key-wallet-ffi/src/managed_account.rs FFI account lookup and type conversion
key-wallet-ffi/src/address_pool.rs FFI address pool access by subfeature
key-wallet-ffi/include/key_wallet_ffi.h C header enum addition

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Add four concrete BlockchainIdentities account type variants for
identity authentication keys at m/9'/coinType'/5'/subfeature':

- BlockchainIdentitiesECDSA (subfeature 0)
- BlockchainIdentitiesECDSAHash160 (subfeature 1)
- BlockchainIdentitiesBLS (subfeature 2)
- BlockchainIdentitiesBLSHash160 (subfeature 3)

These accounts are created by WalletAccountCreationOptions::Default,
use AddressPoolType::Absent (non-hardened leaf), and are routed via
TransactionType::Standard so SPV bloom filters cover them automatically.

Includes FFI bindings (FFIAccountType values 16-19).

Closes #553

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@lklimek lklimek force-pushed the feat/blockchain-identities-account-type branch from 0025841 to bb8b5e4 Compare March 16, 2026 15:24
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 16, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds four concrete BlockchainIdentities account type variants (ECDSA, ECDSAHash160, BLS, BLSHash160) to enable SPV bloom filter monitoring of identity authentication addresses at DIP-9 derivation paths m/9'/coinType'/5'/subfeature'/index.

Changes:

  • Added four new AccountType, ManagedAccountType, CoreAccountTypeMatch, and AccountTypeToCheck variants across key-wallet, with corresponding AccountCollection and ManagedAccountCollection fields
  • Included the new account types in WalletAccountCreationOptions::Default creation and TransactionType::Standard routing
  • Extended key-wallet-ffi with FFIAccountType values 16–19, account lookup, and C header definitions

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
key-wallet/src/account/account_type.rs New AccountType variants with derivation paths and conversions
key-wallet/src/account/account_collection.rs Option<Account> fields and match arms for new variants
key-wallet/src/account/mod.rs Unit tests for derivation paths on testnet/mainnet
key-wallet/src/managed_account/managed_account_type.rs ManagedAccountType variants with AddressPoolType::Absent
key-wallet/src/managed_account/managed_account_collection.rs Collection fields, creation, iteration for new variants
key-wallet/src/managed_account/mod.rs Address extraction match arms for new variants
key-wallet/src/transaction_checking/account_checker.rs CoreAccountTypeMatch variants and transaction checking
key-wallet/src/transaction_checking/transaction_router/mod.rs Added to Standard tx routing and AccountTypeToCheck
key-wallet/src/transaction_checking/transaction_router/tests/identity_transactions.rs Updated test to reflect shared-path detection behavior
key-wallet/src/wallet/helper.rs Account creation and xpub lookup for new variants
key-wallet-ffi/src/types.rs FFI enum values 16–19 and conversions
key-wallet-ffi/src/transaction_checking.rs FFI match arms for transaction checking
key-wallet-ffi/src/managed_account.rs FFI account lookup and type conversion
key-wallet-ffi/src/address_pool.rs FFI address pool access for new variants
key-wallet-ffi/include/key_wallet_ffi.h C header enum additions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Default wallet creation now produces 15 accounts (was 11) with the
addition of 4 BlockchainIdentities variants.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 16, 2026

Codecov Report

❌ Patch coverage is 46.36752% with 251 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.00%. Comparing base (09f03e0) to head (36dd6ff).

Files with missing lines Patch % Lines
key-wallet-ffi/src/transaction_checking.rs 0.00% 56 Missing ⚠️
...wallet/src/transaction_checking/account_checker.rs 44.11% 38 Missing ⚠️
key-wallet-ffi/src/address_pool.rs 0.00% 36 Missing ⚠️
...wallet/src/managed_account/managed_account_type.rs 14.28% 30 Missing ⚠️
.../src/managed_account/managed_account_collection.rs 76.08% 22 Missing ⚠️
key-wallet-ffi/src/managed_account.rs 0.00% 16 Missing ⚠️
key-wallet/src/managed_account/mod.rs 0.00% 16 Missing ⚠️
key-wallet/src/account/account_collection.rs 80.00% 12 Missing ⚠️
key-wallet-ffi/src/types.rs 0.00% 8 Missing ⚠️
...src/transaction_checking/transaction_router/mod.rs 33.33% 8 Missing ⚠️
... and 2 more
Additional details and impacted files
@@              Coverage Diff              @@
##           v0.42-dev     #554      +/-   ##
=============================================
- Coverage      67.45%   67.00%   -0.45%     
=============================================
  Files            320      320              
  Lines          67949    68417     +468     
=============================================
+ Hits           45832    45845      +13     
- Misses         22117    22572     +455     
Flag Coverage Δ
core 75.21% <ø> (ø)
ffi 33.88% <0.00%> (-2.61%) ⬇️
rpc 19.92% <ø> (ø)
spv 83.90% <ø> (+0.08%) ⬆️
wallet 67.54% <61.64%> (-0.05%) ⬇️
Files with missing lines Coverage Δ
key-wallet/src/account/mod.rs 66.76% <100.00%> (+3.97%) ⬆️
key-wallet/src/wallet/helper.rs 42.79% <73.33%> (+0.95%) ⬆️
key-wallet/src/account/account_type.rs 55.72% <72.22%> (+5.99%) ⬆️
key-wallet-ffi/src/types.rs 75.16% <0.00%> (-1.37%) ⬇️
...src/transaction_checking/transaction_router/mod.rs 84.21% <33.33%> (-5.05%) ⬇️
key-wallet/src/account/account_collection.rs 60.17% <80.00%> (+2.99%) ⬆️
key-wallet-ffi/src/managed_account.rs 48.78% <0.00%> (+3.86%) ⬆️
key-wallet/src/managed_account/mod.rs 53.68% <0.00%> (-1.39%) ⬇️
.../src/managed_account/managed_account_collection.rs 58.07% <76.08%> (+2.40%) ⬆️
...wallet/src/managed_account/managed_account_type.rs 21.53% <14.28%> (-0.69%) ⬇️
... and 3 more

... and 14 files with indirect coverage changes

@lklimek lklimek requested a review from xdustinface March 16, 2026 16:57
@lklimek lklimek marked this pull request as ready for review March 16, 2026 16:57
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
key-wallet/src/managed_account/mod.rs (1)

246-261: Consider centralizing single-pool variant handling to reduce future miss risk.

The same variant list is repeated across multiple methods. A shared helper on ManagedAccountType (e.g., returning single-pool addresses) would reduce maintenance drift.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet/src/managed_account/mod.rs` around lines 246 - 261, The pattern
matching for single-pool variants is duplicated; add a helper on
ManagedAccountType (e.g., a method like fn single_pool_addresses(&self) ->
Option<&Vec<AddressType>>) that returns Some(&addresses) for
BlockchainIdentitiesECDSA, BlockchainIdentitiesECDSAHash160,
BlockchainIdentitiesBLS, and BlockchainIdentitiesBLSHash160 and None otherwise,
then replace the repeated match arms in each method with a call to
single_pool_addresses() to centralize handling and avoid future misses.
key-wallet/src/account/mod.rs (1)

576-579: Avoid hardcoding coin-type network parameters in these assertions.

Please derive expected coin-type values from the network/source-of-truth helper instead of embedding 1/5 directly, so tests stay aligned with network parameter definitions.

As per coding guidelines "Never hardcode network parameters, addresses, or keys in Rust code."

Also applies to: 597-600

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet/src/account/mod.rs` around lines 576 - 579, The assertions
hardcode coin-type indices (1 and 5) instead of using the network
source-of-truth; replace those literals with the coin-type derived from the
network/helper (e.g., call the project’s network coin-type accessor or a helper
like get_coin_type(network) and use
ChildNumber::from_hardened_idx(coin_type).unwrap() in place of 1 and 5),
updating both the children assertions shown (the ones using
ChildNumber::from_hardened_idx(1) and ChildNumber::from_hardened_idx(5)) and the
similar assertions at the other occurrence (lines referenced in the comment), so
tests derive coin-type from the canonical network helper rather than hardcoded
values.
key-wallet/src/managed_account/managed_account_type.rs (1)

718-752: Consider replacing unreachable!() with explicit match arms.

The unreachable!() at line 750 could theoretically panic if the code is refactored incorrectly in the future. While it's currently safe due to the outer match guard, per coding guidelines for library code, prefer avoiding panic paths.

♻️ Alternative: Use explicit match arms instead of combined pattern
-            AccountType::BlockchainIdentitiesECDSA
-            | AccountType::BlockchainIdentitiesECDSAHash160
-            | AccountType::BlockchainIdentitiesBLS
-            | AccountType::BlockchainIdentitiesBLSHash160 => {
-                let path = account_type
-                    .derivation_path(network)
-                    .unwrap_or_else(|_| DerivationPath::master());
-                let pool = AddressPool::new(
-                    path,
-                    AddressPoolType::Absent,
-                    DEFAULT_SPECIAL_GAP_LIMIT,
-                    network,
-                    key_source,
-                )?;
-
-                Ok(match account_type {
-                    AccountType::BlockchainIdentitiesECDSA => Self::BlockchainIdentitiesECDSA {
-                        addresses: pool,
-                    },
-                    AccountType::BlockchainIdentitiesECDSAHash160 => {
-                        Self::BlockchainIdentitiesECDSAHash160 {
-                            addresses: pool,
-                        }
-                    }
-                    AccountType::BlockchainIdentitiesBLS => Self::BlockchainIdentitiesBLS {
-                        addresses: pool,
-                    },
-                    AccountType::BlockchainIdentitiesBLSHash160 => {
-                        Self::BlockchainIdentitiesBLSHash160 {
-                            addresses: pool,
-                        }
-                    }
-                    _ => unreachable!(),
-                })
-            }
+            AccountType::BlockchainIdentitiesECDSA => {
+                let path = account_type
+                    .derivation_path(network)
+                    .unwrap_or_else(|_| DerivationPath::master());
+                let pool = AddressPool::new(
+                    path,
+                    AddressPoolType::Absent,
+                    DEFAULT_SPECIAL_GAP_LIMIT,
+                    network,
+                    key_source,
+                )?;
+                Ok(Self::BlockchainIdentitiesECDSA { addresses: pool })
+            }
+            AccountType::BlockchainIdentitiesECDSAHash160 => {
+                let path = account_type
+                    .derivation_path(network)
+                    .unwrap_or_else(|_| DerivationPath::master());
+                let pool = AddressPool::new(
+                    path,
+                    AddressPoolType::Absent,
+                    DEFAULT_SPECIAL_GAP_LIMIT,
+                    network,
+                    key_source,
+                )?;
+                Ok(Self::BlockchainIdentitiesECDSAHash160 { addresses: pool })
+            }
+            AccountType::BlockchainIdentitiesBLS => {
+                let path = account_type
+                    .derivation_path(network)
+                    .unwrap_or_else(|_| DerivationPath::master());
+                let pool = AddressPool::new(
+                    path,
+                    AddressPoolType::Absent,
+                    DEFAULT_SPECIAL_GAP_LIMIT,
+                    network,
+                    key_source,
+                )?;
+                Ok(Self::BlockchainIdentitiesBLS { addresses: pool })
+            }
+            AccountType::BlockchainIdentitiesBLSHash160 => {
+                let path = account_type
+                    .derivation_path(network)
+                    .unwrap_or_else(|_| DerivationPath::master());
+                let pool = AddressPool::new(
+                    path,
+                    AddressPoolType::Absent,
+                    DEFAULT_SPECIAL_GAP_LIMIT,
+                    network,
+                    key_source,
+                )?;
+                Ok(Self::BlockchainIdentitiesBLSHash160 { addresses: pool })
+            }

Alternatively, you could extract a helper function to reduce duplication while keeping explicit arms.

As per coding guidelines: "Never panic in library code; always use Result for fallible operations."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet/src/managed_account/managed_account_type.rs` around lines 718 -
752, The match currently uses a combined pattern for AccountType variants then
returns a nested match with a final `_ => unreachable!()` which can panic if
refactored; instead enumerate explicit match arms for each variant
(AccountType::BlockchainIdentitiesECDSA,
AccountType::BlockchainIdentitiesECDSAHash160,
AccountType::BlockchainIdentitiesBLS,
AccountType::BlockchainIdentitiesBLSHash160) and return the corresponding
Self::... variants directly after creating the AddressPool (from
derivation_path(network).unwrap_or_else(|_| DerivationPath::master()) and
AddressPool::new(..., DEFAULT_SPECIAL_GAP_LIMIT, network, key_source)), removing
the wildcard arm so all handled cases are explicit and no unreachable!()
remains.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@key-wallet-ffi/src/address_pool.rs`:
- Around line 52-59: The managed_wallet_mark_address_used path fails to scan the
new AccountType variants that live in collection.blockchain_identities_ecdsa,
collection.blockchain_identities_ecdsa_hash160,
collection.blockchain_identities_bls, and
collection.blockchain_identities_bls_hash160, causing NotFound and no gap/usage
advancement; update managed_wallet_mark_address_used to include these four
collections when matching AccountType::BlockchainIdentitiesECDSA,
::BlockchainIdentitiesECDSAHash160, ::BlockchainIdentitiesBLS, and
::BlockchainIdentitiesBLSHash160 so the function searches the correct
collection, marks the address used, and advances the usage/gap state (mirroring
the logic used for other account types).

In `@key-wallet-ffi/src/types.rs`:
- Around line 197-204: Add unit tests that perform round-trip conversions for
the new FFI account variants (BlockchainIdentitiesECDSA,
BlockchainIdentitiesECDSAHash160, BlockchainIdentitiesBLS,
BlockchainIdentitiesBLSHash160) to ensure the public ABI discriminants and
conversion branches remain correct; locate the conversion functions in this
module (the enum and its to/from-ffi conversion implementations) and add tests
that convert each new variant to the FFI representation and back, asserting
equality, and mirror similar tests already present for older variants so the new
branches are exercised.

In `@key-wallet/src/transaction_checking/account_checker.rs`:
- Around line 404-427: find_address_account in ManagedCoreAccount does not
consider the new BlockchainIdentities* collections so address-to-account lookups
return None for DIP-9 paths; update ManagedCoreAccount::find_address_account to
include checks against collection.blockchain_identities_ecdsa,
collection.blockchain_identities_ecdsa_hash160,
collection.blockchain_identities_bls, and
collection.blockchain_identities_bls_hash160 (mirroring how AccountTypeToCheck
variants are handled) so that the lookup iterates those collections and returns
the matching account when an address is found; ensure you use the same matching
helper (e.g., the existing per-account check function used elsewhere) and
maintain existing return types and error handling.

In
`@key-wallet/src/transaction_checking/transaction_router/tests/identity_transactions.rs`:
- Around line 231-260: The test uses the shared m/9'/coinType'/5'/1' path but
allows any BlockchainIdentities* variant, so tighten the assertion to check the
single exact expected enum variant (e.g., replace the multi-branch match over
AccountTypeToCheck::BlockchainIdentitiesECDSA | ... with the specific variant
your fixture actually produces such as
AccountTypeToCheck::BlockchainIdentitiesECDSAHash160 or BlockchainIdentitiesBLS,
referencing the result variable and its affected_accounts iterator), update the
assertion message accordingly, and rename the test function from the misleading
*_not_detected name to something like
*_detected_via_blockchain_identities_shared_path to reflect the expected
behavior.

---

Nitpick comments:
In `@key-wallet/src/account/mod.rs`:
- Around line 576-579: The assertions hardcode coin-type indices (1 and 5)
instead of using the network source-of-truth; replace those literals with the
coin-type derived from the network/helper (e.g., call the project’s network
coin-type accessor or a helper like get_coin_type(network) and use
ChildNumber::from_hardened_idx(coin_type).unwrap() in place of 1 and 5),
updating both the children assertions shown (the ones using
ChildNumber::from_hardened_idx(1) and ChildNumber::from_hardened_idx(5)) and the
similar assertions at the other occurrence (lines referenced in the comment), so
tests derive coin-type from the canonical network helper rather than hardcoded
values.

In `@key-wallet/src/managed_account/managed_account_type.rs`:
- Around line 718-752: The match currently uses a combined pattern for
AccountType variants then returns a nested match with a final `_ =>
unreachable!()` which can panic if refactored; instead enumerate explicit match
arms for each variant (AccountType::BlockchainIdentitiesECDSA,
AccountType::BlockchainIdentitiesECDSAHash160,
AccountType::BlockchainIdentitiesBLS,
AccountType::BlockchainIdentitiesBLSHash160) and return the corresponding
Self::... variants directly after creating the AddressPool (from
derivation_path(network).unwrap_or_else(|_| DerivationPath::master()) and
AddressPool::new(..., DEFAULT_SPECIAL_GAP_LIMIT, network, key_source)), removing
the wildcard arm so all handled cases are explicit and no unreachable!()
remains.

In `@key-wallet/src/managed_account/mod.rs`:
- Around line 246-261: The pattern matching for single-pool variants is
duplicated; add a helper on ManagedAccountType (e.g., a method like fn
single_pool_addresses(&self) -> Option<&Vec<AddressType>>) that returns
Some(&addresses) for BlockchainIdentitiesECDSA,
BlockchainIdentitiesECDSAHash160, BlockchainIdentitiesBLS, and
BlockchainIdentitiesBLSHash160 and None otherwise, then replace the repeated
match arms in each method with a call to single_pool_addresses() to centralize
handling and avoid future misses.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 44c65f5b-19a8-4b11-80fd-82d5821ded62

📥 Commits

Reviewing files that changed from the base of the PR and between 4ada2b8 and 620c8d2.

📒 Files selected for processing (16)
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/address_pool.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/transaction_checking.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-manager/tests/integration_test.rs
  • key-wallet/src/account/account_collection.rs
  • key-wallet/src/account/account_type.rs
  • key-wallet/src/account/mod.rs
  • key-wallet/src/managed_account/managed_account_collection.rs
  • key-wallet/src/managed_account/managed_account_type.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/transaction_checking/account_checker.rs
  • key-wallet/src/transaction_checking/transaction_router/mod.rs
  • key-wallet/src/transaction_checking/transaction_router/tests/identity_transactions.rs
  • key-wallet/src/wallet/helper.rs

Copy link
Copy Markdown

Copilot AI commented Mar 16, 2026

@lklimek I've opened a new pull request, #555, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Copy Markdown

Copilot AI commented Mar 16, 2026

@lklimek I've opened a new pull request, #556, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Copy Markdown

Copilot AI commented Mar 16, 2026

@lklimek I've opened a new pull request, #557, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 3 commits March 16, 2026 18:39
…lookup (#555)

* Initial plan

* fix: add blockchain_identities_* checks to find_address_account()

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
…_address_used scan (#557)

* Initial plan

* fix: add blockchain_identities_* scanning to managed_wallet_mark_address_used

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
…ariant (#556)

* Initial plan

* test: rename and narrow BlockchainIdentities test to exact ECDSA_HASH160 shared-path variant

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
key-wallet/src/transaction_checking/account_checker.rs (1)

404-427: Optional: reduce variant-duplication in account dispatch/lookup.

This is correct as-is, but a small helper-driven dispatch for BlockchainIdentities* would reduce maintenance drift if more subfeatures are added later.

Also applies to: 1106-1130

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet/src/transaction_checking/account_checker.rs` around lines 404 -
427, Reduce duplication by adding a small helper on AccountChecker (e.g., a
method like check_blockchain_identity(&self, chooser: impl Fn(&Self) ->
Option<&AccountType>, tx: &Tx) -> Vec<_>) that encapsulates the pattern
.as_ref().and_then(|account| account.check_transaction_for_match(tx,
None)).into_iter().collect(); then replace the four match arms for
AccountTypeToCheck::BlockchainIdentitiesECDSA,
::BlockchainIdentitiesECDSAHash160, ::BlockchainIdentitiesBLS, and
::BlockchainIdentitiesBLSHash160 to call that helper with a selector that
returns the corresponding field (blockchain_identities_ecdsa,
blockchain_identities_ecdsa_hash160, blockchain_identities_bls,
blockchain_identities_bls_hash160), keeping the same behavior and return type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@key-wallet/src/transaction_checking/account_checker.rs`:
- Around line 404-427: Reduce duplication by adding a small helper on
AccountChecker (e.g., a method like check_blockchain_identity(&self, chooser:
impl Fn(&Self) -> Option<&AccountType>, tx: &Tx) -> Vec<_>) that encapsulates
the pattern .as_ref().and_then(|account| account.check_transaction_for_match(tx,
None)).into_iter().collect(); then replace the four match arms for
AccountTypeToCheck::BlockchainIdentitiesECDSA,
::BlockchainIdentitiesECDSAHash160, ::BlockchainIdentitiesBLS, and
::BlockchainIdentitiesBLSHash160 to call that helper with a selector that
returns the corresponding field (blockchain_identities_ecdsa,
blockchain_identities_ecdsa_hash160, blockchain_identities_bls,
blockchain_identities_bls_hash160), keeping the same behavior and return type.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3b014f95-122b-499d-8144-a3d7822c781e

📥 Commits

Reviewing files that changed from the base of the PR and between 620c8d2 and 80b3bd3.

📒 Files selected for processing (3)
  • key-wallet-ffi/src/address_pool.rs
  • key-wallet/src/transaction_checking/account_checker.rs
  • key-wallet/src/transaction_checking/transaction_router/tests/identity_transactions.rs

coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 16, 2026
@github-actions github-actions bot added the merge-conflict The PR conflicts with the target branch. label Mar 20, 2026
@github-actions
Copy link
Copy Markdown

This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them.

@github-actions github-actions bot removed the merge-conflict The PR conflicts with the target branch. label Mar 20, 2026
@lklimek lklimek requested a review from Copilot March 20, 2026 07:28
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 20, 2026
@github-actions github-actions bot added the ready-for-review CodeRabbit has approved this PR label Mar 20, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds dedicated BlockchainIdentities account-type variants across key-wallet and key-wallet-ffi so the SPV transaction router checks identity-derivation-path addresses during standard transaction relevance checks (and exposes them via FFI).

Changes:

  • Introduces four new AccountType / ManagedAccountType / AccountTypeToCheck variants for BlockchainIdentities (ECDSA, ECDSAHash160, BLS, BLSHash160).
  • Creates these accounts as part of WalletAccountCreationOptions::Default and routes TransactionType::Standard through them.
  • Extends account collections, matchers, and FFI enums/headers to support lookup and transaction matching for the new variants.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
key-wallet/src/account/account_type.rs Adds new AccountType variants, derivation paths, and conversions to AccountTypeToCheck.
key-wallet/src/account/account_collection.rs Adds storage/accessors for the new account variants in AccountCollection.
key-wallet/src/account/mod.rs Adds unit tests validating derivation paths and DerivationPathReference for the new variants.
key-wallet/src/wallet/helper.rs Ensures Default wallet creation includes the new BlockchainIdentities accounts and exposes their xpubs.
key-wallet/src/managed_account/managed_account_type.rs Adds new ManagedAccountType variants and address-pool creation for them.
key-wallet/src/managed_account/managed_account_collection.rs Adds the new variants into managed collection storage, creation, and iteration.
key-wallet/src/managed_account/mod.rs Extends ManagedCoreAccount helpers to treat the new variants as single-pool address accounts.
key-wallet/src/transaction_checking/transaction_router/mod.rs Routes standard transactions through the new account types and adds conversions from managed account types.
key-wallet/src/transaction_checking/account_checker.rs Extends matching and “contains address” checks to include the new account types.
key-wallet/src/transaction_checking/transaction_router/tests/identity_transactions.rs Updates routing expectations for identity-path standard transactions.
key-wallet/tests/integration_test.rs Updates Default account-count expectation in integration test.
key-wallet-ffi/src/types.rs Adds FFIAccountType values (16–19) and conversions to/from AccountType.
key-wallet-ffi/src/managed_account.rs Exposes the new account types via managed-account getters and type conversions.
key-wallet-ffi/src/address_pool.rs Extends address-pool lookup/mark-used logic to include the new accounts.
key-wallet-ffi/src/transaction_checking.rs Adds transaction-match mapping for the new core account match variants.
key-wallet-ffi/include/key_wallet_ffi.h Exposes the new FFI account-type constants in the C header.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Collaborator

@xdustinface xdustinface left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: feat(key-wallet): add BlockchainIdentities account type

Summary

Adds 4 BlockchainIdentitiesECDSA/ECDSAHash160/BLS/BLSHash160 account type variants for DIP-9 identity authentication key monitoring at m/9'/coinType'/5'/subfeature'/index. Plumbed through all the expected layers: AccountType, ManagedAccountType, AccountTypeToCheck, CoreAccountTypeMatch, both collection structs, FFI bindings, transaction routing, wallet creation, and tests.

The implementation follows existing crate conventions consistently. A few items worth addressing:

Issues

1. Shared derivation path with IdentityRegistration

The test rename reveals that BlockchainIdentitiesECDSAHash160 (subfeature 1) shares path m/9'/coinType'/5'/1' with IdentityRegistration. This means the same addresses are monitored by two account types — standard transactions match via BlockchainIdentitiesECDSAHash160, asset-lock transactions via IdentityRegistration. Is this intentional? Could it cause duplicate bloom filter entries or double-counted funds?

2. Silent fallback on derivation error

In ManagedAccountType::from_account_type():

let path = account_type
    .derivation_path(network)
    .unwrap_or_else(|_| DerivationPath::master());

This silently falls back to the master path if derivation fails. Should propagate the error instead — a wrong derivation path would be very hard to debug.

3. unreachable!() in nested matches

The subfeature dispatch in derivation_path() and ManagedAccountCollection uses an inner match with _ => unreachable!() after the outer match already narrowed to the 4 variants. A small fn subfeature(&self) -> u32 helper on AccountType would eliminate these and be reusable.

4. Fully-qualified paths in wallet/helper.rs

The new match arms use crate::transaction_checking::transaction_router::AccountTypeToCheck::BlockchainIdentitiesECDSA inline rather than a top-level use import. Follows the existing pattern in that function but the lines are getting quite long.

Looks Good

  • Exhaustive pattern matching everywhere — compiler will catch missing cases
  • Tests verify derivation paths for both testnet and mainnet
  • Correctly added to TransactionType::Standard routing
  • FFI enum values 16-19 are contiguous and consistent
  • AddressPoolType::Absent with DEFAULT_SPECIAL_GAP_LIMIT matches similar account types

@github-actions github-actions bot added the merge-conflict The PR conflicts with the target branch. label Mar 21, 2026
@github-actions
Copy link
Copy Markdown

This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them.

@xdustinface xdustinface removed the ready-for-review CodeRabbit has approved this PR label Mar 23, 2026
Copy link
Copy Markdown
Member

@QuantumExplorer QuantumExplorer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get the point of this PR. It will slow down sync, and for what case? Someone did a registration where the key used for registration was not in the wallet, but then used a key for identities that was in the wallet?

@lklimek
Copy link
Copy Markdown
Contributor Author

lklimek commented Mar 30, 2026

Note: this response was prepared by my AI assistant (Claudius) based on the context of DET issues and PRs — posting on my behalf.


The use case is DET (Dash Evo Tool) wallet integration. DET derives BlockchainIdentities addresses at m/9'/5'/subfeature'/index for identity authentication keys. Today DET bootstraps these addresses manually, outside of WalletManager — which means they're invisible to SPV bloom filters. Users see no balance or transaction history for identity-related addresses (dashpay/dash-evo-tool#692).

The concrete scenario is: user creates an identity through DET, tops it up from a Core wallet address. The topup transaction sends funds to an identity authentication key address derived at the BlockchainIdentities path. Without the SDK knowing about these addresses, SPV never notifies DET about the transaction → the user's wallet shows stale balances and no transaction history for platform operations.

dash-evo-tool PR #752 patched the UI to fetch balances via RPC as a workaround, but the proper fix is making these addresses first-class in the SDK so SPV monitors them. dash-evo-tool Issue #779 (full transaction history for platform addresses) is blocked on this.

Re: sync slowdown — these are 4 additional account types with DEFAULT_SPECIAL_GAP_LIMIT (which is typically small). The bloom filter gets a few more addresses, but the impact should be negligible compared to the existing account types already monitored. Happy to benchmark if that's a concern.

🤖 Co-authored by Claudius the Magnificent AI Agent

lklimek and others added 2 commits April 1, 2026 13:53
…identities-account-type

# Conflicts:
#	key-wallet-ffi/include/key_wallet_ffi.h
…) match

Post-merge fix: upstream PR #605 added `involved_receive_addresses()`
method with exhaustive match on CoreAccountTypeMatch, but our 4 new
BlockchainIdentities variants were not covered. They follow the same
single-pool `involved_addresses` pattern as other special account types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions bot removed the merge-conflict The PR conflicts with the target branch. label Apr 1, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
key-wallet/src/managed_account/managed_account_collection.rs (1)

509-528: Silent error handling may hide conversion failures.

The from_account_collection() method silently discards conversion errors via if let Ok(...). While this follows the existing pattern in the file, consider logging a warning when account conversion fails to aid debugging, especially since these are new account types that could encounter unexpected issues during migration.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet/src/managed_account/managed_account_collection.rs` around lines
509 - 528, The from_account_collection() conversion currently swallows errors
when calling Self::create_managed_account_from_account(...) for each new field
(blockchain_identities_ecdsa, blockchain_identities_ecdsa_hash160,
blockchain_identities_bls, blockchain_identities_bls_hash160); change the
pattern so failures are logged as warnings instead of ignored — e.g. match the
Result and on Err emit a warning that includes the target field name and the
error details, and on Ok set the corresponding managed_collection.<field> so you
still preserve the success path while surfacing conversion problems for
debugging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@key-wallet/src/managed_account/managed_account_collection.rs`:
- Around line 509-528: The from_account_collection() conversion currently
swallows errors when calling Self::create_managed_account_from_account(...) for
each new field (blockchain_identities_ecdsa,
blockchain_identities_ecdsa_hash160, blockchain_identities_bls,
blockchain_identities_bls_hash160); change the pattern so failures are logged as
warnings instead of ignored — e.g. match the Result and on Err emit a warning
that includes the target field name and the error details, and on Ok set the
corresponding managed_collection.<field> so you still preserve the success path
while surfacing conversion problems for debugging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b0460ea1-22bb-43fd-8bfd-03660dc70fec

📥 Commits

Reviewing files that changed from the base of the PR and between 6e95bf2 and 36dd6ff.

📒 Files selected for processing (12)
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/transaction_checking.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-manager/tests/integration_test.rs
  • key-wallet/src/account/account_collection.rs
  • key-wallet/src/account/mod.rs
  • key-wallet/src/managed_account/managed_account_collection.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/transaction_checking/account_checker.rs
  • key-wallet/src/transaction_checking/transaction_router/mod.rs
  • key-wallet/src/transaction_checking/transaction_router/tests/identity_transactions.rs
  • key-wallet/src/wallet/helper.rs
✅ Files skipped from review due to trivial changes (4)
  • key-wallet-manager/tests/integration_test.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/account/mod.rs
  • key-wallet-ffi/src/types.rs
🚧 Files skipped from review as they are similar to previous changes (5)
  • key-wallet/src/transaction_checking/transaction_router/tests/identity_transactions.rs
  • key-wallet-ffi/src/transaction_checking.rs
  • key-wallet/src/wallet/helper.rs
  • key-wallet/src/transaction_checking/transaction_router/mod.rs
  • key-wallet/src/account/account_collection.rs

@github-actions github-actions bot added the ready-for-review CodeRabbit has approved this PR label Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-review CodeRabbit has approved this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(key-wallet): Add BlockchainIdentities account type so SPV monitors identity authentication addresses

5 participants