Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ldk-node"
version = "0.7.0-rc.2"
version = "0.7.0-rc.3"
authors = ["Elias Rohrer <dev@tnull.de>"]
homepage = "https://lightningdevkit.org/"
license = "MIT OR Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import PackageDescription

let tag = "v0.7.0-rc.2"
let checksum = "02b7edc2f3fcf2b8a1c914bd1f03e8a3bf2aca2281a2314d0d03cb7547ecd11a"
let checksum = "328ce1018daa21c07b7e9e2a6d63f3a8a3821619408f3edbcc78a448c102233b"
let url = "https://github.com/synonymdev/ldk-node/releases/download/\(tag)/LDKNodeFFI.xcframework.zip"

let package = Package(
Expand Down
2 changes: 1 addition & 1 deletion bindings/kotlin/ldk-node-android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true
android.enableJetifier=true
kotlin.code.style=official
libraryVersion=0.7.0-rc.2
libraryVersion=0.7.0-rc.3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,8 @@ internal typealias UniffiVTableCallbackInterfaceVssHeaderProviderUniffiByValue =








Expand Down Expand Up @@ -2658,6 +2660,11 @@ internal interface UniffiLib : Library {
fun uniffi_ldk_node_fn_func_default_config(
uniffiCallStatus: UniffiRustCallStatus,
): RustBufferByValue
fun uniffi_ldk_node_fn_func_derive_node_secret_from_mnemonic(
`mnemonic`: RustBufferByValue,
`passphrase`: RustBufferByValue,
uniffiCallStatus: UniffiRustCallStatus,
): RustBufferByValue
fun uniffi_ldk_node_fn_func_generate_entropy_mnemonic(
`wordCount`: RustBufferByValue,
uniffiCallStatus: UniffiRustCallStatus,
Expand Down Expand Up @@ -2876,6 +2883,8 @@ internal interface UniffiLib : Library {
): Unit
fun uniffi_ldk_node_checksum_func_default_config(
): Short
fun uniffi_ldk_node_checksum_func_derive_node_secret_from_mnemonic(
): Short
fun uniffi_ldk_node_checksum_func_generate_entropy_mnemonic(
): Short
fun uniffi_ldk_node_checksum_method_bolt11invoice_amount_milli_satoshis(
Expand Down Expand Up @@ -3268,6 +3277,9 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) {
if (lib.uniffi_ldk_node_checksum_func_default_config() != 55381.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_ldk_node_checksum_func_derive_node_secret_from_mnemonic() != 15067.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_ldk_node_checksum_func_generate_entropy_mnemonic() != 48014.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
Expand Down Expand Up @@ -11054,6 +11066,7 @@ object FfiConverterTypeNodeError : FfiConverterRustBuffer<NodeException> {
59 -> NodeException.TransactionAlreadyConfirmed(FfiConverterString.read(buf))
60 -> NodeException.NoSpendableOutputs(FfiConverterString.read(buf))
61 -> NodeException.CoinSelectionFailed(FfiConverterString.read(buf))
62 -> NodeException.InvalidMnemonic(FfiConverterString.read(buf))
else -> throw RuntimeException("invalid error enum value, something is very wrong!!")
}
}
Expand Down Expand Up @@ -11308,6 +11321,10 @@ object FfiConverterTypeNodeError : FfiConverterRustBuffer<NodeException> {
buf.putInt(61)
Unit
}
is NodeException.InvalidMnemonic -> {
buf.putInt(62)
Unit
}
}.let { /* this makes the `when` an expression, which ensures it is exhaustive */ }
}
}
Expand Down Expand Up @@ -13772,6 +13789,17 @@ fun `defaultConfig`(): Config {
})
}

@Throws(NodeException::class)
fun `deriveNodeSecretFromMnemonic`(`mnemonic`: kotlin.String, `passphrase`: kotlin.String?): List<kotlin.UByte> {
return FfiConverterSequenceUByte.lift(uniffiRustCallWithError(NodeExceptionErrorHandler) { uniffiRustCallStatus ->
UniffiLib.INSTANCE.uniffi_ldk_node_fn_func_derive_node_secret_from_mnemonic(
FfiConverterString.lower(`mnemonic`),
FfiConverterOptionalString.lower(`passphrase`),
uniffiRustCallStatus,
)
})
}

