@@ -200,7 +200,7 @@ pub struct ExplicitSigningPubkey {}
200200/// [`Bolt12Invoice::signing_pubkey`] was derived.
201201///
202202/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
203- pub struct DerivedSigningPubkey ( Keypair ) ;
203+ pub struct DerivedSigningPubkey ( pub ( super ) Keypair ) ;
204204
205205impl SigningPubkeyStrategy for ExplicitSigningPubkey { }
206206impl SigningPubkeyStrategy for DerivedSigningPubkey { }
@@ -958,14 +958,7 @@ impl InvoiceContents {
958958
959959 #[ cfg( feature = "std" ) ]
960960 fn is_expired ( & self ) -> bool {
961- let absolute_expiry = self . created_at ( ) . checked_add ( self . relative_expiry ( ) ) ;
962- match absolute_expiry {
963- Some ( seconds_from_epoch) => match SystemTime :: UNIX_EPOCH . elapsed ( ) {
964- Ok ( elapsed) => elapsed > seconds_from_epoch,
965- Err ( _) => false ,
966- } ,
967- None => false ,
968- }
961+ is_expired ( self . created_at ( ) , self . relative_expiry ( ) )
969962 }
970963
971964 fn payment_hash ( & self ) -> PaymentHash {
@@ -977,36 +970,9 @@ impl InvoiceContents {
977970 }
978971
979972 fn fallbacks ( & self ) -> Vec < Address > {
980- let chain = self . chain ( ) ;
981- let network = if chain == ChainHash :: using_genesis_block ( Network :: Bitcoin ) {
982- Network :: Bitcoin
983- } else if chain == ChainHash :: using_genesis_block ( Network :: Testnet ) {
984- Network :: Testnet
985- } else if chain == ChainHash :: using_genesis_block ( Network :: Signet ) {
986- Network :: Signet
987- } else if chain == ChainHash :: using_genesis_block ( Network :: Regtest ) {
988- Network :: Regtest
989- } else {
990- return Vec :: new ( )
991- } ;
992-
993- let to_valid_address = |address : & FallbackAddress | {
994- let version = match WitnessVersion :: try_from ( address. version ) {
995- Ok ( version) => version,
996- Err ( _) => return None ,
997- } ;
998-
999- let program = address. program . clone ( ) ;
1000- let witness_program = match WitnessProgram :: new ( version, program) {
1001- Ok ( witness_program) => witness_program,
1002- Err ( _) => return None ,
1003- } ;
1004- Some ( Address :: new ( network, Payload :: WitnessProgram ( witness_program) ) )
1005- } ;
1006-
1007973 self . fields ( ) . fallbacks
1008974 . as_ref ( )
1009- . map ( |fallbacks| fallbacks . iter ( ) . filter_map ( to_valid_address ) . collect ( ) )
975+ . map ( |fallbacks| filter_fallbacks ( self . chain ( ) , fallbacks ) )
1010976 . unwrap_or_else ( Vec :: new)
1011977 }
1012978
@@ -1075,6 +1041,50 @@ impl InvoiceContents {
10751041 }
10761042}
10771043
1044+ #[ cfg( feature = "std" ) ]
1045+ pub ( super ) fn is_expired ( created_at : Duration , relative_expiry : Duration ) -> bool {
1046+ let absolute_expiry = created_at. checked_add ( relative_expiry) ;
1047+ match absolute_expiry {
1048+ Some ( seconds_from_epoch) => match SystemTime :: UNIX_EPOCH . elapsed ( ) {
1049+ Ok ( elapsed) => elapsed > seconds_from_epoch,
1050+ Err ( _) => false ,
1051+ } ,
1052+ None => false ,
1053+ }
1054+ }
1055+
1056+ pub ( super ) fn filter_fallbacks (
1057+ chain : ChainHash , fallbacks : & Vec < FallbackAddress >
1058+ ) -> Vec < Address > {
1059+ let network = if chain == ChainHash :: using_genesis_block ( Network :: Bitcoin ) {
1060+ Network :: Bitcoin
1061+ } else if chain == ChainHash :: using_genesis_block ( Network :: Testnet ) {
1062+ Network :: Testnet
1063+ } else if chain == ChainHash :: using_genesis_block ( Network :: Signet ) {
1064+ Network :: Signet
1065+ } else if chain == ChainHash :: using_genesis_block ( Network :: Regtest ) {
1066+ Network :: Regtest
1067+ } else {
1068+ return Vec :: new ( )
1069+ } ;
1070+
1071+ let to_valid_address = |address : & FallbackAddress | {
1072+ let version = match WitnessVersion :: try_from ( address. version ) {
1073+ Ok ( version) => version,
1074+ Err ( _) => return None ,
1075+ } ;
1076+
1077+ let program = address. program . clone ( ) ;
1078+ let witness_program = match WitnessProgram :: new ( version, program) {
1079+ Ok ( witness_program) => witness_program,
1080+ Err ( _) => return None ,
1081+ } ;
1082+ Some ( Address :: new ( network, Payload :: WitnessProgram ( witness_program) ) )
1083+ } ;
1084+
1085+ fallbacks. iter ( ) . filter_map ( to_valid_address) . collect ( )
1086+ }
1087+
10781088impl InvoiceFields {
10791089 fn as_tlv_stream ( & self ) -> InvoiceTlvStreamRef {
10801090 let features = {
@@ -1154,12 +1164,12 @@ tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef, 160..240, {
11541164 ( 176 , node_id: PublicKey ) ,
11551165} ) ;
11561166
1157- type BlindedPathIter < ' a > = core:: iter:: Map <
1167+ pub ( super ) type BlindedPathIter < ' a > = core:: iter:: Map <
11581168 core:: slice:: Iter < ' a , ( BlindedPayInfo , BlindedPath ) > ,
11591169 for <' r > fn ( & ' r ( BlindedPayInfo , BlindedPath ) ) -> & ' r BlindedPath ,
11601170> ;
11611171
1162- type BlindedPayInfoIter < ' a > = core:: iter:: Map <
1172+ pub ( super ) type BlindedPayInfoIter < ' a > = core:: iter:: Map <
11631173 core:: slice:: Iter < ' a , ( BlindedPayInfo , BlindedPath ) > ,
11641174 for <' r > fn ( & ' r ( BlindedPayInfo , BlindedPath ) ) -> & ' r BlindedPayInfo ,
11651175> ;
@@ -1205,8 +1215,8 @@ impl_writeable!(BlindedPayInfo, {
12051215/// Wire representation for an on-chain fallback address.
12061216#[ derive( Clone , Debug , PartialEq ) ]
12071217pub ( super ) struct FallbackAddress {
1208- version : u8 ,
1209- program : Vec < u8 > ,
1218+ pub ( super ) version : u8 ,
1219+ pub ( super ) program : Vec < u8 > ,
12101220}
12111221
12121222impl_writeable ! ( FallbackAddress , { version, program } ) ;
@@ -1294,17 +1304,7 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
12941304 } ,
12951305 ) = tlv_stream;
12961306
1297- let payment_paths = match ( blindedpay, paths) {
1298- ( _, None ) => return Err ( Bolt12SemanticError :: MissingPaths ) ,
1299- ( None , _) => return Err ( Bolt12SemanticError :: InvalidPayInfo ) ,
1300- ( _, Some ( paths) ) if paths. is_empty ( ) => return Err ( Bolt12SemanticError :: MissingPaths ) ,
1301- ( Some ( blindedpay) , Some ( paths) ) if paths. len ( ) != blindedpay. len ( ) => {
1302- return Err ( Bolt12SemanticError :: InvalidPayInfo ) ;
1303- } ,
1304- ( Some ( blindedpay) , Some ( paths) ) => {
1305- blindedpay. into_iter ( ) . zip ( paths. into_iter ( ) ) . collect :: < Vec < _ > > ( )
1306- } ,
1307- } ;
1307+ let payment_paths = construct_payment_paths ( blindedpay, paths) ?;
13081308
13091309 let created_at = match created_at {
13101310 None => return Err ( Bolt12SemanticError :: MissingCreationTime ) ,
@@ -1372,6 +1372,22 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
13721372 }
13731373}
13741374
1375+ pub ( super ) fn construct_payment_paths (
1376+ blinded_payinfos : Option < Vec < BlindedPayInfo > > , blinded_paths : Option < Vec < BlindedPath > >
1377+ ) -> Result < Vec < ( BlindedPayInfo , BlindedPath ) > , Bolt12SemanticError > {
1378+ match ( blinded_payinfos, blinded_paths) {
1379+ ( _, None ) => Err ( Bolt12SemanticError :: MissingPaths ) ,
1380+ ( None , _) => Err ( Bolt12SemanticError :: InvalidPayInfo ) ,
1381+ ( _, Some ( paths) ) if paths. is_empty ( ) => Err ( Bolt12SemanticError :: MissingPaths ) ,
1382+ ( Some ( blindedpay) , Some ( paths) ) if paths. len ( ) != blindedpay. len ( ) => {
1383+ Err ( Bolt12SemanticError :: InvalidPayInfo )
1384+ } ,
1385+ ( Some ( blindedpay) , Some ( paths) ) => {
1386+ Ok ( blindedpay. into_iter ( ) . zip ( paths. into_iter ( ) ) . collect :: < Vec < _ > > ( ) )
1387+ } ,
1388+ }
1389+ }
1390+
13751391#[ cfg( test) ]
13761392mod tests {
13771393 use super :: { Bolt12Invoice , DEFAULT_RELATIVE_EXPIRY , FallbackAddress , FullInvoiceTlvStreamRef , InvoiceTlvStreamRef , SIGNATURE_TAG , UnsignedBolt12Invoice } ;
0 commit comments