diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/Main.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/Main.kt index 8a6bdc7..894b6b2 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/Main.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/Main.kt @@ -18,12 +18,15 @@ import com.github.ajalt.clikt.sources.MapValueSource import com.github.ajalt.mordant.rendering.TextColors.* import com.github.ajalt.mordant.rendering.TextStyles.bold import fr.acinq.bitcoin.Chain +import fr.acinq.bitcoin.MnemonicCode import fr.acinq.lightning.BuildVersions import fr.acinq.lightning.Lightning.randomBytes32 import fr.acinq.lightning.LiquidityEvents import fr.acinq.lightning.NodeParams import fr.acinq.lightning.PaymentEvents +import fr.acinq.lightning.bin.conf.EnvVars.PHOENIX_SEED import fr.acinq.lightning.bin.conf.LSP +import fr.acinq.lightning.bin.conf.PhoenixSeed import fr.acinq.lightning.bin.conf.getOrGenerateSeed import fr.acinq.lightning.bin.conf.readConfFile import fr.acinq.lightning.bin.db.SqliteChannelsDb @@ -47,6 +50,7 @@ import fr.acinq.lightning.payment.LiquidityPolicy import fr.acinq.lightning.utils.Connection import fr.acinq.lightning.utils.msat import fr.acinq.lightning.utils.sat +import fr.acinq.lightning.utils.toByteVector import fr.acinq.phoenix.db.* import io.ktor.http.* import io.ktor.server.application.* @@ -69,6 +73,17 @@ fun main(args: Array) = Phoenixd() class Phoenixd : CliktCommand() { private val confFile = datadir / "phoenix.conf" + private val seed by option("--seed", help = "Manually provide a 12-words seed", hidden = true, envvar = PHOENIX_SEED) + .convert { PhoenixSeed(MnemonicCode.toSeed(it, "").toByteVector(), isNew = false) } + .defaultLazy { + val value = getOrGenerateSeed(datadir) + if (value.isNew) { + terminal.print(yellow("Generating new seed...")) + runBlocking { delay(500.milliseconds) } + terminal.println(white("done")) + } + value + } private val chain by option("--chain", help = "Bitcoin chain to use").choice( "mainnet" to Chain.Mainnet, "testnet" to Chain.Testnet ).default(Chain.Mainnet, defaultForHelp = "mainnet") @@ -155,13 +170,8 @@ class Phoenixd : CliktCommand() { @OptIn(DelicateCoroutinesApi::class) override fun run() { FileSystem.SYSTEM.createDirectories(datadir) - val (seed, new) = getOrGenerateSeed(datadir) - if (new) { + if (seed.isNew) { runBlocking { - terminal.print(yellow("Generating new seed...")) - delay(500.milliseconds) - terminal.println(white("done")) - terminal.println() terminal.println(green("Backup")) terminal.println("This software is self-custodial, you have full control and responsibility over your funds.") terminal.println("Your 12-words seed is located in ${FileSystem.SYSTEM.canonicalize(datadir)}, ${bold(red("make sure to do a backup or you risk losing your funds"))}.") @@ -215,7 +225,7 @@ class Phoenixd : CliktCommand() { skipAbsoluteFeeCheck = false, maxAllowedCredit = liquidityOptions.maxFeeCredit ) - val keyManager = LocalKeyManager(seed, chain, lsp.swapInXpub) + val keyManager = LocalKeyManager(seed.seed, chain, lsp.swapInXpub) val nodeParams = NodeParams(chain, loggerFactory, keyManager) .copy( zeroConfPeers = setOf(lsp.walletParams.trampolineNode.id), diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/conf/EnvVars.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/conf/EnvVars.kt index ef6e0c0..34c28c3 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/conf/EnvVars.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/conf/EnvVars.kt @@ -2,4 +2,5 @@ package fr.acinq.lightning.bin.conf object EnvVars { const val PHOENIX_DATADIR = "PHOENIX_DATADIR" + const val PHOENIX_SEED = "PHOENIX_SEED" } \ No newline at end of file diff --git a/src/commonMain/kotlin/fr/acinq/lightning/bin/conf/Seed.kt b/src/commonMain/kotlin/fr/acinq/lightning/bin/conf/Seed.kt index f5adb04..fbd5c6e 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/bin/conf/Seed.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/bin/conf/Seed.kt @@ -1,18 +1,21 @@ package fr.acinq.lightning.bin.conf import fr.acinq.bitcoin.ByteVector +import fr.acinq.bitcoin.ByteVector32 import fr.acinq.bitcoin.MnemonicCode import fr.acinq.lightning.Lightning.randomBytes import fr.acinq.lightning.utils.toByteVector import okio.FileSystem import okio.Path +data class PhoenixSeed(val seed: ByteVector, val isNew: Boolean) + /** * @return a pair with the seed and a boolean indicating whether the seed was newly generated */ -fun getOrGenerateSeed(dir: Path): Pair { +fun getOrGenerateSeed(dir: Path): PhoenixSeed { val file = dir / "seed.dat" - val (mnemonics, new) = if (FileSystem.SYSTEM.exists(file)) { + val (mnemonics, isNew) = if (FileSystem.SYSTEM.exists(file)) { FileSystem.SYSTEM.read(file) { readUtf8() } to false } else { val entropy = randomBytes(16) @@ -20,5 +23,5 @@ fun getOrGenerateSeed(dir: Path): Pair { FileSystem.SYSTEM.write(file) { writeUtf8(mnemonics) } mnemonics to true } - return MnemonicCode.toSeed(mnemonics, "").toByteVector() to new + return PhoenixSeed(seed = MnemonicCode.toSeed(mnemonics, "").toByteVector(), isNew = isNew) } \ No newline at end of file