fun `generateEntropyMnemonic`(`wordCount`: WordCount?): Mnemonic {
return FfiConverterTypeMnemonic.lift(uniffiRustCall { uniffiRustCallStatus ->
UniffiLib.INSTANCE.uniffi_ldk_node_fn_func_generate_entropy_mnemonic(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1781,6 +1781,8 @@ sealed class NodeException(message: String): kotlin.Exception(message) {

class CoinSelectionFailed(message: String) : NodeException(message)

class InvalidMnemonic(message: String) : NodeException(message)

}


Expand Down
3 changes: 3 additions & 0 deletions bindings/ldk_node.udl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace ldk_node {
Mnemonic generate_entropy_mnemonic(WordCount? word_count);
Config default_config();
[Throws=NodeError]
sequence<u8> derive_node_secret_from_mnemonic(string mnemonic, string? passphrase);
};

dictionary Config {
Expand Down Expand Up @@ -380,6 +382,7 @@ enum NodeError {
"TransactionAlreadyConfirmed",
"NoSpendableOutputs",
"CoinSelectionFailed",
"InvalidMnemonic",
};

dictionary NodeStatus {
Expand Down
35 changes: 35 additions & 0 deletions bindings/python/src/ldk_node/ldk_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,8 @@ def _uniffi_check_contract_api_version(lib):
def _uniffi_check_api_checksums(lib):
if lib.uniffi_ldk_node_checksum_func_default_config() != 55381:
raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
if lib.uniffi_ldk_node_checksum_func_derive_node_secret_from_mnemonic() != 15067:
raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
if lib.uniffi_ldk_node_checksum_func_generate_entropy_mnemonic() != 48014:
raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
if lib.uniffi_ldk_node_checksum_method_bolt11invoice_amount_milli_satoshis() != 50823:
Expand Down Expand Up @@ -2320,6 +2322,12 @@ class _UniffiVTableCallbackInterfaceVssHeaderProvider(ctypes.Structure):
ctypes.POINTER(_UniffiRustCallStatus),
)
_UniffiLib.uniffi_ldk_node_fn_func_default_config.restype = _UniffiRustBuffer
_UniffiLib.uniffi_ldk_node_fn_func_derive_node_secret_from_mnemonic.argtypes = (
_UniffiRustBuffer,
_UniffiRustBuffer,
ctypes.POINTER(_UniffiRustCallStatus),
)
_UniffiLib.uniffi_ldk_node_fn_func_derive_node_secret_from_mnemonic.restype = _UniffiRustBuffer
_UniffiLib.uniffi_ldk_node_fn_func_generate_entropy_mnemonic.argtypes = (
_UniffiRustBuffer,
ctypes.POINTER(_UniffiRustCallStatus),
Expand Down Expand Up @@ -2596,6 +2604,9 @@ class _UniffiVTableCallbackInterfaceVssHeaderProvider(ctypes.Structure):
_UniffiLib.uniffi_ldk_node_checksum_func_default_config.argtypes = (
)
_UniffiLib.uniffi_ldk_node_checksum_func_default_config.restype = ctypes.c_uint16
_UniffiLib.uniffi_ldk_node_checksum_func_derive_node_secret_from_mnemonic.argtypes = (
)
_UniffiLib.uniffi_ldk_node_checksum_func_derive_node_secret_from_mnemonic.restype = ctypes.c_uint16
_UniffiLib.uniffi_ldk_node_checksum_func_generate_entropy_mnemonic.argtypes = (
)
_UniffiLib.uniffi_ldk_node_checksum_func_generate_entropy_mnemonic.restype = ctypes.c_uint16
Expand Down Expand Up @@ -11996,6 +12007,11 @@ class CoinSelectionFailed(_UniffiTempNodeError):
def __repr__(self):
return "NodeError.CoinSelectionFailed({})".format(repr(str(self)))
_UniffiTempNodeError.CoinSelectionFailed = CoinSelectionFailed # type: ignore
class InvalidMnemonic(_UniffiTempNodeError):

def __repr__(self):
return "NodeError.InvalidMnemonic({})".format(repr(str(self)))
_UniffiTempNodeError.InvalidMnemonic = InvalidMnemonic # type: ignore

NodeError = _UniffiTempNodeError # type: ignore
del _UniffiTempNodeError
Expand Down Expand Up @@ -12249,6 +12265,10 @@ def read(buf):
return NodeError.CoinSelectionFailed(
_UniffiConverterString.read(buf),
)
if variant == 62:
return NodeError.InvalidMnemonic(
_UniffiConverterString.read(buf),
)
raise InternalError("Raw enum value doesn't match any cases")

@staticmethod
Expand Down Expand Up @@ -12375,6 +12395,8 @@ def check_lower(value):
return
if isinstance(value, NodeError.CoinSelectionFailed):
return
if isinstance(value, NodeError.InvalidMnemonic):
return

@staticmethod
def write(value, buf):
Expand Down Expand Up @@ -12500,6 +12522,8 @@ def write(value, buf):
buf.write_i32(60)
if isinstance(value, NodeError.CoinSelectionFailed):
buf.write_i32(61)
if isinstance(value, NodeError.InvalidMnemonic):
buf.write_i32(62)



Expand Down Expand Up @@ -15869,6 +15893,16 @@ def default_config() -> "Config":
return _UniffiConverterTypeConfig.lift(_uniffi_rust_call(_UniffiLib.uniffi_ldk_node_fn_func_default_config,))


def derive_node_secret_from_mnemonic(mnemonic: "str",passphrase: "typing.Optional[str]") -> "typing.List[int]":
_UniffiConverterString.check_lower(mnemonic)

_UniffiConverterOptionalString.check_lower(passphrase)

return _UniffiConverterSequenceUInt8.lift(_uniffi_rust_call_with_error(_UniffiConverterTypeNodeError,_UniffiLib.uniffi_ldk_node_fn_func_derive_node_secret_from_mnemonic,
_UniffiConverterString.lower(mnemonic),
_UniffiConverterOptionalString.lower(passphrase)))


def generate_entropy_mnemonic(word_count: "typing.Optional[WordCount]") -> "Mnemonic":
_UniffiConverterOptionalTypeWordCount.check_lower(word_count)

Expand Down Expand Up @@ -15939,6 +15973,7 @@ def generate_entropy_mnemonic(word_count: "typing.Optional[WordCount]") -> "Mnem
"TxInput",
"TxOutput",
"default_config",
"derive_node_secret_from_mnemonic",
"generate_entropy_mnemonic",
"Bolt11Invoice",
"Bolt11Payment",
Expand Down
20 changes: 20 additions & 0 deletions bindings/swift/Sources/LDKNode/LDKNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8190,6 +8190,8 @@ public enum NodeError {
case NoSpendableOutputs(message: String)

case CoinSelectionFailed(message: String)

case InvalidMnemonic(message: String)
}

#if swift(>=5.8)
Expand Down Expand Up @@ -8445,6 +8447,10 @@ public struct FfiConverterTypeNodeError: FfiConverterRustBuffer {
message: FfiConverterString.read(from: &buf)
)

case 62: return try .InvalidMnemonic(
message: FfiConverterString.read(from: &buf)
)

default: throw UniffiInternalError.unexpectedEnumCase
}
}
Expand Down Expand Up @@ -8573,6 +8579,8 @@ public struct FfiConverterTypeNodeError: FfiConverterRustBuffer {
writeInt(&buf, Int32(60))
case .CoinSelectionFailed(_ /* message is ignored*/ ):
writeInt(&buf, Int32(61))
case .InvalidMnemonic(_ /* message is ignored*/ ):
writeInt(&buf, Int32(62))
}
}
}
Expand Down Expand Up @@ -11679,6 +11687,15 @@ public func defaultConfig() -> Config {
})
}

