@@ -26,7 +26,7 @@ object OutgoingPaymentPacket {
2626 return buildOnion(sessionKey, nodes, payloads, associatedData, payloadLength)
2727 }
2828
29- private fun buildOnion (sessionKey : PrivateKey , nodes : List <PublicKey >, payloads : List <PaymentOnion .PerHopPayload >, associatedData : ByteVector32 , payloadLength : Int? = null): PacketAndSecrets {
29+ fun buildOnion (sessionKey : PrivateKey , nodes : List <PublicKey >, payloads : List <PaymentOnion .PerHopPayload >, associatedData : ByteVector32 , payloadLength : Int? = null): PacketAndSecrets {
3030 require(nodes.size == payloads.size)
3131 val payloadsBin = payloads.map { it.write() }
3232 val totalPayloadLength = payloadLength ? : payloadsBin.sumOf { it.size + Sphinx .MacLength }
@@ -43,12 +43,11 @@ object OutgoingPaymentPacket {
4343 * @param hop the trampoline hop from the trampoline node to the recipient.
4444 */
4545 fun buildPacketToTrampolineRecipient (invoice : Bolt11Invoice , amount : MilliSatoshi , expiry : CltvExpiry , hop : NodeHop ): Triple <MilliSatoshi , CltvExpiry , PacketAndSecrets > {
46- require(invoice.features.hasFeature(Feature .ExperimentalTrampolinePayment )) { " invoice must support trampoline" }
46+ require(invoice.features.hasFeature(Feature .TrampolinePayment )) { " invoice must support trampoline" }
4747 val trampolineOnion = run {
4848 val finalPayload = PaymentOnion .FinalPayload .Standard .createSinglePartPayload(amount, expiry, invoice.paymentSecret, invoice.paymentMetadata)
4949 val trampolinePayload = PaymentOnion .NodeRelayPayload .create(amount, expiry, hop.nextNodeId)
50- // We may be paying an older version of lightning-kmp that only supports trampoline packets of size 400.
51- buildOnion(listOf (hop.nodeId, hop.nextNodeId), listOf (trampolinePayload, finalPayload), invoice.paymentHash, payloadLength = 400 )
50+ buildOnion(listOf (hop.nodeId, hop.nextNodeId), listOf (trampolinePayload, finalPayload), invoice.paymentHash)
5251 }
5352 val trampolineAmount = amount + hop.fee(amount)
5453 val trampolineExpiry = expiry + hop.cltvExpiryDelta
@@ -67,7 +66,7 @@ object OutgoingPaymentPacket {
6766 * @param expiry cltv expiry that should be received by the final recipient.
6867 */
6968 fun buildPacketToTrampolinePeer (invoice : Bolt11Invoice , amount : MilliSatoshi , expiry : CltvExpiry ): Triple <MilliSatoshi , CltvExpiry , PacketAndSecrets > {
70- require(invoice.features.hasFeature(Feature .ExperimentalTrampolinePayment )) { " invoice must support trampoline" }
69+ require(invoice.features.hasFeature(Feature .TrampolinePayment )) { " invoice must support trampoline" }
7170 val trampolineOnion = run {
7271 val finalPayload = PaymentOnion .FinalPayload .Standard .createSinglePartPayload(amount, expiry, invoice.paymentSecret, invoice.paymentMetadata)
7372 buildOnion(listOf (invoice.nodeId), listOf (finalPayload), invoice.paymentHash)
@@ -90,23 +89,20 @@ object OutgoingPaymentPacket {
9089 */
9190 fun buildPacketToLegacyRecipient (invoice : Bolt11Invoice , amount : MilliSatoshi , expiry : CltvExpiry , hop : NodeHop ): Triple <MilliSatoshi , CltvExpiry , PacketAndSecrets > {
9291 val trampolineOnion = run {
93- // NB: the final payload will never reach the recipient, since the trampoline node will convert that to a legacy payment.
94- // We use the smallest final payload possible, otherwise we may overflow the trampoline onion size.
95- val dummyFinalPayload = PaymentOnion .FinalPayload .Standard .createSinglePartPayload(amount, expiry, invoice.paymentSecret, null )
96- var routingInfo = invoice.routingInfo
97- var trampolinePayload = PaymentOnion .RelayToNonTrampolinePayload .create(amount, amount, expiry, hop.nextNodeId, invoice, routingInfo)
98- var trampolineOnion = buildOnion(listOf (hop.nodeId, hop.nextNodeId), listOf (trampolinePayload, dummyFinalPayload), invoice.paymentHash)
99- // Ensure that this onion can fit inside the outer 1300 bytes onion. The outer onion fields need ~150 bytes and we add some safety margin.
100- while (trampolineOnion.packet.payload.size() > 1000 ) {
101- routingInfo = routingInfo.dropLast(1 )
102- trampolinePayload = PaymentOnion .RelayToNonTrampolinePayload .create(amount, amount, expiry, hop.nextNodeId, invoice, routingInfo)
103- trampolineOnion = buildOnion(listOf (hop.nodeId, hop.nextNodeId), listOf (trampolinePayload, dummyFinalPayload), invoice.paymentHash)
104- }
105- trampolineOnion
92+ // We create a trampoline onion detailing what to forward to the recipient.
93+ val trampolinePayload = PaymentOnion .NodeRelayPayload .create(amount, expiry, hop.nextNodeId)
94+ buildOnion(listOf (hop.nodeId), listOf (trampolinePayload), invoice.paymentHash)
10695 }
96+ // We wrap that trampoline onion in a payment onion that contains the invoice's routing hints.
97+ // We remove routing hints until they fit inside the payment onion.
10798 val trampolineAmount = amount + hop.fee(amount)
10899 val trampolineExpiry = expiry + hop.cltvExpiryDelta
109- val payload = PaymentOnion .FinalPayload .Standard .createTrampolinePayload(trampolineAmount, trampolineAmount, trampolineExpiry, invoice.paymentSecret, trampolineOnion.packet)
100+ var routingInfo = invoice.routingInfo
101+ var payload = PaymentOnion .FinalPayload .Standard .createTrampolineToLegacyPayload(trampolineAmount, trampolineExpiry, invoice, routingInfo, trampolineOnion.packet)
102+ while (payload.write().size + Sphinx .MacLength > OnionRoutingPacket .PaymentPacketLength ) {
103+ routingInfo = routingInfo.dropLast(1 )
104+ payload = PaymentOnion .FinalPayload .Standard .createTrampolineToLegacyPayload(trampolineAmount, trampolineExpiry, invoice, routingInfo, trampolineOnion.packet)
105+ }
110106 val paymentOnion = buildOnion(listOf (hop.nodeId), listOf (payload), invoice.paymentHash, OnionRoutingPacket .PaymentPacketLength )
111107 return Triple (trampolineAmount, trampolineExpiry, paymentOnion)
112108 }
0 commit comments