Skip to content

Commit bb8b5e4

Browse files
lklimekclaude
andcommitted
feat(key-wallet): add BlockchainIdentities account types (#553)
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>
1 parent 4ada2b8 commit bb8b5e4

15 files changed

Lines changed: 827 additions & 12 deletions

File tree

key-wallet-ffi/include/key_wallet_ffi.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,22 @@ typedef enum {
100100
Asset lock shielded address top-up funding (subfeature 5)
101101
*/
102102
ASSET_LOCK_SHIELDED_ADDRESS_TOP_UP = 15,
103+
/*
104+
Blockchain identity ECDSA keys (DIP-9) - Path: m/9'/coinType'/5'/0'
105+
*/
106+
BLOCKCHAIN_IDENTITIES_ECDSA = 16,
107+
/*
108+
Blockchain identity ECDSA Hash160 keys (DIP-9) - Path: m/9'/coinType'/5'/1'
109+
*/
110+
BLOCKCHAIN_IDENTITIES_ECDSA_HASH160 = 17,
111+
/*
112+
Blockchain identity BLS keys (DIP-9) - Path: m/9'/coinType'/5'/2'
113+
*/
114+
BLOCKCHAIN_IDENTITIES_BLS = 18,
115+
/*
116+
Blockchain identity BLS Hash160 keys (DIP-9) - Path: m/9'/coinType'/5'/3'
117+
*/
118+
BLOCKCHAIN_IDENTITIES_BLS_HASH160 = 19,
103119
} FFIAccountType;
104120

105121
/*

key-wallet-ffi/src/address_pool.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ fn get_managed_account_by_type<'a>(
4949
AccountType::AssetLockShieldedAddressTopUp => {
5050
collection.asset_lock_shielded_address_topup.as_ref()
5151
}
52+
AccountType::BlockchainIdentitiesECDSA => collection.blockchain_identities_ecdsa.as_ref(),
53+
AccountType::BlockchainIdentitiesECDSAHash160 => {
54+
collection.blockchain_identities_ecdsa_hash160.as_ref()
55+
}
56+
AccountType::BlockchainIdentitiesBLS => collection.blockchain_identities_bls.as_ref(),
57+
AccountType::BlockchainIdentitiesBLSHash160 => {
58+
collection.blockchain_identities_bls_hash160.as_ref()
59+
}
5260
AccountType::ProviderVotingKeys => collection.provider_voting_keys.as_ref(),
5361
AccountType::ProviderOwnerKeys => collection.provider_owner_keys.as_ref(),
5462
AccountType::ProviderOperatorKeys => collection.provider_operator_keys.as_ref(),
@@ -102,6 +110,14 @@ fn get_managed_account_by_type_mut<'a>(
102110
AccountType::AssetLockShieldedAddressTopUp => {
103111
collection.asset_lock_shielded_address_topup.as_mut()
104112
}
113+
AccountType::BlockchainIdentitiesECDSA => collection.blockchain_identities_ecdsa.as_mut(),
114+
AccountType::BlockchainIdentitiesECDSAHash160 => {
115+
collection.blockchain_identities_ecdsa_hash160.as_mut()
116+
}
117+
AccountType::BlockchainIdentitiesBLS => collection.blockchain_identities_bls.as_mut(),
118+
AccountType::BlockchainIdentitiesBLSHash160 => {
119+
collection.blockchain_identities_bls_hash160.as_mut()
120+
}
105121
AccountType::ProviderVotingKeys => collection.provider_voting_keys.as_mut(),
106122
AccountType::ProviderOwnerKeys => collection.provider_owner_keys.as_mut(),
107123
AccountType::ProviderOperatorKeys => collection.provider_operator_keys.as_mut(),

key-wallet-ffi/src/managed_account.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,18 @@ pub unsafe extern "C" fn managed_wallet_get_account(
250250
AccountType::AssetLockShieldedAddressTopUp => {
251251
managed_collection.asset_lock_shielded_address_topup.as_ref()
252252
}
253+
AccountType::BlockchainIdentitiesECDSA => {
254+
managed_collection.blockchain_identities_ecdsa.as_ref()
255+
}
256+
AccountType::BlockchainIdentitiesECDSAHash160 => {
257+
managed_collection.blockchain_identities_ecdsa_hash160.as_ref()
258+
}
259+
AccountType::BlockchainIdentitiesBLS => {
260+
managed_collection.blockchain_identities_bls.as_ref()
261+
}
262+
AccountType::BlockchainIdentitiesBLSHash160 => {
263+
managed_collection.blockchain_identities_bls_hash160.as_ref()
264+
}
253265
AccountType::ProviderVotingKeys => managed_collection.provider_voting_keys.as_ref(),
254266
AccountType::ProviderOwnerKeys => managed_collection.provider_owner_keys.as_ref(),
255267
AccountType::ProviderOperatorKeys => managed_collection.provider_operator_keys.as_ref(),
@@ -563,6 +575,14 @@ pub unsafe extern "C" fn managed_core_account_get_account_type(
563575
AccountType::IdentityInvitation => FFIAccountType::IdentityInvitation,
564576
AccountType::AssetLockAddressTopUp => FFIAccountType::AssetLockAddressTopUp,
565577
AccountType::AssetLockShieldedAddressTopUp => FFIAccountType::AssetLockShieldedAddressTopUp,
578+
AccountType::BlockchainIdentitiesECDSA => FFIAccountType::BlockchainIdentitiesECDSA,
579+
AccountType::BlockchainIdentitiesECDSAHash160 => {
580+
FFIAccountType::BlockchainIdentitiesECDSAHash160
581+
}
582+
AccountType::BlockchainIdentitiesBLS => FFIAccountType::BlockchainIdentitiesBLS,
583+
AccountType::BlockchainIdentitiesBLSHash160 => {
584+
FFIAccountType::BlockchainIdentitiesBLSHash160
585+
}
566586
AccountType::ProviderVotingKeys => FFIAccountType::ProviderVotingKeys,
567587
AccountType::ProviderOwnerKeys => FFIAccountType::ProviderOwnerKeys,
568588
AccountType::ProviderOperatorKeys => FFIAccountType::ProviderOperatorKeys,
@@ -1039,6 +1059,18 @@ pub unsafe extern "C" fn managed_core_account_get_address_pool(
10391059
ManagedAccountType::AssetLockShieldedAddressTopUp {
10401060
addresses,
10411061
} => addresses,
1062+
ManagedAccountType::BlockchainIdentitiesECDSA {
1063+
addresses,
1064+
} => addresses,
1065+
ManagedAccountType::BlockchainIdentitiesECDSAHash160 {
1066+
addresses,
1067+
} => addresses,
1068+
ManagedAccountType::BlockchainIdentitiesBLS {
1069+
addresses,
1070+
} => addresses,
1071+
ManagedAccountType::BlockchainIdentitiesBLSHash160 {
1072+
addresses,
1073+
} => addresses,
10421074
ManagedAccountType::ProviderVotingKeys {
10431075
addresses,
10441076
} => addresses,

key-wallet-ffi/src/transaction_checking.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,74 @@ pub unsafe extern "C" fn managed_wallet_check_transaction(
382382
ffi_accounts.push(ffi_match);
383383
continue;
384384
}
385+
CoreAccountTypeMatch::BlockchainIdentitiesECDSA {
386+
involved_addresses,
387+
} => {
388+
let ffi_match = FFIAccountMatch {
389+
account_type: 16, // BlockchainIdentitiesECDSA
390+
account_index: 0,
391+
registration_index: 0,
392+
received: account_match.received,
393+
sent: account_match.sent,
394+
external_addresses_count: involved_addresses.len() as c_uint,
395+
internal_addresses_count: 0,
396+
has_external_addresses: !involved_addresses.is_empty(),
397+
has_internal_addresses: false,
398+
};
399+
ffi_accounts.push(ffi_match);
400+
continue;
401+
}
402+
CoreAccountTypeMatch::BlockchainIdentitiesECDSAHash160 {
403+
involved_addresses,
404+
} => {
405+
let ffi_match = FFIAccountMatch {
406+
account_type: 17, // BlockchainIdentitiesECDSAHash160
407+
account_index: 0,
408+
registration_index: 0,
409+
received: account_match.received,
410+
sent: account_match.sent,
411+
external_addresses_count: involved_addresses.len() as c_uint,
412+
internal_addresses_count: 0,
413+
has_external_addresses: !involved_addresses.is_empty(),
414+
has_internal_addresses: false,
415+
};
416+
ffi_accounts.push(ffi_match);
417+
continue;
418+
}
419+
CoreAccountTypeMatch::BlockchainIdentitiesBLS {
420+
involved_addresses,
421+
} => {
422+
let ffi_match = FFIAccountMatch {
423+
account_type: 18, // BlockchainIdentitiesBLS
424+
account_index: 0,
425+
registration_index: 0,
426+
received: account_match.received,
427+
sent: account_match.sent,
428+
external_addresses_count: involved_addresses.len() as c_uint,
429+
internal_addresses_count: 0,
430+
has_external_addresses: !involved_addresses.is_empty(),
431+
has_internal_addresses: false,
432+
};
433+
ffi_accounts.push(ffi_match);
434+
continue;
435+
}
436+
CoreAccountTypeMatch::BlockchainIdentitiesBLSHash160 {
437+
involved_addresses,
438+
} => {
439+
let ffi_match = FFIAccountMatch {
440+
account_type: 19, // BlockchainIdentitiesBLSHash160
441+
account_index: 0,
442+
registration_index: 0,
443+
received: account_match.received,
444+
sent: account_match.sent,
445+
external_addresses_count: involved_addresses.len() as c_uint,
446+
internal_addresses_count: 0,
447+
has_external_addresses: !involved_addresses.is_empty(),
448+
has_internal_addresses: false,
449+
};
450+
ffi_accounts.push(ffi_match);
451+
continue;
452+
}
385453
CoreAccountTypeMatch::ProviderVotingKeys {
386454
involved_addresses,
387455
} => {

key-wallet-ffi/src/types.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,14 @@ pub enum FFIAccountType {
194194
AssetLockAddressTopUp = 14,
195195
/// Asset lock shielded address top-up funding (subfeature 5)
196196
AssetLockShieldedAddressTopUp = 15,
197+
/// Blockchain identity ECDSA keys (DIP-9) - Path: m/9'/coinType'/5'/0'
198+
BlockchainIdentitiesECDSA = 16,
199+
/// Blockchain identity ECDSA Hash160 keys (DIP-9) - Path: m/9'/coinType'/5'/1'
200+
BlockchainIdentitiesECDSAHash160 = 17,
201+
/// Blockchain identity BLS keys (DIP-9) - Path: m/9'/coinType'/5'/2'
202+
BlockchainIdentitiesBLS = 18,
203+
/// Blockchain identity BLS Hash160 keys (DIP-9) - Path: m/9'/coinType'/5'/3'
204+
BlockchainIdentitiesBLSHash160 = 19,
197205
}
198206

199207
impl FFIAccountType {
@@ -228,6 +236,18 @@ impl FFIAccountType {
228236
FFIAccountType::AssetLockShieldedAddressTopUp => {
229237
key_wallet::AccountType::AssetLockShieldedAddressTopUp
230238
}
239+
FFIAccountType::BlockchainIdentitiesECDSA => {
240+
key_wallet::AccountType::BlockchainIdentitiesECDSA
241+
}
242+
FFIAccountType::BlockchainIdentitiesECDSAHash160 => {
243+
key_wallet::AccountType::BlockchainIdentitiesECDSAHash160
244+
}
245+
FFIAccountType::BlockchainIdentitiesBLS => {
246+
key_wallet::AccountType::BlockchainIdentitiesBLS
247+
}
248+
FFIAccountType::BlockchainIdentitiesBLSHash160 => {
249+
key_wallet::AccountType::BlockchainIdentitiesBLSHash160
250+
}
231251
FFIAccountType::ProviderVotingKeys => key_wallet::AccountType::ProviderVotingKeys,
232252
FFIAccountType::ProviderOwnerKeys => key_wallet::AccountType::ProviderOwnerKeys,
233253
FFIAccountType::ProviderOperatorKeys => key_wallet::AccountType::ProviderOperatorKeys,
@@ -313,6 +333,18 @@ impl FFIAccountType {
313333
key_wallet::AccountType::AssetLockShieldedAddressTopUp => {
314334
(FFIAccountType::AssetLockShieldedAddressTopUp, 0, None)
315335
}
336+
key_wallet::AccountType::BlockchainIdentitiesECDSA => {
337+
(FFIAccountType::BlockchainIdentitiesECDSA, 0, None)
338+
}
339+
key_wallet::AccountType::BlockchainIdentitiesECDSAHash160 => {
340+
(FFIAccountType::BlockchainIdentitiesECDSAHash160, 0, None)
341+
}
342+
key_wallet::AccountType::BlockchainIdentitiesBLS => {
343+
(FFIAccountType::BlockchainIdentitiesBLS, 0, None)
344+
}
345+
key_wallet::AccountType::BlockchainIdentitiesBLSHash160 => {
346+
(FFIAccountType::BlockchainIdentitiesBLSHash160, 0, None)
347+
}
316348
key_wallet::AccountType::ProviderVotingKeys => {
317349
(FFIAccountType::ProviderVotingKeys, 0, None)
318350
}

key-wallet/src/account/account_collection.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ pub struct AccountCollection {
6262
pub asset_lock_address_topup: Option<Account>,
6363
/// Asset lock shielded address top-up account (optional)
6464
pub asset_lock_shielded_address_topup: Option<Account>,
65+
/// Blockchain identities ECDSA account
66+
pub blockchain_identities_ecdsa: Option<Account>,
67+
/// Blockchain identities ECDSA_HASH160 account
68+
pub blockchain_identities_ecdsa_hash160: Option<Account>,
69+
/// Blockchain identities BLS account
70+
pub blockchain_identities_bls: Option<Account>,
71+
/// Blockchain identities BLS_HASH160 account
72+
pub blockchain_identities_bls_hash160: Option<Account>,
6573
/// Provider voting keys (optional)
6674
pub provider_voting_keys: Option<Account>,
6775
/// Provider owner keys (optional)
@@ -93,6 +101,10 @@ impl AccountCollection {
93101
identity_invitation: None,
94102
asset_lock_address_topup: None,
95103
asset_lock_shielded_address_topup: None,
104+
blockchain_identities_ecdsa: None,
105+
blockchain_identities_ecdsa_hash160: None,
106+
blockchain_identities_bls: None,
107+
blockchain_identities_bls_hash160: None,
96108
provider_voting_keys: None,
97109
provider_owner_keys: None,
98110
#[cfg(feature = "bls")]
@@ -147,6 +159,18 @@ impl AccountCollection {
147159
AccountType::AssetLockShieldedAddressTopUp => {
148160
self.asset_lock_shielded_address_topup = Some(account);
149161
}
162+
AccountType::BlockchainIdentitiesECDSA => {
163+
self.blockchain_identities_ecdsa = Some(account);
164+
}
165+
AccountType::BlockchainIdentitiesECDSAHash160 => {
166+
self.blockchain_identities_ecdsa_hash160 = Some(account);
167+
}
168+
AccountType::BlockchainIdentitiesBLS => {
169+
self.blockchain_identities_bls = Some(account);
170+
}
171+
AccountType::BlockchainIdentitiesBLSHash160 => {
172+
self.blockchain_identities_bls_hash160 = Some(account);
173+
}
150174
AccountType::ProviderVotingKeys => {
151175
self.provider_voting_keys = Some(account);
152176
}
@@ -246,6 +270,14 @@ impl AccountCollection {
246270
AccountType::AssetLockShieldedAddressTopUp => {
247271
self.asset_lock_shielded_address_topup.is_some()
248272
}
273+
AccountType::BlockchainIdentitiesECDSA => self.blockchain_identities_ecdsa.is_some(),
274+
AccountType::BlockchainIdentitiesECDSAHash160 => {
275+
self.blockchain_identities_ecdsa_hash160.is_some()
276+
}
277+
AccountType::BlockchainIdentitiesBLS => self.blockchain_identities_bls.is_some(),
278+
AccountType::BlockchainIdentitiesBLSHash160 => {
279+
self.blockchain_identities_bls_hash160.is_some()
280+
}
249281
AccountType::ProviderVotingKeys => self.provider_voting_keys.is_some(),
250282
AccountType::ProviderOwnerKeys => self.provider_owner_keys.is_some(),
251283
#[cfg(feature = "bls")]
@@ -319,6 +351,14 @@ impl AccountCollection {
319351
AccountType::AssetLockShieldedAddressTopUp => {
320352
self.asset_lock_shielded_address_topup.as_ref()
321353
}
354+
AccountType::BlockchainIdentitiesECDSA => self.blockchain_identities_ecdsa.as_ref(),
355+
AccountType::BlockchainIdentitiesECDSAHash160 => {
356+
self.blockchain_identities_ecdsa_hash160.as_ref()
357+
}
358+
AccountType::BlockchainIdentitiesBLS => self.blockchain_identities_bls.as_ref(),
359+
AccountType::BlockchainIdentitiesBLSHash160 => {
360+
self.blockchain_identities_bls_hash160.as_ref()
361+
}
322362
AccountType::ProviderVotingKeys => self.provider_voting_keys.as_ref(),
323363
AccountType::ProviderOwnerKeys => self.provider_owner_keys.as_ref(),
324364
AccountType::ProviderOperatorKeys => None, // BLSAccount, use bls_account_of_type
@@ -386,6 +426,14 @@ impl AccountCollection {
386426
AccountType::AssetLockShieldedAddressTopUp => {
387427
self.asset_lock_shielded_address_topup.as_mut()
388428
}
429+
AccountType::BlockchainIdentitiesECDSA => self.blockchain_identities_ecdsa.as_mut(),
430+
AccountType::BlockchainIdentitiesECDSAHash160 => {
431+
self.blockchain_identities_ecdsa_hash160.as_mut()
432+
}
433+
AccountType::BlockchainIdentitiesBLS => self.blockchain_identities_bls.as_mut(),
434+
AccountType::BlockchainIdentitiesBLSHash160 => {
435+
self.blockchain_identities_bls_hash160.as_mut()
436+
}
389437
AccountType::ProviderVotingKeys => self.provider_voting_keys.as_mut(),
390438
AccountType::ProviderOwnerKeys => self.provider_owner_keys.as_mut(),
391439
AccountType::ProviderOperatorKeys => None, // BLSAccount, use bls_account_of_type_mut
@@ -457,6 +505,19 @@ impl AccountCollection {
457505
accounts.push(account);
458506
}
459507

508+
if let Some(account) = &self.blockchain_identities_ecdsa {
509+
accounts.push(account);
510+
}
511+
if let Some(account) = &self.blockchain_identities_ecdsa_hash160 {
512+
accounts.push(account);
513+
}
514+
if let Some(account) = &self.blockchain_identities_bls {
515+
accounts.push(account);
516+
}
517+
if let Some(account) = &self.blockchain_identities_bls_hash160 {
518+
accounts.push(account);
519+
}
520+
460521
if let Some(account) = &self.provider_voting_keys {
461522
accounts.push(account);
462523
}
@@ -505,6 +566,19 @@ impl AccountCollection {
505566
accounts.push(account);
506567
}
507568

569+
if let Some(account) = &mut self.blockchain_identities_ecdsa {
570+
accounts.push(account);
571+
}
572+
if let Some(account) = &mut self.blockchain_identities_ecdsa_hash160 {
573+
accounts.push(account);
574+
}
575+
if let Some(account) = &mut self.blockchain_identities_bls {
576+
accounts.push(account);
577+
}
578+
if let Some(account) = &mut self.blockchain_identities_bls_hash160 {
579+
accounts.push(account);
580+
}
581+
508582
if let Some(account) = &mut self.provider_voting_keys {
509583
accounts.push(account);
510584
}
@@ -607,6 +681,10 @@ impl AccountCollection {
607681
&& self.identity_invitation.is_none()
608682
&& self.asset_lock_address_topup.is_none()
609683
&& self.asset_lock_shielded_address_topup.is_none()
684+
&& self.blockchain_identities_ecdsa.is_none()
685+
&& self.blockchain_identities_ecdsa_hash160.is_none()
686+
&& self.blockchain_identities_bls.is_none()
687+
&& self.blockchain_identities_bls_hash160.is_none()
610688
&& self.provider_voting_keys.is_none()
611689
&& self.provider_owner_keys.is_none();
612690

@@ -634,6 +712,10 @@ impl AccountCollection {
634712
self.identity_invitation = None;
635713
self.asset_lock_address_topup = None;
636714
self.asset_lock_shielded_address_topup = None;
715+
self.blockchain_identities_ecdsa = None;
716+
self.blockchain_identities_ecdsa_hash160 = None;
717+
self.blockchain_identities_bls = None;
718+
self.blockchain_identities_bls_hash160 = None;
637719
self.provider_voting_keys = None;
638720
self.provider_owner_keys = None;
639721
#[cfg(feature = "bls")]

0 commit comments

Comments
 (0)