mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-23 06:45:21 +01:00
Update Eclair RPC to v0.8.0 (#4994)
* Update Eclair RPC to v0.8.0 * update unit tests
This commit is contained in:
parent
fbcea17e2f
commit
2799d8276a
8 changed files with 160 additions and 44 deletions
|
@ -184,12 +184,20 @@ object ChannelStats {
|
|||
}
|
||||
}
|
||||
|
||||
case class RealChannelId(status: String, realScid: ShortChannelId)
|
||||
|
||||
case class ShortIds(
|
||||
real: RealChannelId,
|
||||
localAlias: String,
|
||||
remoteAlias: String)
|
||||
|
||||
case class UsableBalancesResult(
|
||||
remoteNodeId: NodeId,
|
||||
shortChannelId: ShortChannelId,
|
||||
shortIds: ShortIds,
|
||||
canSend: MilliSatoshis,
|
||||
canReceive: MilliSatoshis,
|
||||
isPublic: Boolean
|
||||
isPublic: Boolean,
|
||||
isEnabled: Boolean
|
||||
)
|
||||
|
||||
case class ReceivedPayment(
|
||||
|
@ -258,7 +266,7 @@ case class ChannelResult(
|
|||
data: JsObject) {
|
||||
|
||||
lazy val shortChannelId: Option[ShortChannelId] =
|
||||
(data \ "shortChannelId").validate[ShortChannelId].asOpt
|
||||
(data \ "shortIds" \ "real" \ "realScid").validate[ShortChannelId].asOpt
|
||||
}
|
||||
|
||||
// ChannelResult ends here
|
||||
|
|
|
@ -952,6 +952,12 @@ object JsonReaders {
|
|||
}
|
||||
}
|
||||
|
||||
implicit val realChannelIdReads: Reads[RealChannelId] =
|
||||
Json.reads[RealChannelId]
|
||||
|
||||
implicit val shortIdsReads: Reads[ShortIds] =
|
||||
Json.reads[ShortIds]
|
||||
|
||||
implicit val nodeInfoReads: Reads[NodeInfo] = {
|
||||
Reads { jsValue =>
|
||||
for {
|
||||
|
@ -1019,7 +1025,7 @@ object JsonReaders {
|
|||
implicit val openChannelInfoReads: Reads[OpenChannelInfo] = Reads { jsValue =>
|
||||
for {
|
||||
nodeId <- (jsValue \ "nodeId").validate[NodeId]
|
||||
shortChannelId <- (jsValue \ "data" \ "shortChannelId")
|
||||
shortChannelId <- (jsValue \ "data" \ "shortIds" \ "real" \ "realScid")
|
||||
.validate[ShortChannelId]
|
||||
channelId <- (jsValue \ "channelId").validate[FundedChannelId]
|
||||
state <- (jsValue \ "state").validate[ChannelState.NORMAL.type]
|
||||
|
@ -1310,7 +1316,7 @@ object JsonReaders {
|
|||
implicit val receivedPaymentResultReads: Reads[IncomingPayment] = Reads {
|
||||
js =>
|
||||
for {
|
||||
paymentRequest <- (js \ "paymentRequest").validate[PaymentRequest]
|
||||
paymentRequest <- (js \ "invoice").validate[PaymentRequest]
|
||||
paymentPreimage <- (js \ "paymentPreimage").validate[PaymentPreimage]
|
||||
paymentType <- (js \ "paymentType").validate[PaymentType]
|
||||
createdAt <- (js \ "createdAt" \ "unix")
|
||||
|
|
|
@ -8,13 +8,20 @@ sealed trait ChannelState
|
|||
|
||||
object ChannelState extends StringFactory[ChannelState] {
|
||||
case object WAIT_FOR_INIT_INTERNAL extends ChannelState
|
||||
case object WAIT_FOR_INIT_SINGLE_FUNDED_CHANNEL extends ChannelState
|
||||
case object WAIT_FOR_OPEN_CHANNEL extends ChannelState
|
||||
case object WAIT_FOR_ACCEPT_CHANNEL extends ChannelState
|
||||
case object WAIT_FOR_FUNDING_INTERNAL extends ChannelState
|
||||
case object WAIT_FOR_FUNDING_CREATED extends ChannelState
|
||||
case object WAIT_FOR_FUNDING_SIGNED extends ChannelState
|
||||
case object WAIT_FOR_FUNDING_CONFIRMED extends ChannelState
|
||||
case object WAIT_FOR_FUNDING_LOCKED extends ChannelState
|
||||
case object WAIT_FOR_CHANNEL_READY extends ChannelState
|
||||
case object WAIT_FOR_INIT_DUAL_FUNDED_CHANNEL extends ChannelState
|
||||
case object WAIT_FOR_OPEN_DUAL_FUNDED_CHANNEL extends ChannelState
|
||||
case object WAIT_FOR_ACCEPT_DUAL_FUNDED_CHANNEL extends ChannelState
|
||||
case object WAIT_FOR_DUAL_FUNDING_CREATED extends ChannelState
|
||||
case object WAIT_FOR_DUAL_FUNDING_CONFIRMED extends ChannelState
|
||||
case object WAIT_FOR_DUAL_FUNDING_READY extends ChannelState
|
||||
case object NORMAL extends ChannelState
|
||||
case object SHUTDOWN extends ChannelState
|
||||
case object NEGOTIATING extends ChannelState
|
||||
|
@ -23,19 +30,24 @@ object ChannelState extends StringFactory[ChannelState] {
|
|||
case object OFFLINE extends ChannelState
|
||||
case object SYNCING extends ChannelState
|
||||
case object WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT extends ChannelState
|
||||
case object ERR_FUNDING_LOST extends ChannelState
|
||||
case object ERR_FUNDING_TIMEOUT extends ChannelState
|
||||
case object ERR_INFORMATION_LEAK extends ChannelState
|
||||
|
||||
private lazy val all: Map[String, ChannelState] = List(
|
||||
WAIT_FOR_INIT_INTERNAL,
|
||||
WAIT_FOR_INIT_SINGLE_FUNDED_CHANNEL,
|
||||
WAIT_FOR_OPEN_CHANNEL,
|
||||
WAIT_FOR_ACCEPT_CHANNEL,
|
||||
WAIT_FOR_FUNDING_INTERNAL,
|
||||
WAIT_FOR_FUNDING_CREATED,
|
||||
WAIT_FOR_FUNDING_SIGNED,
|
||||
WAIT_FOR_FUNDING_CONFIRMED,
|
||||
WAIT_FOR_FUNDING_LOCKED,
|
||||
WAIT_FOR_CHANNEL_READY,
|
||||
WAIT_FOR_INIT_DUAL_FUNDED_CHANNEL,
|
||||
WAIT_FOR_OPEN_DUAL_FUNDED_CHANNEL,
|
||||
WAIT_FOR_ACCEPT_DUAL_FUNDED_CHANNEL,
|
||||
WAIT_FOR_DUAL_FUNDING_CREATED,
|
||||
WAIT_FOR_DUAL_FUNDING_CONFIRMED,
|
||||
WAIT_FOR_DUAL_FUNDING_READY,
|
||||
NORMAL,
|
||||
SHUTDOWN,
|
||||
NEGOTIATING,
|
||||
|
@ -44,8 +56,6 @@ object ChannelState extends StringFactory[ChannelState] {
|
|||
OFFLINE,
|
||||
SYNCING,
|
||||
WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT,
|
||||
ERR_FUNDING_LOST,
|
||||
ERR_FUNDING_TIMEOUT,
|
||||
ERR_INFORMATION_LEAK
|
||||
).map(state => state.toString -> state).toMap
|
||||
|
||||
|
|
|
@ -38,7 +38,19 @@ trait NodeFeature extends Feature
|
|||
|
||||
/** Feature that should be advertised in invoices. */
|
||||
trait InvoiceFeature extends Feature
|
||||
// @formatter:on
|
||||
|
||||
/** Feature negotiated when opening a channel that will apply for all of the channel's lifetime.
|
||||
* This doesn't include features that can be safely activated/deactivated without impacting the channel's operation such
|
||||
* as option_dataloss_protect or option_shutdown_anysegwit.
|
||||
*/
|
||||
trait PermanentChannelFeature extends InitFeature // <- not in the spec
|
||||
|
||||
/** Permanent channel feature negotiated in the channel type. Those features take precedence over permanent channel
|
||||
* features negotiated in init messages. For example, if the channel type is option_static_remotekey, then even if
|
||||
* the option_anchor_outputs feature is supported by both peers, it won't apply to the channel.
|
||||
*/
|
||||
|
||||
trait ChannelTypeFeature extends PermanentChannelFeature // @formatter:on
|
||||
|
||||
case class UnknownFeature(bitIndex: Int)
|
||||
|
||||
|
@ -153,7 +165,8 @@ object Features {
|
|||
case object UpfrontShutdownScript
|
||||
extends Feature
|
||||
with InitFeature
|
||||
with NodeFeature {
|
||||
with NodeFeature
|
||||
with PermanentChannelFeature {
|
||||
val rfcName = "option_upfront_shutdown_script"
|
||||
val mandatory = 4
|
||||
}
|
||||
|
@ -186,7 +199,8 @@ object Features {
|
|||
case object StaticRemoteKey
|
||||
extends Feature
|
||||
with InitFeature
|
||||
with NodeFeature {
|
||||
with NodeFeature
|
||||
with ChannelTypeFeature {
|
||||
val rfcName = "option_static_remotekey"
|
||||
val mandatory = 12
|
||||
}
|
||||
|
@ -209,12 +223,20 @@ object Features {
|
|||
val mandatory = 16
|
||||
}
|
||||
|
||||
case object Wumbo extends Feature with InitFeature with NodeFeature {
|
||||
case object Wumbo
|
||||
extends Feature
|
||||
with InitFeature
|
||||
with NodeFeature
|
||||
with PermanentChannelFeature {
|
||||
val rfcName = "option_support_large_channel"
|
||||
val mandatory = 18
|
||||
}
|
||||
|
||||
case object AnchorOutputs extends Feature with InitFeature with NodeFeature {
|
||||
case object AnchorOutputs
|
||||
extends Feature
|
||||
with InitFeature
|
||||
with NodeFeature
|
||||
with ChannelTypeFeature {
|
||||
val rfcName = "option_anchor_outputs"
|
||||
val mandatory = 20
|
||||
}
|
||||
|
@ -222,11 +244,21 @@ object Features {
|
|||
case object AnchorOutputsZeroFeeHtlcTx
|
||||
extends Feature
|
||||
with InitFeature
|
||||
with NodeFeature {
|
||||
with NodeFeature
|
||||
with ChannelTypeFeature {
|
||||
val rfcName = "option_anchors_zero_fee_htlc_tx"
|
||||
val mandatory = 22
|
||||
}
|
||||
|
||||
case object RouteBlinding
|
||||
extends Feature
|
||||
with InitFeature
|
||||
with NodeFeature
|
||||
with InvoiceFeature {
|
||||
val rfcName = "option_route_blinding"
|
||||
val mandatory = 24
|
||||
}
|
||||
|
||||
case object ShutdownAnySegwit
|
||||
extends Feature
|
||||
with InitFeature
|
||||
|
@ -235,7 +267,11 @@ object Features {
|
|||
val mandatory = 26
|
||||
}
|
||||
|
||||
case object DualFunding extends Feature with InitFeature with NodeFeature {
|
||||
case object DualFunding
|
||||
extends Feature
|
||||
with InitFeature
|
||||
with NodeFeature
|
||||
with PermanentChannelFeature {
|
||||
val rfcName = "option_dual_fund"
|
||||
val mandatory = 28
|
||||
}
|
||||
|
@ -250,11 +286,29 @@ object Features {
|
|||
val mandatory = 44
|
||||
}
|
||||
|
||||
case object ScidAlias
|
||||
extends Feature
|
||||
with InitFeature
|
||||
with NodeFeature
|
||||
with ChannelTypeFeature {
|
||||
val rfcName = "option_scid_alias"
|
||||
val mandatory = 46
|
||||
}
|
||||
|
||||
case object PaymentMetadata extends Feature with InvoiceFeature {
|
||||
val rfcName = "option_payment_metadata"
|
||||
val mandatory = 48
|
||||
}
|
||||
|
||||
case object ZeroConf
|
||||
extends Feature
|
||||
with InitFeature
|
||||
with NodeFeature
|
||||
with ChannelTypeFeature {
|
||||
val rfcName = "option_zeroconf"
|
||||
val mandatory = 50
|
||||
}
|
||||
|
||||
case object KeySend extends Feature with NodeFeature {
|
||||
val rfcName = "keysend"
|
||||
val mandatory = 54
|
||||
|
@ -275,6 +329,15 @@ object Features {
|
|||
val mandatory = 148
|
||||
}
|
||||
|
||||
// TODO: @remyers update feature bits once spec-ed (currently reserved here: https://github.com/lightning/bolts/pull/989)
|
||||
case object AsyncPaymentPrototype
|
||||
extends Feature
|
||||
with InitFeature
|
||||
with InvoiceFeature {
|
||||
val rfcName = "async_payment_prototype"
|
||||
val mandatory = 152
|
||||
}
|
||||
|
||||
val knownFeatures: Set[Feature] = Set(
|
||||
DataLossProtect,
|
||||
InitialRoutingSync,
|
||||
|
@ -288,13 +351,17 @@ object Features {
|
|||
StaticRemoteKey,
|
||||
AnchorOutputs,
|
||||
AnchorOutputsZeroFeeHtlcTx,
|
||||
RouteBlinding,
|
||||
ShutdownAnySegwit,
|
||||
DualFunding,
|
||||
OnionMessages,
|
||||
ChannelType,
|
||||
ScidAlias,
|
||||
PaymentMetadata,
|
||||
ZeroConf,
|
||||
KeySend,
|
||||
TrampolinePaymentPrototype,
|
||||
KeySend
|
||||
AsyncPaymentPrototype
|
||||
)
|
||||
|
||||
// Features may depend on other features, as specified in Bolt 9.
|
||||
|
@ -304,9 +371,10 @@ object Features {
|
|||
BasicMultiPartPayment -> (PaymentSecret :: Nil),
|
||||
AnchorOutputs -> (StaticRemoteKey :: Nil),
|
||||
AnchorOutputsZeroFeeHtlcTx -> (StaticRemoteKey :: Nil),
|
||||
DualFunding -> (AnchorOutputsZeroFeeHtlcTx :: Nil),
|
||||
RouteBlinding -> (VariableLengthOnion :: Nil),
|
||||
TrampolinePaymentPrototype -> (PaymentSecret :: Nil),
|
||||
KeySend -> (VariableLengthOnion :: Nil)
|
||||
KeySend -> (VariableLengthOnion :: Nil),
|
||||
AsyncPaymentPrototype -> (TrampolinePaymentPrototype :: Nil)
|
||||
)
|
||||
|
||||
case class FeatureException(message: String)
|
||||
|
|
|
@ -226,13 +226,20 @@ class EclairRpcClientTest extends BitcoinSAsyncTest {
|
|||
paymentId,
|
||||
duration = 1.second)
|
||||
|
||||
received <- client4.audit()
|
||||
relayed <- client2.audit()
|
||||
sent <- client1.audit()
|
||||
_ <- TestAsyncUtil.retryUntilSatisfiedF(
|
||||
conditionF = () => client4.audit().map(_.received.nonEmpty),
|
||||
interval = 1.second,
|
||||
maxTries = 60)
|
||||
_ <- TestAsyncUtil.retryUntilSatisfiedF(
|
||||
conditionF = () => client2.audit().map(_.relayed.nonEmpty),
|
||||
interval = 1.second,
|
||||
maxTries = 60)
|
||||
_ <- TestAsyncUtil.retryUntilSatisfiedF(
|
||||
conditionF = () => client1.audit().map(_.sent.nonEmpty),
|
||||
interval = 1.second,
|
||||
maxTries = 60)
|
||||
} yield {
|
||||
assert(sent.sent.nonEmpty)
|
||||
assert(received.received.nonEmpty)
|
||||
assert(relayed.relayed.nonEmpty)
|
||||
succeed
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -964,11 +971,16 @@ class EclairRpcClientTest extends BitcoinSAsyncTest {
|
|||
.map(_.collect { case open: OpenChannelInfo =>
|
||||
open
|
||||
})
|
||||
|
||||
ourChannelUpdates <- firstFreshClient.allUpdates(nodeId)
|
||||
_ <- AsyncUtil
|
||||
.retryUntilSatisfiedF(
|
||||
(() => {
|
||||
firstFreshClient
|
||||
.allUpdates(nodeId)
|
||||
.map(_.forall(updateIsInChannels(ourOpenChannels)))
|
||||
}),
|
||||
interval = 1.second,
|
||||
maxTries = 60)
|
||||
} yield {
|
||||
assert(ourChannelUpdates.forall(updateIsInChannels(ourOpenChannels)))
|
||||
|
||||
succeed
|
||||
}
|
||||
}
|
||||
|
@ -1161,10 +1173,16 @@ class EclairRpcClientTest extends BitcoinSAsyncTest {
|
|||
c <- clientF
|
||||
res <- c.listInvoices(from = None, to = Some(Instant.now()))
|
||||
i <- c.createInvoice(description = "abc")
|
||||
pending <- c.listPendingInvoices(from = None, to = None)
|
||||
_ = Thread.sleep(1000 * 5)
|
||||
_ <- AsyncUtil
|
||||
.retryUntilSatisfiedF(
|
||||
(() => {
|
||||
c.listPendingInvoices(from = None, to = None).map(_.contains(i))
|
||||
}),
|
||||
interval = 1.second,
|
||||
maxTries = 60)
|
||||
} yield {
|
||||
assert(res.nonEmpty)
|
||||
assert(pending.contains(i))
|
||||
assert(!res.contains(i))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ TaskKeys.downloadEclair := {
|
|||
Files.createDirectories(binaryDir)
|
||||
}
|
||||
|
||||
val version = "0.7.0"
|
||||
val commit = "a804905"
|
||||
val version = "0.8.0"
|
||||
val commit = "0077471"
|
||||
|
||||
logger.debug(s"(Maybe) downloading Eclair binaries for version: $version")
|
||||
|
||||
|
@ -48,7 +48,7 @@ TaskKeys.downloadEclair := {
|
|||
.mkString
|
||||
|
||||
val expectedHash =
|
||||
"482a00cc597fd4cc471a1b4035c72a440a9ab336ef5b9006629d2fd717b223b4"
|
||||
"d279317de25ba86b275183160d83acd064647371c446a35601397ae87ee04abb"
|
||||
|
||||
val success = hash.equalsIgnoreCase(expectedHash)
|
||||
if (success) {
|
||||
|
|
|
@ -272,7 +272,9 @@ trait EclairApi {
|
|||
|
||||
def onChainBalance(): Future[OnChainBalance]
|
||||
|
||||
def onChainTransactions(): Future[Vector[WalletTransaction]]
|
||||
def onChainTransactions(
|
||||
count: Int,
|
||||
skip: Int): Future[Vector[WalletTransaction]]
|
||||
|
||||
def sendOnChain(
|
||||
address: BitcoinAddress,
|
||||
|
|
|
@ -608,8 +608,12 @@ class EclairRpcClient(
|
|||
eclairCall[OnChainBalance]("onchainbalance")
|
||||
}
|
||||
|
||||
override def onChainTransactions(): Future[Vector[WalletTransaction]] = {
|
||||
eclairCall[Vector[WalletTransaction]]("onchaintransactions")
|
||||
override def onChainTransactions(
|
||||
count: Int = 10,
|
||||
skip: Int = 0): Future[Vector[WalletTransaction]] = {
|
||||
eclairCall[Vector[WalletTransaction]]("onchaintransactions",
|
||||
"count" -> count.toString,
|
||||
"skip" -> skip.toString)
|
||||
}
|
||||
|
||||
override def sendOnChain(
|
||||
|
@ -953,13 +957,13 @@ object EclairRpcClient {
|
|||
implicit system: ActorSystem) = new EclairRpcClient(instance, binary)
|
||||
|
||||
/** The current commit we support of Eclair */
|
||||
private[bitcoins] val commit = "a804905"
|
||||
private[bitcoins] val commit = "0077471"
|
||||
|
||||
/** The current version we support of Eclair */
|
||||
private[bitcoins] val version = "0.7.0"
|
||||
private[bitcoins] val version = "0.8.0"
|
||||
|
||||
/** The bitcoind version that eclair is officially tested & supported with by ACINQ
|
||||
* @see https://github.com/ACINQ/eclair/releases/tag/v0.6.2
|
||||
* @see https://github.com/ACINQ/eclair/releases/tag/v0.8.0
|
||||
*/
|
||||
val bitcoindV: BitcoindVersion = BitcoindVersion.V21
|
||||
val bitcoindV: BitcoindVersion = BitcoindVersion.V23
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue