diff --git a/sphinx-ffi/Cargo.toml b/sphinx-ffi/Cargo.toml index 50b6135..af8f7e1 100644 --- a/sphinx-ffi/Cargo.toml +++ b/sphinx-ffi/Cargo.toml @@ -22,7 +22,8 @@ lightning = { git = "https://github.com/Evanfeenstra/rust-lightning", rev = "3f5 sphinx-crypter = { path = "../crypter" } sphinx-signer = { path = "../signer", default-features = false, features = ["persist", "no-native"] } sphinx-glyph = { path = "../glyph", default-features = false } -sphinx = { git = "https://github.com/stakwork/sphinx", rev = "2cf75b38e1edf52d4203255ab3ea858d5fbec1a2" } +sphinx = { git = "https://github.com/stakwork/sphinx", rev = "e8ba3efe0039e866b16b45dbaf59a1f80df3907f" } +# sphinx = { path = "../../sphinx/sphinx" } uniffi = { version = "0.24.1", optional = true } hex = { version = "0.4.3", default-features = false } thiserror = "1.0.31" diff --git a/sphinx-ffi/src/lib.rs b/sphinx-ffi/src/lib.rs index a43ed62..a47c113 100644 --- a/sphinx-ffi/src/lib.rs +++ b/sphinx-ffi/src/lib.rs @@ -58,6 +58,8 @@ pub enum SphinxError { LssFailed { r: String }, #[error("VLS Failed: {r}")] VlsFailed { r: String }, + #[error("Bad Child Index: {r}")] + BadChildIndex { r: String }, } pub fn pubkey_from_secret_key(my_secret_key: String) -> Result { diff --git a/sphinx-ffi/src/onion.rs b/sphinx-ffi/src/onion.rs index 06d8f4c..3ce7f9d 100644 --- a/sphinx-ffi/src/onion.rs +++ b/sphinx-ffi/src/onion.rs @@ -1,7 +1,6 @@ use crate::{Result, SphinxError}; -use sphinx::{ - KeyDerivationStyle, MyKeysManager, Network, NowStartingTimeFactory, PublicKey, Secp256k1, -}; +use sphinx::bip32::XKey; +use sphinx::{KeyDerivationStyle, MyKeysManager, Network, NowStartingTimeFactory, PublicKey}; use std::convert::TryInto; use std::str::FromStr; @@ -9,8 +8,14 @@ pub fn sha_256(msg: Vec) -> String { hex::encode(sphinx::sha_256(&msg)) } -pub fn sign_ms(seed: String, time: String, network: String) -> Result { - let km = make_keys_manager(&seed, &time, &network)?; +pub fn xpub_from_seed(seed: String, time: String, net: String) -> Result { + let km = make_keys_manager(&seed, Some(-1), &time, &net)?; + let xpub = km.root_xpub(); + Ok(xpub.to_string()) +} + +pub fn root_sign_ms(seed: String, time: String, net: String) -> Result { + let km = make_keys_manager(&seed, Some(-1), &time, &net)?; let sig = sphinx::sig::sign_message(time.as_bytes(), &km.get_node_secret()).map_err(|_| { SphinxError::BadCiper { r: "sign failed".to_string(), @@ -19,21 +24,34 @@ pub fn sign_ms(seed: String, time: String, network: String) -> Result { Ok(hex::encode(sig)) } -pub fn pubkey_from_seed(seed: String, time: String, network: String) -> Result { - let km = make_keys_manager(&seed, &time, &network)?; - let secp_ctx = sphinx::Secp256k1::new(); +pub fn sign_ms(seed: String, idx: u32, time: String, network: String) -> Result { + let idx = idx_to_idx(idx)?; + let km = make_keys_manager(&seed, idx, &time, &network)?; + let sig = sphinx::sig::sign_message(time.as_bytes(), &km.get_node_secret()).map_err(|_| { + SphinxError::BadCiper { + r: "sign failed".to_string(), + } + })?; + Ok(hex::encode(sig)) +} + +pub fn pubkey_from_seed(seed: String, idx: u32, time: String, network: String) -> Result { + let idx = idx_to_idx(idx)?; + let km = make_keys_manager(&seed, idx, &time, &network)?; let pubkey = km.get_node_pubkey(); Ok(hex::encode(pubkey.serialize())) } pub fn create_onion( seed: String, + idx: u32, time: String, network: String, hops: String, payload: Vec, ) -> Result> { - let km = make_keys_manager(&seed, &time, &network)?; + let idx = idx_to_idx(idx)?; + let km = make_keys_manager(&seed, idx, &time, &network)?; let hops = parse_hops(&hops)?; let (_, data) = run_create_onion_bytes(&km, hops, &payload)?; Ok(data) @@ -41,16 +59,19 @@ pub fn create_onion( pub fn peel_onion( seed: String, + idx: u32, time: String, network: String, payload: Vec, ) -> Result> { - let km = make_keys_manager(&seed, &time, &network)?; + let idx = idx_to_idx(idx)?; + let km = make_keys_manager(&seed, idx, &time, &network)?; Ok(run_peel_onion_bytes(&km, &payload)?) } pub fn create_keysend( seed: String, + idx: u32, time: String, network: String, hops: String, @@ -60,7 +81,8 @@ pub fn create_keysend( curr_height: u32, preimage: String, ) -> Result> { - let km = make_keys_manager(&seed, &time, &network)?; + let idx = idx_to_idx(idx)?; + let km = make_keys_manager(&seed, idx, &time, &network)?; let hops = parse_hops(&hops)?; let payment_hash = parse_hash(&rhash)?; let preimage = parse_preimage(&preimage)?; @@ -78,17 +100,32 @@ pub fn create_keysend( pub fn peel_payment( seed: String, + idx: u32, time: String, network: String, payload: Vec, rhash: String, ) -> Result> { - let km = make_keys_manager(&seed, &time, &network)?; + let idx = idx_to_idx(idx)?; + let km = make_keys_manager(&seed, idx, &time, &network)?; let payment_hash = parse_hash(&rhash)?; Ok(run_peel_payment_bytes(&km, &payload, payment_hash)?) } -fn make_keys_manager(seed: &str, time: &str, network: &str) -> Result { +fn idx_to_idx(idx: u32) -> Result> { + Ok(Some(idx.try_into().map_err(|_| { + SphinxError::BadChildIndex { + r: "infallible".to_string(), + } + })?)) +} + +fn make_keys_manager( + seed: &str, + idx: Option, + time: &str, + network: &str, +) -> Result { let seed = parse_seed(seed)?; let ts = parse_u64(time)?; let time = std::time::Duration::from_millis(ts); @@ -97,7 +134,11 @@ fn make_keys_manager(seed: &str, time: &str, network: &str) -> Result Result { diff --git a/sphinx-ffi/src/sphinxrs.swift b/sphinx-ffi/src/sphinxrs.swift index c03ec25..c9f1b80 100644 --- a/sphinx-ffi/src/sphinxrs.swift +++ b/sphinx-ffi/src/sphinxrs.swift @@ -541,6 +541,7 @@ public enum SphinxError { case InitFailed(`r`: String) case LssFailed(`r`: String) case VlsFailed(`r`: String) + case BadChildIndex(`r`: String) fileprivate static func uniffiErrorHandler(_ error: RustBuffer) throws -> Error { return try FfiConverterTypeSphinxError.lift(error) @@ -612,6 +613,9 @@ public struct FfiConverterTypeSphinxError: FfiConverterRustBuffer { case 18: return .VlsFailed( `r`: try FfiConverterString.read(from: &buf) ) + case 19: return .BadChildIndex( + `r`: try FfiConverterString.read(from: &buf) + ) default: throw UniffiInternalError.unexpectedEnumCase } @@ -713,6 +717,11 @@ public struct FfiConverterTypeSphinxError: FfiConverterRustBuffer { writeInt(&buf, Int32(18)) FfiConverterString.write(`r`, into: &buf) + + case let .BadChildIndex(`r`): + writeInt(&buf, Int32(19)) + FfiConverterString.write(`r`, into: &buf) + } } } @@ -881,11 +890,12 @@ public func `sha256`(`msg`: Data) -> String { ) } -public func `createOnion`(`seed`: String, `time`: String, `network`: String, `hops`: String, `payload`: Data) throws -> Data { +public func `createOnion`(`seed`: String, `idx`: UInt32, `time`: String, `network`: String, `hops`: String, `payload`: Data) throws -> Data { return try FfiConverterData.lift( try rustCallWithError(FfiConverterTypeSphinxError.lift) { uniffi_sphinxrs_fn_func_create_onion( FfiConverterString.lower(`seed`), + FfiConverterUInt32.lower(`idx`), FfiConverterString.lower(`time`), FfiConverterString.lower(`network`), FfiConverterString.lower(`hops`), @@ -894,11 +904,12 @@ public func `createOnion`(`seed`: String, `time`: String, `network`: String, `ho ) } -public func `createKeysend`(`seed`: String, `time`: String, `network`: String, `hops`: String, `msat`: UInt64, `rhash`: String, `payload`: Data, `currHeight`: UInt32, `preimage`: String) throws -> Data { +public func `createKeysend`(`seed`: String, `idx`: UInt32, `time`: String, `network`: String, `hops`: String, `msat`: UInt64, `rhash`: String, `payload`: Data, `currHeight`: UInt32, `preimage`: String) throws -> Data { return try FfiConverterData.lift( try rustCallWithError(FfiConverterTypeSphinxError.lift) { uniffi_sphinxrs_fn_func_create_keysend( FfiConverterString.lower(`seed`), + FfiConverterUInt32.lower(`idx`), FfiConverterString.lower(`time`), FfiConverterString.lower(`network`), FfiConverterString.lower(`hops`), @@ -911,11 +922,12 @@ public func `createKeysend`(`seed`: String, `time`: String, `network`: String, ` ) } -public func `peelOnion`(`seed`: String, `time`: String, `network`: String, `payload`: Data) throws -> Data { +public func `peelOnion`(`seed`: String, `idx`: UInt32, `time`: String, `network`: String, `payload`: Data) throws -> Data { return try FfiConverterData.lift( try rustCallWithError(FfiConverterTypeSphinxError.lift) { uniffi_sphinxrs_fn_func_peel_onion( FfiConverterString.lower(`seed`), + FfiConverterUInt32.lower(`idx`), FfiConverterString.lower(`time`), FfiConverterString.lower(`network`), FfiConverterData.lower(`payload`),$0) @@ -923,11 +935,12 @@ public func `peelOnion`(`seed`: String, `time`: String, `network`: String, `payl ) } -public func `peelPayment`(`seed`: String, `time`: String, `network`: String, `payload`: Data, `preimage`: String) throws -> Data { +public func `peelPayment`(`seed`: String, `idx`: UInt32, `time`: String, `network`: String, `payload`: Data, `preimage`: String) throws -> Data { return try FfiConverterData.lift( try rustCallWithError(FfiConverterTypeSphinxError.lift) { uniffi_sphinxrs_fn_func_peel_payment( FfiConverterString.lower(`seed`), + FfiConverterUInt32.lower(`idx`), FfiConverterString.lower(`time`), FfiConverterString.lower(`network`), FfiConverterData.lower(`payload`), @@ -936,21 +949,45 @@ public func `peelPayment`(`seed`: String, `time`: String, `network`: String, `pa ) } -public func `signMs`(`seed`: String, `time`: String, `network`: String) throws -> String { +public func `signMs`(`seed`: String, `idx`: UInt32, `time`: String, `network`: String) throws -> String { return try FfiConverterString.lift( try rustCallWithError(FfiConverterTypeSphinxError.lift) { uniffi_sphinxrs_fn_func_sign_ms( FfiConverterString.lower(`seed`), + FfiConverterUInt32.lower(`idx`), FfiConverterString.lower(`time`), FfiConverterString.lower(`network`),$0) } ) } -public func `pubkeyFromSeed`(`seed`: String, `time`: String, `network`: String) throws -> String { +public func `pubkeyFromSeed`(`seed`: String, `idx`: UInt32, `time`: String, `network`: String) throws -> String { return try FfiConverterString.lift( try rustCallWithError(FfiConverterTypeSphinxError.lift) { uniffi_sphinxrs_fn_func_pubkey_from_seed( + FfiConverterString.lower(`seed`), + FfiConverterUInt32.lower(`idx`), + FfiConverterString.lower(`time`), + FfiConverterString.lower(`network`),$0) +} + ) +} + +public func `rootSignMs`(`seed`: String, `time`: String, `network`: String) throws -> String { + return try FfiConverterString.lift( + try rustCallWithError(FfiConverterTypeSphinxError.lift) { + uniffi_sphinxrs_fn_func_root_sign_ms( + FfiConverterString.lower(`seed`), + FfiConverterString.lower(`time`), + FfiConverterString.lower(`network`),$0) +} + ) +} + +public func `xpubFromSeed`(`seed`: String, `time`: String, `network`: String) throws -> String { + return try FfiConverterString.lift( + try rustCallWithError(FfiConverterTypeSphinxError.lift) { + uniffi_sphinxrs_fn_func_xpub_from_seed( FfiConverterString.lower(`seed`), FfiConverterString.lower(`time`), FfiConverterString.lower(`network`),$0) @@ -1015,22 +1052,28 @@ private var initializationResult: InitializationResult { if (uniffi_sphinxrs_checksum_func_sha_256() != 54805) { return InitializationResult.apiChecksumMismatch } - if (uniffi_sphinxrs_checksum_func_create_onion() != 27807) { + if (uniffi_sphinxrs_checksum_func_create_onion() != 65256) { + return InitializationResult.apiChecksumMismatch + } + if (uniffi_sphinxrs_checksum_func_create_keysend() != 11970) { + return InitializationResult.apiChecksumMismatch + } + if (uniffi_sphinxrs_checksum_func_peel_onion() != 38236) { return InitializationResult.apiChecksumMismatch } - if (uniffi_sphinxrs_checksum_func_create_keysend() != 38040) { + if (uniffi_sphinxrs_checksum_func_peel_payment() != 55979) { return InitializationResult.apiChecksumMismatch } - if (uniffi_sphinxrs_checksum_func_peel_onion() != 6042) { + if (uniffi_sphinxrs_checksum_func_sign_ms() != 54469) { return InitializationResult.apiChecksumMismatch } - if (uniffi_sphinxrs_checksum_func_peel_payment() != 37944) { + if (uniffi_sphinxrs_checksum_func_pubkey_from_seed() != 3734) { return InitializationResult.apiChecksumMismatch } - if (uniffi_sphinxrs_checksum_func_sign_ms() != 34795) { + if (uniffi_sphinxrs_checksum_func_root_sign_ms() != 52594) { return InitializationResult.apiChecksumMismatch } - if (uniffi_sphinxrs_checksum_func_pubkey_from_seed() != 33074) { + if (uniffi_sphinxrs_checksum_func_xpub_from_seed() != 14922) { return InitializationResult.apiChecksumMismatch } diff --git a/sphinx-ffi/src/sphinxrs.udl b/sphinx-ffi/src/sphinxrs.udl index 98e1e50..140bdff 100644 --- a/sphinx-ffi/src/sphinxrs.udl +++ b/sphinx-ffi/src/sphinxrs.udl @@ -18,6 +18,7 @@ interface SphinxError { InitFailed(string r); LssFailed(string r); VlsFailed(string r); + BadChildIndex(string r); }; dictionary Keys { @@ -62,15 +63,19 @@ namespace sphinxrs { VlsResponse run(string topic, string args, bytes state, bytes msg1, u16? expected_sequence); string sha_256(bytes msg); [Throws=SphinxError] - bytes create_onion(string seed, string time, string network, string hops, bytes payload); + bytes create_onion(string seed, u32 idx, string time, string network, string hops, bytes payload); [Throws=SphinxError] - bytes create_keysend(string seed, string time, string network, string hops, u64 msat, string rhash, bytes payload, u32 curr_height, string preimage); + bytes create_keysend(string seed, u32 idx, string time, string network, string hops, u64 msat, string rhash, bytes payload, u32 curr_height, string preimage); [Throws=SphinxError] - bytes peel_onion(string seed, string time, string network, bytes payload); + bytes peel_onion(string seed, u32 idx, string time, string network, bytes payload); [Throws=SphinxError] - bytes peel_payment(string seed, string time, string network, bytes payload, string preimage); + bytes peel_payment(string seed, u32 idx, string time, string network, bytes payload, string preimage); [Throws=SphinxError] - string sign_ms(string seed, string time, string network); + string sign_ms(string seed, u32 idx, string time, string network); [Throws=SphinxError] - string pubkey_from_seed(string seed, string time, string network); + string pubkey_from_seed(string seed, u32 idx, string time, string network); + [Throws=SphinxError] + string root_sign_ms(string seed, string time, string network); + [Throws=SphinxError] + string xpub_from_seed(string seed, string time, string network); }; \ No newline at end of file diff --git a/sphinx-ffi/src/sphinxrsFFI.h b/sphinx-ffi/src/sphinxrsFFI.h index 762b700..458c85a 100644 --- a/sphinx-ffi/src/sphinxrsFFI.h +++ b/sphinx-ffi/src/sphinxrsFFI.h @@ -91,17 +91,21 @@ RustBuffer uniffi_sphinxrs_fn_func_run(RustBuffer topic, RustBuffer args, RustBu ); RustBuffer uniffi_sphinxrs_fn_func_sha_256(RustBuffer msg, RustCallStatus *_Nonnull out_status ); -RustBuffer uniffi_sphinxrs_fn_func_create_onion(RustBuffer seed, RustBuffer time, RustBuffer network, RustBuffer hops, RustBuffer payload, RustCallStatus *_Nonnull out_status +RustBuffer uniffi_sphinxrs_fn_func_create_onion(RustBuffer seed, uint32_t idx, RustBuffer time, RustBuffer network, RustBuffer hops, RustBuffer payload, RustCallStatus *_Nonnull out_status ); -RustBuffer uniffi_sphinxrs_fn_func_create_keysend(RustBuffer seed, RustBuffer time, RustBuffer network, RustBuffer hops, uint64_t msat, RustBuffer rhash, RustBuffer payload, uint32_t curr_height, RustBuffer preimage, RustCallStatus *_Nonnull out_status +RustBuffer uniffi_sphinxrs_fn_func_create_keysend(RustBuffer seed, uint32_t idx, RustBuffer time, RustBuffer network, RustBuffer hops, uint64_t msat, RustBuffer rhash, RustBuffer payload, uint32_t curr_height, RustBuffer preimage, RustCallStatus *_Nonnull out_status ); -RustBuffer uniffi_sphinxrs_fn_func_peel_onion(RustBuffer seed, RustBuffer time, RustBuffer network, RustBuffer payload, RustCallStatus *_Nonnull out_status +RustBuffer uniffi_sphinxrs_fn_func_peel_onion(RustBuffer seed, uint32_t idx, RustBuffer time, RustBuffer network, RustBuffer payload, RustCallStatus *_Nonnull out_status ); -RustBuffer uniffi_sphinxrs_fn_func_peel_payment(RustBuffer seed, RustBuffer time, RustBuffer network, RustBuffer payload, RustBuffer preimage, RustCallStatus *_Nonnull out_status +RustBuffer uniffi_sphinxrs_fn_func_peel_payment(RustBuffer seed, uint32_t idx, RustBuffer time, RustBuffer network, RustBuffer payload, RustBuffer preimage, RustCallStatus *_Nonnull out_status ); -RustBuffer uniffi_sphinxrs_fn_func_sign_ms(RustBuffer seed, RustBuffer time, RustBuffer network, RustCallStatus *_Nonnull out_status +RustBuffer uniffi_sphinxrs_fn_func_sign_ms(RustBuffer seed, uint32_t idx, RustBuffer time, RustBuffer network, RustCallStatus *_Nonnull out_status ); -RustBuffer uniffi_sphinxrs_fn_func_pubkey_from_seed(RustBuffer seed, RustBuffer time, RustBuffer network, RustCallStatus *_Nonnull out_status +RustBuffer uniffi_sphinxrs_fn_func_pubkey_from_seed(RustBuffer seed, uint32_t idx, RustBuffer time, RustBuffer network, RustCallStatus *_Nonnull out_status +); +RustBuffer uniffi_sphinxrs_fn_func_root_sign_ms(RustBuffer seed, RustBuffer time, RustBuffer network, RustCallStatus *_Nonnull out_status +); +RustBuffer uniffi_sphinxrs_fn_func_xpub_from_seed(RustBuffer seed, RustBuffer time, RustBuffer network, RustCallStatus *_Nonnull out_status ); RustBuffer ffi_sphinxrs_rustbuffer_alloc(int32_t size, RustCallStatus *_Nonnull out_status ); @@ -170,6 +174,12 @@ uint16_t uniffi_sphinxrs_checksum_func_sign_ms(void ); uint16_t uniffi_sphinxrs_checksum_func_pubkey_from_seed(void +); +uint16_t uniffi_sphinxrs_checksum_func_root_sign_ms(void + +); +uint16_t uniffi_sphinxrs_checksum_func_xpub_from_seed(void + ); uint32_t ffi_sphinxrs_uniffi_contract_version(void