Skip to content

Commit e78a5ec

Browse files
committed
zcash_keys: Box Address elements to avoid large variations in enum variant sizes
1 parent 02e2dba commit e78a5ec

File tree

16 files changed

+55
-54
lines changed

16 files changed

+55
-54
lines changed

zcash_client_backend/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ and this library adheres to Rust's notion of
220220
- The fields of `ReceivedSaplingNote` are now private. Use
221221
`ReceivedSaplingNote::from_parts` for construction instead. Accessor methods
222222
are provided for each previously public field.
223+
- The address variants of `Recipient` now `Box` their contents to avoid large
224+
discrepancies in enum variant sizing.
223225
- `zcash_client_backend::scanning::ScanError` has a new variant, `TreeSizeInvalid`.
224226
- `zcash_client_backend::zip321::TransactionRequest::payments` now returns a
225227
`BTreeMap<usize, Payment>` instead of `&[Payment]` so that parameter

zcash_client_backend/src/data_api/wallet.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ where
775775
.expect("Payment step references are checked at construction")
776776
.recipient_address
777777
{
778-
Address::Transparent(t) => Some(t),
778+
Address::Transparent(t) => Some(t.as_ref()),
779779
Address::Unified(uaddr) => uaddr.transparent(),
780780
_ => None,
781781
}
@@ -849,8 +849,12 @@ where
849849
.memo
850850
.as_ref()
851851
.map_or_else(MemoBytes::empty, |m| m.clone());
852-
builder.add_sapling_output(external_ovk, *addr, payment.amount, memo.clone())?;
853-
sapling_output_meta.push((Recipient::Sapling(*addr), payment.amount, Some(memo)));
852+
builder.add_sapling_output(external_ovk, **addr, payment.amount, memo.clone())?;
853+
sapling_output_meta.push((
854+
Recipient::Sapling(addr.clone()),
855+
payment.amount,
856+
Some(memo),
857+
));
854858
}
855859
Address::Transparent(to) => {
856860
if payment.memo.is_some() {
@@ -950,7 +954,7 @@ where
950954

951955
SentTransactionOutput::from_parts(
952956
output_index,
953-
Recipient::Transparent(*addr),
957+
Recipient::Transparent(addr.clone()),
954958
value,
955959
None,
956960
None,

zcash_client_backend/src/data_api/wallet/input_selection.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ where
381381
}
382382

383383
return Err(InputSelectorError::Selection(
384-
GreedyInputSelectorError::UnsupportedAddress(Box::new(addr.clone())),
384+
GreedyInputSelectorError::UnsupportedAddress(addr.clone()),
385385
));
386386
}
387387
}

zcash_client_backend/src/wallet.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ impl NoteId {
6666
/// output.
6767
#[derive(Debug, Clone)]
6868
pub enum Recipient {
69-
Transparent(TransparentAddress),
70-
Sapling(sapling::PaymentAddress),
71-
Unified(UnifiedAddress, PoolType),
69+
Transparent(Box<TransparentAddress>),
70+
Sapling(Box<sapling::PaymentAddress>),
71+
Unified(Box<UnifiedAddress>, PoolType),
7272
InternalAccount(AccountId, PoolType),
7373
}
7474

zcash_client_backend/src/zip321.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,7 @@ mod tests {
891891
let expected = TransactionRequest::new(
892892
vec![
893893
Payment {
894-
recipient_address: Address::Sapling(decode_payment_address(TEST_NETWORK.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap()),
894+
recipient_address: Address::from(decode_payment_address(TEST_NETWORK.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap()),
895895
amount: NonNegativeAmount::const_from_u64(376876902796286),
896896
memo: None,
897897
label: None,
@@ -912,7 +912,7 @@ mod tests {
912912
let expected = TransactionRequest::new(
913913
vec![
914914
Payment {
915-
recipient_address: Address::Sapling(decode_payment_address(TEST_NETWORK.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap()),
915+
recipient_address: Address::from(decode_payment_address(TEST_NETWORK.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap()),
916916
amount: NonNegativeAmount::ZERO,
917917
memo: None,
918918
label: None,
@@ -930,7 +930,7 @@ mod tests {
930930
let req = TransactionRequest::new(
931931
vec![
932932
Payment {
933-
recipient_address: Address::Sapling(decode_payment_address(TEST_NETWORK.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap()),
933+
recipient_address: Address::from(decode_payment_address(TEST_NETWORK.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap()),
934934
amount: NonNegativeAmount::ZERO,
935935
memo: None,
936936
label: None,

zcash_client_sqlite/src/chain.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ mod tests {
520520

521521
// We can spend the received notes
522522
let req = TransactionRequest::new(vec![Payment {
523-
recipient_address: Address::Sapling(dfvk.default_address().1),
523+
recipient_address: Address::from(dfvk.default_address().1),
524524
amount: NonNegativeAmount::const_from_u64(110_000),
525525
memo: None,
526526
label: None,

zcash_client_sqlite/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ impl<P: consensus::Parameters> WalletWrite for WalletDb<rusqlite::Connection, P>
589589
match output.transfer_type {
590590
TransferType::Outgoing | TransferType::WalletInternal => {
591591
let recipient = if output.transfer_type == TransferType::Outgoing {
592-
Recipient::Sapling(output.note.recipient())
592+
Recipient::Sapling(Box::new(output.note.recipient()))
593593
} else {
594594
Recipient::InternalAccount(
595595
output.account,
@@ -658,7 +658,7 @@ impl<P: consensus::Parameters> WalletWrite for WalletDb<rusqlite::Connection, P>
658658
*account_id,
659659
tx_ref,
660660
output_index,
661-
&Recipient::Transparent(address),
661+
&Recipient::Transparent(Box::new(address)),
662662
txout.value,
663663
None
664664
)?;

zcash_client_sqlite/src/wallet.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ pub(crate) fn get_current_address<P: consensus::Parameters>(
298298
SqliteClientError::CorruptedData("Not a valid Zcash recipient address".to_owned())
299299
})
300300
.and_then(|addr| match addr {
301-
Address::Unified(ua) => Ok(ua),
301+
Address::Unified(ua) => Ok(*ua),
302302
_ => Err(SqliteClientError::CorruptedData(format!(
303303
"Addresses table contains {} which is not a unified address",
304304
addr_str,

zcash_client_sqlite/src/wallet/init.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1008,7 +1008,7 @@ mod tests {
10081008

10091009
let ufvk_str = ufvk.encode(&wdb.params);
10101010
let address_str =
1011-
Address::Unified(ufvk.default_address(DEFAULT_UA_REQUEST).0).encode(&wdb.params);
1011+
Address::from(ufvk.default_address(DEFAULT_UA_REQUEST).0).encode(&wdb.params);
10121012
wdb.conn.execute(
10131013
"INSERT INTO accounts (account, ufvk, address, transparent_address)
10141014
VALUES (?, ?, ?, '')",
@@ -1022,7 +1022,7 @@ mod tests {
10221022
// add a transparent "sent note"
10231023
#[cfg(feature = "transparent-inputs")]
10241024
{
1025-
let taddr = Address::Transparent(
1025+
let taddr = Address::from(
10261026
*ufvk
10271027
.default_address(DEFAULT_UA_REQUEST)
10281028
.0

zcash_client_sqlite/src/wallet/init/migrations/addresses_table.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
8282
))
8383
})?;
8484
let decoded_address = if let Address::Unified(ua) = decoded {
85-
ua
85+
*ua
8686
} else {
8787
return Err(WalletMigrationError::CorruptedData(
8888
"Address in accounts table was not a Unified Address.".to_string(),
@@ -95,7 +95,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
9595
return Err(WalletMigrationError::CorruptedData(format!(
9696
"Decoded UA {} does not match the UFVK's default address {} at {:?}.",
9797
address,
98-
Address::Unified(expected_address).encode(&self.params),
98+
Address::from(expected_address).encode(&self.params),
9999
idx,
100100
)));
101101
}
@@ -113,7 +113,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
113113
let decoded_transparent_address = if let Address::Transparent(addr) =
114114
decoded_transparent
115115
{
116-
addr
116+
*addr
117117
} else {
118118
return Err(WalletMigrationError::CorruptedData(
119119
"Address in transparent_address column of accounts table was not a transparent address.".to_string(),

zcash_client_sqlite/src/wallet/init/migrations/receiving_key_scopes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ mod tests {
500500
match output.transfer_type {
501501
TransferType::Outgoing | TransferType::WalletInternal => {
502502
let recipient = if output.transfer_type == TransferType::Outgoing {
503-
Recipient::Sapling(output.note.recipient())
503+
Recipient::Sapling(Box::new(output.note.recipient()))
504504
} else {
505505
Recipient::InternalAccount(
506506
output.account,

zcash_client_sqlite/src/wallet/init/migrations/ufvk_support.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
9898
"Derivation should have produced a UFVK containing a Sapling component.",
9999
);
100100
let (idx, expected_address) = dfvk.default_address();
101-
if decoded_address != expected_address {
101+
if *decoded_address != expected_address {
102102
return Err(WalletMigrationError::CorruptedData(
103103
format!("Decoded Sapling address {} does not match the ufvk's Sapling address {} at {:?}.",
104104
address,
105-
Address::Sapling(expected_address).encode(&self.params),
105+
Address::from(expected_address).encode(&self.params),
106106
idx)));
107107
}
108108
}
@@ -112,11 +112,11 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
112112
}
113113
Address::Unified(decoded_address) => {
114114
let (expected_address, idx) = ufvk.default_address(ua_request);
115-
if decoded_address != expected_address {
115+
if *decoded_address != expected_address {
116116
return Err(WalletMigrationError::CorruptedData(
117117
format!("Decoded unified address {} does not match the ufvk's default address {} at {:?}.",
118118
address,
119-
Address::Unified(expected_address).encode(&self.params),
119+
Address::from(expected_address).encode(&self.params),
120120
idx)));
121121
}
122122
}

zcash_client_sqlite/src/wallet/sapling.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@ pub(crate) mod tests {
718718
// spends the first step's output.
719719

720720
// The first step will deshield to the wallet's default transparent address
721-
let to0 = Address::Transparent(usk.default_transparent_address().0);
721+
let to0 = Address::Transparent(Box::new(usk.default_transparent_address().0));
722722
let request0 = zip321::TransactionRequest::new(vec![Payment {
723723
recipient_address: to0,
724724
amount: NonNegativeAmount::const_from_u64(50000),
@@ -754,14 +754,14 @@ pub(crate) mod tests {
754754

755755
// We'll use an internal transparent address that hasn't been added to the wallet
756756
// to simulate an external transparent recipient.
757-
let to1 = Address::Transparent(
757+
let to1 = Address::Transparent(Box::new(
758758
usk.transparent()
759759
.to_account_pubkey()
760760
.derive_internal_ivk()
761761
.unwrap()
762762
.default_address()
763763
.0,
764-
);
764+
));
765765
let request1 = zip321::TransactionRequest::new(vec![Payment {
766766
recipient_address: to1,
767767
amount: NonNegativeAmount::const_from_u64(40000),
@@ -1433,7 +1433,7 @@ pub(crate) mod tests {
14331433
let req = TransactionRequest::new(vec![
14341434
// payment to an external recipient
14351435
Payment {
1436-
recipient_address: Address::Sapling(addr2),
1436+
recipient_address: Address::from(addr2),
14371437
amount: amount_sent,
14381438
memo: None,
14391439
label: None,
@@ -1442,7 +1442,7 @@ pub(crate) mod tests {
14421442
},
14431443
// payment back to the originating wallet, simulating legacy change
14441444
Payment {
1445-
recipient_address: Address::Sapling(addr),
1445+
recipient_address: Address::from(addr),
14461446
amount: amount_legacy_change,
14471447
memo: None,
14481448
label: None,
@@ -1556,7 +1556,7 @@ pub(crate) mod tests {
15561556

15571557
// This first request will fail due to insufficient non-dust funds
15581558
let req = TransactionRequest::new(vec![Payment {
1559-
recipient_address: Address::Sapling(dfvk.default_address().1),
1559+
recipient_address: Address::from(dfvk.default_address().1),
15601560
amount: NonNegativeAmount::const_from_u64(50000),
15611561
memo: None,
15621562
label: None,
@@ -1581,7 +1581,7 @@ pub(crate) mod tests {
15811581
// This request will succeed, spending a single dust input to pay the 10000
15821582
// ZAT fee in addition to the 41000 ZAT output to the recipient
15831583
let req = TransactionRequest::new(vec![Payment {
1584-
recipient_address: Address::Sapling(dfvk.default_address().1),
1584+
recipient_address: Address::from(dfvk.default_address().1),
15851585
amount: NonNegativeAmount::const_from_u64(41000),
15861586
memo: None,
15871587
label: None,

zcash_keys/CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ The entries below are relative to the `zcash_client_backend` crate as of
2424

2525
### Changed
2626
- `zcash_keys::address`:
27-
- `RecipientAddress` has been renamed to `Address`
27+
- `RecipientAddress` has been renamed to `Address`. Also, each variant now
28+
`Box`es its contents to avoid large discrepancies in enum variant sizing.
2829
- `Address::Shielded` has been renamed to `Address::Sapling`
2930
- `UnifiedAddress::from_receivers` has been renamed to `UnifiedAddress::new`.
3031
It no longer takes an Orchard receiver argument unless the `orchard` feature

zcash_keys/src/address.rs

+14-17
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,7 @@ impl UnifiedAddress {
234234
self.expiry_height
235235
.map(|h| unified::MetadataItem::ExpiryHeight(u32::from(h))),
236236
)
237-
.chain(
238-
self.expiry_time
239-
.map(unified::MetadataItem::ExpiryTime),
240-
)
237+
.chain(self.expiry_time.map(unified::MetadataItem::ExpiryTime))
241238
.map(Item::Metadata);
242239

243240
data_items.chain(meta_items).collect()
@@ -250,26 +247,26 @@ impl UnifiedAddress {
250247
/// An address that funds can be sent to.
251248
#[derive(Debug, PartialEq, Eq, Clone)]
252249
pub enum Address {
253-
Sapling(PaymentAddress),
254-
Transparent(TransparentAddress),
255-
Unified(UnifiedAddress),
250+
Sapling(Box<PaymentAddress>),
251+
Transparent(Box<TransparentAddress>),
252+
Unified(Box<UnifiedAddress>),
256253
}
257254

258255
impl From<PaymentAddress> for Address {
259256
fn from(addr: PaymentAddress) -> Self {
260-
Address::Sapling(addr)
257+
Address::Sapling(Box::new(addr))
261258
}
262259
}
263260

264261
impl From<TransparentAddress> for Address {
265262
fn from(addr: TransparentAddress) -> Self {
266-
Address::Transparent(addr)
263+
Address::Transparent(Box::new(addr))
267264
}
268265
}
269266

270267
impl From<UnifiedAddress> for Address {
271268
fn from(addr: UnifiedAddress) -> Self {
272-
Address::Unified(addr)
269+
Address::Unified(Box::new(addr))
273270
}
274271
}
275272

@@ -312,12 +309,12 @@ impl Address {
312309

313310
match self {
314311
Address::Sapling(pa) => ZcashAddress::from_sapling(net, pa.to_bytes()),
315-
Address::Transparent(addr) => match addr {
312+
Address::Transparent(addr) => match **addr {
316313
TransparentAddress::PublicKeyHash(data) => {
317-
ZcashAddress::from_transparent_p2pkh(net, *data)
314+
ZcashAddress::from_transparent_p2pkh(net, data)
318315
}
319316
TransparentAddress::ScriptHash(data) => {
320-
ZcashAddress::from_transparent_p2sh(net, *data)
317+
ZcashAddress::from_transparent_p2sh(net, data)
321318
}
322319
},
323320
Address::Unified(ua) => ua.to_address(net),
@@ -345,9 +342,9 @@ pub mod testing {
345342

346343
pub fn arb_addr(request: UnifiedAddressRequest) -> impl Strategy<Value = Address> {
347344
prop_oneof![
348-
arb_payment_address().prop_map(Address::Sapling),
349-
arb_transparent_addr().prop_map(Address::Transparent),
350-
arb_unified_addr(Network::TestNetwork, request).prop_map(Address::Unified),
345+
arb_payment_address().prop_map(Address::from),
346+
arb_transparent_addr().prop_map(Address::from),
347+
arb_unified_addr(Network::TestNetwork, request).prop_map(Address::from),
351348
]
352349
}
353350
}
@@ -384,7 +381,7 @@ mod tests {
384381
#[cfg(not(feature = "orchard"))]
385382
let ua = UnifiedAddress::new(sapling, transparent, None, None).unwrap();
386383

387-
let addr = Address::Unified(ua);
384+
let addr = Address::from(ua);
388385
let addr_str = addr.encode(&MAIN_NETWORK);
389386
assert_eq!(Address::decode(&MAIN_NETWORK, &addr_str), Some(addr));
390387
}

zcash_keys/src/keys.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -646,10 +646,7 @@ impl UnifiedFullViewingKey {
646646
self.expiry_height
647647
.map(|h| unified::MetadataItem::ExpiryHeight(u32::from(h))),
648648
)
649-
.chain(
650-
self.expiry_time
651-
.map(unified::MetadataItem::ExpiryTime),
652-
);
649+
.chain(self.expiry_time.map(unified::MetadataItem::ExpiryTime));
653650

654651
let ufvk = unified::Ufvk::try_from_items(
655652
data_items

0 commit comments

Comments
 (0)