public func deriveNodeSecretFromMnemonic(mnemonic: String, passphrase: String?) throws -> [UInt8] {
return try FfiConverterSequenceUInt8.lift(rustCallWithError(FfiConverterTypeNodeError.lift) {
uniffi_ldk_node_fn_func_derive_node_secret_from_mnemonic(
FfiConverterString.lower(mnemonic),
FfiConverterOptionString.lower(passphrase), $0
)
})
}

public func generateEntropyMnemonic(wordCount: WordCount?) -> Mnemonic {
return try! FfiConverterTypeMnemonic.lift(try! rustCall {
uniffi_ldk_node_fn_func_generate_entropy_mnemonic(
Expand Down Expand Up @@ -11706,6 +11723,9 @@ private var initializationResult: InitializationResult = {
if uniffi_ldk_node_checksum_func_default_config() != 55381 {
return InitializationResult.apiChecksumMismatch
}
if uniffi_ldk_node_checksum_func_derive_node_secret_from_mnemonic() != 15067 {
return InitializationResult.apiChecksumMismatch
}
if uniffi_ldk_node_checksum_func_generate_entropy_mnemonic() != 48014 {
return InitializationResult.apiChecksumMismatch
}
Expand Down
3 changes: 3 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ pub enum Error {
NoSpendableOutputs,
/// Coin selection failed to find suitable UTXOs.
CoinSelectionFailed,
/// The given mnemonic is invalid.
InvalidMnemonic,
}

impl fmt::Display for Error {
Expand Down Expand Up @@ -227,6 +229,7 @@ impl fmt::Display for Error {
},
Self::NoSpendableOutputs => write!(f, "The transaction has no spendable outputs."),
Self::CoinSelectionFailed => write!(f, "Coin selection failed to find suitable UTXOs."),
Self::InvalidMnemonic => write!(f, "The given mnemonic is invalid."),
}
}
}
Expand Down
21 changes: 21 additions & 0 deletions src/io/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use bdk_chain::tx_graph::ChangeSet as BdkTxGraphChangeSet;
use bdk_chain::ConfirmationBlockTime;
use bdk_wallet::ChangeSet as BdkWalletChangeSet;
use bip39::Mnemonic;
use bitcoin::bip32::Xpriv;
use bitcoin::Network;
use lightning::io::Cursor;
use lightning::ln::msgs::DecodeError;
Expand Down Expand Up @@ -68,6 +69,26 @@ pub fn generate_entropy_mnemonic(word_count: Option<WordCount>) -> Mnemonic {
Mnemonic::generate(word_count).expect("Failed to generate mnemonic")
}

/// Derives the node secret key from a BIP39 mnemonic.
///
/// This is the same key that would be used by a [`Node`] built with this mnemonic via
/// [`Builder::set_entropy_bip39_mnemonic`].
///
/// [`Node`]: crate::Node
/// [`Builder::set_entropy_bip39_mnemonic`]: crate::Builder::set_entropy_bip39_mnemonic
pub fn derive_node_secret_from_mnemonic(
mnemonic: String, passphrase: Option<String>,
) -> Result<Vec<u8>, Error> {
let parsed_mnemonic = Mnemonic::parse(&mnemonic).map_err(|_| Error::InvalidMnemonic)?;

let seed = parsed_mnemonic.to_seed(passphrase.as_deref().unwrap_or(""));

let xpriv =
Xpriv::new_master(Network::Bitcoin, &seed).map_err(|_| Error::InvalidMnemonic)?;

Ok(xpriv.private_key.secret_bytes().to_vec())
}

pub(crate) fn read_or_generate_seed_file<L: Deref>(
keys_seed_path: &str, logger: L,
) -> std::io::Result<[u8; WALLET_KEYS_SEED_LEN]>
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ use fee_estimator::{ConfirmationTarget, FeeEstimator, OnchainFeeEstimator};
use ffi::*;
use gossip::GossipSource;
use graph::NetworkGraph;
pub use io::utils::generate_entropy_mnemonic;
pub use io::utils::{derive_node_secret_from_mnemonic, generate_entropy_mnemonic};
use io::utils::write_node_metrics;
use lightning::chain::BestBlock;
use lightning::events::bump_transaction::{Input, Wallet as LdkWallet};
Expand Down