// licenses.
use crate::blinded_path::BlindedPath;
+use crate::blinded_path::message::ForwardNode;
use crate::blinded_path::payment::ReceiveTlvs;
use crate::chain;
use crate::chain::WatchedOutput;
#[cfg(test)]
use crate::chain::chaininterface::FEERATE_FLOOR_SATS_PER_KW;
use crate::chain::chainmonitor;
-use crate::chain::chainmonitor::{MonitorUpdateId};
use crate::chain::channelmonitor;
use crate::chain::channelmonitor::MonitorEvent;
use crate::chain::transaction::OutPoint;
use crate::sign;
use crate::events;
use crate::events::bump_transaction::{WalletSource, Utxo};
-use crate::ln::ChannelId;
-use crate::ln::channelmanager::{ChannelDetails, self};
+use crate::ln::types::ChannelId;
+use crate::ln::channel_state::ChannelDetails;
+use crate::ln::channelmanager;
#[cfg(test)]
use crate::ln::chan_utils::CommitmentTransaction;
use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
use crate::util::ser::{Readable, ReadableArgs, Writer, Writeable};
use crate::util::persist::KVStore;
+use bitcoin::amount::Amount;
use bitcoin::blockdata::constants::ChainHash;
use bitcoin::blockdata::constants::genesis_block;
use bitcoin::blockdata::transaction::{Transaction, TxOut};
use bitcoin::blockdata::script::{Builder, Script, ScriptBuf};
use bitcoin::blockdata::opcodes;
use bitcoin::blockdata::block::Block;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
use bitcoin::hash_types::{BlockHash, Txid};
+use bitcoin::hashes::Hash;
use bitcoin::sighash::{SighashCache, EcdsaSighashType};
use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, self};
use crate::sync::{Mutex, Arc};
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use core::mem;
-use bitcoin::bech32::u5;
+use bech32::u5;
use crate::sign::{InMemorySigner, RandomBytes, Recipient, EntropySource, NodeSigner, SignerProvider};
#[cfg(feature = "std")]
use std::time::{SystemTime, UNIX_EPOCH};
-use bitcoin::psbt::PartiallySignedTransaction;
+use bitcoin::psbt::Psbt;
use bitcoin::Sequence;
pub fn pubkey(byte: u8) -> PublicKey {
>,
//pub entropy_source: &'a RandomBytes,
pub network_graph: Arc<NetworkGraph<&'a TestLogger>>,
- pub next_routes: Mutex<VecDeque<(RouteParameters, Result<Route, LightningError>)>>,
+ pub next_routes: Mutex<VecDeque<(RouteParameters, Option<Result<Route, LightningError>>)>>,
pub scorer: &'a RwLock<TestScorer>,
}
pub fn expect_find_route(&self, query: RouteParameters, result: Result<Route, LightningError>) {
let mut expected_routes = self.next_routes.lock().unwrap();
- expected_routes.push_back((query, result));
+ expected_routes.push_back((query, Some(result)));
+ }
+
+ pub fn expect_find_route_query(&self, query: RouteParameters) {
+ let mut expected_routes = self.next_routes.lock().unwrap();
+ expected_routes.push_back((query, None));
}
}
let next_route_opt = self.next_routes.lock().unwrap().pop_front();
if let Some((find_route_query, find_route_res)) = next_route_opt {
assert_eq!(find_route_query, *params);
- if let Ok(ref route) = find_route_res {
- assert_eq!(route.route_params, Some(find_route_query));
- let scorer = self.scorer.read().unwrap();
- let scorer = ScorerAccountingForInFlightHtlcs::new(scorer, &inflight_htlcs);
- for path in &route.paths {
- let mut aggregate_msat = 0u64;
- let mut prev_hop_node = payer;
- for (idx, hop) in path.hops.iter().rev().enumerate() {
- aggregate_msat += hop.fee_msat;
- let usage = ChannelUsage {
- amount_msat: aggregate_msat,
- inflight_htlc_msat: 0,
- effective_capacity: EffectiveCapacity::Unknown,
- };
-
- if idx == path.hops.len() - 1 {
- if let Some(first_hops) = first_hops {
- if let Some(idx) = first_hops.iter().position(|h| h.get_outbound_payment_scid() == Some(hop.short_channel_id)) {
- let node_id = NodeId::from_pubkey(payer);
- let candidate = CandidateRouteHop::FirstHop(FirstHopCandidate {
- details: first_hops[idx],
- payer_node_id: &node_id,
- });
- scorer.channel_penalty_msat(&candidate, usage, &Default::default());
- continue;
+ if let Some(res) = find_route_res {
+ if let Ok(ref route) = res {
+ assert_eq!(route.route_params, Some(find_route_query));
+ let scorer = self.scorer.read().unwrap();
+ let scorer = ScorerAccountingForInFlightHtlcs::new(scorer, &inflight_htlcs);
+ for path in &route.paths {
+ let mut aggregate_msat = 0u64;
+ let mut prev_hop_node = payer;
+ for (idx, hop) in path.hops.iter().rev().enumerate() {
+ aggregate_msat += hop.fee_msat;
+ let usage = ChannelUsage {
+ amount_msat: aggregate_msat,
+ inflight_htlc_msat: 0,
+ effective_capacity: EffectiveCapacity::Unknown,
+ };
+
+ if idx == path.hops.len() - 1 {
+ if let Some(first_hops) = first_hops {
+ if let Some(idx) = first_hops.iter().position(|h| h.get_outbound_payment_scid() == Some(hop.short_channel_id)) {
+ let node_id = NodeId::from_pubkey(payer);
+ let candidate = CandidateRouteHop::FirstHop(FirstHopCandidate {
+ details: first_hops[idx],
+ payer_node_id: &node_id,
+ });
+ scorer.channel_penalty_msat(&candidate, usage, &Default::default());
+ continue;
+ }
}
}
+ let network_graph = self.network_graph.read_only();
+ if let Some(channel) = network_graph.channel(hop.short_channel_id) {
+ let (directed, _) = channel.as_directed_to(&NodeId::from_pubkey(&hop.pubkey)).unwrap();
+ let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate {
+ info: directed,
+ short_channel_id: hop.short_channel_id,
+ });
+ scorer.channel_penalty_msat(&candidate, usage, &Default::default());
+ } else {
+ let target_node_id = NodeId::from_pubkey(&hop.pubkey);
+ let route_hint = RouteHintHop {
+ src_node_id: *prev_hop_node,
+ short_channel_id: hop.short_channel_id,
+ fees: RoutingFees { base_msat: 0, proportional_millionths: 0 },
+ cltv_expiry_delta: 0,
+ htlc_minimum_msat: None,
+ htlc_maximum_msat: None,
+ };
+ let candidate = CandidateRouteHop::PrivateHop(PrivateHopCandidate {
+ hint: &route_hint,
+ target_node_id: &target_node_id,
+ });
+ scorer.channel_penalty_msat(&candidate, usage, &Default::default());
+ }
+ prev_hop_node = &hop.pubkey;
}
- let network_graph = self.network_graph.read_only();
- if let Some(channel) = network_graph.channel(hop.short_channel_id) {
- let (directed, _) = channel.as_directed_to(&NodeId::from_pubkey(&hop.pubkey)).unwrap();
- let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate {
- info: directed,
- short_channel_id: hop.short_channel_id,
- });
- scorer.channel_penalty_msat(&candidate, usage, &Default::default());
- } else {
- let target_node_id = NodeId::from_pubkey(&hop.pubkey);
- let route_hint = RouteHintHop {
- src_node_id: *prev_hop_node,
- short_channel_id: hop.short_channel_id,
- fees: RoutingFees { base_msat: 0, proportional_millionths: 0 },
- cltv_expiry_delta: 0,
- htlc_minimum_msat: None,
- htlc_maximum_msat: None,
- };
- let candidate = CandidateRouteHop::PrivateHop(PrivateHopCandidate {
- hint: &route_hint,
- target_node_id: &target_node_id,
- });
- scorer.channel_penalty_msat(&candidate, usage, &Default::default());
- }
- prev_hop_node = &hop.pubkey;
}
}
+ route_res = res;
+ } else {
+ route_res = self.router.find_route(payer, params, first_hops, inflight_htlcs);
}
- route_res = find_route_res;
} else {
route_res = self.router.find_route(payer, params, first_hops, inflight_htlcs);
};
) -> Result<Vec<BlindedPath>, ()> {
self.router.create_blinded_paths(recipient, peers, secp_ctx)
}
+
+ fn create_compact_blinded_paths<
+ T: secp256k1::Signing + secp256k1::Verification
+ >(
+ &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+ ) -> Result<Vec<BlindedPath>, ()> {
+ self.router.create_compact_blinded_paths(recipient, peers, secp_ctx)
+ }
}
impl<'a> Drop for TestRouter<'a> {
) -> Result<Vec<BlindedPath>, ()> {
self.inner.create_blinded_paths(recipient, peers, secp_ctx)
}
+
+ fn create_compact_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
+ &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+ ) -> Result<Vec<BlindedPath>, ()> {
+ self.inner.create_compact_blinded_paths(recipient, peers, secp_ctx)
+ }
}
pub struct OnlyReadsKeysInterface {}
pub struct TestChainMonitor<'a> {
pub added_monitors: Mutex<Vec<(OutPoint, channelmonitor::ChannelMonitor<TestChannelSigner>)>>,
pub monitor_updates: Mutex<HashMap<ChannelId, Vec<channelmonitor::ChannelMonitorUpdate>>>,
- pub latest_monitor_update_id: Mutex<HashMap<ChannelId, (OutPoint, u64, MonitorUpdateId)>>,
+ pub latest_monitor_update_id: Mutex<HashMap<ChannelId, (OutPoint, u64, u64)>>,
pub chain_monitor: chainmonitor::ChainMonitor<TestChannelSigner, &'a TestChainSource, &'a dyn chaininterface::BroadcasterInterface, &'a TestFeeEstimator, &'a TestLogger, &'a dyn chainmonitor::Persist<TestChannelSigner>>,
pub keys_manager: &'a TestKeysInterface,
/// If this is set to Some(), the next update_channel call (not watch_channel) must be a
&mut io::Cursor::new(&w.0), (self.keys_manager, self.keys_manager)).unwrap().1;
assert!(new_monitor == monitor);
self.latest_monitor_update_id.lock().unwrap().insert(monitor.channel_id(),
- (funding_txo, monitor.get_latest_update_id(), MonitorUpdateId::from_new_monitor(&monitor)));
+ (funding_txo, monitor.get_latest_update_id(), monitor.get_latest_update_id()));
self.added_monitors.lock().unwrap().push((funding_txo, monitor));
self.chain_monitor.watch_channel(funding_txo, new_monitor)
}
}
self.latest_monitor_update_id.lock().unwrap().insert(channel_id,
- (funding_txo, update.update_id, MonitorUpdateId::from_monitor_update(update)));
+ (funding_txo, update.update_id, update.update_id));
let update_res = self.chain_monitor.update_channel(funding_txo, update);
// At every point where we get a monitor update, we should be able to send a useful monitor
// to a watchtower and disk...
#[cfg(test)]
struct JusticeTxData {
justice_tx: Transaction,
- value: u64,
+ value: Amount,
commitment_number: u64,
}
}
#[cfg(test)]
-impl<Signer: sign::ecdsa::WriteableEcdsaChannelSigner> chainmonitor::Persist<Signer> for WatchtowerPersister {
+impl<Signer: sign::ecdsa::EcdsaChannelSigner> chainmonitor::Persist<Signer> for WatchtowerPersister {
fn persist_new_channel(&self, funding_txo: OutPoint,
- data: &channelmonitor::ChannelMonitor<Signer>, id: MonitorUpdateId
+ data: &channelmonitor::ChannelMonitor<Signer>
) -> chain::ChannelMonitorUpdateStatus {
- let res = self.persister.persist_new_channel(funding_txo, data, id);
+ let res = self.persister.persist_new_channel(funding_txo, data);
assert!(self.unsigned_justice_tx_data.lock().unwrap()
.insert(funding_txo, VecDeque::new()).is_none());
fn update_persisted_channel(
&self, funding_txo: OutPoint, update: Option<&channelmonitor::ChannelMonitorUpdate>,
- data: &channelmonitor::ChannelMonitor<Signer>, update_id: MonitorUpdateId
+ data: &channelmonitor::ChannelMonitor<Signer>
) -> chain::ChannelMonitorUpdateStatus {
- let res = self.persister.update_persisted_channel(funding_txo, update, data, update_id);
+ let res = self.persister.update_persisted_channel(funding_txo, update, data);
if let Some(update) = update {
let commitment_txs = data.counterparty_commitment_txs_from_update(update);
while let Some(JusticeTxData { justice_tx, value, commitment_number }) = channel_state.front() {
let input_idx = 0;
let commitment_txid = justice_tx.input[input_idx].previous_output.txid;
- match data.sign_to_local_justice_tx(justice_tx.clone(), input_idx, *value, *commitment_number) {
+ match data.sign_to_local_justice_tx(justice_tx.clone(), input_idx, value.to_sat(), *commitment_number) {
Ok(signed_justice_tx) => {
let dup = self.watchtower_state.lock().unwrap()
.get_mut(&funding_txo).unwrap()
/// The queue of update statuses we'll return. If none are queued, ::Completed will always be
/// returned.
pub update_rets: Mutex<VecDeque<chain::ChannelMonitorUpdateStatus>>,
- /// When we get an update_persisted_channel call with no ChannelMonitorUpdate, we insert the
- /// MonitorUpdateId here.
- pub chain_sync_monitor_persistences: Mutex<VecDeque<OutPoint>>,
/// When we get an update_persisted_channel call *with* a ChannelMonitorUpdate, we insert the
- /// MonitorUpdateId here.
- pub offchain_monitor_updates: Mutex<HashMap<OutPoint, HashSet<MonitorUpdateId>>>,
+ /// [`ChannelMonitor::get_latest_update_id`] here.
+ ///
+ /// [`ChannelMonitor`]: channelmonitor::ChannelMonitor
+ pub offchain_monitor_updates: Mutex<HashMap<OutPoint, HashSet<u64>>>,
}
impl TestPersister {
pub fn new() -> Self {
Self {
update_rets: Mutex::new(VecDeque::new()),
- chain_sync_monitor_persistences: Mutex::new(VecDeque::new()),
offchain_monitor_updates: Mutex::new(new_hash_map()),
}
}
self.update_rets.lock().unwrap().push_back(next_ret);
}
}
-impl<Signer: sign::ecdsa::WriteableEcdsaChannelSigner> chainmonitor::Persist<Signer> for TestPersister {
- fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor<Signer>, _id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus {
+impl<Signer: sign::ecdsa::EcdsaChannelSigner> chainmonitor::Persist<Signer> for TestPersister {
+ fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor<Signer>) -> chain::ChannelMonitorUpdateStatus {
if let Some(update_ret) = self.update_rets.lock().unwrap().pop_front() {
return update_ret
}
chain::ChannelMonitorUpdateStatus::Completed
}
- fn update_persisted_channel(&self, funding_txo: OutPoint, update: Option<&channelmonitor::ChannelMonitorUpdate>, _data: &channelmonitor::ChannelMonitor<Signer>, update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus {
+ fn update_persisted_channel(&self, funding_txo: OutPoint, update: Option<&channelmonitor::ChannelMonitorUpdate>, _data: &channelmonitor::ChannelMonitor<Signer>) -> chain::ChannelMonitorUpdateStatus {
let mut ret = chain::ChannelMonitorUpdateStatus::Completed;
if let Some(update_ret) = self.update_rets.lock().unwrap().pop_front() {
ret = update_ret;
}
- if update.is_some() {
- self.offchain_monitor_updates.lock().unwrap().entry(funding_txo).or_insert(new_hash_set()).insert(update_id);
- } else {
- self.chain_sync_monitor_persistences.lock().unwrap().push_back(funding_txo);
+ if let Some(update) = update {
+ self.offchain_monitor_updates.lock().unwrap().entry(funding_txo).or_insert(new_hash_set()).insert(update.update_id);
}
ret
}
- fn archive_persisted_channel(&self, funding_txo: OutPoint) {
+ fn archive_persisted_channel(&self, funding_txo: OutPoint) {
// remove the channel from the offchain_monitor_updates map
- match self.offchain_monitor_updates.lock().unwrap().remove(&funding_txo) {
- Some(_) => {},
- None => {
- // If the channel was not in the offchain_monitor_updates map, it should be in the
- // chain_sync_monitor_persistences map.
- self.chain_sync_monitor_persistences.lock().unwrap().retain(|x| x != &funding_txo);
- }
- };
+ self.offchain_monitor_updates.lock().unwrap().remove(&funding_txo);
}
}
Ok(SharedSecret::new(other_key, &node_secret))
}
- fn sign_invoice(&self, _: &[u8], _: &[bitcoin::bech32::u5], _: Recipient) -> Result<bitcoin::secp256k1::ecdsa::RecoverableSignature, ()> {
+ fn sign_invoice(&self, _: &[u8], _: &[bech32::u5], _: Recipient) -> Result<bitcoin::secp256k1::ecdsa::RecoverableSignature, ()> {
unreachable!()
}
let script_pubkey = Builder::new().push_opcode(opcodes::OP_TRUE).into_script();
Self {
chain_hash: ChainHash::using_genesis_block(network),
- utxo_ret: Mutex::new(UtxoResult::Sync(Ok(TxOut { value: u64::max_value(), script_pubkey }))),
+ utxo_ret: Mutex::new(UtxoResult::Sync(Ok(TxOut { value: Amount::MAX, script_pubkey }))),
get_utxo_call_count: AtomicUsize::new(0),
watched_txn: Mutex::new(new_hash_set()),
watched_outputs: Mutex::new(new_hash_set()),
}
}
pub fn remove_watched_txn_and_outputs(&self, outpoint: OutPoint, script_pubkey: ScriptBuf) {
- self.watched_outputs.lock().unwrap().remove(&(outpoint, script_pubkey.clone()));
+ self.watched_outputs.lock().unwrap().remove(&(outpoint, script_pubkey.clone()));
self.watched_txn.lock().unwrap().remove(&(outpoint.txid, script_pubkey));
}
}
}
}
- pub fn add_utxo(&self, outpoint: bitcoin::OutPoint, value: u64) -> TxOut {
+ pub fn add_utxo(&self, outpoint: bitcoin::OutPoint, value: Amount) -> TxOut {
let public_key = bitcoin::PublicKey::new(self.secret_key.public_key(&self.secp));
let utxo = Utxo::new_p2pkh(outpoint, value, &public_key.pubkey_hash());
self.utxos.borrow_mut().push(utxo.clone());
Ok(ScriptBuf::new_p2pkh(&public_key.pubkey_hash()))
}
- fn sign_psbt(&self, psbt: PartiallySignedTransaction) -> Result<Transaction, ()> {
- let mut tx = psbt.extract_tx();
+ fn sign_psbt(&self, psbt: Psbt) -> Result<Transaction, ()> {
+ let mut tx = psbt.extract_tx_unchecked_fee_rate();
let utxos = self.utxos.borrow();
for i in 0..tx.input.len() {
if let Some(utxo) = utxos.iter().find(|utxo| utxo.outpoint == tx.input[i].previous_output) {
let sighash = SighashCache::new(&tx)
.legacy_signature_hash(i, &utxo.output.script_pubkey, EcdsaSighashType::All as u32)
.map_err(|_| ())?;
- let sig = self.secp.sign_ecdsa(&(*sighash.as_raw_hash()).into(), &self.secret_key);
+ let sig = self.secp.sign_ecdsa(&secp256k1::Message::from_digest(sighash.to_byte_array()), &self.secret_key);
let bitcoin_sig = bitcoin::ecdsa::Signature { sig, hash_ty: EcdsaSighashType::All };
tx.input[i].script_sig = Builder::new()
.push_slice(&bitcoin_sig.serialize())