@@ -148,7 +148,8 @@ impl<'a> InvoiceBuilder<'a> {
148148 Some ( amount_msats) => amount_msats,
149149 None => match invoice_request. contents . offer . amount ( ) {
150150 Some ( Amount :: Bitcoin { amount_msats } ) => {
151- amount_msats * invoice_request. quantity ( ) . unwrap_or ( 1 )
151+ amount_msats. checked_mul ( invoice_request. quantity ( ) . unwrap_or ( 1 ) )
152+ . ok_or ( SemanticError :: InvalidAmount ) ?
152153 } ,
153154 Some ( Amount :: Currency { .. } ) => return Err ( SemanticError :: UnsupportedCurrency ) ,
154155 None => return Err ( SemanticError :: MissingAmount ) ,
@@ -787,7 +788,7 @@ mod tests {
787788 use crate :: ln:: features:: { BlindedHopFeatures , Bolt12InvoiceFeatures } ;
788789 use crate :: offers:: invoice_request:: InvoiceRequestTlvStreamRef ;
789790 use crate :: offers:: merkle:: { SignError , SignatureTlvStreamRef , self } ;
790- use crate :: offers:: offer:: { OfferBuilder , OfferTlvStreamRef } ;
791+ use crate :: offers:: offer:: { OfferBuilder , OfferTlvStreamRef , Quantity } ;
791792 use crate :: offers:: parse:: { ParseError , SemanticError } ;
792793 use crate :: offers:: payer:: PayerTlvStreamRef ;
793794 use crate :: offers:: refund:: RefundBuilder ;
@@ -1177,6 +1178,38 @@ mod tests {
11771178 assert_eq ! ( tlv_stream. amount, Some ( 1001 ) ) ;
11781179 }
11791180
1181+ #[ test]
1182+ fn builds_invoice_with_quantity_from_request ( ) {
1183+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1184+ . amount_msats ( 1000 )
1185+ . supported_quantity ( Quantity :: Unbounded )
1186+ . build ( ) . unwrap ( )
1187+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1188+ . quantity ( 2 ) . unwrap ( )
1189+ . build ( ) . unwrap ( )
1190+ . sign ( payer_sign) . unwrap ( )
1191+ . respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1192+ . build ( ) . unwrap ( )
1193+ . sign ( recipient_sign) . unwrap ( ) ;
1194+ let ( _, _, _, tlv_stream, _) = invoice. as_tlv_stream ( ) ;
1195+ assert_eq ! ( invoice. amount_msats( ) , 2000 ) ;
1196+ assert_eq ! ( tlv_stream. amount, Some ( 2000 ) ) ;
1197+
1198+ match OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1199+ . amount_msats ( 1000 )
1200+ . supported_quantity ( Quantity :: Unbounded )
1201+ . build ( ) . unwrap ( )
1202+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1203+ . quantity ( u64:: max_value ( ) ) . unwrap ( )
1204+ . build_unchecked ( )
1205+ . sign ( payer_sign) . unwrap ( )
1206+ . respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) )
1207+ {
1208+ Ok ( _) => panic ! ( "expected error" ) ,
1209+ Err ( e) => assert_eq ! ( e, SemanticError :: InvalidAmount ) ,
1210+ }
1211+ }
1212+
11801213 #[ test]
11811214 fn builds_invoice_with_fallback_address ( ) {
11821215 let script = Script :: new ( ) ;
0 commit comments