1
0
mirror of https://github.com/ACINQ/eclair.git synced 2024-11-20 10:39:19 +01:00

Added json serializers to handle payment failures (#515)

Added a serializer for Throwable (local failures), and a serializer for FailureMessage (remote failures)
This commit is contained in:
Dominique 2018-03-27 14:06:52 +02:00 committed by GitHub
parent 2a02461bcc
commit a767aa17f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 9 deletions

View File

@ -21,13 +21,13 @@ import java.net.InetSocketAddress
import com.google.common.net.HostAndPort
import fr.acinq.bitcoin.Crypto.{Point, PrivateKey, PublicKey, Scalar}
import fr.acinq.bitcoin.{BinaryData, OutPoint, Transaction}
import fr.acinq.eclair.{ShortChannelId, UInt64}
import fr.acinq.eclair.channel.State
import fr.acinq.eclair.crypto.ShaChain
import fr.acinq.eclair.router.RouteResponse
import fr.acinq.eclair.transactions.Transactions.{InputInfo, TransactionWithInputInfo}
import fr.acinq.eclair.wire.Color
import org.json4s.JsonAST.{JArray, JInt, JNull, JObject, JString}
import fr.acinq.eclair.wire.{Color, FailureMessage}
import fr.acinq.eclair.{ShortChannelId, UInt64}
import org.json4s.JsonAST._
import org.json4s.{CustomKeySerializer, CustomSerializer}
/**
@ -106,3 +106,12 @@ class RouteResponseSerializer extends CustomSerializer[RouteResponse](format =>
}
JArray(nodeIds.toList.map(n => JString(n.toString)))
}))
class ThrowableSerializer extends CustomSerializer[Throwable](format => ({ null }, {
case t: Throwable if t.getMessage != null => JString(t.getMessage)
case t: Throwable => JString(t.getClass.getSimpleName)
}))
class FailureMessageSerializer extends CustomSerializer[FailureMessage](format => ({ null }, {
case m: FailureMessage => JString(m.message)
}))

View File

@ -34,9 +34,9 @@ import fr.acinq.bitcoin.{BinaryData, MilliSatoshi, Satoshi}
import fr.acinq.eclair.channel._
import fr.acinq.eclair.io.Peer.{GetPeerInfo, PeerInfo}
import fr.acinq.eclair.io.{NodeURI, Peer}
import fr.acinq.eclair.payment.PaymentLifecycle.{CheckPayment, PaymentResult, ReceivePayment, SendPayment}
import fr.acinq.eclair.payment.PaymentRequest
import fr.acinq.eclair.router.{ChannelDesc,RouteRequest,RouteResponse}
import fr.acinq.eclair.payment.PaymentLifecycle._
import fr.acinq.eclair.payment.{PaymentLifecycle, PaymentRequest}
import fr.acinq.eclair.router.{ChannelDesc, RouteRequest, RouteResponse}
import fr.acinq.eclair.wire.{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement}
import fr.acinq.eclair.{Kit, ShortChannelId, feerateByte2Kw}
import grizzled.slf4j.Logging
@ -70,7 +70,7 @@ trait Service extends Logging {
def scheduler: Scheduler
implicit val serialization = jackson.Serialization
implicit val formats = org.json4s.DefaultFormats + new BinaryDataSerializer + new UInt64Serializer + new ShortChannelIdSerializer + new StateSerializer + new ShaChainSerializer + new PublicKeySerializer + new PrivateKeySerializer + new ScalarSerializer + new PointSerializer + new TransactionSerializer + new TransactionWithInputInfoSerializer + new InetSocketAddressSerializer + new OutPointSerializer + new OutPointKeySerializer + new InputInfoSerializer + new ColorSerializer + new RouteResponseSerializer
implicit val formats = org.json4s.DefaultFormats + new BinaryDataSerializer + new UInt64Serializer + new ShortChannelIdSerializer + new StateSerializer + new ShaChainSerializer + new PublicKeySerializer + new PrivateKeySerializer + new ScalarSerializer + new PointSerializer + new TransactionSerializer + new TransactionWithInputInfoSerializer + new InetSocketAddressSerializer + new OutPointSerializer + new OutPointKeySerializer + new InputInfoSerializer + new ColorSerializer + new RouteResponseSerializer + new ThrowableSerializer + new FailureMessageSerializer
implicit val timeout = Timeout(60 seconds)
implicit val shouldWritePretty: ShouldWritePretty = ShouldWritePretty.True
@ -246,7 +246,11 @@ trait Service extends Logging {
// user manually sets the payment information
case JInt(amountMsat) :: JString(paymentHash) :: JString(nodeId) :: Nil =>
(Try(BinaryData(paymentHash)), Try(PublicKey(nodeId))) match {
case (Success(ph), Success(pk)) => completeRpcFuture(req.id, (paymentInitiator ? SendPayment(amountMsat.toLong, ph, pk, maxFeePct = nodeParams.maxPaymentFee)).mapTo[PaymentResult])
case (Success(ph), Success(pk)) => completeRpcFuture(req.id, (paymentInitiator ?
SendPayment(amountMsat.toLong, ph, pk, maxFeePct = nodeParams.maxPaymentFee)).mapTo[PaymentResult].map {
case s: PaymentSucceeded => s
case f: PaymentFailed => f.copy(failures = PaymentLifecycle.transformForUser(f.failures))
})
case (Failure(_), _) => reject(RpcValidationRejection(req.id, s"invalid payment hash '$paymentHash'"))
case _ => reject(RpcValidationRejection(req.id, s"invalid node id '$nodeId'"))
}
@ -266,7 +270,10 @@ trait Service extends Logging {
case None => SendPayment(amount_msat, pr.paymentHash, pr.nodeId, maxFeePct = nodeParams.maxPaymentFee)
case Some(minFinalCltvExpiry) => SendPayment(amount_msat, pr.paymentHash, pr.nodeId, assistedRoutes = Nil, minFinalCltvExpiry, maxFeePct = nodeParams.maxPaymentFee)
}
completeRpcFuture(req.id, (paymentInitiator ? sendPayment).mapTo[PaymentResult])
completeRpcFuture(req.id, (paymentInitiator ? sendPayment).mapTo[PaymentResult].map {
case s: PaymentSucceeded => s
case f: PaymentFailed => f.copy(failures = PaymentLifecycle.transformForUser(f.failures))
})
case _ => reject(RpcValidationRejection(req.id, s"payment request is not valid"))
}
case _ => reject(UnknownParamsRejection(req.id, "[amountMsat, paymentHash, nodeId or [paymentRequest] or [paymentRequest, amountMsat]"))