diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/Features.scala b/eclair-core/src/main/scala/fr/acinq/eclair/Features.scala index 1159ba3076..80d689b50e 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/Features.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/Features.scala @@ -247,17 +247,17 @@ object Features { val mandatory = 28 } - case object AttributableError extends Feature with InitFeature with NodeFeature with Bolt11Feature { - val rfcName = "option_attributable_error" - val mandatory = 30 - } - // TODO: this should also extend NodeFeature once the spec is finalized case object Quiescence extends Feature with InitFeature { val rfcName = "option_quiesce" val mandatory = 34 } + case object AttributableError extends Feature with InitFeature with NodeFeature with Bolt11Feature { + val rfcName = "option_attributable_error" + val mandatory = 36 + } + case object OnionMessages extends Feature with InitFeature with NodeFeature { val rfcName = "option_onion_messages" val mandatory = 38 diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Sphinx.scala b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Sphinx.scala index d58b5298c4..7fe8bd05ab 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Sphinx.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Sphinx.scala @@ -376,7 +376,9 @@ object Sphinx extends Logging { def wrapOrCreate(errorPacket: ByteVector, sharedSecret: ByteVector32, holdTime: FiniteDuration): ByteVector = wrap(errorPacket, sharedSecret, holdTime, isSource = false) match { - case Failure(_) => create(sharedSecret, TemporaryNodeFailure(), holdTime) + case Failure(_) => + // There is no failure message for this use-case, using TemporaryNodeFailure instead. + create(sharedSecret, TemporaryNodeFailure(), holdTime) case Success(value) => value } diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/SphinxSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/SphinxSpec.scala index da5225800c..2560821fdf 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/SphinxSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/SphinxSpec.scala @@ -437,15 +437,15 @@ class SphinxSpec extends AnyFunSuite { ).map(ByteVector32(_)) // publicKeys(2) creates an invalid random packet, or publicKeys(1) tries to shift blame by pretending to receive random data from publicKeys(2) - val packet1 = randomBytes(12599) + val packet1 = randomBytes(1200) val hopPayload2 = AttributableError.HopPayload(isPayloadSource = false, 50 millis) val Success(packet2) = AttributableErrorPacket.wrap(packet1, sharedSecrets(1), 50 millis, isSource = false) - assert(packet2.length == 12599) + assert(packet2.length == 1200) val hopPayload3 = AttributableError.HopPayload(isPayloadSource = false, 100 millis) val Success(packet3) = AttributableErrorPacket.wrap(packet2, sharedSecrets(0), 100 millis, isSource = false) - assert(packet3.length == 12599) + assert(packet3.length == 1200) val Left(decryptionError) = AttributableErrorPacket.decrypt(packet3, (0 to 4).map(i => (sharedSecrets(i), publicKeys(i)))) val expected = InvalidAttributableErrorPacket(Seq((publicKeys(0), hopPayload3), (publicKeys(1), hopPayload2)), publicKeys(2)) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/basic/payment/OfferPaymentSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/basic/payment/OfferPaymentSpec.scala index fb57e6b07c..7a7f452d4b 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/basic/payment/OfferPaymentSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/basic/payment/OfferPaymentSpec.scala @@ -24,7 +24,7 @@ import com.softwaremill.quicklens.ModifyPimp import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey import fr.acinq.bitcoin.scalacompat.{ByteVector32, SatoshiLong} import fr.acinq.eclair.FeatureSupport.Optional -import fr.acinq.eclair.Features.{KeySend, RouteBlinding} +import fr.acinq.eclair.Features.{AttributableError, KeySend, RouteBlinding} import fr.acinq.eclair.channel.{DATA_NORMAL, RealScidStatus} import fr.acinq.eclair.integration.basic.fixtures.MinimalNodeFixture import fr.acinq.eclair.integration.basic.fixtures.MinimalNodeFixture.{connect, getChannelData, getPeerChannels, getRouterData, knownFundingTxs, nodeParamsFor, openChannel, watcherAutopilot} @@ -34,12 +34,11 @@ import fr.acinq.eclair.payment._ import fr.acinq.eclair.payment.offer.OfferManager import fr.acinq.eclair.payment.receive.MultiPartHandler.{DummyBlindedHop, ReceivingRoute} import fr.acinq.eclair.payment.send.PaymentInitiator.{SendPaymentToNode, SendSpontaneousPayment} -import fr.acinq.eclair.payment.send.{ClearRecipient, OfferPayment, PaymentLifecycle} -import fr.acinq.eclair.router.Router +import fr.acinq.eclair.payment.send.{OfferPayment, PaymentLifecycle} import fr.acinq.eclair.testutils.FixtureSpec import fr.acinq.eclair.wire.protocol.OfferTypes.{Offer, OfferPaths} import fr.acinq.eclair.wire.protocol.{IncorrectOrUnknownPaymentDetails, InvalidOnionBlinding} -import fr.acinq.eclair.{CltvExpiry, CltvExpiryDelta, Features, MilliSatoshi, MilliSatoshiLong, ShortChannelId, randomBytes32, randomKey} +import fr.acinq.eclair.{CltvExpiryDelta, Features, MilliSatoshi, MilliSatoshiLong, ShortChannelId, randomBytes32, randomKey} import org.scalatest.concurrent.IntegrationPatience import org.scalatest.{Tag, TestData} import scodec.bits.HexStringSyntax @@ -62,16 +61,19 @@ class OfferPaymentSpec extends FixtureSpec with IntegrationPatience { val aliceParams = nodeParamsFor("alice", ByteVector32(hex"b4acd47335b25ab7b84b8c020997b12018592bb4631b868762154d77fa8b93a3")) .modify(_.onionMessageConfig.timeout).setTo(5 minutes) .modify(_.features.activated).using(_ + (RouteBlinding -> Optional)) + .modify(_.features.activated).using(_ - AttributableError) .modify(_.channelConf.channelFlags.announceChannel).setTo(!testData.tags.contains(PrivateChannels)) val bobParams = nodeParamsFor("bob", ByteVector32(hex"7620226fec887b0b2ebe76492e5a3fd3eb0e47cd3773263f6a81b59a704dc492")) .modify(_.onionMessageConfig.timeout).setTo(5 minutes) .modify(_.features.activated).using(_ + (RouteBlinding -> Optional)) + .modify(_.features.activated).using(_ - AttributableError) .modify(_.features.activated).usingIf(testData.tags.contains(RouteBlindingDisabledBob))(_ - RouteBlinding) .modify(_.channelConf.channelFlags.announceChannel).setTo(!testData.tags.contains(PrivateChannels)) val carolParams = nodeParamsFor("carol", ByteVector32(hex"ebd5a5d3abfb3ef73731eb3418d918f247445183180522674666db98a66411cc")) .modify(_.onionMessageConfig.timeout).setTo(5 minutes) .modify(_.features.activated).using(_ + (RouteBlinding -> Optional)) .modify(_.features.activated).using(_ + (KeySend -> Optional)) + .modify(_.features.activated).using(_ - AttributableError) .modify(_.features.activated).usingIf(testData.tags.contains(RouteBlindingDisabledCarol))(_ - RouteBlinding) .modify(_.channelConf.channelFlags.announceChannel).setTo(!testData.tags.contains(PrivateChannels))