mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-19 01:40:55 +01:00
2024 04 29 eclair upgrade v0.9.0
(#5556)
* Rework EclairRpcTestUtil.shutdown() to shutdown eclair/bitcoind separately * Fix keysend test * Add new eclair websocket events * Empty commit to re-run CI * First bug where we weren't shutting down a bitcoind in eclairRpcTest
This commit is contained in:
parent
819a047d1e
commit
7ee749adcb
@ -7,12 +7,14 @@ import org.bitcoins.core.protocol.ln.channel.{
|
||||
ChannelId,
|
||||
ChannelState,
|
||||
FundedChannelId,
|
||||
ShortChannelId
|
||||
ShortChannelId,
|
||||
TempChannelId
|
||||
}
|
||||
import org.bitcoins.core.protocol.ln.currency.MilliSatoshis
|
||||
import org.bitcoins.core.protocol.ln.fee.FeeProportionalMillionths
|
||||
import org.bitcoins.core.protocol.ln.node.{Feature, FeatureSupport, NodeId}
|
||||
import org.bitcoins.core.protocol.ln.{LnHumanReadablePart, PaymentPreimage}
|
||||
import org.bitcoins.core.wallet.fee.SatoshisPerKW
|
||||
import org.bitcoins.crypto._
|
||||
import play.api.libs.json.JsObject
|
||||
|
||||
@ -459,6 +461,26 @@ object WebSocketEvent {
|
||||
timestamp: Instant // milliseconds
|
||||
) extends WebSocketEvent
|
||||
|
||||
case class ChannelStateChange(
|
||||
channelId: FundedChannelId,
|
||||
remoteNodeId: NodeId,
|
||||
previousState: ChannelState,
|
||||
currentState: ChannelState)
|
||||
extends WebSocketEvent
|
||||
|
||||
case class ChannelCreated(
|
||||
remoteNodeId: NodeId,
|
||||
isInitiator: Boolean,
|
||||
temporaryChannelId: TempChannelId,
|
||||
commitTxFeeratePerKw: SatoshisPerKW,
|
||||
fundingTxFeeratePerKw: Option[SatoshisPerKW])
|
||||
extends WebSocketEvent
|
||||
|
||||
case class ChannelOpened(remoteNodeId: NodeId, channelId: FundedChannelId)
|
||||
extends WebSocketEvent
|
||||
|
||||
case class ChannelClosed(channelId: FundedChannelId, closingType: String)
|
||||
extends WebSocketEvent
|
||||
}
|
||||
|
||||
case class OnChainBalance(confirmed: Satoshis, unconfirmed: Satoshis)
|
||||
|
@ -7,6 +7,12 @@ import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.{
|
||||
}
|
||||
import org.bitcoins.commons.jsonmodels.bitcoind._
|
||||
import org.bitcoins.commons.jsonmodels.clightning.CLightningJsonModels._
|
||||
import org.bitcoins.commons.jsonmodels.eclair.WebSocketEvent.{
|
||||
ChannelClosed,
|
||||
ChannelCreated,
|
||||
ChannelOpened,
|
||||
ChannelStateChange
|
||||
}
|
||||
import org.bitcoins.commons.jsonmodels.eclair._
|
||||
import org.bitcoins.commons.serializers.JsonSerializers._
|
||||
import org.bitcoins.core.config._
|
||||
@ -51,6 +57,12 @@ import scala.util.{Failure, Success, Try}
|
||||
|
||||
object JsonReaders {
|
||||
|
||||
implicit val byteVectorReads: Reads[ByteVector] = {
|
||||
Reads { jsValue =>
|
||||
SerializerUtil.processJsStringOpt(str => ByteVector.fromHex(str))(jsValue)
|
||||
}
|
||||
}
|
||||
|
||||
/** Tries to prase the provided JSON into a map with keys of type `K` and
|
||||
* values of type `V`
|
||||
*/
|
||||
@ -733,6 +745,13 @@ object JsonReaders {
|
||||
SatoshisPerVirtualByte.fromLong(num.toLong))(json)
|
||||
}
|
||||
|
||||
implicit object SatoshisPerKWReads extends Reads[SatoshisPerKW] {
|
||||
override def reads(json: JsValue): JsResult[SatoshisPerKW] = {
|
||||
SerializerUtil.processJsNumberBigInt(num =>
|
||||
SatoshisPerKW(Satoshis(num.toLong)))(json)
|
||||
}
|
||||
}
|
||||
|
||||
implicit object FileReads extends Reads[File] {
|
||||
|
||||
override def reads(json: JsValue): JsResult[File] =
|
||||
@ -967,6 +986,15 @@ object JsonReaders {
|
||||
implicit val realChannelIdReads: Reads[RealChannelId] =
|
||||
Json.reads[RealChannelId]
|
||||
|
||||
implicit val tempChannelIdReads: Reads[TempChannelId] =
|
||||
Reads {
|
||||
case string: JsString =>
|
||||
byteVectorReads.reads(string).map(TempChannelId(_))
|
||||
case x @ (_: JsBoolean | _: JsNumber | _: JsArray | _: JsObject |
|
||||
JsNull) =>
|
||||
JsError(s"Invalid json type for tempChannelId, got=$x")
|
||||
}
|
||||
|
||||
implicit val shortIdsReads: Reads[ShortIds] =
|
||||
Json.reads[ShortIds]
|
||||
|
||||
@ -1045,11 +1073,13 @@ object JsonReaders {
|
||||
.validate[ShortChannelId]
|
||||
channelId <- (jsValue \ "channelId").validate[FundedChannelId]
|
||||
state <- (jsValue \ "state").validate[ChannelState.NORMAL.type]
|
||||
active <- (jsValue \ "data" \ "commitments" \ "active")
|
||||
.validate[Vector[JsObject]]
|
||||
remoteMsat <-
|
||||
(jsValue \ "data" \ "commitments" \ "localCommit" \ "spec" \ "toRemote")
|
||||
(active.head \ "localCommit" \ "spec" \ "toRemote")
|
||||
.validate[MilliSatoshis]
|
||||
localMsat <-
|
||||
(jsValue \ "data" \ "commitments" \ "localCommit" \ "spec" \ "toLocal")
|
||||
(active.head \ "localCommit" \ "spec" \ "toLocal")
|
||||
.validate[MilliSatoshis]
|
||||
|
||||
} yield OpenChannelInfo(
|
||||
@ -1067,11 +1097,13 @@ object JsonReaders {
|
||||
nodeId <- (jsValue \ "nodeId").validate[NodeId]
|
||||
channelId <- (jsValue \ "channelId").validate[FundedChannelId]
|
||||
state <- (jsValue \ "state").validate[ChannelState]
|
||||
active <- (jsValue \ "data" \ "commitments" \ "active")
|
||||
.validate[Vector[JsObject]]
|
||||
remoteMsat <-
|
||||
(jsValue \ "data" \ "commitments" \ "localCommit" \ "spec" \ "toRemote")
|
||||
(active.head \ "localCommit" \ "spec" \ "toRemote")
|
||||
.validate[MilliSatoshis]
|
||||
localMsat <-
|
||||
(jsValue \ "data" \ "commitments" \ "localCommit" \ "spec" \ "toLocal")
|
||||
(active.head \ "localCommit" \ "spec" \ "toLocal")
|
||||
.validate[MilliSatoshis]
|
||||
|
||||
} yield BaseChannelInfo(
|
||||
@ -1576,6 +1608,22 @@ object JsonReaders {
|
||||
)
|
||||
}
|
||||
|
||||
implicit val channelStateChangeReads: Reads[ChannelStateChange] = {
|
||||
Json.reads[ChannelStateChange]
|
||||
}
|
||||
|
||||
implicit val channelCreatedReads: Reads[ChannelCreated] = {
|
||||
Json.reads[ChannelCreated]
|
||||
}
|
||||
|
||||
implicit val channelClosedReads: Reads[ChannelClosed] = {
|
||||
Json.reads[ChannelClosed]
|
||||
}
|
||||
|
||||
implicit val channelOpenReads: Reads[ChannelOpened] = {
|
||||
Json.reads[ChannelOpened]
|
||||
}
|
||||
|
||||
implicit val webSocketEventReads: Reads[WebSocketEvent] =
|
||||
Reads { js =>
|
||||
(js \ "type")
|
||||
@ -1589,6 +1637,14 @@ object JsonReaders {
|
||||
js.validate[WebSocketEvent.PaymentSent]
|
||||
case "payment-settling-onchain" =>
|
||||
js.validate[WebSocketEvent.PaymentSettlingOnchain]
|
||||
case "channel-state-changed" =>
|
||||
js.validate[WebSocketEvent.ChannelStateChange]
|
||||
case "channel-created" =>
|
||||
js.validate[WebSocketEvent.ChannelCreated]
|
||||
case "channel-opened" =>
|
||||
js.validate[WebSocketEvent.ChannelOpened]
|
||||
case "channel-closed" =>
|
||||
js.validate[WebSocketEvent.ChannelClosed]
|
||||
}
|
||||
}
|
||||
|
||||
@ -1608,12 +1664,6 @@ object JsonReaders {
|
||||
throw Value.InvalidData(js, "Expected value in Satoshis")
|
||||
}
|
||||
|
||||
implicit val byteVectorReads: Reads[ByteVector] = {
|
||||
Reads { jsValue =>
|
||||
SerializerUtil.processJsStringOpt(str => ByteVector.fromHex(str))(jsValue)
|
||||
}
|
||||
}
|
||||
|
||||
implicit val outputStatusReads: Reads[OutputStatus] = {
|
||||
Reads { jsValue =>
|
||||
SerializerUtil.processJsStringOpt(OutputStatus.fromStringOpt)(jsValue)
|
||||
|
@ -29,6 +29,7 @@ import org.bitcoins.eclair.rpc.config.{
|
||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||
import org.bitcoins.testkit.async.TestAsyncUtil
|
||||
import org.bitcoins.testkit.eclair.rpc.{EclairNodes4, EclairRpcTestUtil}
|
||||
import org.bitcoins.testkit.rpc.BitcoindRpcTestUtil
|
||||
import org.bitcoins.testkit.util.{BitcoinSAsyncTest, EclairRpcTestClient}
|
||||
import org.scalatest.Assertion
|
||||
|
||||
@ -425,14 +426,17 @@ class EclairRpcClientTest extends BitcoinSAsyncTest {
|
||||
}
|
||||
|
||||
it should "be able to start and shutdown a node" in {
|
||||
val eclairTestClient =
|
||||
val eclairTestClientF = for {
|
||||
bitcoind <- bitcoindRpcClientF
|
||||
} yield {
|
||||
EclairRpcTestClient.fromSbtDownload(
|
||||
eclairVersionOpt = None,
|
||||
eclairCommitOpt = None,
|
||||
bitcoindRpcClientOpt = None
|
||||
bitcoindRpcClientOpt = Some(bitcoind)
|
||||
)
|
||||
}
|
||||
for {
|
||||
eclair <- eclairTestClient.start()
|
||||
eclair <- eclairTestClientF.flatMap(_.start())
|
||||
_ <- TestAsyncUtil.retryUntilSatisfiedF(
|
||||
conditionF = () => eclair.isStarted(),
|
||||
interval = 1.second,
|
||||
@ -1326,7 +1330,12 @@ class EclairRpcClientTest extends BitcoinSAsyncTest {
|
||||
}
|
||||
|
||||
override def afterAll(): Unit = {
|
||||
clients.result().foreach(EclairRpcTestUtil.shutdown)
|
||||
val resultF = for {
|
||||
_ <- Future.traverse(clients.result())(EclairRpcTestUtil.shutdown)
|
||||
bitcoind <- bitcoindRpcClientF
|
||||
_ <- BitcoindRpcTestUtil.stopServer(bitcoind)
|
||||
} yield ()
|
||||
val _ = Await.result(resultF, 30.second)
|
||||
super.afterAll()
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,12 @@ package org.bitcoins.eclair.rpc
|
||||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.bitcoins.eclair.rpc.client.EclairRpcClient
|
||||
import org.bitcoins.testkit.eclair.rpc.EclairRpcTestUtil
|
||||
import org.bitcoins.testkit.rpc.BitcoindRpcTestUtil
|
||||
import org.bitcoins.testkit.util.BitcoinSAsyncTest
|
||||
|
||||
import scala.concurrent.duration.DurationInt
|
||||
import scala.concurrent.{Await, Future}
|
||||
|
||||
class EclairRpcTestUtilTest extends BitcoinSAsyncTest {
|
||||
|
||||
implicit private val actorSystem: ActorSystem =
|
||||
@ -21,7 +25,12 @@ class EclairRpcTestUtilTest extends BitcoinSAsyncTest {
|
||||
Vector.newBuilder[EclairRpcClient]
|
||||
|
||||
override def afterAll(): Unit = {
|
||||
clients.result().foreach(EclairRpcTestUtil.shutdown)
|
||||
val resultF = for {
|
||||
_ <- Future.traverse(clients.result())(EclairRpcTestUtil.shutdown)
|
||||
bitcoind <- bitcoindRpcF
|
||||
_ <- BitcoindRpcTestUtil.stopServer(bitcoind)
|
||||
} yield ()
|
||||
val _ = Await.result(resultF, 30.second)
|
||||
super.afterAll()
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,8 @@ TaskKeys.downloadEclair := {
|
||||
Files.createDirectories(binaryDir)
|
||||
}
|
||||
|
||||
val version = "0.8.0"
|
||||
val commit = "0077471"
|
||||
val version = "0.9.0"
|
||||
val commit = "623f7e4"
|
||||
|
||||
logger.debug(s"(Maybe) downloading Eclair binaries for version: $version")
|
||||
|
||||
@ -48,7 +48,7 @@ TaskKeys.downloadEclair := {
|
||||
.mkString
|
||||
|
||||
val expectedHash =
|
||||
"d279317de25ba86b275183160d83acd064647371c446a35601397ae87ee04abb"
|
||||
"249604de45c54dc48f02c7335b49ff2896334fd44541dbb175e56aff66054cdc"
|
||||
|
||||
val success = hash.equalsIgnoreCase(expectedHash)
|
||||
if (success) {
|
||||
|
@ -263,9 +263,10 @@ class EclairRpcClient(
|
||||
// this is unfortunately returned in this format
|
||||
// created channel 30bdf849eb9f72c9b41a09e38a6d83138c2edf332cb116dd7cf0f0dfb66be395
|
||||
val call = eclairCall[String]("open", params: _*)
|
||||
|
||||
// let's just return the chanId
|
||||
val chanIdF = call.map(_.split(" ").last)
|
||||
// format:
|
||||
// created channel 19e11470b0dd96ed15c56ea8f32e9a3277dcbd570e7392c1c34709adc7ebfdc3 with fundingTxId=c2fdebc7ad0947c3c192730e57bddc77329a2ef3a86ec515ed96ddb07014e119 and fees=24750 sat
|
||||
val chanIdF = call.map(_.split(" ")(2))
|
||||
|
||||
chanIdF.map(FundedChannelId.fromHex)
|
||||
}
|
||||
@ -1080,10 +1081,10 @@ object EclairRpcClient {
|
||||
) = new EclairRpcClient(instance, binary)
|
||||
|
||||
/** The current commit we support of Eclair */
|
||||
private[bitcoins] val commit = "0077471"
|
||||
private[bitcoins] val commit = "623f7e4"
|
||||
|
||||
/** The current version we support of Eclair */
|
||||
private[bitcoins] val version = "0.8.0"
|
||||
private[bitcoins] val version = "0.9.0"
|
||||
|
||||
/** The bitcoind version that eclair is officially tested & supported with by
|
||||
* ACINQ
|
||||
|
@ -20,7 +20,7 @@
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="OFF">
|
||||
<root level="INFO">
|
||||
<appender-ref ref="FILE"/>
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
|
@ -793,33 +793,29 @@ trait EclairRpcTestUtil extends BitcoinSLogger {
|
||||
info <- client.getInfo
|
||||
} yield info.blockHeight == blockCount
|
||||
|
||||
/** Shuts down an eclair daemon and the bitcoind daemon it is associated with
|
||||
*/
|
||||
/** Shuts down an eclair daemon */
|
||||
def shutdown(
|
||||
eclairRpcClient: EclairRpcClient
|
||||
)(implicit system: ActorSystem): Future[Unit] = {
|
||||
import system.dispatcher
|
||||
val bitcoindRpc = getBitcoindRpc(eclairRpcClient)
|
||||
|
||||
logger.debug(s"shutting down eclair")
|
||||
val stopEclairF = eclairRpcClient.stop()
|
||||
val killBitcoindF = BitcoindRpcTestUtil.stopServer(bitcoindRpc)
|
||||
val iskilled = eclairRpcClient.isStopped
|
||||
|
||||
val shutdownF = for {
|
||||
_ <- killBitcoindF
|
||||
_ <- stopEclairF
|
||||
_ <- iskilled
|
||||
} yield {
|
||||
logger.debug(
|
||||
"Successfully shutdown eclair and it's corresponding bitcoind"
|
||||
"Successfully shutdown eclair"
|
||||
)
|
||||
}
|
||||
shutdownF.failed.foreach { err: Throwable =>
|
||||
logger.info(
|
||||
s"Killed a bitcoind instance, but could not find an eclair process to kill"
|
||||
logger.error(
|
||||
s"Could kill eclair process",
|
||||
err
|
||||
)
|
||||
throw err
|
||||
}
|
||||
shutdownF
|
||||
}
|
||||
|
@ -352,7 +352,7 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
||||
servers: Vector[BitcoindRpcClient]
|
||||
)(implicit system: ActorSystem): Future[Unit] = {
|
||||
implicit val ec: ExecutionContextExecutor = system.getDispatcher
|
||||
|
||||
logger.info(s"Shutting down ${servers.length} bitcoinds")
|
||||
val serverStopsF = Future.traverse(servers) { s =>
|
||||
val stopF = s.stop()
|
||||
stopF.onComplete {
|
||||
@ -366,7 +366,10 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
||||
_ <- removeDataDirectory(s)
|
||||
} yield ()
|
||||
}
|
||||
serverStopsF.map(_ => ())
|
||||
serverStopsF.map { _ =>
|
||||
logger.info(s"Done shutting down ${servers.length} bitcoinds")
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
/** Stops the given server and deletes its data directory
|
||||
|
Loading…
Reference in New Issue
Block a user