@@ -859,7 +859,184 @@ where
859859 amount_msat,
860860 ) ;
861861 let payment_preimage = match purpose {
862- PaymentPurpose :: Bolt11InvoicePayment { payment_preimage, .. } => {
862+ PaymentPurpose :: Bolt11InvoicePayment {
863+ payment_preimage,
864+ payment_secret,
865+ ..
866+ } => {
867+ if payment_preimage. is_none ( ) {
868+ // This is a manual-claim (`_for_hash`) payment that was not
869+ // pre-registered in the payment store. Check metadata store for
870+ // LSP fee limits and create the store entry.
871+ let lsp_fee_limits = self
872+ . payment_metadata_store
873+ . get_lsp_fee_limits_for_payment_id ( & payment_id) ;
874+
875+ if let Some ( ref limits) = lsp_fee_limits {
876+ let max_total_opening_fee_msat = limits
877+ . max_total_opening_fee_msat
878+ . or_else ( || {
879+ limits. max_proportional_opening_fee_ppm_msat . and_then (
880+ |max_prop_fee| {
881+ compute_opening_fee ( amount_msat, 0 , max_prop_fee)
882+ } ,
883+ )
884+ } )
885+ . unwrap_or ( 0 ) ;
886+
887+ if counterparty_skimmed_fee_msat > max_total_opening_fee_msat {
888+ log_info ! (
889+ self . logger,
890+ "Refusing inbound payment with hash {} as the counterparty-withheld fee of {}msat exceeds our limit of {}msat" ,
891+ hex_utils:: to_string( & payment_hash. 0 ) ,
892+ counterparty_skimmed_fee_msat,
893+ max_total_opening_fee_msat,
894+ ) ;
895+ self . channel_manager . fail_htlc_backwards ( & payment_hash) ;
896+ return Ok ( ( ) ) ;
897+ }
898+ }
899+
900+ let kind = if lsp_fee_limits. is_some ( ) {
901+ PaymentKind :: Bolt11Jit {
902+ hash : payment_hash,
903+ preimage : None ,
904+ secret : Some ( payment_secret) ,
905+ counterparty_skimmed_fee_msat : if counterparty_skimmed_fee_msat
906+ > 0
907+ {
908+ Some ( counterparty_skimmed_fee_msat)
909+ } else {
910+ None
911+ } ,
912+ lsp_fee_limits : lsp_fee_limits. unwrap ( ) ,
913+ }
914+ } else {
915+ PaymentKind :: Bolt11 {
916+ hash : payment_hash,
917+ preimage : None ,
918+ secret : Some ( payment_secret) ,
919+ }
920+ } ;
921+
922+ let payment = PaymentDetails :: new (
923+ payment_id,
924+ kind,
925+ Some ( amount_msat) ,
926+ None ,
927+ PaymentDirection :: Inbound ,
928+ PaymentStatus :: Pending ,
929+ ) ;
930+
931+ match self . payment_store . insert ( payment) {
932+ Ok ( _) => { } ,
933+ Err ( e) => {
934+ log_error ! (
935+ self . logger,
936+ "Failed to insert payment with ID {}: {}" ,
937+ payment_id,
938+ e
939+ ) ;
940+ return Err ( ReplayEvent ( ) ) ;
941+ } ,
942+ }
943+
944+ let custom_records = onion_fields
945+ . map ( |cf| {
946+ cf. custom_tlvs ( ) . into_iter ( ) . map ( |tlv| tlv. into ( ) ) . collect ( )
947+ } )
948+ . unwrap_or_default ( ) ;
949+ let event = Event :: PaymentClaimable {
950+ payment_id,
951+ payment_hash,
952+ claimable_amount_msat : amount_msat,
953+ claim_deadline,
954+ custom_records,
955+ } ;
956+ match self . event_queue . add_event ( event) . await {
957+ Ok ( _) => return Ok ( ( ) ) ,
958+ Err ( e) => {
959+ log_error ! ( self . logger, "Failed to push to event queue: {}" , e) ;
960+ return Err ( ReplayEvent ( ) ) ;
961+ } ,
962+ } ;
963+ } else {
964+ // Auto-claim path: payment has a preimage but was not
965+ // pre-registered in the store. Check metadata store for
966+ // LSP fee limits and create the store entry before claiming.
967+ let lsp_fee_limits = self
968+ . payment_metadata_store
969+ . get_lsp_fee_limits_for_payment_id ( & payment_id) ;
970+
971+ if let Some ( ref limits) = lsp_fee_limits {
972+ let max_total_opening_fee_msat = limits
973+ . max_total_opening_fee_msat
974+ . or_else ( || {
975+ limits. max_proportional_opening_fee_ppm_msat . and_then (
976+ |max_prop_fee| {
977+ compute_opening_fee ( amount_msat, 0 , max_prop_fee)
978+ } ,
979+ )
980+ } )
981+ . unwrap_or ( 0 ) ;
982+
983+ if counterparty_skimmed_fee_msat > max_total_opening_fee_msat {
984+ log_info ! (
985+ self . logger,
986+ "Refusing inbound payment with hash {} as the counterparty-withheld fee of {}msat exceeds our limit of {}msat" ,
987+ hex_utils:: to_string( & payment_hash. 0 ) ,
988+ counterparty_skimmed_fee_msat,
989+ max_total_opening_fee_msat,
990+ ) ;
991+ self . channel_manager . fail_htlc_backwards ( & payment_hash) ;
992+ return Ok ( ( ) ) ;
993+ }
994+ }
995+
996+ let kind = if lsp_fee_limits. is_some ( ) {
997+ PaymentKind :: Bolt11Jit {
998+ hash : payment_hash,
999+ preimage : payment_preimage,
1000+ secret : Some ( payment_secret) ,
1001+ counterparty_skimmed_fee_msat : if counterparty_skimmed_fee_msat
1002+ > 0
1003+ {
1004+ Some ( counterparty_skimmed_fee_msat)
1005+ } else {
1006+ None
1007+ } ,
1008+ lsp_fee_limits : lsp_fee_limits. unwrap ( ) ,
1009+ }
1010+ } else {
1011+ PaymentKind :: Bolt11 {
1012+ hash : payment_hash,
1013+ preimage : payment_preimage,
1014+ secret : Some ( payment_secret) ,
1015+ }
1016+ } ;
1017+
1018+ let payment = PaymentDetails :: new (
1019+ payment_id,
1020+ kind,
1021+ Some ( amount_msat) ,
1022+ None ,
1023+ PaymentDirection :: Inbound ,
1024+ PaymentStatus :: Pending ,
1025+ ) ;
1026+
1027+ match self . payment_store . insert ( payment) {
1028+ Ok ( _) => { } ,
1029+ Err ( e) => {
1030+ log_error ! (
1031+ self . logger,
1032+ "Failed to insert payment with ID {}: {}" ,
1033+ payment_id,
1034+ e
1035+ ) ;
1036+ return Err ( ReplayEvent ( ) ) ;
1037+ } ,
1038+ }
1039+ }
8631040 payment_preimage
8641041 } ,
8651042 PaymentPurpose :: Bolt12OfferPayment {
@@ -998,43 +1175,85 @@ where
9981175 amount_msat,
9991176 ) ;
10001177
1001- let update = match purpose {
1178+ let ( update, kind_for_insert ) = match purpose {
10021179 PaymentPurpose :: Bolt11InvoicePayment {
10031180 payment_preimage,
10041181 payment_secret,
10051182 ..
1006- } => PaymentDetailsUpdate {
1007- preimage : Some ( payment_preimage) ,
1008- secret : Some ( Some ( payment_secret) ) ,
1009- amount_msat : Some ( Some ( amount_msat) ) ,
1010- status : Some ( PaymentStatus :: Succeeded ) ,
1011- ..PaymentDetailsUpdate :: new ( payment_id)
1183+ } => {
1184+ let kind = PaymentKind :: Bolt11 {
1185+ hash : payment_hash,
1186+ preimage : payment_preimage,
1187+ secret : Some ( payment_secret. clone ( ) ) ,
1188+ } ;
1189+ let update = PaymentDetailsUpdate {
1190+ preimage : Some ( payment_preimage) ,
1191+ secret : Some ( Some ( payment_secret) ) ,
1192+ amount_msat : Some ( Some ( amount_msat) ) ,
1193+ status : Some ( PaymentStatus :: Succeeded ) ,
1194+ ..PaymentDetailsUpdate :: new ( payment_id)
1195+ } ;
1196+ ( update, kind)
10121197 } ,
10131198 PaymentPurpose :: Bolt12OfferPayment {
1014- payment_preimage, payment_secret, ..
1015- } => PaymentDetailsUpdate {
1016- preimage : Some ( payment_preimage) ,
1017- secret : Some ( Some ( payment_secret) ) ,
1018- amount_msat : Some ( Some ( amount_msat) ) ,
1019- status : Some ( PaymentStatus :: Succeeded ) ,
1020- ..PaymentDetailsUpdate :: new ( payment_id)
1199+ payment_preimage,
1200+ payment_secret,
1201+ payment_context,
1202+ ..
1203+ } => {
1204+ let payer_note = payment_context. invoice_request . payer_note_truncated ;
1205+ let offer_id = payment_context. offer_id ;
1206+ let quantity = payment_context. invoice_request . quantity ;
1207+ let kind = PaymentKind :: Bolt12Offer {
1208+ hash : Some ( payment_hash) ,
1209+ preimage : payment_preimage,
1210+ secret : Some ( payment_secret. clone ( ) ) ,
1211+ offer_id,
1212+ payer_note,
1213+ quantity,
1214+ } ;
1215+ let update = PaymentDetailsUpdate {
1216+ preimage : Some ( payment_preimage) ,
1217+ secret : Some ( Some ( payment_secret) ) ,
1218+ amount_msat : Some ( Some ( amount_msat) ) ,
1219+ status : Some ( PaymentStatus :: Succeeded ) ,
1220+ ..PaymentDetailsUpdate :: new ( payment_id)
1221+ } ;
1222+ ( update, kind)
10211223 } ,
10221224 PaymentPurpose :: Bolt12RefundPayment {
10231225 payment_preimage,
10241226 payment_secret,
10251227 ..
1026- } => PaymentDetailsUpdate {
1027- preimage : Some ( payment_preimage) ,
1028- secret : Some ( Some ( payment_secret) ) ,
1029- amount_msat : Some ( Some ( amount_msat) ) ,
1030- status : Some ( PaymentStatus :: Succeeded ) ,
1031- ..PaymentDetailsUpdate :: new ( payment_id)
1228+ } => {
1229+ let kind = PaymentKind :: Bolt12Refund {
1230+ hash : Some ( payment_hash) ,
1231+ preimage : payment_preimage,
1232+ secret : Some ( payment_secret. clone ( ) ) ,
1233+ payer_note : None ,
1234+ quantity : None ,
1235+ } ;
1236+ let update = PaymentDetailsUpdate {
1237+ preimage : Some ( payment_preimage) ,
1238+ secret : Some ( Some ( payment_secret) ) ,
1239+ amount_msat : Some ( Some ( amount_msat) ) ,
1240+ status : Some ( PaymentStatus :: Succeeded ) ,
1241+ ..PaymentDetailsUpdate :: new ( payment_id)
1242+ } ;
1243+ ( update, kind)
10321244 } ,
1033- PaymentPurpose :: SpontaneousPayment ( preimage) => PaymentDetailsUpdate {
1034- preimage : Some ( Some ( preimage) ) ,
1035- amount_msat : Some ( Some ( amount_msat) ) ,
1036- status : Some ( PaymentStatus :: Succeeded ) ,
1037- ..PaymentDetailsUpdate :: new ( payment_id)
1245+ PaymentPurpose :: SpontaneousPayment ( preimage) => {
1246+ let kind = PaymentKind :: Spontaneous {
1247+ hash : payment_hash,
1248+ preimage : Some ( preimage) ,
1249+ } ;
1250+ let update = PaymentDetailsUpdate {
1251+ preimage : Some ( Some ( preimage) ) ,
1252+ amount_msat : Some ( Some ( amount_msat) ) ,
1253+ status : Some ( PaymentStatus :: Succeeded ) ,
1254+ ..PaymentDetailsUpdate :: new ( payment_id)
1255+ } ;
1256+ ( update, kind)
10381257 } ,
10391258 } ;
10401259
@@ -1044,11 +1263,27 @@ where
10441263 // be the result of a replayed event.
10451264 ) ,
10461265 Ok ( DataStoreUpdateResult :: NotFound ) => {
1047- log_error ! (
1048- self . logger,
1049- "Claimed payment with ID {} couldn't be found in store" ,
1266+ // Payment was auto-claimed without a prior store entry.
1267+ let payment = PaymentDetails :: new (
10501268 payment_id,
1269+ kind_for_insert,
1270+ Some ( amount_msat) ,
1271+ None ,
1272+ PaymentDirection :: Inbound ,
1273+ PaymentStatus :: Succeeded ,
10511274 ) ;
1275+ match self . payment_store . insert ( payment) {
1276+ Ok ( _) => ( ) ,
1277+ Err ( e) => {
1278+ log_error ! (
1279+ self . logger,
1280+ "Failed to insert payment with ID {}: {}" ,
1281+ payment_id,
1282+ e
1283+ ) ;
1284+ return Err ( ReplayEvent ( ) ) ;
1285+ } ,
1286+ }
10521287 } ,
10531288 Err ( e) => {
10541289 log_error ! (
0 commit comments