message_paths: None,
},
SignatureTlvStreamRef { signature: Some(&invoice.signature()) },
- ExperimentalOfferTlvStreamRef {},
+ ExperimentalOfferTlvStreamRef {
+ experimental_foo: None,
+ },
),
);
message_paths: None,
},
SignatureTlvStreamRef { signature: Some(&invoice.signature()) },
- ExperimentalOfferTlvStreamRef {},
+ ExperimentalOfferTlvStreamRef {
+ experimental_foo: None,
+ },
),
);
let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
.amount_msats(1000)
.path(blinded_path)
+ .experimental_foo(42)
.build().unwrap();
let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap()
let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
.amount_msats(1000)
// Omit the path so that node_id is used for the signing pubkey instead of deriving it
+ .experimental_foo(42)
.build().unwrap();
let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap()
let secp_ctx = Secp256k1::new();
let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap()
+ .experimental_foo(42)
.build().unwrap();
if let Err(e) = refund
paths: None,
},
SignatureTlvStreamRef { signature: Some(&invoice_request.signature()) },
- ExperimentalOfferTlvStreamRef {},
+ ExperimentalOfferTlvStreamRef {
+ experimental_foo: None,
+ },
),
);
let offer = OfferBuilder::new(recipient_pubkey())
.amount_msats(1000)
+ .experimental_foo(42)
.build().unwrap();
let invoice_request = offer
.request_invoice_deriving_metadata(signing_pubkey, &expanded_key, nonce, payment_id)
let offer = OfferBuilder::new(recipient_pubkey())
.amount_msats(1000)
+ .experimental_foo(42)
.build().unwrap();
let invoice_request = offer
.request_invoice_deriving_signing_pubkey(&expanded_key, nonce, &secp_ctx, payment_id)
chains: None, metadata: None, amount: None, description: None,
features: OfferFeatures::empty(), absolute_expiry: None, issuer: None, paths: None,
supported_quantity: Quantity::One, issuer_signing_pubkey: Some(signing_pubkey),
+ #[cfg(test)]
+ experimental_foo: None,
},
metadata_strategy: core::marker::PhantomData,
secp_ctx: None,
chains: None, metadata: Some(metadata), amount: None, description: None,
features: OfferFeatures::empty(), absolute_expiry: None, issuer: None, paths: None,
supported_quantity: Quantity::One, issuer_signing_pubkey: Some(node_id),
+ #[cfg(test)]
+ experimental_foo: None,
},
metadata_strategy: core::marker::PhantomData,
secp_ctx: Some(secp_ctx),
$return_value
}
+ #[cfg_attr(c_bindings, allow(dead_code))]
+ pub(super) fn experimental_foo($($self_mut)* $self: $self_type, experimental_foo: u64) -> $return_type {
+ $self.offer.experimental_foo = Some(experimental_foo);
+ $return_value
+ }
+
#[cfg_attr(c_bindings, allow(dead_code))]
pub(super) fn build_unchecked($self: $self_type) -> Offer {
$self.build_without_checks()
paths: Option<Vec<BlindedMessagePath>>,
supported_quantity: Quantity,
issuer_signing_pubkey: Option<PublicKey>,
+ #[cfg(test)]
+ experimental_foo: Option<u64>,
}
macro_rules! offer_accessors { ($self: ident, $contents: expr) => {
issuer_id: self.issuer_signing_pubkey.as_ref(),
};
- let experimental_offer = ExperimentalOfferTlvStreamRef {};
+ let experimental_offer = ExperimentalOfferTlvStreamRef {
+ #[cfg(test)]
+ experimental_foo: self.experimental_foo,
+ };
(offer, experimental_offer)
}
/// Valid type range for experimental offer TLV records.
pub(super) const EXPERIMENTAL_OFFER_TYPES: core::ops::Range<u64> = 1_000_000_000..2_000_000_000;
+#[cfg(not(test))]
tlv_stream!(ExperimentalOfferTlvStream, ExperimentalOfferTlvStreamRef, EXPERIMENTAL_OFFER_TYPES, {
});
+#[cfg(test)]
+tlv_stream!(ExperimentalOfferTlvStream, ExperimentalOfferTlvStreamRef, EXPERIMENTAL_OFFER_TYPES, {
+ (1_999_999_999, experimental_foo: (u64, HighZeroBytesDroppedBigSize)),
+});
+
type FullOfferTlvStream = (OfferTlvStream, ExperimentalOfferTlvStream);
type FullOfferTlvStreamRef<'a> = (OfferTlvStreamRef<'a>, ExperimentalOfferTlvStreamRef);
chains, metadata, currency, amount, description, features, absolute_expiry, paths,
issuer, quantity_max, issuer_id,
},
- ExperimentalOfferTlvStream {},
+ ExperimentalOfferTlvStream {
+ #[cfg(test)]
+ experimental_foo,
+ },
) = tlv_stream;
let metadata = metadata.map(|metadata| Metadata::Bytes(metadata));
Ok(OfferContents {
chains, metadata, amount, description, features, absolute_expiry, issuer, paths,
supported_quantity, issuer_signing_pubkey,
+ #[cfg(test)]
+ experimental_foo,
})
}
}
quantity_max: None,
issuer_id: Some(&pubkey(42)),
},
- ExperimentalOfferTlvStreamRef {},
+ ExperimentalOfferTlvStreamRef {
+ experimental_foo: None,
+ },
),
);
use super::OfferWithDerivedMetadataBuilder as OfferBuilder;
let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
.amount_msats(1000)
+ .experimental_foo(42)
.build().unwrap();
assert!(offer.metadata().is_some());
assert_eq!(offer.issuer_signing_pubkey(), Some(node_id));
let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
.amount_msats(1000)
.path(blinded_path)
+ .experimental_foo(42)
.build().unwrap();
assert!(offer.metadata().is_none());
assert_ne!(offer.issuer_signing_pubkey(), Some(node_id));
payer: PayerContents(metadata), description: String::new(), absolute_expiry: None,
issuer: None, chain: None, amount_msats, features: InvoiceRequestFeatures::empty(),
quantity: None, payer_signing_pubkey: signing_pubkey, payer_note: None, paths: None,
+ #[cfg(test)]
+ experimental_foo: None,
},
secp_ctx: None,
})
payer: PayerContents(metadata), description: String::new(), absolute_expiry: None,
issuer: None, chain: None, amount_msats, features: InvoiceRequestFeatures::empty(),
quantity: None, payer_signing_pubkey: node_id, payer_note: None, paths: None,
+ #[cfg(test)]
+ experimental_foo: None,
},
secp_ctx: Some(secp_ctx),
})
$self.refund.features = features;
$return_value
}
+
+ #[cfg_attr(c_bindings, allow(dead_code))]
+ pub(super) fn experimental_foo($($self_mut)* $self: $self_type, experimental_foo: u64) -> $return_type {
+ $self.refund.experimental_foo = Some(experimental_foo);
+ $return_value
+ }
} }
impl<'a> RefundBuilder<'a, secp256k1::SignOnly> {
payer_signing_pubkey: PublicKey,
payer_note: Option<String>,
paths: Option<Vec<BlindedMessagePath>>,
+ #[cfg(test)]
+ experimental_foo: Option<u64>,
}
impl Refund {
paths: self.paths.as_ref(),
};
- let experimental_offer = ExperimentalOfferTlvStreamRef {};
+ let experimental_offer = ExperimentalOfferTlvStreamRef {
+ #[cfg(test)]
+ experimental_foo: self.experimental_foo,
+ };
(payer, offer, invoice_request, experimental_offer)
}
InvoiceRequestTlvStream {
chain, amount, features, quantity, payer_id, payer_note, paths
},
- _experimental_offer_tlv_stream,
+ ExperimentalOfferTlvStream {
+ #[cfg(test)]
+ experimental_foo,
+ },
) = tlv_stream;
let payer = match payer_metadata {
Ok(RefundContents {
payer, description, absolute_expiry, issuer, chain, amount_msats, features, quantity,
payer_signing_pubkey, payer_note, paths,
+ #[cfg(test)]
+ experimental_foo,
})
}
}
payer_note: None,
paths: None,
},
- ExperimentalOfferTlvStreamRef {},
+ ExperimentalOfferTlvStreamRef {
+ experimental_foo: None,
+ },
),
);
let refund = RefundBuilder
::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx, 1000, payment_id)
.unwrap()
+ .experimental_foo(42)
.build().unwrap();
assert_eq!(refund.payer_signing_pubkey(), node_id);
::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx, 1000, payment_id)
.unwrap()
.path(blinded_path)
+ .experimental_foo(42)
.build().unwrap();
assert_ne!(refund.payer_signing_pubkey(), node_id);
message_paths: Some(&paths),
},
SignatureTlvStreamRef { signature: Some(&invoice.signature()) },
- ExperimentalOfferTlvStreamRef {},
+ ExperimentalOfferTlvStreamRef { experimental_foo: None },
)
);
}
}
+ #[test]
+ fn builds_invoice_from_offer_using_derived_key() {
+ let node_id = recipient_pubkey();
+ let now = now();
+ let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
+ let entropy = FixedEntropy {};
+ let nonce = Nonce::from_entropy_source(&entropy);
+ let secp_ctx = Secp256k1::new();
+
+ let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
+ .path(blinded_path())
+ .experimental_foo(42)
+ .build()
+ .unwrap();
+
+ if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys(
+ &offer,
+ payment_paths(),
+ vec![blinded_path()],
+ now,
+ &expanded_key,
+ nonce,
+ &secp_ctx,
+ )
+ .unwrap()
+ .build_and_sign(&secp_ctx)
+ {
+ panic!("error building invoice: {:?}", e);
+ }
+
+ let expanded_key = ExpandedKey::new(&KeyMaterial([41; 32]));
+ if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys(
+ &offer,
+ payment_paths(),
+ vec![blinded_path()],
+ now,
+ &expanded_key,
+ nonce,
+ &secp_ctx,
+ ) {
+ assert_eq!(e, Bolt12SemanticError::InvalidMetadata);
+ } else {
+ panic!("expected error")
+ }
+ }
+
#[test]
fn fails_build_with_missing_paths() {
let node_id = recipient_pubkey();