Skip to content

Commit

Permalink
WIP: Static invoice building tests
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinewallace committed May 23, 2024
1 parent a3e5f42 commit dc6dff4
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
7 changes: 7 additions & 0 deletions lightning/src/offers/offer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,13 @@ impl Offer {
pub fn expects_quantity(&self) -> bool {
self.contents.expects_quantity()
}

#[cfg(test)]
pub(crate) fn verify<T: secp256k1::Signing>(
&self, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
) -> Result<(OfferId, Option<KeyPair>), ()> {
self.contents.verify(&self.bytes, key, secp_ctx)
}
}

macro_rules! request_invoice_derived_payer_id { ($self: ident, $builder: ty) => {
Expand Down
80 changes: 80 additions & 0 deletions lightning/src/offers/static_invoice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,3 +503,83 @@ impl TryFrom<(OfferTlvStream, InvoiceTlvStream)> for InvoiceContents {
})
}
}

#[cfg(test)]
mod tests {
use super::{StaticInvoiceBuilder, DEFAULT_RELATIVE_EXPIRY};

use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode};
use crate::ln::features::{Bolt12InvoiceFeatures, OfferFeatures};
use crate::ln::inbound_payment::ExpandedKey;
use crate::offers::invoice::SIGNATURE_TAG;
use crate::offers::merkle;
use crate::offers::merkle::TaggedHash;
use crate::offers::offer::{OfferBuilder, Quantity};
use crate::offers::test_utils::*;
use crate::sign::KeyMaterial;
use crate::util::ser::Writeable;
use bitcoin::blockdata::constants::ChainHash;
use bitcoin::network::constants::Network;
use bitcoin::secp256k1::Secp256k1;

#[test]
fn builds_invoice_for_offer_with_defaults() {
let node_id = recipient_pubkey();
let payment_paths = payment_paths();
let now = now();
let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
let entropy = FixedEntropy {};
let secp_ctx = Secp256k1::new();

let blinded_path = BlindedPath {
introduction_node: IntroductionNode::NodeId(pubkey(40)),
blinding_point: pubkey(41),
blinded_hops: vec![
BlindedHop { blinded_node_id: pubkey(42), encrypted_payload: vec![0; 43] },
BlindedHop { blinded_node_id: node_id, encrypted_payload: vec![0; 44] },
],
};

let offer =
OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, &entropy, &secp_ctx)
.path(blinded_path.clone())
.build()
.unwrap();

let (_offer_id, keys_opt) = offer.verify(&expanded_key, &secp_ctx).unwrap();
let invoice = StaticInvoiceBuilder::for_offer_using_keys(
&offer,
payment_paths.clone(),
now,
keys_opt.unwrap(),
)
.unwrap()
.build_and_sign(&secp_ctx)
.unwrap();

let mut buffer = Vec::new();
invoice.write(&mut buffer).unwrap();

assert_eq!(invoice.bytes, buffer.as_slice());
assert!(invoice.metadata().is_some());
assert_eq!(invoice.amount(), None);
assert_eq!(invoice.description(), None);
assert_eq!(invoice.offer_features(), &OfferFeatures::empty());
assert_eq!(invoice.absolute_expiry(), None);
assert_eq!(invoice.message_paths(), &[blinded_path]);
assert_eq!(invoice.issuer(), None);
assert_eq!(invoice.supported_quantity(), Quantity::One);
assert_ne!(invoice.signing_pubkey(), recipient_pubkey());
assert_eq!(invoice.chain(), ChainHash::using_genesis_block(Network::Bitcoin));
assert_eq!(invoice.payment_paths(), payment_paths.as_slice());
assert_eq!(invoice.created_at(), now);
assert_eq!(invoice.relative_expiry(), DEFAULT_RELATIVE_EXPIRY);
#[cfg(feature = "std")]
assert!(!invoice.is_expired());
assert_eq!(invoice.fallbacks(), vec![]);
assert_eq!(invoice.invoice_features(), &Bolt12InvoiceFeatures::empty());

let message = TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &invoice.bytes);
assert!(merkle::verify_signature(&invoice.signature, &message, keys_opt.unwrap().public_key()).is_ok());
}
}

0 comments on commit dc6dff4

Please sign in to comment.