Skip to content

Commit

Permalink
Allow specifying a bitcoin wallet with an empty name (#2737)
Browse files Browse the repository at this point in the history
We make the distinction between _not_ defining a bitcoin wallet name, and using an bitcoin wallet with an _empty_ name.

This remains mostly backward compatible, as:
- by default `eclair.bitcoind.wallet` is undefined so we keep using the default loaded wallet as before
- if user already set `eclair.bitcoind.wallet`, then eclair will use that wallet.
- only in the case where the user left `eclair.bitcoind.wallet` undefined, and if bitcoin had only one wallet with a non-empty name, then eclair will fail right at startup with an explicit error

---------

Co-authored-by: Bastien Teinturier <31281497+t-bast@users.noreply.github.com>
  • Loading branch information
pm47 and t-bast committed Sep 21, 2023
1 parent 6f87137 commit 4e339aa
Show file tree
Hide file tree
Showing 5 changed files with 8 additions and 10 deletions.
4 changes: 2 additions & 2 deletions eclair-core/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ eclair {
rpcpassword = "bar"
// Name of the bitcoind wallet that should be used to fund channels.
// Once set you should NOT change it if your node has channels open, otherwise you may lose funds.
// NB: leave empty to automatically select the default loaded wallet.
wallet = ""
// NB: leave this field commented to automatically select the default loaded wallet.
// wallet = ""
zmqblock = "tcp://127.0.0.1:29000"
zmqtx = "tcp://127.0.0.1:29000"
// Batching requests saves bandwidth but may slightly degrade latency and reliability. It is useful for the watcher,
Expand Down
5 changes: 1 addition & 4 deletions eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,7 @@ class Setup(val datadir: File,
val onChainKeyManager_opt = LocalOnChainKeyManager.load(datadir, NodeParams.hashFromChain(chain))

val (bitcoin, bitcoinChainHash) = {
val wallet = {
val name = config.getString("bitcoind.wallet")
if (!name.isBlank) Some(name) else None
}
val wallet = if (config.hasPath("bitcoind.wallet")) Some(config.getString("bitcoind.wallet")) else None
val rpcAuthMethod = config.getString("bitcoind.auth") match {
case "safecookie" => BitcoinJsonRPCAuthMethod.readCookie(config.getString("bitcoind.cookie")) match {
case Success(safeCookie) => safeCookie
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ object Monitoring {

object Tags {
val Method = "method"
val Wallet = "wallet"
val Priority = "priority"

object Priorities {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ class BasicBitcoinJsonRPCClient(rpcAuthMethod: BitcoinJsonRPCAuthMethod, host: S

private def send(requests: Seq[JsonRPCRequest], user: String, password: String)(implicit ec: ExecutionContext): Future[Response[Either[ResponseException[String, Exception], Seq[JsonRPCResponse]]]] = {
requests.groupBy(_.method).foreach {
case (method, calls) => Metrics.RpcBasicInvokeCount.withTag(Tags.Method, method).increment(calls.size)
case (method, calls) => Metrics.RpcBasicInvokeCount.withTag(Tags.Method, method).withTag(Tags.Wallet, wallet.getOrElse("default")).increment(calls.size)
}
// for the duration metric, we use a "mixed" method for batched requests
KamonExt.timeFuture(Metrics.RpcBasicInvokeDuration.withTag(Tags.Method, if (requests.size == 1) requests.head.method else "mixed")) {
KamonExt.timeFuture(Metrics.RpcBasicInvokeDuration.withTag(Tags.Method, if (requests.size == 1) requests.head.method else "mixed").withTag(Tags.Wallet, wallet.getOrElse("default"))) {
for {
response <- basicRequest
.post(serviceUri)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ import scala.jdk.CollectionConverters._
class StartupIntegrationSpec extends IntegrationSpec {

test("no bitcoind wallet configured and one wallet loaded") {
instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.bitcoind.wallet" -> "", "eclair.server.port" -> TestUtils.availablePort).asJava).withFallback(withDefaultCommitment).withFallback(commonConfig))
instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.server.port" -> TestUtils.availablePort).asJava).withFallback(withDefaultCommitment).withFallback(commonConfig).withoutPath("eclair.bitcoind.wallet"))
}

test("no bitcoind wallet configured and two wallets loaded") {
val sender = TestProbe()
sender.send(bitcoincli, BitcoinReq("createwallet", ""))
sender.expectMsgType[Any]
val thrown = intercept[BitcoinDefaultWalletException] {
instantiateEclairNode("C", ConfigFactory.parseMap(Map("eclair.bitcoind.wallet" -> "", "eclair.server.port" -> TestUtils.availablePort).asJava).withFallback(withDefaultCommitment).withFallback(commonConfig))
instantiateEclairNode("C", ConfigFactory.parseMap(Map("eclair.server.port" -> TestUtils.availablePort).asJava).withFallback(withDefaultCommitment).withFallback(commonConfig).withoutPath("eclair.bitcoind.wallet"))
}
assert(thrown == BitcoinDefaultWalletException(List(defaultWallet, "")))
}
Expand Down

0 comments on commit 4e339aa

Please sign in to comment.