mirror of
https://github.com/ACINQ/eclair.git
synced 2025-02-22 22:25:26 +01:00
Allow plain outgoing_node_id
in blinded payment_relay
(#2943)
When we're the introduction node of a trampoline blinded path, we previously only allowed our custom `wallet_node_id` format when a `short_channel_id` was not included. But we actually can allow plain `node_id`s as well, as we only need to know the public key. We've rejected some payments in the past months because they included an `outgoing_node_id` that didn't use the wallet format: by removing that limitation we ensure that those payments will be correctly relayed in the future.
This commit is contained in:
parent
47fdfaec9f
commit
02abc3a7e5
2 changed files with 17 additions and 17 deletions
|
@ -101,7 +101,7 @@ object BlindedRouteData {
|
|||
// This is usually a channel, unless the next node is a mobile wallet connected to our node.
|
||||
val outgoing: Either[PublicKey, ShortChannelId] = records.get[RouteBlindingEncryptedDataTlv.OutgoingChannelId] match {
|
||||
case Some(r) => Right(r.shortChannelId)
|
||||
case None => Left(records.get[RouteBlindingEncryptedDataTlv.OutgoingNodeId].get.nodeId.asInstanceOf[EncodedNodeId.WithPublicKey.Wallet].publicKey)
|
||||
case None => Left(records.get[RouteBlindingEncryptedDataTlv.OutgoingNodeId].get.nodeId.asInstanceOf[EncodedNodeId.WithPublicKey].publicKey)
|
||||
}
|
||||
val paymentRelay: PaymentRelay = records.get[RouteBlindingEncryptedDataTlv.PaymentRelay].get
|
||||
val paymentConstraints: PaymentConstraints = records.get[RouteBlindingEncryptedDataTlv.PaymentConstraints].get
|
||||
|
@ -114,9 +114,9 @@ object BlindedRouteData {
|
|||
}
|
||||
|
||||
def validatePaymentRelayData(records: TlvStream[RouteBlindingEncryptedDataTlv]): Either[InvalidTlvPayload, PaymentRelayData] = {
|
||||
// Note that the BOLTs require using an OutgoingChannelId, but we optionally support a wallet node_id.
|
||||
// Note that the BOLTs require using an OutgoingChannelId, but we optionally support using a node_id.
|
||||
if (records.get[OutgoingChannelId].isEmpty && records.get[OutgoingNodeId].isEmpty) return Left(MissingRequiredTlv(UInt64(2)))
|
||||
if (records.get[OutgoingNodeId].nonEmpty && !records.get[OutgoingNodeId].get.nodeId.isInstanceOf[EncodedNodeId.WithPublicKey.Wallet]) return Left(ForbiddenTlv(UInt64(4)))
|
||||
if (records.get[OutgoingNodeId].nonEmpty && !records.get[OutgoingNodeId].get.nodeId.isInstanceOf[EncodedNodeId.WithPublicKey]) return Left(ForbiddenTlv(UInt64(4)))
|
||||
if (records.get[PaymentRelay].isEmpty) return Left(MissingRequiredTlv(UInt64(10)))
|
||||
if (records.get[PaymentConstraints].isEmpty) return Left(MissingRequiredTlv(UInt64(12)))
|
||||
if (records.get[PathId].nonEmpty) return Left(ForbiddenTlv(UInt64(6)))
|
||||
|
|
|
@ -119,18 +119,20 @@ class PaymentOnionSpec extends AnyFunSuite {
|
|||
}
|
||||
}
|
||||
|
||||
test("encode/decode channel relay blinded per-hop-payload (with wallet node_id)") {
|
||||
val walletNodeId = PublicKey(hex"0221cd519eba9c8b840a5e40b65dc2c040e159a766979723ed770efceb97260ec8")
|
||||
val blindedTlvs = TlvStream[RouteBlindingEncryptedDataTlv](
|
||||
RouteBlindingEncryptedDataTlv.OutgoingNodeId(EncodedNodeId.WithPublicKey.Wallet(walletNodeId)),
|
||||
RouteBlindingEncryptedDataTlv.PaymentRelay(CltvExpiryDelta(144), 100, 10 msat),
|
||||
RouteBlindingEncryptedDataTlv.PaymentConstraints(CltvExpiry(1500), 1 msat),
|
||||
)
|
||||
val Right(payload) = IntermediatePayload.ChannelRelay.Blinded.validate(TlvStream(EncryptedRecipientData(hex"deadbeef")), blindedTlvs, randomKey().publicKey)
|
||||
assert(payload.outgoing == Left(walletNodeId))
|
||||
assert(payload.amountToForward(10_000 msat) == 9990.msat)
|
||||
assert(payload.outgoingCltv(CltvExpiry(1000)) == CltvExpiry(856))
|
||||
assert(payload.paymentRelayData.allowedFeatures.isEmpty)
|
||||
test("encode/decode channel relay blinded per-hop-payload (with node_id)") {
|
||||
val nextNodeId = PublicKey(hex"0221cd519eba9c8b840a5e40b65dc2c040e159a766979723ed770efceb97260ec8")
|
||||
Seq(EncodedNodeId.WithPublicKey.Wallet(nextNodeId), EncodedNodeId.WithPublicKey.Plain(nextNodeId)).foreach(outgoingNodeId => {
|
||||
val blindedTlvs = TlvStream[RouteBlindingEncryptedDataTlv](
|
||||
RouteBlindingEncryptedDataTlv.OutgoingNodeId(outgoingNodeId),
|
||||
RouteBlindingEncryptedDataTlv.PaymentRelay(CltvExpiryDelta(144), 100, 10 msat),
|
||||
RouteBlindingEncryptedDataTlv.PaymentConstraints(CltvExpiry(1500), 1 msat),
|
||||
)
|
||||
val Right(payload) = IntermediatePayload.ChannelRelay.Blinded.validate(TlvStream(EncryptedRecipientData(hex"deadbeef")), blindedTlvs, randomKey().publicKey)
|
||||
assert(payload.outgoing == Left(nextNodeId))
|
||||
assert(payload.amountToForward(10_000 msat) == 9990.msat)
|
||||
assert(payload.outgoingCltv(CltvExpiry(1000)) == CltvExpiry(856))
|
||||
assert(payload.paymentRelayData.allowedFeatures.isEmpty)
|
||||
})
|
||||
}
|
||||
|
||||
test("encode/decode node relay per-hop payload") {
|
||||
|
@ -306,8 +308,6 @@ class PaymentOnionSpec extends AnyFunSuite {
|
|||
TestCase(MissingRequiredTlv(UInt64(10)), hex"23 0c21036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2", validBlindedTlvs),
|
||||
// Missing encrypted outgoing channel.
|
||||
TestCase(MissingRequiredTlv(UInt64(2)), hex"0a 0a080123456789abcdef", TlvStream(RouteBlindingEncryptedDataTlv.PaymentRelay(CltvExpiryDelta(144), 100, 10 msat), RouteBlindingEncryptedDataTlv.PaymentConstraints(CltvExpiry(1500), 1 msat))),
|
||||
// Forbidden encrypted outgoing plain node_id.
|
||||
TestCase(ForbiddenTlv(UInt64(4)), hex"0a 0a080123456789abcdef", TlvStream(RouteBlindingEncryptedDataTlv.OutgoingNodeId(EncodedNodeId.WithPublicKey.Plain(randomKey().publicKey)), RouteBlindingEncryptedDataTlv.PaymentRelay(CltvExpiryDelta(144), 100, 10 msat), RouteBlindingEncryptedDataTlv.PaymentConstraints(CltvExpiry(1500), 1 msat))),
|
||||
// Missing encrypted payment relay data.
|
||||
TestCase(MissingRequiredTlv(UInt64(10)), hex"0a 0a080123456789abcdef", TlvStream(RouteBlindingEncryptedDataTlv.OutgoingChannelId(ShortChannelId(42)), RouteBlindingEncryptedDataTlv.PaymentConstraints(CltvExpiry(1500), 1 msat))),
|
||||
// Missing encrypted payment constraint.
|
||||
|
|
Loading…
Add table
Reference in a new issue