Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ object Bolt12Invoice {
_ -> ()
)
if (records.get[InvoiceAmount].isEmpty) return Left(MissingRequiredTlv(UInt64(170)))
if (records.get[InvoicePaths].forall(_.paths.isEmpty)) return Left(MissingRequiredTlv(UInt64(160)))
if (records.get[InvoicePaths].isEmpty) return Left(MissingRequiredTlv(UInt64(160)))
if (records.get[InvoiceBlindedPay].map(_.paymentInfo.length) != records.get[InvoicePaths].map(_.paths.length)) return Left(MissingRequiredTlv(UInt64(162)))
if (records.get[InvoiceNodeId].isEmpty) return Left(MissingRequiredTlv(UInt64(176)))
if (records.get[InvoiceCreatedAt].isEmpty) return Left(MissingRequiredTlv(UInt64(164)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,29 @@

package fr.acinq.eclair.wire.protocol

import fr.acinq.bitcoin.scalacompat.BlockHash
import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey
import fr.acinq.eclair.crypto.Sphinx.RouteBlinding.{BlindedHop, BlindedRoute}
import fr.acinq.eclair.wire.protocol.CommonCodecs._
import fr.acinq.eclair.wire.protocol.OfferTypes._
import fr.acinq.eclair.wire.protocol.TlvCodecs.{tlvField, tmillisatoshi, tu32, tu64overflow}
import fr.acinq.eclair.{EncodedNodeId, TimestampSecond, UInt64}
import scodec.{Attempt, Codec}
import scodec.{Attempt, Codec, Err}
import scodec.codecs._

import java.util.Currency
import scala.util.Try

object OfferCodecs {
private val offerChains: Codec[OfferChains] = tlvField(list(blockHash).xmap[Seq[BlockHash]](_.toSeq, _.toList))
private def nonEmptyList[A](codec: Codec[A], name: String): Codec[Seq[A]] =
list(codec).narrow(l => {
if (l.nonEmpty) {
Attempt.successful(l.toSeq)
} else {
Attempt.failure(Err(s"$name must not be empty"))
}
}, _.toList)
Comment thread
t-bast marked this conversation as resolved.
Outdated

private val offerChains: Codec[OfferChains] = tlvField(nonEmptyList(blockHash, "offer_chains"))

private val offerMetadata: Codec[OfferMetadata] = tlvField(bytes)

Expand Down Expand Up @@ -76,7 +84,7 @@ object OfferCodecs {
("firstPathKey" | publicKey) ::
("path" | blindedNodesCodec)).as[BlindedRoute]

private val offerPaths: Codec[OfferPaths] = tlvField(list(blindedRouteCodec).xmap[Seq[BlindedRoute]](_.toSeq, _.toList))
private val offerPaths: Codec[OfferPaths] = tlvField(nonEmptyList(blindedRouteCodec, "offer_paths"))

private val offerIssuer: Codec[OfferIssuer] = tlvField(utf8)

Expand Down Expand Up @@ -138,7 +146,7 @@ object OfferCodecs {
.typecase(UInt64(240), signature)
).complete)

private val invoicePaths: Codec[InvoicePaths] = tlvField(list(blindedRouteCodec).xmap[Seq[BlindedRoute]](_.toSeq, _.toList))
private val invoicePaths: Codec[InvoicePaths] = tlvField(nonEmptyList(blindedRouteCodec, "invoice_paths"))

val paymentInfo: Codec[PaymentInfo] =
(("fee_base_msat" | millisatoshi32) ::
Expand All @@ -148,7 +156,7 @@ object OfferCodecs {
("htlc_maximum_msat" | millisatoshi) ::
("features" | variableSizeBytes(uint16, bytes))).as[PaymentInfo]

private val invoiceBlindedPay: Codec[InvoiceBlindedPay] = tlvField(list(paymentInfo).xmap[Seq[PaymentInfo]](_.toSeq, _.toList))
private val invoiceBlindedPay: Codec[InvoiceBlindedPay] = tlvField(nonEmptyList(paymentInfo, "invoice_blindedpay"))

private val invoiceCreatedAt: Codec[InvoiceCreatedAt] = tlvField(tu64overflow.as[TimestampSecond])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ object OfferTypes {

def validate(records: TlvStream[OfferTlv]): Either[InvalidTlvPayload, Offer] = {
if (records.get[OfferDescription].isEmpty && records.get[OfferAmount].nonEmpty) return Left(MissingRequiredTlv(UInt64(10)))
if (records.get[OfferNodeId].isEmpty && records.get[OfferPaths].forall(_.paths.isEmpty)) return Left(MissingRequiredTlv(UInt64(22)))
if (records.get[OfferNodeId].isEmpty && records.get[OfferPaths].isEmpty) return Left(MissingRequiredTlv(UInt64(22)))
if (records.get[OfferCurrency].nonEmpty && records.get[OfferAmount].isEmpty) return Left(MissingRequiredTlv(UInt64(8)))
if (records.unknown.exists(!isOfferTlv(_))) return Left(ForbiddenTlv(records.unknown.find(!isOfferTlv(_)).get.tag))
Right(Offer(records))
Expand Down