From af915cf45c9a1c2cae7b2b72721fd7f384cbcc81 Mon Sep 17 00:00:00 2001 From: Philip Kannegaard Hayes Date: Tue, 8 Apr 2025 20:52:59 -0700 Subject: [PATCH 1/2] ln: box InvoiceContents in {Bolt12,Static}Invoice to reduce sizeof Event Reduces `mem::size_of::()` from 1680 B -> 1072 B --- lightning/src/offers/invoice.rs | 42 +++++++++++++------------- lightning/src/offers/static_invoice.rs | 14 ++++----- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 3615850a22e..be122a8b85e 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -184,7 +184,7 @@ pub const SIGNATURE_TAG: &'static str = concat!("lightning", "invoice", "signatu /// [module-level documentation]: self pub struct InvoiceBuilder<'a, S: SigningPubkeyStrategy> { invreq_bytes: &'a Vec, - invoice: InvoiceContents, + invoice: Box, signing_pubkey_strategy: S, } @@ -200,7 +200,7 @@ pub struct InvoiceBuilder<'a, S: SigningPubkeyStrategy> { #[cfg(c_bindings)] pub struct InvoiceWithExplicitSigningPubkeyBuilder<'a> { invreq_bytes: &'a Vec, - invoice: InvoiceContents, + invoice: Box, signing_pubkey_strategy: ExplicitSigningPubkey, } @@ -216,7 +216,7 @@ pub struct InvoiceWithExplicitSigningPubkeyBuilder<'a> { #[cfg(c_bindings)] pub struct InvoiceWithDerivedSigningPubkeyBuilder<'a> { invreq_bytes: &'a Vec, - invoice: InvoiceContents, + invoice: Box, signing_pubkey_strategy: DerivedSigningPubkey, } @@ -246,7 +246,7 @@ macro_rules! invoice_explicit_signing_pubkey_builder_methods { created_at: Duration, payment_hash: PaymentHash, signing_pubkey: PublicKey, ) -> Result { let amount_msats = Self::amount_msats(invoice_request)?; - let contents = InvoiceContents::ForOffer { + let contents = Box::new(InvoiceContents::ForOffer { invoice_request: invoice_request.contents.clone(), fields: Self::fields( payment_paths, @@ -255,7 +255,7 @@ macro_rules! invoice_explicit_signing_pubkey_builder_methods { amount_msats, signing_pubkey, ), - }; + }); Self::new(&invoice_request.bytes, contents, ExplicitSigningPubkey {}) } @@ -266,7 +266,7 @@ macro_rules! invoice_explicit_signing_pubkey_builder_methods { payment_hash: PaymentHash, signing_pubkey: PublicKey, ) -> Result { let amount_msats = refund.amount_msats(); - let contents = InvoiceContents::ForRefund { + let contents = Box::new(InvoiceContents::ForRefund { refund: refund.contents.clone(), fields: Self::fields( payment_paths, @@ -275,7 +275,7 @@ macro_rules! invoice_explicit_signing_pubkey_builder_methods { amount_msats, signing_pubkey, ), - }; + }); Self::new(&refund.bytes, contents, ExplicitSigningPubkey {}) } @@ -319,7 +319,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { ) -> Result { let amount_msats = Self::amount_msats(invoice_request)?; let signing_pubkey = keys.public_key(); - let contents = InvoiceContents::ForOffer { + let contents = Box::new(InvoiceContents::ForOffer { invoice_request: invoice_request.contents.clone(), fields: Self::fields( payment_paths, @@ -328,7 +328,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { amount_msats, signing_pubkey, ), - }; + }); Self::new(&invoice_request.bytes, contents, DerivedSigningPubkey(keys)) } @@ -340,7 +340,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { ) -> Result { let amount_msats = refund.amount_msats(); let signing_pubkey = keys.public_key(); - let contents = InvoiceContents::ForRefund { + let contents = Box::new(InvoiceContents::ForRefund { refund: refund.contents.clone(), fields: Self::fields( payment_paths, @@ -349,7 +349,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { amount_msats, signing_pubkey, ), - }; + }); Self::new(&refund.bytes, contents, DerivedSigningPubkey(keys)) } @@ -429,7 +429,7 @@ macro_rules! invoice_builder_methods { #[cfg_attr(c_bindings, allow(dead_code))] fn new( - invreq_bytes: &'a Vec, contents: InvoiceContents, + invreq_bytes: &'a Vec, contents: Box, signing_pubkey_strategy: $type_param, ) -> Result { if contents.fields().payment_paths.is_empty() { @@ -593,7 +593,7 @@ impl<'a> From> pub struct UnsignedBolt12Invoice { bytes: Vec, experimental_bytes: Vec, - contents: InvoiceContents, + contents: Box, tagged_hash: TaggedHash, } @@ -622,7 +622,7 @@ where } impl UnsignedBolt12Invoice { - fn new(invreq_bytes: &[u8], contents: InvoiceContents) -> Self { + fn new(invreq_bytes: &[u8], contents: Box) -> Self { // TLV record ranges applicable to invreq_bytes. const NON_EXPERIMENTAL_TYPES: core::ops::Range = 0..INVOICE_REQUEST_TYPES.end; const EXPERIMENTAL_TYPES: core::ops::Range = @@ -731,7 +731,7 @@ impl AsRef for UnsignedBolt12Invoice { #[derive(Clone, Debug)] pub struct Bolt12Invoice { bytes: Vec, - contents: InvoiceContents, + contents: Box, signature: Signature, tagged_hash: TaggedHash, } @@ -974,7 +974,7 @@ impl Bolt12Invoice { pub fn verify_using_metadata( &self, key: &ExpandedKey, secp_ctx: &Secp256k1, ) -> Result { - let (metadata, iv_bytes) = match &self.contents { + let (metadata, iv_bytes) = match &*self.contents { InvoiceContents::ForOffer { invoice_request, .. } => { (&invoice_request.inner.payer.0, INVOICE_REQUEST_IV_BYTES) }, @@ -992,7 +992,7 @@ impl Bolt12Invoice { &self, payment_id: PaymentId, nonce: Nonce, key: &ExpandedKey, secp_ctx: &Secp256k1, ) -> Result { let metadata = Metadata::payer_data(payment_id, nonce, key); - let iv_bytes = match &self.contents { + let iv_bytes = match &*self.contents { InvoiceContents::ForOffer { .. } => INVOICE_REQUEST_IV_BYTES, InvoiceContents::ForRefund { .. } => REFUND_IV_BYTES_WITHOUT_METADATA, }; @@ -1027,7 +1027,7 @@ impl Bolt12Invoice { } pub(crate) fn is_for_refund_without_paths(&self) -> bool { - match self.contents { + match &*self.contents { InvoiceContents::ForOffer { .. } => false, InvoiceContents::ForRefund { .. } => self.message_paths().is_empty(), } @@ -1422,7 +1422,7 @@ impl TryFrom> for UnsignedBolt12Invoice { fn try_from(bytes: Vec) -> Result { let invoice = ParsedMessage::::try_from(bytes)?; let ParsedMessage { mut bytes, tlv_stream } = invoice; - let contents = InvoiceContents::try_from(tlv_stream)?; + let contents = Box::new(InvoiceContents::try_from(tlv_stream)?); let tagged_hash = TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &bytes); @@ -1606,7 +1606,7 @@ impl TryFrom> for Bolt12Invoice { experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream, ) = tlv_stream; - let contents = InvoiceContents::try_from(( + let contents = Box::new(InvoiceContents::try_from(( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, @@ -1614,7 +1614,7 @@ impl TryFrom> for Bolt12Invoice { experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream, - ))?; + ))?); let signature = signature .ok_or(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature))?; diff --git a/lightning/src/offers/static_invoice.rs b/lightning/src/offers/static_invoice.rs index d48a83eb9b7..773c22b9929 100644 --- a/lightning/src/offers/static_invoice.rs +++ b/lightning/src/offers/static_invoice.rs @@ -68,7 +68,7 @@ pub const SIGNATURE_TAG: &'static str = concat!("lightning", "static_invoice", " #[derive(Clone, Debug)] pub struct StaticInvoice { bytes: Vec, - contents: InvoiceContents, + contents: Box, signature: Signature, } @@ -104,7 +104,7 @@ struct InvoiceContents { // TODO: add module-level docs and link here pub struct StaticInvoiceBuilder<'a> { offer_bytes: &'a Vec, - invoice: InvoiceContents, + invoice: Box, keys: Keypair, } @@ -141,7 +141,7 @@ impl<'a> StaticInvoiceBuilder<'a> { } let invoice = - InvoiceContents::new(offer, payment_paths, message_paths, created_at, signing_pubkey); + Box::new(InvoiceContents::new(offer, payment_paths, message_paths, created_at, signing_pubkey)); Ok(Self { offer_bytes: &offer.bytes, invoice, keys }) } @@ -190,7 +190,7 @@ impl<'a> StaticInvoiceBuilder<'a> { pub struct UnsignedStaticInvoice { bytes: Vec, experimental_bytes: Vec, - contents: InvoiceContents, + contents: Box, tagged_hash: TaggedHash, } @@ -294,7 +294,7 @@ macro_rules! invoice_accessors_signing_pubkey { } } impl UnsignedStaticInvoice { - fn new(offer_bytes: &Vec, contents: InvoiceContents) -> Self { + fn new(offer_bytes: &Vec, contents: Box) -> Self { let (_, invoice_tlv_stream, _, experimental_invoice_tlv_stream) = contents.as_tlv_stream(); const INVOICE_ALLOCATION_SIZE: usize = 1024; @@ -602,12 +602,12 @@ impl TryFrom> for StaticInvoice { experimental_offer_tlv_stream, experimental_invoice_tlv_stream, ) = tlv_stream; - let contents = InvoiceContents::try_from(( + let contents = Box::new(InvoiceContents::try_from(( offer_tlv_stream, invoice_tlv_stream, experimental_offer_tlv_stream, experimental_invoice_tlv_stream, - ))?; + ))?); let signature = match signature { None => { From ddf2296a67263e9ad8dc8050eb58102be5ed31e2 Mon Sep 17 00:00:00 2001 From: Philip Kannegaard Hayes Date: Tue, 8 Apr 2025 20:55:17 -0700 Subject: [PATCH 2/2] ln: box AnchorDescriptor in BumpTransactionEvent to reduce sizeof Event Reduces `mem::size_of::()` from 1072 B -> 576 B --- lightning/src/chain/channelmonitor.rs | 4 ++-- lightning/src/events/bump_transaction.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index f709183f2d1..6df7d7bf394 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -3544,7 +3544,7 @@ impl ChannelMonitorImpl { package_target_feerate_sat_per_1000_weight, commitment_tx, commitment_tx_fee_satoshis, - anchor_descriptor: AnchorDescriptor { + anchor_descriptor: Box::new(AnchorDescriptor { channel_derivation_parameters: ChannelDerivationParameters { keys_id: self.channel_keys_id, value_satoshis: channel_parameters.channel_value_satoshis, @@ -3554,7 +3554,7 @@ impl ChannelMonitorImpl { txid: commitment_txid, vout: anchor_output_idx, }, - }, + }), pending_htlcs: pending_nondust_htlcs, })); }, diff --git a/lightning/src/events/bump_transaction.rs b/lightning/src/events/bump_transaction.rs index a9550a67236..4c33e822211 100644 --- a/lightning/src/events/bump_transaction.rs +++ b/lightning/src/events/bump_transaction.rs @@ -167,7 +167,7 @@ pub enum BumpTransactionEvent { commitment_tx_fee_satoshis: u64, /// The descriptor to sign the anchor input of the anchor transaction constructed as a /// result of consuming this event. - anchor_descriptor: AnchorDescriptor, + anchor_descriptor: Box, /// The set of pending HTLCs on the commitment transaction that need to be resolved once the /// commitment transaction confirms. pending_htlcs: Vec, @@ -955,14 +955,14 @@ mod tests { package_target_feerate_sat_per_1000_weight: 868, commitment_tx_fee_satoshis: 930, commitment_tx, - anchor_descriptor: AnchorDescriptor { + anchor_descriptor: Box::new(AnchorDescriptor { channel_derivation_parameters: ChannelDerivationParameters { value_satoshis: 42_000_000, keys_id: [42; 32], transaction_parameters, }, outpoint: OutPoint { txid: Txid::from_byte_array([42; 32]), vout: 0 }, - }, + }), pending_htlcs: Vec::new(), }); }