88//! with a map containing:
99//! - Seed fingerprint: A byte string that uniquely identifies the seed
1010//! - Accounts: An array of Zcash unified full viewing keys
11- //!
12- //! Decode also accepts a device version string at CBOR map key 3 if present.
13- //! The standard encoder does not emit that field, preserving the existing
14- //! two-key account export shape for older consumers.
11+ //! - Device version: An optional firmware version string
1512
1613use alloc:: {
1714 string:: { String , ToString } ,
@@ -70,16 +67,19 @@ impl ZcashAccounts {
7067 self . device_version . clone ( )
7168 }
7269
73- /// Stores device version metadata without changing the canonical
74- /// `zcash-accounts` encoding.
70+ /// Sets the firmware version emitted at CBOR map key 3.
7571 pub fn set_device_version ( & mut self , device_version : String ) {
7672 self . device_version = Some ( device_version) ;
7773 }
7874}
7975
8076impl MapSize for ZcashAccounts {
8177 fn map_size ( & self ) -> u64 {
82- 2
78+ if self . device_version . is_some ( ) {
79+ 3
80+ } else {
81+ 2
82+ }
8383 }
8484}
8585
@@ -107,6 +107,10 @@ impl<C> minicbor::Encode<C> for ZcashAccounts {
107107 ZcashUnifiedFullViewingKey :: encode ( account, e, _ctx) ?;
108108 }
109109
110+ if let Some ( device_version) = & self . device_version {
111+ e. int ( Int :: from ( DEVICE_VERSION ) ) ?. str ( device_version) ?;
112+ }
113+
110114 Ok ( ( ) )
111115 }
112116}
@@ -259,7 +263,7 @@ mod tests {
259263 }
260264
261265 #[ test]
262- fn test_zcash_accounts_encoder_omits_device_version_for_compatibility ( ) {
266+ fn test_zcash_accounts_encodes_device_version ( ) {
263267 let seed_fingerprint = hex:: decode ( "d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1" ) . unwrap ( ) ;
264268 let mut accounts = ZcashAccounts :: new ( seed_fingerprint, vec ! [ ] ) ;
265269 accounts. set_device_version ( "1.2.3" . to_string ( ) ) ;
@@ -268,16 +272,22 @@ mod tests {
268272
269273 assert_eq ! (
270274 hex:: encode( & cbor) ,
271- "a20150d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d10280 "
275+ "a30150d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d102800365312e322e33 "
272276 ) ;
273277 let decoded: ZcashAccounts = minicbor:: decode ( & cbor) . unwrap ( ) ;
274- assert_eq ! ( decoded. device_version, None ) ;
278+ assert_eq ! ( decoded. device_version, Some ( "1.2.3" . to_string ( ) ) ) ;
275279 }
276280
277281 #[ test]
278- fn test_zcash_accounts_without_device_version_decodes_from_old_cbor ( ) {
282+ fn test_zcash_accounts_without_device_version_preserves_old_cbor ( ) {
279283 let seed_fingerprint = hex:: decode ( "d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1" ) . unwrap ( ) ;
280- let cbor = hex:: decode ( "a20150d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d10280" ) . unwrap ( ) ;
284+ let accounts = ZcashAccounts :: new ( seed_fingerprint. clone ( ) , vec ! [ ] ) ;
285+ let cbor = minicbor:: to_vec ( & accounts) . unwrap ( ) ;
286+
287+ assert_eq ! (
288+ hex:: encode( & cbor) ,
289+ "a20150d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d10280"
290+ ) ;
281291 let decoded: ZcashAccounts = minicbor:: decode ( & cbor) . unwrap ( ) ;
282292
283293 assert_eq ! ( decoded. seed_fingerprint, seed_fingerprint) ;
@@ -381,6 +391,6 @@ mod tests {
381391
382392 let mut accounts_with_version = ZcashAccounts :: new ( vec ! [ ] , vec ! [ ] ) ;
383393 accounts_with_version. set_device_version ( "1.0.0" . to_string ( ) ) ;
384- assert_eq ! ( accounts_with_version. map_size( ) , 2 ) ;
394+ assert_eq ! ( accounts_with_version. map_size( ) , 3 ) ;
385395 }
386396}
0 commit comments