From 03d0a4b497338b29fe9aa8c065edcfe26442e6e0 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Wed, 21 Sep 2022 22:38:11 -0500 Subject: [PATCH] Offer parsing tests Test semantic errors when parsing offer bytes. --- lightning/src/offers/offer.rs | 174 +++++++++++++++++++++++++++++++++- 1 file changed, 173 insertions(+), 1 deletion(-) diff --git a/lightning/src/offers/offer.rs b/lightning/src/offers/offer.rs index ebab6599f..e57334f31 100644 --- a/lightning/src/offers/offer.rs +++ b/lightning/src/offers/offer.rs @@ -552,7 +552,7 @@ mod tests { use core::time::Duration; use crate::ln::features::OfferFeatures; use crate::ln::msgs::MAX_VALUE_MSAT; - use crate::offers::parse::SemanticError; + use crate::offers::parse::{ParseError, SemanticError}; use crate::onion_message::{BlindedHop, BlindedPath}; use crate::util::ser::Writeable; use crate::util::string::PrintableString; @@ -831,6 +831,178 @@ mod tests { assert_eq!(offer.supported_quantity(), Quantity::one()); assert_eq!(tlv_stream.quantity_max, None); } + + #[test] + fn parses_offer_with_chains() { + let offer = OfferBuilder::new("foo".into(), pubkey(42)) + .chain(Network::Bitcoin) + .chain(Network::Testnet) + .build() + .unwrap(); + if let Err(e) = offer.to_string().parse::() { + panic!("error parsing offer: {:?}", e); + } + } + + #[test] + fn parses_offer_with_amount() { + let offer = OfferBuilder::new("foo".into(), pubkey(42)) + .amount(Amount::Bitcoin { amount_msats: 1000 }) + .build() + .unwrap(); + if let Err(e) = offer.to_string().parse::() { + panic!("error parsing offer: {:?}", e); + } + + let mut tlv_stream = offer.as_tlv_stream(); + tlv_stream.amount = Some(1000); + tlv_stream.currency = Some(b"USD"); + + let mut encoded_offer = Vec::new(); + tlv_stream.write(&mut encoded_offer).unwrap(); + + if let Err(e) = Offer::try_from(encoded_offer) { + panic!("error parsing offer: {:?}", e); + } + + let mut tlv_stream = offer.as_tlv_stream(); + tlv_stream.amount = None; + tlv_stream.currency = Some(b"USD"); + + let mut encoded_offer = Vec::new(); + tlv_stream.write(&mut encoded_offer).unwrap(); + + match Offer::try_from(encoded_offer) { + Ok(_) => panic!("expected error"), + Err(e) => assert_eq!(e, ParseError::InvalidSemantics(SemanticError::MissingAmount)), + } + + let mut tlv_stream = offer.as_tlv_stream(); + tlv_stream.amount = Some(MAX_VALUE_MSAT + 1); + tlv_stream.currency = None; + + let mut encoded_offer = Vec::new(); + tlv_stream.write(&mut encoded_offer).unwrap(); + + match Offer::try_from(encoded_offer) { + Ok(_) => panic!("expected error"), + Err(e) => assert_eq!(e, ParseError::InvalidSemantics(SemanticError::InvalidAmount)), + } + } + + #[test] + fn parses_offer_with_description() { + let offer = OfferBuilder::new("foo".into(), pubkey(42)).build().unwrap(); + if let Err(e) = offer.to_string().parse::() { + panic!("error parsing offer: {:?}", e); + } + + let mut tlv_stream = offer.as_tlv_stream(); + tlv_stream.description = None; + + let mut encoded_offer = Vec::new(); + tlv_stream.write(&mut encoded_offer).unwrap(); + + match Offer::try_from(encoded_offer) { + Ok(_) => panic!("expected error"), + Err(e) => { + assert_eq!(e, ParseError::InvalidSemantics(SemanticError::MissingDescription)); + }, + } + } + + #[test] + fn parses_offer_with_paths() { + let offer = OfferBuilder::new("foo".into(), pubkey(42)) + .path(BlindedPath { + introduction_node_id: pubkey(40), + blinding_point: pubkey(41), + blinded_hops: vec![ + BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, + BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] }, + ], + }) + .path(BlindedPath { + introduction_node_id: pubkey(40), + blinding_point: pubkey(41), + blinded_hops: vec![ + BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] }, + BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] }, + ], + }) + .build() + .unwrap(); + if let Err(e) = offer.to_string().parse::() { + panic!("error parsing offer: {:?}", e); + } + + let mut builder = OfferBuilder::new("foo".into(), pubkey(42)); + builder.offer.paths = Some(vec![]); + + let offer = builder.build().unwrap(); + if let Err(e) = offer.to_string().parse::() { + panic!("error parsing offer: {:?}", e); + } + } + + #[test] + fn parses_offer_with_quantity() { + let offer = OfferBuilder::new("foo".into(), pubkey(42)) + .supported_quantity(Quantity::one()) + .build() + .unwrap(); + if let Err(e) = offer.to_string().parse::() { + panic!("error parsing offer: {:?}", e); + } + + let offer = OfferBuilder::new("foo".into(), pubkey(42)) + .supported_quantity(Quantity::Unbounded) + .build() + .unwrap(); + if let Err(e) = offer.to_string().parse::() { + panic!("error parsing offer: {:?}", e); + } + + let offer = OfferBuilder::new("foo".into(), pubkey(42)) + .supported_quantity(Quantity::Bounded(NonZeroU64::new(10).unwrap())) + .build() + .unwrap(); + if let Err(e) = offer.to_string().parse::() { + panic!("error parsing offer: {:?}", e); + } + + let mut tlv_stream = offer.as_tlv_stream(); + tlv_stream.quantity_max = Some(1); + + let mut encoded_offer = Vec::new(); + tlv_stream.write(&mut encoded_offer).unwrap(); + + match Offer::try_from(encoded_offer) { + Ok(_) => panic!("expected error"), + Err(e) => { + assert_eq!(e, ParseError::InvalidSemantics(SemanticError::InvalidQuantity)); + }, + } + } + + #[test] + fn parses_offer_with_node_id() { + let offer = OfferBuilder::new("foo".into(), pubkey(42)).build().unwrap(); + if let Err(e) = offer.to_string().parse::() { + panic!("error parsing offer: {:?}", e); + } + + let mut builder = OfferBuilder::new("foo".into(), pubkey(42)); + builder.offer.signing_pubkey = None; + + let offer = builder.build().unwrap(); + match offer.to_string().parse::() { + Ok(_) => panic!("expected error"), + Err(e) => { + assert_eq!(e, ParseError::InvalidSemantics(SemanticError::MissingSigningPubkey)); + }, + } + } } #[cfg(test)] -- 2.39.5