mirror of
https://github.com/ACINQ/eclair.git
synced 2025-02-22 06:21:42 +01:00
Add HTLC endorsement/confidence (#2884)
Implements https://github.com/lightning/blips/pull/27, a subsequent PR will implement a confidence estimator.
This commit is contained in:
parent
e298ba96ea
commit
7aacd4b460
41 changed files with 451 additions and 400 deletions
|
@ -196,7 +196,7 @@ sealed trait HasOptionalReplyToCommand extends Command { def replyTo_opt: Option
|
|||
sealed trait ForbiddenCommandDuringSplice extends Command
|
||||
sealed trait ForbiddenCommandDuringQuiescence extends Command
|
||||
|
||||
final case class CMD_ADD_HTLC(replyTo: ActorRef, amount: MilliSatoshi, paymentHash: ByteVector32, cltvExpiry: CltvExpiry, onion: OnionRoutingPacket, nextBlindingKey_opt: Option[PublicKey], origin: Origin.Hot, commit: Boolean = false) extends HasReplyToCommand with ForbiddenCommandDuringSplice with ForbiddenCommandDuringQuiescence
|
||||
final case class CMD_ADD_HTLC(replyTo: ActorRef, amount: MilliSatoshi, paymentHash: ByteVector32, cltvExpiry: CltvExpiry, onion: OnionRoutingPacket, nextBlindingKey_opt: Option[PublicKey], confidence: Double, origin: Origin.Hot, commit: Boolean = false) extends HasReplyToCommand with ForbiddenCommandDuringSplice with ForbiddenCommandDuringQuiescence
|
||||
sealed trait HtlcSettlementCommand extends HasOptionalReplyToCommand with ForbiddenCommandDuringSplice with ForbiddenCommandDuringQuiescence { def id: Long }
|
||||
final case class CMD_FULFILL_HTLC(id: Long, r: ByteVector32, commit: Boolean = false, replyTo_opt: Option[ActorRef] = None) extends HtlcSettlementCommand
|
||||
final case class CMD_FAIL_HTLC(id: Long, reason: Either[ByteVector, FailureMessage], delay_opt: Option[FiniteDuration] = None, commit: Boolean = false, replyTo_opt: Option[ActorRef] = None) extends HtlcSettlementCommand
|
||||
|
|
|
@ -854,7 +854,7 @@ case class Commitments(params: ChannelParams,
|
|||
return Left(HtlcValueTooSmall(params.channelId, minimum = htlcMinimum, actual = cmd.amount))
|
||||
}
|
||||
|
||||
val add = UpdateAddHtlc(channelId, changes.localNextHtlcId, cmd.amount, cmd.paymentHash, cmd.cltvExpiry, cmd.onion, cmd.nextBlindingKey_opt)
|
||||
val add = UpdateAddHtlc(channelId, changes.localNextHtlcId, cmd.amount, cmd.paymentHash, cmd.cltvExpiry, cmd.onion, cmd.nextBlindingKey_opt, cmd.confidence)
|
||||
// we increment the local htlc index and add an entry to the origins map
|
||||
val changes1 = changes.addLocalProposal(add).copy(localNextHtlcId = changes.localNextHtlcId + 1)
|
||||
val originChannels1 = originChannels + (add.id -> cmd.origin)
|
||||
|
|
|
@ -67,6 +67,10 @@ object Monitoring {
|
|||
PaymentNodeOutAmount.withoutTags().record(bucket, amount.truncateToSatoshi.toLong)
|
||||
PaymentNodeOut.withoutTags().record(bucket)
|
||||
}
|
||||
|
||||
private val RelayConfidence = Kamon.histogram("payment.relay.confidence", "Confidence (in percent) that the relayed HTLC will be fulfilled")
|
||||
def relayFulfill(confidence: Double) = RelayConfidence.withTag("status", "fulfill").record((confidence * 100).toLong)
|
||||
def relayFail(confidence: Double) = RelayConfidence.withTag("status", "fail").record((confidence * 100).toLong)
|
||||
}
|
||||
|
||||
object Tags {
|
||||
|
|
|
@ -285,12 +285,12 @@ object OutgoingPaymentPacket {
|
|||
}
|
||||
|
||||
/** Build the command to add an HTLC for the given recipient using the provided route. */
|
||||
def buildOutgoingPayment(origin: Origin.Hot, paymentHash: ByteVector32, route: Route, recipient: Recipient): Either[OutgoingPaymentError, OutgoingPaymentPacket] = {
|
||||
def buildOutgoingPayment(origin: Origin.Hot, paymentHash: ByteVector32, route: Route, recipient: Recipient, confidence: Double): Either[OutgoingPaymentError, OutgoingPaymentPacket] = {
|
||||
for {
|
||||
payment <- recipient.buildPayloads(paymentHash, route)
|
||||
onion <- buildOnion(payment.payloads, paymentHash, Some(PaymentOnionCodecs.paymentOnionPayloadLength)) // BOLT 2 requires that associatedData == paymentHash
|
||||
} yield {
|
||||
val cmd = CMD_ADD_HTLC(origin.replyTo, payment.amount, paymentHash, payment.expiry, onion.packet, payment.outerBlinding_opt, origin, commit = true)
|
||||
val cmd = CMD_ADD_HTLC(origin.replyTo, payment.amount, paymentHash, payment.expiry, onion.packet, payment.outerBlinding_opt, confidence, origin, commit = true)
|
||||
OutgoingPaymentPacket(cmd, route.hops.head.shortChannelId, onion.sharedSecrets)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
package fr.acinq.eclair.payment.relay
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.Behavior
|
||||
import akka.actor.typed.eventstream.EventStream
|
||||
import akka.actor.typed.scaladsl.adapter.TypedActorRefOps
|
||||
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
|
||||
import akka.actor.{ActorRef, typed}
|
||||
import fr.acinq.bitcoin.scalacompat.ByteVector32
|
||||
import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey
|
||||
import fr.acinq.eclair.channel._
|
||||
|
@ -54,7 +54,12 @@ object ChannelRelay {
|
|||
case class RelaySuccess(selectedChannelId: ByteVector32, cmdAdd: CMD_ADD_HTLC) extends RelayResult
|
||||
// @formatter:on
|
||||
|
||||
def apply(nodeParams: NodeParams, register: ActorRef, channels: Map[ByteVector32, Relayer.OutgoingChannel], originNode: PublicKey, relayId: UUID, r: IncomingPaymentPacket.ChannelRelayPacket): Behavior[Command] =
|
||||
def apply(nodeParams: NodeParams,
|
||||
register: ActorRef,
|
||||
channels: Map[ByteVector32, Relayer.OutgoingChannel],
|
||||
originNode:PublicKey,
|
||||
relayId: UUID,
|
||||
r: IncomingPaymentPacket.ChannelRelayPacket): Behavior[Command] =
|
||||
Behaviors.setup { context =>
|
||||
Behaviors.withMdc(Logs.mdc(
|
||||
category_opt = Some(Logs.LogCategory.PAYMENT),
|
||||
|
@ -63,7 +68,8 @@ object ChannelRelay {
|
|||
nodeAlias_opt = Some(nodeParams.alias))) {
|
||||
val upstream = Upstream.Hot.Channel(r.add.removeUnknownTlvs(), TimestampMilli.now(), originNode)
|
||||
context.self ! DoRelay
|
||||
new ChannelRelay(nodeParams, register, channels, r, upstream, context).relay(Seq.empty)
|
||||
val confidence = (r.add.endorsement + 0.5) / 8
|
||||
new ChannelRelay(nodeParams, register, channels, r, upstream, confidence, context).relay(Seq.empty)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,6 +113,7 @@ class ChannelRelay private(nodeParams: NodeParams,
|
|||
channels: Map[ByteVector32, Relayer.OutgoingChannel],
|
||||
r: IncomingPaymentPacket.ChannelRelayPacket,
|
||||
upstream: Upstream.Hot.Channel,
|
||||
confidence: Double,
|
||||
context: ActorContext[ChannelRelay.Command]) {
|
||||
|
||||
import ChannelRelay._
|
||||
|
@ -149,22 +156,24 @@ class ChannelRelay private(nodeParams: NodeParams,
|
|||
context.self ! DoRelay
|
||||
relay(previousFailures :+ PreviouslyTried(selectedChannelId, addFailed))
|
||||
|
||||
case WrappedAddResponse(_: RES_SUCCESS[_]) =>
|
||||
case WrappedAddResponse(r: RES_SUCCESS[_]) =>
|
||||
context.log.debug("sent htlc to the downstream channel")
|
||||
waitForAddSettled()
|
||||
waitForAddSettled(r.channelId)
|
||||
}
|
||||
|
||||
def waitForAddSettled(): Behavior[Command] =
|
||||
def waitForAddSettled(channelId: ByteVector32): Behavior[Command] =
|
||||
Behaviors.receiveMessagePartial {
|
||||
case WrappedAddResponse(RES_ADD_SETTLED(_, htlc, fulfill: HtlcResult.Fulfill)) =>
|
||||
context.log.debug("relaying fulfill to upstream")
|
||||
context.log.info("relaying fulfill to upstream, startedAt={}, endedAt={}, confidence={}, originNode={}, outgoingChannel={}", upstream.receivedAt, TimestampMilli.now(), confidence, upstream.receivedFrom, channelId)
|
||||
Metrics.relayFulfill(confidence)
|
||||
val cmd = CMD_FULFILL_HTLC(upstream.add.id, fulfill.paymentPreimage, commit = true)
|
||||
context.system.eventStream ! EventStream.Publish(ChannelPaymentRelayed(upstream.amountIn, htlc.amountMsat, htlc.paymentHash, upstream.add.channelId, htlc.channelId, upstream.receivedAt, TimestampMilli.now()))
|
||||
recordRelayDuration(isSuccess = true)
|
||||
safeSendAndStop(upstream.add.channelId, cmd)
|
||||
|
||||
case WrappedAddResponse(RES_ADD_SETTLED(_, _, fail: HtlcResult.Fail)) =>
|
||||
context.log.debug("relaying fail to upstream")
|
||||
context.log.info("relaying fail to upstream, startedAt={}, endedAt={}, confidence={}, originNode={}, outgoingChannel={}", upstream.receivedAt, TimestampMilli.now(), confidence, upstream.receivedFrom, channelId)
|
||||
Metrics.relayFail(confidence)
|
||||
Metrics.recordPaymentRelayFailed(Tags.FailureType.Remote, Tags.RelayType.Channel)
|
||||
val cmd = translateRelayFailure(upstream.add.id, fail)
|
||||
recordRelayDuration(isSuccess = false)
|
||||
|
@ -312,7 +321,7 @@ class ChannelRelay private(nodeParams: NodeParams,
|
|||
case payload: IntermediatePayload.ChannelRelay.Blinded => Some(payload.nextBlinding)
|
||||
case _: IntermediatePayload.ChannelRelay.Standard => None
|
||||
}
|
||||
RelaySuccess(c.channelId, CMD_ADD_HTLC(addResponseAdapter.toClassic, r.amountToForward, r.add.paymentHash, r.outgoingCltv, r.nextPacket, nextBlindingKey_opt, origin, commit = true))
|
||||
RelaySuccess(c.channelId, CMD_ADD_HTLC(addResponseAdapter.toClassic, r.amountToForward, r.add.paymentHash, r.outgoingCltv, r.nextPacket, nextBlindingKey_opt, confidence, origin, commit = true))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -259,7 +259,8 @@ class NodeRelay private(nodeParams: NodeParams,
|
|||
|
||||
private def doSend(upstream: Upstream.Hot.Trampoline, nextPayload: IntermediatePayload.NodeRelay, nextPacket_opt: Option[OnionRoutingPacket]): Behavior[Command] = {
|
||||
context.log.debug(s"relaying trampoline payment (amountIn=${upstream.amountIn} expiryIn=${upstream.expiryIn} amountOut=${nextPayload.amountToForward} expiryOut=${nextPayload.outgoingCltv})")
|
||||
relay(upstream, nextPayload, nextPacket_opt)
|
||||
val confidence = (upstream.received.map(_.add.endorsement).min + 0.5) / 8
|
||||
relay(upstream, nextPayload, nextPacket_opt, confidence)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -316,12 +317,12 @@ class NodeRelay private(nodeParams: NodeParams,
|
|||
context.messageAdapter[PaymentFailed](WrappedPaymentFailed)
|
||||
}.toClassic
|
||||
|
||||
private def relay(upstream: Upstream.Hot.Trampoline, payloadOut: IntermediatePayload.NodeRelay, packetOut_opt: Option[OnionRoutingPacket]): Behavior[Command] = {
|
||||
private def relay(upstream: Upstream.Hot.Trampoline, payloadOut: IntermediatePayload.NodeRelay, packetOut_opt: Option[OnionRoutingPacket], confidence: Double): Behavior[Command] = {
|
||||
val displayNodeId = payloadOut match {
|
||||
case payloadOut: IntermediatePayload.NodeRelay.Standard => payloadOut.outgoingNodeId
|
||||
case _: IntermediatePayload.NodeRelay.ToBlindedPaths => randomKey().publicKey
|
||||
}
|
||||
val paymentCfg = SendPaymentConfig(relayId, relayId, None, paymentHash, displayNodeId, upstream, None, None, storeInDb = false, publishEvent = false, recordPathFindingMetrics = true)
|
||||
val paymentCfg = SendPaymentConfig(relayId, relayId, None, paymentHash, displayNodeId, upstream, None, None, storeInDb = false, publishEvent = false, recordPathFindingMetrics = true, confidence)
|
||||
val routeParams = computeRouteParams(nodeParams, upstream.amountIn, upstream.expiryIn, payloadOut.amountToForward, payloadOut.outgoingCltv)
|
||||
payloadOut match {
|
||||
case payloadOut: IntermediatePayload.NodeRelay.Standard =>
|
||||
|
|
|
@ -50,7 +50,7 @@ class PaymentInitiator(nodeParams: NodeParams, outgoingPaymentFactory: PaymentIn
|
|||
// Immediately return the paymentId
|
||||
replyTo ! paymentId
|
||||
}
|
||||
val paymentCfg = SendPaymentConfig(paymentId, paymentId, r.externalId, r.paymentHash, r.invoice.nodeId, Upstream.Local(paymentId), Some(r.invoice), r.payerKey_opt, storeInDb = true, publishEvent = true, recordPathFindingMetrics = true)
|
||||
val paymentCfg = SendPaymentConfig(paymentId, paymentId, r.externalId, r.paymentHash, r.invoice.nodeId, Upstream.Local(paymentId), Some(r.invoice), r.payerKey_opt, storeInDb = true, publishEvent = true, recordPathFindingMetrics = true, confidence = 1.0)
|
||||
val finalExpiry = r.finalExpiry(nodeParams)
|
||||
val recipient = r.invoice match {
|
||||
case invoice: Bolt11Invoice => ClearRecipient(invoice, r.recipientAmount, finalExpiry, r.userCustomTlvs)
|
||||
|
@ -71,7 +71,7 @@ class PaymentInitiator(nodeParams: NodeParams, outgoingPaymentFactory: PaymentIn
|
|||
case r: SendSpontaneousPayment =>
|
||||
val paymentId = UUID.randomUUID()
|
||||
sender() ! paymentId
|
||||
val paymentCfg = SendPaymentConfig(paymentId, paymentId, r.externalId, r.paymentHash, r.recipientNodeId, Upstream.Local(paymentId), None, None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = r.recordPathFindingMetrics)
|
||||
val paymentCfg = SendPaymentConfig(paymentId, paymentId, r.externalId, r.paymentHash, r.recipientNodeId, Upstream.Local(paymentId), None, None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = r.recordPathFindingMetrics, confidence = 1.0)
|
||||
val finalExpiry = nodeParams.paymentFinalExpiry.computeFinalExpiry(nodeParams.currentBlockHeight, Channel.MIN_CLTV_EXPIRY_DELTA)
|
||||
val recipient = SpontaneousRecipient(r.recipientNodeId, r.recipientAmount, finalExpiry, r.paymentPreimage, r.userCustomTlvs)
|
||||
val fsm = outgoingPaymentFactory.spawnOutgoingPayment(context, paymentCfg)
|
||||
|
@ -104,13 +104,13 @@ class PaymentInitiator(nodeParams: NodeParams, outgoingPaymentFactory: PaymentIn
|
|||
val trampolineHop = NodeHop(trampolineNodeId, r.recipientNodeId, trampolineAttempt.cltvExpiryDelta, trampolineAttempt.fees)
|
||||
val recipient = buildTrampolineRecipient(r, trampolineHop)
|
||||
sender() ! SendPaymentToRouteResponse(paymentId, parentPaymentId, Some(recipient.trampolinePaymentSecret))
|
||||
val paymentCfg = SendPaymentConfig(paymentId, parentPaymentId, r.externalId, r.paymentHash, r.recipientNodeId, Upstream.Local(paymentId), Some(r.invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = false)
|
||||
val paymentCfg = SendPaymentConfig(paymentId, parentPaymentId, r.externalId, r.paymentHash, r.recipientNodeId, Upstream.Local(paymentId), Some(r.invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = false, confidence = 1.0)
|
||||
val payFsm = outgoingPaymentFactory.spawnOutgoingPayment(context, paymentCfg)
|
||||
payFsm ! PaymentLifecycle.SendPaymentToRoute(self, Left(r.route), recipient)
|
||||
context become main(pending + (paymentId -> PendingPaymentToRoute(sender(), r)))
|
||||
case None =>
|
||||
sender() ! SendPaymentToRouteResponse(paymentId, parentPaymentId, None)
|
||||
val paymentCfg = SendPaymentConfig(paymentId, parentPaymentId, r.externalId, r.paymentHash, r.recipientNodeId, Upstream.Local(paymentId), Some(r.invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = false)
|
||||
val paymentCfg = SendPaymentConfig(paymentId, parentPaymentId, r.externalId, r.paymentHash, r.recipientNodeId, Upstream.Local(paymentId), Some(r.invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = false, confidence = 1.0)
|
||||
val finalExpiry = r.finalExpiry(nodeParams)
|
||||
val recipient = r.invoice match {
|
||||
case invoice: Bolt11Invoice => ClearRecipient(invoice, r.recipientAmount, finalExpiry, Set.empty)
|
||||
|
@ -192,7 +192,7 @@ class PaymentInitiator(nodeParams: NodeParams, outgoingPaymentFactory: PaymentIn
|
|||
|
||||
private def sendTrampolinePayment(paymentId: UUID, r: SendTrampolinePayment, trampolineFees: MilliSatoshi, trampolineExpiryDelta: CltvExpiryDelta): Unit = {
|
||||
val trampolineHop = NodeHop(r.trampolineNodeId, r.recipientNodeId, trampolineExpiryDelta, trampolineFees)
|
||||
val paymentCfg = SendPaymentConfig(paymentId, paymentId, None, r.paymentHash, r.recipientNodeId, Upstream.Local(paymentId), Some(r.invoice), None, storeInDb = true, publishEvent = false, recordPathFindingMetrics = true)
|
||||
val paymentCfg = SendPaymentConfig(paymentId, paymentId, None, r.paymentHash, r.recipientNodeId, Upstream.Local(paymentId), Some(r.invoice), None, storeInDb = true, publishEvent = false, recordPathFindingMetrics = true, confidence = 1.0)
|
||||
val recipient = buildTrampolineRecipient(r, trampolineHop)
|
||||
val fsm = outgoingPaymentFactory.spawnOutgoingMultiPartPayment(context, paymentCfg, publishPreimage = false)
|
||||
fsm ! MultiPartPaymentLifecycle.SendMultiPartPayment(self, recipient, nodeParams.maxPaymentAttempts, r.routeParams)
|
||||
|
@ -395,6 +395,7 @@ object PaymentInitiator {
|
|||
* @param publishEvent whether to publish a [[fr.acinq.eclair.payment.PaymentEvent]] on success/failure (e.g. for
|
||||
* multi-part child payments, we don't want to emit events for each child, only for the whole payment).
|
||||
* @param recordPathFindingMetrics We don't record metrics for payments that don't use path finding or that are a part of a bigger payment.
|
||||
* @param confidence How confident we are that this payment will succeed. Used to set the outgoing endorsement value.
|
||||
*/
|
||||
case class SendPaymentConfig(id: UUID,
|
||||
parentId: UUID,
|
||||
|
@ -406,7 +407,8 @@ object PaymentInitiator {
|
|||
payerKey_opt: Option[PrivateKey],
|
||||
storeInDb: Boolean, // e.g. for trampoline we don't want to store in the DB when we're relaying payments
|
||||
publishEvent: Boolean,
|
||||
recordPathFindingMetrics: Boolean) {
|
||||
recordPathFindingMetrics: Boolean,
|
||||
confidence: Double) {
|
||||
val paymentContext: PaymentContext = PaymentContext(id, parentId, paymentHash)
|
||||
val paymentType = invoice match {
|
||||
case Some(_: Bolt12Invoice) => PaymentType.Blinded
|
||||
|
|
|
@ -75,7 +75,7 @@ class PaymentLifecycle(nodeParams: NodeParams, cfg: SendPaymentConfig, router: A
|
|||
when(WAITING_FOR_ROUTE) {
|
||||
case Event(RouteResponse(route +: _), WaitingForRoute(request, failures, ignore)) =>
|
||||
log.info(s"route found: attempt=${failures.size + 1}/${request.maxAttempts} route=${route.printNodes()} channels=${route.printChannels()}")
|
||||
OutgoingPaymentPacket.buildOutgoingPayment(Origin.Hot(self, cfg.upstream), paymentHash, route, request.recipient) match {
|
||||
OutgoingPaymentPacket.buildOutgoingPayment(Origin.Hot(self, cfg.upstream), paymentHash, route, request.recipient, cfg.confidence) match {
|
||||
case Right(payment) =>
|
||||
register ! Register.ForwardShortId(self.toTyped[Register.ForwardShortIdFailure[CMD_ADD_HTLC]], payment.outgoingChannel, payment.cmd)
|
||||
goto(WAITING_FOR_PAYMENT_COMPLETE) using WaitingForComplete(request, payment.cmd, failures, payment.sharedSecrets, ignore, route)
|
||||
|
|
|
@ -20,7 +20,7 @@ import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey
|
|||
import fr.acinq.eclair.UInt64
|
||||
import fr.acinq.eclair.wire.protocol.CommonCodecs._
|
||||
import fr.acinq.eclair.wire.protocol.TlvCodecs.{tlvField, tlvStream, tu16}
|
||||
import scodec.Codec
|
||||
import scodec.{Attempt, Codec, Err}
|
||||
import scodec.bits.HexStringSyntax
|
||||
import scodec.codecs._
|
||||
|
||||
|
@ -34,9 +34,15 @@ object UpdateAddHtlcTlv {
|
|||
/** Blinding ephemeral public key that should be used to derive shared secrets when using route blinding. */
|
||||
case class BlindingPoint(publicKey: PublicKey) extends UpdateAddHtlcTlv
|
||||
|
||||
case class Endorsement(level: Int) extends UpdateAddHtlcTlv
|
||||
|
||||
private val blindingPoint: Codec[BlindingPoint] = (("length" | constant(hex"21")) :: ("blinding" | publicKey)).as[BlindingPoint]
|
||||
|
||||
val addHtlcTlvCodec: Codec[TlvStream[UpdateAddHtlcTlv]] = tlvStream(discriminated[UpdateAddHtlcTlv].by(varint).typecase(UInt64(0), blindingPoint))
|
||||
private val endorsement: Codec[Endorsement] = tlvField(uint8.narrow[Endorsement](n => if (n >= 8) Attempt.failure(Err(s"invalid endorsement level: $n")) else Attempt.successful(Endorsement(n)), _.level))
|
||||
|
||||
val addHtlcTlvCodec: Codec[TlvStream[UpdateAddHtlcTlv]] = tlvStream(discriminated[UpdateAddHtlcTlv].by(varint)
|
||||
.typecase(UInt64(0), blindingPoint)
|
||||
.typecase(UInt64(106823), endorsement))
|
||||
}
|
||||
|
||||
sealed trait UpdateFulfillHtlcTlv extends Tlv
|
||||
|
|
|
@ -351,9 +351,11 @@ case class UpdateAddHtlc(channelId: ByteVector32,
|
|||
paymentHash: ByteVector32,
|
||||
cltvExpiry: CltvExpiry,
|
||||
onionRoutingPacket: OnionRoutingPacket,
|
||||
tlvStream: TlvStream[UpdateAddHtlcTlv]) extends HtlcMessage with UpdateMessage with HasChannelId {
|
||||
tlvStream: TlvStream[UpdateAddHtlcTlv] = TlvStream.empty) extends HtlcMessage with UpdateMessage with HasChannelId {
|
||||
val blinding_opt: Option[PublicKey] = tlvStream.get[UpdateAddHtlcTlv.BlindingPoint].map(_.publicKey)
|
||||
|
||||
val endorsement: Int = tlvStream.get[UpdateAddHtlcTlv.Endorsement].map(_.level).getOrElse(0)
|
||||
|
||||
/** When storing in our DB, we avoid wasting storage with unknown data. */
|
||||
def removeUnknownTlvs(): UpdateAddHtlc = this.copy(tlvStream = tlvStream.copy(unknown = Set.empty))
|
||||
}
|
||||
|
@ -365,8 +367,9 @@ object UpdateAddHtlc {
|
|||
paymentHash: ByteVector32,
|
||||
cltvExpiry: CltvExpiry,
|
||||
onionRoutingPacket: OnionRoutingPacket,
|
||||
blinding_opt: Option[PublicKey]): UpdateAddHtlc = {
|
||||
val tlvs = blinding_opt.map(UpdateAddHtlcTlv.BlindingPoint).toSet[UpdateAddHtlcTlv]
|
||||
blinding_opt: Option[PublicKey],
|
||||
confidence: Double): UpdateAddHtlc = {
|
||||
val tlvs: Set[UpdateAddHtlcTlv] = Set(blinding_opt.map(UpdateAddHtlcTlv.BlindingPoint), Some(UpdateAddHtlcTlv.Endorsement((confidence * 7.999).toInt))).flatten
|
||||
UpdateAddHtlc(channelId, id, amountMsat, paymentHash, cltvExpiry, onionRoutingPacket, TlvStream(tlvs))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -409,7 +409,7 @@ class CommitmentsSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
test("can receive availableForReceive") { f =>
|
||||
for (isInitiator <- Seq(true, false)) {
|
||||
val c = CommitmentsSpec.makeCommitments(31000000 msat, 702000000 msat, FeeratePerKw(2679 sat), 546 sat, isInitiator)
|
||||
val add = UpdateAddHtlc(randomBytes32(), c.changes.remoteNextHtlcId, c.availableBalanceForReceive, randomBytes32(), CltvExpiry(f.currentBlockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(randomBytes32(), c.changes.remoteNextHtlcId, c.availableBalanceForReceive, randomBytes32(), CltvExpiry(f.currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
c.receiveAdd(add, feerates, feeConfNoMismatch)
|
||||
}
|
||||
}
|
||||
|
@ -460,14 +460,14 @@ class CommitmentsSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
// Add some initial HTLCs to the pending list (bigger commit tx).
|
||||
for (_ <- 1 to t.pendingHtlcs) {
|
||||
val amount = Random.nextInt(maxPendingHtlcAmount.toLong.toInt).msat.max(1 msat)
|
||||
val add = UpdateAddHtlc(randomBytes32(), c.changes.remoteNextHtlcId, amount, randomBytes32(), CltvExpiry(f.currentBlockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(randomBytes32(), c.changes.remoteNextHtlcId, amount, randomBytes32(), CltvExpiry(f.currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
c.receiveAdd(add, feerates, feeConfNoMismatch) match {
|
||||
case Right(cc) => c = cc
|
||||
case Left(e) => ignore(s"$t -> could not setup initial htlcs: $e")
|
||||
}
|
||||
}
|
||||
if (c.availableBalanceForReceive > 0.msat) {
|
||||
val add = UpdateAddHtlc(randomBytes32(), c.changes.remoteNextHtlcId, c.availableBalanceForReceive, randomBytes32(), CltvExpiry(f.currentBlockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(randomBytes32(), c.changes.remoteNextHtlcId, c.availableBalanceForReceive, randomBytes32(), CltvExpiry(f.currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
c.receiveAdd(add, feerates, feeConfNoMismatch) match {
|
||||
case Right(_) => ()
|
||||
case Left(e) => fail(s"$t -> $e")
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.scalatest.funsuite.AnyFunSuiteLike
|
|||
class DustExposureSpec extends AnyFunSuiteLike {
|
||||
|
||||
def createHtlc(id: Long, amount: MilliSatoshi): UpdateAddHtlc = {
|
||||
UpdateAddHtlc(ByteVector32.Zeroes, id, amount, randomBytes32(), CltvExpiry(500), TestConstants.emptyOnionPacket, None)
|
||||
UpdateAddHtlc(ByteVector32.Zeroes, id, amount, randomBytes32(), CltvExpiry(500), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
}
|
||||
|
||||
test("compute dust exposure") {
|
||||
|
|
|
@ -38,7 +38,6 @@ import grizzled.slf4j.Logging
|
|||
import org.scalatest.funsuite.FixtureAnyFunSuiteLike
|
||||
import org.scalatest.{Outcome, Tag}
|
||||
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import scala.concurrent.duration._
|
||||
import scala.util.Random
|
||||
|
@ -119,7 +118,7 @@ class FuzzySpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Channe
|
|||
// allow overpaying (no more than 2 times the required amount)
|
||||
val amount = requiredAmount + Random.nextInt(requiredAmount.toLong.toInt).msat
|
||||
val expiry = (Channel.MIN_CLTV_EXPIRY_DELTA + 1).toCltvExpiry(currentBlockHeight = BlockHeight(400000))
|
||||
val Right(payment) = OutgoingPaymentPacket.buildOutgoingPayment(localOrigin(self), invoice.paymentHash, makeSingleHopRoute(amount, invoice.nodeId), ClearRecipient(invoice, amount, expiry, Set.empty))
|
||||
val Right(payment) = OutgoingPaymentPacket.buildOutgoingPayment(localOrigin(self), invoice.paymentHash, makeSingleHopRoute(amount, invoice.nodeId), ClearRecipient(invoice, amount, expiry, Set.empty), 1.0)
|
||||
payment.cmd
|
||||
}
|
||||
|
||||
|
|
|
@ -68,14 +68,14 @@ class HelpersSpec extends TestKitBaseClass with AnyFunSuiteLike with ChannelStat
|
|||
awaitCond(bob.stateName == NORMAL)
|
||||
// We have two identical HTLCs (MPP):
|
||||
val (_, htlca1a) = addHtlc(15_000_000 msat, alice, bob, alice2bob, bob2alice)
|
||||
val aliceMppCmd = CMD_ADD_HTLC(TestProbe().ref, 15_000_000 msat, htlca1a.paymentHash, htlca1a.cltvExpiry, htlca1a.onionRoutingPacket, None, Origin.Hot(TestProbe().ref, Upstream.Local(UUID.randomUUID())))
|
||||
val aliceMppCmd = CMD_ADD_HTLC(TestProbe().ref, 15_000_000 msat, htlca1a.paymentHash, htlca1a.cltvExpiry, htlca1a.onionRoutingPacket, None, 1.0, Origin.Hot(TestProbe().ref, Upstream.Local(UUID.randomUUID())))
|
||||
val htlca1b = addHtlc(aliceMppCmd, alice, bob, alice2bob, bob2alice)
|
||||
val (ra2, htlca2) = addHtlc(16_000_000 msat, alice, bob, alice2bob, bob2alice)
|
||||
addHtlc(500_000 msat, alice, bob, alice2bob, bob2alice) // below dust
|
||||
crossSign(alice, bob, alice2bob, bob2alice)
|
||||
// We have two identical HTLCs (MPP):
|
||||
val (_, htlcb1a) = addHtlc(17_000_000 msat, bob, alice, bob2alice, alice2bob)
|
||||
val bobMppCmd = CMD_ADD_HTLC(TestProbe().ref, 17_000_000 msat, htlcb1a.paymentHash, htlcb1a.cltvExpiry, htlcb1a.onionRoutingPacket, None, Origin.Hot(TestProbe().ref, Upstream.Local(UUID.randomUUID())))
|
||||
val bobMppCmd = CMD_ADD_HTLC(TestProbe().ref, 17_000_000 msat, htlcb1a.paymentHash, htlcb1a.cltvExpiry, htlcb1a.onionRoutingPacket, None, 1.0, Origin.Hot(TestProbe().ref, Upstream.Local(UUID.randomUUID())))
|
||||
val htlcb1b = addHtlc(bobMppCmd, bob, alice, bob2alice, alice2bob)
|
||||
val (rb2, htlcb2) = addHtlc(18_000_000 msat, bob, alice, bob2alice, alice2bob)
|
||||
addHtlc(400_000 msat, bob, alice, bob2alice, alice2bob) // below dust
|
||||
|
|
|
@ -388,7 +388,7 @@ trait ChannelStateTestsBase extends Assertions with Eventually {
|
|||
val paymentHash = Crypto.sha256(paymentPreimage)
|
||||
val expiry = cltvExpiryDelta.toCltvExpiry(currentBlockHeight)
|
||||
val recipient = SpontaneousRecipient(destination, amount, expiry, paymentPreimage)
|
||||
val Right(payment) = OutgoingPaymentPacket.buildOutgoingPayment(Origin.Hot(replyTo, upstream), paymentHash, makeSingleHopRoute(amount, destination), recipient)
|
||||
val Right(payment) = OutgoingPaymentPacket.buildOutgoingPayment(Origin.Hot(replyTo, upstream), paymentHash, makeSingleHopRoute(amount, destination), recipient, 1.0)
|
||||
(paymentPreimage, payment.cmd.copy(commit = false))
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ class NormalQuiescentStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteL
|
|||
// initiator should reject commands that change the commitment once it became quiescent
|
||||
val sender1, sender2, sender3 = TestProbe()
|
||||
val cmds = Seq(
|
||||
CMD_ADD_HTLC(sender1.ref, 1_000_000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender1.ref)),
|
||||
CMD_ADD_HTLC(sender1.ref, 1_000_000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender1.ref)),
|
||||
CMD_UPDATE_FEE(FeeratePerKw(100 sat), replyTo_opt = Some(sender2.ref)),
|
||||
CMD_CLOSE(sender3.ref, None, None)
|
||||
)
|
||||
|
@ -164,7 +164,7 @@ class NormalQuiescentStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteL
|
|||
// both should reject commands that change the commitment while quiescent
|
||||
val sender1, sender2, sender3 = TestProbe()
|
||||
val cmds = Seq(
|
||||
CMD_ADD_HTLC(sender1.ref, 1_000_000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender1.ref)),
|
||||
CMD_ADD_HTLC(sender1.ref, 1_000_000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender1.ref)),
|
||||
CMD_UPDATE_FEE(FeeratePerKw(100 sat), replyTo_opt = Some(sender2.ref)),
|
||||
CMD_CLOSE(sender3.ref, None, None)
|
||||
)
|
||||
|
@ -352,7 +352,7 @@ class NormalQuiescentStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteL
|
|||
import f._
|
||||
initiateQuiescence(f, sendInitialStfu = true)
|
||||
// have to build a htlc manually because eclair would refuse to accept this command as it's forbidden
|
||||
val forbiddenMsg = UpdateAddHtlc(channelId = randomBytes32(), id = 5656, amountMsat = 50000000 msat, cltvExpiry = CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), paymentHash = randomBytes32(), onionRoutingPacket = TestConstants.emptyOnionPacket, blinding_opt = None)
|
||||
val forbiddenMsg = UpdateAddHtlc(channelId = randomBytes32(), id = 5656, amountMsat = 50000000 msat, cltvExpiry = CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), paymentHash = randomBytes32(), onionRoutingPacket = TestConstants.emptyOnionPacket, blinding_opt = None, confidence = 1.0)
|
||||
// both parties will respond to a forbidden msg while quiescent with a warning (and disconnect)
|
||||
bob2alice.forward(alice, forbiddenMsg)
|
||||
alice2bob.expectMsg(Warning(channelId(alice), ForbiddenDuringSplice(channelId(alice), "UpdateAddHtlc").getMessage))
|
||||
|
|
|
@ -588,7 +588,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
|
|||
|
||||
val sender = TestProbe()
|
||||
// command for a large payment (larger than local balance pre-slice)
|
||||
val cmd = CMD_ADD_HTLC(sender.ref, 1_000_000_000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val cmd = CMD_ADD_HTLC(sender.ref, 1_000_000_000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
// first attempt at payment fails (not enough balance)
|
||||
alice ! cmd
|
||||
sender.expectMsgType[RES_ADD_FAILED[_]]
|
||||
|
@ -840,7 +840,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
|
|||
import f._
|
||||
initiateSplice(f, spliceIn_opt = Some(SpliceIn(500_000 sat)))
|
||||
val sender = TestProbe()
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 500_000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 500_000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
alice2bob.forward(bob)
|
||||
|
@ -869,7 +869,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
|
|||
import f._
|
||||
initiateSplice(f, spliceIn_opt = Some(SpliceIn(500_000 sat)))
|
||||
val sender = TestProbe()
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 500_000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 500_000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
alice2bob.forward(bob)
|
||||
|
@ -903,7 +903,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
|
|||
val cmd = CMD_SPLICE(sender.ref, spliceIn_opt = Some(SpliceIn(500_000 sat, pushAmount = 0 msat)), spliceOut_opt = None)
|
||||
alice ! cmd
|
||||
alice2bob.expectMsgType[SpliceInit]
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_ADD_FAILED[_]]
|
||||
alice2bob.expectNoMessage(100 millis)
|
||||
}
|
||||
|
@ -918,7 +918,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
|
|||
bob2alice.expectMsgType[SpliceAck]
|
||||
bob2alice.forward(alice)
|
||||
alice2bob.expectMsgType[TxAddInput]
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_ADD_FAILED[_]]
|
||||
alice2bob.expectNoMessage(100 millis)
|
||||
}
|
||||
|
@ -960,7 +960,7 @@ class NormalSplicesStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLik
|
|||
alice2bob.expectMsgType[TxAddInput]
|
||||
|
||||
// have to build a htlc manually because eclair would refuse to accept this command as it's forbidden
|
||||
val fakeHtlc = UpdateAddHtlc(channelId = randomBytes32(), id = 5656, amountMsat = 50000000 msat, cltvExpiry = CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), paymentHash = randomBytes32(), onionRoutingPacket = TestConstants.emptyOnionPacket, blinding_opt = None)
|
||||
val fakeHtlc = UpdateAddHtlc(channelId = randomBytes32(), id = 5656, amountMsat = 50000000 msat, cltvExpiry = CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), paymentHash = randomBytes32(), onionRoutingPacket = TestConstants.emptyOnionPacket, blinding_opt = None, confidence = 1.0)
|
||||
bob2alice.forward(alice, fakeHtlc)
|
||||
// alice returns a warning and schedules a disconnect after receiving UpdateAddHtlc
|
||||
alice2bob.expectMsg(Warning(channelId(alice), ForbiddenDuringSplice(channelId(alice), "UpdateAddHtlc").getMessage))
|
||||
|
|
|
@ -77,7 +77,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val listener = TestProbe()
|
||||
alice.underlying.system.eventStream.subscribe(listener.ref, classOf[AvailableBalanceChanged])
|
||||
val h = randomBytes32()
|
||||
val add = CMD_ADD_HTLC(sender.ref, 50000000 msat, h, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 50000000 msat, h, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
val e = listener.expectMsgType[AvailableBalanceChanged]
|
||||
|
@ -103,7 +103,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val sender = TestProbe()
|
||||
val h = randomBytes32()
|
||||
for (i <- 0 until 10) {
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 500000 msat, h, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 500000 msat, h, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
val htlc = alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
assert(htlc.id == i && htlc.paymentHash == h)
|
||||
|
@ -115,9 +115,9 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
|
||||
val sender = TestProbe()
|
||||
val h = randomBytes32()
|
||||
val originHtlc = UpdateAddHtlc(channelId = randomBytes32(), id = 5656, amountMsat = 50000000 msat, cltvExpiry = CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), paymentHash = h, onionRoutingPacket = TestConstants.emptyOnionPacket, blinding_opt = None)
|
||||
val originHtlc = UpdateAddHtlc(channelId = randomBytes32(), id = 5656, amountMsat = 50000000 msat, cltvExpiry = CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), paymentHash = h, onionRoutingPacket = TestConstants.emptyOnionPacket, blinding_opt = None, confidence = 1.0)
|
||||
val origin = Origin.Hot(sender.ref, Upstream.Hot.Channel(originHtlc, TimestampMilli.now(), randomKey().publicKey))
|
||||
val cmd = CMD_ADD_HTLC(sender.ref, originHtlc.amountMsat - 10_000.msat, h, originHtlc.cltvExpiry - CltvExpiryDelta(7), TestConstants.emptyOnionPacket, None, origin)
|
||||
val cmd = CMD_ADD_HTLC(sender.ref, originHtlc.amountMsat - 10_000.msat, h, originHtlc.cltvExpiry - CltvExpiryDelta(7), TestConstants.emptyOnionPacket, None, 1.0, origin)
|
||||
alice ! cmd
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
val htlc = alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
|
@ -133,10 +133,10 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
|
||||
val sender = TestProbe()
|
||||
val h = randomBytes32()
|
||||
val originHtlc1 = UpdateAddHtlc(randomBytes32(), 47, 30000000 msat, h, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val originHtlc2 = UpdateAddHtlc(randomBytes32(), 32, 20000000 msat, h, CltvExpiryDelta(160).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val originHtlc1 = UpdateAddHtlc(randomBytes32(), 47, 30000000 msat, h, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val originHtlc2 = UpdateAddHtlc(randomBytes32(), 32, 20000000 msat, h, CltvExpiryDelta(160).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val origin = Origin.Hot(sender.ref, Upstream.Hot.Trampoline(Seq(originHtlc1, originHtlc2).map(htlc => Upstream.Hot.Channel(htlc, TimestampMilli.now(), randomKey().publicKey))))
|
||||
val cmd = CMD_ADD_HTLC(sender.ref, originHtlc1.amountMsat + originHtlc2.amountMsat - 10000.msat, h, originHtlc2.cltvExpiry - CltvExpiryDelta(7), TestConstants.emptyOnionPacket, None, origin)
|
||||
val cmd = CMD_ADD_HTLC(sender.ref, originHtlc1.amountMsat + originHtlc2.amountMsat - 10000.msat, h, originHtlc2.cltvExpiry - CltvExpiryDelta(7), TestConstants.emptyOnionPacket, None, 1.0, origin)
|
||||
alice ! cmd
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
val htlc = alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
|
@ -152,7 +152,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val sender = TestProbe()
|
||||
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
|
||||
val expiryTooSmall = CltvExpiry(currentBlockHeight)
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000000 msat, randomBytes32(), expiryTooSmall, TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000000 msat, randomBytes32(), expiryTooSmall, TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
val error = ExpiryTooSmall(channelId(alice), CltvExpiry(currentBlockHeight + 3), expiryTooSmall, currentBlockHeight)
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -165,7 +165,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
|
||||
val maxAllowedExpiryDelta = alice.underlyingActor.nodeParams.channelConf.maxExpiryDelta
|
||||
val expiryTooBig = (maxAllowedExpiryDelta + 1).toCltvExpiry(currentBlockHeight)
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000000 msat, randomBytes32(), expiryTooBig, TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000000 msat, randomBytes32(), expiryTooBig, TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
val error = ExpiryTooBig(channelId(alice), maximum = maxAllowedExpiryDelta.toCltvExpiry(currentBlockHeight), actual = expiryTooBig, blockHeight = currentBlockHeight)
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -176,7 +176,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
import f._
|
||||
val sender = TestProbe()
|
||||
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
|
||||
val add = CMD_ADD_HTLC(sender.ref, 50 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 50 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
val error = HtlcValueTooSmall(channelId(alice), 1000 msat, 50 msat)
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -189,7 +189,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
// Alice has a minimum set to 0 msat (which should be invalid, but may mislead Bob into relaying 0-value HTLCs which is forbidden by the spec).
|
||||
assert(alice.stateData.asInstanceOf[DATA_NORMAL].commitments.params.localParams.htlcMinimum == 0.msat)
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
val add = CMD_ADD_HTLC(sender.ref, 0 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 0 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
bob ! add
|
||||
val error = HtlcValueTooSmall(channelId(bob), 1 msat, 0 msat)
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -201,7 +201,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val sender = TestProbe()
|
||||
// channel starts with all funds on alice's side, alice sends some funds to bob, but not enough to make it go above reserve
|
||||
val h = randomBytes32()
|
||||
val add = CMD_ADD_HTLC(sender.ref, 50000000 msat, h, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 50000000 msat, h, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
import f._
|
||||
val sender = TestProbe()
|
||||
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
|
||||
val add = CMD_ADD_HTLC(sender.ref, MilliSatoshi(Int.MaxValue), randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, MilliSatoshi(Int.MaxValue), randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
val error = InsufficientFunds(channelId(alice), amount = MilliSatoshi(Int.MaxValue), missing = 1388843 sat, reserve = 20000 sat, fees = 8960 sat)
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -223,7 +223,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
|
||||
// The anchor outputs commitment format costs more fees for the funder (bigger commit tx + cost of anchor outputs)
|
||||
assert(initialState.commitments.availableBalanceForSend < initialState.commitments.modify(_.params.channelFeatures).setTo(ChannelFeatures()).availableBalanceForSend)
|
||||
val add = CMD_ADD_HTLC(sender.ref, initialState.commitments.availableBalanceForSend + 1.msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, initialState.commitments.availableBalanceForSend + 1.msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
|
||||
val error = InsufficientFunds(channelId(alice), amount = add.amount, missing = 0 sat, reserve = 20000 sat, fees = 3900 sat)
|
||||
|
@ -235,7 +235,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
import f._
|
||||
val sender = TestProbe()
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
val add = CMD_ADD_HTLC(sender.ref, initialState.commitments.availableBalanceForSend + 1.msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, initialState.commitments.availableBalanceForSend + 1.msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
bob ! add
|
||||
|
||||
val error = InsufficientFunds(channelId(alice), amount = add.amount, missing = 0 sat, reserve = 10000 sat, fees = 0 sat)
|
||||
|
@ -253,7 +253,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
// At this point alice has the minimal amount to sustain a channel.
|
||||
// Alice maintains an extra reserve to accommodate for a few more HTLCs, so the first few HTLCs should be allowed.
|
||||
val htlcs = (1 to 7).map { _ =>
|
||||
bob ! CMD_ADD_HTLC(sender.ref, 12_000_000 msat, randomBytes32(), CltvExpiry(400144), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
bob ! CMD_ADD_HTLC(sender.ref, 12_000_000 msat, randomBytes32(), CltvExpiry(400144), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
val add = bob2alice.expectMsgType[UpdateAddHtlc]
|
||||
bob2alice.forward(alice, add)
|
||||
|
@ -261,7 +261,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
}
|
||||
|
||||
// But this one will dip alice below her reserve: we must wait for the previous HTLCs to settle before sending any more.
|
||||
val failedAdd = CMD_ADD_HTLC(sender.ref, 11_000_000 msat, randomBytes32(), CltvExpiry(400144), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val failedAdd = CMD_ADD_HTLC(sender.ref, 11_000_000 msat, randomBytes32(), CltvExpiry(400144), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
bob ! failedAdd
|
||||
val error = RemoteCannotAffordFeesForNewHtlc(channelId(bob), failedAdd.amount, missing = 1360 sat, 20_000 sat, 22_720 sat)
|
||||
sender.expectMsg(RES_ADD_FAILED(failedAdd, error, Some(bob.stateData.asInstanceOf[DATA_NORMAL].channelUpdate)))
|
||||
|
@ -285,13 +285,13 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
|
||||
// At this point alice has the minimal amount to sustain a channel.
|
||||
// Alice maintains an extra reserve to accommodate for a one more HTLCs, so the first few HTLCs should be allowed.
|
||||
bob ! CMD_ADD_HTLC(sender.ref, 25_000_000 msat, randomBytes32(), CltvExpiry(400144), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
bob ! CMD_ADD_HTLC(sender.ref, 25_000_000 msat, randomBytes32(), CltvExpiry(400144), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
val add = bob2alice.expectMsgType[UpdateAddHtlc]
|
||||
bob2alice.forward(alice, add)
|
||||
|
||||
// But this one will dip alice below her reserve: we must wait for the previous HTLCs to settle before sending any more.
|
||||
val failedAdd = CMD_ADD_HTLC(sender.ref, 25_000_000 msat, randomBytes32(), CltvExpiry(400144), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val failedAdd = CMD_ADD_HTLC(sender.ref, 25_000_000 msat, randomBytes32(), CltvExpiry(400144), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
bob ! failedAdd
|
||||
val error = RemoteCannotAffordFeesForNewHtlc(channelId(bob), failedAdd.amount, missing = 340 sat, 20_000 sat, 21_700 sat)
|
||||
sender.expectMsg(RES_ADD_FAILED(failedAdd, error, Some(bob.stateData.asInstanceOf[DATA_NORMAL].channelUpdate)))
|
||||
|
@ -306,16 +306,16 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
import f._
|
||||
val sender = TestProbe()
|
||||
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 500000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 500000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 200000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 200000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 51760000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 51760000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
val add = CMD_ADD_HTLC(sender.ref, 1000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 1000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
val error = InsufficientFunds(channelId(alice), amount = 1000000 msat, missing = 1000 sat, reserve = 20000 sat, fees = 12400 sat)
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -326,13 +326,13 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
import f._
|
||||
val sender = TestProbe()
|
||||
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 300000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 300000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 300000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 300000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
val error = InsufficientFunds(channelId(alice), amount = 500000000 msat, missing = 348240 sat, reserve = 20000 sat, fees = 12400 sat)
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -345,7 +345,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
assert(initialState.commitments.params.localParams.maxHtlcValueInFlightMsat == initialState.commitments.latest.capacity.toMilliSatoshi)
|
||||
assert(initialState.commitments.params.remoteParams.maxHtlcValueInFlightMsat == UInt64(150000000))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 151000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 151000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
bob ! add
|
||||
val error = HtlcValueTooHighInFlight(channelId(bob), maximum = 150000000 msat, actual = 151000000 msat)
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -358,11 +358,11 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
assert(initialState.commitments.params.localParams.maxHtlcValueInFlightMsat == initialState.commitments.latest.capacity.toMilliSatoshi)
|
||||
assert(initialState.commitments.params.remoteParams.maxHtlcValueInFlightMsat == UInt64(150000000))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 75500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 75500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
bob ! add
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
bob2alice.expectMsgType[UpdateAddHtlc]
|
||||
val add1 = CMD_ADD_HTLC(sender.ref, 75500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add1 = CMD_ADD_HTLC(sender.ref, 75500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
bob ! add1
|
||||
val error = HtlcValueTooHighInFlight(channelId(bob), maximum = 150000000 msat, actual = 151000000 msat)
|
||||
sender.expectMsg(RES_ADD_FAILED(add1, error, Some(initialState.channelUpdate)))
|
||||
|
@ -375,7 +375,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
|
||||
assert(initialState.commitments.params.localParams.maxHtlcValueInFlightMsat == 150000000.msat)
|
||||
assert(initialState.commitments.params.remoteParams.maxHtlcValueInFlightMsat == UInt64(initialState.commitments.latest.capacity.toMilliSatoshi.toLong))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 151000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 151000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
val error = HtlcValueTooHighInFlight(channelId(alice), maximum = 150000000 msat, actual = 151000000 msat)
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -389,11 +389,11 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
assert(initialState.commitments.params.localParams.maxAcceptedHtlcs == 100)
|
||||
assert(initialState.commitments.params.remoteParams.maxAcceptedHtlcs == 30) // Bob accepts a maximum of 30 htlcs
|
||||
for (_ <- 0 until 30) {
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 10000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 10000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
}
|
||||
val add = CMD_ADD_HTLC(sender.ref, 10000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 10000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
val error = TooManyAcceptedHtlcs(channelId(alice), maximum = 30)
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -407,11 +407,11 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
assert(initialState.commitments.params.localParams.maxAcceptedHtlcs == 30) // Bob accepts a maximum of 30 htlcs
|
||||
assert(initialState.commitments.params.remoteParams.maxAcceptedHtlcs == 100) // Alice accepts more, but Bob will stop at 30 HTLCs
|
||||
for (_ <- 0 until 30) {
|
||||
bob ! CMD_ADD_HTLC(sender.ref, 500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
bob ! CMD_ADD_HTLC(sender.ref, 500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
bob2alice.expectMsgType[UpdateAddHtlc]
|
||||
}
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
bob ! add
|
||||
val error = TooManyAcceptedHtlcs(channelId(bob), maximum = 30)
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -444,18 +444,18 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
crossSign(bob, alice, bob2alice, alice2bob)
|
||||
|
||||
// HTLCs that take Alice's dust exposure above her threshold are rejected.
|
||||
val dustAdd = CMD_ADD_HTLC(sender.ref, 501.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val dustAdd = CMD_ADD_HTLC(sender.ref, 501.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! dustAdd
|
||||
sender.expectMsg(RES_ADD_FAILED(dustAdd, LocalDustHtlcExposureTooHigh(channelId(alice), 25000.sat, 25001.sat.toMilliSatoshi), Some(initialState.channelUpdate)))
|
||||
val trimmedAdd = CMD_ADD_HTLC(sender.ref, 5000.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val trimmedAdd = CMD_ADD_HTLC(sender.ref, 5000.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! trimmedAdd
|
||||
sender.expectMsg(RES_ADD_FAILED(trimmedAdd, LocalDustHtlcExposureTooHigh(channelId(alice), 25000.sat, 29500.sat.toMilliSatoshi), Some(initialState.channelUpdate)))
|
||||
val justAboveTrimmedAdd = CMD_ADD_HTLC(sender.ref, 8500.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val justAboveTrimmedAdd = CMD_ADD_HTLC(sender.ref, 8500.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! justAboveTrimmedAdd
|
||||
sender.expectMsg(RES_ADD_FAILED(justAboveTrimmedAdd, LocalDustHtlcExposureTooHigh(channelId(alice), 25000.sat, 33000.sat.toMilliSatoshi), Some(initialState.channelUpdate)))
|
||||
|
||||
// HTLCs that don't contribute to dust exposure are accepted.
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 25000.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 25000.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
}
|
||||
|
@ -481,7 +481,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
addHtlc(1500.sat.toMilliSatoshi, alice, bob, alice2bob, bob2alice)
|
||||
|
||||
// HTLCs that take Alice's dust exposure above her threshold are rejected.
|
||||
val add = CMD_ADD_HTLC(sender.ref, 1001.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 1001.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
sender.expectMsg(RES_ADD_FAILED(add, LocalDustHtlcExposureTooHigh(channelId(alice), 25000.sat, 25001.sat.toMilliSatoshi), Some(initialState.channelUpdate)))
|
||||
}
|
||||
|
@ -505,7 +505,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
(1 to 3).foreach(_ => addHtlc(1050.sat.toMilliSatoshi, alice, bob, alice2bob, bob2alice))
|
||||
|
||||
// HTLCs that take Alice's dust exposure above her threshold are rejected.
|
||||
val add = CMD_ADD_HTLC(sender.ref, 1050.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 1050.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
sender.expectMsg(RES_ADD_FAILED(add, LocalDustHtlcExposureTooHigh(channelId(alice), 25000.sat, 25200.sat.toMilliSatoshi), Some(initialState.channelUpdate)))
|
||||
}
|
||||
|
@ -529,7 +529,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
(1 to 8).foreach(_ => addHtlc(1050.sat.toMilliSatoshi, bob, alice, bob2alice, alice2bob))
|
||||
|
||||
// HTLCs that take Bob's dust exposure above his threshold are rejected.
|
||||
val add = CMD_ADD_HTLC(sender.ref, 1050.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 1050.sat.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
bob ! add
|
||||
sender.expectMsg(RES_ADD_FAILED(add, RemoteDustHtlcExposureTooHigh(channelId(bob), 30000.sat, 30450.sat.toMilliSatoshi), Some(initialState.channelUpdate)))
|
||||
}
|
||||
|
@ -538,14 +538,14 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
import f._
|
||||
val sender = TestProbe()
|
||||
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
|
||||
val add1 = CMD_ADD_HTLC(sender.ref, TestConstants.fundingSatoshis.toMilliSatoshi * 2 / 3, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add1 = CMD_ADD_HTLC(sender.ref, TestConstants.fundingSatoshis.toMilliSatoshi * 2 / 3, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add1
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
alice ! CMD_SIGN()
|
||||
alice2bob.expectMsgType[CommitSig]
|
||||
// this is over channel-capacity
|
||||
val add2 = CMD_ADD_HTLC(sender.ref, TestConstants.fundingSatoshis.toMilliSatoshi * 2 / 3, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add2 = CMD_ADD_HTLC(sender.ref, TestConstants.fundingSatoshis.toMilliSatoshi * 2 / 3, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add2
|
||||
val error = InsufficientFunds(channelId(alice), add2.amount, 578133 sat, 20000 sat, 10680 sat)
|
||||
sender.expectMsg(RES_ADD_FAILED(add2, error, Some(initialState.channelUpdate)))
|
||||
|
@ -562,7 +562,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
val upstream = localOrigin(sender.ref)
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, upstream)
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, upstream)
|
||||
bob ! add
|
||||
val error = FeerateTooDifferent(channelId(bob), FeeratePerKw(20000 sat), FeeratePerKw(10000 sat))
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -587,7 +587,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
awaitCond(alice.stateData.asInstanceOf[DATA_NORMAL].localShutdown.isDefined && alice.stateData.asInstanceOf[DATA_NORMAL].remoteShutdown.isEmpty)
|
||||
|
||||
// actual test starts here
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
val error = NoMoreHtlcsClosingInProgress(channelId(alice))
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, Some(initialState.channelUpdate)))
|
||||
|
@ -599,14 +599,14 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val sender = TestProbe()
|
||||
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
|
||||
// let's make alice send an htlc
|
||||
val add1 = CMD_ADD_HTLC(sender.ref, 50000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add1 = CMD_ADD_HTLC(sender.ref, 50000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add1
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
// at the same time bob initiates a closing
|
||||
bob ! CMD_CLOSE(sender.ref, None, None)
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_CLOSE]]
|
||||
// this command will be received by alice right after having received the shutdown
|
||||
val add2 = CMD_ADD_HTLC(sender.ref, 10000000 msat, randomBytes32(), CltvExpiry(300000), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add2 = CMD_ADD_HTLC(sender.ref, 10000000 msat, randomBytes32(), CltvExpiry(300000), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
// messages cross
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
alice2bob.forward(bob)
|
||||
|
@ -620,7 +620,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
test("recv UpdateAddHtlc") { f =>
|
||||
import f._
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, 150000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, 150000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
bob ! htlc
|
||||
awaitCond(bob.stateData == initialState
|
||||
.modify(_.commitments.changes.remoteChanges.proposed).using(_ :+ htlc)
|
||||
|
@ -632,7 +632,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
test("recv UpdateAddHtlc (unexpected id)") { f =>
|
||||
import f._
|
||||
val tx = bob.stateData.asInstanceOf[DATA_NORMAL].commitments.latest.localCommit.commitTxAndRemoteSig.commitTx.tx
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 42, 150000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 42, 150000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
bob ! htlc.copy(id = 0)
|
||||
bob ! htlc.copy(id = 1)
|
||||
bob ! htlc.copy(id = 2)
|
||||
|
@ -649,7 +649,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
test("recv UpdateAddHtlc (value too small)") { f =>
|
||||
import f._
|
||||
val tx = bob.stateData.asInstanceOf[DATA_NORMAL].commitments.latest.localCommit.commitTxAndRemoteSig.commitTx.tx
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, 150 msat, randomBytes32(), cltvExpiry = CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, 150 msat, randomBytes32(), cltvExpiry = CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
alice2bob.forward(bob, htlc)
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data.toArray) == HtlcValueTooSmall(channelId(bob), minimum = 1000 msat, actual = 150 msat).getMessage)
|
||||
|
@ -664,7 +664,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
test("recv UpdateAddHtlc (insufficient funds)") { f =>
|
||||
import f._
|
||||
val tx = bob.stateData.asInstanceOf[DATA_NORMAL].commitments.latest.localCommit.commitTxAndRemoteSig.commitTx.tx
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, MilliSatoshi(Long.MaxValue), randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, MilliSatoshi(Long.MaxValue), randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
alice2bob.forward(bob, htlc)
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data.toArray) == InsufficientFunds(channelId(bob), amount = MilliSatoshi(Long.MaxValue), missing = 9223372036083735L sat, reserve = 20000 sat, fees = 8960 sat).getMessage)
|
||||
|
@ -679,9 +679,9 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
test("recv UpdateAddHtlc (insufficient funds w/ pending htlcs) (anchor outputs)", Tag(ChannelStateTestsTags.AnchorOutputs)) { f =>
|
||||
import f._
|
||||
val tx = bob.stateData.asInstanceOf[DATA_NORMAL].commitments.latest.localCommit.commitTxAndRemoteSig.commitTx.tx
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 0, 400000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 1, 300000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 2, 100000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 0, 400000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 1, 300000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 2, 100000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data.toArray) == InsufficientFunds(channelId(bob), amount = 100000000 msat, missing = 24760 sat, reserve = 20000 sat, fees = 4760 sat).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
|
@ -693,10 +693,10 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
test("recv UpdateAddHtlc (insufficient funds w/ pending htlcs 1/2)") { f =>
|
||||
import f._
|
||||
val tx = bob.stateData.asInstanceOf[DATA_NORMAL].commitments.latest.localCommit.commitTxAndRemoteSig.commitTx.tx
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 0, 400000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 1, 200000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 2, 167600000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 3, 10000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 0, 400000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 1, 200000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 2, 167600000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 3, 10000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data.toArray) == InsufficientFunds(channelId(bob), amount = 10000000 msat, missing = 11720 sat, reserve = 20000 sat, fees = 14120 sat).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
|
@ -710,9 +710,9 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
test("recv UpdateAddHtlc (insufficient funds w/ pending htlcs 2/2)") { f =>
|
||||
import f._
|
||||
val tx = bob.stateData.asInstanceOf[DATA_NORMAL].commitments.latest.localCommit.commitTxAndRemoteSig.commitTx.tx
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 0, 300000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 1, 300000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 2, 500000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 0, 300000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 1, 300000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 2, 500000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data.toArray) == InsufficientFunds(channelId(bob), amount = 500000000 msat, missing = 332400 sat, reserve = 20000 sat, fees = 12400 sat).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
|
@ -726,7 +726,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
test("recv UpdateAddHtlc (over max inflight htlc value)", Tag(ChannelStateTestsTags.AliceLowMaxHtlcValueInFlight)) { f =>
|
||||
import f._
|
||||
val tx = alice.stateData.asInstanceOf[DATA_NORMAL].commitments.latest.localCommit.commitTxAndRemoteSig.commitTx.tx
|
||||
alice2bob.forward(alice, UpdateAddHtlc(ByteVector32.Zeroes, 0, 151000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(alice, UpdateAddHtlc(ByteVector32.Zeroes, 0, 151000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
val error = alice2bob.expectMsgType[Error]
|
||||
assert(new String(error.data.toArray) == HtlcValueTooHighInFlight(channelId(alice), maximum = 150000000 msat, actual = 151000000 msat).getMessage)
|
||||
awaitCond(alice.stateName == CLOSING)
|
||||
|
@ -742,9 +742,9 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val tx = bob.stateData.asInstanceOf[DATA_NORMAL].commitments.latest.localCommit.commitTxAndRemoteSig.commitTx.tx
|
||||
// Bob accepts a maximum of 30 htlcs
|
||||
for (i <- 0 until 30) {
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, i, 1000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, i, 1000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
}
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 30, 1000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.forward(bob, UpdateAddHtlc(ByteVector32.Zeroes, 30, 1000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data.toArray) == TooManyAcceptedHtlcs(channelId(bob), maximum = 30).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
|
@ -767,7 +767,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
test("recv CMD_SIGN (two identical htlcs in each direction)") { f =>
|
||||
import f._
|
||||
val sender = TestProbe()
|
||||
val add = CMD_ADD_HTLC(sender.ref, 10000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 10000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
|
@ -818,19 +818,19 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
assert(a2b_2 > aliceMinOffer && a2b_2 > bobMinReceive)
|
||||
assert(b2a_1 > aliceMinReceive && b2a_1 > bobMinOffer)
|
||||
assert(b2a_2 < aliceMinReceive && b2a_2 > bobMinOffer)
|
||||
alice ! CMD_ADD_HTLC(sender.ref, a2b_1.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, a2b_1.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
alice2bob.forward(bob)
|
||||
alice ! CMD_ADD_HTLC(sender.ref, a2b_2.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, a2b_2.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
alice2bob.forward(bob)
|
||||
bob ! CMD_ADD_HTLC(sender.ref, b2a_1.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
bob ! CMD_ADD_HTLC(sender.ref, b2a_1.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
bob2alice.expectMsgType[UpdateAddHtlc]
|
||||
bob2alice.forward(alice)
|
||||
bob ! CMD_ADD_HTLC(sender.ref, b2a_2.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
bob ! CMD_ADD_HTLC(sender.ref, b2a_2.toMilliSatoshi, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
bob2alice.expectMsgType[UpdateAddHtlc]
|
||||
bob2alice.forward(alice)
|
||||
|
@ -850,7 +850,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
test("recv CMD_SIGN (htlcs with same pubkeyScript but different amounts)") { f =>
|
||||
import f._
|
||||
val sender = TestProbe()
|
||||
val add = CMD_ADD_HTLC(sender.ref, 10000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 10000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
val epsilons = List(3, 1, 5, 7, 6) // unordered on purpose
|
||||
val htlcCount = epsilons.size
|
||||
for (i <- epsilons) {
|
||||
|
@ -1184,12 +1184,12 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
val r = randomBytes32()
|
||||
val h = Crypto.sha256(r)
|
||||
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 50000000 msat, h, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 50000000 msat, h, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
val htlc1 = alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
alice2bob.forward(bob)
|
||||
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 50000000 msat, h, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 50000000 msat, h, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
val htlc2 = alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
alice2bob.forward(bob)
|
||||
|
@ -2271,7 +2271,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
bob2alice.expectNoMessage(250 millis) // we don't close because the commitment doesn't contain any HTLC
|
||||
|
||||
// when we try to add an HTLC, we still disagree on the feerate so we close
|
||||
alice2bob.send(bob, UpdateAddHtlc(ByteVector32.Zeroes, 0, 2500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.send(bob, UpdateAddHtlc(ByteVector32.Zeroes, 0, 2500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data.toArray).contains("local/remote feerates are too different"))
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
|
@ -2299,7 +2299,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
assert(initialState.commitments.latest.localCommit.spec.commitTxFeerate == TestConstants.anchorOutputsFeeratePerKw)
|
||||
val add = UpdateAddHtlc(ByteVector32.Zeroes, 0, 2500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.Zeroes, 0, 2500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
alice2bob.send(bob, add)
|
||||
val fee = UpdateFee(initialState.channelId, FeeratePerKw(FeeratePerByte(2 sat)))
|
||||
alice2bob.send(bob, fee)
|
||||
|
@ -3067,7 +3067,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
bob2alice.expectNoMessage(250 millis) // we don't close because the commitment doesn't contain any HTLC
|
||||
|
||||
// when we try to add an HTLC, we still disagree on the feerate so we close
|
||||
alice2bob.send(bob, UpdateAddHtlc(ByteVector32.Zeroes, 0, 2500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None))
|
||||
alice2bob.send(bob, UpdateAddHtlc(ByteVector32.Zeroes, 0, 2500000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
bob2alice.expectMsgType[Error]
|
||||
bob2blockchain.expectMsgType[PublishTx] // commit tx
|
||||
bob2blockchain.expectMsgType[PublishTx] // main delayed
|
||||
|
@ -3315,7 +3315,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
// alice = 800 000
|
||||
// bob = 200 000
|
||||
|
||||
val add = CMD_ADD_HTLC(sender.ref, 10000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 10000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
|
|
|
@ -80,7 +80,7 @@ class OfflineStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
// |--- sig --X |
|
||||
// | |
|
||||
val sender = TestProbe()
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 1000000 msat, ByteVector32.Zeroes, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 1000000 msat, ByteVector32.Zeroes, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
val htlc = alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
// bob receives the htlc
|
||||
alice2bob.forward(bob)
|
||||
|
@ -134,7 +134,7 @@ class OfflineStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
// | X-- rev ---|
|
||||
// | X-- sig ---|
|
||||
val sender = TestProbe()
|
||||
alice ! CMD_ADD_HTLC(ActorRef.noSender, 1000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(ActorRef.noSender, 1000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
val htlc = alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
// bob receives the htlc and the signature
|
||||
alice2bob.forward(bob, htlc)
|
||||
|
@ -178,7 +178,7 @@ class OfflineStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
// |<--- rev ---|
|
||||
// | X-- sig ---|
|
||||
val sender = TestProbe()
|
||||
alice ! CMD_ADD_HTLC(ActorRef.noSender, 1000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(ActorRef.noSender, 1000000 msat, randomBytes32(), CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
val htlc = alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
// bob receives the htlc and the signature
|
||||
alice2bob.forward(bob, htlc)
|
||||
|
@ -511,7 +511,7 @@ class OfflineStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
channelUpdateListener.expectNoMessage(300 millis)
|
||||
|
||||
// we attempt to send a payment
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 4200 msat, randomBytes32(), CltvExpiry(123456), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
alice ! CMD_ADD_HTLC(sender.ref, 4200 msat, randomBytes32(), CltvExpiry(123456), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
sender.expectMsgType[RES_ADD_FAILED[ChannelUnavailable]]
|
||||
|
||||
// alice will broadcast a new disabled channel_update
|
||||
|
|
|
@ -60,7 +60,7 @@ class ShutdownStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike wit
|
|||
// alice sends an HTLC to bob
|
||||
val h1 = Crypto.sha256(r1)
|
||||
val recipient1 = SpontaneousRecipient(TestConstants.Bob.nodeParams.nodeId, 300_000_000 msat, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), r1)
|
||||
val Right(cmd1) = OutgoingPaymentPacket.buildOutgoingPayment(localOrigin(sender.ref), h1, makeSingleHopRoute(recipient1.totalAmount, recipient1.nodeId), recipient1).map(_.cmd.copy(commit = false))
|
||||
val Right(cmd1) = OutgoingPaymentPacket.buildOutgoingPayment(localOrigin(sender.ref), h1, makeSingleHopRoute(recipient1.totalAmount, recipient1.nodeId), recipient1, 1.0).map(_.cmd.copy(commit = false))
|
||||
alice ! cmd1
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
val htlc1 = alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
|
@ -69,7 +69,7 @@ class ShutdownStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike wit
|
|||
// alice sends another HTLC to bob
|
||||
val h2 = Crypto.sha256(r2)
|
||||
val recipient2 = SpontaneousRecipient(TestConstants.Bob.nodeParams.nodeId, 200_000_000 msat, CltvExpiryDelta(144).toCltvExpiry(currentBlockHeight), r2)
|
||||
val Right(cmd2) = OutgoingPaymentPacket.buildOutgoingPayment(localOrigin(sender.ref), h2, makeSingleHopRoute(recipient2.totalAmount, recipient2.nodeId), recipient2).map(_.cmd.copy(commit = false))
|
||||
val Right(cmd2) = OutgoingPaymentPacket.buildOutgoingPayment(localOrigin(sender.ref), h2, makeSingleHopRoute(recipient2.totalAmount, recipient2.nodeId), recipient2, 1.0).map(_.cmd.copy(commit = false))
|
||||
alice ! cmd2
|
||||
sender.expectMsgType[RES_SUCCESS[CMD_ADD_HTLC]]
|
||||
val htlc2 = alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
|
@ -141,7 +141,7 @@ class ShutdownStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike wit
|
|||
test("recv CMD_ADD_HTLC") { f =>
|
||||
import f._
|
||||
val sender = TestProbe()
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000000 msat, r1, cltvExpiry = CltvExpiry(300000), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000000 msat, r1, cltvExpiry = CltvExpiry(300000), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
val error = ChannelUnavailable(channelId(alice))
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, None))
|
||||
|
|
|
@ -123,7 +123,7 @@ class NegotiatingStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
aliceClose(f)
|
||||
alice2bob.expectMsgType[ClosingSigned]
|
||||
val sender = TestProbe()
|
||||
val add = CMD_ADD_HTLC(sender.ref, 5000000000L msat, randomBytes32(), CltvExpiry(300000), TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 5000000000L msat, randomBytes32(), CltvExpiry(300000), TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
val error = ChannelUnavailable(channelId(alice))
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, None))
|
||||
|
|
|
@ -267,7 +267,7 @@ class ClosingStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
|
|||
|
||||
// actual test starts here
|
||||
val sender = TestProbe()
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000000 msat, ByteVector32(ByteVector.fill(32)(1)), cltvExpiry = CltvExpiry(300000), onion = TestConstants.emptyOnionPacket, None, localOrigin(sender.ref))
|
||||
val add = CMD_ADD_HTLC(sender.ref, 500000000 msat, ByteVector32(ByteVector.fill(32)(1)), cltvExpiry = CltvExpiry(300000), onion = TestConstants.emptyOnionPacket, None, 1.0, localOrigin(sender.ref))
|
||||
alice ! add
|
||||
val error = ChannelUnavailable(channelId(alice))
|
||||
sender.expectMsg(RES_ADD_FAILED(add, error, None))
|
||||
|
|
|
@ -57,7 +57,7 @@ class SynchronizationPipe(latch: CountDownLatch) extends Actor with ActorLogging
|
|||
|
||||
(script: @unchecked) match {
|
||||
case offer(x, amount, rhash) :: rest =>
|
||||
resolve(x) ! CMD_ADD_HTLC(self, MilliSatoshi(amount.toInt), ByteVector32.fromValidHex(rhash), CltvExpiry(144), TestConstants.emptyOnionPacket, None, Origin.Hot(self, Upstream.Local(UUID.randomUUID())))
|
||||
resolve(x) ! CMD_ADD_HTLC(self, MilliSatoshi(amount.toInt), ByteVector32.fromValidHex(rhash), CltvExpiry(144), TestConstants.emptyOnionPacket, None, 1.0, Origin.Hot(self, Upstream.Local(UUID.randomUUID())))
|
||||
exec(rest, a, b)
|
||||
case fulfill(x, id, r) :: rest =>
|
||||
resolve(x) ! CMD_FULFILL_HTLC(id.toInt, ByteVector32.fromValidHex(r))
|
||||
|
|
|
@ -253,7 +253,8 @@ class JsonSerializersSpec extends TestKitBaseClass with AnyFunSuiteLike with Mat
|
|||
payload = hex"3c7a66997c681a3de1bae56438abeee4fc50a16554725a430ade1dc8db6bdd76704d45c6151c4051d710cf487e63f8cbe9f5e537e6e518d7998f11c40277d551bee036d227a421f344c0185b4533660d200acbc4f4aa6148e29f813bb537e950a79ba961b80ccaa6ad808cb88f858ee73f8b1f129d3214d194f76fc011c46e18c2caec0fcb69715e79cb381e449e5be20281e0aaa92defa089c98b7e29c22181f2d1af9f5fe2a37ede4ac3163b123aa72318201b1128b17053c381e7bf111620dfb7ea3dcc5c28cafdd9cb7bb1a4202b64199aa02af145c563ba1b9f10288203ce2666f486aacb2ee385dc0b67915864c95174dfaac1e0ea195329d1741cd1febb4b49b33f84e0d10a5ec8ee0a1a94f73abf081ec69bb863edfeb46d24ce424b025ac3f593a7ba9419ec9b17fb39f0fbeac80e0898f95b6709cbc95f7c097e22e3a6ca0efbc947bbcd4a9077f6bd9daba25b18bb16179fca9d9cb2ce49fc7cbd2de589237926cacb87ea60e2cc60a90b47575517921b5529b8a95823dd0c3d02a7747d74c4ca927ba6b70c06c1c1ef27e14d371e8dd8f5d9380a65b08ae1e6384f9b3575c5d7278de22ce80e63612a27f3b3f45dbe32ee855185293c719e5a7203a682a08fd810c46fa12b67e61349831f8fae3f558090ea988e1a22ec877b790ea09169055529247c4dd597857aad74eaeb3a5879e96453e681e213f2796ed704d620509f34f91d9d16f881fd397e2836a0a4d2f1bcd230067f7acb5381a2b17e8c5135e38c4d258afbe4f69ac7ad39b789e99686ee926b3ad31b98993673313b7b18a4faaea238d8055824fde7339a791fc7777ef28cc4a1a5d177b3c3882ced4921c6cd85ae82e1fe13fe680ae432a9918ce37b15f88d4d18fb16b69e5369d18c204aaf7ee49b830bf2328380e6ad96e8f6a9e01bc2c97ffbaa402d5406dc7b83c6eb5d515ffc3bea8c42cf299c9e2bea693515246c6ff859d33ba6c4da4c4c1706e0c6b4a574e927f02eb92b7d56722cff80c3e6f6b98d1c84cb576abdcc27a6bc7b110fc2ac5fead57f05ad854c3331ce1ff94c0dc97303540ee797d71566497af09f20e3554d467528e1fed8e69438171072fe2deca3979a8f5ec9043b9bc4da921b095c29dc0294148c1b7001dafda4c48600d1194f745e6d0689c561bf19d20758c4d25fac64d81780607a4106e220ef546fc4026af7b9da8defb2fe3c21d48798ac67c794fb40aabe44618a8911673466be06808c6f54a772b87bcfafb4d120a9bebffb8051bf24bb332eaa769cf175c1aadb0186f8946dc32513fd81fe1a61bfb860886bdd070359a43e06e74607d300bd2e01a3f1ee900c4039e8db742170228db61ef0c77724c49d1573144564a80cc1ebc0449b34f84be35187ceba3fbc2facf5ad1f1e15945e3c6c236579aca7bc97e4cc76a3310022693b64008562b254a7d11c0086813e551c4817bbb72a1d6fbfc84d326ce973651200f80aa8ab0976c53c390249ca8e7e5ec21b80e70c3e0205983d313b28a5d1b9d9149501e05d3257c8ae88c6308e9e00feeab19121d1032a582e68ca1f9f64a1fd91cb5d8613b985fd4be22a4d5c14a132c20811a75ee3cc61de0b3fbc3254d61995d086603032269888b942ec0971ad26ea4b8df1746c5ec1de904ddeb5045abc0a6ede9d6a199ed0782cb69efa3a4dc00747553dbef12fb8299ca364b4cdf2ac3eba03b0d8b273684116bba4458b5717bc4aca5406901173a89b3643ccc076f22779fccf1ad69981e24eef18c711a2d58dfe5834b41f9e7166d54dc8628e754baaca1cbb7db8256f88ebc889de6078ba83a1af14a4",
|
||||
hmac = ByteVector32(hex"9442626f72c475963dbddf8a57ab2cef3013eb3d6a5e8afbea9e631dac4481f5")
|
||||
),
|
||||
blinding_opt = None
|
||||
blinding_opt = None,
|
||||
confidence = 0.7,
|
||||
)
|
||||
|
||||
val expectedIn = """{"direction":"IN","id":926,"amountMsat":12365,"paymentHash":"9fcd45bbaa09c60c991ac0425704163c3f3d2d683c789fa409455b9c97792692","cltvExpiry":621500}"""
|
||||
|
|
|
@ -96,7 +96,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
}
|
||||
|
||||
def createBlindedPacket(amount: MilliSatoshi, paymentHash: ByteVector32, expiry: CltvExpiry, finalExpiry: CltvExpiry, pathId: ByteVector): IncomingPaymentPacket.FinalPacket = {
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, amount, paymentHash, expiry, TestConstants.emptyOnionPacket, Some(randomKey().publicKey))
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, amount, paymentHash, expiry, TestConstants.emptyOnionPacket, Some(randomKey().publicKey), 1.0)
|
||||
val payload = FinalPayload.Blinded(TlvStream(AmountToForward(amount), TotalAmount(amount), OutgoingCltv(finalExpiry), EncryptedRecipientData(hex"deadbeef")), TlvStream(PathId(pathId), PaymentConstraints(CltvExpiry(500_000), 1 msat)))
|
||||
IncomingPaymentPacket.FinalPacket(add, payload)
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
assert(!incoming.get.invoice.isExpired())
|
||||
assert(Crypto.sha256(incoming.get.paymentPreimage) == invoice.paymentHash)
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 1, amountMsat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 1, amountMsat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithoutMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, add.amountMsat, add.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
assert(register.expectMsgType[Register.Forward[CMD_FULFILL_HTLC]].message.id == add.id)
|
||||
|
||||
|
@ -131,7 +131,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
sender.send(handlerWithoutMpp, ReceiveStandardPayment(sender.ref, Some(50_000 msat), Left("1 coffee with extra fees and expiry")))
|
||||
val invoice = sender.expectMsgType[Bolt11Invoice]
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 1, 75_000 msat, invoice.paymentHash, defaultExpiry + CltvExpiryDelta(12), TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 1, 75_000 msat, invoice.paymentHash, defaultExpiry + CltvExpiryDelta(12), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithoutMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(70_000 msat, 70_000 msat, defaultExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
assert(register.expectMsgType[Register.Forward[CMD_FULFILL_HTLC]].message.id == add.id)
|
||||
|
||||
|
@ -149,7 +149,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
assert(invoice.features.hasFeature(BasicMultiPartPayment))
|
||||
assert(nodeParams.db.payments.getIncomingPayment(invoice.paymentHash).get.status == IncomingPaymentStatus.Pending)
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 2, amountMsat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 2, amountMsat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, add.amountMsat, add.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
assert(register.expectMsgType[Register.Forward[CMD_FULFILL_HTLC]].message.id == add.id)
|
||||
|
||||
|
@ -196,7 +196,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val invoice = sender.expectMsgType[Bolt11Invoice]
|
||||
assert(nodeParams.db.payments.getIncomingPayment(invoice.paymentHash).get.status == IncomingPaymentStatus.Pending)
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, amountMsat, invoice.paymentHash, CltvExpiryDelta(3).toCltvExpiry(nodeParams.currentBlockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, amountMsat, invoice.paymentHash, CltvExpiryDelta(3).toCltvExpiry(nodeParams.currentBlockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, add.amountMsat, add.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
val cmd = register.expectMsgType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
assert(cmd.reason == Right(IncorrectOrUnknownPaymentDetails(amountMsat, nodeParams.currentBlockHeight)))
|
||||
|
@ -356,7 +356,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
assert(!invoice.features.hasFeature(BasicMultiPartPayment))
|
||||
assert(invoice.isExpired())
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 1000 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 1000 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithoutMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, add.amountMsat, add.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
register.expectMsgType[Register.Forward[CMD_FAIL_HTLC]]
|
||||
val Some(incoming) = nodeParams.db.payments.getIncomingPayment(invoice.paymentHash)
|
||||
|
@ -371,7 +371,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
assert(invoice.features.hasFeature(BasicMultiPartPayment))
|
||||
assert(invoice.isExpired())
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, 1000 msat, add.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
val cmd = register.expectMsgType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
assert(cmd.reason == Right(IncorrectOrUnknownPaymentDetails(1000 msat, nodeParams.currentBlockHeight)))
|
||||
|
@ -386,7 +386,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val invoice = sender.expectMsgType[Bolt11Invoice]
|
||||
assert(!invoice.features.hasFeature(BasicMultiPartPayment))
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithoutMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, 1000 msat, add.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
val cmd = register.expectMsgType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
assert(cmd.reason == Right(IncorrectOrUnknownPaymentDetails(1000 msat, nodeParams.currentBlockHeight)))
|
||||
|
@ -401,7 +401,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
assert(invoice.features.hasFeature(BasicMultiPartPayment))
|
||||
|
||||
val lowCltvExpiry = nodeParams.channelConf.fulfillSafetyBeforeTimeout.toCltvExpiry(nodeParams.currentBlockHeight)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, lowCltvExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, lowCltvExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, 1000 msat, add.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
val cmd = register.expectMsgType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
assert(cmd.reason == Right(IncorrectOrUnknownPaymentDetails(1000 msat, nodeParams.currentBlockHeight)))
|
||||
|
@ -415,7 +415,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val invoice = sender.expectMsgType[Bolt11Invoice]
|
||||
assert(invoice.features.hasFeature(BasicMultiPartPayment))
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash.reverse, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash.reverse, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, 1000 msat, add.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
val cmd = register.expectMsgType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
assert(cmd.reason == Right(IncorrectOrUnknownPaymentDetails(1000 msat, nodeParams.currentBlockHeight)))
|
||||
|
@ -429,7 +429,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val invoice = sender.expectMsgType[Bolt11Invoice]
|
||||
assert(invoice.features.hasFeature(BasicMultiPartPayment))
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, 999 msat, add.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
val cmd = register.expectMsgType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
assert(cmd.reason == Right(IncorrectOrUnknownPaymentDetails(999 msat, nodeParams.currentBlockHeight)))
|
||||
|
@ -443,7 +443,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val invoice = sender.expectMsgType[Bolt11Invoice]
|
||||
assert(invoice.features.hasFeature(BasicMultiPartPayment))
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, 2001 msat, add.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
val cmd = register.expectMsgType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
assert(cmd.reason == Right(IncorrectOrUnknownPaymentDetails(2001 msat, nodeParams.currentBlockHeight)))
|
||||
|
@ -458,7 +458,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
assert(invoice.features.hasFeature(BasicMultiPartPayment))
|
||||
|
||||
// Invalid payment secret.
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, 1000 msat, add.cltvExpiry, invoice.paymentSecret.reverse, invoice.paymentMetadata)))
|
||||
val cmd = register.expectMsgType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
assert(cmd.reason == Right(IncorrectOrUnknownPaymentDetails(1000 msat, nodeParams.currentBlockHeight)))
|
||||
|
@ -490,7 +490,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
sender.send(handlerWithRouteBlinding, ReceiveOfferPayment(sender.ref, nodeKey, invoiceReq, createEmptyReceivingRoute(), TestProbe().ref, randomBytes32(), randomBytes32()))
|
||||
val invoice = sender.expectMsgType[CreateInvoiceActor.InvoiceCreated].invoice
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 5000 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 5000 msat, invoice.paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, add.amountMsat, add.cltvExpiry, randomBytes32(), None)))
|
||||
val cmd = register.expectMsgType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
assert(cmd.reason == Right(IncorrectOrUnknownPaymentDetails(5000 msat, nodeParams.currentBlockHeight)))
|
||||
|
@ -571,13 +571,13 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
// Partial payment missing additional parts.
|
||||
f.sender.send(handler, ReceiveStandardPayment(f.sender.ref, Some(1000 msat), Left("1 slow coffee")))
|
||||
val pr1 = f.sender.expectMsgType[Bolt11Invoice]
|
||||
val add1 = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, pr1.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add1 = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, pr1.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
f.sender.send(handler, IncomingPaymentPacket.FinalPacket(add1, FinalPayload.Standard.createPayload(add1.amountMsat, 1000 msat, add1.cltvExpiry, pr1.paymentSecret, pr1.paymentMetadata)))
|
||||
|
||||
// Partial payment exceeding the invoice amount, but incomplete because it promises to overpay.
|
||||
f.sender.send(handler, ReceiveStandardPayment(f.sender.ref, Some(1500 msat), Left("1 slow latte")))
|
||||
val pr2 = f.sender.expectMsgType[Bolt11Invoice]
|
||||
val add2 = UpdateAddHtlc(ByteVector32.One, 1, 1600 msat, pr2.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add2 = UpdateAddHtlc(ByteVector32.One, 1, 1600 msat, pr2.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
f.sender.send(handler, IncomingPaymentPacket.FinalPacket(add2, FinalPayload.Standard.createPayload(add2.amountMsat, 2000 msat, add2.cltvExpiry, pr2.paymentSecret, pr2.paymentMetadata)))
|
||||
|
||||
awaitCond {
|
||||
|
@ -596,7 +596,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
})
|
||||
|
||||
// Extraneous HTLCs should be failed.
|
||||
f.sender.send(handler, MultiPartPaymentFSM.ExtraPaymentReceived(pr1.paymentHash, HtlcPart(1000 msat, UpdateAddHtlc(ByteVector32.One, 42, 200 msat, pr1.paymentHash, add1.cltvExpiry, add1.onionRoutingPacket, None)), Some(PaymentTimeout())))
|
||||
f.sender.send(handler, MultiPartPaymentFSM.ExtraPaymentReceived(pr1.paymentHash, HtlcPart(1000 msat, UpdateAddHtlc(ByteVector32.One, 42, 200 msat, pr1.paymentHash, add1.cltvExpiry, add1.onionRoutingPacket, None, 1.0)), Some(PaymentTimeout())))
|
||||
f.register.expectMsg(Register.Forward(null, ByteVector32.One, CMD_FAIL_HTLC(42, Right(PaymentTimeout()), commit = true)))
|
||||
|
||||
// The payment should still be pending in DB.
|
||||
|
@ -612,10 +612,10 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
f.sender.send(handler, ReceiveStandardPayment(f.sender.ref, Some(1000 msat), Left("1 fast coffee"), paymentPreimage_opt = Some(preimage)))
|
||||
val invoice = f.sender.expectMsgType[Bolt11Invoice]
|
||||
|
||||
val add1 = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add1 = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
f.sender.send(handler, IncomingPaymentPacket.FinalPacket(add1, FinalPayload.Standard.createPayload(add1.amountMsat, 1000 msat, add1.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
// Invalid payment secret -> should be rejected.
|
||||
val add2 = UpdateAddHtlc(ByteVector32.Zeroes, 42, 200 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add2 = UpdateAddHtlc(ByteVector32.Zeroes, 42, 200 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
f.sender.send(handler, IncomingPaymentPacket.FinalPacket(add2, FinalPayload.Standard.createPayload(add2.amountMsat, 1000 msat, add2.cltvExpiry, invoice.paymentSecret.reverse, invoice.paymentMetadata)))
|
||||
val add3 = add2.copy(id = 43)
|
||||
f.sender.send(handler, IncomingPaymentPacket.FinalPacket(add3, FinalPayload.Standard.createPayload(add3.amountMsat, 1000 msat, add3.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
|
@ -637,7 +637,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
})
|
||||
|
||||
// Extraneous HTLCs should be fulfilled.
|
||||
f.sender.send(handler, MultiPartPaymentFSM.ExtraPaymentReceived(invoice.paymentHash, HtlcPart(1000 msat, UpdateAddHtlc(ByteVector32.One, 44, 200 msat, invoice.paymentHash, add1.cltvExpiry, add1.onionRoutingPacket, None)), None))
|
||||
f.sender.send(handler, MultiPartPaymentFSM.ExtraPaymentReceived(invoice.paymentHash, HtlcPart(1000 msat, UpdateAddHtlc(ByteVector32.One, 44, 200 msat, invoice.paymentHash, add1.cltvExpiry, add1.onionRoutingPacket, None, 1.0)), None))
|
||||
f.register.expectMsg(Register.Forward(null, ByteVector32.One, CMD_FULFILL_HTLC(44, preimage, commit = true)))
|
||||
assert(f.eventListener.expectMsgType[PaymentReceived].amount == 200.msat)
|
||||
val received2 = nodeParams.db.payments.getIncomingPayment(invoice.paymentHash)
|
||||
|
@ -655,9 +655,9 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
f.sender.send(handler, ReceiveStandardPayment(f.sender.ref, Some(1000 msat), Left("1 coffee with tip please"), paymentPreimage_opt = Some(preimage)))
|
||||
val invoice = f.sender.expectMsgType[Bolt11Invoice]
|
||||
|
||||
val add1 = UpdateAddHtlc(randomBytes32(), 0, 1100 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add1 = UpdateAddHtlc(randomBytes32(), 0, 1100 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
f.sender.send(handler, IncomingPaymentPacket.FinalPacket(add1, FinalPayload.Standard.createPayload(add1.amountMsat, 1500 msat, add1.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
val add2 = UpdateAddHtlc(randomBytes32(), 1, 500 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add2 = UpdateAddHtlc(randomBytes32(), 1, 500 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
f.sender.send(handler, IncomingPaymentPacket.FinalPacket(add2, FinalPayload.Standard.createPayload(add2.amountMsat, 1500 msat, add2.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
|
||||
f.register.expectMsgAllOf(
|
||||
|
@ -682,7 +682,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
assert(invoice.features.hasFeature(BasicMultiPartPayment))
|
||||
assert(invoice.paymentHash == Crypto.sha256(preimage))
|
||||
|
||||
val add1 = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add1 = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
f.sender.send(handler, IncomingPaymentPacket.FinalPacket(add1, FinalPayload.Standard.createPayload(add1.amountMsat, 1000 msat, add1.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
f.register.expectMsg(Register.Forward(null, ByteVector32.One, CMD_FAIL_HTLC(0, Right(PaymentTimeout()), commit = true)))
|
||||
awaitCond({
|
||||
|
@ -690,9 +690,9 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
f.sender.expectMsgType[PendingPayments].paymentHashes.isEmpty
|
||||
})
|
||||
|
||||
val add2 = UpdateAddHtlc(ByteVector32.One, 2, 300 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add2 = UpdateAddHtlc(ByteVector32.One, 2, 300 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
f.sender.send(handler, IncomingPaymentPacket.FinalPacket(add2, FinalPayload.Standard.createPayload(add2.amountMsat, 1000 msat, add2.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
val add3 = UpdateAddHtlc(ByteVector32.Zeroes, 5, 700 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add3 = UpdateAddHtlc(ByteVector32.Zeroes, 5, 700 msat, invoice.paymentHash, f.defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
f.sender.send(handler, IncomingPaymentPacket.FinalPacket(add3, FinalPayload.Standard.createPayload(add3.amountMsat, 1000 msat, add3.cltvExpiry, invoice.paymentSecret, invoice.paymentMetadata)))
|
||||
|
||||
// the fulfill are not necessarily in the same order as the commands
|
||||
|
@ -724,7 +724,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
|
||||
assert(nodeParams.db.payments.getIncomingPayment(paymentHash).isEmpty)
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, amountMsat, paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, amountMsat, paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithKeySend, IncomingPaymentPacket.FinalPacket(add, payload))
|
||||
register.expectMsgType[Register.Forward[CMD_FULFILL_HTLC]]
|
||||
|
||||
|
@ -745,7 +745,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
|
||||
assert(nodeParams.db.payments.getIncomingPayment(paymentHash).isEmpty)
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, amountMsat, paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, amountMsat, paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithKeySend, IncomingPaymentPacket.FinalPacket(add, payload))
|
||||
register.expectMsgType[Register.Forward[CMD_FULFILL_HTLC]]
|
||||
|
||||
|
@ -767,7 +767,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
|
||||
assert(nodeParams.db.payments.getIncomingPayment(paymentHash).isEmpty)
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, amountMsat, paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, amountMsat, paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, payload))
|
||||
|
||||
f.register.expectMsg(Register.Forward(null, add.channelId, CMD_FAIL_HTLC(add.id, Right(IncorrectOrUnknownPaymentDetails(42000 msat, nodeParams.currentBlockHeight)), commit = true)))
|
||||
|
@ -781,7 +781,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val paymentSecret = randomBytes32()
|
||||
assert(nodeParams.db.payments.getIncomingPayment(paymentHash).isEmpty)
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 1000 msat, paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 1000 msat, paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithoutMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, add.amountMsat, add.cltvExpiry, paymentSecret, None)))
|
||||
val cmd = register.expectMsgType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
assert(cmd.id == add.id)
|
||||
|
@ -795,7 +795,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val paymentSecret = randomBytes32()
|
||||
assert(nodeParams.db.payments.getIncomingPayment(paymentHash).isEmpty)
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 800 msat, paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
sender.send(handlerWithMpp, IncomingPaymentPacket.FinalPacket(add, FinalPayload.Standard.createPayload(add.amountMsat, 1000 msat, add.cltvExpiry, paymentSecret, Some(hex"012345"))))
|
||||
val cmd = register.expectMsgType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
assert(cmd.id == add.id)
|
||||
|
@ -809,7 +809,7 @@ class MultiPartHandlerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val paymentHash = Crypto.sha256(paymentPreimage)
|
||||
assert(nodeParams.db.payments.getIncomingPayment(paymentHash).isEmpty)
|
||||
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 1000 msat, paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(ByteVector32.One, 0, 1000 msat, paymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val invoice = Bolt11Invoice(Block.TestnetGenesisBlock.hash, None, paymentHash, randomKey(), Left("dummy"), CltvExpiryDelta(12))
|
||||
val incomingPayment = IncomingStandardPayment(invoice, paymentPreimage, PaymentType.Standard, invoice.createdAt.toTimestampMilli, IncomingPaymentStatus.Pending)
|
||||
val fulfill = DoFulfill(incomingPayment, MultiPartPaymentFSM.MultiPartPaymentSucceeded(paymentHash, Queue(HtlcPart(1000 msat, add))))
|
||||
|
|
|
@ -232,7 +232,7 @@ object MultiPartPaymentFSMSpec {
|
|||
def htlcIdToChannelId(htlcId: Long) = ByteVector32(ByteVector.fromLong(htlcId).padLeft(32))
|
||||
|
||||
def createMultiPartHtlc(totalAmount: MilliSatoshi, htlcAmount: MilliSatoshi, htlcId: Long): HtlcPart = {
|
||||
val htlc = UpdateAddHtlc(htlcIdToChannelId(htlcId), htlcId, htlcAmount, paymentHash, CltvExpiry(42), TestConstants.emptyOnionPacket, None)
|
||||
val htlc = UpdateAddHtlc(htlcIdToChannelId(htlcId), htlcId, htlcAmount, paymentHash, CltvExpiry(42), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
HtlcPart(totalAmount, htlc)
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ class MultiPartPaymentLifecycleSpec extends TestKitBaseClass with FixtureAnyFunS
|
|||
|
||||
override def withFixture(test: OneArgTest): Outcome = {
|
||||
val id = UUID.randomUUID()
|
||||
val cfg = SendPaymentConfig(id, id, Some("42"), paymentHash, randomKey().publicKey, Upstream.Local(id), None, None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = true)
|
||||
val cfg = SendPaymentConfig(id, id, Some("42"), paymentHash, randomKey().publicKey, Upstream.Local(id), None, None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = true, confidence = 1.0)
|
||||
val nodeParams = TestConstants.Alice.nodeParams
|
||||
val (childPayFsm, router, sender, eventListener, metricsListener) = (TestProbe(), TestProbe(), TestProbe(), TestProbe(), TestProbe())
|
||||
val paymentHandler = TestFSMRef(new MultiPartPaymentLifecycle(nodeParams, cfg, publishPreimage = true, router.ref, FakePaymentFactory(childPayFsm)))
|
||||
|
|
|
@ -174,7 +174,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val request = SendPaymentToRoute(finalAmount, invoice, Nil, route, None, None, None)
|
||||
sender.send(initiator, request)
|
||||
val payment = sender.expectMsgType[SendPaymentToRouteResponse]
|
||||
payFsm.expectMsg(SendPaymentConfig(payment.paymentId, payment.parentId, None, paymentHash, c, Upstream.Local(payment.paymentId), Some(invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = false))
|
||||
payFsm.expectMsg(SendPaymentConfig(payment.paymentId, payment.parentId, None, paymentHash, c, Upstream.Local(payment.paymentId), Some(invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = false, confidence = 1.0))
|
||||
payFsm.expectMsg(PaymentLifecycle.SendPaymentToRoute(initiator, Left(route), ClearRecipient(invoice, finalAmount, finalExpiryDelta.toCltvExpiry(nodeParams.currentBlockHeight + 1), Set.empty)))
|
||||
|
||||
sender.send(initiator, GetPayment(PaymentIdentifier.PaymentUUID(payment.paymentId)))
|
||||
|
@ -199,7 +199,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
assert(req.finalExpiry(nodeParams) == (finalExpiryDelta + 1).toCltvExpiry(nodeParams.currentBlockHeight))
|
||||
sender.send(initiator, req)
|
||||
val id = sender.expectMsgType[UUID]
|
||||
payFsm.expectMsg(SendPaymentConfig(id, id, None, paymentHash, c, Upstream.Local(id), Some(invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = true))
|
||||
payFsm.expectMsg(SendPaymentConfig(id, id, None, paymentHash, c, Upstream.Local(id), Some(invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = true, confidence = 1.0))
|
||||
payFsm.expectMsg(PaymentLifecycle.SendPaymentToNode(initiator, ClearRecipient(invoice, finalAmount, req.finalExpiry(nodeParams), Set.empty), 1, nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams))
|
||||
|
||||
sender.send(initiator, GetPayment(PaymentIdentifier.PaymentUUID(id)))
|
||||
|
@ -222,7 +222,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val req = SendPaymentToNode(sender.ref, finalAmount + 100.msat, invoice, Nil, 1, routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams)
|
||||
sender.send(initiator, req)
|
||||
val id = sender.expectMsgType[UUID]
|
||||
multiPartPayFsm.expectMsg(SendPaymentConfig(id, id, None, paymentHash, c, Upstream.Local(id), Some(invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = true))
|
||||
multiPartPayFsm.expectMsg(SendPaymentConfig(id, id, None, paymentHash, c, Upstream.Local(id), Some(invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = true, confidence = 1.0))
|
||||
multiPartPayFsm.expectMsg(SendMultiPartPayment(initiator, ClearRecipient(invoice, finalAmount + 100.msat, req.finalExpiry(nodeParams), Set.empty), 1, nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams))
|
||||
|
||||
sender.send(initiator, GetPayment(PaymentIdentifier.PaymentUUID(id)))
|
||||
|
@ -246,7 +246,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val req = SendPaymentToNode(sender.ref, finalAmount, invoice, Nil, 1, routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams)
|
||||
sender.send(initiator, req)
|
||||
val id = sender.expectMsgType[UUID]
|
||||
multiPartPayFsm.expectMsg(SendPaymentConfig(id, id, None, paymentHash, c, Upstream.Local(id), Some(invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = true))
|
||||
multiPartPayFsm.expectMsg(SendPaymentConfig(id, id, None, paymentHash, c, Upstream.Local(id), Some(invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = true, confidence = 1.0))
|
||||
val payment = multiPartPayFsm.expectMsgType[SendMultiPartPayment]
|
||||
val expiry = payment.recipient.asInstanceOf[ClearRecipient].expiry
|
||||
assert(nodeParams.currentBlockHeight + invoiceFinalExpiryDelta.toInt + 50 <= expiry.blockHeight)
|
||||
|
@ -260,7 +260,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val req = SendPaymentToRoute(finalAmount, invoice, Nil, route, None, None, None)
|
||||
sender.send(initiator, req)
|
||||
val payment = sender.expectMsgType[SendPaymentToRouteResponse]
|
||||
payFsm.expectMsg(SendPaymentConfig(payment.paymentId, payment.parentId, None, paymentHash, c, Upstream.Local(payment.paymentId), Some(invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = false))
|
||||
payFsm.expectMsg(SendPaymentConfig(payment.paymentId, payment.parentId, None, paymentHash, c, Upstream.Local(payment.paymentId), Some(invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = false, confidence = 1.0))
|
||||
val msg = payFsm.expectMsgType[PaymentLifecycle.SendPaymentToRoute]
|
||||
assert(msg.replyTo == initiator)
|
||||
assert(msg.route == Left(route))
|
||||
|
@ -302,7 +302,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val req = SendPaymentToNode(sender.ref, finalAmount, invoice, resolvedPaths, 1, routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams, payerKey_opt = Some(payerKey))
|
||||
sender.send(initiator, req)
|
||||
val id = sender.expectMsgType[UUID]
|
||||
payFsm.expectMsg(SendPaymentConfig(id, id, None, paymentHash, invoice.nodeId, Upstream.Local(id), Some(invoice), Some(payerKey), storeInDb = true, publishEvent = true, recordPathFindingMetrics = true))
|
||||
payFsm.expectMsg(SendPaymentConfig(id, id, None, paymentHash, invoice.nodeId, Upstream.Local(id), Some(invoice), Some(payerKey), storeInDb = true, publishEvent = true, recordPathFindingMetrics = true, confidence = 1.0))
|
||||
val payment = payFsm.expectMsgType[PaymentLifecycle.SendPaymentToNode]
|
||||
assert(payment.amount == finalAmount)
|
||||
assert(payment.recipient.nodeId == invoice.nodeId)
|
||||
|
@ -336,7 +336,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
val req = SendPaymentToNode(sender.ref, finalAmount, invoice, resolvedPaths, 1, routeParams = nodeParams.routerConf.pathFindingExperimentConf.getRandomConf().getDefaultRouteParams, payerKey_opt = Some(payerKey))
|
||||
sender.send(initiator, req)
|
||||
val id = sender.expectMsgType[UUID]
|
||||
multiPartPayFsm.expectMsg(SendPaymentConfig(id, id, None, paymentHash, invoice.nodeId, Upstream.Local(id), Some(invoice), Some(payerKey), storeInDb = true, publishEvent = true, recordPathFindingMetrics = true))
|
||||
multiPartPayFsm.expectMsg(SendPaymentConfig(id, id, None, paymentHash, invoice.nodeId, Upstream.Local(id), Some(invoice), Some(payerKey), storeInDb = true, publishEvent = true, recordPathFindingMetrics = true, confidence = 1.0))
|
||||
val payment = multiPartPayFsm.expectMsgType[SendMultiPartPayment]
|
||||
assert(payment.recipient.nodeId == invoice.nodeId)
|
||||
assert(payment.recipient.totalAmount == finalAmount)
|
||||
|
@ -529,7 +529,7 @@ class PaymentInitiatorSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
|
|||
sender.send(initiator, req)
|
||||
val payment = sender.expectMsgType[SendPaymentToRouteResponse]
|
||||
assert(payment.trampolineSecret.contains(trampolineAttempt.paymentSecret))
|
||||
payFsm.expectMsg(SendPaymentConfig(payment.paymentId, payment.parentId, None, paymentHash, c, Upstream.Local(payment.paymentId), Some(invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = false))
|
||||
payFsm.expectMsg(SendPaymentConfig(payment.paymentId, payment.parentId, None, paymentHash, c, Upstream.Local(payment.paymentId), Some(invoice), None, storeInDb = true, publishEvent = true, recordPathFindingMetrics = false, confidence = 1.0))
|
||||
val msg = payFsm.expectMsgType[PaymentLifecycle.SendPaymentToRoute]
|
||||
assert(msg.route == Left(route))
|
||||
assert(msg.amount == finalAmount + trampolineAttempt.fees)
|
||||
|
|
|
@ -81,7 +81,7 @@ class PaymentLifecycleSpec extends BaseRouterSpec {
|
|||
def createPaymentLifecycle(invoice: Invoice, storeInDb: Boolean = true, publishEvent: Boolean = true, recordMetrics: Boolean = true): PaymentFixture = {
|
||||
val (id, parentId) = (UUID.randomUUID(), UUID.randomUUID())
|
||||
val nodeParams = TestConstants.Alice.nodeParams.copy(nodeKeyManager = testNodeKeyManager, channelKeyManager = testChannelKeyManager)
|
||||
val cfg = SendPaymentConfig(id, parentId, Some(defaultExternalId), defaultPaymentHash, invoice.nodeId, Upstream.Local(id), Some(invoice), None, storeInDb, publishEvent, recordMetrics)
|
||||
val cfg = SendPaymentConfig(id, parentId, Some(defaultExternalId), defaultPaymentHash, invoice.nodeId, Upstream.Local(id), Some(invoice), None, storeInDb, publishEvent, recordMetrics, confidence = 1.0)
|
||||
val (routerForwarder, register, sender, monitor, eventListener, metricsListener) = (TestProbe(), TestProbe(), TestProbe(), TestProbe(), TestProbe(), TestProbe())
|
||||
val paymentFSM = TestFSMRef(new PaymentLifecycle(nodeParams, cfg, routerForwarder.ref, register.ref))
|
||||
paymentFSM ! SubscribeTransitionCallBack(monitor.ref)
|
||||
|
@ -94,7 +94,7 @@ class PaymentLifecycleSpec extends BaseRouterSpec {
|
|||
def addCompleted(result: HtlcResult) = {
|
||||
RES_ADD_SETTLED(
|
||||
origin = defaultOrigin,
|
||||
htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, defaultAmountMsat, defaultPaymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None),
|
||||
htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, defaultAmountMsat, defaultPaymentHash, defaultExpiry, TestConstants.emptyOnionPacket, None, 1.0),
|
||||
result)
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
|
||||
def testBuildOutgoingPayment(): Unit = {
|
||||
val recipient = ClearRecipient(e, Features.empty, finalAmount, finalExpiry, paymentSecret)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, hops, None), recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, hops, None), recipient, 1.0)
|
||||
assert(payment.outgoingChannel == channelUpdate_ab.shortChannelId)
|
||||
assert(payment.cmd.amount == amount_ab)
|
||||
assert(payment.cmd.cltvExpiry == expiry_ab)
|
||||
|
@ -79,7 +79,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
}
|
||||
|
||||
def testPeelOnion(packet_b: OnionRoutingPacket): Unit = {
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, amount_ab, paymentHash, expiry_ab, packet_b, None)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, amount_ab, paymentHash, expiry_ab, packet_b, None, 1.0)
|
||||
val Right(relay_b@ChannelRelayPacket(add_b2, payload_b, packet_c)) = decrypt(add_b, priv_b.privateKey, Features.empty)
|
||||
assert(add_b2 == add_b)
|
||||
assert(packet_c.payload.length == PaymentOnionCodecs.paymentOnionPayloadLength)
|
||||
|
@ -89,7 +89,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
assert(relay_b.relayFeeMsat == fee_b)
|
||||
assert(relay_b.expiryDelta == channelUpdate_bc.cltvExpiryDelta)
|
||||
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 1, amount_bc, paymentHash, expiry_bc, packet_c, None)
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 1, amount_bc, paymentHash, expiry_bc, packet_c, None, 1.0)
|
||||
val Right(relay_c@ChannelRelayPacket(add_c2, payload_c, packet_d)) = decrypt(add_c, priv_c.privateKey, Features.empty)
|
||||
assert(add_c2 == add_c)
|
||||
assert(packet_d.payload.length == PaymentOnionCodecs.paymentOnionPayloadLength)
|
||||
|
@ -99,7 +99,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
assert(relay_c.relayFeeMsat == fee_c)
|
||||
assert(relay_c.expiryDelta == channelUpdate_cd.cltvExpiryDelta)
|
||||
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 2, amount_cd, paymentHash, expiry_cd, packet_d, None)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 2, amount_cd, paymentHash, expiry_cd, packet_d, None, 1.0)
|
||||
val Right(relay_d@ChannelRelayPacket(add_d2, payload_d, packet_e)) = decrypt(add_d, priv_d.privateKey, Features.empty)
|
||||
assert(add_d2 == add_d)
|
||||
assert(packet_e.payload.length == PaymentOnionCodecs.paymentOnionPayloadLength)
|
||||
|
@ -109,7 +109,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
assert(relay_d.relayFeeMsat == fee_d)
|
||||
assert(relay_d.expiryDelta == channelUpdate_de.cltvExpiryDelta)
|
||||
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 2, amount_de, paymentHash, expiry_de, packet_e, None)
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 2, amount_de, paymentHash, expiry_de, packet_e, None, 1.0)
|
||||
val Right(FinalPacket(add_e2, payload_e)) = decrypt(add_e, priv_e.privateKey, Features.empty)
|
||||
assert(add_e2 == add_e)
|
||||
assert(payload_e.isInstanceOf[FinalPayload.Standard])
|
||||
|
@ -126,14 +126,14 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
test("build outgoing payment for direct peer") {
|
||||
val recipient = ClearRecipient(b, Features.empty, finalAmount, finalExpiry, paymentSecret, paymentMetadata_opt = Some(paymentMetadata))
|
||||
val route = Route(finalAmount, hops.take(1), None)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
assert(payment.cmd.amount == finalAmount)
|
||||
assert(payment.cmd.cltvExpiry == finalExpiry)
|
||||
assert(payment.cmd.paymentHash == paymentHash)
|
||||
assert(payment.cmd.onion.payload.length == PaymentOnionCodecs.paymentOnionPayloadLength)
|
||||
|
||||
// let's peel the onion
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, finalAmount, paymentHash, finalExpiry, payment.cmd.onion, None)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, finalAmount, paymentHash, finalExpiry, payment.cmd.onion, None, 1.0)
|
||||
val Right(FinalPacket(add_b2, payload_b)) = decrypt(add_b, priv_b.privateKey, Features.empty)
|
||||
assert(add_b2 == add_b)
|
||||
assert(payload_b.isInstanceOf[FinalPayload.Standard])
|
||||
|
@ -147,10 +147,10 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
test("build outgoing payment with greater amount and expiry") {
|
||||
val recipient = ClearRecipient(b, Features.empty, finalAmount, finalExpiry, paymentSecret, paymentMetadata_opt = Some(paymentMetadata))
|
||||
val route = Route(finalAmount, hops.take(1), None)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
|
||||
// let's peel the onion
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, finalAmount + 100.msat, paymentHash, finalExpiry + CltvExpiryDelta(6), payment.cmd.onion, None)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, finalAmount + 100.msat, paymentHash, finalExpiry + CltvExpiryDelta(6), payment.cmd.onion, None, 1.0)
|
||||
val Right(FinalPacket(_, payload_b)) = decrypt(add_b, priv_b.privateKey, Features.empty)
|
||||
assert(payload_b.isInstanceOf[FinalPayload.Standard])
|
||||
assert(payload_b.amount == finalAmount)
|
||||
|
@ -164,13 +164,13 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
assert(recipient.extraEdges.length == 1)
|
||||
assert(recipient.extraEdges.head.sourceNodeId == c)
|
||||
assert(recipient.extraEdges.head.targetNodeId == invoice.nodeId)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
assert(payment.outgoingChannel == channelUpdate_ab.shortChannelId)
|
||||
assert(payment.cmd.amount >= amount_ab)
|
||||
assert(payment.cmd.cltvExpiry == expiry_ab)
|
||||
assert(payment.cmd.nextBlindingKey_opt.isEmpty)
|
||||
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
val Right(relay_b@ChannelRelayPacket(_, payload_b, packet_c)) = decrypt(add_b, priv_b.privateKey, Features.empty)
|
||||
assert(packet_c.payload.length == PaymentOnionCodecs.paymentOnionPayloadLength)
|
||||
assert(relay_b.amountToForward >= amount_bc)
|
||||
|
@ -180,7 +180,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
assert(relay_b.expiryDelta == channelUpdate_bc.cltvExpiryDelta)
|
||||
assert(payload_b.isInstanceOf[IntermediatePayload.ChannelRelay.Standard])
|
||||
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 1, relay_b.amountToForward, relay_b.add.paymentHash, relay_b.outgoingCltv, packet_c, None)
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 1, relay_b.amountToForward, relay_b.add.paymentHash, relay_b.outgoingCltv, packet_c, None, 1.0)
|
||||
val Right(relay_c@ChannelRelayPacket(_, payload_c, packet_d)) = decrypt(add_c, priv_c.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(packet_d.payload.length == PaymentOnionCodecs.paymentOnionPayloadLength)
|
||||
assert(relay_c.amountToForward >= amount_cd)
|
||||
|
@ -191,7 +191,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
assert(payload_c.isInstanceOf[IntermediatePayload.ChannelRelay.Blinded])
|
||||
val blinding_d = payload_c.asInstanceOf[IntermediatePayload.ChannelRelay.Blinded].nextBlinding
|
||||
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 2, relay_c.amountToForward, relay_c.add.paymentHash, relay_c.outgoingCltv, packet_d, Some(blinding_d))
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 2, relay_c.amountToForward, relay_c.add.paymentHash, relay_c.outgoingCltv, packet_d, Some(blinding_d), 1.0)
|
||||
val Right(relay_d@ChannelRelayPacket(_, payload_d, packet_e)) = decrypt(add_d, priv_d.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(packet_e.payload.length == PaymentOnionCodecs.paymentOnionPayloadLength)
|
||||
assert(relay_d.amountToForward >= amount_de)
|
||||
|
@ -202,7 +202,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
assert(payload_d.isInstanceOf[IntermediatePayload.ChannelRelay.Blinded])
|
||||
val blinding_e = payload_d.asInstanceOf[IntermediatePayload.ChannelRelay.Blinded].nextBlinding
|
||||
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 2, relay_d.amountToForward, relay_d.add.paymentHash, relay_d.outgoingCltv, packet_e, Some(blinding_e))
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 2, relay_d.amountToForward, relay_d.add.paymentHash, relay_d.outgoingCltv, packet_e, Some(blinding_e), 1.0)
|
||||
val Right(FinalPacket(_, payload_e)) = decrypt(add_e, priv_e.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(payload_e.amount == finalAmount)
|
||||
assert(payload_e.totalAmount == finalAmount)
|
||||
|
@ -227,13 +227,13 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
})
|
||||
val recipient = BlindedRecipient(invoice, resolvedPaths, amount_bc, expiry_bc, Set.empty)
|
||||
val hops = Seq(channelHopFromUpdate(a, b, channelUpdate_ab), channelHopFromUpdate(b, c, channelUpdate_bc))
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(amount_bc, hops, Some(recipient.blindedHops.head)), recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(amount_bc, hops, Some(recipient.blindedHops.head)), recipient, 1.0)
|
||||
assert(payment.outgoingChannel == channelUpdate_ab.shortChannelId)
|
||||
assert(payment.cmd.amount == amount_ab)
|
||||
assert(payment.cmd.cltvExpiry == expiry_ab)
|
||||
assert(payment.cmd.nextBlindingKey_opt.isEmpty)
|
||||
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
val Right(relay_b@ChannelRelayPacket(_, payload_b, packet_c)) = decrypt(add_b, priv_b.privateKey, Features.empty)
|
||||
assert(packet_c.payload.length == PaymentOnionCodecs.paymentOnionPayloadLength)
|
||||
assert(relay_b.amountToForward >= amount_bc)
|
||||
|
@ -243,7 +243,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
assert(relay_b.expiryDelta == channelUpdate_bc.cltvExpiryDelta)
|
||||
assert(payload_b.isInstanceOf[IntermediatePayload.ChannelRelay.Standard])
|
||||
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 1, amount_bc, paymentHash, expiry_bc, packet_c, None)
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 1, amount_bc, paymentHash, expiry_bc, packet_c, None, 1.0)
|
||||
val Right(FinalPacket(_, payload_c)) = decrypt(add_c, priv_c.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(payload_c.amount == amount_bc)
|
||||
assert(payload_c.totalAmount == amount_bc)
|
||||
|
@ -259,7 +259,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
assert(payment.cmd.cltvExpiry == finalExpiry)
|
||||
assert(payment.cmd.nextBlindingKey_opt.nonEmpty)
|
||||
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
val Right(FinalPacket(_, payload_b)) = decrypt(add_b, priv_b.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(payload_b.amount == finalAmount)
|
||||
assert(payload_b.totalAmount == finalAmount)
|
||||
|
@ -272,7 +272,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
val Right(payment) = buildOutgoingBlindedPaymentAB(paymentHash)
|
||||
assert(payment.outgoingChannel == channelUpdate_ab.shortChannelId)
|
||||
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount + 100.msat, payment.cmd.paymentHash, payment.cmd.cltvExpiry + CltvExpiryDelta(6), payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount + 100.msat, payment.cmd.paymentHash, payment.cmd.cltvExpiry + CltvExpiryDelta(6), payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
val Right(FinalPacket(_, payload_b)) = decrypt(add_b, priv_b.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(payload_b.amount == finalAmount)
|
||||
assert(payload_b.totalAmount == finalAmount)
|
||||
|
@ -288,17 +288,17 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
val recipient = TrampolineRecipient(invoice, finalAmount, finalExpiry, trampolineHop, randomBytes32())
|
||||
assert(recipient.trampolineAmount == amount_bc)
|
||||
assert(recipient.trampolineExpiry == expiry_bc)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(recipient.trampolineAmount, trampolineChannelHops, Some(trampolineHop)), recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(recipient.trampolineAmount, trampolineChannelHops, Some(trampolineHop)), recipient, 1.0)
|
||||
assert(payment.outgoingChannel == channelUpdate_ab.shortChannelId)
|
||||
assert(payment.cmd.amount == amount_ab)
|
||||
assert(payment.cmd.cltvExpiry == expiry_ab)
|
||||
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None, 1.0)
|
||||
val Right(ChannelRelayPacket(add_b2, payload_b, packet_c)) = decrypt(add_b, priv_b.privateKey, Features.empty)
|
||||
assert(add_b2 == add_b)
|
||||
assert(payload_b == IntermediatePayload.ChannelRelay.Standard(channelUpdate_bc.shortChannelId, amount_bc, expiry_bc))
|
||||
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 2, amount_bc, paymentHash, expiry_bc, packet_c, None)
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 2, amount_bc, paymentHash, expiry_bc, packet_c, None, 1.0)
|
||||
val Right(RelayToTrampolinePacket(add_c2, outer_c, inner_c, trampolinePacket_e)) = decrypt(add_c, priv_c.privateKey, Features.empty)
|
||||
assert(add_c2 == add_c)
|
||||
assert(outer_c.amount == amount_bc)
|
||||
|
@ -315,16 +315,16 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
|
||||
// c forwards the trampoline payment to e through d.
|
||||
val recipient_e = ClearRecipient(e, Features.empty, inner_c.amountToForward, inner_c.outgoingCltv, randomBytes32(), nextTrampolineOnion_opt = Some(trampolinePacket_e))
|
||||
val Right(payment_e) = buildOutgoingPayment(Origin.Hot(ActorRef.noSender, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_c, TimestampMilli(1687345927000L), b)))), paymentHash, Route(inner_c.amountToForward, afterTrampolineChannelHops, None), recipient_e)
|
||||
val Right(payment_e) = buildOutgoingPayment(Origin.Hot(ActorRef.noSender, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_c, TimestampMilli(1687345927000L), b)))), paymentHash, Route(inner_c.amountToForward, afterTrampolineChannelHops, None), recipient_e, 1.0)
|
||||
assert(payment_e.outgoingChannel == channelUpdate_cd.shortChannelId)
|
||||
assert(payment_e.cmd.amount == amount_cd)
|
||||
assert(payment_e.cmd.cltvExpiry == expiry_cd)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 3, payment_e.cmd.amount, paymentHash, payment_e.cmd.cltvExpiry, payment_e.cmd.onion, None)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 3, payment_e.cmd.amount, paymentHash, payment_e.cmd.cltvExpiry, payment_e.cmd.onion, None, 1.0)
|
||||
val Right(ChannelRelayPacket(add_d2, payload_d, packet_e)) = decrypt(add_d, priv_d.privateKey, Features.empty)
|
||||
assert(add_d2 == add_d)
|
||||
assert(payload_d == IntermediatePayload.ChannelRelay.Standard(channelUpdate_de.shortChannelId, amount_de, expiry_de))
|
||||
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 4, amount_de, paymentHash, expiry_de, packet_e, None)
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 4, amount_de, paymentHash, expiry_de, packet_e, None, 1.0)
|
||||
val Right(FinalPacket(add_e2, payload_e)) = decrypt(add_e, priv_e.privateKey, Features.empty)
|
||||
assert(add_e2 == add_e)
|
||||
assert(payload_e == FinalPayload.Standard(TlvStream(AmountToForward(finalAmount), OutgoingCltv(finalExpiry), PaymentData(paymentSecret, finalAmount), OnionPaymentPayloadTlv.PaymentMetadata(hex"010203"))))
|
||||
|
@ -341,15 +341,15 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
val recipient = TrampolineRecipient(invoice, finalAmount, finalExpiry, trampolineHop, randomBytes32())
|
||||
assert(recipient.trampolineAmount == amount_bc)
|
||||
assert(recipient.trampolineExpiry == expiry_bc)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(recipient.trampolineAmount, trampolineChannelHops, Some(trampolineHop)), recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(recipient.trampolineAmount, trampolineChannelHops, Some(trampolineHop)), recipient, 1.0)
|
||||
assert(payment.outgoingChannel == channelUpdate_ab.shortChannelId)
|
||||
assert(payment.cmd.amount == amount_ab)
|
||||
assert(payment.cmd.cltvExpiry == expiry_ab)
|
||||
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None, 1.0)
|
||||
val Right(ChannelRelayPacket(_, _, packet_c)) = decrypt(add_b, priv_b.privateKey, Features.empty)
|
||||
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 2, amount_bc, paymentHash, expiry_bc, packet_c, None)
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 2, amount_bc, paymentHash, expiry_bc, packet_c, None, 1.0)
|
||||
val Right(RelayToTrampolinePacket(_, outer_c, inner_c, _)) = decrypt(add_c, priv_c.privateKey, Features.empty)
|
||||
assert(outer_c.amount == amount_bc)
|
||||
assert(outer_c.totalAmount == amount_bc)
|
||||
|
@ -367,16 +367,16 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
|
||||
// c forwards the trampoline payment to e through d.
|
||||
val recipient_e = ClearRecipient(e, Features.empty, inner_c.amountToForward, inner_c.outgoingCltv, inner_c.paymentSecret.get, invoice.extraEdges, inner_c.paymentMetadata)
|
||||
val Right(payment_e) = buildOutgoingPayment(Origin.Hot(ActorRef.noSender, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_c, TimestampMilli(1687345927000L), b)))), paymentHash, Route(inner_c.amountToForward, afterTrampolineChannelHops, None), recipient_e)
|
||||
val Right(payment_e) = buildOutgoingPayment(Origin.Hot(ActorRef.noSender, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_c, TimestampMilli(1687345927000L), b)))), paymentHash, Route(inner_c.amountToForward, afterTrampolineChannelHops, None), recipient_e, 1.0)
|
||||
assert(payment_e.outgoingChannel == channelUpdate_cd.shortChannelId)
|
||||
assert(payment_e.cmd.amount == amount_cd)
|
||||
assert(payment_e.cmd.cltvExpiry == expiry_cd)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 3, payment_e.cmd.amount, paymentHash, payment_e.cmd.cltvExpiry, payment_e.cmd.onion, None)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 3, payment_e.cmd.amount, paymentHash, payment_e.cmd.cltvExpiry, payment_e.cmd.onion, None, 1.0)
|
||||
val Right(ChannelRelayPacket(add_d2, payload_d, packet_e)) = decrypt(add_d, priv_d.privateKey, Features.empty)
|
||||
assert(add_d2 == add_d)
|
||||
assert(payload_d == IntermediatePayload.ChannelRelay.Standard(channelUpdate_de.shortChannelId, amount_de, expiry_de))
|
||||
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 4, amount_de, paymentHash, expiry_de, packet_e, None)
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 4, amount_de, paymentHash, expiry_de, packet_e, None, 1.0)
|
||||
val Right(FinalPacket(add_e2, payload_e)) = decrypt(add_e, priv_e.privateKey, Features.empty)
|
||||
assert(add_e2 == add_e)
|
||||
assert(payload_e == FinalPayload.Standard(TlvStream(AmountToForward(finalAmount), OutgoingCltv(finalExpiry), PaymentData(invoice.paymentSecret, finalAmount), OnionPaymentPayloadTlv.PaymentMetadata(hex"010203"))))
|
||||
|
@ -393,13 +393,13 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
val invoiceFeatures = Features[Bolt11Feature](VariableLengthOnion -> Mandatory, PaymentSecret -> Mandatory, BasicMultiPartPayment -> Optional)
|
||||
val invoice = Bolt11Invoice(Block.RegtestGenesisBlock.hash, Some(finalAmount), paymentHash, priv_e.privateKey, Left("#reckless"), CltvExpiryDelta(18), extraHops = routingHints, features = invoiceFeatures, paymentMetadata = Some(paymentMetadata))
|
||||
val recipient = TrampolineRecipient(invoice, finalAmount, finalExpiry, trampolineHop, randomBytes32())
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(recipient.trampolineAmount, trampolineChannelHops, Some(trampolineHop)), recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(recipient.trampolineAmount, trampolineChannelHops, Some(trampolineHop)), recipient, 1.0)
|
||||
assert(payment.outgoingChannel == channelUpdate_ab.shortChannelId)
|
||||
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None, 1.0)
|
||||
val Right(ChannelRelayPacket(_, _, packet_c)) = decrypt(add_b, priv_b.privateKey, Features.empty)
|
||||
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 2, amount_bc, paymentHash, expiry_bc, packet_c, None)
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 2, amount_bc, paymentHash, expiry_bc, packet_c, None, 1.0)
|
||||
val Right(RelayToTrampolinePacket(_, outer_c, inner_c, _)) = decrypt(add_c, priv_c.privateKey, Features.empty)
|
||||
assert(outer_c.records.get[OnionPaymentPayloadTlv.TrampolineOnion].get.packet.payload.size > 800)
|
||||
assert(inner_c.outgoingNodeId == e)
|
||||
|
@ -408,14 +408,14 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
|
||||
// c forwards the trampoline payment to e through d.
|
||||
val recipient_e = ClearRecipient(e, Features.empty, inner_c.amountToForward, inner_c.outgoingCltv, inner_c.paymentSecret.get, invoice.extraEdges, inner_c.paymentMetadata)
|
||||
val Right(payment_e) = buildOutgoingPayment(Origin.Hot(ActorRef.noSender, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_c, TimestampMilli(1687345927000L), b)))), paymentHash, Route(inner_c.amountToForward, afterTrampolineChannelHops, None), recipient_e)
|
||||
val Right(payment_e) = buildOutgoingPayment(Origin.Hot(ActorRef.noSender, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_c, TimestampMilli(1687345927000L), b)))), paymentHash, Route(inner_c.amountToForward, afterTrampolineChannelHops, None), recipient_e, 1.0)
|
||||
assert(payment_e.outgoingChannel == channelUpdate_cd.shortChannelId)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 3, payment_e.cmd.amount, paymentHash, payment_e.cmd.cltvExpiry, payment_e.cmd.onion, None)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 3, payment_e.cmd.amount, paymentHash, payment_e.cmd.cltvExpiry, payment_e.cmd.onion, None, 1.0)
|
||||
val Right(ChannelRelayPacket(add_d2, payload_d, packet_e)) = decrypt(add_d, priv_d.privateKey, Features.empty)
|
||||
assert(add_d2 == add_d)
|
||||
assert(payload_d == IntermediatePayload.ChannelRelay.Standard(channelUpdate_de.shortChannelId, amount_de, expiry_de))
|
||||
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 4, amount_de, paymentHash, expiry_de, packet_e, None)
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 4, amount_de, paymentHash, expiry_de, packet_e, None, 1.0)
|
||||
val Right(FinalPacket(add_e2, payload_e)) = decrypt(add_e, priv_e.privateKey, Features.empty)
|
||||
assert(add_e2 == add_e)
|
||||
assert(payload_e == FinalPayload.Standard(TlvStream(AmountToForward(finalAmount), OutgoingCltv(finalExpiry), PaymentData(invoice.paymentSecret, finalAmount), OnionPaymentPayloadTlv.PaymentMetadata(paymentMetadata))))
|
||||
|
@ -424,7 +424,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
test("fail to build outgoing payment with invalid route") {
|
||||
val recipient = ClearRecipient(e, Features.empty, finalAmount, finalExpiry, paymentSecret)
|
||||
val route = Route(finalAmount, hops.dropRight(1), None) // route doesn't reach e
|
||||
val Left(failure) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val Left(failure) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
assert(failure == InvalidRouteRecipient(e, d))
|
||||
}
|
||||
|
||||
|
@ -433,22 +433,22 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
val invoice = Bolt11Invoice(Block.RegtestGenesisBlock.hash, None, paymentHash, priv_e.privateKey, Left("invoice"), CltvExpiryDelta(6), paymentSecret = paymentSecret, features = invoiceFeatures)
|
||||
val recipient = TrampolineRecipient(invoice, finalAmount, finalExpiry, trampolineHop, randomBytes32())
|
||||
val route = Route(finalAmount, trampolineChannelHops, None) // missing trampoline hop
|
||||
val Left(failure) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val Left(failure) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
assert(failure == MissingTrampolineHop(c))
|
||||
}
|
||||
|
||||
test("fail to build outgoing blinded payment with invalid route") {
|
||||
val (_, route, recipient) = longBlindedHops(hex"deadbeef")
|
||||
assert(buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient).isRight)
|
||||
assert(buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0).isRight)
|
||||
val routeMissingBlindedHop = route.copy(finalHop_opt = None)
|
||||
val Left(failure) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, routeMissingBlindedHop, recipient)
|
||||
val Left(failure) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, routeMissingBlindedHop, recipient, 1.0)
|
||||
assert(failure == MissingBlindedHop(Set(c)))
|
||||
}
|
||||
|
||||
test("fail to decrypt when the onion is invalid") {
|
||||
val recipient = ClearRecipient(e, Features.empty, finalAmount, finalExpiry, paymentSecret)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, hops, None), recipient)
|
||||
val add = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion.copy(payload = payment.cmd.onion.payload.reverse), None)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, hops, None), recipient, 1.0)
|
||||
val add = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion.copy(payload = payment.cmd.onion.payload.reverse), None, 1.0)
|
||||
val Left(failure) = decrypt(add, priv_b.privateKey, Features.empty)
|
||||
assert(failure.isInstanceOf[InvalidOnionHmac])
|
||||
}
|
||||
|
@ -457,30 +457,30 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
val invoiceFeatures = Features[Bolt11Feature](VariableLengthOnion -> Mandatory, PaymentSecret -> Mandatory, BasicMultiPartPayment -> Optional, PaymentMetadata -> Optional, TrampolinePaymentPrototype -> Optional)
|
||||
val invoice = Bolt11Invoice(Block.RegtestGenesisBlock.hash, None, paymentHash, priv_e.privateKey, Left("invoice"), CltvExpiryDelta(6), paymentSecret = paymentSecret, features = invoiceFeatures, paymentMetadata = Some(hex"010203"))
|
||||
val recipient = TrampolineRecipient(invoice, finalAmount, finalExpiry, trampolineHop, randomBytes32())
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(recipient.trampolineAmount, trampolineChannelHops, Some(trampolineHop)), recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(recipient.trampolineAmount, trampolineChannelHops, Some(trampolineHop)), recipient, 1.0)
|
||||
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None, 1.0)
|
||||
val Right(ChannelRelayPacket(_, _, packet_c)) = decrypt(add_b, priv_b.privateKey, Features.empty)
|
||||
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 2, amount_bc, paymentHash, expiry_bc, packet_c, None)
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 2, amount_bc, paymentHash, expiry_bc, packet_c, None, 1.0)
|
||||
val Right(RelayToTrampolinePacket(_, _, inner_c, trampolinePacket_e)) = decrypt(add_c, priv_c.privateKey, Features.empty)
|
||||
|
||||
// c forwards an invalid trampoline onion to e through d.
|
||||
val recipient_e = ClearRecipient(e, Features.empty, inner_c.amountToForward, inner_c.outgoingCltv, randomBytes32(), nextTrampolineOnion_opt = Some(trampolinePacket_e.copy(payload = trampolinePacket_e.payload.reverse)))
|
||||
val Right(payment_e) = buildOutgoingPayment(Origin.Hot(ActorRef.noSender, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_c, TimestampMilli(1687345927000L), b)))), paymentHash, Route(inner_c.amountToForward, afterTrampolineChannelHops, None), recipient_e)
|
||||
val Right(payment_e) = buildOutgoingPayment(Origin.Hot(ActorRef.noSender, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_c, TimestampMilli(1687345927000L), b)))), paymentHash, Route(inner_c.amountToForward, afterTrampolineChannelHops, None), recipient_e, 1.0)
|
||||
assert(payment_e.outgoingChannel == channelUpdate_cd.shortChannelId)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 3, payment_e.cmd.amount, paymentHash, payment_e.cmd.cltvExpiry, payment_e.cmd.onion, None)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 3, payment_e.cmd.amount, paymentHash, payment_e.cmd.cltvExpiry, payment_e.cmd.onion, None, 1.0)
|
||||
val Right(ChannelRelayPacket(_, _, packet_e)) = decrypt(add_d, priv_d.privateKey, Features.empty)
|
||||
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 4, amount_de, paymentHash, expiry_de, packet_e, None)
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 4, amount_de, paymentHash, expiry_de, packet_e, None, 1.0)
|
||||
val Left(failure) = decrypt(add_e, priv_e.privateKey, Features.empty)
|
||||
assert(failure.isInstanceOf[InvalidOnionHmac])
|
||||
}
|
||||
|
||||
test("fail to decrypt when payment hash doesn't match associated data") {
|
||||
val recipient = ClearRecipient(e, Features.empty, finalAmount, finalExpiry, paymentSecret)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash.reverse, Route(finalAmount, hops, None), recipient)
|
||||
val add = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash.reverse, Route(finalAmount, hops, None), recipient, 1.0)
|
||||
val add = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None, 1.0)
|
||||
val Left(failure) = decrypt(add, priv_b.privateKey, Features.empty)
|
||||
assert(failure.isInstanceOf[InvalidOnionHmac])
|
||||
}
|
||||
|
@ -503,19 +503,19 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
val route = Route(amount_bc, Seq(channelHopFromUpdate(a, b, channelUpdate_ab)), Some(recipient.blindedHops.head))
|
||||
(route, recipient)
|
||||
}
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
assert(payment.outgoingChannel == channelUpdate_ab.shortChannelId)
|
||||
assert(payment.cmd.amount == amount_bc + fee_b)
|
||||
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
val Left(failure) = decrypt(add_b, priv_b.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(failure.isInstanceOf[InvalidOnionBlinding])
|
||||
}
|
||||
|
||||
test("fail to decrypt blinded payment when route blinding is disabled") {
|
||||
val (route, recipient) = shortBlindedHops()
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
val Left(failure) = decrypt(add_d, priv_d.privateKey, Features.empty) // d doesn't support route blinding
|
||||
assert(failure == InvalidOnionPayload(UInt64(10), 0))
|
||||
}
|
||||
|
@ -523,8 +523,8 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
test("fail to decrypt at the final node when amount has been modified by next-to-last node") {
|
||||
val recipient = ClearRecipient(b, Features.empty, finalAmount, finalExpiry, paymentSecret)
|
||||
val route = Route(finalAmount, hops.take(1), None)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val add = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount - 100.msat, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
val add = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount - 100.msat, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None, 1.0)
|
||||
val Left(failure) = decrypt(add, priv_b.privateKey, Features.empty)
|
||||
assert(failure == FinalIncorrectHtlcAmount(payment.cmd.amount - 100.msat))
|
||||
}
|
||||
|
@ -532,20 +532,20 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
test("fail to decrypt at the final node when expiry has been modified by next-to-last node") {
|
||||
val recipient = ClearRecipient(b, Features.empty, finalAmount, finalExpiry, paymentSecret)
|
||||
val route = Route(finalAmount, hops.take(1), None)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val add = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry - CltvExpiryDelta(12), payment.cmd.onion, None)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
val add = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry - CltvExpiryDelta(12), payment.cmd.onion, None, 1.0)
|
||||
val Left(failure) = decrypt(add, priv_b.privateKey, Features.empty)
|
||||
assert(failure == FinalIncorrectCltvExpiry(payment.cmd.cltvExpiry - CltvExpiryDelta(12)))
|
||||
}
|
||||
|
||||
test("fail to decrypt blinded payment at the final node when amount is too low") {
|
||||
val (route, recipient) = shortBlindedHops()
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
assert(payment.outgoingChannel == channelUpdate_cd.shortChannelId)
|
||||
assert(payment.cmd.amount == amount_cd)
|
||||
|
||||
// A smaller amount is sent to d, who doesn't know that it's invalid.
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 0, amount_de, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 0, amount_de, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
val Right(relay_d@ChannelRelayPacket(_, payload_d, packet_e)) = decrypt(add_d, priv_d.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(payload_d.outgoingChannelId == channelUpdate_de.shortChannelId)
|
||||
assert(relay_d.amountToForward < amount_de)
|
||||
|
@ -553,21 +553,21 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
val blinding_e = payload_d.asInstanceOf[IntermediatePayload.ChannelRelay.Blinded].nextBlinding
|
||||
|
||||
// When e receives a smaller amount than expected, it rejects the payment.
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 0, relay_d.amountToForward, paymentHash, relay_d.outgoingCltv, packet_e, Some(blinding_e))
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 0, relay_d.amountToForward, paymentHash, relay_d.outgoingCltv, packet_e, Some(blinding_e), 1.0)
|
||||
val Left(failure) = decrypt(add_e, priv_e.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(failure.isInstanceOf[InvalidOnionBlinding])
|
||||
}
|
||||
|
||||
test("fail to decrypt blinded payment at the final node when expiry is too low") {
|
||||
val (route, recipient) = shortBlindedHops()
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
assert(payment.outgoingChannel == channelUpdate_cd.shortChannelId)
|
||||
assert(payment.cmd.cltvExpiry == expiry_cd)
|
||||
|
||||
// A smaller expiry is sent to d, who doesn't know that it's invalid.
|
||||
// Intermediate nodes can reduce the expiry by at most min_final_expiry_delta.
|
||||
val invalidExpiry = payment.cmd.cltvExpiry - Channel.MIN_CLTV_EXPIRY_DELTA - CltvExpiryDelta(1)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, paymentHash, invalidExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, paymentHash, invalidExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
val Right(relay_d@ChannelRelayPacket(_, payload_d, packet_e)) = decrypt(add_d, priv_d.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(payload_d.outgoingChannelId == channelUpdate_de.shortChannelId)
|
||||
assert(relay_d.outgoingCltv < CltvExpiry(currentBlockCount))
|
||||
|
@ -575,7 +575,7 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
val blinding_e = payload_d.asInstanceOf[IntermediatePayload.ChannelRelay.Blinded].nextBlinding
|
||||
|
||||
// When e receives a smaller expiry than expected, it rejects the payment.
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 0, relay_d.amountToForward, paymentHash, relay_d.outgoingCltv, packet_e, Some(blinding_e))
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 0, relay_d.amountToForward, paymentHash, relay_d.outgoingCltv, packet_e, Some(blinding_e), 1.0)
|
||||
val Left(failure) = decrypt(add_e, priv_e.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(failure.isInstanceOf[InvalidOnionBlinding])
|
||||
}
|
||||
|
@ -583,11 +583,11 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
test("fail to decrypt blinded payment at intermediate node when expiry is too high") {
|
||||
val routeExpiry = expiry_de - channelUpdate_de.cltvExpiryDelta
|
||||
val (route, recipient) = shortBlindedHops(routeExpiry)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
assert(payment.outgoingChannel == channelUpdate_cd.shortChannelId)
|
||||
assert(payment.cmd.cltvExpiry > expiry_de)
|
||||
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
val Left(failure) = decrypt(add_d, priv_d.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(failure.isInstanceOf[InvalidOnionBlinding])
|
||||
}
|
||||
|
@ -602,12 +602,12 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
val invoiceFeatures = Features[Bolt11Feature](VariableLengthOnion -> Mandatory, PaymentSecret -> Mandatory, BasicMultiPartPayment -> Optional, TrampolinePaymentPrototype -> Optional)
|
||||
val invoice = Bolt11Invoice(Block.RegtestGenesisBlock.hash, None, paymentHash, priv_e.privateKey, Left("invoice"), CltvExpiryDelta(6), paymentSecret = paymentSecret, features = invoiceFeatures)
|
||||
val recipient = TrampolineRecipient(invoice, finalAmount, finalExpiry, trampolineHop, randomBytes32())
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(recipient.trampolineAmount, trampolineChannelHops, Some(trampolineHop)), recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(recipient.trampolineAmount, trampolineChannelHops, Some(trampolineHop)), recipient, 1.0)
|
||||
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 1, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None, 1.0)
|
||||
val Right(ChannelRelayPacket(_, _, packet_c)) = decrypt(add_b, priv_b.privateKey, Features.empty)
|
||||
|
||||
UpdateAddHtlc(randomBytes32(), 2, amount_bc, paymentHash, expiry_bc, packet_c, None)
|
||||
UpdateAddHtlc(randomBytes32(), 2, amount_bc, paymentHash, expiry_bc, packet_c, None, 1.0)
|
||||
}
|
||||
|
||||
test("fail to decrypt at the final trampoline node when amount has been decreased by next-to-last trampoline") {
|
||||
|
@ -617,11 +617,11 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
// c forwards an invalid amount to e through (the outer total amount doesn't match the inner amount).
|
||||
val invalidTotalAmount = inner_c.amountToForward - 1.msat
|
||||
val recipient_e = ClearRecipient(e, Features.empty, invalidTotalAmount, inner_c.outgoingCltv, randomBytes32(), nextTrampolineOnion_opt = Some(trampolinePacket_e))
|
||||
val Right(payment_e) = buildOutgoingPayment(Origin.Hot(ActorRef.noSender, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_c, TimestampMilli(1687345927000L), b)))), paymentHash, Route(invalidTotalAmount, afterTrampolineChannelHops, None), recipient_e)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 3, payment_e.cmd.amount, paymentHash, payment_e.cmd.cltvExpiry, payment_e.cmd.onion, None)
|
||||
val Right(payment_e) = buildOutgoingPayment(Origin.Hot(ActorRef.noSender, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_c, TimestampMilli(1687345927000L), b)))), paymentHash, Route(invalidTotalAmount, afterTrampolineChannelHops, None), recipient_e, 1.0)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 3, payment_e.cmd.amount, paymentHash, payment_e.cmd.cltvExpiry, payment_e.cmd.onion, None, 1.0)
|
||||
val Right(ChannelRelayPacket(_, payload_d, packet_e)) = decrypt(add_d, priv_d.privateKey, Features.empty)
|
||||
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 4, payload_d.amountToForward(add_d.amountMsat), paymentHash, payload_d.outgoingCltv(add_d.cltvExpiry), packet_e, None)
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 4, payload_d.amountToForward(add_d.amountMsat), paymentHash, payload_d.outgoingCltv(add_d.cltvExpiry), packet_e, None, 1.0)
|
||||
val Left(failure) = decrypt(add_e, priv_e.privateKey, Features.empty)
|
||||
assert(failure == FinalIncorrectHtlcAmount(invalidTotalAmount))
|
||||
}
|
||||
|
@ -633,11 +633,11 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
// c forwards an invalid amount to e through (the outer expiry doesn't match the inner expiry).
|
||||
val invalidExpiry = inner_c.outgoingCltv - CltvExpiryDelta(12)
|
||||
val recipient_e = ClearRecipient(e, Features.empty, inner_c.amountToForward, invalidExpiry, randomBytes32(), nextTrampolineOnion_opt = Some(trampolinePacket_e))
|
||||
val Right(payment_e) = buildOutgoingPayment(Origin.Hot(ActorRef.noSender, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_c, TimestampMilli(1687345927000L), b)))), paymentHash, Route(inner_c.amountToForward, afterTrampolineChannelHops, None), recipient_e)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 3, payment_e.cmd.amount, paymentHash, payment_e.cmd.cltvExpiry, payment_e.cmd.onion, None)
|
||||
val Right(payment_e) = buildOutgoingPayment(Origin.Hot(ActorRef.noSender, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_c, TimestampMilli(1687345927000L), b)))), paymentHash, Route(inner_c.amountToForward, afterTrampolineChannelHops, None), recipient_e, 1.0)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 3, payment_e.cmd.amount, paymentHash, payment_e.cmd.cltvExpiry, payment_e.cmd.onion, None, 1.0)
|
||||
val Right(ChannelRelayPacket(_, payload_d, packet_e)) = decrypt(add_d, priv_d.privateKey, Features.empty)
|
||||
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 4, payload_d.amountToForward(add_d.amountMsat), paymentHash, payload_d.outgoingCltv(add_d.cltvExpiry), packet_e, None)
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 4, payload_d.amountToForward(add_d.amountMsat), paymentHash, payload_d.outgoingCltv(add_d.cltvExpiry), packet_e, None, 1.0)
|
||||
val Left(failure) = decrypt(add_e, priv_e.privateKey, Features.empty)
|
||||
assert(failure == FinalIncorrectCltvExpiry(invalidExpiry))
|
||||
}
|
||||
|
@ -660,14 +660,14 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
test("build htlc failure onion") {
|
||||
// a -> b -> c -> d -> e
|
||||
val recipient = ClearRecipient(e, Features.empty, finalAmount, finalExpiry, paymentSecret)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, hops, None), recipient)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, amount_ab, paymentHash, expiry_ab, payment.cmd.onion, None)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, hops, None), recipient, 1.0)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, amount_ab, paymentHash, expiry_ab, payment.cmd.onion, None, 1.0)
|
||||
val Right(ChannelRelayPacket(_, _, packet_c)) = decrypt(add_b, priv_b.privateKey, Features.empty)
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 1, amount_bc, paymentHash, expiry_bc, packet_c, None)
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 1, amount_bc, paymentHash, expiry_bc, packet_c, None, 1.0)
|
||||
val Right(ChannelRelayPacket(_, _, packet_d)) = decrypt(add_c, priv_c.privateKey, Features.empty)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 2, amount_cd, paymentHash, expiry_cd, packet_d, None)
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 2, amount_cd, paymentHash, expiry_cd, packet_d, None, 1.0)
|
||||
val Right(ChannelRelayPacket(_, _, packet_e)) = decrypt(add_d, priv_d.privateKey, Features.empty)
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 3, amount_de, paymentHash, expiry_de, packet_e, None)
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 3, amount_de, paymentHash, expiry_de, packet_e, None, 1.0)
|
||||
val Right(FinalPacket(_, payload_e)) = decrypt(add_e, priv_e.privateKey, Features.empty)
|
||||
assert(payload_e.isInstanceOf[FinalPayload.Standard])
|
||||
|
||||
|
@ -689,16 +689,16 @@ class PaymentPacketSpec extends AnyFunSuite with BeforeAndAfterAll {
|
|||
test("build htlc failure onion (blinded payment)") {
|
||||
// a -> b -> c -> d -> e, blinded after c
|
||||
val (_, route, recipient) = longBlindedHops(hex"0451")
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
val add_b = UpdateAddHtlc(randomBytes32(), 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
val Right(ChannelRelayPacket(_, _, packet_c)) = decrypt(add_b, priv_b.privateKey, Features.empty)
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 1, amount_bc, paymentHash, expiry_bc, packet_c, None)
|
||||
val add_c = UpdateAddHtlc(randomBytes32(), 1, amount_bc, paymentHash, expiry_bc, packet_c, None, 1.0)
|
||||
val Right(ChannelRelayPacket(_, payload_c, packet_d)) = decrypt(add_c, priv_c.privateKey, Features(RouteBlinding -> Optional))
|
||||
val blinding_d = payload_c.asInstanceOf[IntermediatePayload.ChannelRelay.Blinded].nextBlinding
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 2, amount_cd, paymentHash, expiry_cd, packet_d, Some(blinding_d))
|
||||
val add_d = UpdateAddHtlc(randomBytes32(), 2, amount_cd, paymentHash, expiry_cd, packet_d, Some(blinding_d), 1.0)
|
||||
val Right(ChannelRelayPacket(_, payload_d, packet_e)) = decrypt(add_d, priv_d.privateKey, Features(RouteBlinding -> Optional))
|
||||
val blinding_e = payload_d.asInstanceOf[IntermediatePayload.ChannelRelay.Blinded].nextBlinding
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 3, amount_de, paymentHash, expiry_de, packet_e, Some(blinding_e))
|
||||
val add_e = UpdateAddHtlc(randomBytes32(), 3, amount_de, paymentHash, expiry_de, packet_e, Some(blinding_e), 1.0)
|
||||
val Right(FinalPacket(_, payload_e)) = decrypt(add_e, priv_e.privateKey, Features(RouteBlinding -> Optional))
|
||||
assert(payload_e.isInstanceOf[FinalPayload.Blinded])
|
||||
|
||||
|
@ -796,7 +796,7 @@ object PaymentPacketSpec {
|
|||
val blindedRoute = BlindedRouteCreation.createBlindedRouteWithoutHops(b, hex"deadbeef", 1.msat, routeExpiry).route
|
||||
val finalPayload = NodePayload(blindedRoute.introductionNode.blindedPublicKey, OutgoingBlindedPerHopPayload.createFinalPayload(finalAmount, finalAmount, finalExpiry, blindedRoute.introductionNode.encryptedPayload))
|
||||
val onion = buildOnion(Seq(finalPayload), paymentHash, Some(PaymentOnionCodecs.paymentOnionPayloadLength)).toOption.get // BOLT 2 requires that associatedData == paymentHash
|
||||
val cmd = CMD_ADD_HTLC(ActorRef.noSender, finalAmount, paymentHash, finalExpiry, onion.packet, Some(blindedRoute.blindingKey), TestConstants.emptyOrigin, commit = true)
|
||||
val cmd = CMD_ADD_HTLC(ActorRef.noSender, finalAmount, paymentHash, finalExpiry, onion.packet, Some(blindedRoute.blindingKey), 1.0, TestConstants.emptyOrigin, commit = true)
|
||||
Right(OutgoingPaymentPacket(cmd, channelUpdate_ab.shortChannelId, onion.sharedSecrets))
|
||||
}
|
||||
|
||||
|
|
|
@ -700,9 +700,9 @@ object PostRestartHtlcCleanerSpec {
|
|||
buildOutgoingBlindedPaymentAB(paymentHash)
|
||||
} else {
|
||||
val (route, recipient) = (Route(finalAmount, hops, None), SpontaneousRecipient(e, finalAmount, finalExpiry, randomBytes32()))
|
||||
buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
}
|
||||
UpdateAddHtlc(channelId, htlcId, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
UpdateAddHtlc(channelId, htlcId, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
}
|
||||
|
||||
def buildHtlcIn(htlcId: Long, channelId: ByteVector32, paymentHash: ByteVector32, blinded: Boolean = false): DirectedHtlc = IncomingHtlc(buildHtlc(htlcId, channelId, paymentHash, blinded))
|
||||
|
@ -710,8 +710,8 @@ object PostRestartHtlcCleanerSpec {
|
|||
def buildHtlcOut(htlcId: Long, channelId: ByteVector32, paymentHash: ByteVector32, blinded: Boolean = false): DirectedHtlc = OutgoingHtlc(buildHtlc(htlcId, channelId, paymentHash, blinded))
|
||||
|
||||
def buildFinalHtlc(htlcId: Long, channelId: ByteVector32, paymentHash: ByteVector32): DirectedHtlc = {
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, Seq(channelHopFromUpdate(a, b, channelUpdate_ab)), None), SpontaneousRecipient(b, finalAmount, finalExpiry, randomBytes32()))
|
||||
IncomingHtlc(UpdateAddHtlc(channelId, htlcId, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None))
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, Seq(channelHopFromUpdate(a, b, channelUpdate_ab)), None), SpontaneousRecipient(b, finalAmount, finalExpiry, randomBytes32()), 1.0)
|
||||
IncomingHtlc(UpdateAddHtlc(channelId, htlcId, payment.cmd.amount, paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None, 1.0))
|
||||
}
|
||||
|
||||
def buildForwardFail(add: UpdateAddHtlc, upstream: Upstream.Cold): RES_ADD_SETTLED[Origin.Cold, HtlcResult.Fail] =
|
||||
|
@ -734,11 +734,11 @@ object PostRestartHtlcCleanerSpec {
|
|||
val parentId = UUID.randomUUID()
|
||||
val (id1, id2, id3) = (UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID())
|
||||
|
||||
val add1 = UpdateAddHtlc(channelId_bc_1, 72, 561 msat, paymentHash1, CltvExpiry(4200), onionRoutingPacket = TestConstants.emptyOnionPacket, blinding_opt = None)
|
||||
val add1 = UpdateAddHtlc(channelId_bc_1, 72, 561 msat, paymentHash1, CltvExpiry(4200), onionRoutingPacket = TestConstants.emptyOnionPacket, blinding_opt = None, confidence = 1.0)
|
||||
val origin1 = Origin.Cold(Upstream.Local(id1))
|
||||
val add2 = UpdateAddHtlc(channelId_bc_1, 75, 1105 msat, paymentHash2, CltvExpiry(4250), onionRoutingPacket = TestConstants.emptyOnionPacket, blinding_opt = None)
|
||||
val add2 = UpdateAddHtlc(channelId_bc_1, 75, 1105 msat, paymentHash2, CltvExpiry(4250), onionRoutingPacket = TestConstants.emptyOnionPacket, blinding_opt = None, confidence = 1.0)
|
||||
val origin2 = Origin.Cold(Upstream.Local(id2))
|
||||
val add3 = UpdateAddHtlc(channelId_bc_1, 78, 1729 msat, paymentHash2, CltvExpiry(4300), onionRoutingPacket = TestConstants.emptyOnionPacket, blinding_opt = None)
|
||||
val add3 = UpdateAddHtlc(channelId_bc_1, 78, 1729 msat, paymentHash2, CltvExpiry(4300), onionRoutingPacket = TestConstants.emptyOnionPacket, blinding_opt = None, confidence = 1.0)
|
||||
val origin3 = Origin.Cold(Upstream.Local(id3))
|
||||
|
||||
// Prepare channels and payment state before restart.
|
||||
|
@ -847,10 +847,10 @@ object PostRestartHtlcCleanerSpec {
|
|||
|
||||
val notRelayed = Set((1L, channelId_bc_1), (0L, channelId_bc_2), (3L, channelId_bc_3), (5L, channelId_bc_3), (7L, channelId_bc_4))
|
||||
|
||||
val downstream_1_1 = UpdateAddHtlc(channelId_bc_1, 6L, finalAmount, paymentHash1, finalExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val downstream_2_1 = UpdateAddHtlc(channelId_bc_1, 8L, finalAmount, paymentHash2, finalExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val downstream_2_2 = UpdateAddHtlc(channelId_bc_2, 1L, finalAmount, paymentHash2, finalExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val downstream_2_3 = UpdateAddHtlc(channelId_bc_3, 4L, finalAmount, paymentHash2, finalExpiry, TestConstants.emptyOnionPacket, None)
|
||||
val downstream_1_1 = UpdateAddHtlc(channelId_bc_1, 6L, finalAmount, paymentHash1, finalExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val downstream_2_1 = UpdateAddHtlc(channelId_bc_1, 8L, finalAmount, paymentHash2, finalExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val downstream_2_2 = UpdateAddHtlc(channelId_bc_2, 1L, finalAmount, paymentHash2, finalExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val downstream_2_3 = UpdateAddHtlc(channelId_bc_3, 4L, finalAmount, paymentHash2, finalExpiry, TestConstants.emptyOnionPacket, None, 1.0)
|
||||
|
||||
val data_ab_1 = ChannelCodecsSpec.makeChannelDataNormal(htlc_ab_1, Map.empty)
|
||||
val data_ab_2 = ChannelCodecsSpec.makeChannelDataNormal(htlc_ab_2, Map.empty)
|
||||
|
|
|
@ -68,11 +68,12 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
fwd
|
||||
}
|
||||
|
||||
def expectFwdAdd(register: TestProbe[Any], channelId: ByteVector32, outAmount: MilliSatoshi, outExpiry: CltvExpiry): Register.Forward[CMD_ADD_HTLC] = {
|
||||
def expectFwdAdd(register: TestProbe[Any], channelId: ByteVector32, outAmount: MilliSatoshi, outExpiry: CltvExpiry, outEndorsement: Int): Register.Forward[CMD_ADD_HTLC] = {
|
||||
val fwd = register.expectMessageType[Register.Forward[CMD_ADD_HTLC]]
|
||||
inside(fwd.message) { case add: CMD_ADD_HTLC =>
|
||||
assert(add.amount == outAmount)
|
||||
assert(add.cltvExpiry == outExpiry)
|
||||
assert((add.confidence * 7.999).toInt == outEndorsement)
|
||||
}
|
||||
assert(fwd.channelId == channelId)
|
||||
fwd
|
||||
|
@ -88,7 +89,7 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
|
||||
if (success) {
|
||||
expectFwdAdd(register, lcu.channelId, outgoingAmount, outgoingExpiry)
|
||||
expectFwdAdd(register, lcu.channelId, outgoingAmount, outgoingExpiry, 7)
|
||||
} else {
|
||||
expectFwdFail(register, r.add.channelId, CMD_FAIL_HTLC(r.add.id, Right(UnknownNextPeer()), commit = true))
|
||||
}
|
||||
|
@ -135,7 +136,7 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
val r1 = createValidIncomingPacket(payload1)
|
||||
channelRelayer ! WrappedLocalChannelUpdate(lcu1)
|
||||
channelRelayer ! Relay(r1, TestConstants.Alice.nodeParams.nodeId)
|
||||
expectFwdAdd(register, lcu1.channelId, outgoingAmount, outgoingExpiry)
|
||||
expectFwdAdd(register, lcu1.channelId, outgoingAmount, outgoingExpiry, 7)
|
||||
|
||||
// reorg happens
|
||||
val realScid1AfterReorg = RealShortChannelId(111112)
|
||||
|
@ -146,10 +147,10 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
|
||||
// both old and new real scids work
|
||||
channelRelayer ! Relay(r1, TestConstants.Alice.nodeParams.nodeId)
|
||||
expectFwdAdd(register, lcu1.channelId, outgoingAmount, outgoingExpiry)
|
||||
expectFwdAdd(register, lcu1.channelId, outgoingAmount, outgoingExpiry, 7)
|
||||
// new real scid works
|
||||
channelRelayer ! Relay(r2, TestConstants.Alice.nodeParams.nodeId)
|
||||
expectFwdAdd(register, lcu2.channelId, outgoingAmount, outgoingExpiry)
|
||||
expectFwdAdd(register, lcu2.channelId, outgoingAmount, outgoingExpiry, 7)
|
||||
}
|
||||
|
||||
test("relay blinded payment") { f =>
|
||||
|
@ -162,7 +163,7 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
channelRelayer ! WrappedLocalChannelUpdate(u)
|
||||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
|
||||
expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry)
|
||||
expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry, 7)
|
||||
}
|
||||
|
||||
test("relay with retries") { f =>
|
||||
|
@ -182,12 +183,12 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
|
||||
// first try
|
||||
val fwd1 = expectFwdAdd(register, channelIds(realScid2), outgoingAmount, outgoingExpiry)
|
||||
val fwd1 = expectFwdAdd(register, channelIds(realScid2), outgoingAmount, outgoingExpiry, 7)
|
||||
// channel returns an error
|
||||
fwd1.message.replyTo ! RES_ADD_FAILED(fwd1.message, HtlcValueTooHighInFlight(channelIds(realScid2), 1000000000 msat, 1516977616 msat), Some(u2.channelUpdate))
|
||||
|
||||
// second try
|
||||
val fwd2 = expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry)
|
||||
val fwd2 = expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry, 7)
|
||||
// failure again
|
||||
fwd1.message.replyTo ! RES_ADD_FAILED(fwd2.message, HtlcValueTooHighInFlight(channelIds(realScid1), 1000000000 msat, 1516977616 msat), Some(u1.channelUpdate))
|
||||
|
||||
|
@ -216,7 +217,7 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
channelRelayer ! WrappedLocalChannelUpdate(u)
|
||||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
|
||||
val fwd = expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry)
|
||||
val fwd = expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry, 7)
|
||||
fwd.replyTo ! Register.ForwardFailure(fwd)
|
||||
|
||||
expectFwdFail(register, r.add.channelId, CMD_FAIL_HTLC(r.add.id, Right(UnknownNextPeer()), commit = true))
|
||||
|
@ -302,7 +303,7 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
channelRelayer ! WrappedLocalChannelUpdate(u)
|
||||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
|
||||
expectFwdAdd(register, channelIds(realScid1), r.amountToForward, r.outgoingCltv).message
|
||||
expectFwdAdd(register, channelIds(realScid1), r.amountToForward, r.outgoingCltv, 7).message
|
||||
}
|
||||
|
||||
test("fail to relay when expiry is too small") { f =>
|
||||
|
@ -342,7 +343,7 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
|
||||
// relay succeeds with current channel update (u1) with lower fees
|
||||
expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry)
|
||||
expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry, 7)
|
||||
|
||||
val u2 = createLocalUpdate(channelId1, timestamp = TimestampSecond.now() - 530)
|
||||
|
||||
|
@ -350,7 +351,7 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
|
||||
// relay succeeds because the current update (u2) with higher fees occurred less than 10 minutes ago
|
||||
expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry)
|
||||
expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry, 7)
|
||||
|
||||
val u3 = createLocalUpdate(channelId1, timestamp = TimestampSecond.now() - 601)
|
||||
|
||||
|
@ -386,7 +387,7 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
testCases.foreach { testCase =>
|
||||
channelRelayer ! WrappedLocalChannelUpdate(u)
|
||||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
val fwd = expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry)
|
||||
val fwd = expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry, 7)
|
||||
fwd.message.replyTo ! RES_ADD_FAILED(fwd.message, testCase.exc, Some(testCase.update))
|
||||
expectFwdFail(register, r.add.channelId, CMD_FAIL_HTLC(r.add.id, Right(testCase.failure), commit = true))
|
||||
}
|
||||
|
@ -419,19 +420,19 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
|
||||
{
|
||||
val payload = ChannelRelay.Standard(ShortChannelId(12345), 998900 msat, CltvExpiry(60))
|
||||
val r = createValidIncomingPacket(payload, 1000000 msat, CltvExpiry(70))
|
||||
val r = createValidIncomingPacket(payload, 1000000 msat, CltvExpiry(70), endorsementIn = 5)
|
||||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
// select the channel to the same node, with the lowest capacity and balance but still high enough to handle the payment
|
||||
val cmd1 = expectFwdAdd(register, channelUpdates(ShortChannelId(22223)).channelId, r.amountToForward, r.outgoingCltv).message
|
||||
val cmd1 = expectFwdAdd(register, channelUpdates(ShortChannelId(22223)).channelId, r.amountToForward, r.outgoingCltv, 5).message
|
||||
cmd1.replyTo ! RES_ADD_FAILED(cmd1, ChannelUnavailable(randomBytes32()), None)
|
||||
// select 2nd-to-best channel: higher capacity and balance
|
||||
val cmd2 = expectFwdAdd(register, channelUpdates(ShortChannelId(22222)).channelId, r.amountToForward, r.outgoingCltv).message
|
||||
val cmd2 = expectFwdAdd(register, channelUpdates(ShortChannelId(22222)).channelId, r.amountToForward, r.outgoingCltv, 5).message
|
||||
cmd2.replyTo ! RES_ADD_FAILED(cmd2, TooManyAcceptedHtlcs(randomBytes32(), 42), Some(channelUpdates(ShortChannelId(22222)).channelUpdate))
|
||||
// select 3rd-to-best channel: same balance but higher capacity
|
||||
val cmd3 = expectFwdAdd(register, channelUpdates(ShortChannelId(12345)).channelId, r.amountToForward, r.outgoingCltv).message
|
||||
val cmd3 = expectFwdAdd(register, channelUpdates(ShortChannelId(12345)).channelId, r.amountToForward, r.outgoingCltv, 5).message
|
||||
cmd3.replyTo ! RES_ADD_FAILED(cmd3, TooManyAcceptedHtlcs(randomBytes32(), 42), Some(channelUpdates(ShortChannelId(12345)).channelUpdate))
|
||||
// select 4th-to-best channel: same capacity but higher balance
|
||||
val cmd4 = expectFwdAdd(register, channelUpdates(ShortChannelId(11111)).channelId, r.amountToForward, r.outgoingCltv).message
|
||||
val cmd4 = expectFwdAdd(register, channelUpdates(ShortChannelId(11111)).channelId, r.amountToForward, r.outgoingCltv, 5).message
|
||||
cmd4.replyTo ! RES_ADD_FAILED(cmd4, HtlcValueTooHighInFlight(randomBytes32(), 100000000 msat, 100000000 msat), Some(channelUpdates(ShortChannelId(11111)).channelUpdate))
|
||||
// all the suitable channels have been tried
|
||||
expectFwdFail(register, r.add.channelId, CMD_FAIL_HTLC(r.add.id, Right(TemporaryChannelFailure(Some(channelUpdates(ShortChannelId(12345)).channelUpdate))), commit = true))
|
||||
|
@ -439,30 +440,30 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
{
|
||||
// higher amount payment (have to increased incoming htlc amount for fees to be sufficient)
|
||||
val payload = ChannelRelay.Standard(ShortChannelId(12345), 50000000 msat, CltvExpiry(60))
|
||||
val r = createValidIncomingPacket(payload, 60000000 msat, CltvExpiry(70))
|
||||
val r = createValidIncomingPacket(payload, 60000000 msat, CltvExpiry(70), endorsementIn = 0)
|
||||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
expectFwdAdd(register, channelUpdates(ShortChannelId(11111)).channelId, r.amountToForward, r.outgoingCltv).message
|
||||
expectFwdAdd(register, channelUpdates(ShortChannelId(11111)).channelId, r.amountToForward, r.outgoingCltv, 0).message
|
||||
}
|
||||
{
|
||||
// lower amount payment
|
||||
val payload = ChannelRelay.Standard(ShortChannelId(12345), 1000 msat, CltvExpiry(60))
|
||||
val r = createValidIncomingPacket(payload, 60000000 msat, CltvExpiry(70))
|
||||
val r = createValidIncomingPacket(payload, 60000000 msat, CltvExpiry(70), endorsementIn = 6)
|
||||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
expectFwdAdd(register, channelUpdates(ShortChannelId(33333)).channelId, r.amountToForward, r.outgoingCltv).message
|
||||
expectFwdAdd(register, channelUpdates(ShortChannelId(33333)).channelId, r.amountToForward, r.outgoingCltv, 6).message
|
||||
}
|
||||
{
|
||||
// payment too high, no suitable channel found, we keep the requested one
|
||||
val payload = ChannelRelay.Standard(ShortChannelId(12345), 1000000000 msat, CltvExpiry(60))
|
||||
val r = createValidIncomingPacket(payload, 1010000000 msat, CltvExpiry(70))
|
||||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
expectFwdAdd(register, channelUpdates(ShortChannelId(12345)).channelId, r.amountToForward, r.outgoingCltv).message
|
||||
expectFwdAdd(register, channelUpdates(ShortChannelId(12345)).channelId, r.amountToForward, r.outgoingCltv, 7).message
|
||||
}
|
||||
{
|
||||
// cltv expiry larger than our requirements
|
||||
val payload = ChannelRelay.Standard(ShortChannelId(12345), 998900 msat, CltvExpiry(50))
|
||||
val r = createValidIncomingPacket(payload, 1000000 msat, CltvExpiry(70))
|
||||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
expectFwdAdd(register, channelUpdates(ShortChannelId(22223)).channelId, r.amountToForward, r.outgoingCltv).message
|
||||
expectFwdAdd(register, channelUpdates(ShortChannelId(22223)).channelId, r.amountToForward, r.outgoingCltv, 7).message
|
||||
}
|
||||
{
|
||||
// cltv expiry too small, no suitable channel found
|
||||
|
@ -480,7 +481,7 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
val payload = ChannelRelay.Standard(realScid1, outgoingAmount, outgoingExpiry)
|
||||
val r = createValidIncomingPacket(payload, outgoingAmount + u.channelUpdate.feeBaseMsat, outgoingExpiry + u.channelUpdate.cltvExpiryDelta)
|
||||
val u_disabled = createLocalUpdate(channelId1, enabled = false)
|
||||
val downstream_htlc = UpdateAddHtlc(channelId1, 7, outgoingAmount, paymentHash, outgoingExpiry, emptyOnionPacket, None)
|
||||
val downstream_htlc = UpdateAddHtlc(channelId1, 7, outgoingAmount, paymentHash, outgoingExpiry, emptyOnionPacket, None, 1.0)
|
||||
|
||||
case class TestCase(result: HtlcResult, cmd: channel.HtlcSettlementCommand)
|
||||
|
||||
|
@ -495,7 +496,7 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
testCases.foreach { testCase =>
|
||||
channelRelayer ! WrappedLocalChannelUpdate(u)
|
||||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
val fwd = expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry)
|
||||
val fwd = expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry, 7)
|
||||
fwd.message.replyTo ! RES_SUCCESS(fwd.message, channelId1)
|
||||
fwd.message.origin.replyTo ! RES_ADD_SETTLED(fwd.message.origin, downstream_htlc, testCase.result)
|
||||
expectFwdFail(register, r.add.channelId, testCase.cmd)
|
||||
|
@ -506,7 +507,7 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
import f._
|
||||
|
||||
val u = createLocalUpdate(channelId1, feeBaseMsat = 5000 msat, feeProportionalMillionths = 0)
|
||||
val downstream = UpdateAddHtlc(channelId1, 7, outgoingAmount, paymentHash, outgoingExpiry, emptyOnionPacket, None)
|
||||
val downstream = UpdateAddHtlc(channelId1, 7, outgoingAmount, paymentHash, outgoingExpiry, emptyOnionPacket, None, 0.0625)
|
||||
|
||||
val testCases = Seq(
|
||||
HtlcResult.RemoteFail(UpdateFailHtlc(channelId1, downstream.id, hex"deadbeef")),
|
||||
|
@ -518,10 +519,10 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
|
||||
Seq(true, false).foreach { isIntroduction =>
|
||||
testCases.foreach { htlcResult =>
|
||||
val r = createValidIncomingPacket(createBlindedPayload(u.channelUpdate, isIntroduction), outgoingAmount + u.channelUpdate.feeBaseMsat, outgoingExpiry + u.channelUpdate.cltvExpiryDelta)
|
||||
val r = createValidIncomingPacket(createBlindedPayload(u.channelUpdate, isIntroduction), outgoingAmount + u.channelUpdate.feeBaseMsat, outgoingExpiry + u.channelUpdate.cltvExpiryDelta, endorsementIn = 0)
|
||||
channelRelayer ! WrappedLocalChannelUpdate(u)
|
||||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
val fwd = expectFwdAdd(register, channelId1, outgoingAmount, outgoingExpiry)
|
||||
val fwd = expectFwdAdd(register, channelId1, outgoingAmount, outgoingExpiry, 0)
|
||||
fwd.message.replyTo ! RES_SUCCESS(fwd.message, channelId1)
|
||||
fwd.message.origin.replyTo ! RES_ADD_SETTLED(fwd.message.origin, downstream, htlcResult)
|
||||
val cmd = register.expectMessageType[Register.Forward[channel.Command]]
|
||||
|
@ -550,9 +551,9 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
|
||||
val channelId1 = channelIds(realScid1)
|
||||
val payload = ChannelRelay.Standard(realScid1, outgoingAmount, outgoingExpiry)
|
||||
val r = createValidIncomingPacket(payload)
|
||||
val r = createValidIncomingPacket(payload, endorsementIn = 3)
|
||||
val u = createLocalUpdate(channelId1)
|
||||
val downstream_htlc = UpdateAddHtlc(channelId1, 7, outgoingAmount, paymentHash, outgoingExpiry, emptyOnionPacket, None)
|
||||
val downstream_htlc = UpdateAddHtlc(channelId1, 7, outgoingAmount, paymentHash, outgoingExpiry, emptyOnionPacket, None, 0.4375)
|
||||
|
||||
case class TestCase(result: HtlcResult)
|
||||
|
||||
|
@ -565,7 +566,7 @@ class ChannelRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("a
|
|||
channelRelayer ! WrappedLocalChannelUpdate(u)
|
||||
channelRelayer ! Relay(r, TestConstants.Alice.nodeParams.nodeId)
|
||||
|
||||
val fwd1 = expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry)
|
||||
val fwd1 = expectFwdAdd(register, channelIds(realScid1), outgoingAmount, outgoingExpiry, 3)
|
||||
fwd1.message.replyTo ! RES_SUCCESS(fwd1.message, channelId1)
|
||||
fwd1.message.origin.replyTo ! RES_ADD_SETTLED(fwd1.message.origin, downstream_htlc, testCase.result)
|
||||
|
||||
|
@ -665,12 +666,13 @@ object ChannelRelayerSpec {
|
|||
ChannelRelay.Blinded(tlvs, PaymentRelayData(blindedTlvs), randomKey().publicKey)
|
||||
}
|
||||
|
||||
def createValidIncomingPacket(payload: IntermediatePayload.ChannelRelay, amountIn: MilliSatoshi = 11_000_000 msat, expiryIn: CltvExpiry = CltvExpiry(400_100)): IncomingPaymentPacket.ChannelRelayPacket = {
|
||||
def createValidIncomingPacket(payload: IntermediatePayload.ChannelRelay, amountIn: MilliSatoshi = 11_000_000 msat, expiryIn: CltvExpiry = CltvExpiry(400_100), endorsementIn: Int = 7): IncomingPaymentPacket.ChannelRelayPacket = {
|
||||
val nextBlinding_opt = payload match {
|
||||
case p: ChannelRelay.Blinded => Some(p.nextBlinding)
|
||||
case p: ChannelRelay.Blinded => Some(UpdateAddHtlcTlv.BlindingPoint(p.nextBlinding))
|
||||
case _: ChannelRelay.Standard => None
|
||||
}
|
||||
val add_ab = UpdateAddHtlc(channelId = randomBytes32(), id = 123456, amountIn, paymentHash, expiryIn, emptyOnionPacket, nextBlinding_opt)
|
||||
val tlvs = TlvStream(Set[Option[UpdateAddHtlcTlv]](nextBlinding_opt, Some(UpdateAddHtlcTlv.Endorsement(endorsementIn))).flatten)
|
||||
val add_ab = UpdateAddHtlc(channelId = randomBytes32(), id = 123456, amountIn, paymentHash, expiryIn, emptyOnionPacket, tlvs)
|
||||
ChannelRelayPacket(add_ab, payload, emptyOnionPacket)
|
||||
}
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
incomingMultiPart.foreach(incoming => nodeRelayer ! NodeRelay.Relay(incoming, randomKey().publicKey))
|
||||
// and then one extra
|
||||
val extra = IncomingPaymentPacket.RelayToTrampolinePacket(
|
||||
UpdateAddHtlc(randomBytes32(), Random.nextInt(100), 1000 msat, paymentHash, CltvExpiry(499990), TestConstants.emptyOnionPacket, None),
|
||||
UpdateAddHtlc(randomBytes32(), Random.nextInt(100), 1000 msat, paymentHash, CltvExpiry(499990), TestConstants.emptyOnionPacket, None, 1.0),
|
||||
FinalPayload.Standard.createPayload(1000 msat, incomingAmount, CltvExpiry(499990), incomingSecret, None),
|
||||
IntermediatePayload.NodeRelay.Standard(outgoingAmount, outgoingExpiry, outgoingNodeId),
|
||||
nextTrampolinePacket)
|
||||
|
@ -248,13 +248,13 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
incomingMultiPart.foreach(incoming => nodeRelayer ! NodeRelay.Relay(incoming, randomKey().publicKey))
|
||||
|
||||
val outgoingCfg = mockPayFSM.expectMessageType[SendPaymentConfig]
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))))
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))), 5)
|
||||
val outgoingPayment = mockPayFSM.expectMessageType[SendMultiPartPayment]
|
||||
validateOutgoingPayment(outgoingPayment)
|
||||
|
||||
// Receive new extraneous multi-part HTLC.
|
||||
val i1 = IncomingPaymentPacket.RelayToTrampolinePacket(
|
||||
UpdateAddHtlc(randomBytes32(), Random.nextInt(100), 1000 msat, paymentHash, CltvExpiry(499990), TestConstants.emptyOnionPacket, None),
|
||||
UpdateAddHtlc(randomBytes32(), Random.nextInt(100), 1000 msat, paymentHash, CltvExpiry(499990), TestConstants.emptyOnionPacket, None, 1.0),
|
||||
FinalPayload.Standard.createPayload(1000 msat, incomingAmount, CltvExpiry(499990), incomingSecret, None),
|
||||
IntermediatePayload.NodeRelay.Standard(outgoingAmount, outgoingExpiry, outgoingNodeId),
|
||||
nextTrampolinePacket)
|
||||
|
@ -267,7 +267,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
|
||||
// Receive new HTLC with different details, but for the same payment hash.
|
||||
val i2 = IncomingPaymentPacket.RelayToTrampolinePacket(
|
||||
UpdateAddHtlc(randomBytes32(), Random.nextInt(100), 1500 msat, paymentHash, CltvExpiry(499990), TestConstants.emptyOnionPacket, None),
|
||||
UpdateAddHtlc(randomBytes32(), Random.nextInt(100), 1500 msat, paymentHash, CltvExpiry(499990), TestConstants.emptyOnionPacket, None, 1.0),
|
||||
PaymentOnion.FinalPayload.Standard.createPayload(1500 msat, 1500 msat, CltvExpiry(499990), incomingSecret, None),
|
||||
IntermediatePayload.NodeRelay.Standard(1250 msat, outgoingExpiry, outgoingNodeId),
|
||||
nextTrampolinePacket)
|
||||
|
@ -377,7 +377,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
|
||||
// upstream payment relayed
|
||||
val outgoingCfg = mockPayFSM.expectMessageType[SendPaymentConfig]
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingAsyncPayment.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))))
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingAsyncPayment.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))), 5)
|
||||
val outgoingPayment = mockPayFSM.expectMessageType[SendMultiPartPayment]
|
||||
validateOutgoingPayment(outgoingPayment)
|
||||
// those are adapters for pay-fsm messages
|
||||
|
@ -454,7 +454,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
|
||||
// upstream payment relayed
|
||||
val outgoingCfg = mockPayFSM.expectMessageType[SendPaymentConfig]
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingAsyncPayment.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))))
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingAsyncPayment.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))), 5)
|
||||
val outgoingPayment = mockPayFSM.expectMessageType[SendMultiPartPayment]
|
||||
validateOutgoingPayment(outgoingPayment)
|
||||
// those are adapters for pay-fsm messages
|
||||
|
@ -662,7 +662,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
nodeRelayer ! NodeRelay.Relay(incomingMultiPart.last, randomKey().publicKey)
|
||||
|
||||
val outgoingCfg = mockPayFSM.expectMessageType[SendPaymentConfig]
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))))
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))), 5)
|
||||
val outgoingPayment = mockPayFSM.expectMessageType[SendMultiPartPayment]
|
||||
validateOutgoingPayment(outgoingPayment)
|
||||
// those are adapters for pay-fsm messages
|
||||
|
@ -698,7 +698,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
nodeRelayer ! NodeRelay.Relay(incomingSinglePart, randomKey().publicKey)
|
||||
|
||||
val outgoingCfg = mockPayFSM.expectMessageType[SendPaymentConfig]
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(Upstream.Hot.Channel(incomingSinglePart.add, TimestampMilli.now(), randomKey().publicKey) :: Nil))
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(Upstream.Hot.Channel(incomingSinglePart.add, TimestampMilli.now(), randomKey().publicKey) :: Nil), 7)
|
||||
val outgoingPayment = mockPayFSM.expectMessageType[SendMultiPartPayment]
|
||||
validateOutgoingPayment(outgoingPayment)
|
||||
// those are adapters for pay-fsm messages
|
||||
|
@ -733,7 +733,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
incomingPayments.foreach(incoming => nodeRelayer ! NodeRelay.Relay(incoming, randomKey().publicKey))
|
||||
|
||||
val outgoingCfg = mockPayFSM.expectMessageType[SendPaymentConfig]
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))))
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))), 5)
|
||||
val outgoingPayment = mockPayFSM.expectMessageType[SendMultiPartPayment]
|
||||
assert(outgoingPayment.recipient.nodeId == outgoingNodeId)
|
||||
assert(outgoingPayment.recipient.totalAmount == outgoingAmount)
|
||||
|
@ -777,7 +777,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
incomingPayments.foreach(incoming => nodeRelayer ! NodeRelay.Relay(incoming, randomKey().publicKey))
|
||||
|
||||
val outgoingCfg = mockPayFSM.expectMessageType[SendPaymentConfig]
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))))
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))), 5)
|
||||
val outgoingPayment = mockPayFSM.expectMessageType[SendPaymentToNode]
|
||||
assert(outgoingPayment.recipient.nodeId == outgoingNodeId)
|
||||
assert(outgoingPayment.amount == outgoingAmount)
|
||||
|
@ -846,7 +846,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
incomingPayments.foreach(incoming => nodeRelayer ! NodeRelay.Relay(incoming, randomKey().publicKey))
|
||||
|
||||
val outgoingCfg = mockPayFSM.expectMessageType[SendPaymentConfig]
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))), ignoreNodeId = true)
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))), 5, ignoreNodeId = true)
|
||||
val outgoingPayment = mockPayFSM.expectMessageType[SendPaymentToNode]
|
||||
assert(outgoingPayment.amount == outgoingAmount)
|
||||
assert(outgoingPayment.recipient.expiry == outgoingExpiry)
|
||||
|
@ -885,7 +885,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
incomingPayments.foreach(incoming => nodeRelayer ! NodeRelay.Relay(incoming, randomKey().publicKey))
|
||||
|
||||
val outgoingCfg = mockPayFSM.expectMessageType[SendPaymentConfig]
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))), ignoreNodeId = true)
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))), 5, ignoreNodeId = true)
|
||||
val outgoingPayment = mockPayFSM.expectMessageType[SendMultiPartPayment]
|
||||
assert(outgoingPayment.recipient.totalAmount == outgoingAmount)
|
||||
assert(outgoingPayment.recipient.expiry == outgoingExpiry)
|
||||
|
@ -932,7 +932,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
getNodeId.replyTo ! Some(outgoingNodeId)
|
||||
|
||||
val outgoingCfg = mockPayFSM.expectMessageType[SendPaymentConfig]
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))), ignoreNodeId = true)
|
||||
validateOutgoingCfg(outgoingCfg, Upstream.Hot.Trampoline(incomingMultiPart.map(p => Upstream.Hot.Channel(p.add, TimestampMilli.now(), randomKey().publicKey))), 5, ignoreNodeId = true)
|
||||
val outgoingPayment = mockPayFSM.expectMessageType[SendPaymentToNode]
|
||||
assert(outgoingPayment.amount == outgoingAmount)
|
||||
assert(outgoingPayment.recipient.expiry == outgoingExpiry)
|
||||
|
@ -987,7 +987,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
}
|
||||
}
|
||||
|
||||
def validateOutgoingCfg(outgoingCfg: SendPaymentConfig, upstream: Upstream, ignoreNodeId: Boolean = false): Unit = {
|
||||
def validateOutgoingCfg(outgoingCfg: SendPaymentConfig, upstream: Upstream, endorsement: Int, ignoreNodeId: Boolean = false): Unit = {
|
||||
assert(!outgoingCfg.publishEvent)
|
||||
assert(!outgoingCfg.storeInDb)
|
||||
assert(outgoingCfg.paymentHash == paymentHash)
|
||||
|
@ -997,6 +997,7 @@ class NodeRelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
|
|||
case (Upstream.Hot.Trampoline(adds1), Upstream.Hot.Trampoline(adds2)) => assert(adds1.map(_.add) == adds2.map(_.add))
|
||||
case _ => assert(outgoingCfg.upstream == upstream)
|
||||
}
|
||||
assert((outgoingCfg.confidence * 7.999).toInt == endorsement)
|
||||
}
|
||||
|
||||
def validateOutgoingPayment(outgoingPayment: SendMultiPartPayment): Unit = {
|
||||
|
@ -1037,9 +1038,9 @@ object NodeRelayerSpec {
|
|||
val incomingAmount = 41_000_000 msat
|
||||
val incomingSecret = randomBytes32()
|
||||
val incomingMultiPart = Seq(
|
||||
createValidIncomingPacket(15_000_000 msat, incomingAmount, CltvExpiry(500000), outgoingAmount, outgoingExpiry),
|
||||
createValidIncomingPacket(15_000_000 msat, incomingAmount, CltvExpiry(499999), outgoingAmount, outgoingExpiry),
|
||||
createValidIncomingPacket(11_000_000 msat, incomingAmount, CltvExpiry(499999), outgoingAmount, outgoingExpiry)
|
||||
createValidIncomingPacket(15_000_000 msat, incomingAmount, CltvExpiry(500000), outgoingAmount, outgoingExpiry, endorsementIn = 6),
|
||||
createValidIncomingPacket(15_000_000 msat, incomingAmount, CltvExpiry(499999), outgoingAmount, outgoingExpiry, endorsementIn = 5),
|
||||
createValidIncomingPacket(11_000_000 msat, incomingAmount, CltvExpiry(499999), outgoingAmount, outgoingExpiry, endorsementIn = 7)
|
||||
)
|
||||
val incomingSinglePart = createValidIncomingPacket(incomingAmount, incomingAmount, CltvExpiry(500000), outgoingAmount, outgoingExpiry)
|
||||
val incomingAsyncPayment: Seq[RelayToTrampolinePacket] = incomingMultiPart.map(p => p.copy(innerPayload = IntermediatePayload.NodeRelay.Standard.createNodeRelayForAsyncPayment(p.innerPayload.amountToForward, p.innerPayload.outgoingCltv, outgoingNodeId)))
|
||||
|
@ -1053,10 +1054,11 @@ object NodeRelayerSpec {
|
|||
def createSuccessEvent(): PaymentSent =
|
||||
PaymentSent(relayId, paymentHash, paymentPreimage, outgoingAmount, outgoingNodeId, Seq(PaymentSent.PartialPayment(UUID.randomUUID(), outgoingAmount, 10 msat, randomBytes32(), None)))
|
||||
|
||||
def createValidIncomingPacket(amountIn: MilliSatoshi, totalAmountIn: MilliSatoshi, expiryIn: CltvExpiry, amountOut: MilliSatoshi, expiryOut: CltvExpiry): RelayToTrampolinePacket = {
|
||||
def createValidIncomingPacket(amountIn: MilliSatoshi, totalAmountIn: MilliSatoshi, expiryIn: CltvExpiry, amountOut: MilliSatoshi, expiryOut: CltvExpiry, endorsementIn: Int = 7): RelayToTrampolinePacket = {
|
||||
val outerPayload = FinalPayload.Standard.createPayload(amountIn, totalAmountIn, expiryIn, incomingSecret, None)
|
||||
val tlvs = TlvStream[UpdateAddHtlcTlv](UpdateAddHtlcTlv.Endorsement(endorsementIn))
|
||||
RelayToTrampolinePacket(
|
||||
UpdateAddHtlc(randomBytes32(), Random.nextInt(100), amountIn, paymentHash, expiryIn, TestConstants.emptyOnionPacket, None),
|
||||
UpdateAddHtlc(randomBytes32(), Random.nextInt(100), amountIn, paymentHash, expiryIn, TestConstants.emptyOnionPacket, tlvs),
|
||||
outerPayload,
|
||||
IntermediatePayload.NodeRelay.Standard(amountOut, expiryOut, outgoingNodeId),
|
||||
nextTrampolinePacket)
|
||||
|
@ -1066,7 +1068,7 @@ object NodeRelayerSpec {
|
|||
val (expiryIn, expiryOut) = (CltvExpiry(500000), CltvExpiry(490000))
|
||||
val amountIn = incomingAmount / 2
|
||||
RelayToTrampolinePacket(
|
||||
UpdateAddHtlc(randomBytes32(), Random.nextInt(100), amountIn, paymentHash, expiryIn, TestConstants.emptyOnionPacket, None),
|
||||
UpdateAddHtlc(randomBytes32(), Random.nextInt(100), amountIn, paymentHash, expiryIn, TestConstants.emptyOnionPacket, None, 1.0),
|
||||
FinalPayload.Standard.createPayload(amountIn, incomingAmount, expiryIn, paymentSecret, None),
|
||||
IntermediatePayload.NodeRelay.Standard(outgoingAmount, expiryOut, outgoingNodeId),
|
||||
nextTrampolinePacket)
|
||||
|
|
|
@ -90,9 +90,9 @@ class RelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("applicat
|
|||
}
|
||||
|
||||
// we use this to build a valid onion
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, hops, None), ClearRecipient(e, Features.empty, finalAmount, finalExpiry, paymentSecret))
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, hops, None), ClearRecipient(e, Features.empty, finalAmount, finalExpiry, paymentSecret), 1.0)
|
||||
// and then manually build an htlc
|
||||
val add_ab = UpdateAddHtlc(randomBytes32(), 123456, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None)
|
||||
val add_ab = UpdateAddHtlc(randomBytes32(), 123456, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None, 1.0)
|
||||
relayer ! RelayForward(add_ab, priv_a.publicKey)
|
||||
register.expectMessageType[Register.Forward[CMD_ADD_HTLC]]
|
||||
}
|
||||
|
@ -100,8 +100,8 @@ class RelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("applicat
|
|||
test("relay an htlc-add at the final node to the payment handler") { f =>
|
||||
import f._
|
||||
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, hops.take(1), None), ClearRecipient(b, Features.empty, finalAmount, finalExpiry, paymentSecret))
|
||||
val add_ab = UpdateAddHtlc(channelId_ab, 123456, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, hops.take(1), None), ClearRecipient(b, Features.empty, finalAmount, finalExpiry, paymentSecret), 1.0)
|
||||
val add_ab = UpdateAddHtlc(channelId_ab, 123456, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None, 1.0)
|
||||
relayer ! RelayForward(add_ab, priv_a.publicKey)
|
||||
|
||||
val fp = paymentHandler.expectMessageType[FinalPacket]
|
||||
|
@ -119,10 +119,10 @@ class RelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("applicat
|
|||
val finalTrampolinePayload = NodePayload(b, FinalPayload.Standard.createPayload(finalAmount, totalAmount, finalExpiry, paymentSecret))
|
||||
val Right(trampolineOnion) = buildOnion(Seq(finalTrampolinePayload), paymentHash, None)
|
||||
val recipient = ClearRecipient(b, nodeParams.features.invoiceFeatures(), finalAmount, finalExpiry, randomBytes32(), nextTrampolineOnion_opt = Some(trampolineOnion.packet))
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, Seq(channelHopFromUpdate(priv_a.publicKey, b, channelUpdate_ab)), None), recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, Seq(channelHopFromUpdate(priv_a.publicKey, b, channelUpdate_ab)), None), recipient, 1.0)
|
||||
assert(payment.cmd.amount == finalAmount)
|
||||
assert(payment.cmd.cltvExpiry == finalExpiry)
|
||||
val add_ab = UpdateAddHtlc(channelId_ab, 123456, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None)
|
||||
val add_ab = UpdateAddHtlc(channelId_ab, 123456, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None, 1.0)
|
||||
relayer ! RelayForward(add_ab, priv_a.publicKey)
|
||||
|
||||
val fp = paymentHandler.expectMessageType[FinalPacket]
|
||||
|
@ -140,9 +140,9 @@ class RelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("applicat
|
|||
import f._
|
||||
|
||||
// we use this to build a valid onion
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, hops, None), ClearRecipient(e, Features.empty, finalAmount, finalExpiry, paymentSecret))
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(finalAmount, hops, None), ClearRecipient(e, Features.empty, finalAmount, finalExpiry, paymentSecret), 1.0)
|
||||
// and then manually build an htlc with an invalid onion (hmac)
|
||||
val add_ab = UpdateAddHtlc(channelId_ab, 123456, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion.copy(hmac = payment.cmd.onion.hmac.reverse), None)
|
||||
val add_ab = UpdateAddHtlc(channelId_ab, 123456, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion.copy(hmac = payment.cmd.onion.hmac.reverse), None, 1.0)
|
||||
relayer ! RelayForward(add_ab, priv_a.publicKey)
|
||||
|
||||
val fail = register.expectMessageType[Register.Forward[CMD_FAIL_MALFORMED_HTLC]].message
|
||||
|
@ -160,8 +160,8 @@ class RelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("applicat
|
|||
val routeExpiry = CltvExpiry(nodeParams.currentBlockHeight - 10)
|
||||
val (_, blindedHop, recipient) = blindedRouteFromHops(finalAmount, finalExpiry, Seq(channelHopFromUpdate(b, c, channelUpdate_bc)), routeExpiry, paymentPreimage, hex"deadbeef")
|
||||
val route = Route(finalAmount, Seq(channelHopFromUpdate(priv_a.publicKey, b, channelUpdate_ab)), Some(blindedHop))
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient)
|
||||
val add_ab = UpdateAddHtlc(channelId_ab, 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, route, recipient, 1.0)
|
||||
val add_ab = UpdateAddHtlc(channelId_ab, 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
relayer ! RelayForward(add_ab, priv_a.publicKey)
|
||||
|
||||
val fail = register.expectMessageType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
|
@ -177,7 +177,7 @@ class RelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("applicat
|
|||
|
||||
// we use an expired blinded route.
|
||||
val Right(payment) = buildOutgoingBlindedPaymentAB(paymentHash, routeExpiry = CltvExpiry(nodeParams.currentBlockHeight - 1))
|
||||
val add_ab = UpdateAddHtlc(channelId_ab, 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt)
|
||||
val add_ab = UpdateAddHtlc(channelId_ab, 0, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, payment.cmd.nextBlindingKey_opt, 1.0)
|
||||
relayer ! RelayForward(add_ab, priv_a.publicKey)
|
||||
|
||||
val fail = register.expectMessageType[Register.Forward[CMD_FAIL_MALFORMED_HTLC]].message
|
||||
|
@ -196,10 +196,10 @@ class RelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("applicat
|
|||
val invoice = Bolt11Invoice(Block.RegtestGenesisBlock.hash, None, paymentHash, priv_c.privateKey, Left("invoice"), CltvExpiryDelta(6), paymentSecret = paymentSecret, features = invoiceFeatures)
|
||||
val trampolineHop = NodeHop(b, c, channelUpdate_bc.cltvExpiryDelta, fee_b)
|
||||
val recipient = TrampolineRecipient(invoice, finalAmount, finalExpiry, trampolineHop, randomBytes32())
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(recipient.trampolineAmount, Seq(channelHopFromUpdate(priv_a.publicKey, b, channelUpdate_ab)), Some(trampolineHop)), recipient)
|
||||
val Right(payment) = buildOutgoingPayment(TestConstants.emptyOrigin, paymentHash, Route(recipient.trampolineAmount, Seq(channelHopFromUpdate(priv_a.publicKey, b, channelUpdate_ab)), Some(trampolineHop)), recipient, 1.0)
|
||||
|
||||
// and then manually build an htlc
|
||||
val add_ab = UpdateAddHtlc(channelId_ab, 123456, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None)
|
||||
val add_ab = UpdateAddHtlc(channelId_ab, 123456, payment.cmd.amount, payment.cmd.paymentHash, payment.cmd.cltvExpiry, payment.cmd.onion, None, 1.0)
|
||||
relayer ! RelayForward(add_ab, priv_a.publicKey)
|
||||
|
||||
val fail = register.expectMessageType[Register.Forward[CMD_FAIL_HTLC]].message
|
||||
|
@ -213,8 +213,8 @@ class RelayerSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("applicat
|
|||
import f._
|
||||
|
||||
val replyTo = TestProbe[Any]()
|
||||
val add_ab = UpdateAddHtlc(channelId = channelId_ab, id = 42, amountMsat = 11000000 msat, paymentHash = ByteVector32.Zeroes, CltvExpiry(4200), TestConstants.emptyOnionPacket, None)
|
||||
val add_bc = UpdateAddHtlc(channelId_bc, 72, 1000 msat, paymentHash, CltvExpiry(1), TestConstants.emptyOnionPacket, None)
|
||||
val add_ab = UpdateAddHtlc(channelId = channelId_ab, id = 42, amountMsat = 11000000 msat, paymentHash = ByteVector32.Zeroes, CltvExpiry(4200), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val add_bc = UpdateAddHtlc(channelId_bc, 72, 1000 msat, paymentHash, CltvExpiry(1), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val channelOrigin = Origin.Hot(replyTo.ref.toClassic, Upstream.Hot.Channel(add_ab, TimestampMilli.now(), priv_a.publicKey))
|
||||
val trampolineOrigin = Origin.Hot(replyTo.ref.toClassic, Upstream.Hot.Trampoline(Seq(Upstream.Hot.Channel(add_ab, TimestampMilli.now(), priv_a.publicKey))))
|
||||
|
||||
|
|
|
@ -29,11 +29,11 @@ class CommitmentSpecSpec extends AnyFunSuite {
|
|||
val R = randomBytes32()
|
||||
val H = Crypto.sha256(R)
|
||||
|
||||
val add1 = UpdateAddHtlc(ByteVector32.Zeroes, 1, (2000 * 1000) msat, H, CltvExpiry(400), TestConstants.emptyOnionPacket, None)
|
||||
val add1 = UpdateAddHtlc(ByteVector32.Zeroes, 1, (2000 * 1000) msat, H, CltvExpiry(400), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val spec1 = CommitmentSpec.reduce(spec, add1 :: Nil, Nil)
|
||||
assert(spec1 == spec.copy(htlcs = Set(OutgoingHtlc(add1)), toLocal = 3000000 msat))
|
||||
|
||||
val add2 = UpdateAddHtlc(ByteVector32.Zeroes, 2, (1000 * 1000) msat, H, CltvExpiry(400), TestConstants.emptyOnionPacket, None)
|
||||
val add2 = UpdateAddHtlc(ByteVector32.Zeroes, 2, (1000 * 1000) msat, H, CltvExpiry(400), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val spec2 = CommitmentSpec.reduce(spec1, add2 :: Nil, Nil)
|
||||
assert(spec2 == spec1.copy(htlcs = Set(OutgoingHtlc(add1), OutgoingHtlc(add2)), toLocal = 2000000 msat))
|
||||
|
||||
|
@ -51,11 +51,11 @@ class CommitmentSpecSpec extends AnyFunSuite {
|
|||
val R = randomBytes32()
|
||||
val H = Crypto.sha256(R)
|
||||
|
||||
val add1 = UpdateAddHtlc(ByteVector32.Zeroes, 1, (2000 * 1000) msat, H, CltvExpiry(400), TestConstants.emptyOnionPacket, None)
|
||||
val add1 = UpdateAddHtlc(ByteVector32.Zeroes, 1, (2000 * 1000) msat, H, CltvExpiry(400), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val spec1 = CommitmentSpec.reduce(spec, Nil, add1 :: Nil)
|
||||
assert(spec1 == spec.copy(htlcs = Set(IncomingHtlc(add1)), toRemote = 3000 * 1000 msat))
|
||||
|
||||
val add2 = UpdateAddHtlc(ByteVector32.Zeroes, 2, (1000 * 1000) msat, H, CltvExpiry(400), TestConstants.emptyOnionPacket, None)
|
||||
val add2 = UpdateAddHtlc(ByteVector32.Zeroes, 2, (1000 * 1000) msat, H, CltvExpiry(400), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val spec2 = CommitmentSpec.reduce(spec1, Nil, add2 :: Nil)
|
||||
assert(spec2 == spec1.copy(htlcs = Set(IncomingHtlc(add1), IncomingHtlc(add2)), toRemote = (2000 * 1000) msat))
|
||||
|
||||
|
@ -76,7 +76,7 @@ class CommitmentSpecSpec extends AnyFunSuite {
|
|||
}
|
||||
|
||||
def createHtlc(amount: MilliSatoshi): UpdateAddHtlc = {
|
||||
UpdateAddHtlc(ByteVector32.Zeroes, 0, amount, randomBytes32(), CltvExpiry(500), TestConstants.emptyOnionPacket, None)
|
||||
UpdateAddHtlc(ByteVector32.Zeroes, 0, amount, randomBytes32(), CltvExpiry(500), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -153,13 +153,13 @@ trait TestVectorsSpec extends AnyFunSuite with Logging {
|
|||
)
|
||||
|
||||
val htlcs = Seq[DirectedHtlc](
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 1000000 msat, Crypto.sha256(paymentPreimages(0)), CltvExpiry(500), TestConstants.emptyOnionPacket, None)),
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 1, 2000000 msat, Crypto.sha256(paymentPreimages(1)), CltvExpiry(501), TestConstants.emptyOnionPacket, None)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 2000000 msat, Crypto.sha256(paymentPreimages(2)), CltvExpiry(502), TestConstants.emptyOnionPacket, None)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 1, 3000000 msat, Crypto.sha256(paymentPreimages(3)), CltvExpiry(503), TestConstants.emptyOnionPacket, None)),
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 2, 4000000 msat, Crypto.sha256(paymentPreimages(4)), CltvExpiry(504), TestConstants.emptyOnionPacket, None)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 2, 5000001.msat, Crypto.sha256(paymentPreimages(5)), CltvExpiry(505), TestConstants.emptyOnionPacket, None)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 3, 5000000.msat, Crypto.sha256(paymentPreimages(5)), CltvExpiry(506), TestConstants.emptyOnionPacket, None))
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 1000000 msat, Crypto.sha256(paymentPreimages(0)), CltvExpiry(500), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 1, 2000000 msat, Crypto.sha256(paymentPreimages(1)), CltvExpiry(501), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 2000000 msat, Crypto.sha256(paymentPreimages(2)), CltvExpiry(502), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 1, 3000000 msat, Crypto.sha256(paymentPreimages(3)), CltvExpiry(503), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 2, 4000000 msat, Crypto.sha256(paymentPreimages(4)), CltvExpiry(504), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 2, 5000001.msat, Crypto.sha256(paymentPreimages(5)), CltvExpiry(505), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 3, 5000000.msat, Crypto.sha256(paymentPreimages(5)), CltvExpiry(506), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
)
|
||||
val htlcScripts = htlcs.map {
|
||||
case OutgoingHtlc(add) => Scripts.htlcOffered(Local.htlc_privkey.publicKey, Remote.htlc_privkey.publicKey, Local.revocation_pubkey, Crypto.ripemd160(add.paymentHash), commitmentFormat)
|
||||
|
|
|
@ -100,10 +100,10 @@ class TransactionsSpec extends AnyFunSuite with Logging {
|
|||
test("compute fees") {
|
||||
// see BOLT #3 specs
|
||||
val htlcs = Set[DirectedHtlc](
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 5000000 msat, ByteVector32.Zeroes, CltvExpiry(552), TestConstants.emptyOnionPacket, None)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 1000000 msat, ByteVector32.Zeroes, CltvExpiry(553), TestConstants.emptyOnionPacket, None)),
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 7000000 msat, ByteVector32.Zeroes, CltvExpiry(550), TestConstants.emptyOnionPacket, None)),
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 800000 msat, ByteVector32.Zeroes, CltvExpiry(551), TestConstants.emptyOnionPacket, None))
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 5000000 msat, ByteVector32.Zeroes, CltvExpiry(552), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 1000000 msat, ByteVector32.Zeroes, CltvExpiry(553), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 7000000 msat, ByteVector32.Zeroes, CltvExpiry(550), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 800000 msat, ByteVector32.Zeroes, CltvExpiry(551), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
)
|
||||
val spec = CommitmentSpec(htlcs, FeeratePerKw(5000 sat), toLocal = 0 msat, toRemote = 0 msat)
|
||||
val fee = commitTxFeeMsat(546 sat, spec, DefaultCommitmentFormat)
|
||||
|
@ -154,7 +154,7 @@ class TransactionsSpec extends AnyFunSuite with Logging {
|
|||
// HtlcPenaltyTx
|
||||
// first we create a fake commitTx tx, containing only the output that will be spent by the ClaimHtlcSuccessTx
|
||||
val paymentPreimage = randomBytes32()
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, (20000 * 1000) msat, sha256(paymentPreimage), CltvExpiryDelta(144).toCltvExpiry(blockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, (20000 * 1000) msat, sha256(paymentPreimage), CltvExpiryDelta(144).toCltvExpiry(blockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val redeemScript = htlcReceived(localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localRevocationPriv.publicKey, ripemd160(htlc.paymentHash), htlc.cltvExpiry, DefaultCommitmentFormat)
|
||||
val pubKeyScript = write(pay2wsh(redeemScript))
|
||||
val commitTx = Transaction(version = 2, txIn = Nil, txOut = TxOut(htlc.amountMsat.truncateToSatoshi, pubKeyScript) :: Nil, lockTime = 0)
|
||||
|
@ -168,7 +168,7 @@ class TransactionsSpec extends AnyFunSuite with Logging {
|
|||
// ClaimHtlcSuccessTx
|
||||
// first we create a fake commitTx tx, containing only the output that will be spent by the ClaimHtlcSuccessTx
|
||||
val paymentPreimage = randomBytes32()
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, (20000 * 1000) msat, sha256(paymentPreimage), CltvExpiryDelta(144).toCltvExpiry(blockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, (20000 * 1000) msat, sha256(paymentPreimage), CltvExpiryDelta(144).toCltvExpiry(blockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val spec = CommitmentSpec(Set(OutgoingHtlc(htlc)), feeratePerKw, toLocal = 0 msat, toRemote = 0 msat)
|
||||
val outputs = makeCommitTxOutputs(localPaysCommitTxFees = true, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, remotePaymentPriv.publicKey, localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localFundingPriv.publicKey, remoteFundingPriv.publicKey, spec, DefaultCommitmentFormat)
|
||||
val pubKeyScript = write(pay2wsh(htlcOffered(localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localRevocationPriv.publicKey, ripemd160(htlc.paymentHash), DefaultCommitmentFormat)))
|
||||
|
@ -183,7 +183,7 @@ class TransactionsSpec extends AnyFunSuite with Logging {
|
|||
// ClaimHtlcTimeoutTx
|
||||
// first we create a fake commitTx tx, containing only the output that will be spent by the ClaimHtlcTimeoutTx
|
||||
val paymentPreimage = randomBytes32()
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, (20000 * 1000) msat, sha256(paymentPreimage), toLocalDelay.toCltvExpiry(blockHeight), TestConstants.emptyOnionPacket, None)
|
||||
val htlc = UpdateAddHtlc(ByteVector32.Zeroes, 0, (20000 * 1000) msat, sha256(paymentPreimage), toLocalDelay.toCltvExpiry(blockHeight), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val spec = CommitmentSpec(Set(IncomingHtlc(htlc)), feeratePerKw, toLocal = 0 msat, toRemote = 0 msat)
|
||||
val outputs = makeCommitTxOutputs(localPaysCommitTxFees = true, localDustLimit, localRevocationPriv.publicKey, toLocalDelay, localDelayedPaymentPriv.publicKey, remotePaymentPriv.publicKey, localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localFundingPriv.publicKey, remoteFundingPriv.publicKey, spec, DefaultCommitmentFormat)
|
||||
val pubKeyScript = write(pay2wsh(htlcReceived(localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localRevocationPriv.publicKey, ripemd160(htlc.paymentHash), htlc.cltvExpiry, DefaultCommitmentFormat)))
|
||||
|
@ -261,17 +261,17 @@ class TransactionsSpec extends AnyFunSuite with Logging {
|
|||
|
||||
// htlc1 and htlc2 are regular IN/OUT htlcs
|
||||
val paymentPreimage1 = randomBytes32()
|
||||
val htlc1 = UpdateAddHtlc(ByteVector32.Zeroes, 0, MilliBtc(100).toMilliSatoshi, sha256(paymentPreimage1), CltvExpiry(300), TestConstants.emptyOnionPacket, None)
|
||||
val htlc1 = UpdateAddHtlc(ByteVector32.Zeroes, 0, MilliBtc(100).toMilliSatoshi, sha256(paymentPreimage1), CltvExpiry(300), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val paymentPreimage2 = randomBytes32()
|
||||
val htlc2 = UpdateAddHtlc(ByteVector32.Zeroes, 1, MilliBtc(200).toMilliSatoshi, sha256(paymentPreimage2), CltvExpiry(310), TestConstants.emptyOnionPacket, None)
|
||||
val htlc2 = UpdateAddHtlc(ByteVector32.Zeroes, 1, MilliBtc(200).toMilliSatoshi, sha256(paymentPreimage2), CltvExpiry(310), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
// htlc3 and htlc4 are dust IN/OUT htlcs, with an amount large enough to be included in the commit tx, but too small to be claimed at 2nd stage
|
||||
val paymentPreimage3 = randomBytes32()
|
||||
val htlc3 = UpdateAddHtlc(ByteVector32.Zeroes, 2, (localDustLimit + weight2fee(feeratePerKw, DefaultCommitmentFormat.htlcTimeoutWeight)).toMilliSatoshi, sha256(paymentPreimage3), CltvExpiry(295), TestConstants.emptyOnionPacket, None)
|
||||
val htlc3 = UpdateAddHtlc(ByteVector32.Zeroes, 2, (localDustLimit + weight2fee(feeratePerKw, DefaultCommitmentFormat.htlcTimeoutWeight)).toMilliSatoshi, sha256(paymentPreimage3), CltvExpiry(295), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val paymentPreimage4 = randomBytes32()
|
||||
val htlc4 = UpdateAddHtlc(ByteVector32.Zeroes, 3, (localDustLimit + weight2fee(feeratePerKw, DefaultCommitmentFormat.htlcSuccessWeight)).toMilliSatoshi, sha256(paymentPreimage4), CltvExpiry(300), TestConstants.emptyOnionPacket, None)
|
||||
val htlc4 = UpdateAddHtlc(ByteVector32.Zeroes, 3, (localDustLimit + weight2fee(feeratePerKw, DefaultCommitmentFormat.htlcSuccessWeight)).toMilliSatoshi, sha256(paymentPreimage4), CltvExpiry(300), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
// htlc5 and htlc6 are dust IN/OUT htlcs
|
||||
val htlc5 = UpdateAddHtlc(ByteVector32.Zeroes, 4, (localDustLimit * 0.9).toMilliSatoshi, sha256(randomBytes32()), CltvExpiry(295), TestConstants.emptyOnionPacket, None)
|
||||
val htlc6 = UpdateAddHtlc(ByteVector32.Zeroes, 5, (localDustLimit * 0.9).toMilliSatoshi, sha256(randomBytes32()), CltvExpiry(305), TestConstants.emptyOnionPacket, None)
|
||||
val htlc5 = UpdateAddHtlc(ByteVector32.Zeroes, 4, (localDustLimit * 0.9).toMilliSatoshi, sha256(randomBytes32()), CltvExpiry(295), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val htlc6 = UpdateAddHtlc(ByteVector32.Zeroes, 5, (localDustLimit * 0.9).toMilliSatoshi, sha256(randomBytes32()), CltvExpiry(305), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val spec = CommitmentSpec(
|
||||
htlcs = Set(
|
||||
OutgoingHtlc(htlc1),
|
||||
|
@ -492,21 +492,21 @@ class TransactionsSpec extends AnyFunSuite with Logging {
|
|||
|
||||
// htlc1, htlc2a and htlc2b are regular IN/OUT htlcs
|
||||
val paymentPreimage1 = randomBytes32()
|
||||
val htlc1 = UpdateAddHtlc(ByteVector32.Zeroes, 0, MilliBtc(100).toMilliSatoshi, sha256(paymentPreimage1), CltvExpiry(300), TestConstants.emptyOnionPacket, None)
|
||||
val htlc1 = UpdateAddHtlc(ByteVector32.Zeroes, 0, MilliBtc(100).toMilliSatoshi, sha256(paymentPreimage1), CltvExpiry(300), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val paymentPreimage2 = randomBytes32()
|
||||
val htlc2a = UpdateAddHtlc(ByteVector32.Zeroes, 1, MilliBtc(50).toMilliSatoshi, sha256(paymentPreimage2), CltvExpiry(310), TestConstants.emptyOnionPacket, None)
|
||||
val htlc2b = UpdateAddHtlc(ByteVector32.Zeroes, 2, MilliBtc(150).toMilliSatoshi, sha256(paymentPreimage2), CltvExpiry(310), TestConstants.emptyOnionPacket, None)
|
||||
val htlc2a = UpdateAddHtlc(ByteVector32.Zeroes, 1, MilliBtc(50).toMilliSatoshi, sha256(paymentPreimage2), CltvExpiry(310), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val htlc2b = UpdateAddHtlc(ByteVector32.Zeroes, 2, MilliBtc(150).toMilliSatoshi, sha256(paymentPreimage2), CltvExpiry(310), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
// htlc3 and htlc4 are dust IN/OUT htlcs, with an amount large enough to be included in the commit tx, but too small to be claimed at 2nd stage
|
||||
val paymentPreimage3 = randomBytes32()
|
||||
val htlc3 = UpdateAddHtlc(ByteVector32.Zeroes, 3, (localDustLimit + weight2fee(feeratePerKw, UnsafeLegacyAnchorOutputsCommitmentFormat.htlcTimeoutWeight)).toMilliSatoshi, sha256(paymentPreimage3), CltvExpiry(295), TestConstants.emptyOnionPacket, None)
|
||||
val htlc3 = UpdateAddHtlc(ByteVector32.Zeroes, 3, (localDustLimit + weight2fee(feeratePerKw, UnsafeLegacyAnchorOutputsCommitmentFormat.htlcTimeoutWeight)).toMilliSatoshi, sha256(paymentPreimage3), CltvExpiry(295), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val paymentPreimage4 = randomBytes32()
|
||||
val htlc4 = UpdateAddHtlc(ByteVector32.Zeroes, 4, (localDustLimit + weight2fee(feeratePerKw, UnsafeLegacyAnchorOutputsCommitmentFormat.htlcSuccessWeight)).toMilliSatoshi, sha256(paymentPreimage4), CltvExpiry(300), TestConstants.emptyOnionPacket, None)
|
||||
val htlc4 = UpdateAddHtlc(ByteVector32.Zeroes, 4, (localDustLimit + weight2fee(feeratePerKw, UnsafeLegacyAnchorOutputsCommitmentFormat.htlcSuccessWeight)).toMilliSatoshi, sha256(paymentPreimage4), CltvExpiry(300), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
// htlc5 and htlc6 are dust IN/OUT htlcs
|
||||
val htlc5 = UpdateAddHtlc(ByteVector32.Zeroes, 5, (localDustLimit * 0.9).toMilliSatoshi, sha256(randomBytes32()), CltvExpiry(295), TestConstants.emptyOnionPacket, None)
|
||||
val htlc6 = UpdateAddHtlc(ByteVector32.Zeroes, 6, (localDustLimit * 0.9).toMilliSatoshi, sha256(randomBytes32()), CltvExpiry(305), TestConstants.emptyOnionPacket, None)
|
||||
val htlc5 = UpdateAddHtlc(ByteVector32.Zeroes, 5, (localDustLimit * 0.9).toMilliSatoshi, sha256(randomBytes32()), CltvExpiry(295), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val htlc6 = UpdateAddHtlc(ByteVector32.Zeroes, 6, (localDustLimit * 0.9).toMilliSatoshi, sha256(randomBytes32()), CltvExpiry(305), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
// htlc7 and htlc8 are at the dust limit when we ignore 2nd-stage tx fees
|
||||
val htlc7 = UpdateAddHtlc(ByteVector32.Zeroes, 7, localDustLimit.toMilliSatoshi, sha256(randomBytes32()), CltvExpiry(300), TestConstants.emptyOnionPacket, None)
|
||||
val htlc8 = UpdateAddHtlc(ByteVector32.Zeroes, 8, localDustLimit.toMilliSatoshi, sha256(randomBytes32()), CltvExpiry(302), TestConstants.emptyOnionPacket, None)
|
||||
val htlc7 = UpdateAddHtlc(ByteVector32.Zeroes, 7, localDustLimit.toMilliSatoshi, sha256(randomBytes32()), CltvExpiry(300), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val htlc8 = UpdateAddHtlc(ByteVector32.Zeroes, 8, localDustLimit.toMilliSatoshi, sha256(randomBytes32()), CltvExpiry(302), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val spec = CommitmentSpec(
|
||||
htlcs = Set(
|
||||
OutgoingHtlc(htlc1),
|
||||
|
@ -760,11 +760,11 @@ class TransactionsSpec extends AnyFunSuite with Logging {
|
|||
val paymentPreimage1 = ByteVector32(hex"1111111111111111111111111111111111111111111111111111111111111111")
|
||||
val paymentPreimage2 = ByteVector32(hex"2222222222222222222222222222222222222222222222222222222222222222")
|
||||
val paymentPreimage3 = ByteVector32(hex"3333333333333333333333333333333333333333333333333333333333333333")
|
||||
val htlc1 = UpdateAddHtlc(randomBytes32(), 1, millibtc2satoshi(MilliBtc(100)).toMilliSatoshi, sha256(paymentPreimage1), CltvExpiry(300), TestConstants.emptyOnionPacket, None)
|
||||
val htlc2 = UpdateAddHtlc(randomBytes32(), 2, millibtc2satoshi(MilliBtc(200)).toMilliSatoshi, sha256(paymentPreimage2), CltvExpiry(300), TestConstants.emptyOnionPacket, None)
|
||||
val htlc3 = UpdateAddHtlc(randomBytes32(), 3, millibtc2satoshi(MilliBtc(200)).toMilliSatoshi, sha256(paymentPreimage3), CltvExpiry(300), TestConstants.emptyOnionPacket, None)
|
||||
val htlc4 = UpdateAddHtlc(randomBytes32(), 4, millibtc2satoshi(MilliBtc(200)).toMilliSatoshi, sha256(paymentPreimage3), CltvExpiry(300), TestConstants.emptyOnionPacket, None)
|
||||
val htlc5 = UpdateAddHtlc(randomBytes32(), 5, millibtc2satoshi(MilliBtc(200)).toMilliSatoshi, sha256(paymentPreimage3), CltvExpiry(301), TestConstants.emptyOnionPacket, None)
|
||||
val htlc1 = UpdateAddHtlc(randomBytes32(), 1, millibtc2satoshi(MilliBtc(100)).toMilliSatoshi, sha256(paymentPreimage1), CltvExpiry(300), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val htlc2 = UpdateAddHtlc(randomBytes32(), 2, millibtc2satoshi(MilliBtc(200)).toMilliSatoshi, sha256(paymentPreimage2), CltvExpiry(300), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val htlc3 = UpdateAddHtlc(randomBytes32(), 3, millibtc2satoshi(MilliBtc(200)).toMilliSatoshi, sha256(paymentPreimage3), CltvExpiry(300), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val htlc4 = UpdateAddHtlc(randomBytes32(), 4, millibtc2satoshi(MilliBtc(200)).toMilliSatoshi, sha256(paymentPreimage3), CltvExpiry(300), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val htlc5 = UpdateAddHtlc(randomBytes32(), 5, millibtc2satoshi(MilliBtc(200)).toMilliSatoshi, sha256(paymentPreimage3), CltvExpiry(301), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
|
||||
val spec = CommitmentSpec(
|
||||
htlcs = Set(
|
||||
|
@ -877,9 +877,9 @@ class TransactionsSpec extends AnyFunSuite with Logging {
|
|||
formatted
|
||||
}
|
||||
|
||||
def htlcIn(amount: Satoshi): DirectedHtlc = IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, amount.toMilliSatoshi, ByteVector32.Zeroes, CltvExpiry(144), TestConstants.emptyOnionPacket, None))
|
||||
def htlcIn(amount: Satoshi): DirectedHtlc = IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, amount.toMilliSatoshi, ByteVector32.Zeroes, CltvExpiry(144), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
|
||||
def htlcOut(amount: Satoshi): DirectedHtlc = OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, amount.toMilliSatoshi, ByteVector32.Zeroes, CltvExpiry(144), TestConstants.emptyOnionPacket, None))
|
||||
def htlcOut(amount: Satoshi): DirectedHtlc = OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, amount.toMilliSatoshi, ByteVector32.Zeroes, CltvExpiry(144), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
|
||||
case class TestVector(name: String, spec: CommitmentSpec, expectedFee: Satoshi)
|
||||
|
||||
|
|
|
@ -291,11 +291,11 @@ object ChannelCodecsSpec {
|
|||
)
|
||||
|
||||
val htlcs: Seq[DirectedHtlc] = Seq[DirectedHtlc](
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 1000000 msat, Crypto.sha256(paymentPreimages(0)), CltvExpiry(500), TestConstants.emptyOnionPacket, None)),
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 1, 2000000 msat, Crypto.sha256(paymentPreimages(1)), CltvExpiry(501), TestConstants.emptyOnionPacket, None)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 30, 2000000 msat, Crypto.sha256(paymentPreimages(2)), CltvExpiry(502), TestConstants.emptyOnionPacket, None)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 31, 3000000 msat, Crypto.sha256(paymentPreimages(3)), CltvExpiry(503), TestConstants.emptyOnionPacket, None)),
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 2, 4000000 msat, Crypto.sha256(paymentPreimages(4)), CltvExpiry(504), TestConstants.emptyOnionPacket, None))
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 0, 1000000 msat, Crypto.sha256(paymentPreimages(0)), CltvExpiry(500), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 1, 2000000 msat, Crypto.sha256(paymentPreimages(1)), CltvExpiry(501), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 30, 2000000 msat, Crypto.sha256(paymentPreimages(2)), CltvExpiry(502), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
OutgoingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 31, 3000000 msat, Crypto.sha256(paymentPreimages(3)), CltvExpiry(503), TestConstants.emptyOnionPacket, None, 1.0)),
|
||||
IncomingHtlc(UpdateAddHtlc(ByteVector32.Zeroes, 2, 4000000 msat, Crypto.sha256(paymentPreimages(4)), CltvExpiry(504), TestConstants.emptyOnionPacket, None, 1.0))
|
||||
)
|
||||
|
||||
val normal: DATA_NORMAL = {
|
||||
|
|
|
@ -4,7 +4,7 @@ import fr.acinq.bitcoin.scalacompat.ByteVector32
|
|||
import fr.acinq.eclair.transactions.{IncomingHtlc, OutgoingHtlc}
|
||||
import fr.acinq.eclair.wire.internal.channel.version0.ChannelCodecs0.Codecs._
|
||||
import fr.acinq.eclair.wire.internal.channel.version0.ChannelTypes0.ChannelVersion
|
||||
import fr.acinq.eclair.wire.protocol.{OnionRoutingPacket, UpdateAddHtlc}
|
||||
import fr.acinq.eclair.wire.protocol.{OnionRoutingPacket, TlvStream, UpdateAddHtlc}
|
||||
import fr.acinq.eclair.{CltvExpiry, MilliSatoshiLong}
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
import scodec.bits._
|
||||
|
@ -58,7 +58,6 @@ class ChannelCodecs0Spec extends AnyFunSuite {
|
|||
hex"1e3a0e7c55b9f74b209e3704695e38874dd0950c54089a2be675bbf1a83679f6ff",
|
||||
hex"2db02ba44906455d5ba19cf75979889cc23ecd86b88728478133ccf180ee407abf882bd86f6f318d8e993dda100dcd9641e56c270aaee5810d9dcc0c85677387232c4f90ef4c54afb9ed9c0077db8a7516f41af552364609df16a25fc3534087c821af9a6013dbff96ba980b9f6a8b59da95fd5177c4d8bfe924c05dbf3a9d6e62a83cc1c91fa35cbc676094c2868df62dc1399b3797120ffd3f850eeafd525014068c4533d2a144e983b8a7f75d18843ccfafbc6ae13db41e2379a82f81e42accfd171995c206ba05024295e4b7ed202056301cba96ae647a0556b9dcba6cd368600a73a05dfeaa6287e10b9ae1ca8516f5e64c483154ecc9aad87fa5380145f114d4bdd2d0be8b6c30588ba925642e16125c96b12248f79ffd04c4770cc6f7d85239943b8e53eae8fb085d9be5f849d5f2b8a4597d7d35083cf9ff06fce2b6d13e166cd725450a10eac6d2c574850c756dbe25dd2715b4dcd5cf2bf169f7d035bd48f19553133fda1ad99bef442e76d365a7fe372790581189b4c7684da5f2922421332fd1dcb0618bffc76c192e8715c2a43452adce7534c1e2db8274bccacb209c097ecd9db47b6d27f8f418d5a9efb9196fe3dea8a4f822b136f86b9cb641cfe47415620f480df4e8e86bfe1012d4ea675156feba6c61ab841922c2203f2458ec0f292fc01c794c579c06765760cbd42e678a16b40c925a568ce2b024007e5350ea96bb82c92105127cf7cecaa18b1b31d02aadc9bbe414489e6c77847cead92a44866ba1dd99a7b40d522c3898e55c7b275fd205500dd5ba42cfa2b8099e6051f8c3a10877a4e1fae05458b5f11356b78f3452908f229f1ba81353732152c72fb208d870b953021f6f8f658c29238ce4c84af4c037cffd188f50b36ad5e8395e0d7cfd439b6a80e33f87784c06ceb6f3fa6d4de52220876f1b53e30da5403e2413a1b22a11d1d7d99c13fae5047a182cca85eda0b3f50e4bb3ae3344a64513911ef45234d77c03eb63f07984465ae2defbf8d4207f70c6faeb35572735544f19ffc094c9e8284ac82261004ed7dcfa7d8c5c7f10f071c7043e1bae2666f2e5bf3282c1db853997372c6188353d8f932997de4a034c21c386d09cd2fbe461fadede20a4d9288dd060f43f6fc93119beff9154659141240c227b048f555c85c728581ffa523acf06fa591046390b104cceb05d943a4acc26989dc2603bd1c2c6fe128cf68e7747c6a73249100917a6964db98dede8e8ea36f58b775a8d18c9db455d57fcd5242a149f556284453af2698944884e8830a1a1bd5cbb700560528086be739d550bc5a7a44d2a21103564d24d862ce90f54271a71739eca1eb3e154170852e8f24e3840139bcc3cb8b184d7f142b5750d0d35f07283d8292e5b276d5c94dd9ecb084702a14c290fad7a729b681421ae21fa5a0cb0a1ca5d4ca6d4e9b1128e890443839c927fd97e40e1331c09aa4c726a9118526be5a75fda9a1f8e8e5807cca5f251cd431ef0052087e433eca5b325c208a5229352f1cb8cc180103fcd42f3b7cc5b96b2fe769c92f8c093604abf1e60dc963192f86739304e157f0d49d635f27629b101ddb440776774b6dc6227a1c007f1cabe7a88d7a9b9b4d0d66af9415be3fc4a720ecf481fe10d524b1a09833608e8911555f58643e10fa57a1b81c0ad5b3eb6b5f4be7b05787e31667bd2088a52c6ffda0b0f3ed7a881e66380c011ba7185f7045845f88403d2ff3df3f86a300f808bbd9c28fa33fa034d0c098796d6bc1b6369a3d7c70ece00420cfb2840df7b93da67583e93b0ff2c396ba89e9100bcabf0c6f947bc9d93bb2d3289",
|
||||
ByteVector32(hex"dac3bc8b2e16fdf2db3e627483bc395c701c1fc96ace53e4ebc54150e807921d")),
|
||||
None
|
||||
)
|
||||
val remaining = bin"0000000" // 7 bits remainder because the direction is encoded with 1 bit and we are dealing with bytes
|
||||
|
||||
|
|
|
@ -75,7 +75,8 @@ class ChannelCodecs1Spec extends AnyFunSuite {
|
|||
cltvExpiry = CltvExpiry(Random.nextInt(Int.MaxValue)),
|
||||
paymentHash = randomBytes32(),
|
||||
onionRoutingPacket = TestConstants.emptyOnionPacket,
|
||||
blinding_opt = None)
|
||||
blinding_opt = None,
|
||||
confidence = 1.0)
|
||||
val htlc1 = IncomingHtlc(add)
|
||||
val htlc2 = OutgoingHtlc(add)
|
||||
assert(htlcCodec.decodeValue(htlcCodec.encode(htlc1).require).require == htlc1)
|
||||
|
@ -90,7 +91,8 @@ class ChannelCodecs1Spec extends AnyFunSuite {
|
|||
cltvExpiry = CltvExpiry(Random.nextInt(Int.MaxValue)),
|
||||
paymentHash = randomBytes32(),
|
||||
onionRoutingPacket = TestConstants.emptyOnionPacket,
|
||||
blinding_opt = None)
|
||||
blinding_opt = None,
|
||||
confidence = 1.0)
|
||||
val add2 = UpdateAddHtlc(
|
||||
channelId = randomBytes32(),
|
||||
id = Random.nextInt(Int.MaxValue),
|
||||
|
@ -98,7 +100,8 @@ class ChannelCodecs1Spec extends AnyFunSuite {
|
|||
cltvExpiry = CltvExpiry(Random.nextInt(Int.MaxValue)),
|
||||
paymentHash = randomBytes32(),
|
||||
onionRoutingPacket = TestConstants.emptyOnionPacket,
|
||||
blinding_opt = None)
|
||||
blinding_opt = None,
|
||||
confidence = 1.0)
|
||||
val htlc1 = IncomingHtlc(add1)
|
||||
val htlc2 = OutgoingHtlc(add2)
|
||||
val htlcs = Set[DirectedHtlc](htlc1, htlc2)
|
||||
|
@ -122,16 +125,16 @@ class ChannelCodecs1Spec extends AnyFunSuite {
|
|||
assert(originCodec.decodeValue(originCodec.encode(localHot).require).require == localCold)
|
||||
assert(originCodec.decodeValue(originCodec.encode(localCold).require).require == localCold)
|
||||
|
||||
val add = UpdateAddHtlc(randomBytes32(), 4324, 11000000 msat, randomBytes32(), CltvExpiry(400000), TestConstants.emptyOnionPacket, None)
|
||||
val add = UpdateAddHtlc(randomBytes32(), 4324, 11000000 msat, randomBytes32(), CltvExpiry(400000), TestConstants.emptyOnionPacket, None, 1.0)
|
||||
val relayedHot = Origin.Hot(replyTo, Upstream.Hot.Channel(add, TimestampMilli(0), randomKey().publicKey))
|
||||
val relayedCold = Origin.Cold(Upstream.Cold.Channel(add.channelId, add.id, add.amountMsat))
|
||||
assert(originCodec.decodeValue(originCodec.encode(relayedHot).require).require == relayedCold)
|
||||
assert(originCodec.decodeValue(originCodec.encode(relayedCold).require).require == relayedCold)
|
||||
|
||||
val adds = Seq(
|
||||
UpdateAddHtlc(randomBytes32(), 1L, 1000 msat, randomBytes32(), CltvExpiry(400000), TestConstants.emptyOnionPacket, None),
|
||||
UpdateAddHtlc(randomBytes32(), 1L, 2000 msat, randomBytes32(), CltvExpiry(400000), TestConstants.emptyOnionPacket, None),
|
||||
UpdateAddHtlc(randomBytes32(), 2L, 3000 msat, randomBytes32(), CltvExpiry(400000), TestConstants.emptyOnionPacket, None),
|
||||
UpdateAddHtlc(randomBytes32(), 1L, 1000 msat, randomBytes32(), CltvExpiry(400000), TestConstants.emptyOnionPacket, None, 1.0),
|
||||
UpdateAddHtlc(randomBytes32(), 1L, 2000 msat, randomBytes32(), CltvExpiry(400000), TestConstants.emptyOnionPacket, None, 1.0),
|
||||
UpdateAddHtlc(randomBytes32(), 2L, 3000 msat, randomBytes32(), CltvExpiry(400000), TestConstants.emptyOnionPacket, None, 1.0),
|
||||
)
|
||||
val trampolineRelayedHot = Origin.Hot(replyTo, Upstream.Hot.Trampoline(adds.map(add => Upstream.Hot.Channel(add, TimestampMilli(0), randomKey().publicKey))))
|
||||
// We didn't encode the incoming HTLC amount.
|
||||
|
|
|
@ -391,7 +391,7 @@ class LightningMessageCodecsSpec extends AnyFunSuite {
|
|||
UpdateFee(randomBytes32(), FeeratePerKw(2 sat)),
|
||||
Shutdown(randomBytes32(), bin(47, 0)),
|
||||
ClosingSigned(randomBytes32(), 2 sat, randomBytes64()),
|
||||
UpdateAddHtlc(randomBytes32(), 2, 3 msat, bin32(0), CltvExpiry(4), TestConstants.emptyOnionPacket, None),
|
||||
UpdateAddHtlc(randomBytes32(), 2, 3 msat, bin32(0), CltvExpiry(4), TestConstants.emptyOnionPacket, None, 1.0),
|
||||
UpdateFulfillHtlc(randomBytes32(), 2, bin32(0)),
|
||||
UpdateFailHtlc(randomBytes32(), 2, bin(154, 0)),
|
||||
UpdateFailMalformedHtlc(randomBytes32(), 2, randomBytes32(), 1111),
|
||||
|
@ -556,4 +556,24 @@ class LightningMessageCodecsSpec extends AnyFunSuite {
|
|||
}
|
||||
}
|
||||
|
||||
test("encode/decode UpdateAddHtlc") {
|
||||
val testCases = Map(
|
||||
hex"2e184fc141277ba9a3fbe752206f5714c3cfe50765c258dfbdb10cead1ef57f9 0000000000000001 000000000000b5bb 05fc4f9f94ecb97574a90c9154740a3a6c16195d6d0136b71d60d9dae33ce999 000d5fff 00 02c606691a88f80fdc10d007ef5dfa0b91ce33b7b3fa40a6df84f7285aaf37174e 708636c4c5bab2c45e0e9b94f48791e468a9e54af63ee9dfd09d947d6a845b03133eb69226293754caf18b41b99c66830e327938b2fe44e54e31cd8a2c0ee1c43c6c50a8d29bd3f27eb88f70d6ecd7f1b2afb7d721dbad9ac34a511c5e49e5c44e0beb5e513b930fea34eb3ce22e5cebc55c85efa2b24a698ee4f45207977693cebc59f3cad9088387ea89ae45cbb9700bb3e0d93b82d10ea994979a90f4d6265312ae370c80a0c323f5abaa8dcc09aa637b85f2b40d7324885fc744719ec966154c2cd4a512abc618232b82855261886937af9f92d308eba5a5b03e99f4e96535a7e4aeb29c4a260938b85bc16218eb0fe2c765519dd811e0e633bb6e26004393db285ffd04bf6be33ec410bcad437d515484e910960b3d2b1f719963c215c26a0f29b86dfde41c098780d5aaf9b48c95f7e3d6582955feee058e5d0f87671202caf4899a2f5f238f4938b20d14f3d1e94893666e9c36f9c559f05f065ec547f417b58b81d7f5e71563f0565c30f82e9e8e4755f74b8633fb5c7645a551ebf27b9535aa1bde6f12df2b85cc30b9083d602f7eea0e9093f86aa2346e8900851e884470026f6f46e9748322c786145cd0cc8a0d712aef89466a06e5c2795cf5d326f78a5af746f61f4df3b08f17104b1ce3099a20fab9b2751b3635aec743a986173861d790c31942bd608258a927d75309c15ffd690a0713179d62a60b459be7486d03b774119d12168a9d0761134d789264662ed1e21329c840aa6f958cd0bfddd8cbeb61ac9fb5f379ee8557e3962f85871928d2fae5d9f1026eb95248f38689f44597d1b316a1860597abb77e08fa58778f39fbb13f38c727cdabf58592f3932a272195dde4ccd62d57239cb82d274ed239f39132cf83fa4629435af985ef24a8aecc4e8837ce53658cdbe97951b83f5f3643525f19f3e46312285684631b93e12e47b6922855cdf81ef5459bc26667a17459c537fbc169485bc23daa9c573a86010b9627864842eb3fb01afd90b288e86050c87e5f1e8d49fd6fae7c5c5256d27471baf29017e092b4c5a96f063a8c56ccf90838e2da89f42a9d4af35236e3f12b3253f6981e5db1a4cf453622fcc2e11b51afd2a88b09ed13905bbaeef91b9b80523e13fe6b8c2386f6c83c3cad5de89405e2da894bf30733846266904be964ac8d67e8eff54b9ee3f8e6c88797fdaf9832a2693e7d0b6471bbc234fd72c1f02a8e48f3fb43cf0609802d129e6b46ad542dac1feee2128cf2688a354dacddd0a50ec88b517e9f315c7df81d5002f2809b4009b0ed55b2d960f0390eec4c1824afe013332aa6d0e1f0d65877485471918e7667addd27e592731011e813a5085035f1dc11b4d7dac122f05a033b702d91708e0c708337b3be0fa8463cce23e52f667520908dc5e8a94ff051ffaf50fec11b8a3f880e4d0ededd7b0a6c71f6e939553402eb2ea370334776336e726880a184d7dcfd7c84d12c8feb31a479259f2c6520c5432cf71babc522b7f090cc527df41b1c7d8e3b5e2c1f5a8d4a3e1da578921321e472be5f6f5076be9e9d2255a46e072e19771c461973c44bb47e154e85bb76f0f1152e9bb1209c1707b0f42e6507cd9e4f026156a788ef65b221f0c864efc334132624ba1b96a1ecd7c7d460acb7c1d7b408395410b189c4ae374d143c96c48392abceee4366903a05d9ba884496bbff603b65967fd5a434530fe5accd48f40f00f1a5347f1602dd4abe545e5826f24344bbe88cd3b2ffd1320fb40407ec175f8c17c16a52ade59383357e52eff8b8d5c318172b703c69c4a04786088ee63f2fc9cea63294a33546ea1a954ae9a79c 47de7249c4b76e4db71df5d070dab15ea294f22011fc21a544c26416aaff2682 00 21 0396b9c21b054a49f35ee7abb96e677ebbcaae876d602349cd58b3854380782818 fe0001a147 01 05" ->
|
||||
UpdateAddHtlc(ByteVector32(hex"2e184fc141277ba9a3fbe752206f5714c3cfe50765c258dfbdb10cead1ef57f9"), 1, 46523 msat, ByteVector32(hex"05fc4f9f94ecb97574a90c9154740a3a6c16195d6d0136b71d60d9dae33ce999"), CltvExpiry(876543), OnionRoutingPacket(0, hex"02c606691a88f80fdc10d007ef5dfa0b91ce33b7b3fa40a6df84f7285aaf37174e", payload = hex"708636c4c5bab2c45e0e9b94f48791e468a9e54af63ee9dfd09d947d6a845b03133eb69226293754caf18b41b99c66830e327938b2fe44e54e31cd8a2c0ee1c43c6c50a8d29bd3f27eb88f70d6ecd7f1b2afb7d721dbad9ac34a511c5e49e5c44e0beb5e513b930fea34eb3ce22e5cebc55c85efa2b24a698ee4f45207977693cebc59f3cad9088387ea89ae45cbb9700bb3e0d93b82d10ea994979a90f4d6265312ae370c80a0c323f5abaa8dcc09aa637b85f2b40d7324885fc744719ec966154c2cd4a512abc618232b82855261886937af9f92d308eba5a5b03e99f4e96535a7e4aeb29c4a260938b85bc16218eb0fe2c765519dd811e0e633bb6e26004393db285ffd04bf6be33ec410bcad437d515484e910960b3d2b1f719963c215c26a0f29b86dfde41c098780d5aaf9b48c95f7e3d6582955feee058e5d0f87671202caf4899a2f5f238f4938b20d14f3d1e94893666e9c36f9c559f05f065ec547f417b58b81d7f5e71563f0565c30f82e9e8e4755f74b8633fb5c7645a551ebf27b9535aa1bde6f12df2b85cc30b9083d602f7eea0e9093f86aa2346e8900851e884470026f6f46e9748322c786145cd0cc8a0d712aef89466a06e5c2795cf5d326f78a5af746f61f4df3b08f17104b1ce3099a20fab9b2751b3635aec743a986173861d790c31942bd608258a927d75309c15ffd690a0713179d62a60b459be7486d03b774119d12168a9d0761134d789264662ed1e21329c840aa6f958cd0bfddd8cbeb61ac9fb5f379ee8557e3962f85871928d2fae5d9f1026eb95248f38689f44597d1b316a1860597abb77e08fa58778f39fbb13f38c727cdabf58592f3932a272195dde4ccd62d57239cb82d274ed239f39132cf83fa4629435af985ef24a8aecc4e8837ce53658cdbe97951b83f5f3643525f19f3e46312285684631b93e12e47b6922855cdf81ef5459bc26667a17459c537fbc169485bc23daa9c573a86010b9627864842eb3fb01afd90b288e86050c87e5f1e8d49fd6fae7c5c5256d27471baf29017e092b4c5a96f063a8c56ccf90838e2da89f42a9d4af35236e3f12b3253f6981e5db1a4cf453622fcc2e11b51afd2a88b09ed13905bbaeef91b9b80523e13fe6b8c2386f6c83c3cad5de89405e2da894bf30733846266904be964ac8d67e8eff54b9ee3f8e6c88797fdaf9832a2693e7d0b6471bbc234fd72c1f02a8e48f3fb43cf0609802d129e6b46ad542dac1feee2128cf2688a354dacddd0a50ec88b517e9f315c7df81d5002f2809b4009b0ed55b2d960f0390eec4c1824afe013332aa6d0e1f0d65877485471918e7667addd27e592731011e813a5085035f1dc11b4d7dac122f05a033b702d91708e0c708337b3be0fa8463cce23e52f667520908dc5e8a94ff051ffaf50fec11b8a3f880e4d0ededd7b0a6c71f6e939553402eb2ea370334776336e726880a184d7dcfd7c84d12c8feb31a479259f2c6520c5432cf71babc522b7f090cc527df41b1c7d8e3b5e2c1f5a8d4a3e1da578921321e472be5f6f5076be9e9d2255a46e072e19771c461973c44bb47e154e85bb76f0f1152e9bb1209c1707b0f42e6507cd9e4f026156a788ef65b221f0c864efc334132624ba1b96a1ecd7c7d460acb7c1d7b408395410b189c4ae374d143c96c48392abceee4366903a05d9ba884496bbff603b65967fd5a434530fe5accd48f40f00f1a5347f1602dd4abe545e5826f24344bbe88cd3b2ffd1320fb40407ec175f8c17c16a52ade59383357e52eff8b8d5c318172b703c69c4a04786088ee63f2fc9cea63294a33546ea1a954ae9a79c", ByteVector32(hex"47de7249c4b76e4db71df5d070dab15ea294f22011fc21a544c26416aaff2682")), TlvStream(UpdateAddHtlcTlv.BlindingPoint(PublicKey(hex"0396b9c21b054a49f35ee7abb96e677ebbcaae876d602349cd58b3854380782818")), UpdateAddHtlcTlv.Endorsement(5))),
|
||||
hex"f865a44f81f02f3539842b863668403a68ddb3703e03cd91045c9ac114dbd28e 0000000000000002 0000000000000092 d3708298fd195572cceb86a1745210543c42f931a1a2baeed7f705d333ebed22 00013368 00 037cb785d5a9de762adc62e3f2407d452bd1f13d368d0429caee5541a89488e3b9 5b90dd3803ff56400a40dc539efa0a0e29736c76e83d2d8b44775adcb4d485be5eb84eefbfedc69b687ee5c7080f83ff31760ec036990d904de480064966bba393af729d57437c91bea905a66464461a6462c5a0c66976ecaeded73d330dfaeb5651ba68e74b210c123e63ac6ee15d6673cf126f046840bbf4364c907f56382870da85101045fc9392357b0b32081cde0e28460d20c1d5d61a5d56fe50d107304e4b184dd005048f9bcd159eff3cfaaef4ab5a8f29d38de109ea41a7ceaa886a0559a4fd0c7448cf28db85c3758fbde23443776e08dd29c435b1195f205aa787f2ec4a7259afeff078faa419c9af5706b9c08e7ce5772326e09df22eb85b0abc625b969aae34a881c12bd9653a08dc62b8e82cf89d0d66974f96149c6dcd7fc4363eecbf4fdac39e500c416b8d6a2e5871d80775acd1c13df4e4ad30a150390d500869ee6a4eab1c4285952d0549c45960a0b1b5ccfb93c75b63923fbc02b1d5a91e53f7424478cc58bf4366a612d40deec5efea700a7b127f7fdded1c4232e5b2eb7190f964e20b156e62d63d097005a24d96457a3db387a6b25e2a65fb169de0323a48f275780dc320d1c7d22642d3371e65559bf5510a3990b67aceb87daccd40e7f82fbba5a0065a63849dbb6600b420e8cb3561154dc69a3b063784737a7eb9d3f770fa1312c03e8518200cefc1be356bf0b0d1928816e712d24b5021b72f20d84a062a47ef50acf5cc9de025378611fbd7fd6473bc0258aa1697b057f6ce4c99f7a6ade34411a008aaccb3e3b2f78e2bc0720c3050960ad8b2988907a410a8fe565b671d3f2a274b9ed230786da769ebc73e9212b41902bec589d602dc941a6dc8a3c37ede467fdb21101cc8befe111b8a365b94612be8eef16a14dc1f163647744c2d0eabc17dc0bd297ba2e9237fea5d8c845e11ae207c4ce8d5d17b2dffdb6ba20c0474ab9e8547b90bdf61d41602b64b84b3d725279e818dccb82f25c6a75dc473af074c97bd6ea775eb575dd07bd2574dfe308748ecc0d39df14659e1958dbc0413fa7f214b6ffb4059b0ef21e9c2602723695988382201c36dfb9bb5916246f0ecad281b1431846e43b5651a85745a4b81586282285f56625fdb8f46a7b752f1a81159f04c12ec20723c22ae2dadd384bcedecc16de9ae253081ec8b5616b94ec716eb2e91c6af58eddcb360841ec942782fe7b44e9ea191e98007faa5722f12b5e0ff23304297f3aeb369a3ff79434f2ff2e7575bd7e7a1d2592043ea245ca0f69cc0c781b42258230b45391d1c1545ed0a9dcdbedc454c6e7dd313b2e6e757f91309d8fa7801bba864f60f04a1b12e0770e4aa62b7d388f8a0b85d38defa8a21a7764388dd7273b941a17f1f1b1a7acefc8f1726a7cb4ea3f19ddb7a70082c1c5cb6921d4c0eea07cf4d226c98ed1c57a92652b2687181da8091db3ac77bbf5634c351990296494868dd1e365af320c88148a0ed887a06f4be3256cf4556f00ce3376a7016ffddc26f36272d48fc5500451a2ea6de5f6778948e9ba856db5a38129ad1367b983d1f2b624ac5e2e35ce9145eee563d047c853a30c6cabb8064ea183dba622adebae8d2149b93752776e55155319009f2f9a3c1aec9a2b266fdb0451c97fbcc8ca7c1adff0806adc1dc8105b678a30af95cfc5f370dd0e4a6db9811b2deac2ed1fc8716b0571210ee7208316f24dc2af7394519401173d36c3f25fbe4ebd965aa19f53e6fef550ab72216dcfd20ac974b40b456ce143bd4e495dd51fd58e23877ac91e28abed7e9a12c7fbf694e5b5cf144f011da4aca445cf5546d68b2341401460bf2d717663c 022406339068be457a4430d0de697ee810f0911afc344bd3d4d662771874d2ce 00 21 02039885cd5b9ffd24b5ce83f464a7d4c0e3f23c1a8061c9fc85730db67ffdbd0c fe0001a147 01 00" ->
|
||||
UpdateAddHtlc(ByteVector32(hex"f865a44f81f02f3539842b863668403a68ddb3703e03cd91045c9ac114dbd28e"), 2, 146 msat, ByteVector32(hex"d3708298fd195572cceb86a1745210543c42f931a1a2baeed7f705d333ebed22"), CltvExpiry(78696), OnionRoutingPacket(0, hex"037cb785d5a9de762adc62e3f2407d452bd1f13d368d0429caee5541a89488e3b9", payload = hex"5b90dd3803ff56400a40dc539efa0a0e29736c76e83d2d8b44775adcb4d485be5eb84eefbfedc69b687ee5c7080f83ff31760ec036990d904de480064966bba393af729d57437c91bea905a66464461a6462c5a0c66976ecaeded73d330dfaeb5651ba68e74b210c123e63ac6ee15d6673cf126f046840bbf4364c907f56382870da85101045fc9392357b0b32081cde0e28460d20c1d5d61a5d56fe50d107304e4b184dd005048f9bcd159eff3cfaaef4ab5a8f29d38de109ea41a7ceaa886a0559a4fd0c7448cf28db85c3758fbde23443776e08dd29c435b1195f205aa787f2ec4a7259afeff078faa419c9af5706b9c08e7ce5772326e09df22eb85b0abc625b969aae34a881c12bd9653a08dc62b8e82cf89d0d66974f96149c6dcd7fc4363eecbf4fdac39e500c416b8d6a2e5871d80775acd1c13df4e4ad30a150390d500869ee6a4eab1c4285952d0549c45960a0b1b5ccfb93c75b63923fbc02b1d5a91e53f7424478cc58bf4366a612d40deec5efea700a7b127f7fdded1c4232e5b2eb7190f964e20b156e62d63d097005a24d96457a3db387a6b25e2a65fb169de0323a48f275780dc320d1c7d22642d3371e65559bf5510a3990b67aceb87daccd40e7f82fbba5a0065a63849dbb6600b420e8cb3561154dc69a3b063784737a7eb9d3f770fa1312c03e8518200cefc1be356bf0b0d1928816e712d24b5021b72f20d84a062a47ef50acf5cc9de025378611fbd7fd6473bc0258aa1697b057f6ce4c99f7a6ade34411a008aaccb3e3b2f78e2bc0720c3050960ad8b2988907a410a8fe565b671d3f2a274b9ed230786da769ebc73e9212b41902bec589d602dc941a6dc8a3c37ede467fdb21101cc8befe111b8a365b94612be8eef16a14dc1f163647744c2d0eabc17dc0bd297ba2e9237fea5d8c845e11ae207c4ce8d5d17b2dffdb6ba20c0474ab9e8547b90bdf61d41602b64b84b3d725279e818dccb82f25c6a75dc473af074c97bd6ea775eb575dd07bd2574dfe308748ecc0d39df14659e1958dbc0413fa7f214b6ffb4059b0ef21e9c2602723695988382201c36dfb9bb5916246f0ecad281b1431846e43b5651a85745a4b81586282285f56625fdb8f46a7b752f1a81159f04c12ec20723c22ae2dadd384bcedecc16de9ae253081ec8b5616b94ec716eb2e91c6af58eddcb360841ec942782fe7b44e9ea191e98007faa5722f12b5e0ff23304297f3aeb369a3ff79434f2ff2e7575bd7e7a1d2592043ea245ca0f69cc0c781b42258230b45391d1c1545ed0a9dcdbedc454c6e7dd313b2e6e757f91309d8fa7801bba864f60f04a1b12e0770e4aa62b7d388f8a0b85d38defa8a21a7764388dd7273b941a17f1f1b1a7acefc8f1726a7cb4ea3f19ddb7a70082c1c5cb6921d4c0eea07cf4d226c98ed1c57a92652b2687181da8091db3ac77bbf5634c351990296494868dd1e365af320c88148a0ed887a06f4be3256cf4556f00ce3376a7016ffddc26f36272d48fc5500451a2ea6de5f6778948e9ba856db5a38129ad1367b983d1f2b624ac5e2e35ce9145eee563d047c853a30c6cabb8064ea183dba622adebae8d2149b93752776e55155319009f2f9a3c1aec9a2b266fdb0451c97fbcc8ca7c1adff0806adc1dc8105b678a30af95cfc5f370dd0e4a6db9811b2deac2ed1fc8716b0571210ee7208316f24dc2af7394519401173d36c3f25fbe4ebd965aa19f53e6fef550ab72216dcfd20ac974b40b456ce143bd4e495dd51fd58e23877ac91e28abed7e9a12c7fbf694e5b5cf144f011da4aca445cf5546d68b2341401460bf2d717663c", ByteVector32(hex"022406339068be457a4430d0de697ee810f0911afc344bd3d4d662771874d2ce")), TlvStream(UpdateAddHtlcTlv.BlindingPoint(PublicKey(hex"02039885cd5b9ffd24b5ce83f464a7d4c0e3f23c1a8061c9fc85730db67ffdbd0c")), UpdateAddHtlcTlv.Endorsement(0))),
|
||||
hex"2c2c2f7eb2eed5b415aed6671228a90d428d9c9fa1dbf492b0625dc4c7d243c3 0000000000000003 00000000000ba6f3 0b7cb0fb7cedeb92573b8865018730232430c8d2365c4e22017f306ae3853ff7 00001211 00 0344ad77d64a38466f8cabc92a956ccceb64e451d09945a45d4be7a16bcb59d84c a62cd346fe5002786e00d538f85d0606b7e946717c62f0df9cd806c04c27d02ce1e536560633099d81fa158aba333c4ccfb91b30bc7e361fcde9705457a0efb1aa5e5983448833b3603d4459a1322275cc29b79d285b762c38b916e176fb779c5ca8cb1804300342462cf4c10d6229e73e5a382976306d0d65583490a5b595fb7f41f4fef20496791381b16a51840c17e805ee44961316cb0ca62d7a0a23a1d42c0d8098128b09ab21ce4a6b5b8749c45f5e0f761c1e24c2e141714fa32bba27da8a113ea26f9af687dd6bafc902b4fb7e53af3dea9fc675928207c898eb2327cea938b342cab7e57cf9c34ec443ace8e66bdc41f98f934e8ba18db357f49d1bdf540632b369435b2e378cd97304e49ce037f531f2faf381a70aaef06582eb2b0956a6b7e39dcaf469253ed6a508947f1a715f6c42c028af2342ced466d7d65bf7d3282ee403b6f220403abad14541d806b355ac38c262dc943c7c239c23b1f863f87259838288a6b5868da8436a56d4d14e7eca32b92070f95ef332c09f3693e952841d6771cd5904a903910b8333337786acdc3099733534ac237e0fbef3acd8e0b4fd665afae94f886dcd86ba0ffe39b6a2fff7e761125ed48c9ef7340d73c3b52a4acf4336b9cc891196158ad77442b242016c1b2333d4be6708c51e5d4ca42cf90438cf21bb7e63731a3be083b20c74954997114c4d08ca886e93055f0fdb34efc3237ca40d28f386b441a699dbaf27f2abb82a49b864d67bca6db2b8b393c02181ec058e350f0f28037ccdca3815fe3f85af3fbcc9c2bcfbffec9ddbc292539ccd16df09c6c892533b3831d7463ac0091d6e3ddd1a5a282a686ce037d47a7c6e373f98110616a1f5f2031a8d231532beebc1703cbaf262c286db4d42ddcdf11c338a0b15dddf422ca09e76a43d453414b8900db9a1e2a6791543e8d9d3d0e3cbe82f2c6ffaa433bb675322e9ae104a9d7b7af7052a44f4b58b522418563ff4c859d5e954c50a8af1295d71f575a888fc30ce25c9d23f1954636ae6f6b2f987ce15a25fbfd7432ca83d2d6f1292dbb1c557b82b9d5bd0fed0b9e21e15401c23d08dfd613403d9127d6b8e4b7673c6ff6c07c47f806f251e36e71e5778f38e73233008d1968a5e6adab26cf77c6fcadd62ae3304c7ba89614107faeaa8eec0c9e9ea9307abcca1e44e40228991aec789cac3d190bb9ab425ad834b6fc69ca8776d926dc6215de382a1275bc327447a5f5ef6c92ae1a2c45cf27441692a5f5ff13a1d5b365aec77c726923f14e376a6aaa9b4ada3931350b8b7eab50e101a9714b884c73ad4fef78520f2582c4f4328b18b1102ea5c93b96055bdc9c955adbeda29a58acc1937e4cb185a481a7d9ec56050d5216869bdcb7773718c68f36de348043116f6f33d98c9b56f8111a2a08f76cf1dbcb0e86660dab947900ed0c6592429b23a9f1d21c72d9a27544a8e135241eb52e3080fa517efd232d6f7f7fb03f82e9332ab5292be9bdf8d67978dd1bc99eff426e02fb3dc9dd15c660747c88a46dd92aeba448be690bf1659a30b1ef304db9d5d607e82a5120439c36e70225a234ef3e4699920426826098ea215553fcb933a4e1ee8a86e53d9cbbcb1b3da0122cfaa2c245b0c60abd5a6dcbf27d4d5cc3374c0285c973bce4f2ab75c7fe19b1e75694568db79c7181a91f36737bb02d635a831e35afa93cb068e8389c3968443a6d2f679ace7e71c1525689b34cfb714e46843fe268320193ce5afdc9dd7aa506f5ed845292dbdd96f91dcbd436e870d59aa4dcac71b19c9756498b2ac9e4d8c7bb7c456559a0775494c326510a2d84a60ac eb26d892176ae2cddd393e1bb626ec2df1f1ae4c65e89f091cb4201e6aa132a5 fe0001a147 01 03" ->
|
||||
UpdateAddHtlc(ByteVector32(hex"2c2c2f7eb2eed5b415aed6671228a90d428d9c9fa1dbf492b0625dc4c7d243c3"), 3, 763635 msat, ByteVector32(hex"0b7cb0fb7cedeb92573b8865018730232430c8d2365c4e22017f306ae3853ff7"), CltvExpiry(4625), OnionRoutingPacket(0, hex"0344ad77d64a38466f8cabc92a956ccceb64e451d09945a45d4be7a16bcb59d84c", payload = hex"a62cd346fe5002786e00d538f85d0606b7e946717c62f0df9cd806c04c27d02ce1e536560633099d81fa158aba333c4ccfb91b30bc7e361fcde9705457a0efb1aa5e5983448833b3603d4459a1322275cc29b79d285b762c38b916e176fb779c5ca8cb1804300342462cf4c10d6229e73e5a382976306d0d65583490a5b595fb7f41f4fef20496791381b16a51840c17e805ee44961316cb0ca62d7a0a23a1d42c0d8098128b09ab21ce4a6b5b8749c45f5e0f761c1e24c2e141714fa32bba27da8a113ea26f9af687dd6bafc902b4fb7e53af3dea9fc675928207c898eb2327cea938b342cab7e57cf9c34ec443ace8e66bdc41f98f934e8ba18db357f49d1bdf540632b369435b2e378cd97304e49ce037f531f2faf381a70aaef06582eb2b0956a6b7e39dcaf469253ed6a508947f1a715f6c42c028af2342ced466d7d65bf7d3282ee403b6f220403abad14541d806b355ac38c262dc943c7c239c23b1f863f87259838288a6b5868da8436a56d4d14e7eca32b92070f95ef332c09f3693e952841d6771cd5904a903910b8333337786acdc3099733534ac237e0fbef3acd8e0b4fd665afae94f886dcd86ba0ffe39b6a2fff7e761125ed48c9ef7340d73c3b52a4acf4336b9cc891196158ad77442b242016c1b2333d4be6708c51e5d4ca42cf90438cf21bb7e63731a3be083b20c74954997114c4d08ca886e93055f0fdb34efc3237ca40d28f386b441a699dbaf27f2abb82a49b864d67bca6db2b8b393c02181ec058e350f0f28037ccdca3815fe3f85af3fbcc9c2bcfbffec9ddbc292539ccd16df09c6c892533b3831d7463ac0091d6e3ddd1a5a282a686ce037d47a7c6e373f98110616a1f5f2031a8d231532beebc1703cbaf262c286db4d42ddcdf11c338a0b15dddf422ca09e76a43d453414b8900db9a1e2a6791543e8d9d3d0e3cbe82f2c6ffaa433bb675322e9ae104a9d7b7af7052a44f4b58b522418563ff4c859d5e954c50a8af1295d71f575a888fc30ce25c9d23f1954636ae6f6b2f987ce15a25fbfd7432ca83d2d6f1292dbb1c557b82b9d5bd0fed0b9e21e15401c23d08dfd613403d9127d6b8e4b7673c6ff6c07c47f806f251e36e71e5778f38e73233008d1968a5e6adab26cf77c6fcadd62ae3304c7ba89614107faeaa8eec0c9e9ea9307abcca1e44e40228991aec789cac3d190bb9ab425ad834b6fc69ca8776d926dc6215de382a1275bc327447a5f5ef6c92ae1a2c45cf27441692a5f5ff13a1d5b365aec77c726923f14e376a6aaa9b4ada3931350b8b7eab50e101a9714b884c73ad4fef78520f2582c4f4328b18b1102ea5c93b96055bdc9c955adbeda29a58acc1937e4cb185a481a7d9ec56050d5216869bdcb7773718c68f36de348043116f6f33d98c9b56f8111a2a08f76cf1dbcb0e86660dab947900ed0c6592429b23a9f1d21c72d9a27544a8e135241eb52e3080fa517efd232d6f7f7fb03f82e9332ab5292be9bdf8d67978dd1bc99eff426e02fb3dc9dd15c660747c88a46dd92aeba448be690bf1659a30b1ef304db9d5d607e82a5120439c36e70225a234ef3e4699920426826098ea215553fcb933a4e1ee8a86e53d9cbbcb1b3da0122cfaa2c245b0c60abd5a6dcbf27d4d5cc3374c0285c973bce4f2ab75c7fe19b1e75694568db79c7181a91f36737bb02d635a831e35afa93cb068e8389c3968443a6d2f679ace7e71c1525689b34cfb714e46843fe268320193ce5afdc9dd7aa506f5ed845292dbdd96f91dcbd436e870d59aa4dcac71b19c9756498b2ac9e4d8c7bb7c456559a0775494c326510a2d84a60ac", ByteVector32(hex"eb26d892176ae2cddd393e1bb626ec2df1f1ae4c65e89f091cb4201e6aa132a5")), TlvStream(UpdateAddHtlcTlv.Endorsement(3))),
|
||||
hex"6c963f8e8b9be358f190a3ac3e12a34400bda4796ed9c23daf179794474a9b62 0000000000000004 00000000000000f5 d9b2563807d4830dc7a42e2df0a146b2acecd54ca3870a928f2b4ac5b489d0eb 000b3c4e 00 033df0a97d288ef59a42b68c03083c36f06b75e651f2620275347e49456e924949 afe9ae18f4780afe43a1450247b5c790e47a27983aa63b82356d049c277517f4991776396cfbbbb5905059a8ebcd49a1c63299a40df59bb8e1842025c8644defa4a0f0bd80d159c68b49747ad1625fbb5182a48634238d42b2678d39d5db9a67fbb3624cf10249b286ba780ced9ede8e37d93a248f756dc134401656d787d2106303082d26601a48aa30804632877de8bc721556f30e57caa3787b04f3712b4d320c24afa7891e70e6f76751cc47a09ddf86aea7099c43809c7f244b21e551d63d363f1c6b5db02504c46449fcfc8038e057713ed1bc5e6daa1b44a90a9db259964b963be6cbdfb4aa000caaf9984aa12ae5a2dc2323b9ab57c1ca35f722c29adeb08789aff2f25936070f38b9b390937983ba8d6434fed6cfd9077e6508b85a2ba020ffc9dc2507beb3278fda821f2ae61ef0ec6a4a226f7b067cc7e69122eeb91dda7885bf9d358d1dfd4ea5af1df4bae30eebe79ddc27abb4edfa4882e9167e557bd0aabb71c5b906f4d5c537a816ee958a1d7a76597e262b50198ba25fd0fb4971c5e22ad0724d1686afa1edb8a5ddf8ad57443258d8044f331463c6ce0f278b16a9a11b8c7b88a494c2c524bdfc37d67f0635f36b15356762f825d23e8228602421e065d828d628f3e76a0505be69179772aa62ee481def1ce1621f874e1ea74afcf0f42c3ab559163afd06c493a56ab0e0ce2563f3351dda1096ff7f7215d61689dd3adc51f2204c664c2cb429237423c7cca52d222662577ab5411b1ed05810b2b1e43ade1958fed3b21623cbf19933dd35e6596c886b3fcfb11b7efa78067786740f0ea887921c8d6a6841b74d2166b6cf83d4432b1f17cefdcffebc0ef08fe5416f5f1f5072d44fa835b5f7078723727aba801343669c8a1afc4e9a2ec3c3821af297c5ee5fd6364b866d7f8b47b6709303246a09274f5d17640b6c60fa9eeb2f7e35472f33db8538ca1cff95e39dd09ac3680faa4ca8ba1ed33f9726adc84a50619605a1b763765f1c26d884d74b884351cbca23d935b25095e08b8cce04e360e0587c034d883f1c7a44cfebf82c7c67dc13c6b76d396cb90a8158fa8d270084f716237eb9b6dc464b2c3e857443f0e8f3073079fefdd7f757abaf19b38da991956034ce1be47315022433bbe766e1d6d02c822314706702c2a61234345ff374c4291f5bd00d8d4caeef0a48785c63afb8196d4874f9c19bb53199bc7ed81a0e94108a7b6851b9a2e3a6f4e12a0eaddf16d4ff1cf6ff9f9da6d81cfc167896ecc3b7a2b6f774a1f394a321bdfb40bdaedc2ecc7148a6d6b1ef64e38c6ea35b0bb17986351e82be82aa2233ed069a6913bbf3a87e5b1094bc2c0ff28b918974357217e160562748a2440670ea1055df53e18a9a3afc0f9f34e40f222cb4f9f35a19488f0ca1b23ada14804f32d183971cb918d7b2430b3f2e4b7633204b0793862521d130e926b6583ca466acf4300020e2c85297f617e29e1c4f0e1ea5676062d8fabc8035f71d2598e3cf7f38e5f61b0f4896442b1c0b102f85fbd1068339dafc9debf90b88e89420337ac34643acf017debff60d030de65c22883205327c0af6cdf70349722073195e2597775514a86f766590c43a3b844f78618b7c7a63d2665a800d5bd1edee916c93ede8c0c8dc980ab9f85ff33c3b4740a4b0fc3f3b3e324a349e9c21e0aec8fdcc0a14b0e35b68b3d46cfcfd991eefc8b616f1a376030de33c1662c0210cfbaa27653ff8a814b4acd2ad0a09761db5f0ba8ef2a00cf66053725a4e422b0cd22f9d4881e28573ccfd3b9b3088698c1acb647d8ddeda65303fc57d9ad663a016b1c1a0dd6712 f6514b5e1eae383e2c5ae1ec1820f28583304274fa11ef2d2e2d6f3cafa2ede0 fe0001a147 01 07" ->
|
||||
UpdateAddHtlc(ByteVector32(hex"6c963f8e8b9be358f190a3ac3e12a34400bda4796ed9c23daf179794474a9b62"), 4, 245 msat, ByteVector32(hex"d9b2563807d4830dc7a42e2df0a146b2acecd54ca3870a928f2b4ac5b489d0eb"), CltvExpiry(736334), OnionRoutingPacket(0, hex"033df0a97d288ef59a42b68c03083c36f06b75e651f2620275347e49456e924949", payload = hex"afe9ae18f4780afe43a1450247b5c790e47a27983aa63b82356d049c277517f4991776396cfbbbb5905059a8ebcd49a1c63299a40df59bb8e1842025c8644defa4a0f0bd80d159c68b49747ad1625fbb5182a48634238d42b2678d39d5db9a67fbb3624cf10249b286ba780ced9ede8e37d93a248f756dc134401656d787d2106303082d26601a48aa30804632877de8bc721556f30e57caa3787b04f3712b4d320c24afa7891e70e6f76751cc47a09ddf86aea7099c43809c7f244b21e551d63d363f1c6b5db02504c46449fcfc8038e057713ed1bc5e6daa1b44a90a9db259964b963be6cbdfb4aa000caaf9984aa12ae5a2dc2323b9ab57c1ca35f722c29adeb08789aff2f25936070f38b9b390937983ba8d6434fed6cfd9077e6508b85a2ba020ffc9dc2507beb3278fda821f2ae61ef0ec6a4a226f7b067cc7e69122eeb91dda7885bf9d358d1dfd4ea5af1df4bae30eebe79ddc27abb4edfa4882e9167e557bd0aabb71c5b906f4d5c537a816ee958a1d7a76597e262b50198ba25fd0fb4971c5e22ad0724d1686afa1edb8a5ddf8ad57443258d8044f331463c6ce0f278b16a9a11b8c7b88a494c2c524bdfc37d67f0635f36b15356762f825d23e8228602421e065d828d628f3e76a0505be69179772aa62ee481def1ce1621f874e1ea74afcf0f42c3ab559163afd06c493a56ab0e0ce2563f3351dda1096ff7f7215d61689dd3adc51f2204c664c2cb429237423c7cca52d222662577ab5411b1ed05810b2b1e43ade1958fed3b21623cbf19933dd35e6596c886b3fcfb11b7efa78067786740f0ea887921c8d6a6841b74d2166b6cf83d4432b1f17cefdcffebc0ef08fe5416f5f1f5072d44fa835b5f7078723727aba801343669c8a1afc4e9a2ec3c3821af297c5ee5fd6364b866d7f8b47b6709303246a09274f5d17640b6c60fa9eeb2f7e35472f33db8538ca1cff95e39dd09ac3680faa4ca8ba1ed33f9726adc84a50619605a1b763765f1c26d884d74b884351cbca23d935b25095e08b8cce04e360e0587c034d883f1c7a44cfebf82c7c67dc13c6b76d396cb90a8158fa8d270084f716237eb9b6dc464b2c3e857443f0e8f3073079fefdd7f757abaf19b38da991956034ce1be47315022433bbe766e1d6d02c822314706702c2a61234345ff374c4291f5bd00d8d4caeef0a48785c63afb8196d4874f9c19bb53199bc7ed81a0e94108a7b6851b9a2e3a6f4e12a0eaddf16d4ff1cf6ff9f9da6d81cfc167896ecc3b7a2b6f774a1f394a321bdfb40bdaedc2ecc7148a6d6b1ef64e38c6ea35b0bb17986351e82be82aa2233ed069a6913bbf3a87e5b1094bc2c0ff28b918974357217e160562748a2440670ea1055df53e18a9a3afc0f9f34e40f222cb4f9f35a19488f0ca1b23ada14804f32d183971cb918d7b2430b3f2e4b7633204b0793862521d130e926b6583ca466acf4300020e2c85297f617e29e1c4f0e1ea5676062d8fabc8035f71d2598e3cf7f38e5f61b0f4896442b1c0b102f85fbd1068339dafc9debf90b88e89420337ac34643acf017debff60d030de65c22883205327c0af6cdf70349722073195e2597775514a86f766590c43a3b844f78618b7c7a63d2665a800d5bd1edee916c93ede8c0c8dc980ab9f85ff33c3b4740a4b0fc3f3b3e324a349e9c21e0aec8fdcc0a14b0e35b68b3d46cfcfd991eefc8b616f1a376030de33c1662c0210cfbaa27653ff8a814b4acd2ad0a09761db5f0ba8ef2a00cf66053725a4e422b0cd22f9d4881e28573ccfd3b9b3088698c1acb647d8ddeda65303fc57d9ad663a016b1c1a0dd6712", ByteVector32(hex"f6514b5e1eae383e2c5ae1ec1820f28583304274fa11ef2d2e2d6f3cafa2ede0")), TlvStream(UpdateAddHtlcTlv.Endorsement(7))),
|
||||
hex"2af2f6410744de2c8c5fe949443d8e137064bd97ef782278c8e02189b6f0231c 0000000000000005 000000002ef6eb30 9fbe04e7e3f8e71768cfc95d1b67a30ff995dbd2a312e44a839123e95f944258 00008e68 00 02c606691a88f80fdc10d007ef5dfa0b91ce33b7b3fa40a6df84f7285aaf37174e cf939423f7ca7c34b07034acef7e19feab1eba59462cf32fb785d4ecf61008247a17c87380ba957f2503ea6a899707f2167ad3972dfc0e7a00d9a0b6aae7b23b5b57903697f74f98808b35f16f546bd4d32395297ed0caddbd744bfe4ab301d8584756d43d6d1e005a35ef9a71ce2e0c88164165f6f125ea3aaed89dba3291e6adfaa29721a9694df0c3cf1f8d09626cf2026e4c10a7bcd42a5220c0f13a5f0caa397c5685aee4bc487f831a28d98b327522c8f63a36e76a367ca82e88ea0ea77a511447142f655fd35e44fb595c96ac7b0c32c79a6bac6d7b3035abbf7fe7ce05c1d2b4b7c25b9626f249a7b9ebc830461b899f460ecd11037c4bec9b0f4c0a4e32b41ae2010fe2c523c56f4d86ef9f0b6aa73b150734f616b8bf20c201620cd05555b7e2e3a822ee02602b3f5f39f9ec933a418b3da707b4f29a42b3346e79a29d9ebb57c14d6c29ad94bc400e2941db92d3f90ebb4af0dd395747f6b0e0bb42648ea37280279ca0d8762ad1af4c96f56f41082cfe446f0a0c923e5fa97fec390382b401940c53ea9ac3f71a20ff61792557ab9d520816e1aa489ea2a38caa20c40e4aff6954e6b8d7469c496f9372a0c031267fa247f1901f1cebe87d2181288740345537f7af69e3f21b65ea1a622e1741cd5504e33afb6922544b3ee022e2be4f9f400ae401db1a43240d9c272a6dc653b647e6d91b392246b98f9a15547bbf6ddf289844c4910c880b362a383728f91379173b527f8ac5bef772267e5633ec6e758d0c3671903b32c8dad8d21ffec3a0b6f27cc5004fc5a12bcf6bd57aa5c6a982f82c8271e9177ccc2b118957d16c760aa1d60cc7e9408040acbfd186d3c76fcdc7b57b180d6e6b8ea311495d7611e73c4548bd3cccc7d12f0ca69b6240f578a635187713aaa9b561e0dff791c437f95a61818ebf55cdc35a44b0860aac41c3abfedccb4eb8970152fa324e10afdbdebc80dbfbb09e4800cbe51c32daf942e3f54f3d3bee352c3c31290a76f07f4b1a079f5f38109b0d0520a253c9feb0b2e0982730ab2b5f3afd41a9f22d7f4380f4ea6f795540daaae771fe6a9119a13ba3f07ca861ed78698447d070dcfc6cb4843c348e33eaf5e576e1ce9412fd72b69673a3c30b9cc528b041b5489c48c265d7f2251a204e8dc40991b3c8f5620e7a207df2eee41f3c42520b21bba2208e5eff594928271250861982334a139738c030e70606c3da9e26c4ec3c286dd678f3b8ffc4dcd4b0bf5ac595764887de862d5c241368d9f2481eb81a529b0cf4d8d75140b440e26e5af4effa7ad05b1b41a2bf223e902e70af44277ebd1690b5d6da0a3dad18485d967dbb77a3d319fd6e4693e6ee9e99ed8d66f2fb0f355560d87fa8d4ed6e1aac8db481be2091b922df75eb738f64246ad5497ef67c0193d7d8cd0a22694ff63b7bdd915217d93bec2c26077f4de4c3a111b19d4455fb4f77ff72c755e89a71f58155fa47b7f8cd775daa881077b908c89be5e7064c588dc6f520f60d4d6816507c156e553775c843a13fafb9db03de8422c36426f3856124f22236dc8151539ae18a927a4a6fa7e4aed21898184c4b9383b0dbaf9b2938bec0a64a6a8cd606eeb72076655ded0d0f71f95f075c03fed936e688c2d202c7c7e93586d8b49eac1dd9871b5fbc2ab854aa4e86119bf317902cb362e03e0c5bb7b79f80071652a64dc1f5172575edcb0e3fac774d853083b6faca3860b661163f4fe4f8595238c76987d088eaedf8c2fafc14a2995b0cfa951c5df92c55e3784215b0722d08bc9a43bb32c6531393465714b190ae78dd1b18b0f3e0c0432c034a11273d36 931651e9b75081bf2acdf3b9b5f1dc9871b47ff39841b5b17e0a2ea2c9bf4fdc" ->
|
||||
UpdateAddHtlc(ByteVector32(hex"2af2f6410744de2c8c5fe949443d8e137064bd97ef782278c8e02189b6f0231c"), 5, 787934000 msat, ByteVector32(hex"9fbe04e7e3f8e71768cfc95d1b67a30ff995dbd2a312e44a839123e95f944258"), CltvExpiry(36456), OnionRoutingPacket(0, hex"02c606691a88f80fdc10d007ef5dfa0b91ce33b7b3fa40a6df84f7285aaf37174e", payload = hex"cf939423f7ca7c34b07034acef7e19feab1eba59462cf32fb785d4ecf61008247a17c87380ba957f2503ea6a899707f2167ad3972dfc0e7a00d9a0b6aae7b23b5b57903697f74f98808b35f16f546bd4d32395297ed0caddbd744bfe4ab301d8584756d43d6d1e005a35ef9a71ce2e0c88164165f6f125ea3aaed89dba3291e6adfaa29721a9694df0c3cf1f8d09626cf2026e4c10a7bcd42a5220c0f13a5f0caa397c5685aee4bc487f831a28d98b327522c8f63a36e76a367ca82e88ea0ea77a511447142f655fd35e44fb595c96ac7b0c32c79a6bac6d7b3035abbf7fe7ce05c1d2b4b7c25b9626f249a7b9ebc830461b899f460ecd11037c4bec9b0f4c0a4e32b41ae2010fe2c523c56f4d86ef9f0b6aa73b150734f616b8bf20c201620cd05555b7e2e3a822ee02602b3f5f39f9ec933a418b3da707b4f29a42b3346e79a29d9ebb57c14d6c29ad94bc400e2941db92d3f90ebb4af0dd395747f6b0e0bb42648ea37280279ca0d8762ad1af4c96f56f41082cfe446f0a0c923e5fa97fec390382b401940c53ea9ac3f71a20ff61792557ab9d520816e1aa489ea2a38caa20c40e4aff6954e6b8d7469c496f9372a0c031267fa247f1901f1cebe87d2181288740345537f7af69e3f21b65ea1a622e1741cd5504e33afb6922544b3ee022e2be4f9f400ae401db1a43240d9c272a6dc653b647e6d91b392246b98f9a15547bbf6ddf289844c4910c880b362a383728f91379173b527f8ac5bef772267e5633ec6e758d0c3671903b32c8dad8d21ffec3a0b6f27cc5004fc5a12bcf6bd57aa5c6a982f82c8271e9177ccc2b118957d16c760aa1d60cc7e9408040acbfd186d3c76fcdc7b57b180d6e6b8ea311495d7611e73c4548bd3cccc7d12f0ca69b6240f578a635187713aaa9b561e0dff791c437f95a61818ebf55cdc35a44b0860aac41c3abfedccb4eb8970152fa324e10afdbdebc80dbfbb09e4800cbe51c32daf942e3f54f3d3bee352c3c31290a76f07f4b1a079f5f38109b0d0520a253c9feb0b2e0982730ab2b5f3afd41a9f22d7f4380f4ea6f795540daaae771fe6a9119a13ba3f07ca861ed78698447d070dcfc6cb4843c348e33eaf5e576e1ce9412fd72b69673a3c30b9cc528b041b5489c48c265d7f2251a204e8dc40991b3c8f5620e7a207df2eee41f3c42520b21bba2208e5eff594928271250861982334a139738c030e70606c3da9e26c4ec3c286dd678f3b8ffc4dcd4b0bf5ac595764887de862d5c241368d9f2481eb81a529b0cf4d8d75140b440e26e5af4effa7ad05b1b41a2bf223e902e70af44277ebd1690b5d6da0a3dad18485d967dbb77a3d319fd6e4693e6ee9e99ed8d66f2fb0f355560d87fa8d4ed6e1aac8db481be2091b922df75eb738f64246ad5497ef67c0193d7d8cd0a22694ff63b7bdd915217d93bec2c26077f4de4c3a111b19d4455fb4f77ff72c755e89a71f58155fa47b7f8cd775daa881077b908c89be5e7064c588dc6f520f60d4d6816507c156e553775c843a13fafb9db03de8422c36426f3856124f22236dc8151539ae18a927a4a6fa7e4aed21898184c4b9383b0dbaf9b2938bec0a64a6a8cd606eeb72076655ded0d0f71f95f075c03fed936e688c2d202c7c7e93586d8b49eac1dd9871b5fbc2ab854aa4e86119bf317902cb362e03e0c5bb7b79f80071652a64dc1f5172575edcb0e3fac774d853083b6faca3860b661163f4fe4f8595238c76987d088eaedf8c2fafc14a2995b0cfa951c5df92c55e3784215b0722d08bc9a43bb32c6531393465714b190ae78dd1b18b0f3e0c0432c034a11273d36", ByteVector32(hex"931651e9b75081bf2acdf3b9b5f1dc9871b47ff39841b5b17e0a2ea2c9bf4fdc")), TlvStream()),
|
||||
)
|
||||
for ((bin, ref) <- testCases) {
|
||||
val decoded = updateAddHtlcCodec.decode(bin.bits).require
|
||||
assert(decoded.value == ref)
|
||||
assert(decoded.remainder.isEmpty)
|
||||
assert(updateAddHtlcCodec.encode(decoded.value).require.bytes == bin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue