Skip to content
Draft
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
210 changes: 101 additions & 109 deletions Cargo.lock

Large diffs are not rendered by default.

36 changes: 20 additions & 16 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ base64 = "0.21.2"
bech32 = "0.9.1"
bs58 = "0.4.0"
bigdecimal = { version = "0.3", features = ["serde"] }
bip32 = { version = "0.2.2", default-features = false, features = ["alloc", "secp256k1-ffi"] }
bip32 = { version = "0.5.0", default-features = false, features = ["alloc", "secp256k1-ffi"] }
bip39 = { version = "2.0.0", features = ["rand_core", "zeroize"], default-features = false }
bitcoin = "0.29"
bitcoin_hashes = "0.11"
bitcoin = "0.30"
bitcoin_hashes = "0.12"
blake2 = "0.10.6"
blake2b_simd = "0.5.10"
bytes = "1.1"
Expand All @@ -89,9 +89,9 @@ either = "1.6"
enum-primitive-derive = "0.2"
env_logger = { version = "0.11", default-features = false }
ethabi = "17.0.0"
ethcore-transaction = { git = "https://github.com/KomodoPlatform/mm2-parity-ethereum.git", rev = "mm2-v2.1.1" }
ethcore-transaction = { git = "https://github.com/KomodoPlatform/mm2-parity-ethereum.git", branch = "upgrade-secp256k1" }
ethereum-types = { version = "0.13", default-features = false, features = ["std", "serialize"] }
ethkey = { git = "https://github.com/KomodoPlatform/mm2-parity-ethereum.git", rev = "mm2-v2.1.1" }
ethkey = { git = "https://github.com/KomodoPlatform/mm2-parity-ethereum.git", branch = "upgrade-secp256k1" }
# Waiting for https://github.com/rust-lang/rust/issues/54725 to use on Stable.
#enum_dispatch = "0.1"
ff = "0.8"
Expand Down Expand Up @@ -127,10 +127,11 @@ jsonrpc-core = "18.0.0"
lazy_static = "1.4"
libc = "0.2"
libp2p = { git = "https://github.com/KomodoPlatform/rust-libp2p.git", tag = "k-0.52.12", default-features = false }
lightning = "0.0.113"
lightning-background-processor = "0.0.113"
lightning-invoice = { version = "0.21.0", features = ["serde"] }
lightning-net-tokio = "0.0.113"
lightning = "0.0.119"
lightning-background-processor = "0.0.119"
lightning-invoice = { version = "0.27.0", features = ["serde"] }
lightning-net-tokio = "0.0.119"
lightning-persister = "0.0.119"
log = "0.4"
metrics = "0.21"
metrics-exporter-prometheus = "0.12.1"
Expand Down Expand Up @@ -169,8 +170,7 @@ rust-ini = "0.13"
rustls = { version = "0.21", default-features = false }
rustls-pemfile = "1.0.2"
rusqlite = { version = "0.28", features = ["bundled"] }
secp256k1 = "0.20"
secp256k1v24 = { version = "0.24", package = "secp256k1" }
secp256k1 = "0.27"
serde = { version = "1", default-features = false }
serde_bytes = "0.11.5"
serde_derive = { version = "1", default-features = false }
Expand Down Expand Up @@ -222,11 +222,11 @@ web-sys = {version = "0.3.55", default-features = false }
web3 = { git = "https://github.com/komodoplatform/rust-web3", tag = "v0.20.0", default-features = false }
winapi = "0.3"
zbase32 = "0.1.2"
zcash_client_backend = { git = "https://github.com/komodoplatform/librustzcash.git", tag = "k-1.4.2" }
zcash_client_sqlite = { git = "https://github.com/KomodoPlatform/librustzcash.git", tag = "k-1.4.2" }
zcash_extras = { git = "https://github.com/komodoplatform/librustzcash.git", tag = "k-1.4.2" }
zcash_primitives = { git = "https://github.com/komodoplatform/librustzcash.git", tag = "k-1.4.2", features = ["transparent-inputs"] }
zcash_proofs = { git = "https://github.com/KomodoPlatform/librustzcash.git", tag = "k-1.4.2", default-features = false }
zcash_client_backend = { git = "https://github.com/komodoplatform/librustzcash.git", branch = "upgrade-secp256k1" }
zcash_client_sqlite = { git = "https://github.com/komodoplatform/librustzcash.git", branch = "upgrade-secp256k1" }
zcash_extras = { git = "https://github.com/komodoplatform/librustzcash.git", branch = "upgrade-secp256k1" }
zcash_primitives = { git = "https://github.com/komodoplatform/librustzcash.git", branch = "upgrade-secp256k1", features = ["transparent-inputs"] }
zcash_proofs = { git = "https://github.com/komodoplatform/librustzcash.git", branch = "upgrade-secp256k1", default-features = false }
x25519-dalek = { version = "2.0", features = ["static_secrets"] }
zeroize = { version = "1.8.1", features = ["zeroize_derive"] }

Expand All @@ -249,3 +249,7 @@ codegen-units = 256

[profile.release.package.mocktopus]
opt-level = 1 # TODO: MIR fails on optimizing this dependency, remove that..

# [patch.crates-io]
# secp256k1-sys61 = { version = "0.6.1", git = "https://github.com/rust-bitcoin/rust-secp256k1.git", tag = "secp256k1-sys-0.6.1", package = "secp256k1-sys" }
# secp256k1-sys42 = { version = "0.4.2", git = "https://github.com/rust-bitcoin/rust-secp256k1.git", tag = "secp256k1-sys-0.6.1", package = "secp256k1-sys" }
17 changes: 12 additions & 5 deletions mm2src/coins/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ enable-sia = [
"dep:blake2b_simd",
"dep:sia-rust"
]
enable-lightning = [
"dep:lightning",
"dep:lightning-background-processor",
"dep:lightning-invoice",
"dep:lightning-net-tokio",
"dep:lightning-persister"
]
enable-solana = []
default = []
run-docker-tests = []
Expand Down Expand Up @@ -157,13 +164,13 @@ zcash_proofs = { workspace = true, features = ["local-prover"] }
bitcoin.workspace = true
hyper = { workspace = true, features = ["client", "http2", "server", "tcp"] }
hyper-rustls = { workspace = true, default-features = false, features = ["http1", "http2", "webpki-tokio"] }
lightning.workspace = true
lightning-background-processor.workspace = true
lightning-invoice.workspace = true
lightning-net-tokio.workspace = true
lightning = { workspace = true, optional = true }
lightning-background-processor = { workspace = true, optional = true }
lightning-invoice = { workspace = true, optional = true }
lightning-net-tokio = { workspace = true, optional = true }
lightning-persister = { workspace = true, optional = true }
rust-ini.workspace = true
rustls = { workspace = true, features = ["dangerous_configuration"] }
secp256k1v24.workspace = true
timed-map = { workspace = true, features = ["rustc-hash"] }
tokio.workspace = true
tokio-rustls.workspace = true
Expand Down
4 changes: 2 additions & 2 deletions mm2src/coins/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6148,11 +6148,11 @@ impl MmCoin for EthCoin {
}

fn swap_contract_address(&self) -> Option<BytesJson> {
Some(BytesJson::from(self.swap_contract_address.0.as_ref()))
Some(BytesJson::new(self.swap_contract_address.0.to_vec()))
}

fn fallback_swap_contract(&self) -> Option<BytesJson> {
self.fallback_swap_contract.map(|a| BytesJson::from(a.0.as_ref()))
self.fallback_swap_contract.map(|a| BytesJson::new(a.0.to_vec()))
}

fn mature_confirmations(&self) -> Option<u32> {
Expand Down
4 changes: 2 additions & 2 deletions mm2src/coins/eth/wallet_connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use kdf_walletconnect::chain::{WcChainId, WcRequestMethods};
use kdf_walletconnect::error::WalletConnectError;
use kdf_walletconnect::{WalletConnectCtx, WalletConnectOps, WcTopic};
use mm2_err_handle::prelude::*;
use secp256k1::recovery::{RecoverableSignature, RecoveryId};
use secp256k1::ecdsa::{RecoverableSignature, RecoveryId};
use secp256k1::{PublicKey, Secp256k1};
use std::iter::FromIterator;
use std::str::FromStr;
Expand Down Expand Up @@ -258,7 +258,7 @@ pub(crate) fn recover(signature: &Signature, message: &Message) -> Result<Public
RecoveryId::from_i32(recovery_id as i32)?
};
let sig = RecoverableSignature::from_compact(&signature[0..64], recovery_id)?;
let pubkey = Secp256k1::new().recover(&secp256k1::Message::from_slice(&message[..])?, &sig)?;
let pubkey = Secp256k1::new().recover_ecdsa(&secp256k1::Message::from_slice(&message[..])?, &sig)?;

Ok(pubkey)
}
Expand Down
96 changes: 54 additions & 42 deletions mm2src/coins/lightning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ use derive_more::Display;
use futures::{FutureExt, TryFutureExt};
use futures01::Future;
use keys::{hash::H256, CompactSignature, KeyPair, Private, Public};
use lightning::chain::keysinterface::{KeysInterface, KeysManager, Recipient};
use lightning::ln::channelmanager::{ChannelDetails, MIN_FINAL_CLTV_EXPIRY};
use lightning::ln::channelmanager::{ChannelDetails, MIN_FINAL_CLTV_EXPIRY_DELTA};
use lightning::ln::{PaymentHash, PaymentPreimage};
use lightning::routing::router::{DefaultRouter, PaymentParameters, RouteParameters, Router as RouterTrait};
use lightning::sign::{KeysManager, Recipient, SignerProvider};
use lightning::util::ser::{Readable, Writeable};
use lightning_background_processor::BackgroundProcessor;
use lightning_invoice::payment::Payer;
Expand All @@ -70,7 +70,7 @@ use mm2_number::{BigDecimal, MmNumber};
use parking_lot::Mutex as PaMutex;
use rpc::v1::types::{Bytes as BytesJson, H256 as H256Json, H264 as H264Json};
use script::TransactionInputSigner;
use secp256k1v24::PublicKey;
use secp256k1::PublicKey;
use serde::Deserialize;
use serde_json::Value as Json;
use std::collections::{HashMap, HashSet};
Expand Down Expand Up @@ -256,10 +256,13 @@ impl LightningCoin {
&self,
destination: PublicKey,
amount_msat: u64,
final_cltv_expiry_delta: u32,
final_cltv_expiry_delta: u16,
) -> Result<PaymentInfo, MmError<PaymentError>> {
if final_cltv_expiry_delta < MIN_FINAL_CLTV_EXPIRY {
return MmError::err(PaymentError::CLTVExpiry(final_cltv_expiry_delta, MIN_FINAL_CLTV_EXPIRY));
if final_cltv_expiry_delta < MIN_FINAL_CLTV_EXPIRY_DELTA {
return MmError::err(PaymentError::CLTVExpiry(
final_cltv_expiry_delta,
MIN_FINAL_CLTV_EXPIRY_DELTA,
));
}
let payment_preimage = PaymentPreimage(self.keys_manager.get_secure_random_bytes());

Expand Down Expand Up @@ -425,15 +428,15 @@ impl LightningCoin {
}
}

// Todo: this can be removed after next rust-lightning release when min_final_cltv_expiry can be specified in
// Todo: this can be removed after next rust-lightning release when min_final_cltv_expiry_delta can be specified in
// Todo: create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash https://github.com/lightningdevkit/rust-lightning/pull/1878
// Todo: The above PR will also validate min_final_cltv_expiry.
// Todo: The above PR will also validate min_final_cltv_expiry_delta.
async fn create_invoice_for_hash(
&self,
payment_hash: PaymentHash,
amt_msat: Option<u64>,
description: String,
min_final_cltv_expiry: u64,
min_final_cltv_expiry_delta: u64,
invoice_expiry_delta_secs: u32,
) -> Result<Invoice, MmError<SignOrCreationError<()>>> {
let open_channels_nodes = self.open_channels_nodes.lock().clone();
Expand All @@ -445,11 +448,19 @@ impl LightningCoin {
));
}

// TODO: Here we just don't set the delta if we can't convert it to u16. There is probably a better solution.
let min_final_cltv_expiry_delta: Option<u16> = min_final_cltv_expiry_delta.try_into().ok();

// `create_inbound_payment` only returns an error if the amount is greater than the total bitcoin
// supply.
let payment_secret = self
.channel_manager
.create_inbound_payment_for_hash(payment_hash, amt_msat, invoice_expiry_delta_secs)
.create_inbound_payment_for_hash(
payment_hash,
amt_msat,
invoice_expiry_delta_secs,
min_final_cltv_expiry_delta,
)
.map_to_mm(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?;
let our_node_pubkey = self.channel_manager.get_our_node_id();
// Todo: Check if it's better to use UTC instead of local time for invoice generations
Expand All @@ -462,7 +473,6 @@ impl LightningCoin {
.payment_hash(Hash::from_inner(payment_hash.0))
.payment_secret(payment_secret)
.basic_mpp()
.min_final_cltv_expiry(min_final_cltv_expiry)
.expiry_time(core::time::Duration::from_secs(invoice_expiry_delta_secs.into()));
if let Some(amt) = amt_msat {
invoice = invoice.amount_milli_satoshis(amt);
Expand Down Expand Up @@ -499,7 +509,7 @@ impl LightningCoin {
secret_hash: &[u8],
amount: BigDecimal,
expires_in: u64,
min_final_cltv_expiry: u64,
min_final_cltv_expiry_delta: u64,
) -> Result<Vec<u8>, MmError<PaymentInstructionsErr>> {
// lightning decimals should be 11 in config since the smallest divisible unit in lightning coin is msat
let amt_msat = sat_from_big_decimal(&amount, self.decimals()).map_mm_err()?;
Expand All @@ -511,7 +521,7 @@ impl LightningCoin {
payment_hash,
Some(amt_msat),
"".into(),
min_final_cltv_expiry,
min_final_cltv_expiry_delta,
expires_in.try_into().expect("expires_in shouldn't exceed u32::MAX"),
)
.await
Expand All @@ -524,7 +534,7 @@ impl LightningCoin {
instructions: &[u8],
secret_hash: &[u8],
amount: BigDecimal,
min_final_cltv_expiry: u64,
min_final_cltv_expiry_delta: u64,
) -> Result<PaymentInstructions, MmError<ValidateInstructionsErr>> {
let invoice = Invoice::from_str(&String::from_utf8_lossy(instructions))?;
if invoice.payment_hash().as_inner() != secret_hash
Expand All @@ -544,9 +554,9 @@ impl LightningCoin {
));
}

if invoice.min_final_cltv_expiry() != min_final_cltv_expiry {
if invoice.min_final_cltv_expiry() != min_final_cltv_expiry_delta {
return MmError::err(ValidateInstructionsErr::ValidateLightningInvoiceErr(
"Invalid invoice min_final_cltv_expiry!".into(),
"Invalid invoice min_final_cltv_expiry_delta!".into(),
));
}

Expand Down Expand Up @@ -585,7 +595,7 @@ impl LightningCoin {
match coin.db.get_payment_from_db(payment_hash).await {
Ok(Some(payment)) => {
let amount_claimable = payment.amt_msat;
// Note: locktime doesn't need to be validated since min_final_cltv_expiry should be validated in rust-lightning after fixing the below issue
// Note: locktime doesn't need to be validated since min_final_cltv_expiry_delta should be validated in rust-lightning after fixing the below issue
// https://github.com/lightningdevkit/rust-lightning/issues/1850
// Also, PaymentClaimable won't be fired if amount_claimable < the amount requested in the invoice, this check is probably not needed.
// But keeping it just in case any changes happen in rust-lightning
Expand Down Expand Up @@ -875,10 +885,15 @@ impl SwapOps for LightningCoin {
&self,
args: PaymentInstructionArgs<'_>,
) -> Result<Option<Vec<u8>>, MmError<PaymentInstructionsErr>> {
let min_final_cltv_expiry = self.estimate_blocks_from_duration(args.maker_lock_duration);
self.swap_payment_instructions(args.secret_hash, args.amount, args.expires_in, min_final_cltv_expiry)
.await
.map(Some)
let min_final_cltv_expiry_delta = self.estimate_blocks_from_duration(args.maker_lock_duration);
self.swap_payment_instructions(
args.secret_hash,
args.amount,
args.expires_in,
min_final_cltv_expiry_delta,
)
.await
.map(Some)
}

#[inline]
Expand All @@ -890,7 +905,7 @@ impl SwapOps for LightningCoin {
args.secret_hash,
args.amount,
args.expires_in,
MIN_FINAL_CLTV_EXPIRY as u64,
MIN_FINAL_CLTV_EXPIRY_DELTA as u64,
)
.await
.map(Some)
Expand All @@ -901,8 +916,8 @@ impl SwapOps for LightningCoin {
instructions: &[u8],
args: PaymentInstructionArgs,
) -> Result<PaymentInstructions, MmError<ValidateInstructionsErr>> {
let min_final_cltv_expiry = self.estimate_blocks_from_duration(args.maker_lock_duration);
self.validate_swap_instructions(instructions, args.secret_hash, args.amount, min_final_cltv_expiry)
let min_final_cltv_expiry_delta = self.estimate_blocks_from_duration(args.maker_lock_duration);
self.validate_swap_instructions(instructions, args.secret_hash, args.amount, min_final_cltv_expiry_delta)
}

#[inline]
Expand All @@ -915,7 +930,7 @@ impl SwapOps for LightningCoin {
instructions,
args.secret_hash,
args.amount,
MIN_FINAL_CLTV_EXPIRY as u64,
MIN_FINAL_CLTV_EXPIRY_DELTA as u64,
)
}

Expand Down Expand Up @@ -992,10 +1007,7 @@ impl MarketCoinOps for LightningCoin {
));
}
let message_hash = self.sign_message_hash(message).ok_or(SignatureError::PrefixNotFound)?;
let secret_key = self
.keys_manager
.get_node_secret(Recipient::Node)
.map_err(|_| SignatureError::InternalError("Error accessing node keys".to_string()))?;
let secret_key = self.keys_manager.get_node_secret_key();
let private = Private {
prefix: 239,
secret: H256::from_slice(secret_key.as_ref())
Expand Down Expand Up @@ -1182,12 +1194,7 @@ impl MarketCoinOps for LightningCoin {
}

fn display_priv_key(&self) -> Result<String, String> {
Ok(self
.keys_manager
.get_node_secret(Recipient::Node)
.map_err(|_| "Unsupported recipient".to_string())?
.display_secret()
.to_string())
Ok(self.keys_manager.get_node_secret_key().display_secret().to_string())
}

// This will depend on the route/routes taken for the payment, since every channel's counterparty specifies the minimum amount they will allow to route.
Expand Down Expand Up @@ -1413,27 +1420,32 @@ impl MmCoin for LightningCoin {
let hint = log_err_and_return_false!(Readable::read(&mut Cursor::new(h)));
route_hints.push(hint);
}
let mut payment_params =
PaymentParameters::from_node_id(protocol_info.node_id.into()).with_route_hints(route_hints);
let final_cltv_expiry_delta = if is_maker {
self.estimate_blocks_from_duration(locktime)
.try_into()
.expect("final_cltv_expiry_delta shouldn't exceed u32::MAX")
} else {
MIN_FINAL_CLTV_EXPIRY_DELTA as u32
};
let mut payment_params = PaymentParameters::from_node_id(protocol_info.node_id.into(), final_cltv_expiry_delta)
.with_route_hints(route_hints)
.expect("Payment is initialized as clear payment, so route hints should be valid");
if is_maker {
payment_params.max_total_cltv_expiry_delta = self
.estimate_blocks_from_duration(locktime)
.try_into()
.expect("max_total_cltv_expiry_delta shouldn't exceed u32::MAX");
MIN_FINAL_CLTV_EXPIRY
};
}

drop_mutability!(payment_params);
let route_params = RouteParameters {
payment_params,
final_value_msat,
final_cltv_expiry_delta,
// TODO: We should set a sane limit here on the maximum fee to be paid.
max_total_routing_fee_msat: None,
};
let payer = self.channel_manager.node_id();
let first_hops = self.channel_manager.first_hops();
let payer = self.channel_manager.get_our_node_id();
let first_hops = self.channel_manager.list_usable_channels();
let inflight_htlcs = self.channel_manager.compute_inflight_htlcs();
self.router
.find_route(
Expand Down
Loading
Loading