Merge pull request #649 from jkczyz/2020-06-refactor-chain-listener

Refactor chain monitoring
This commit is contained in:
Matt Corallo 2020-10-01 11:10:13 -07:00 committed by GitHub
commit 8fb4a3ddc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 1242 additions and 1425 deletions

46
ARCH.md
View file

@ -6,7 +6,7 @@ need to use are `ChannelManager` and `ChannelMonitor`. `ChannelManager` holds mu
channels, routes payments between them, and exposes a simple API to make and receive
payments. Individual `ChannelMonitor`s monitor the on-chain state of a channel, punish
counterparties if they misbehave, and force-close channels if they contain unresolved
HTLCs which are near expiration. The `ManyChannelMonitor` API provides a way for you to
HTLCs which are near expiration. The `chain::Watch` interface provides a way for you to
receive `ChannelMonitorUpdate`s from `ChannelManager` and persist them to disk before the
channel steps forward.
@ -37,26 +37,26 @@ At a high level, some of the common interfaces fit together as follows:
-----------------
| KeysInterface | --------------
----------------- | UserConfig |
-------------------- | --------------
/------| MessageSendEvent | | | ----------------
| -------------------- | | | FeeEstimator |
| (as MessageSendEventsProvider) | | ----------------
| ^ | | / | ------------------------
| \ | | / ---------> | BroadcasterInterface |
| \ | | / / | ------------------------
| \ v v v / v ^
| (as ------------------ ----------------------
| ChannelMessageHandler)-> | ChannelManager | ----> | ManyChannelMonitor |
v / ------------------ ----------------------
--------------- / ^ (as EventsProvider) ^
| PeerManager |- | \ / /
--------------- | -------\---/----------
| ----------------------- / \ /
| | ChainWatchInterface | - v
| ----------------------- ---------
| | | Event |
(as RoutingMessageHandler) v ---------
\ --------------------
-----------------> | NetGraphMsgHandler |
--------------------
-------------------- ^ --------------
------| MessageSendEvent | | ^ ----------------
/ -------------------- | | | FeeEstimator | <-----------------------
| (as MessageSendEventsProvider) | | ---------------- \
| ^ | | ^ ------------------------ |
| \ | | / ---------> | BroadcasterInterface | |
| \ | | / / ------------------------ |
| \ | | / / ^ |
| (as ------------------ ---------------- | |
| ChannelMessageHandler)-> | ChannelManager | ----> | chain::Watch | | |
v / ------------------ ---------------- | |
--------------- / (as EventsProvider) ^ | |
| PeerManager |- \ | | |
--------------- \ | (is-a) | |
| ----------------- \ _---------------- / /
| | chain::Access | \ / | ChainMonitor |---------------
| ----------------- \ / ----------------
| ^ \ / |
(as RoutingMessageHandler) | v v
\ ---------------------- --------- -----------------
-----------------> | NetGraphMsgHandler | | Event | | chain::Filter |
---------------------- --------- -----------------
```

View file

@ -28,12 +28,13 @@ use bitcoin::hashes::Hash as TraitImport;
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hash_types::{BlockHash, WPubkeyHash};
use lightning::chain::chaininterface;
use lightning::chain;
use lightning::chain::chainmonitor;
use lightning::chain::channelmonitor;
use lightning::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, MonitorEvent};
use lightning::chain::transaction::OutPoint;
use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil,ChainWatchInterface};
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
use lightning::chain::keysinterface::{KeysInterface, InMemoryChannelKeys};
use lightning::ln::channelmonitor;
use lightning::ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, MonitorEvent};
use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, ChannelManagerReadArgs};
use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, ErrorAction, UpdateAddHTLC, Init};
@ -81,9 +82,9 @@ impl Writer for VecWriter {
}
}
struct TestChannelMonitor {
struct TestChainMonitor {
pub logger: Arc<dyn Logger>,
pub simple_monitor: Arc<channelmonitor::SimpleManyChannelMonitor<OutPoint, EnforcingChannelKeys, Arc<TestBroadcaster>, Arc<FuzzEstimator>, Arc<dyn Logger>, Arc<dyn ChainWatchInterface>>>,
pub chain_monitor: Arc<chainmonitor::ChainMonitor<EnforcingChannelKeys, Arc<dyn chain::Filter>, Arc<TestBroadcaster>, Arc<FuzzEstimator>, Arc<dyn Logger>>>,
pub update_ret: Mutex<Result<(), channelmonitor::ChannelMonitorUpdateErr>>,
// If we reload a node with an old copy of ChannelMonitors, the ChannelManager deserialization
// logic will automatically force-close our channels for us (as we don't have an up-to-date
@ -93,10 +94,10 @@ struct TestChannelMonitor {
pub latest_monitors: Mutex<HashMap<OutPoint, (u64, Vec<u8>)>>,
pub should_update_manager: atomic::AtomicBool,
}
impl TestChannelMonitor {
pub fn new(chain_monitor: Arc<dyn chaininterface::ChainWatchInterface>, broadcaster: Arc<TestBroadcaster>, logger: Arc<dyn Logger>, feeest: Arc<FuzzEstimator>) -> Self {
impl TestChainMonitor {
pub fn new(broadcaster: Arc<TestBroadcaster>, logger: Arc<dyn Logger>, feeest: Arc<FuzzEstimator>) -> Self {
Self {
simple_monitor: Arc::new(channelmonitor::SimpleManyChannelMonitor::new(chain_monitor, broadcaster, logger.clone(), feeest)),
chain_monitor: Arc::new(chainmonitor::ChainMonitor::new(None, broadcaster, logger.clone(), feeest)),
logger,
update_ret: Mutex::new(Ok(())),
latest_monitors: Mutex::new(HashMap::new()),
@ -104,21 +105,21 @@ impl TestChannelMonitor {
}
}
}
impl channelmonitor::ManyChannelMonitor for TestChannelMonitor {
impl chain::Watch for TestChainMonitor {
type Keys = EnforcingChannelKeys;
fn add_monitor(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor<EnforcingChannelKeys>) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor<EnforcingChannelKeys>) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
let mut ser = VecWriter(Vec::new());
monitor.write_for_disk(&mut ser).unwrap();
if let Some(_) = self.latest_monitors.lock().unwrap().insert(funding_txo, (monitor.get_latest_update_id(), ser.0)) {
panic!("Already had monitor pre-add_monitor");
panic!("Already had monitor pre-watch_channel");
}
self.should_update_manager.store(true, atomic::Ordering::Relaxed);
assert!(self.simple_monitor.add_monitor(funding_txo, monitor).is_ok());
assert!(self.chain_monitor.watch_channel(funding_txo, monitor).is_ok());
self.update_ret.lock().unwrap().clone()
}
fn update_monitor(&self, funding_txo: OutPoint, update: channelmonitor::ChannelMonitorUpdate) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
fn update_channel(&self, funding_txo: OutPoint, update: channelmonitor::ChannelMonitorUpdate) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
let mut map_lock = self.latest_monitors.lock().unwrap();
let mut map_entry = match map_lock.entry(funding_txo) {
hash_map::Entry::Occupied(entry) => entry,
@ -134,8 +135,8 @@ impl channelmonitor::ManyChannelMonitor for TestChannelMonitor {
self.update_ret.lock().unwrap().clone()
}
fn get_and_clear_pending_monitor_events(&self) -> Vec<MonitorEvent> {
return self.simple_monitor.get_and_clear_pending_monitor_events();
fn release_pending_monitor_events(&self) -> Vec<MonitorEvent> {
return self.chain_monitor.release_pending_monitor_events();
}
}
@ -191,8 +192,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
macro_rules! make_node {
($node_id: expr) => { {
let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new($node_id.to_string(), out.clone()));
let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin));
let monitor = Arc::new(TestChannelMonitor::new(watch.clone(), broadcast.clone(), logger.clone(), fee_est.clone()));
let monitor = Arc::new(TestChainMonitor::new(broadcast.clone(), logger.clone(), fee_est.clone()));
let keys_manager = Arc::new(KeyProvider { node_id: $node_id, rand_bytes_id: atomic::AtomicU8::new(0) });
let mut config = UserConfig::default();
@ -207,8 +207,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
macro_rules! reload_node {
($ser: expr, $node_id: expr, $old_monitors: expr) => { {
let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new($node_id.to_string(), out.clone()));
let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin));
let monitor = Arc::new(TestChannelMonitor::new(watch.clone(), broadcast.clone(), logger.clone(), fee_est.clone()));
let chain_monitor = Arc::new(TestChainMonitor::new(broadcast.clone(), logger.clone(), fee_est.clone()));
let keys_manager = Arc::new(KeyProvider { node_id: $node_id, rand_bytes_id: atomic::AtomicU8::new(0) });
let mut config = UserConfig::default();
@ -220,7 +219,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
let mut old_monitors = $old_monitors.latest_monitors.lock().unwrap();
for (outpoint, (update_id, monitor_ser)) in old_monitors.drain() {
monitors.insert(outpoint, <(BlockHash, ChannelMonitor<EnforcingChannelKeys>)>::read(&mut Cursor::new(&monitor_ser)).expect("Failed to read monitor").1);
monitor.latest_monitors.lock().unwrap().insert(outpoint, (update_id, monitor_ser));
chain_monitor.latest_monitors.lock().unwrap().insert(outpoint, (update_id, monitor_ser));
}
let mut monitor_refs = HashMap::new();
for (outpoint, monitor) in monitors.iter_mut() {
@ -230,14 +229,14 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
let read_args = ChannelManagerReadArgs {
keys_manager,
fee_estimator: fee_est.clone(),
monitor: monitor.clone(),
chain_monitor: chain_monitor.clone(),
tx_broadcaster: broadcast.clone(),
logger,
default_config: config,
channel_monitors: monitor_refs,
};
(<(BlockHash, ChannelManager<EnforcingChannelKeys, Arc<TestChannelMonitor>, Arc<TestBroadcaster>, Arc<KeyProvider>, Arc<FuzzEstimator>, Arc<dyn Logger>>)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor)
(<(BlockHash, ChannelManager<EnforcingChannelKeys, Arc<TestChainMonitor>, Arc<TestBroadcaster>, Arc<KeyProvider>, Arc<FuzzEstimator>, Arc<dyn Logger>>)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, chain_monitor)
} }
}
@ -308,16 +307,11 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
macro_rules! confirm_txn {
($node: expr) => { {
let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
let mut txn = Vec::with_capacity(channel_txn.len());
let mut posn = Vec::with_capacity(channel_txn.len());
for i in 0..channel_txn.len() {
txn.push(&channel_txn[i]);
posn.push(i + 1);
}
$node.block_connected(&header, 1, &txn, &posn);
let txdata: Vec<_> = channel_txn.iter().enumerate().map(|(i, tx)| (i + 1, tx)).collect();
$node.block_connected(&header, &txdata, 1);
for i in 2..100 {
header = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
$node.block_connected(&header, i, &Vec::new(), &[0; 0]);
$node.block_connected(&header, &[], i);
}
} }
}

View file

@ -3,8 +3,8 @@
use bitcoin::hash_types::BlockHash;
use lightning::chain::channelmonitor;
use lightning::util::enforcing_trait_impls::EnforcingChannelKeys;
use lightning::ln::channelmonitor;
use lightning::util::ser::{Readable, Writer};
use utils::test_logger;

View file

@ -25,10 +25,11 @@ use bitcoin::hashes::HashEngine as TraitImportEngine;
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil};
use lightning::chain;
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
use lightning::chain::chainmonitor;
use lightning::chain::transaction::OutPoint;
use lightning::chain::keysinterface::{InMemoryChannelKeys, KeysInterface};
use lightning::ln::channelmonitor;
use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret};
use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor};
use lightning::routing::router::get_route;
@ -144,14 +145,13 @@ impl<'a> std::hash::Hash for Peer<'a> {
type ChannelMan = ChannelManager<
EnforcingChannelKeys,
Arc<channelmonitor::SimpleManyChannelMonitor<OutPoint, EnforcingChannelKeys, Arc<TestBroadcaster>, Arc<FuzzEstimator>, Arc<dyn Logger>, Arc<ChainWatchInterfaceUtil>>>,
Arc<chainmonitor::ChainMonitor<EnforcingChannelKeys, Arc<dyn chain::Filter>, Arc<TestBroadcaster>, Arc<FuzzEstimator>, Arc<dyn Logger>>>,
Arc<TestBroadcaster>, Arc<KeyProvider>, Arc<FuzzEstimator>, Arc<dyn Logger>>;
type PeerMan<'a> = PeerManager<Peer<'a>, Arc<ChannelMan>, Arc<NetGraphMsgHandler<Arc<ChainWatchInterfaceUtil>, Arc<dyn Logger>>>, Arc<dyn Logger>>;
type PeerMan<'a> = PeerManager<Peer<'a>, Arc<ChannelMan>, Arc<NetGraphMsgHandler<Arc<dyn chain::Access>, Arc<dyn Logger>>>, Arc<dyn Logger>>;
struct MoneyLossDetector<'a> {
manager: Arc<ChannelMan>,
monitor: Arc<channelmonitor::SimpleManyChannelMonitor<
OutPoint, EnforcingChannelKeys, Arc<TestBroadcaster>, Arc<FuzzEstimator>, Arc<dyn Logger>, Arc<ChainWatchInterfaceUtil>>>,
monitor: Arc<chainmonitor::ChainMonitor<EnforcingChannelKeys, Arc<dyn chain::Filter>, Arc<TestBroadcaster>, Arc<FuzzEstimator>, Arc<dyn Logger>>>,
handler: PeerMan<'a>,
peers: &'a RefCell<[bool; 256]>,
@ -165,7 +165,7 @@ struct MoneyLossDetector<'a> {
impl<'a> MoneyLossDetector<'a> {
pub fn new(peers: &'a RefCell<[bool; 256]>,
manager: Arc<ChannelMan>,
monitor: Arc<channelmonitor::SimpleManyChannelMonitor<OutPoint, EnforcingChannelKeys, Arc<TestBroadcaster>, Arc<FuzzEstimator>, Arc<dyn Logger>, Arc<ChainWatchInterfaceUtil>>>,
monitor: Arc<chainmonitor::ChainMonitor<EnforcingChannelKeys, Arc<dyn chain::Filter>, Arc<TestBroadcaster>, Arc<FuzzEstimator>, Arc<dyn Logger>>>,
handler: PeerMan<'a>) -> Self {
MoneyLossDetector {
manager,
@ -183,15 +183,13 @@ impl<'a> MoneyLossDetector<'a> {
}
fn connect_block(&mut self, all_txn: &[Transaction]) {
let mut txn = Vec::with_capacity(all_txn.len());
let mut txn_idxs = Vec::with_capacity(all_txn.len());
let mut txdata = Vec::with_capacity(all_txn.len());
for (idx, tx) in all_txn.iter().enumerate() {
let txid = tx.txid();
match self.txids_confirmed.entry(txid) {
hash_map::Entry::Vacant(e) => {
e.insert(self.height);
txn.push(tx);
txn_idxs.push(idx + 1);
txdata.push((idx + 1, tx));
},
_ => {},
}
@ -200,8 +198,8 @@ impl<'a> MoneyLossDetector<'a> {
let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: self.blocks_connected, bits: 42, nonce: 42 };
self.height += 1;
self.blocks_connected += 1;
self.manager.block_connected(&header, self.height as u32, &txn[..], &txn_idxs[..]);
(*self.monitor).block_connected(&header, self.height as u32, &txn[..], &txn_idxs[..]);
self.manager.block_connected(&header, &txdata, self.height as u32);
(*self.monitor).block_connected(&header, &txdata, self.height as u32);
if self.header_hashes.len() > self.height {
self.header_hashes[self.height] = header.block_hash();
} else {
@ -214,7 +212,7 @@ impl<'a> MoneyLossDetector<'a> {
fn disconnect_block(&mut self) {
if self.height > 0 && (self.max_height < 6 || self.height >= self.max_height - 6) {
let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
self.manager.block_disconnected(&header, self.height as u32);
self.manager.block_disconnected(&header);
self.monitor.block_disconnected(&header, self.height as u32);
self.height -= 1;
let removal_height = self.height;
@ -334,9 +332,8 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
Err(_) => return,
};
let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin));
let broadcast = Arc::new(TestBroadcaster{});
let monitor = Arc::new(channelmonitor::SimpleManyChannelMonitor::new(watch.clone(), broadcast.clone(), Arc::clone(&logger), fee_est.clone()));
let monitor = Arc::new(chainmonitor::ChainMonitor::new(None, broadcast.clone(), Arc::clone(&logger), fee_est.clone()));
let keys_manager = Arc::new(KeyProvider { node_secret: our_network_key.clone(), counter: AtomicU64::new(0) });
let mut config = UserConfig::default();
@ -345,7 +342,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
config.peer_channel_config_limits.min_dust_limit_satoshis = 0;
let channelmanager = Arc::new(ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0));
let our_id = PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret());
let net_graph_msg_handler = Arc::new(NetGraphMsgHandler::new(watch.clone(), Arc::clone(&logger)));
let net_graph_msg_handler = Arc::new(NetGraphMsgHandler::new(None, Arc::clone(&logger)));
let peers = RefCell::new([false; 256]);
let mut loss_detector = MoneyLossDetector::new(&peers, channelmanager.clone(), monitor.clone(), PeerManager::new(MessageHandler {
@ -903,6 +900,6 @@ mod tests {
assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 with 1 adds, 0 fulfills, 0 fails for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 7
assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 1 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 8
assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 1 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&2)); // 9
assert_eq!(log_entries.get(&("lightning::ln::channelmonitor".to_string(), "Input spending counterparty commitment tx (00000000000000000000000000000000000000000000000000000000000000a1:0) in 0000000000000000000000000000000000000000000000000000000000000018 resolves outbound HTLC with payment hash ff00000000000000000000000000000000000000000000000000000000000000 with timeout".to_string())), Some(&1)); // 10
assert_eq!(log_entries.get(&("lightning::chain::channelmonitor".to_string(), "Input spending counterparty commitment tx (00000000000000000000000000000000000000000000000000000000000000a1:0) in 0000000000000000000000000000000000000000000000000000000000000018 resolves outbound HTLC with payment hash ff00000000000000000000000000000000000000000000000000000000000000 with timeout".to_string())), Some(&1)); // 10
}
}

View file

@ -7,11 +7,11 @@
// You may not use this file except in accordance with one or both of these
// licenses.
use bitcoin::blockdata::script::{Script, Builder};
use bitcoin::blockdata::block::Block;
use bitcoin::hash_types::{Txid, BlockHash};
use bitcoin::blockdata::script::Builder;
use bitcoin::blockdata::transaction::TxOut;
use bitcoin::hash_types::BlockHash;
use lightning::chain::chaininterface::{ChainError,ChainWatchInterface};
use lightning::chain;
use lightning::ln::channelmanager::ChannelDetails;
use lightning::ln::features::InitFeatures;
use lightning::ln::msgs;
@ -76,26 +76,16 @@ impl InputData {
}
}
struct DummyChainWatcher {
struct FuzzChainSource {
input: Arc<InputData>,
}
impl ChainWatchInterface for DummyChainWatcher {
fn install_watch_tx(&self, _txid: &Txid, _script_pub_key: &Script) { }
fn install_watch_outpoint(&self, _outpoint: (Txid, u32), _out_script: &Script) { }
fn watch_all_txn(&self) { }
fn filter_block(&self, _block: &Block) -> Vec<usize> {
Vec::new()
}
fn reentered(&self) -> usize { 0 }
fn get_chain_utxo(&self, _genesis_hash: BlockHash, _unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError> {
impl chain::Access for FuzzChainSource {
fn get_utxo(&self, _genesis_hash: &BlockHash, _short_channel_id: u64) -> Result<TxOut, chain::AccessError> {
match self.input.get_slice(2) {
Some(&[0, _]) => Err(ChainError::NotSupported),
Some(&[1, _]) => Err(ChainError::NotWatched),
Some(&[2, _]) => Err(ChainError::UnknownTx),
Some(&[_, x]) => Ok((Builder::new().push_int(x as i64).into_script().to_v0_p2wsh(), 0)),
None => Err(ChainError::UnknownTx),
Some(&[0, _]) => Err(chain::AccessError::UnknownChain),
Some(&[1, _]) => Err(chain::AccessError::UnknownTx),
Some(&[_, x]) => Ok(TxOut { value: 0, script_pubkey: Builder::new().push_int(x as i64).into_script().to_v0_p2wsh() }),
None => Err(chain::AccessError::UnknownTx),
_ => unreachable!(),
}
}
@ -160,12 +150,16 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
}
let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new("".to_owned(), out));
let chain_monitor = Arc::new(DummyChainWatcher {
input: Arc::clone(&input),
});
let chain_source = if get_slice!(1)[0] % 2 == 0 {
None
} else {
Some(Arc::new(FuzzChainSource {
input: Arc::clone(&input),
}))
};
let our_pubkey = get_pubkey!();
let net_graph_msg_handler = NetGraphMsgHandler::new(chain_monitor, Arc::clone(&logger));
let net_graph_msg_handler = NetGraphMsgHandler::new(chain_source, Arc::clone(&logger));
loop {
match get_slice!(1)[0] {

View file

@ -34,13 +34,14 @@
//! type TxBroadcaster = dyn lightning::chain::chaininterface::BroadcasterInterface;
//! type FeeEstimator = dyn lightning::chain::chaininterface::FeeEstimator;
//! type Logger = dyn lightning::util::logger::Logger;
//! type ChainWatchInterface = dyn lightning::chain::chaininterface::ChainWatchInterface;
//! type ChannelMonitor = lightning::ln::channelmonitor::SimpleManyChannelMonitor<lightning::chain::transaction::OutPoint, lightning::chain::keysinterface::InMemoryChannelKeys, Arc<TxBroadcaster>, Arc<FeeEstimator>, Arc<Logger>, Arc<ChainWatchInterface>>;
//! type ChannelManager = lightning::ln::channelmanager::SimpleArcChannelManager<ChannelMonitor, TxBroadcaster, FeeEstimator, Logger>;
//! type PeerManager = lightning::ln::peer_handler::SimpleArcPeerManager<lightning_net_tokio::SocketDescriptor, ChannelMonitor, TxBroadcaster, FeeEstimator, ChainWatchInterface, Logger>;
//! type ChainAccess = dyn lightning::chain::Access;
//! type ChainFilter = dyn lightning::chain::Filter;
//! type ChainMonitor = lightning::chain::chainmonitor::ChainMonitor<lightning::chain::keysinterface::InMemoryChannelKeys, Arc<ChainFilter>, Arc<TxBroadcaster>, Arc<FeeEstimator>, Arc<Logger>>;
//! type ChannelManager = lightning::ln::channelmanager::SimpleArcChannelManager<ChainMonitor, TxBroadcaster, FeeEstimator, Logger>;
//! type PeerManager = lightning::ln::peer_handler::SimpleArcPeerManager<lightning_net_tokio::SocketDescriptor, ChainMonitor, TxBroadcaster, FeeEstimator, ChainAccess, Logger>;
//!
//! // Connect to node with pubkey their_node_id at addr:
//! async fn connect_to_node(peer_manager: PeerManager, channel_monitor: Arc<ChannelMonitor>, channel_manager: ChannelManager, their_node_id: PublicKey, addr: SocketAddr) {
//! async fn connect_to_node(peer_manager: PeerManager, chain_monitor: Arc<ChainMonitor>, channel_manager: ChannelManager, their_node_id: PublicKey, addr: SocketAddr) {
//! let (sender, mut receiver) = mpsc::channel(2);
//! lightning_net_tokio::connect_outbound(peer_manager, sender, their_node_id, addr).await;
//! loop {
@ -48,14 +49,14 @@
//! for _event in channel_manager.get_and_clear_pending_events().drain(..) {
//! // Handle the event!
//! }
//! for _event in channel_monitor.get_and_clear_pending_events().drain(..) {
//! for _event in chain_monitor.get_and_clear_pending_events().drain(..) {
//! // Handle the event!
//! }
//! }
//! }
//!
//! // Begin reading from a newly accepted socket and talk to the peer:
//! async fn accept_socket(peer_manager: PeerManager, channel_monitor: Arc<ChannelMonitor>, channel_manager: ChannelManager, socket: TcpStream) {
//! async fn accept_socket(peer_manager: PeerManager, chain_monitor: Arc<ChainMonitor>, channel_manager: ChannelManager, socket: TcpStream) {
//! let (sender, mut receiver) = mpsc::channel(2);
//! lightning_net_tokio::setup_inbound(peer_manager, sender, socket);
//! loop {
@ -63,7 +64,7 @@
//! for _event in channel_manager.get_and_clear_pending_events().drain(..) {
//! // Handle the event!
//! }
//! for _event in channel_monitor.get_and_clear_pending_events().drain(..) {
//! for _event in chain_monitor.get_and_clear_pending_events().drain(..) {
//! // Handle the event!
//! }
//! }

View file

@ -13,63 +13,7 @@
//! Includes traits for monitoring and receiving notifications of new blocks and block
//! disconnections, transaction broadcasting, and feerate information requests.
use bitcoin::blockdata::block::{Block, BlockHeader};
use bitcoin::blockdata::transaction::Transaction;
use bitcoin::blockdata::script::Script;
use bitcoin::blockdata::constants::genesis_block;
use bitcoin::network::constants::Network;
use bitcoin::hash_types::{Txid, BlockHash};
use std::sync::{Mutex, MutexGuard, Arc};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::collections::HashSet;
use std::ops::Deref;
use std::marker::PhantomData;
use std::ptr;
/// Used to give chain error details upstream
#[derive(Clone)]
pub enum ChainError {
/// Client doesn't support UTXO lookup (but the chain hash matches our genesis block hash)
NotSupported,
/// Chain isn't the one watched
NotWatched,
/// Tx doesn't exist or is unconfirmed
UnknownTx,
}
/// An interface to request notification of certain scripts as they appear the
/// chain.
///
/// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're
/// called from inside the library in response to ChainListener events, P2P events, or timer
/// events).
pub trait ChainWatchInterface: Sync + Send {
/// Provides a txid/random-scriptPubKey-in-the-tx which much be watched for.
fn install_watch_tx(&self, txid: &Txid, script_pub_key: &Script);
/// Provides an outpoint which must be watched for, providing any transactions which spend the
/// given outpoint.
fn install_watch_outpoint(&self, outpoint: (Txid, u32), out_script: &Script);
/// Indicates that a listener needs to see all transactions.
fn watch_all_txn(&self);
/// Gets the script and value in satoshis for a given unspent transaction output given a
/// short_channel_id (aka unspent_tx_output_identier). For BTC/tBTC channels the top three
/// bytes are the block height, the next 3 the transaction index within the block, and the
/// final two the output within the transaction.
fn get_chain_utxo(&self, genesis_hash: BlockHash, unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError>;
/// Gets the list of transaction indices within a given block that the ChainWatchInterface is
/// watching for.
fn filter_block(&self, block: &Block) -> Vec<usize>;
/// Returns a usize that changes when the ChainWatchInterface's watched data is modified.
/// Users of `filter_block` should pre-save a copy of `reentered`'s return value and use it to
/// determine whether they need to re-filter a given block.
fn reentered(&self) -> usize;
}
/// An interface to send a transaction to the Bitcoin network.
pub trait BroadcasterInterface: Sync + Send {
@ -77,30 +21,6 @@ pub trait BroadcasterInterface: Sync + Send {
fn broadcast_transaction(&self, tx: &Transaction);
}
/// A trait indicating a desire to listen for events from the chain
pub trait ChainListener: Sync + Send {
/// Notifies a listener that a block was connected.
///
/// The txn_matched array should be set to references to transactions which matched the
/// relevant installed watch outpoints/txn, or the full set of transactions in the block.
///
/// Note that if txn_matched includes only matched transactions, and a new
/// transaction/outpoint is watched during a block_connected call, the block *must* be
/// re-scanned with the new transaction/outpoints and block_connected should be called
/// again with the same header and (at least) the new transactions.
///
/// Note that if non-new transaction/outpoints are be registered during a call, a second call
/// *must not* happen.
///
/// This also means those counting confirmations using block_connected callbacks should watch
/// for duplicate headers and not count them towards confirmations!
fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[usize]);
/// Notifies a listener that a block was disconnected.
/// Unlike block_connected, this *must* never be called twice for the same disconnect event.
/// Height must be the one of the block which was disconnected (not new height of the best chain)
fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32);
}
/// An enum that represents the speed at which we want a transaction to confirm used for feerate
/// estimation.
pub enum ConfirmationTarget {
@ -116,8 +36,7 @@ pub enum ConfirmationTarget {
/// horizons.
///
/// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're
/// called from inside the library in response to ChainListener events, P2P events, or timer
/// events).
/// called from inside the library in response to chain events, P2P events, or timer events).
pub trait FeeEstimator: Sync + Send {
/// Gets estimated satoshis of fee required per 1000 Weight-Units.
///
@ -132,373 +51,3 @@ pub trait FeeEstimator: Sync + Send {
/// Minimum relay fee as required by bitcoin network mempool policy.
pub const MIN_RELAY_FEE_SAT_PER_1000_WEIGHT: u64 = 4000;
/// Utility for tracking registered txn/outpoints and checking for matches
#[cfg_attr(test, derive(PartialEq))]
pub struct ChainWatchedUtil {
watch_all: bool,
// We are more conservative in matching during testing to ensure everything matches *exactly*,
// even though during normal runtime we take more optimized match approaches...
#[cfg(test)]
watched_txn: HashSet<(Txid, Script)>,
#[cfg(not(test))]
watched_txn: HashSet<Script>,
watched_outpoints: HashSet<(Txid, u32)>,
}
impl ChainWatchedUtil {
/// Constructs an empty (watches nothing) ChainWatchedUtil
pub fn new() -> Self {
Self {
watch_all: false,
watched_txn: HashSet::new(),
watched_outpoints: HashSet::new(),
}
}
/// Registers a tx for monitoring, returning true if it was a new tx and false if we'd already
/// been watching for it.
pub fn register_tx(&mut self, txid: &Txid, script_pub_key: &Script) -> bool {
if self.watch_all { return false; }
#[cfg(test)]
{
self.watched_txn.insert((txid.clone(), script_pub_key.clone()))
}
#[cfg(not(test))]
{
let _tx_unused = txid; // It's used in cfg(test), though
self.watched_txn.insert(script_pub_key.clone())
}
}
/// Registers an outpoint for monitoring, returning true if it was a new outpoint and false if
/// we'd already been watching for it
pub fn register_outpoint(&mut self, outpoint: (Txid, u32), _script_pub_key: &Script) -> bool {
if self.watch_all { return false; }
self.watched_outpoints.insert(outpoint)
}
/// Sets us to match all transactions, returning true if this is a new setting and false if
/// we'd already been set to match everything.
pub fn watch_all(&mut self) -> bool {
if self.watch_all { return false; }
self.watch_all = true;
true
}
/// Checks if a given transaction matches the current filter.
pub fn does_match_tx(&self, tx: &Transaction) -> bool {
if self.watch_all {
return true;
}
for out in tx.output.iter() {
#[cfg(test)]
for &(ref txid, ref script) in self.watched_txn.iter() {
if *script == out.script_pubkey {
if tx.txid() == *txid {
return true;
}
}
}
#[cfg(not(test))]
for script in self.watched_txn.iter() {
if *script == out.script_pubkey {
return true;
}
}
}
for input in tx.input.iter() {
for outpoint in self.watched_outpoints.iter() {
let &(outpoint_hash, outpoint_index) = outpoint;
if outpoint_hash == input.previous_output.txid && outpoint_index == input.previous_output.vout {
return true;
}
}
}
false
}
}
/// BlockNotifierArc is useful when you need a BlockNotifier that points to ChainListeners with
/// static lifetimes, e.g. when you're using lightning-net-tokio (since tokio::spawn requires
/// parameters with static lifetimes). Other times you can afford a reference, which is more
/// efficient, in which case BlockNotifierRef is a more appropriate type. Defining these type
/// aliases prevents issues such as overly long function definitions.
///
/// (C-not exported) as we let clients handle any reference counting they need to do
pub type BlockNotifierArc<C> = Arc<BlockNotifier<'static, Arc<ChainListener>, C>>;
/// BlockNotifierRef is useful when you want a BlockNotifier that points to ChainListeners
/// with nonstatic lifetimes. This is useful for when static lifetimes are not needed. Nonstatic
/// lifetimes are more efficient but less flexible, and should be used by default unless static
/// lifetimes are required, e.g. when you're using lightning-net-tokio (since tokio::spawn
/// requires parameters with static lifetimes), in which case BlockNotifierArc is a more
/// appropriate type. Defining these type aliases for common usages prevents issues such as
/// overly long function definitions.
pub type BlockNotifierRef<'a, C> = BlockNotifier<'a, &'a ChainListener, C>;
/// Utility for notifying listeners about new blocks, and handling block rescans if new watch
/// data is registered.
///
/// Rather than using a plain BlockNotifier, it is preferable to use either a BlockNotifierArc
/// or a BlockNotifierRef for conciseness. See their documentation for more details, but essentially
/// you should default to using a BlockNotifierRef, and use a BlockNotifierArc instead when you
/// require ChainListeners with static lifetimes, such as when you're using lightning-net-tokio.
pub struct BlockNotifier<'a, CL: Deref + 'a, C: Deref>
where CL::Target: ChainListener + 'a, C::Target: ChainWatchInterface {
listeners: Mutex<Vec<CL>>,
chain_monitor: C,
phantom: PhantomData<&'a ()>,
}
impl<'a, CL: Deref + 'a, C: Deref> BlockNotifier<'a, CL, C>
where CL::Target: ChainListener + 'a, C::Target: ChainWatchInterface {
/// Constructs a new BlockNotifier without any listeners.
pub fn new(chain_monitor: C) -> BlockNotifier<'a, CL, C> {
BlockNotifier {
listeners: Mutex::new(Vec::new()),
chain_monitor,
phantom: PhantomData,
}
}
/// Register the given listener to receive events.
pub fn register_listener(&self, listener: CL) {
let mut vec = self.listeners.lock().unwrap();
vec.push(listener);
}
/// Unregister the given listener to no longer
/// receive events.
///
/// If the same listener is registered multiple times, unregistering
/// will remove ALL occurrences of that listener. Comparison is done using
/// the pointer returned by the Deref trait implementation.
///
/// (C-not exported) because the equality check would always fail
pub fn unregister_listener(&self, listener: CL) {
let mut vec = self.listeners.lock().unwrap();
// item is a ref to an abstract thing that dereferences to a ChainListener,
// so dereference it twice to get the ChainListener itself
vec.retain(|item | !ptr::eq(&(**item), &(*listener)));
}
/// Notify listeners that a block was connected given a full, unfiltered block.
///
/// Handles re-scanning the block and calling block_connected again if listeners register new
/// watch data during the callbacks for you (see ChainListener::block_connected for more info).
pub fn block_connected(&self, block: &Block, height: u32) {
let mut reentered = true;
while reentered {
let matched_indexes = self.chain_monitor.filter_block(block);
let mut matched_txn = Vec::new();
for index in matched_indexes.iter() {
matched_txn.push(&block.txdata[*index]);
}
reentered = self.block_connected_checked(&block.header, height, matched_txn.as_slice(), matched_indexes.as_slice());
}
}
/// Notify listeners that a block was connected, given pre-filtered list of transactions in the
/// block which matched the filter (probably using does_match_tx).
///
/// Returns true if notified listeners registered additional watch data (implying that the
/// block must be re-scanned and this function called again prior to further block_connected
/// calls, see ChainListener::block_connected for more info).
pub fn block_connected_checked(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[usize]) -> bool {
let last_seen = self.chain_monitor.reentered();
let listeners = self.listeners.lock().unwrap();
for listener in listeners.iter() {
listener.block_connected(header, height, txn_matched, indexes_of_txn_matched);
}
return last_seen != self.chain_monitor.reentered();
}
/// Notify listeners that a block was disconnected.
pub fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
let listeners = self.listeners.lock().unwrap();
for listener in listeners.iter() {
listener.block_disconnected(&header, disconnected_height);
}
}
}
/// Utility to capture some common parts of ChainWatchInterface implementors.
///
/// Keeping a local copy of this in a ChainWatchInterface implementor is likely useful.
pub struct ChainWatchInterfaceUtil {
network: Network,
watched: Mutex<ChainWatchedUtil>,
reentered: AtomicUsize,
}
// We only expose PartialEq in test since its somewhat unclear exactly what it should do and we're
// only comparing a subset of fields (essentially just checking that the set of things we're
// watching is the same).
#[cfg(test)]
impl PartialEq for ChainWatchInterfaceUtil {
fn eq(&self, o: &Self) -> bool {
self.network == o.network &&
*self.watched.lock().unwrap() == *o.watched.lock().unwrap()
}
}
/// Register listener
impl ChainWatchInterface for ChainWatchInterfaceUtil {
fn install_watch_tx(&self, txid: &Txid, script_pub_key: &Script) {
let mut watched = self.watched.lock().unwrap();
if watched.register_tx(txid, script_pub_key) {
self.reentered.fetch_add(1, Ordering::Relaxed);
}
}
fn install_watch_outpoint(&self, outpoint: (Txid, u32), out_script: &Script) {
let mut watched = self.watched.lock().unwrap();
if watched.register_outpoint(outpoint, out_script) {
self.reentered.fetch_add(1, Ordering::Relaxed);
}
}
fn watch_all_txn(&self) {
let mut watched = self.watched.lock().unwrap();
if watched.watch_all() {
self.reentered.fetch_add(1, Ordering::Relaxed);
}
}
fn get_chain_utxo(&self, genesis_hash: BlockHash, _unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError> {
if genesis_hash != genesis_block(self.network).header.block_hash() {
return Err(ChainError::NotWatched);
}
Err(ChainError::NotSupported)
}
fn filter_block(&self, block: &Block) -> Vec<usize> {
let mut matched_index = Vec::new();
let mut matched_txids = HashSet::new();
{
let watched = self.watched.lock().unwrap();
for (index, transaction) in block.txdata.iter().enumerate() {
// A tx matches the filter if it either matches the filter directly (via
// does_match_tx_unguarded) or if it is a descendant of another matched
// transaction within the same block, which we check for in the loop.
let mut matched = self.does_match_tx_unguarded(transaction, &watched);
for input in transaction.input.iter() {
if matched || matched_txids.contains(&input.previous_output.txid) {
matched = true;
break;
}
}
if matched {
matched_txids.insert(transaction.txid());
matched_index.push(index);
}
}
}
matched_index
}
fn reentered(&self) -> usize {
self.reentered.load(Ordering::Relaxed)
}
}
impl ChainWatchInterfaceUtil {
/// Creates a new ChainWatchInterfaceUtil for the given network
pub fn new(network: Network) -> ChainWatchInterfaceUtil {
ChainWatchInterfaceUtil {
network,
watched: Mutex::new(ChainWatchedUtil::new()),
reentered: AtomicUsize::new(1),
}
}
/// Checks if a given transaction matches the current filter.
pub fn does_match_tx(&self, tx: &Transaction) -> bool {
let watched = self.watched.lock().unwrap();
self.does_match_tx_unguarded (tx, &watched)
}
fn does_match_tx_unguarded(&self, tx: &Transaction, watched: &MutexGuard<ChainWatchedUtil>) -> bool {
watched.does_match_tx(tx)
}
}
#[cfg(test)]
mod tests {
use ln::functional_test_utils::{create_chanmon_cfgs, create_node_cfgs};
use super::{BlockNotifier, ChainListener};
use std::ptr;
#[test]
fn register_listener_test() {
let chanmon_cfgs = create_chanmon_cfgs(1);
let node_cfgs = create_node_cfgs(1, &chanmon_cfgs);
let block_notifier = BlockNotifier::new(node_cfgs[0].chain_monitor);
assert_eq!(block_notifier.listeners.lock().unwrap().len(), 0);
let listener = &node_cfgs[0].chan_monitor.simple_monitor as &ChainListener;
block_notifier.register_listener(listener);
let vec = block_notifier.listeners.lock().unwrap();
assert_eq!(vec.len(), 1);
let item = vec.first().clone().unwrap();
assert!(ptr::eq(&(**item), &(*listener)));
}
#[test]
fn unregister_single_listener_test() {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let block_notifier = BlockNotifier::new(node_cfgs[0].chain_monitor);
let listener1 = &node_cfgs[0].chan_monitor.simple_monitor as &ChainListener;
let listener2 = &node_cfgs[1].chan_monitor.simple_monitor as &ChainListener;
block_notifier.register_listener(listener1);
block_notifier.register_listener(listener2);
let vec = block_notifier.listeners.lock().unwrap();
assert_eq!(vec.len(), 2);
drop(vec);
block_notifier.unregister_listener(listener1);
let vec = block_notifier.listeners.lock().unwrap();
assert_eq!(vec.len(), 1);
let item = vec.first().clone().unwrap();
assert!(ptr::eq(&(**item), &(*listener2)));
}
#[test]
fn unregister_single_listener_ref_test() {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let block_notifier = BlockNotifier::new(node_cfgs[0].chain_monitor);
block_notifier.register_listener(&node_cfgs[0].chan_monitor.simple_monitor as &ChainListener);
block_notifier.register_listener(&node_cfgs[1].chan_monitor.simple_monitor as &ChainListener);
let vec = block_notifier.listeners.lock().unwrap();
assert_eq!(vec.len(), 2);
drop(vec);
block_notifier.unregister_listener(&node_cfgs[0].chan_monitor.simple_monitor);
let vec = block_notifier.listeners.lock().unwrap();
assert_eq!(vec.len(), 1);
let item = vec.first().clone().unwrap();
assert!(ptr::eq(&(**item), &(*&node_cfgs[1].chan_monitor.simple_monitor)));
}
#[test]
fn unregister_multiple_of_the_same_listeners_test() {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let block_notifier = BlockNotifier::new(node_cfgs[0].chain_monitor);
let listener1 = &node_cfgs[0].chan_monitor.simple_monitor as &ChainListener;
let listener2 = &node_cfgs[1].chan_monitor.simple_monitor as &ChainListener;
block_notifier.register_listener(listener1);
block_notifier.register_listener(listener1);
block_notifier.register_listener(listener2);
let vec = block_notifier.listeners.lock().unwrap();
assert_eq!(vec.len(), 3);
drop(vec);
block_notifier.unregister_listener(listener1);
let vec = block_notifier.listeners.lock().unwrap();
assert_eq!(vec.len(), 1);
let item = vec.first().clone().unwrap();
assert!(ptr::eq(&(**item), &(*listener2)));
}
}

View file

@ -0,0 +1,227 @@
// This file is Copyright its original authors, visible in version control
// history.
//
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
// You may not use this file except in accordance with one or both of these
// licenses.
//! Logic to connect off-chain channel management with on-chain transaction monitoring.
//!
//! [`ChainMonitor`] is an implementation of [`chain::Watch`] used both to process blocks and to
//! update [`ChannelMonitor`]s accordingly. If any on-chain events need further processing, it will
//! make those available as [`MonitorEvent`]s to be consumed.
//!
//! `ChainMonitor` is parameterized by an optional chain source, which must implement the
//! [`chain::Filter`] trait. This provides a mechanism to signal new relevant outputs back to light
//! clients, such that transactions spending those outputs are included in block data.
//!
//! `ChainMonitor` may be used directly to monitor channels locally or as a part of a distributed
//! setup to monitor channels remotely. In the latter case, a custom `chain::Watch` implementation
//! would be responsible for routing each update to a remote server and for retrieving monitor
//! events. The remote server would make use of `ChainMonitor` for block processing and for
//! servicing `ChannelMonitor` updates from the client.
//!
//! [`ChainMonitor`]: struct.ChainMonitor.html
//! [`chain::Filter`]: ../trait.Filter.html
//! [`chain::Watch`]: ../trait.Watch.html
//! [`ChannelMonitor`]: ../channelmonitor/struct.ChannelMonitor.html
//! [`MonitorEvent`]: ../channelmonitor/enum.MonitorEvent.html
use bitcoin::blockdata::block::BlockHeader;
use chain;
use chain::Filter;
use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, MonitorEvent, MonitorUpdateError};
use chain::transaction::{OutPoint, TransactionData};
use chain::keysinterface::ChannelKeys;
use util::logger::Logger;
use util::events;
use util::events::Event;
use std::collections::{HashMap, hash_map};
use std::sync::Mutex;
use std::ops::Deref;
/// An implementation of [`chain::Watch`] for monitoring channels.
///
/// Connected and disconnected blocks must be provided to `ChainMonitor` as documented by
/// [`chain::Watch`]. May be used in conjunction with [`ChannelManager`] to monitor channels locally
/// or used independently to monitor channels remotely. See the [module-level documentation] for
/// details.
///
/// [`chain::Watch`]: ../trait.Watch.html
/// [`ChannelManager`]: ../../ln/channelmanager/struct.ChannelManager.html
/// [module-level documentation]: index.html
pub struct ChainMonitor<ChanSigner: ChannelKeys, C: Deref, T: Deref, F: Deref, L: Deref>
where C::Target: chain::Filter,
T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
{
/// The monitors
pub monitors: Mutex<HashMap<OutPoint, ChannelMonitor<ChanSigner>>>,
chain_source: Option<C>,
broadcaster: T,
logger: L,
fee_estimator: F
}
impl<ChanSigner: ChannelKeys, C: Deref, T: Deref, F: Deref, L: Deref> ChainMonitor<ChanSigner, C, T, F, L>
where C::Target: chain::Filter,
T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
{
/// Dispatches to per-channel monitors, which are responsible for updating their on-chain view
/// of a channel and reacting accordingly based on transactions in the connected block. See
/// [`ChannelMonitor::block_connected`] for details. Any HTLCs that were resolved on chain will
/// be returned by [`chain::Watch::release_pending_monitor_events`].
///
/// Calls back to [`chain::Filter`] if any monitor indicated new outputs to watch, returning
/// `true` if so. Subsequent calls must not exclude any transactions matching the new outputs
/// nor any in-block descendants of such transactions. It is not necessary to re-fetch the block
/// to obtain updated `txdata`.
///
/// [`ChannelMonitor::block_connected`]: ../channelmonitor/struct.ChannelMonitor.html#method.block_connected
/// [`chain::Watch::release_pending_monitor_events`]: ../trait.Watch.html#tymethod.release_pending_monitor_events
/// [`chain::Filter`]: ../trait.Filter.html
pub fn block_connected(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) -> bool {
let mut has_new_outputs_to_watch = false;
{
let mut monitors = self.monitors.lock().unwrap();
for monitor in monitors.values_mut() {
let mut txn_outputs = monitor.block_connected(header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
has_new_outputs_to_watch |= !txn_outputs.is_empty();
if let Some(ref chain_source) = self.chain_source {
for (txid, outputs) in txn_outputs.drain(..) {
for (idx, output) in outputs.iter().enumerate() {
chain_source.register_output(&OutPoint { txid, index: idx as u16 }, &output.script_pubkey);
}
}
}
}
}
has_new_outputs_to_watch
}
/// Dispatches to per-channel monitors, which are responsible for updating their on-chain view
/// of a channel based on the disconnected block. See [`ChannelMonitor::block_disconnected`] for
/// details.
///
/// [`ChannelMonitor::block_disconnected`]: ../channelmonitor/struct.ChannelMonitor.html#method.block_disconnected
pub fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
let mut monitors = self.monitors.lock().unwrap();
for monitor in monitors.values_mut() {
monitor.block_disconnected(header, disconnected_height, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
}
}
/// Creates a new `ChainMonitor` used to watch on-chain activity pertaining to channels.
///
/// When an optional chain source implementing [`chain::Filter`] is provided, the chain monitor
/// will call back to it indicating transactions and outputs of interest. This allows clients to
/// pre-filter blocks or only fetch blocks matching a compact filter. Otherwise, clients may
/// always need to fetch full blocks absent another means for determining which blocks contain
/// transactions relevant to the watched channels.
///
/// [`chain::Filter`]: ../trait.Filter.html
pub fn new(chain_source: Option<C>, broadcaster: T, logger: L, feeest: F) -> Self {
Self {
monitors: Mutex::new(HashMap::new()),
chain_source,
broadcaster,
logger,
fee_estimator: feeest,
}
}
/// Adds the monitor that watches the channel referred to by the given outpoint.
///
/// Calls back to [`chain::Filter`] with the funding transaction and outputs to watch.
///
/// [`chain::Filter`]: ../trait.Filter.html
fn add_monitor(&self, outpoint: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
let mut monitors = self.monitors.lock().unwrap();
let entry = match monitors.entry(outpoint) {
hash_map::Entry::Occupied(_) => return Err(MonitorUpdateError("Channel monitor for given outpoint is already present")),
hash_map::Entry::Vacant(e) => e,
};
{
let funding_txo = monitor.get_funding_txo();
log_trace!(self.logger, "Got new Channel Monitor for channel {}", log_bytes!(funding_txo.0.to_channel_id()[..]));
if let Some(ref chain_source) = self.chain_source {
chain_source.register_tx(&funding_txo.0.txid, &funding_txo.1);
for (txid, outputs) in monitor.get_outputs_to_watch().iter() {
for (idx, script_pubkey) in outputs.iter().enumerate() {
chain_source.register_output(&OutPoint { txid: *txid, index: idx as u16 }, &script_pubkey);
}
}
}
}
entry.insert(monitor);
Ok(())
}
/// Updates the monitor that watches the channel referred to by the given outpoint.
fn update_monitor(&self, outpoint: OutPoint, update: ChannelMonitorUpdate) -> Result<(), MonitorUpdateError> {
let mut monitors = self.monitors.lock().unwrap();
match monitors.get_mut(&outpoint) {
Some(orig_monitor) => {
log_trace!(self.logger, "Updating Channel Monitor for channel {}", log_funding_info!(orig_monitor));
orig_monitor.update_monitor(update, &self.broadcaster, &self.logger)
},
None => Err(MonitorUpdateError("No such monitor registered"))
}
}
}
impl<ChanSigner: ChannelKeys, C: Deref + Sync + Send, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send> chain::Watch for ChainMonitor<ChanSigner, C, T, F, L>
where C::Target: chain::Filter,
T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
{
type Keys = ChanSigner;
fn watch_channel(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr> {
match self.add_monitor(funding_txo, monitor) {
Ok(_) => Ok(()),
Err(_) => Err(ChannelMonitorUpdateErr::PermanentFailure),
}
}
fn update_channel(&self, funding_txo: OutPoint, update: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr> {
match self.update_monitor(funding_txo, update) {
Ok(_) => Ok(()),
Err(_) => Err(ChannelMonitorUpdateErr::PermanentFailure),
}
}
fn release_pending_monitor_events(&self) -> Vec<MonitorEvent> {
let mut pending_monitor_events = Vec::new();
for chan in self.monitors.lock().unwrap().values_mut() {
pending_monitor_events.append(&mut chan.get_and_clear_pending_monitor_events());
}
pending_monitor_events
}
}
impl<ChanSigner: ChannelKeys, C: Deref, T: Deref, F: Deref, L: Deref> events::EventsProvider for ChainMonitor<ChanSigner, C, T, F, L>
where C::Target: chain::Filter,
T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
{
fn get_and_clear_pending_events(&self) -> Vec<Event> {
let mut pending_events = Vec::new();
for chan in self.monitors.lock().unwrap().values_mut() {
pending_events.append(&mut chan.get_and_clear_pending_events());
}
pending_events
}
}

View file

@ -12,13 +12,15 @@
//!
//! ChannelMonitor objects are generated by ChannelManager in response to relevant
//! messages/actions, and MUST be persisted to disk (and, preferably, remotely) before progress can
//! be made in responding to certain messages, see ManyChannelMonitor for more.
//! be made in responding to certain messages, see [`chain::Watch`] for more.
//!
//! Note that ChannelMonitors are an important part of the lightning trust model and a copy of the
//! latest ChannelMonitor must always be actively monitoring for chain updates (and no out-of-date
//! ChannelMonitors should do so). Thus, if you're building rust-lightning into an HSM or other
//! security-domain-separated system design, you should consider having multiple paths for
//! ChannelMonitors to get out of the HSM and onto monitoring devices.
//!
//! [`chain::Watch`]: ../trait.Watch.html
use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::transaction::{TxOut,Transaction};
@ -40,17 +42,16 @@ use ln::chan_utils;
use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HolderCommitmentTransaction, HTLCType};
use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
use ln::onchaintx::{OnchainTxHandler, InputDescriptors};
use chain::chaininterface::{ChainListener, ChainWatchInterface, BroadcasterInterface, FeeEstimator};
use chain::transaction::OutPoint;
use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
use chain::transaction::{OutPoint, TransactionData};
use chain::keysinterface::{SpendableOutputDescriptor, ChannelKeys};
use util::logger::Logger;
use util::ser::{Readable, MaybeReadable, Writer, Writeable, U48};
use util::{byte_utils, events};
use util::byte_utils;
use util::events::Event;
use std::collections::{HashMap, hash_map};
use std::sync::Mutex;
use std::{hash,cmp, mem};
use std::collections::{HashMap, HashSet, hash_map};
use std::{cmp, mem};
use std::ops::Deref;
use std::io::Error;
@ -60,7 +61,7 @@ use std::io::Error;
#[derive(Clone)]
#[must_use]
pub struct ChannelMonitorUpdate {
pub(super) updates: Vec<ChannelMonitorUpdateStep>,
pub(crate) updates: Vec<ChannelMonitorUpdateStep>,
/// The sequence number of this update. Updates *must* be replayed in-order according to this
/// sequence number (and updates may panic if they are not). The update_id values are strictly
/// increasing and increase by one for each new update.
@ -146,6 +147,11 @@ pub enum ChannelMonitorUpdateErr {
/// Note that even when you fail a holder commitment transaction update, you must store the
/// update to ensure you can claim from it in case of a duplicate copy of this ChannelMonitor
/// broadcasts it (e.g distributed channel-monitor deployment)
///
/// In case of distributed watchtowers deployment, the new version must be written to disk, as
/// state may have been stored but rejected due to a block forcing a commitment broadcast. This
/// storage is used to claim outputs of rejected state confirmed onchain by another watchtower,
/// lagging behind on block processing.
PermanentFailure,
}
@ -167,176 +173,19 @@ pub enum MonitorEvent {
CommitmentTxBroadcasted(OutPoint),
}
/// Simple structure send back by ManyChannelMonitor in case of HTLC detected onchain from a
/// forward channel and from which info are needed to update HTLC in a backward channel.
/// Simple structure sent back by `chain::Watch` when an HTLC from a forward channel is detected on
/// chain. Used to update the corresponding HTLC in the backward channel. Failing to pass the
/// preimage claim backward will lead to loss of funds.
///
/// [`chain::Watch`]: ../trait.Watch.html
#[derive(Clone, PartialEq)]
pub struct HTLCUpdate {
pub(super) payment_hash: PaymentHash,
pub(super) payment_preimage: Option<PaymentPreimage>,
pub(super) source: HTLCSource
pub(crate) payment_hash: PaymentHash,
pub(crate) payment_preimage: Option<PaymentPreimage>,
pub(crate) source: HTLCSource
}
impl_writeable!(HTLCUpdate, 0, { payment_hash, payment_preimage, source });
/// A simple implementation of a ManyChannelMonitor and ChainListener. Can be used to create a
/// watchtower or watch our own channels.
///
/// Note that you must provide your own key by which to refer to channels.
///
/// If you're accepting remote monitors (ie are implementing a watchtower), you must verify that
/// users cannot overwrite a given channel by providing a duplicate key. ie you should probably
/// index by a PublicKey which is required to sign any updates.
///
/// If you're using this for local monitoring of your own channels, you probably want to use
/// `OutPoint` as the key, which will give you a ManyChannelMonitor implementation.
///
/// (C-not exported) due to an unconstrained generic in `Key`
pub struct SimpleManyChannelMonitor<Key, ChanSigner: ChannelKeys, T: Deref, F: Deref, L: Deref, C: Deref>
where T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
C::Target: ChainWatchInterface,
{
/// The monitors
pub monitors: Mutex<HashMap<Key, ChannelMonitor<ChanSigner>>>,
chain_monitor: C,
broadcaster: T,
logger: L,
fee_estimator: F
}
impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send, C: Deref + Sync + Send>
ChainListener for SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C>
where T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
C::Target: ChainWatchInterface,
{
fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], _indexes_of_txn_matched: &[usize]) {
let block_hash = header.block_hash();
{
let mut monitors = self.monitors.lock().unwrap();
for monitor in monitors.values_mut() {
let txn_outputs = monitor.block_connected(txn_matched, height, &block_hash, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
for (ref txid, ref outputs) in txn_outputs {
for (idx, output) in outputs.iter().enumerate() {
self.chain_monitor.install_watch_outpoint((txid.clone(), idx as u32), &output.script_pubkey);
}
}
}
}
}
fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
let block_hash = header.block_hash();
let mut monitors = self.monitors.lock().unwrap();
for monitor in monitors.values_mut() {
monitor.block_disconnected(disconnected_height, &block_hash, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
}
}
}
impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: Deref, F: Deref, L: Deref, C: Deref> SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C>
where T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
C::Target: ChainWatchInterface,
{
/// Creates a new object which can be used to monitor several channels given the chain
/// interface with which to register to receive notifications.
pub fn new(chain_monitor: C, broadcaster: T, logger: L, feeest: F) -> SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C> {
let res = SimpleManyChannelMonitor {
monitors: Mutex::new(HashMap::new()),
chain_monitor,
broadcaster,
logger,
fee_estimator: feeest,
};
res
}
/// Adds or updates the monitor which monitors the channel referred to by the given key.
pub fn add_monitor_by_key(&self, key: Key, monitor: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
let mut monitors = self.monitors.lock().unwrap();
let entry = match monitors.entry(key) {
hash_map::Entry::Occupied(_) => return Err(MonitorUpdateError("Channel monitor for given key is already present")),
hash_map::Entry::Vacant(e) => e,
};
{
let funding_txo = monitor.get_funding_txo();
log_trace!(self.logger, "Got new Channel Monitor for channel {}", log_bytes!(funding_txo.0.to_channel_id()[..]));
self.chain_monitor.install_watch_tx(&funding_txo.0.txid, &funding_txo.1);
self.chain_monitor.install_watch_outpoint((funding_txo.0.txid, funding_txo.0.index as u32), &funding_txo.1);
for (txid, outputs) in monitor.get_outputs_to_watch().iter() {
for (idx, script) in outputs.iter().enumerate() {
self.chain_monitor.install_watch_outpoint((*txid, idx as u32), script);
}
}
}
entry.insert(monitor);
Ok(())
}
/// Updates the monitor which monitors the channel referred to by the given key.
pub fn update_monitor_by_key(&self, key: Key, update: ChannelMonitorUpdate) -> Result<(), MonitorUpdateError> {
let mut monitors = self.monitors.lock().unwrap();
match monitors.get_mut(&key) {
Some(orig_monitor) => {
log_trace!(self.logger, "Updating Channel Monitor for channel {}", log_funding_info!(orig_monitor));
orig_monitor.update_monitor(update, &self.broadcaster, &self.logger)
},
None => Err(MonitorUpdateError("No such monitor registered"))
}
}
}
impl<ChanSigner: ChannelKeys, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send, C: Deref + Sync + Send> ManyChannelMonitor for SimpleManyChannelMonitor<OutPoint, ChanSigner, T, F, L, C>
where T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
C::Target: ChainWatchInterface,
{
type Keys = ChanSigner;
fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr> {
match self.add_monitor_by_key(funding_txo, monitor) {
Ok(_) => Ok(()),
Err(_) => Err(ChannelMonitorUpdateErr::PermanentFailure),
}
}
fn update_monitor(&self, funding_txo: OutPoint, update: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr> {
match self.update_monitor_by_key(funding_txo, update) {
Ok(_) => Ok(()),
Err(_) => Err(ChannelMonitorUpdateErr::PermanentFailure),
}
}
fn get_and_clear_pending_monitor_events(&self) -> Vec<MonitorEvent> {
let mut pending_monitor_events = Vec::new();
for chan in self.monitors.lock().unwrap().values_mut() {
pending_monitor_events.append(&mut chan.get_and_clear_pending_monitor_events());
}
pending_monitor_events
}
}
impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref, F: Deref, L: Deref, C: Deref> events::EventsProvider for SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C>
where T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
C::Target: ChainWatchInterface,
{
fn get_and_clear_pending_events(&self) -> Vec<Event> {
let mut pending_events = Vec::new();
for chan in self.monitors.lock().unwrap().values_mut() {
pending_events.append(&mut chan.get_and_clear_pending_events());
}
pending_events
}
}
/// If an HTLC expires within this many blocks, don't try to claim it in a shared transaction,
/// instead claiming it in its own individual transaction.
pub(crate) const CLTV_SHARED_CLAIM_BUFFER: u32 = 12;
@ -623,7 +472,7 @@ const MIN_SERIALIZATION_VERSION: u8 = 1;
#[cfg_attr(test, derive(PartialEq))]
#[derive(Clone)]
pub(super) enum ChannelMonitorUpdateStep {
pub(crate) enum ChannelMonitorUpdateStep {
LatestHolderCommitmentTXInfo {
commitment_tx: HolderCommitmentTransaction,
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>,
@ -847,75 +696,6 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
secp_ctx: Secp256k1<secp256k1::All>, //TODO: dedup this a bit...
}
/// Simple trait indicating ability to track a set of ChannelMonitors and multiplex events between
/// them. Generally should be implemented by keeping a local SimpleManyChannelMonitor and passing
/// events to it, while also taking any add/update_monitor events and passing them to some remote
/// server(s).
///
/// In general, you must always have at least one local copy in memory, which must never fail to
/// update (as it is responsible for broadcasting the latest state in case the channel is closed),
/// and then persist it to various on-disk locations. If, for some reason, the in-memory copy fails
/// to update (eg out-of-memory or some other condition), you must immediately shut down without
/// taking any further action such as writing the current state to disk. This should likely be
/// accomplished via panic!() or abort().
///
/// Note that any updates to a channel's monitor *must* be applied to each instance of the
/// channel's monitor everywhere (including remote watchtowers) *before* this function returns. If
/// an update occurs and a remote watchtower is left with old state, it may broadcast transactions
/// which we have revoked, allowing our counterparty to claim all funds in the channel!
///
/// User needs to notify implementors of ManyChannelMonitor when a new block is connected or
/// disconnected using their `block_connected` and `block_disconnected` methods. However, rather
/// than calling these methods directly, the user should register implementors as listeners to the
/// BlockNotifier and call the BlockNotifier's `block_(dis)connected` methods, which will notify
/// all registered listeners in one go.
pub trait ManyChannelMonitor: Send + Sync {
/// The concrete type which signs for transactions and provides access to our channel public
/// keys.
type Keys: ChannelKeys;
/// Adds a monitor for the given `funding_txo`.
///
/// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
/// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
/// callbacks with the funding transaction, or any spends of it.
///
/// Further, the implementer must also ensure that each output returned in
/// monitor.get_outputs_to_watch() is registered to ensure that the provided monitor learns about
/// any spends of any of the outputs.
///
/// Any spends of outputs which should have been registered which aren't passed to
/// ChannelMonitors via block_connected may result in FUNDS LOSS.
fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<Self::Keys>) -> Result<(), ChannelMonitorUpdateErr>;
/// Updates a monitor for the given `funding_txo`.
///
/// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
/// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
/// callbacks with the funding transaction, or any spends of it.
///
/// Further, the implementer must also ensure that each output returned in
/// monitor.get_watch_outputs() is registered to ensure that the provided monitor learns about
/// any spends of any of the outputs.
///
/// Any spends of outputs which should have been registered which aren't passed to
/// ChannelMonitors via block_connected may result in FUNDS LOSS.
///
/// In case of distributed watchtowers deployment, even if an Err is return, the new version
/// must be written to disk, as state may have been stored but rejected due to a block forcing
/// a commitment broadcast. This storage is used to claim outputs of rejected state confirmed
/// onchain by another watchtower, lagging behind on block processing.
fn update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr>;
/// Used by ChannelManager to get list of HTLC resolved onchain and which needed to be updated
/// with success or failure.
///
/// You should probably just call through to
/// ChannelMonitor::get_and_clear_pending_monitor_events() for each ChannelMonitor and return
/// the full list.
fn get_and_clear_pending_monitor_events(&self) -> Vec<MonitorEvent>;
}
#[cfg(any(test, feature = "fuzztarget"))]
/// Used only in testing and fuzztarget to check serialization roundtrips don't change the
/// underlying object
@ -1155,7 +935,7 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
}
impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
pub(super) fn new(keys: ChanSigner, shutdown_pubkey: &PublicKey,
pub(crate) fn new(keys: ChanSigner, shutdown_pubkey: &PublicKey,
on_counterparty_tx_csv: u16, destination_script: &Script, funding_info: (OutPoint, Script),
counterparty_htlc_base_key: &PublicKey, counterparty_delayed_payment_base_key: &PublicKey,
on_holder_tx_csv: u16, funding_redeemscript: Script, channel_value_satoshis: u64,
@ -1186,6 +966,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
};
onchain_tx_handler.provide_latest_holder_tx(initial_holder_commitment_tx);
let mut outputs_to_watch = HashMap::new();
outputs_to_watch.insert(funding_info.0.txid, vec![funding_info.1.clone()]);
ChannelMonitor {
latest_update_id: 0,
commitment_transaction_number_obscure_factor,
@ -1222,7 +1005,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
pending_events: Vec::new(),
onchain_events_waiting_threshold_conf: HashMap::new(),
outputs_to_watch: HashMap::new(),
outputs_to_watch,
onchain_tx_handler,
@ -1237,7 +1020,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
/// Inserts a revocation secret into this channel monitor. Prunes old preimages if neither
/// needed by holder commitment transactions HTCLs nor by counterparty ones. Unless we haven't already seen
/// counterparty commitment transaction's secret, they are de facto pruned (we can use revocation key).
pub(super) fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), MonitorUpdateError> {
fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), MonitorUpdateError> {
if let Err(()) = self.commitment_secrets.provide_secret(idx, secret) {
return Err(MonitorUpdateError("Previous secret did not match new one"));
}
@ -1289,7 +1072,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
/// The monitor watches for it to be broadcasted and then uses the HTLC information (and
/// possibly future revocation/preimage information) to claim outputs where possible.
/// We cache also the mapping hash:commitment number to lighten pruning of old preimages by watchtowers.
pub(super) fn provide_latest_counterparty_commitment_tx_info<L: Deref>(&mut self, unsigned_commitment_tx: &Transaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>, commitment_number: u64, their_revocation_point: PublicKey, logger: &L) where L::Target: Logger {
pub(crate) fn provide_latest_counterparty_commitment_tx_info<L: Deref>(&mut self, unsigned_commitment_tx: &Transaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>, commitment_number: u64, their_revocation_point: PublicKey, logger: &L) where L::Target: Logger {
// TODO: Encrypt the htlc_outputs data with the single-hash of the commitment transaction
// so that a remote monitor doesn't learn anything unless there is a malicious close.
// (only maybe, sadly we cant do the same for local info, as we need to be aware of
@ -1338,7 +1121,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
/// is important that any clones of this channel monitor (including remote clones) by kept
/// up-to-date as our holder commitment transaction is updated.
/// Panics if set_on_holder_tx_csv has never been called.
pub(super) fn provide_latest_holder_commitment_tx_info(&mut self, commitment_tx: HolderCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), MonitorUpdateError> {
fn provide_latest_holder_commitment_tx_info(&mut self, commitment_tx: HolderCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), MonitorUpdateError> {
let txid = commitment_tx.txid();
let sequence = commitment_tx.unsigned_tx.input[0].sequence as u64;
let locktime = commitment_tx.unsigned_tx.lock_time as u64;
@ -1364,11 +1147,11 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
/// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all
/// commitment_tx_infos which contain the payment hash have been revoked.
pub(super) fn provide_payment_preimage(&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage) {
pub(crate) fn provide_payment_preimage(&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage) {
self.payment_preimages.insert(payment_hash.clone(), payment_preimage.clone());
}
pub(super) fn broadcast_latest_holder_commitment_txn<B: Deref, L: Deref>(&mut self, broadcaster: &B, logger: &L)
pub(crate) fn broadcast_latest_holder_commitment_txn<B: Deref, L: Deref>(&mut self, broadcaster: &B, logger: &L)
where B::Target: BroadcasterInterface,
L::Target: Logger,
{
@ -1451,7 +1234,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
}
/// Get the list of HTLCs who's status has been updated on chain. This should be called by
/// ChannelManager via ManyChannelMonitor::get_and_clear_pending_monitor_events().
/// ChannelManager via [`chain::Watch::release_pending_monitor_events`].
///
/// [`chain::Watch::release_pending_monitor_events`]: ../trait.Watch.html#tymethod.release_pending_monitor_events
pub fn get_and_clear_pending_monitor_events(&mut self) -> Vec<MonitorEvent> {
let mut ret = Vec::new();
mem::swap(&mut ret, &mut self.pending_monitor_events);
@ -1461,7 +1246,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
/// Gets the list of pending events which were generated by previous actions, clearing the list
/// in the process.
///
/// This is called by ManyChannelMonitor::get_and_clear_pending_events() and is equivalent to
/// This is called by ChainMonitor::get_and_clear_pending_events() and is equivalent to
/// EventsProvider::get_and_clear_pending_events() except that it requires &mut self as we do
/// no internal locking in ChannelMonitors.
pub fn get_and_clear_pending_events(&mut self) -> Vec<Event> {
@ -1471,19 +1256,19 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
}
/// Can only fail if idx is < get_min_seen_secret
pub(super) fn get_secret(&self, idx: u64) -> Option<[u8; 32]> {
fn get_secret(&self, idx: u64) -> Option<[u8; 32]> {
self.commitment_secrets.get_secret(idx)
}
pub(super) fn get_min_seen_secret(&self) -> u64 {
pub(crate) fn get_min_seen_secret(&self) -> u64 {
self.commitment_secrets.get_min_seen_secret()
}
pub(super) fn get_cur_counterparty_commitment_number(&self) -> u64 {
pub(crate) fn get_cur_counterparty_commitment_number(&self) -> u64 {
self.current_counterparty_commitment_number
}
pub(super) fn get_cur_holder_commitment_number(&self) -> u64 {
pub(crate) fn get_cur_holder_commitment_number(&self) -> u64 {
self.current_holder_commitment_number
}
@ -1880,17 +1665,24 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
Vec::new()
}
/// Called by SimpleManyChannelMonitor::block_connected, which implements
/// ChainListener::block_connected.
/// Eventually this should be pub and, roughly, implement ChainListener, however this requires
/// &mut self, as well as returns new spendable outputs and outpoints to watch for spending of
/// on-chain.
fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec<TxOut>)>
/// Processes transactions in a newly connected block, which may result in any of the following:
/// - update the monitor's state against resolved HTLCs
/// - punish the counterparty in the case of seeing a revoked commitment transaction
/// - force close the channel and claim/timeout incoming/outgoing HTLCs if near expiration
/// - detect settled outputs for later spending
/// - schedule and bump any in-flight claims
///
/// Returns any new outputs to watch from `txdata`; after called, these are also included in
/// [`get_outputs_to_watch`].
///
/// [`get_outputs_to_watch`]: #method.get_outputs_to_watch
pub fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, header: &BlockHeader, txdata: &TransactionData, height: u32, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec<TxOut>)>
where B::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
{
for tx in txn_matched {
let txn_matched = self.filter_block(txdata);
for tx in &txn_matched {
let mut output_val = 0;
for out in tx.output.iter() {
if out.value > 21_000_000_0000_0000 { panic!("Value-overflowing transaction provided to block connected"); }
@ -1899,10 +1691,12 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
}
}
let block_hash = header.block_hash();
log_trace!(logger, "Block {} at height {} connected with {} txn matched", block_hash, height, txn_matched.len());
let mut watch_outputs = Vec::new();
let mut claimable_outpoints = Vec::new();
for tx in txn_matched {
for tx in &txn_matched {
if tx.input.len() == 1 {
// Assuming our keys were not leaked (in which case we're screwed no matter what),
// commitment transactions and HTLC transactions will all only ever have one input,
@ -1977,22 +1771,28 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
}
}
self.onchain_tx_handler.block_connected(txn_matched, claimable_outpoints, height, &*broadcaster, &*fee_estimator, &*logger);
self.last_block_hash = block_hash.clone();
for &(ref txid, ref output_scripts) in watch_outputs.iter() {
self.outputs_to_watch.insert(txid.clone(), output_scripts.iter().map(|o| o.script_pubkey.clone()).collect());
}
self.onchain_tx_handler.block_connected(&txn_matched, claimable_outpoints, height, &*broadcaster, &*fee_estimator, &*logger);
self.last_block_hash = block_hash;
// Determine new outputs to watch by comparing against previously known outputs to watch,
// updating the latter in the process.
watch_outputs.retain(|&(ref txid, ref txouts)| {
let output_scripts = txouts.iter().map(|o| o.script_pubkey.clone()).collect();
self.outputs_to_watch.insert(txid.clone(), output_scripts).is_none()
});
watch_outputs
}
fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)
/// Determines if the disconnected block contained any transactions of interest and updates
/// appropriately.
pub fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, header: &BlockHeader, height: u32, broadcaster: B, fee_estimator: F, logger: L)
where B::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
{
let block_hash = header.block_hash();
log_trace!(logger, "Block {} at height {} disconnected", block_hash, height);
if let Some(_) = self.onchain_events_waiting_threshold_conf.remove(&(height + ANTI_REORG_DELAY - 1)) {
//We may discard:
//- htlc update there as failure-trigger tx (revoked commitment tx, non-revoked commitment tx, HTLC-timeout tx) has been disconnected
@ -2001,7 +1801,41 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
self.onchain_tx_handler.block_disconnected(height, broadcaster, fee_estimator, logger);
self.last_block_hash = block_hash.clone();
self.last_block_hash = block_hash;
}
/// Filters a block's `txdata` for transactions spending watched outputs or for any child
/// transactions thereof.
fn filter_block<'a>(&self, txdata: &TransactionData<'a>) -> Vec<&'a Transaction> {
let mut matched_txn = HashSet::new();
txdata.iter().filter(|&&(_, tx)| {
let mut matches = self.spends_watched_output(tx);
for input in tx.input.iter() {
if matches { break; }
if matched_txn.contains(&input.previous_output.txid) {
matches = true;
}
}
if matches {
matched_txn.insert(tx.txid());
}
matches
}).map(|(_, tx)| *tx).collect()
}
/// Checks if a given transaction spends any watched outputs.
fn spends_watched_output(&self, tx: &Transaction) -> bool {
for input in tx.input.iter() {
if let Some(outputs) = self.get_outputs_to_watch().get(&input.previous_output.txid) {
for (idx, _script_pubkey) in outputs.iter().enumerate() {
if idx == input.previous_output.vout as usize {
return true;
}
}
}
}
false
}
fn would_broadcast_at_height<L: Deref>(&self, height: u32, logger: &L) -> bool where L::Target: Logger {
@ -2579,9 +2413,9 @@ mod tests {
use bitcoin::hashes::hex::FromHex;
use bitcoin::hash_types::Txid;
use hex;
use chain::channelmonitor::ChannelMonitor;
use chain::transaction::OutPoint;
use ln::channelmanager::{PaymentPreimage, PaymentHash};
use ln::channelmonitor::ChannelMonitor;
use ln::onchaintx::{OnchainTxHandler, InputDescriptors};
use ln::chan_utils;
use ln::chan_utils::{HTLCOutputInCommitment, HolderCommitmentTransaction};

View file

@ -9,6 +9,120 @@
//! Structs and traits which allow other parts of rust-lightning to interact with the blockchain.
use bitcoin::blockdata::script::Script;
use bitcoin::blockdata::transaction::TxOut;
use bitcoin::hash_types::{BlockHash, Txid};
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, MonitorEvent};
use chain::keysinterface::ChannelKeys;
use chain::transaction::OutPoint;
pub mod chaininterface;
pub mod chainmonitor;
pub mod channelmonitor;
pub mod transaction;
pub mod keysinterface;
/// The `Access` trait defines behavior for accessing chain data and state, such as blocks and
/// UTXOs.
pub trait Access: Send + Sync {
/// Returns the transaction output of a funding transaction encoded by [`short_channel_id`].
/// Returns an error if `genesis_hash` is for a different chain or if such a transaction output
/// is unknown.
///
/// [`short_channel_id`]: https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md#definition-of-short_channel_id
fn get_utxo(&self, genesis_hash: &BlockHash, short_channel_id: u64) -> Result<TxOut, AccessError>;
}
/// An error when accessing the chain via [`Access`].
///
/// [`Access`]: trait.Access.html
#[derive(Clone)]
pub enum AccessError {
/// The requested chain is unknown.
UnknownChain,
/// The requested transaction doesn't exist or hasn't confirmed.
UnknownTx,
}
/// The `Watch` trait defines behavior for watching on-chain activity pertaining to channels as
/// blocks are connected and disconnected.
///
/// Each channel is associated with a [`ChannelMonitor`]. Implementations of this trait are
/// responsible for maintaining a set of monitors such that they can be updated accordingly as
/// channel state changes and HTLCs are resolved. See method documentation for specific
/// requirements.
///
/// Implementations **must** ensure that updates are successfully applied and persisted upon method
/// completion. If an update fails with a [`PermanentFailure`], then it must immediately shut down
/// without taking any further action such as persisting the current state.
///
/// If an implementation maintains multiple instances of a channel's monitor (e.g., by storing
/// backup copies), then it must ensure that updates are applied across all instances. Otherwise, it
/// could result in a revoked transaction being broadcast, allowing the counterparty to claim all
/// funds in the channel. See [`ChannelMonitorUpdateErr`] for more details about how to handle
/// multiple instances.
///
/// [`ChannelMonitor`]: channelmonitor/struct.ChannelMonitor.html
/// [`ChannelMonitorUpdateErr`]: channelmonitor/enum.ChannelMonitorUpdateErr.html
/// [`PermanentFailure`]: channelmonitor/enum.ChannelMonitorUpdateErr.html#variant.PermanentFailure
pub trait Watch: Send + Sync {
/// Keys needed by monitors for creating and signing transactions.
type Keys: ChannelKeys;
/// Watches a channel identified by `funding_txo` using `monitor`.
///
/// Implementations are responsible for watching the chain for the funding transaction along
/// with any spends of outputs returned by [`get_outputs_to_watch`]. In practice, this means
/// calling [`block_connected`] and [`block_disconnected`] on the monitor.
///
/// [`get_outputs_to_watch`]: channelmonitor/struct.ChannelMonitor.html#method.get_outputs_to_watch
/// [`block_connected`]: channelmonitor/struct.ChannelMonitor.html#method.block_connected
/// [`block_disconnected`]: channelmonitor/struct.ChannelMonitor.html#method.block_disconnected
fn watch_channel(&self, funding_txo: OutPoint, monitor: ChannelMonitor<Self::Keys>) -> Result<(), ChannelMonitorUpdateErr>;
/// Updates a channel identified by `funding_txo` by applying `update` to its monitor.
///
/// Implementations must call [`update_monitor`] with the given update. See
/// [`ChannelMonitorUpdateErr`] for invariants around returning an error.
///
/// [`update_monitor`]: channelmonitor/struct.ChannelMonitor.html#method.update_monitor
/// [`ChannelMonitorUpdateErr`]: channelmonitor/enum.ChannelMonitorUpdateErr.html
fn update_channel(&self, funding_txo: OutPoint, update: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr>;
/// Returns any monitor events since the last call. Subsequent calls must only return new
/// events.
fn release_pending_monitor_events(&self) -> Vec<MonitorEvent>;
}
/// The `Filter` trait defines behavior for indicating chain activity of interest pertaining to
/// channels.
///
/// This is useful in order to have a [`Watch`] implementation convey to a chain source which
/// transactions to be notified of. Notification may take the form of pre-filtering blocks or, in
/// the case of [BIP 157]/[BIP 158], only fetching a block if the compact filter matches. If
/// receiving full blocks from a chain source, any further filtering is unnecessary.
///
/// After an output has been registered, subsequent block retrievals from the chain source must not
/// exclude any transactions matching the new criteria nor any in-block descendants of such
/// transactions.
///
/// Note that use as part of a [`Watch`] implementation involves reentrancy. Therefore, the `Filter`
/// should not block on I/O. Implementations should instead queue the newly monitored data to be
/// processed later. Then, in order to block until the data has been processed, any `Watch`
/// invocation that has called the `Filter` must return [`TemporaryFailure`].
///
/// [`Watch`]: trait.Watch.html
/// [`TemporaryFailure`]: channelmonitor/enum.ChannelMonitorUpdateErr.html#variant.TemporaryFailure
/// [BIP 157]: https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki
/// [BIP 158]: https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki
pub trait Filter: Send + Sync {
/// Registers interest in a transaction with `txid` and having an output with `script_pubkey` as
/// a spending condition.
fn register_tx(&self, txid: &Txid, script_pubkey: &Script);
/// Registers interest in spends of a transaction output identified by `outpoint` having
/// `script_pubkey` as the spending condition.
fn register_output(&self, outpoint: &OutPoint, script_pubkey: &Script);
}

View file

@ -7,10 +7,41 @@
// You may not use this file except in accordance with one or both of these
// licenses.
//! Contains simple structs describing parts of transactions on the chain.
//! Types describing on-chain transactions.
use bitcoin::hash_types::Txid;
use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
use bitcoin::blockdata::transaction::Transaction;
/// Transaction data where each item consists of a transaction reference paired with the index of
/// the transaction within a block.
///
/// Useful for passing enumerated transactions from a block, possibly filtered, in order to retain
/// the transaction index.
///
/// ```
/// extern crate bitcoin;
/// extern crate lightning;
///
/// use bitcoin::blockdata::block::Block;
/// use bitcoin::blockdata::constants::genesis_block;
/// use bitcoin::network::constants::Network;
/// use lightning::chain::transaction::TransactionData;
///
/// let block = genesis_block(Network::Bitcoin);
/// let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
/// check_block(&block, &txdata);
///
/// fn check_block(block: &Block, txdata: &TransactionData) {
/// assert_eq!(block.txdata.len(), 1);
/// assert_eq!(txdata.len(), 1);
///
/// let (index, tx) = txdata[0];
/// assert_eq!(index, 0);
/// assert_eq!(tx, &block.txdata[0]);
/// }
/// ```
pub type TransactionData<'a> = [(usize, &'a Transaction)];
/// A reference to a transaction output.
///

View file

@ -81,7 +81,7 @@ pub fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32]
/// Allows us to keep track of all of the revocation secrets of counterarties in just 50*32 bytes
/// or so.
#[derive(Clone)]
pub(super) struct CounterpartyCommitmentSecrets {
pub(crate) struct CounterpartyCommitmentSecrets {
old_secrets: [([u8; 32], u64); 49],
}
@ -97,7 +97,7 @@ impl PartialEq for CounterpartyCommitmentSecrets {
}
impl CounterpartyCommitmentSecrets {
pub(super) fn new() -> Self {
pub(crate) fn new() -> Self {
Self { old_secrets: [([0; 32], 1 << 48); 49], }
}
@ -111,7 +111,7 @@ impl CounterpartyCommitmentSecrets {
48
}
pub(super) fn get_min_seen_secret(&self) -> u64 {
pub(crate) fn get_min_seen_secret(&self) -> u64 {
//TODO This can be optimized?
let mut min = 1 << 48;
for &(_, idx) in self.old_secrets.iter() {
@ -123,7 +123,7 @@ impl CounterpartyCommitmentSecrets {
}
#[inline]
pub(super) fn derive_secret(secret: [u8; 32], bits: u8, idx: u64) -> [u8; 32] {
fn derive_secret(secret: [u8; 32], bits: u8, idx: u64) -> [u8; 32] {
let mut res: [u8; 32] = secret;
for i in 0..bits {
let bitpos = bits - 1 - i;
@ -135,7 +135,7 @@ impl CounterpartyCommitmentSecrets {
res
}
pub(super) fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), ()> {
pub(crate) fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), ()> {
let pos = Self::place_secret(idx);
for i in 0..pos {
let (old_secret, old_idx) = self.old_secrets[i as usize];
@ -151,7 +151,7 @@ impl CounterpartyCommitmentSecrets {
}
/// Can only fail if idx is < get_min_seen_secret
pub(super) fn get_secret(&self, idx: u64) -> Option<[u8; 32]> {
pub(crate) fn get_secret(&self, idx: u64) -> Option<[u8; 32]> {
for i in 0..self.old_secrets.len() {
if (idx & (!((1 << i) - 1))) == self.old_secrets[i].1 {
return Some(Self::derive_secret(self.old_secrets[i].0, i as u8, idx))

View file

@ -12,9 +12,9 @@
//! There are a bunch of these as their handling is relatively error-prone so they are split out
//! here. See also the chanmon_fail_consistency fuzz test.
use chain::channelmonitor::ChannelMonitorUpdateErr;
use chain::transaction::OutPoint;
use ln::channelmanager::{RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure};
use ln::channelmonitor::ChannelMonitorUpdateErr;
use ln::features::InitFeatures;
use ln::msgs;
use ln::msgs::{ChannelMessageHandler, ErrorAction, RoutingMessageHandler};
@ -41,7 +41,7 @@ fn test_simple_monitor_permanent_update_fail() {
let (_, payment_hash_1) = get_payment_preimage_hash!(&nodes[0]);
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::PermanentFailure);
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::PermanentFailure);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash_1, &None), true, APIError::ChannelUnavailable {..}, {});
@ -76,7 +76,7 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(&nodes[0]);
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
@ -95,8 +95,8 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
}
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[0].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[0], 0);
@ -125,7 +125,7 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
// Now set it to failed again...
let (_, payment_hash_2) = get_payment_preimage_hash!(&nodes[0]);
{
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash_2, &None), false, APIError::MonitorUpdateFailed, {});
@ -191,7 +191,7 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
// Now try to send a second payment which will fail to send
let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
{
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash_2, &None), false, APIError::MonitorUpdateFailed, {});
@ -245,8 +245,8 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
}
// Now fix monitor updating...
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[0].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[0], 0);
@ -532,15 +532,15 @@ fn test_monitor_update_fail_cs() {
let send_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0));
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &send_event.commitment_msg);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Failed to update ChannelMonitor".to_string(), 1);
check_added_monitors!(nodes[1], 1);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[1].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[1], 0);
let responses = nodes[1].node.get_and_clear_pending_msg_events();
@ -563,7 +563,7 @@ fn test_monitor_update_fail_cs() {
assert!(updates.update_fee.is_none());
assert_eq!(*node_id, nodes[0].node.get_our_node_id());
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &updates.commitment_signed);
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Failed to update ChannelMonitor".to_string(), 1);
@ -573,8 +573,8 @@ fn test_monitor_update_fail_cs() {
_ => panic!("Unexpected event"),
}
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[0].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[0], 0);
@ -622,7 +622,7 @@ fn test_monitor_update_fail_no_rebroadcast() {
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]);
let bs_raa = commitment_signed_dance!(nodes[1], nodes[0], send_event.commitment_msg, false, true, false, true);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &bs_raa);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Failed to update ChannelMonitor".to_string(), 1);
@ -630,8 +630,8 @@ fn test_monitor_update_fail_no_rebroadcast() {
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
check_added_monitors!(nodes[1], 1);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[1].node.channel_monitor_updated(&outpoint, latest_update);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
check_added_monitors!(nodes[1], 0);
@ -684,7 +684,7 @@ fn test_monitor_update_raa_while_paused() {
check_added_monitors!(nodes[1], 1);
let bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
nodes[0].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &send_event_2.msgs[0]);
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &send_event_2.commitment_msg);
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
@ -696,8 +696,8 @@ fn test_monitor_update_raa_while_paused() {
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Previous monitor update failure prevented responses to RAA".to_string(), 1);
check_added_monitors!(nodes[0], 1);
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[0].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[0], 0);
@ -779,7 +779,7 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
// Now fail monitor updating.
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
nodes[1].node.handle_revoke_and_ack(&nodes[2].node.get_our_node_id(), &bs_revoke_and_ack);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Failed to update ChannelMonitor".to_string(), 1);
@ -797,7 +797,7 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
check_added_monitors!(nodes[0], 1);
}
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); // We succeed in updating the monitor for the first channel
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(()); // We succeed in updating the monitor for the first channel
send_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0));
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]);
commitment_signed_dance!(nodes[1], nodes[0], send_event.commitment_msg, false, true);
@ -858,8 +858,8 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
// Restore monitor updating, ensuring we immediately get a fail-back update and a
// update_add update.
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_2.2).unwrap().clone();
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_2.2).unwrap().clone();
nodes[1].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[1], 0);
expect_pending_htlcs_forwardable!(nodes[1]);
@ -1020,7 +1020,7 @@ fn test_monitor_update_fail_reestablish() {
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
@ -1049,8 +1049,8 @@ fn test_monitor_update_fail_reestablish() {
check_added_monitors!(nodes[1], 0);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone();
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone();
nodes[1].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[1], 0);
@ -1123,7 +1123,7 @@ fn raa_no_response_awaiting_raa_state() {
// Now we have a CS queued up which adds a new HTLC (which will need a RAA/CS response from
// nodes[1]) followed by an RAA. Fail the monitor updating prior to the CS, deliver the RAA,
// then restore channel monitor updates.
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
@ -1135,8 +1135,8 @@ fn raa_no_response_awaiting_raa_state() {
nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Previous monitor update failure prevented responses to RAA".to_string(), 1);
check_added_monitors!(nodes[1], 1);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[1].node.channel_monitor_updated(&outpoint, latest_update);
// nodes[1] should be AwaitingRAA here!
check_added_monitors!(nodes[1], 0);
@ -1228,7 +1228,7 @@ fn claim_while_disconnected_monitor_update_fail() {
// Now deliver a's reestablish, freeing the claim from the holding cell, but fail the monitor
// update.
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_reconnect);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
@ -1257,8 +1257,8 @@ fn claim_while_disconnected_monitor_update_fail() {
// Now un-fail the monitor, which will result in B sending its original commitment update,
// receiving the commitment update from A, and the resulting commitment dances.
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[1].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[1], 0);
@ -1342,7 +1342,7 @@ fn monitor_failed_no_reestablish_response() {
check_added_monitors!(nodes[0], 1);
}
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
let payment_event = SendEvent::from_event(events.pop().unwrap());
@ -1366,8 +1366,8 @@ fn monitor_failed_no_reestablish_response() {
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_reconnect);
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reconnect);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[1].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[1], 0);
let bs_responses = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
@ -1445,7 +1445,7 @@ fn first_message_on_recv_ordering() {
let payment_event = SendEvent::from_event(events.pop().unwrap());
assert_eq!(payment_event.node_id, nodes[1].node.get_our_node_id());
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
// Deliver the final RAA for the first payment, which does not require a response. RAAs
// generally require a commitment_signed, so the fact that we're expecting an opposite response
@ -1464,8 +1464,8 @@ fn first_message_on_recv_ordering() {
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Previous monitor update failure prevented generation of RAA".to_string(), 1);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[1].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[1], 0);
@ -1509,7 +1509,7 @@ fn test_monitor_update_fail_claim() {
let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
assert!(nodes[1].node.claim_funds(payment_preimage_1, &None, 1_000_000));
check_added_monitors!(nodes[1], 1);
@ -1523,7 +1523,7 @@ fn test_monitor_update_fail_claim() {
// Successfully update the monitor on the 1<->2 channel, but the 0<->1 channel should still be
// paused, so forward shouldn't succeed until we call channel_monitor_updated().
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(());
let mut events = nodes[2].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
@ -1556,7 +1556,7 @@ fn test_monitor_update_fail_claim() {
} else { panic!("Unexpected event!"); }
// Now restore monitor updating on the 0<->1 channel and claim the funds on B.
let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone();
let (outpoint, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone();
nodes[1].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[1], 0);
@ -1612,14 +1612,14 @@ fn test_monitor_update_on_pending_forwards() {
nodes[1].node.handle_update_add_htlc(&nodes[2].node.get_our_node_id(), &payment_event.msgs[0]);
commitment_signed_dance!(nodes[1], nodes[2], payment_event.commitment_msg, false);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
expect_pending_htlcs_forwardable!(nodes[1]);
check_added_monitors!(nodes[1], 1);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Failed to update ChannelMonitor".to_string(), 1);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone();
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone();
nodes[1].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[1], 0);
@ -1675,15 +1675,15 @@ fn monitor_update_claim_fail_no_response() {
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
let as_raa = commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false, true, false, true);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
assert!(nodes[1].node.claim_funds(payment_preimage_1, &None, 1_000_000));
check_added_monitors!(nodes[1], 1);
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 0);
nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Temporary failure claiming HTLC, treating as success: Failed to update ChannelMonitor".to_string(), 1);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[1].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[1], 0);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
@ -1728,20 +1728,20 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf:
nodes[0].node.funding_transaction_generated(&temporary_channel_id, funding_output);
check_added_monitors!(nodes[0], 0);
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
let channel_id = OutPoint { txid: funding_created_msg.funding_txid, index: funding_created_msg.funding_output_index }.to_channel_id();
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
check_added_monitors!(nodes[1], 1);
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Failed to update ChannelMonitor".to_string(), 1);
check_added_monitors!(nodes[0], 1);
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[0].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[0], 0);
@ -1756,11 +1756,11 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf:
};
if confirm_a_first {
confirm_transaction(&nodes[0].block_notifier, &nodes[0].chain_monitor, &funding_tx, funding_tx.version);
confirm_transaction(&nodes[0], &funding_tx);
nodes[1].node.handle_funding_locked(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendFundingLocked, nodes[1].node.get_our_node_id()));
} else {
assert!(!restore_b_before_conf);
confirm_transaction(&nodes[1].block_notifier, &nodes[1].chain_monitor, &funding_tx, funding_tx.version);
confirm_transaction(&nodes[1], &funding_tx);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
}
@ -1772,25 +1772,25 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf:
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
if !restore_b_before_conf {
confirm_transaction(&nodes[1].block_notifier, &nodes[1].chain_monitor, &funding_tx, funding_tx.version);
confirm_transaction(&nodes[1], &funding_tx);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
}
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Ok(());
let (outpoint, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
nodes[1].node.channel_monitor_updated(&outpoint, latest_update);
check_added_monitors!(nodes[1], 0);
let (channel_id, (announcement, as_update, bs_update)) = if !confirm_a_first {
nodes[0].node.handle_funding_locked(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingLocked, nodes[0].node.get_our_node_id()));
confirm_transaction(&nodes[0].block_notifier, &nodes[0].chain_monitor, &funding_tx, funding_tx.version);
confirm_transaction(&nodes[0], &funding_tx);
let (funding_locked, channel_id) = create_chan_between_nodes_with_value_confirm_second(&nodes[1], &nodes[0]);
(channel_id, create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &funding_locked))
} else {
if restore_b_before_conf {
confirm_transaction(&nodes[1].block_notifier, &nodes[1].chain_monitor, &funding_tx, funding_tx.version);
confirm_transaction(&nodes[1], &funding_tx);
}
let (funding_locked, channel_id) = create_chan_between_nodes_with_value_confirm_second(&nodes[0], &nodes[1]);
(channel_id, create_chan_between_nodes_with_value_b(&nodes[1], &nodes[0], &funding_locked))
@ -1843,8 +1843,8 @@ fn test_path_paused_mpp() {
// Set it so that the first monitor update (for the path 0 -> 1 -> 3) succeeds, but the second
// (for the path 0 -> 2 -> 3) fails.
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
*nodes[0].chan_monitor.next_update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure));
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Ok(());
*nodes[0].chain_monitor.next_update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure));
// Now check that we get the right return value, indicating that the first path succeeded but
// the second got a MonitorUpdateFailed err. This implies PaymentSendFailure::PartialFailure as
@ -1855,7 +1855,7 @@ fn test_path_paused_mpp() {
if let Err(APIError::MonitorUpdateFailed) = results[1] {} else { panic!(); }
} else { panic!(); }
check_added_monitors!(nodes[0], 2);
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Ok(());
// Pass the first HTLC of the payment along to nodes[3].
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
@ -1864,7 +1864,7 @@ fn test_path_paused_mpp() {
// And check that, after we successfully update the monitor for chan_2 we can pass the second
// HTLC along to nodes[3] and claim the whole payment back to nodes[0].
let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_2_id).unwrap().clone();
let (outpoint, latest_update) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_2_id).unwrap().clone();
nodes[0].node.channel_monitor_updated(&outpoint, latest_update);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);

View file

@ -25,12 +25,12 @@ use bitcoin::secp256k1;
use ln::features::{ChannelFeatures, InitFeatures};
use ln::msgs;
use ln::msgs::{DecodeError, OptionalField, DataLossProtect};
use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER};
use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT};
use ln::chan_utils::{CounterpartyCommitmentSecrets, HolderCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys, PreCalculatedTxCreationKeys};
use ln::chan_utils;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
use chain::transaction::OutPoint;
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER};
use chain::transaction::{OutPoint, TransactionData};
use chain::keysinterface::{ChannelKeys, KeysInterface};
use util::transaction_utils;
use util::ser::{Readable, Writeable, Writer};
@ -3315,7 +3315,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
///
/// May return some HTLCs (and their payment_hash) which have timed out and should be failed
/// back.
pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[usize]) -> Result<(Option<msgs::FundingLocked>, Vec<(HTLCSource, PaymentHash)>), msgs::ErrorMessage> {
pub fn block_connected(&mut self, header: &BlockHeader, txdata: &TransactionData, height: u32) -> Result<(Option<msgs::FundingLocked>, Vec<(HTLCSource, PaymentHash)>), msgs::ErrorMessage> {
let mut timed_out_htlcs = Vec::new();
self.holding_cell_htlc_updates.retain(|htlc_update| {
match htlc_update {
@ -3335,7 +3335,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
}
}
if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 {
for (ref tx, index_in_block) in txn_matched.iter().zip(indexes_of_txn_matched) {
for &(index_in_block, tx) in txdata.iter() {
if tx.txid() == self.funding_txo.unwrap().txid {
let txo_idx = self.funding_txo.unwrap().index as usize;
if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.get_funding_redeemscript().to_v0_p2wsh() ||
@ -3366,14 +3366,14 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
}
}
}
if height > 0xff_ff_ff || (*index_in_block) > 0xff_ff_ff {
if height > 0xff_ff_ff || (index_in_block) > 0xff_ff_ff {
panic!("Block was bogus - either height 16 million or had > 16 million transactions");
}
assert!(txo_idx <= 0xffff); // txo_idx is a (u16 as usize), so this is just listed here for completeness
self.funding_tx_confirmations = 1;
self.short_channel_id = Some(((height as u64) << (5*8)) |
((*index_in_block as u64) << (2*8)) |
((txo_idx as u64) << (0*8)));
self.short_channel_id = Some(((height as u64) << (5*8)) |
((index_in_block as u64) << (2*8)) |
((txo_idx as u64) << (0*8)));
}
}
}

View file

@ -18,7 +18,6 @@
//! imply it needs to fail HTLCs/payments/channels it manages).
use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::transaction::Transaction;
use bitcoin::blockdata::constants::genesis_block;
use bitcoin::network::constants::Network;
@ -34,10 +33,12 @@ use bitcoin::secp256k1::Secp256k1;
use bitcoin::secp256k1::ecdh::SharedSecret;
use bitcoin::secp256k1;
use chain::chaininterface::{BroadcasterInterface,ChainListener,FeeEstimator};
use chain::transaction::OutPoint;
use chain;
use chain::Watch;
use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, HTLC_FAIL_BACK_BUFFER, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent};
use chain::transaction::{OutPoint, TransactionData};
use ln::channel::{Channel, ChannelError};
use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, ManyChannelMonitor, HTLC_FAIL_BACK_BUFFER, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent};
use ln::features::{InitFeatures, NodeFeatures};
use routing::router::{Route, RouteHop};
use ln::msgs;
@ -128,7 +129,7 @@ pub(super) enum HTLCForwardInfo {
/// Tracks the inbound corresponding to an outbound HTLC
#[derive(Clone, PartialEq)]
pub(super) struct HTLCPreviousHopData {
pub(crate) struct HTLCPreviousHopData {
short_channel_id: u64,
htlc_id: u64,
incoming_packet_shared_secret: [u8; 32],
@ -147,7 +148,7 @@ struct ClaimableHTLC {
/// Tracks the inbound corresponding to an outbound HTLC
#[derive(Clone, PartialEq)]
pub(super) enum HTLCSource {
pub(crate) enum HTLCSource {
PreviousHopData(HTLCPreviousHopData),
OutboundRoute {
path: Vec<RouteHop>,
@ -360,7 +361,7 @@ pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, M, T, F, L> = ChannelManage
///
/// Note that you can be a bit lazier about writing out ChannelManager than you can be with
/// ChannelMonitors. With ChannelMonitors you MUST write each monitor update out to disk before
/// returning from ManyChannelMonitor::add_/update_monitor, with ChannelManagers, writing updates
/// returning from chain::Watch::watch_/update_channel, with ChannelManagers, writing updates
/// happens out-of-band (and will prevent any other ChannelManager operations from occurring during
/// the serialization process). If the deserialized version is out-of-date compared to the
/// ChannelMonitors passed by reference to read(), those channels will be force-closed based on the
@ -384,7 +385,7 @@ pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, M, T, F, L> = ChannelManage
/// SimpleArcChannelManager when you require a ChannelManager with a static lifetime, such as when
/// you're using lightning-net-tokio.
pub struct ChannelManager<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
where M::Target: ManyChannelMonitor<Keys=ChanSigner>,
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
F::Target: FeeEstimator,
@ -393,7 +394,7 @@ pub struct ChannelManager<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref,
default_configuration: UserConfig,
genesis_hash: BlockHash,
fee_estimator: F,
monitor: M,
chain_monitor: M,
tx_broadcaster: T,
#[cfg(test)]
@ -697,7 +698,7 @@ macro_rules! maybe_break_monitor_err {
}
impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<ChanSigner, M, T, K, F, L>
where M::Target: ManyChannelMonitor<Keys=ChanSigner>,
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
F::Target: FeeEstimator,
@ -717,18 +718,14 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
///
/// Users need to notify the new ChannelManager when a new block is connected or
/// disconnected using its `block_connected` and `block_disconnected` methods.
/// However, rather than calling these methods directly, the user should register
/// the ChannelManager as a listener to the BlockNotifier and call the BlockNotifier's
/// `block_(dis)connected` methods, which will notify all registered listeners in one
/// go.
pub fn new(network: Network, fee_est: F, monitor: M, tx_broadcaster: T, logger: L, keys_manager: K, config: UserConfig, current_blockchain_height: usize) -> Self {
pub fn new(network: Network, fee_est: F, chain_monitor: M, tx_broadcaster: T, logger: L, keys_manager: K, config: UserConfig, current_blockchain_height: usize) -> Self {
let secp_ctx = Secp256k1::new();
ChannelManager {
default_configuration: config.clone(),
genesis_hash: genesis_block(network).header.block_hash(),
fee_estimator: fee_est,
monitor,
chain_monitor,
tx_broadcaster,
latest_block_height: AtomicUsize::new(current_blockchain_height),
@ -903,7 +900,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
// force-closing. The monitor update on the required in-memory copy should broadcast
// the latest local state, which is the best we can do anyway. Thus, it is safe to
// ignore the result here.
let _ = self.monitor.update_monitor(funding_txo, monitor_update);
let _ = self.chain_monitor.update_channel(funding_txo, monitor_update);
}
}
@ -1283,7 +1280,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
}, onion_packet, &self.logger), channel_state, chan)
} {
Some((update_add, commitment_signed, monitor_update)) => {
if let Err(e) = self.monitor.update_monitor(chan.get().get_funding_txo().unwrap(), monitor_update) {
if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
maybe_break_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::CommitmentFirst, false, true);
// Note that MonitorUpdateFailed here indicates (per function docs)
// that we will resend the commitment update once monitor updating
@ -1679,7 +1676,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
continue;
}
};
if let Err(e) = self.monitor.update_monitor(chan.get().get_funding_txo().unwrap(), monitor_update) {
if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
handle_errors.push((chan.get().get_counterparty_node_id(), handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::CommitmentFirst, false, true)));
continue;
}
@ -2089,7 +2086,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
match chan.get_mut().get_update_fulfill_htlc_and_commit(prev_hop.htlc_id, payment_preimage, &self.logger) {
Ok((msgs, monitor_option)) => {
if let Some(monitor_update) = monitor_option {
if let Err(e) = self.monitor.update_monitor(chan.get().get_funding_txo().unwrap(), monitor_update) {
if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
if was_frozen_for_monitor {
assert!(msgs.is_none());
} else {
@ -2173,7 +2170,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
/// exists largely only to prevent races between this and concurrent update_monitor calls.
///
/// Thus, the anticipated use is, at a high level:
/// 1) You register a ManyChannelMonitor with this ChannelManager,
/// 1) You register a chain::Watch with this ChannelManager,
/// 2) it stores each update to disk, and begins updating any remote (eg watchtower) copies of
/// said ChannelMonitors as it can, returning ChannelMonitorUpdateErr::TemporaryFailures
/// any time it cannot do so instantly,
@ -2314,7 +2311,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
}
fn internal_funding_created(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingCreated) -> Result<(), MsgHandleErrInternal> {
let ((funding_msg, monitor_update), mut chan) = {
let ((funding_msg, monitor), mut chan) = {
let mut channel_lock = self.channel_state.lock().unwrap();
let channel_state = &mut *channel_lock;
match channel_state.by_id.entry(msg.temporary_channel_id.clone()) {
@ -2328,8 +2325,8 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
}
};
// Because we have exclusive ownership of the channel here we can release the channel_state
// lock before add_monitor
if let Err(e) = self.monitor.add_monitor(monitor_update.get_funding_txo().0, monitor_update) {
// lock before watch_channel
if let Err(e) = self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor) {
match e {
ChannelMonitorUpdateErr::PermanentFailure => {
// Note that we reply with the new channel_id in error messages if we gave up on the
@ -2377,7 +2374,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
Ok(update) => update,
Err(e) => try_chan_entry!(self, Err(e), channel_state, chan),
};
if let Err(e) = self.monitor.add_monitor(chan.get().get_funding_txo().unwrap(), monitor) {
if let Err(e) = self.chain_monitor.watch_channel(chan.get().get_funding_txo().unwrap(), monitor) {
return_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::RevokeAndACKFirst, false, false);
}
(chan.get().get_funding_txo().unwrap(), chan.get().get_user_id())
@ -2647,13 +2644,13 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
Err((None, e)) => try_chan_entry!(self, Err(e), channel_state, chan),
Err((Some(update), e)) => {
assert!(chan.get().is_awaiting_monitor_update());
let _ = self.monitor.update_monitor(chan.get().get_funding_txo().unwrap(), update);
let _ = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), update);
try_chan_entry!(self, Err(e), channel_state, chan);
unreachable!();
},
Ok(res) => res
};
if let Err(e) = self.monitor.update_monitor(chan.get().get_funding_txo().unwrap(), monitor_update) {
if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
return_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::RevokeAndACKFirst, true, commitment_signed.is_some());
//TODO: Rebroadcast closing_signed if present on monitor update restoration
}
@ -2735,7 +2732,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
let (commitment_update, pending_forwards, pending_failures, closing_signed, monitor_update, htlcs_to_fail_in) =
break_chan_entry!(self, chan.get_mut().revoke_and_ack(&msg, &self.fee_estimator, &self.logger), channel_state, chan);
htlcs_to_fail = htlcs_to_fail_in;
if let Err(e) = self.monitor.update_monitor(chan.get().get_funding_txo().unwrap(), monitor_update) {
if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
if was_frozen_for_monitor {
assert!(commitment_update.is_none() && closing_signed.is_none() && pending_forwards.is_empty() && pending_failures.is_empty());
break Err(MsgHandleErrInternal::ignore_no_close("Previous monitor update failure prevented responses to RAA".to_owned()));
@ -2860,7 +2857,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
let (funding_locked, revoke_and_ack, commitment_update, monitor_update_opt, mut order, shutdown) =
try_chan_entry!(self, chan.get_mut().channel_reestablish(msg, &self.logger), channel_state, chan);
if let Some(monitor_update) = monitor_update_opt {
if let Err(e) = self.monitor.update_monitor(chan.get().get_funding_txo().unwrap(), monitor_update) {
if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
// channel_reestablish doesn't guarantee the order it returns is sensical
// for the messages it returns, but if we're setting what messages to
// re-transmit on monitor update success, we need to make sure it is sane.
@ -2947,7 +2944,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
if let Some((update_fee, commitment_signed, monitor_update)) =
break_chan_entry!(self, chan.get_mut().send_update_fee_and_commit(feerate_per_kw, &self.logger), channel_state, chan)
{
if let Err(_e) = self.monitor.update_monitor(chan.get().get_funding_txo().unwrap(), monitor_update) {
if let Err(_e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
unimplemented!();
}
channel_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
@ -2973,11 +2970,11 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
}
}
/// Process pending events from the ManyChannelMonitor.
/// Process pending events from the `chain::Watch`.
fn process_pending_monitor_events(&self) {
let mut failed_channels = Vec::new();
{
for monitor_event in self.monitor.get_and_clear_pending_monitor_events() {
for monitor_event in self.chain_monitor.release_pending_monitor_events() {
match monitor_event {
MonitorEvent::HTLCEvent(htlc_update) => {
if let Some(preimage) = htlc_update.payment_preimage {
@ -3017,7 +3014,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
}
impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> MessageSendEventsProvider for ChannelManager<ChanSigner, M, T, K, F, L>
where M::Target: ManyChannelMonitor<Keys=ChanSigner>,
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
F::Target: FeeEstimator,
@ -3036,7 +3033,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
}
impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> EventsProvider for ChannelManager<ChanSigner, M, T, K, F, L>
where M::Target: ManyChannelMonitor<Keys=ChanSigner>,
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
F::Target: FeeEstimator,
@ -3054,17 +3051,17 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
}
}
impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send>
ChainListener for ChannelManager<ChanSigner, M, T, K, F, L>
where M::Target: ManyChannelMonitor<Keys=ChanSigner>,
impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<ChanSigner, M, T, K, F, L>
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
F::Target: FeeEstimator,
L::Target: Logger,
L::Target: Logger,
{
fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[usize]) {
/// Updates channel state based on transactions seen in a connected block.
pub fn block_connected(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) {
let header_hash = header.block_hash();
log_trace!(self.logger, "Block {} at height {} connected with {} txn matched", header_hash, height, txn_matched.len());
log_trace!(self.logger, "Block {} at height {} connected", header_hash, height);
let _ = self.total_consistency_lock.read().unwrap();
let mut failed_channels = Vec::new();
let mut timed_out_htlcs = Vec::new();
@ -3074,7 +3071,7 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
let short_to_id = &mut channel_state.short_to_id;
let pending_msg_events = &mut channel_state.pending_msg_events;
channel_state.by_id.retain(|_, channel| {
let res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
let res = channel.block_connected(header, txdata, height);
if let Ok((chan_res, mut timed_out_pending_htlcs)) = res {
for (source, payment_hash) in timed_out_pending_htlcs.drain(..) {
let chan_update = self.get_channel_update(&channel).map(|u| u.encode_with_len()).unwrap(); // Cannot add/recv HTLCs before we have a short_id so unwrap is safe
@ -3107,7 +3104,7 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
return false;
}
if let Some(funding_txo) = channel.get_funding_txo() {
for tx in txn_matched {
for &(_, tx) in txdata.iter() {
for inp in tx.input.iter() {
if inp.previous_output == funding_txo.into_bitcoin_outpoint() {
log_trace!(self.logger, "Detected channel-closing tx {} spending {}:{}, closing channel {}", tx.txid(), inp.previous_output.txid, inp.previous_output.vout, log_bytes!(channel.channel_id()));
@ -3173,8 +3170,11 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
}
}
/// We force-close the channel without letting our counterparty participate in the shutdown
fn block_disconnected(&self, header: &BlockHeader, _: u32) {
/// Updates channel state based on a disconnected block.
///
/// If necessary, the channel may be force-closed without letting the counterparty participate
/// in the shutdown.
pub fn block_disconnected(&self, header: &BlockHeader) {
let _ = self.total_consistency_lock.read().unwrap();
let mut failed_channels = Vec::new();
{
@ -3209,7 +3209,7 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send>
ChannelMessageHandler for ChannelManager<ChanSigner, M, T, K, F, L>
where M::Target: ManyChannelMonitor<Keys=ChanSigner>,
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
F::Target: FeeEstimator,
@ -3652,7 +3652,7 @@ impl Readable for HTLCForwardInfo {
}
impl<ChanSigner: ChannelKeys + Writeable, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable for ChannelManager<ChanSigner, M, T, K, F, L>
where M::Target: ManyChannelMonitor<Keys=ChanSigner>,
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
F::Target: FeeEstimator,
@ -3732,11 +3732,10 @@ impl<ChanSigner: ChannelKeys + Writeable, M: Deref, T: Deref, K: Deref, F: Deref
/// 3) Register all relevant ChannelMonitor outpoints with your chain watch mechanism using
/// ChannelMonitor::get_monitored_outpoints and ChannelMonitor::get_funding_txo().
/// 4) Reconnect blocks on your ChannelMonitors.
/// 5) Move the ChannelMonitors into your local ManyChannelMonitor.
/// 5) Move the ChannelMonitors into your local chain::Watch.
/// 6) Disconnect/connect blocks on the ChannelManager.
/// 7) Register the new ChannelManager with your ChainWatchInterface.
pub struct ChannelManagerReadArgs<'a, ChanSigner: 'a + ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
where M::Target: ManyChannelMonitor<Keys=ChanSigner>,
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
F::Target: FeeEstimator,
@ -3750,12 +3749,12 @@ pub struct ChannelManagerReadArgs<'a, ChanSigner: 'a + ChannelKeys, M: Deref, T:
///
/// No calls to the FeeEstimator will be made during deserialization.
pub fee_estimator: F,
/// The ManyChannelMonitor for use in the ChannelManager in the future.
/// The chain::Watch for use in the ChannelManager in the future.
///
/// No calls to the ManyChannelMonitor will be made during deserialization. It is assumed that
/// No calls to the chain::Watch will be made during deserialization. It is assumed that
/// you have deserialized ChannelMonitors separately and will add them to your
/// ManyChannelMonitor after deserializing this ChannelManager.
pub monitor: M,
/// chain::Watch after deserializing this ChannelManager.
pub chain_monitor: M,
/// The BroadcasterInterface which will be used in the ChannelManager in the future and may be
/// used to broadcast the latest local commitment transactions of channels which must be
@ -3785,7 +3784,7 @@ pub struct ChannelManagerReadArgs<'a, ChanSigner: 'a + ChannelKeys, M: Deref, T:
impl<'a, ChanSigner: 'a + ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
ChannelManagerReadArgs<'a, ChanSigner, M, T, K, F, L>
where M::Target: ManyChannelMonitor<Keys=ChanSigner>,
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
F::Target: FeeEstimator,
@ -3794,10 +3793,10 @@ impl<'a, ChanSigner: 'a + ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L
/// Simple utility function to create a ChannelManagerReadArgs which creates the monitor
/// HashMap for you. This is primarily useful for C bindings where it is not practical to
/// populate a HashMap directly from C.
pub fn new(keys_manager: K, fee_estimator: F, monitor: M, tx_broadcaster: T, logger: L, default_config: UserConfig,
pub fn new(keys_manager: K, fee_estimator: F, chain_monitor: M, tx_broadcaster: T, logger: L, default_config: UserConfig,
mut channel_monitors: Vec<&'a mut ChannelMonitor<ChanSigner>>) -> Self {
Self {
keys_manager, fee_estimator, monitor, tx_broadcaster, logger, default_config,
keys_manager, fee_estimator, chain_monitor, tx_broadcaster, logger, default_config,
channel_monitors: channel_monitors.drain(..).map(|monitor| { (monitor.get_funding_txo().0, monitor) }).collect()
}
}
@ -3807,7 +3806,7 @@ impl<'a, ChanSigner: 'a + ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L
// SipmleArcChannelManager type:
impl<'a, ChanSigner: ChannelKeys + Readable, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
ReadableArgs<ChannelManagerReadArgs<'a, ChanSigner, M, T, K, F, L>> for (BlockHash, Arc<ChannelManager<ChanSigner, M, T, K, F, L>>)
where M::Target: ManyChannelMonitor<Keys=ChanSigner>,
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
F::Target: FeeEstimator,
@ -3821,7 +3820,7 @@ impl<'a, ChanSigner: ChannelKeys + Readable, M: Deref, T: Deref, K: Deref, F: De
impl<'a, ChanSigner: ChannelKeys + Readable, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
ReadableArgs<ChannelManagerReadArgs<'a, ChanSigner, M, T, K, F, L>> for (BlockHash, ChannelManager<ChanSigner, M, T, K, F, L>)
where M::Target: ManyChannelMonitor<Keys=ChanSigner>,
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
F::Target: FeeEstimator,
@ -3933,7 +3932,7 @@ impl<'a, ChanSigner: ChannelKeys + Readable, M: Deref, T: Deref, K: Deref, F: De
let channel_manager = ChannelManager {
genesis_hash,
fee_estimator: args.fee_estimator,
monitor: args.monitor,
chain_monitor: args.chain_monitor,
tx_broadcaster: args.tx_broadcaster,
latest_block_height: AtomicUsize::new(latest_block_height as usize),

View file

@ -10,10 +10,10 @@
//! A bunch of useful utilities for building networks of nodes and exchanging messages between
//! nodes for functional tests.
use chain::chaininterface;
use chain::Watch;
use chain::channelmonitor::ChannelMonitor;
use chain::transaction::OutPoint;
use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure};
use ln::channelmonitor::{ChannelMonitor, ManyChannelMonitor};
use routing::router::{Route, get_route};
use routing::network_graph::{NetGraphMsgHandler, NetworkGraph};
use ln::features::InitFeatures;
@ -21,13 +21,13 @@ use ln::msgs;
use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler};
use util::enforcing_trait_impls::EnforcingChannelKeys;
use util::test_utils;
use util::test_utils::TestChannelMonitor;
use util::test_utils::TestChainMonitor;
use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
use util::errors::APIError;
use util::config::UserConfig;
use util::ser::{ReadableArgs, Writeable, Readable};
use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::block::{Block, BlockHeader};
use bitcoin::blockdata::transaction::{Transaction, TxOut};
use bitcoin::network::constants::Network;
@ -44,51 +44,76 @@ use std::mem;
use std::collections::HashMap;
pub const CHAN_CONFIRM_DEPTH: u32 = 100;
pub fn confirm_transaction<'a, 'b: 'a>(notifier: &'a chaininterface::BlockNotifierRef<'b, &chaininterface::ChainWatchInterfaceUtil>, chain: &chaininterface::ChainWatchInterfaceUtil, tx: &Transaction, chan_id: i32) {
assert!(chain.does_match_tx(tx));
let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
notifier.block_connected_checked(&header, 1, &[tx; 1], &[chan_id as usize; 1]);
pub fn confirm_transaction<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction) {
let dummy_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
let dummy_tx_count = tx.version as usize;
let mut block = Block {
header: BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: vec![dummy_tx; dummy_tx_count],
};
block.txdata.push(tx.clone());
connect_block(node, &block, 1);
for i in 2..CHAN_CONFIRM_DEPTH {
header = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
notifier.block_connected_checked(&header, i, &vec![], &[0; 0]);
block = Block {
header: BlockHeader { version: 0x20000000, prev_blockhash: block.header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: vec![],
};
connect_block(node, &block, i);
}
}
pub fn connect_blocks<'a, 'b>(notifier: &'a chaininterface::BlockNotifierRef<'b, &chaininterface::ChainWatchInterfaceUtil>, depth: u32, height: u32, parent: bool, prev_blockhash: BlockHash) -> BlockHash {
let mut header = BlockHeader { version: 0x2000000, prev_blockhash: if parent { prev_blockhash } else { Default::default() }, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
notifier.block_connected_checked(&header, height + 1, &Vec::new(), &Vec::new());
pub fn connect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, depth: u32, height: u32, parent: bool, prev_blockhash: BlockHash) -> BlockHash {
let mut block = Block {
header: BlockHeader { version: 0x2000000, prev_blockhash: if parent { prev_blockhash } else { Default::default() }, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: vec![],
};
connect_block(node, &block, height + 1);
for i in 2..depth + 1 {
header = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
notifier.block_connected_checked(&header, height + i, &Vec::new(), &Vec::new());
block = Block {
header: BlockHeader { version: 0x20000000, prev_blockhash: block.header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: vec![],
};
connect_block(node, &block, height + i);
}
header.block_hash()
block.header.block_hash()
}
pub fn connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: &Block, height: u32) {
let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
while node.chain_monitor.chain_monitor.block_connected(&block.header, &txdata, height) {}
node.node.block_connected(&block.header, &txdata, height);
}
pub fn disconnect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, header: &BlockHeader, height: u32) {
node.chain_monitor.chain_monitor.block_disconnected(header, height);
node.node.block_disconnected(header);
}
pub struct TestChanMonCfg {
pub tx_broadcaster: test_utils::TestBroadcaster,
pub fee_estimator: test_utils::TestFeeEstimator,
pub chain_monitor: chaininterface::ChainWatchInterfaceUtil,
pub chain_source: test_utils::TestChainSource,
pub logger: test_utils::TestLogger,
}
pub struct NodeCfg<'a> {
pub chain_monitor: &'a chaininterface::ChainWatchInterfaceUtil,
pub chain_source: &'a test_utils::TestChainSource,
pub tx_broadcaster: &'a test_utils::TestBroadcaster,
pub fee_estimator: &'a test_utils::TestFeeEstimator,
pub chan_monitor: test_utils::TestChannelMonitor<'a>,
pub chain_monitor: test_utils::TestChainMonitor<'a>,
pub keys_manager: test_utils::TestKeysInterface,
pub logger: &'a test_utils::TestLogger,
pub node_seed: [u8; 32],
}
pub struct Node<'a, 'b: 'a, 'c: 'b> {
pub block_notifier: chaininterface::BlockNotifierRef<'a, &'c chaininterface::ChainWatchInterfaceUtil>,
pub chain_monitor: &'c chaininterface::ChainWatchInterfaceUtil,
pub chain_source: &'c test_utils::TestChainSource,
pub tx_broadcaster: &'c test_utils::TestBroadcaster,
pub chan_monitor: &'b test_utils::TestChannelMonitor<'c>,
pub chain_monitor: &'b test_utils::TestChainMonitor<'c>,
pub keys_manager: &'b test_utils::TestKeysInterface,
pub node: &'a ChannelManager<EnforcingChannelKeys, &'b TestChannelMonitor<'c>, &'c test_utils::TestBroadcaster, &'b test_utils::TestKeysInterface, &'c test_utils::TestFeeEstimator, &'c test_utils::TestLogger>,
pub net_graph_msg_handler: NetGraphMsgHandler<&'c chaininterface::ChainWatchInterfaceUtil, &'c test_utils::TestLogger>,
pub node: &'a ChannelManager<EnforcingChannelKeys, &'b TestChainMonitor<'c>, &'c test_utils::TestBroadcaster, &'b test_utils::TestKeysInterface, &'c test_utils::TestFeeEstimator, &'c test_utils::TestLogger>,
pub net_graph_msg_handler: NetGraphMsgHandler<&'c test_utils::TestChainSource, &'c test_utils::TestLogger>,
pub node_seed: [u8; 32],
pub network_payment_count: Rc<RefCell<u8>>,
pub network_chan_count: Rc<RefCell<u32>>,
@ -101,7 +126,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> {
// Check that we processed all pending events
assert!(self.node.get_and_clear_pending_msg_events().is_empty());
assert!(self.node.get_and_clear_pending_events().is_empty());
assert!(self.chan_monitor.added_monitors.lock().unwrap().is_empty());
assert!(self.chain_monitor.added_monitors.lock().unwrap().is_empty());
// Check that if we serialize the Router, we can deserialize it again.
{
@ -111,7 +136,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> {
let network_graph_deser = <NetworkGraph>::read(&mut ::std::io::Cursor::new(&w.0)).unwrap();
assert!(network_graph_deser == *self.net_graph_msg_handler.network_graph.read().unwrap());
let net_graph_msg_handler = NetGraphMsgHandler::from_net_graph(
self.chain_monitor, self.logger, network_graph_deser
Some(self.chain_source), self.logger, network_graph_deser
);
let mut chan_progress = 0;
loop {
@ -141,7 +166,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> {
let feeest = test_utils::TestFeeEstimator { sat_per_kw: 253 };
let mut deserialized_monitors = Vec::new();
{
let old_monitors = self.chan_monitor.simple_monitor.monitors.lock().unwrap();
let old_monitors = self.chain_monitor.chain_monitor.monitors.lock().unwrap();
for (_, old_monitor) in old_monitors.iter() {
let mut w = test_utils::TestVecWriter(Vec::new());
old_monitor.write_for_disk(&mut w).unwrap();
@ -161,27 +186,26 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> {
let mut w = test_utils::TestVecWriter(Vec::new());
self.node.write(&mut w).unwrap();
<(BlockHash, ChannelManager<EnforcingChannelKeys, &test_utils::TestChannelMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut ::std::io::Cursor::new(w.0), ChannelManagerReadArgs {
<(BlockHash, ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut ::std::io::Cursor::new(w.0), ChannelManagerReadArgs {
default_config: UserConfig::default(),
keys_manager: self.keys_manager,
fee_estimator: &test_utils::TestFeeEstimator { sat_per_kw: 253 },
monitor: self.chan_monitor,
chain_monitor: self.chain_monitor,
tx_broadcaster: self.tx_broadcaster.clone(),
logger: &test_utils::TestLogger::new(),
channel_monitors,
}).unwrap();
}
let chain_watch = chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet);
let channel_monitor = test_utils::TestChannelMonitor::new(&chain_watch, self.tx_broadcaster.clone(), &self.logger, &feeest);
let chain_source = test_utils::TestChainSource::new(Network::Testnet);
let chain_monitor = test_utils::TestChainMonitor::new(Some(&chain_source), self.tx_broadcaster.clone(), &self.logger, &feeest);
for deserialized_monitor in deserialized_monitors.drain(..) {
if let Err(_) = channel_monitor.add_monitor(deserialized_monitor.get_funding_txo().0, deserialized_monitor) {
if let Err(_) = chain_monitor.watch_channel(deserialized_monitor.get_funding_txo().0, deserialized_monitor) {
panic!();
}
}
if chain_watch != *self.chain_monitor {
panic!();
}
assert_eq!(*chain_source.watched_txn.lock().unwrap(), *self.chain_source.watched_txn.lock().unwrap());
assert_eq!(*chain_source.watched_outputs.lock().unwrap(), *self.chain_source.watched_outputs.lock().unwrap());
}
}
}
@ -268,7 +292,7 @@ macro_rules! get_feerate {
macro_rules! get_local_commitment_txn {
($node: expr, $channel_id: expr) => {
{
let mut monitors = $node.chan_monitor.simple_monitor.monitors.lock().unwrap();
let mut monitors = $node.chain_monitor.chain_monitor.monitors.lock().unwrap();
let mut commitment_txn = None;
for (funding_txo, monitor) in monitors.iter_mut() {
if funding_txo.to_channel_id() == $channel_id {
@ -306,7 +330,7 @@ macro_rules! unwrap_send_err {
macro_rules! check_added_monitors {
($node: expr, $count: expr) => {
{
let mut added_monitors = $node.chan_monitor.added_monitors.lock().unwrap();
let mut added_monitors = $node.chain_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), $count);
added_monitors.clear();
}
@ -345,7 +369,7 @@ pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, '
node_b.node.handle_funding_created(&node_a.node.get_our_node_id(), &get_event_msg!(node_a, MessageSendEvent::SendFundingCreated, node_b.node.get_our_node_id()));
{
let mut added_monitors = node_b.chan_monitor.added_monitors.lock().unwrap();
let mut added_monitors = node_b.chain_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 1);
assert_eq!(added_monitors[0].0, funding_output);
added_monitors.clear();
@ -353,7 +377,7 @@ pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, '
node_a.node.handle_funding_signed(&node_b.node.get_our_node_id(), &get_event_msg!(node_b, MessageSendEvent::SendFundingSigned, node_a.node.get_our_node_id()));
{
let mut added_monitors = node_a.chan_monitor.added_monitors.lock().unwrap();
let mut added_monitors = node_a.chain_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 1);
assert_eq!(added_monitors[0].0, funding_output);
added_monitors.clear();
@ -373,7 +397,7 @@ pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, '
}
pub fn create_chan_between_nodes_with_value_confirm_first<'a, 'b, 'c, 'd>(node_recv: &'a Node<'b, 'c, 'c>, node_conf: &'a Node<'b, 'c, 'd>, tx: &Transaction) {
confirm_transaction(&node_conf.block_notifier, &node_conf.chain_monitor, &tx, tx.version);
confirm_transaction(node_conf, tx);
node_recv.node.handle_funding_locked(&node_conf.node.get_our_node_id(), &get_event_msg!(node_conf, MessageSendEvent::SendFundingLocked, node_recv.node.get_our_node_id()));
}
@ -399,7 +423,7 @@ pub fn create_chan_between_nodes_with_value_confirm_second<'a, 'b, 'c>(node_recv
pub fn create_chan_between_nodes_with_value_confirm<'a, 'b, 'c, 'd>(node_a: &'a Node<'b, 'c, 'd>, node_b: &'a Node<'b, 'c, 'd>, tx: &Transaction) -> ((msgs::FundingLocked, msgs::AnnouncementSignatures), [u8; 32]) {
create_chan_between_nodes_with_value_confirm_first(node_a, node_b, tx);
confirm_transaction(&node_a.block_notifier, &node_a.chain_monitor, &tx, tx.version);
confirm_transaction(node_a, tx);
create_chan_between_nodes_with_value_confirm_second(node_b, node_a)
}
@ -1067,9 +1091,9 @@ pub fn create_chanmon_cfgs(node_count: usize) -> Vec<TestChanMonCfg> {
for i in 0..node_count {
let tx_broadcaster = test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())};
let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 };
let chain_monitor = chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet);
let chain_source = test_utils::TestChainSource::new(Network::Testnet);
let logger = test_utils::TestLogger::with_id(format!("node {}", i));
chan_mon_cfgs.push(TestChanMonCfg{ tx_broadcaster, fee_estimator, chain_monitor, logger });
chan_mon_cfgs.push(TestChanMonCfg{ tx_broadcaster, fee_estimator, chain_source, logger });
}
chan_mon_cfgs
@ -1081,39 +1105,36 @@ pub fn create_node_cfgs<'a>(node_count: usize, chanmon_cfgs: &'a Vec<TestChanMon
for i in 0..node_count {
let seed = [i as u8; 32];
let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
let chan_monitor = test_utils::TestChannelMonitor::new(&chanmon_cfgs[i].chain_monitor, &chanmon_cfgs[i].tx_broadcaster, &chanmon_cfgs[i].logger, &chanmon_cfgs[i].fee_estimator);
nodes.push(NodeCfg { chain_monitor: &chanmon_cfgs[i].chain_monitor, logger: &chanmon_cfgs[i].logger, tx_broadcaster: &chanmon_cfgs[i].tx_broadcaster, fee_estimator: &chanmon_cfgs[i].fee_estimator, chan_monitor, keys_manager, node_seed: seed });
let chain_monitor = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[i].chain_source), &chanmon_cfgs[i].tx_broadcaster, &chanmon_cfgs[i].logger, &chanmon_cfgs[i].fee_estimator);
nodes.push(NodeCfg { chain_source: &chanmon_cfgs[i].chain_source, logger: &chanmon_cfgs[i].logger, tx_broadcaster: &chanmon_cfgs[i].tx_broadcaster, fee_estimator: &chanmon_cfgs[i].fee_estimator, chain_monitor, keys_manager, node_seed: seed });
}
nodes
}
pub fn create_node_chanmgrs<'a, 'b>(node_count: usize, cfgs: &'a Vec<NodeCfg<'b>>, node_config: &[Option<UserConfig>]) -> Vec<ChannelManager<EnforcingChannelKeys, &'a TestChannelMonitor<'b>, &'b test_utils::TestBroadcaster, &'a test_utils::TestKeysInterface, &'b test_utils::TestFeeEstimator, &'b test_utils::TestLogger>> {
pub fn create_node_chanmgrs<'a, 'b>(node_count: usize, cfgs: &'a Vec<NodeCfg<'b>>, node_config: &[Option<UserConfig>]) -> Vec<ChannelManager<EnforcingChannelKeys, &'a TestChainMonitor<'b>, &'b test_utils::TestBroadcaster, &'a test_utils::TestKeysInterface, &'b test_utils::TestFeeEstimator, &'b test_utils::TestLogger>> {
let mut chanmgrs = Vec::new();
for i in 0..node_count {
let mut default_config = UserConfig::default();
default_config.channel_options.announced_channel = true;
default_config.peer_channel_config_limits.force_announced_channel_preference = false;
default_config.own_channel_config.our_htlc_minimum_msat = 1000; // sanitization being done by the sender, to exerce receiver logic we need to lift of limit
let node = ChannelManager::new(Network::Testnet, cfgs[i].fee_estimator, &cfgs[i].chan_monitor, cfgs[i].tx_broadcaster, cfgs[i].logger.clone(), &cfgs[i].keys_manager, if node_config[i].is_some() { node_config[i].clone().unwrap() } else { default_config }, 0);
let node = ChannelManager::new(Network::Testnet, cfgs[i].fee_estimator, &cfgs[i].chain_monitor, cfgs[i].tx_broadcaster, cfgs[i].logger.clone(), &cfgs[i].keys_manager, if node_config[i].is_some() { node_config[i].clone().unwrap() } else { default_config }, 0);
chanmgrs.push(node);
}
chanmgrs
}
pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec<NodeCfg<'c>>, chan_mgrs: &'a Vec<ChannelManager<EnforcingChannelKeys, &'b TestChannelMonitor<'c>, &'c test_utils::TestBroadcaster, &'b test_utils::TestKeysInterface, &'c test_utils::TestFeeEstimator, &'c test_utils::TestLogger>>) -> Vec<Node<'a, 'b, 'c>> {
pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec<NodeCfg<'c>>, chan_mgrs: &'a Vec<ChannelManager<EnforcingChannelKeys, &'b TestChainMonitor<'c>, &'c test_utils::TestBroadcaster, &'b test_utils::TestKeysInterface, &'c test_utils::TestFeeEstimator, &'c test_utils::TestLogger>>) -> Vec<Node<'a, 'b, 'c>> {
let mut nodes = Vec::new();
let chan_count = Rc::new(RefCell::new(0));
let payment_count = Rc::new(RefCell::new(0));
for i in 0..node_count {
let block_notifier = chaininterface::BlockNotifier::new(cfgs[i].chain_monitor);
block_notifier.register_listener(&cfgs[i].chan_monitor.simple_monitor as &chaininterface::ChainListener);
block_notifier.register_listener(&chan_mgrs[i] as &chaininterface::ChainListener);
let net_graph_msg_handler = NetGraphMsgHandler::new(cfgs[i].chain_monitor, cfgs[i].logger);
nodes.push(Node{ chain_monitor: &cfgs[i].chain_monitor, block_notifier,
tx_broadcaster: cfgs[i].tx_broadcaster, chan_monitor: &cfgs[i].chan_monitor,
let net_graph_msg_handler = NetGraphMsgHandler::new(None, cfgs[i].logger);
nodes.push(Node{ chain_source: cfgs[i].chain_source,
tx_broadcaster: cfgs[i].tx_broadcaster, chain_monitor: &cfgs[i].chain_monitor,
keys_manager: &cfgs[i].keys_manager, node: &chan_mgrs[i], net_graph_msg_handler,
node_seed: cfgs[i].node_seed, network_chan_count: chan_count.clone(),
network_payment_count: payment_count.clone(), logger: cfgs[i].logger,

File diff suppressed because it is too large Load diff

View file

@ -19,7 +19,6 @@
//! call into your NetGraphMsgHandler.
pub mod channelmanager;
pub mod channelmonitor;
pub mod msgs;
pub mod peer_handler;
pub mod chan_utils;

View file

@ -22,11 +22,11 @@ use bitcoin::secp256k1::{Secp256k1, Signature};
use bitcoin::secp256k1;
use ln::msgs::DecodeError;
use ln::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest};
use ln::channelmanager::PaymentPreimage;
use ln::chan_utils;
use ln::chan_utils::{TxCreationKeys, HolderCommitmentTransaction};
use chain::chaininterface::{FeeEstimator, BroadcasterInterface, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT};
use chain::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest};
use chain::keysinterface::ChannelKeys;
use util::logger::Logger;
use util::ser::{Readable, Writer, Writeable};
@ -405,7 +405,7 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for OnchainTxHandler<ChanSigne
}
impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
pub(super) fn new(destination_script: Script, keys: ChanSigner, on_holder_tx_csv: u16) -> Self {
pub(crate) fn new(destination_script: Script, keys: ChanSigner, on_holder_tx_csv: u16) -> Self {
let key_storage = keys;
@ -425,7 +425,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
}
}
pub(super) fn get_witnesses_weight(inputs: &[InputDescriptors]) -> usize {
pub(crate) fn get_witnesses_weight(inputs: &[InputDescriptors]) -> usize {
let mut tx_weight = 2; // count segwit flags
for inp in inputs {
// We use expected weight (and not actual) as signatures and time lock delays may vary
@ -657,7 +657,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
None
}
pub(super) fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], claimable_outpoints: Vec<ClaimRequest>, height: u32, broadcaster: B, fee_estimator: F, logger: L)
pub(crate) fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], claimable_outpoints: Vec<ClaimRequest>, height: u32, broadcaster: B, fee_estimator: F, logger: L)
where B::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
@ -829,7 +829,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
}
}
pub(super) fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, broadcaster: B, fee_estimator: F, logger: L)
pub(crate) fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, broadcaster: B, fee_estimator: F, logger: L)
where B::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
@ -877,7 +877,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
}
}
pub(super) fn provide_latest_holder_tx(&mut self, tx: HolderCommitmentTransaction) {
pub(crate) fn provide_latest_holder_tx(&mut self, tx: HolderCommitmentTransaction) {
self.prev_holder_commitment = self.holder_commitment.take();
self.holder_commitment = Some(tx);
}
@ -919,7 +919,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
// have empty holder commitment transaction if a ChannelMonitor is asked to force-close just after Channel::get_outbound_funding_created,
// before providing a initial commitment transaction. For outbound channel, init ChannelMonitor at Channel::funding_signed, there is nothing
// to monitor before.
pub(super) fn get_fully_signed_holder_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> {
pub(crate) fn get_fully_signed_holder_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> {
if let Some(ref mut holder_commitment) = self.holder_commitment {
match self.key_storage.sign_holder_commitment(holder_commitment, &self.secp_ctx) {
Ok(sig) => Some(holder_commitment.add_holder_sig(funding_redeemscript, sig)),
@ -931,7 +931,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
}
#[cfg(any(test, feature="unsafe_revoked_tx_signing"))]
pub(super) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> {
pub(crate) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> {
if let Some(ref mut holder_commitment) = self.holder_commitment {
let holder_commitment = holder_commitment.clone();
match self.key_storage.sign_holder_commitment(&holder_commitment, &self.secp_ctx) {
@ -943,7 +943,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
}
}
pub(super) fn get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>) -> Option<Transaction> {
pub(crate) fn get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>) -> Option<Transaction> {
let mut htlc_tx = None;
if self.holder_commitment.is_some() {
let commitment_txid = self.holder_commitment.as_ref().unwrap().txid();
@ -971,7 +971,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
}
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
pub(super) fn unsafe_get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>) -> Option<Transaction> {
pub(crate) fn unsafe_get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>) -> Option<Transaction> {
let latest_had_sigs = self.holder_htlc_sigs.is_some();
let prev_had_sigs = self.prev_holder_htlc_sigs.is_some();
let ret = self.get_fully_signed_htlc_tx(outp, preimage);

View file

@ -11,8 +11,8 @@
//! These tests work by standing up full nodes and route payments across the network, checking the
//! returned errors decode to the correct thing.
use chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
use ln::channelmanager::{HTLCForwardInfo, PaymentPreimage, PaymentHash};
use ln::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
use ln::onion_utils;
use routing::router::{Route, get_route};
use ln::features::InitFeatures;
@ -23,7 +23,7 @@ use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsPro
use util::ser::{Writeable, Writer};
use util::config::UserConfig;
use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::block::{Block, BlockHeader};
use bitcoin::hash_types::BlockHash;
use bitcoin::hashes::sha256::Hash as Sha256;
@ -59,9 +59,12 @@ fn run_onion_failure_test_with_fail_intercept<F1,F2,F3>(_name: &str, test_case:
{
// reset block height
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
let block = Block {
header: BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: vec![],
};
for ix in 0..nodes.len() {
nodes[ix].block_notifier.block_connected_checked(&header, 1, &[], &[]);
connect_block(&nodes[ix], &block, 1);
}
macro_rules! expect_event {
@ -440,9 +443,12 @@ fn test_onion_failure() {
run_onion_failure_test("expiry_too_soon", 0, &nodes, &route, &payment_hash, |msg| {
let height = msg.cltv_expiry - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS + 1;
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
let block = Block {
header: BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: vec![],
};
nodes[1].block_notifier.block_connected_checked(&header, height, &[], &[]);
connect_block(&nodes[1], &block, height);
}, ||{}, true, Some(UPDATE|14), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
run_onion_failure_test("unknown_payment_hash", 2, &nodes, &route, &payment_hash, |_| {}, || {
@ -451,9 +457,12 @@ fn test_onion_failure() {
run_onion_failure_test("final_expiry_too_soon", 1, &nodes, &route, &payment_hash, |msg| {
let height = msg.cltv_expiry - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS + 1;
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
let block = Block {
header: BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: vec![],
};
nodes[2].block_notifier.block_connected_checked(&header, height, &[], &[]);
connect_block(&nodes[2], &block, height);
}, || {}, true, Some(17), None);
run_onion_failure_test("final_incorrect_cltv_expiry", 1, &nodes, &route, &payment_hash, |_| {}, || {

View file

@ -9,7 +9,7 @@
//! Further functional tests which test blockchain reorganizations.
use ln::channelmonitor::ANTI_REORG_DELAY;
use chain::channelmonitor::ANTI_REORG_DELAY;
use ln::features::InitFeatures;
use ln::msgs::{ChannelMessageHandler, ErrorAction, HTLCFailChannelUpdate};
use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
@ -51,8 +51,7 @@ fn do_test_onchain_htlc_reorg(local_commitment: bool, claim: bool) {
check_added_monitors!(nodes[2], 1);
get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
let mut headers = Vec::new();
let mut header = BlockHeader { version: 0x2000_0000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
let header = BlockHeader { version: 0x2000_0000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
let claim_txn = if local_commitment {
// Broadcast node 1 commitment txn to broadcast the HTLC-Timeout
let node_1_commitment_txn = get_local_commitment_txn!(nodes[1], chan_2.2);
@ -62,7 +61,7 @@ fn do_test_onchain_htlc_reorg(local_commitment: bool, claim: bool) {
check_spends!(node_1_commitment_txn[1], node_1_commitment_txn[0]);
// Give node 2 node 1's transactions and get its response (claiming the HTLC instead).
nodes[2].block_notifier.block_connected(&Block { header, txdata: node_1_commitment_txn.clone() }, CHAN_CONFIRM_DEPTH + 1);
connect_block(&nodes[2], &Block { header, txdata: node_1_commitment_txn.clone() }, CHAN_CONFIRM_DEPTH + 1);
check_added_monitors!(nodes[2], 1);
check_closed_broadcast!(nodes[2], false); // We should get a BroadcastChannelUpdate (and *only* a BroadcstChannelUpdate)
let node_2_commitment_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap();
@ -73,7 +72,7 @@ fn do_test_onchain_htlc_reorg(local_commitment: bool, claim: bool) {
check_spends!(node_2_commitment_txn[0], node_1_commitment_txn[0]);
// Confirm node 1's commitment txn (and HTLC-Timeout) on node 1
nodes[1].block_notifier.block_connected(&Block { header, txdata: node_1_commitment_txn.clone() }, CHAN_CONFIRM_DEPTH + 1);
connect_block(&nodes[1], &Block { header, txdata: node_1_commitment_txn.clone() }, CHAN_CONFIRM_DEPTH + 1);
// ...but return node 1's commitment tx in case claim is set and we're preparing to reorg
vec![node_1_commitment_txn[0].clone(), node_2_commitment_txn[0].clone()]
@ -86,7 +85,7 @@ fn do_test_onchain_htlc_reorg(local_commitment: bool, claim: bool) {
check_spends!(node_2_commitment_txn[1], node_2_commitment_txn[0]);
// Give node 1 node 2's commitment transaction and get its response (timing the HTLC out)
nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![node_2_commitment_txn[0].clone()] }, CHAN_CONFIRM_DEPTH + 1);
connect_block(&nodes[1], &Block { header, txdata: vec![node_2_commitment_txn[0].clone()] }, CHAN_CONFIRM_DEPTH + 1);
let node_1_commitment_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
assert_eq!(node_1_commitment_txn.len(), 3); // ChannelMonitor: 1 offered HTLC-Timeout, ChannelManger: 1 local commitment tx, 1 Offered HTLC-Timeout
assert_eq!(node_1_commitment_txn[1].output.len(), 2); // to-local and Offered HTLC (to-remote is dust)
@ -95,39 +94,50 @@ fn do_test_onchain_htlc_reorg(local_commitment: bool, claim: bool) {
check_spends!(node_1_commitment_txn[0], node_2_commitment_txn[0]);
// Confirm node 2's commitment txn (and node 1's HTLC-Timeout) on node 1
nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![node_2_commitment_txn[0].clone(), node_1_commitment_txn[0].clone()] }, CHAN_CONFIRM_DEPTH + 1);
connect_block(&nodes[1], &Block { header, txdata: vec![node_2_commitment_txn[0].clone(), node_1_commitment_txn[0].clone()] }, CHAN_CONFIRM_DEPTH + 1);
// ...but return node 2's commitment tx (and claim) in case claim is set and we're preparing to reorg
node_2_commitment_txn
};
check_added_monitors!(nodes[1], 1);
check_closed_broadcast!(nodes[1], false); // We should get a BroadcastChannelUpdate (and *only* a BroadcstChannelUpdate)
headers.push(header.clone());
let mut block = Block { header, txdata: vec![] };
let mut blocks = Vec::new();
blocks.push(block.clone());
// At CHAN_CONFIRM_DEPTH + 1 we have a confirmation count of 1, so CHAN_CONFIRM_DEPTH +
// ANTI_REORG_DELAY - 1 will give us a confirmation count of ANTI_REORG_DELAY - 1.
for i in CHAN_CONFIRM_DEPTH + 2..CHAN_CONFIRM_DEPTH + ANTI_REORG_DELAY - 1 {
header = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[1].block_notifier.block_connected_checked(&header, i, &vec![], &[0; 0]);
headers.push(header.clone());
block = Block {
header: BlockHeader { version: 0x20000000, prev_blockhash: block.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: vec![],
};
connect_block(&nodes[1], &block, i);
blocks.push(block.clone());
}
check_added_monitors!(nodes[1], 0);
assert_eq!(nodes[1].node.get_and_clear_pending_events().len(), 0);
if claim {
// Now reorg back to CHAN_CONFIRM_DEPTH and confirm node 2's broadcasted transactions:
for (height, header) in (CHAN_CONFIRM_DEPTH + 1..CHAN_CONFIRM_DEPTH + ANTI_REORG_DELAY - 1).zip(headers.iter()).rev() {
nodes[1].block_notifier.block_disconnected(&header, height);
for (height, block) in (CHAN_CONFIRM_DEPTH + 1..CHAN_CONFIRM_DEPTH + ANTI_REORG_DELAY - 1).zip(blocks.iter()).rev() {
disconnect_block(&nodes[1], &block.header, height);
}
header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[1].block_notifier.block_connected(&Block { header, txdata: claim_txn }, CHAN_CONFIRM_DEPTH + 1);
block = Block {
header: BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: claim_txn,
};
connect_block(&nodes[1], &block, CHAN_CONFIRM_DEPTH + 1);
// ChannelManager only polls ManyChannelMonitor::get_and_clear_pending_monitor_events when we
// ChannelManager only polls chain::Watch::release_pending_monitor_events when we
// probe it for events, so we probe non-message events here (which should still end up empty):
assert_eq!(nodes[1].node.get_and_clear_pending_events().len(), 0);
} else {
// Confirm the timeout tx and check that we fail the HTLC backwards
header = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[1].block_notifier.block_connected_checked(&header, CHAN_CONFIRM_DEPTH + ANTI_REORG_DELAY, &vec![], &[0; 0]);
block = Block {
header: BlockHeader { version: 0x20000000, prev_blockhash: block.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: vec![],
};
connect_block(&nodes[1], &block, CHAN_CONFIRM_DEPTH + ANTI_REORG_DELAY);
expect_pending_htlcs_forwardable!(nodes[1]);
}

View file

@ -16,9 +16,11 @@ use bitcoin::secp256k1;
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
use bitcoin::hashes::Hash;
use bitcoin::blockdata::script::Builder;
use bitcoin::blockdata::transaction::TxOut;
use bitcoin::blockdata::opcodes;
use chain::chaininterface::{ChainError, ChainWatchInterface};
use chain;
use chain::Access;
use ln::features::{ChannelFeatures, NodeFeatures};
use ln::msgs::{DecodeError, ErrorAction, LightningError, RoutingMessageHandler, NetAddress, MAX_VALUE_MSAT};
use ln::msgs::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, OptionalField};
@ -51,22 +53,22 @@ pub struct LockedNetworkGraph<'a>(pub RwLockReadGuard<'a, NetworkGraph>);
/// This network graph is then used for routing payments.
/// Provides interface to help with initial routing sync by
/// serving historical announcements.
pub struct NetGraphMsgHandler<C: Deref, L: Deref> where C::Target: ChainWatchInterface, L::Target: Logger {
pub struct NetGraphMsgHandler<C: Deref, L: Deref> where C::Target: chain::Access, L::Target: Logger {
secp_ctx: Secp256k1<secp256k1::VerifyOnly>,
/// Representation of the payment channel network
pub network_graph: RwLock<NetworkGraph>,
chain_monitor: C,
chain_access: Option<C>,
full_syncs_requested: AtomicUsize,
logger: L,
}
impl<C: Deref, L: Deref> NetGraphMsgHandler<C, L> where C::Target: ChainWatchInterface, L::Target: Logger {
impl<C: Deref, L: Deref> NetGraphMsgHandler<C, L> where C::Target: chain::Access, L::Target: Logger {
/// Creates a new tracker of the actual state of the network of channels and nodes,
/// assuming a fresh network graph.
/// Chain monitor is used to make sure announced channels exist on-chain,
/// channel data is correct, and that the announcement is signed with
/// channel owners' keys.
pub fn new(chain_monitor: C, logger: L) -> Self {
pub fn new(chain_access: Option<C>, logger: L) -> Self {
NetGraphMsgHandler {
secp_ctx: Secp256k1::verification_only(),
network_graph: RwLock::new(NetworkGraph {
@ -74,19 +76,19 @@ impl<C: Deref, L: Deref> NetGraphMsgHandler<C, L> where C::Target: ChainWatchInt
nodes: BTreeMap::new(),
}),
full_syncs_requested: AtomicUsize::new(0),
chain_monitor,
chain_access,
logger,
}
}
/// Creates a new tracker of the actual state of the network of channels and nodes,
/// assuming an existing Network Graph.
pub fn from_net_graph(chain_monitor: C, logger: L, network_graph: NetworkGraph) -> Self {
pub fn from_net_graph(chain_access: Option<C>, logger: L, network_graph: NetworkGraph) -> Self {
NetGraphMsgHandler {
secp_ctx: Secp256k1::verification_only(),
network_graph: RwLock::new(network_graph),
full_syncs_requested: AtomicUsize::new(0),
chain_monitor,
chain_access,
logger,
}
}
@ -117,7 +119,7 @@ macro_rules! secp_verify_sig {
};
}
impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for NetGraphMsgHandler<C, L> where C::Target: ChainWatchInterface, L::Target: Logger {
impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for NetGraphMsgHandler<C, L> where C::Target: chain::Access, L::Target: Logger {
fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<bool, LightningError> {
self.network_graph.write().unwrap().update_node_from_announcement(msg, Some(&self.secp_ctx))
}
@ -127,29 +129,33 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError});
}
let utxo_value = match self.chain_monitor.get_chain_utxo(msg.contents.chain_hash, msg.contents.short_channel_id) {
Ok((script_pubkey, value)) => {
let expected_script = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2)
.push_slice(&msg.contents.bitcoin_key_1.serialize())
.push_slice(&msg.contents.bitcoin_key_2.serialize())
.push_opcode(opcodes::all::OP_PUSHNUM_2)
.push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh();
if script_pubkey != expected_script {
return Err(LightningError{err: format!("Channel announcement key ({}) didn't match on-chain script ({})", script_pubkey.to_hex(), expected_script.to_hex()), action: ErrorAction::IgnoreError});
}
//TODO: Check if value is worth storing, use it to inform routing, and compare it
//to the new HTLC max field in channel_update
Some(value)
},
Err(ChainError::NotSupported) => {
let utxo_value = match &self.chain_access {
&None => {
// Tentatively accept, potentially exposing us to DoS attacks
None
},
Err(ChainError::NotWatched) => {
return Err(LightningError{err: format!("Channel announced on an unknown chain ({})", msg.contents.chain_hash.encode().to_hex()), action: ErrorAction::IgnoreError});
},
Err(ChainError::UnknownTx) => {
return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorAction::IgnoreError});
&Some(ref chain_access) => {
match chain_access.get_utxo(&msg.contents.chain_hash, msg.contents.short_channel_id) {
Ok(TxOut { value, script_pubkey }) => {
let expected_script = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2)
.push_slice(&msg.contents.bitcoin_key_1.serialize())
.push_slice(&msg.contents.bitcoin_key_2.serialize())
.push_opcode(opcodes::all::OP_PUSHNUM_2)
.push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh();
if script_pubkey != expected_script {
return Err(LightningError{err: format!("Channel announcement key ({}) didn't match on-chain script ({})", script_pubkey.to_hex(), expected_script.to_hex()), action: ErrorAction::IgnoreError});
}
//TODO: Check if value is worth storing, use it to inform routing, and compare it
//to the new HTLC max field in channel_update
Some(value)
},
Err(chain::AccessError::UnknownChain) => {
return Err(LightningError{err: format!("Channel announced on an unknown chain ({})", msg.contents.chain_hash.encode().to_hex()), action: ErrorAction::IgnoreError});
},
Err(chain::AccessError::UnknownTx) => {
return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorAction::IgnoreError});
},
}
},
};
let result = self.network_graph.write().unwrap().update_channel_from_announcement(msg, utxo_value, Some(&self.secp_ctx));
@ -828,7 +834,7 @@ impl NetworkGraph {
#[cfg(test)]
mod tests {
use chain::chaininterface;
use chain;
use ln::features::{ChannelFeatures, NodeFeatures};
use routing::network_graph::{NetGraphMsgHandler, NetworkGraph};
use ln::msgs::{OptionalField, RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
@ -843,6 +849,7 @@ mod tests {
use bitcoin::network::constants::Network;
use bitcoin::blockdata::constants::genesis_block;
use bitcoin::blockdata::script::Builder;
use bitcoin::blockdata::transaction::TxOut;
use bitcoin::blockdata::opcodes;
use hex;
@ -852,11 +859,10 @@ mod tests {
use std::sync::Arc;
fn create_net_graph_msg_handler() -> (Secp256k1<All>, NetGraphMsgHandler<Arc<chaininterface::ChainWatchInterfaceUtil>, Arc<test_utils::TestLogger>>) {
fn create_net_graph_msg_handler() -> (Secp256k1<All>, NetGraphMsgHandler<Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>) {
let secp_ctx = Secp256k1::new();
let logger = Arc::new(test_utils::TestLogger::new());
let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet));
let net_graph_msg_handler = NetGraphMsgHandler::new(chain_monitor, Arc::clone(&logger));
let net_graph_msg_handler = NetGraphMsgHandler::new(None, Arc::clone(&logger));
(secp_ctx, net_graph_msg_handler)
}
@ -981,9 +987,6 @@ mod tests {
fn handling_channel_announcements() {
let secp_ctx = Secp256k1::new();
let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::new());
let chain_monitor = Arc::new(test_utils::TestChainWatcher::new());
let net_graph_msg_handler = NetGraphMsgHandler::new(chain_monitor.clone(), Arc::clone(&logger));
let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
@ -1020,8 +1023,7 @@ mod tests {
};
// Test if the UTXO lookups were not supported
*chain_monitor.utxo_ret.lock().unwrap() = Err(chaininterface::ChainError::NotSupported);
let mut net_graph_msg_handler = NetGraphMsgHandler::new(None, Arc::clone(&logger));
match net_graph_msg_handler.handle_channel_announcement(&valid_announcement) {
Ok(res) => assert!(res),
_ => panic!()
@ -1035,7 +1037,6 @@ mod tests {
}
}
// If we receive announcement for the same channel (with UTXO lookups disabled),
// drop new one on the floor, since we can't see any changes.
match net_graph_msg_handler.handle_channel_announcement(&valid_announcement) {
@ -1043,9 +1044,10 @@ mod tests {
Err(e) => assert_eq!(e.err, "Already have knowledge of channel")
};
// Test if an associated transaction were not on-chain (or not confirmed).
*chain_monitor.utxo_ret.lock().unwrap() = Err(chaininterface::ChainError::UnknownTx);
let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Testnet));
*chain_source.utxo_ret.lock().unwrap() = Err(chain::AccessError::UnknownTx);
net_graph_msg_handler = NetGraphMsgHandler::new(Some(chain_source.clone()), Arc::clone(&logger));
unsigned_announcement.short_channel_id += 1;
msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
@ -1062,10 +1064,9 @@ mod tests {
Err(e) => assert_eq!(e.err, "Channel announced without corresponding UTXO entry")
};
// Now test if the transaction is found in the UTXO set and the script is correct.
unsigned_announcement.short_channel_id += 1;
*chain_monitor.utxo_ret.lock().unwrap() = Ok((good_script.clone(), 0));
*chain_source.utxo_ret.lock().unwrap() = Ok(TxOut { value: 0, script_pubkey: good_script.clone() });
msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
let valid_announcement = ChannelAnnouncement {
@ -1090,14 +1091,14 @@ mod tests {
// If we receive announcement for the same channel (but TX is not confirmed),
// drop new one on the floor, since we can't see any changes.
*chain_monitor.utxo_ret.lock().unwrap() = Err(chaininterface::ChainError::UnknownTx);
*chain_source.utxo_ret.lock().unwrap() = Err(chain::AccessError::UnknownTx);
match net_graph_msg_handler.handle_channel_announcement(&valid_announcement) {
Ok(_) => panic!(),
Err(e) => assert_eq!(e.err, "Channel announced without corresponding UTXO entry")
};
// But if it is confirmed, replace the channel
*chain_monitor.utxo_ret.lock().unwrap() = Ok((good_script, 0));
*chain_source.utxo_ret.lock().unwrap() = Ok(TxOut { value: 0, script_pubkey: good_script });
unsigned_announcement.features = ChannelFeatures::empty();
msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
let valid_announcement = ChannelAnnouncement {
@ -1169,8 +1170,8 @@ mod tests {
fn handling_channel_update() {
let secp_ctx = Secp256k1::new();
let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::new());
let chain_monitor = Arc::new(test_utils::TestChainWatcher::new());
let net_graph_msg_handler = NetGraphMsgHandler::new(chain_monitor.clone(), Arc::clone(&logger));
let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Testnet));
let net_graph_msg_handler = NetGraphMsgHandler::new(Some(chain_source.clone()), Arc::clone(&logger));
let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
@ -1191,7 +1192,7 @@ mod tests {
.push_slice(&PublicKey::from_secret_key(&secp_ctx, node_2_btckey).serialize())
.push_opcode(opcodes::all::OP_PUSHNUM_2)
.push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh();
*chain_monitor.utxo_ret.lock().unwrap() = Ok((good_script.clone(), amount_sats));
*chain_source.utxo_ret.lock().unwrap() = Ok(TxOut { value: amount_sats, script_pubkey: good_script.clone() });
let unsigned_announcement = UnsignedChannelAnnouncement {
features: ChannelFeatures::empty(),
chain_hash,

View file

@ -410,7 +410,6 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
#[cfg(test)]
mod tests {
use chain::chaininterface;
use routing::router::{get_route, RouteHint, RoutingFees};
use routing::network_graph::NetGraphMsgHandler;
use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
@ -433,7 +432,7 @@ mod tests {
use std::sync::Arc;
// Using the same keys for LN and BTC ids
fn add_channel(net_graph_msg_handler: &NetGraphMsgHandler<Arc<chaininterface::ChainWatchInterfaceUtil>, Arc<test_utils::TestLogger>>, secp_ctx: &Secp256k1<All>, node_1_privkey: &SecretKey,
fn add_channel(net_graph_msg_handler: &NetGraphMsgHandler<Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>, secp_ctx: &Secp256k1<All>, node_1_privkey: &SecretKey,
node_2_privkey: &SecretKey, features: ChannelFeatures, short_channel_id: u64) {
let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_privkey);
let node_id_2 = PublicKey::from_secret_key(&secp_ctx, node_2_privkey);
@ -463,7 +462,7 @@ mod tests {
};
}
fn update_channel(net_graph_msg_handler: &NetGraphMsgHandler<Arc<chaininterface::ChainWatchInterfaceUtil>, Arc<test_utils::TestLogger>>, secp_ctx: &Secp256k1<All>, node_privkey: &SecretKey, update: UnsignedChannelUpdate) {
fn update_channel(net_graph_msg_handler: &NetGraphMsgHandler<Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>, secp_ctx: &Secp256k1<All>, node_privkey: &SecretKey, update: UnsignedChannelUpdate) {
let msghash = hash_to_message!(&Sha256dHash::hash(&update.encode()[..])[..]);
let valid_channel_update = ChannelUpdate {
signature: secp_ctx.sign(&msghash, node_privkey),
@ -478,7 +477,7 @@ mod tests {
}
fn add_or_update_node(net_graph_msg_handler: &NetGraphMsgHandler<Arc<chaininterface::ChainWatchInterfaceUtil>, Arc<test_utils::TestLogger>>, secp_ctx: &Secp256k1<All>, node_privkey: &SecretKey,
fn add_or_update_node(net_graph_msg_handler: &NetGraphMsgHandler<Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>, secp_ctx: &Secp256k1<All>, node_privkey: &SecretKey,
features: NodeFeatures, timestamp: u32) {
let node_id = PublicKey::from_secret_key(&secp_ctx, node_privkey);
let unsigned_announcement = UnsignedNodeAnnouncement {
@ -531,11 +530,10 @@ mod tests {
}
}
fn build_graph() -> (Secp256k1<All>, NetGraphMsgHandler<std::sync::Arc<crate::chain::chaininterface::ChainWatchInterfaceUtil>, std::sync::Arc<crate::util::test_utils::TestLogger>>, std::sync::Arc<test_utils::TestLogger>) {
fn build_graph() -> (Secp256k1<All>, NetGraphMsgHandler<std::sync::Arc<crate::util::test_utils::TestChainSource>, std::sync::Arc<crate::util::test_utils::TestLogger>>, std::sync::Arc<test_utils::TestLogger>) {
let secp_ctx = Secp256k1::new();
let logger = Arc::new(test_utils::TestLogger::new());
let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet));
let net_graph_msg_handler = NetGraphMsgHandler::new(chain_monitor, Arc::clone(&logger));
let net_graph_msg_handler = NetGraphMsgHandler::new(None, Arc::clone(&logger));
// Build network from our_id to node7:
//
// -1(1)2- node0 -1(3)2-

View file

@ -42,7 +42,7 @@ pub enum APIError {
/// A human-readable error message
err: String
},
/// An attempt to call add/update_monitor returned an Err (ie you did this!), causing the
/// An attempt to call watch/update_channel returned an Err (ie you did this!), causing the
/// attempted action to fail.
MonitorUpdateFailed,
}

View file

@ -72,7 +72,7 @@ impl<'a, T> std::fmt::Display for DebugFundingInfo<'a, T> {
}
macro_rules! log_funding_info {
($key_storage: expr) => {
::util::macro_logger::DebugFundingInfo(&$key_storage.funding_info)
::util::macro_logger::DebugFundingInfo($key_storage.get_funding_txo())
}
}

View file

@ -7,27 +7,28 @@
// You may not use this file except in accordance with one or both of these
// licenses.
use chain;
use chain::chaininterface;
use chain::chaininterface::{ConfirmationTarget, ChainError, ChainWatchInterface};
use chain::chaininterface::ConfirmationTarget;
use chain::chainmonitor;
use chain::channelmonitor;
use chain::channelmonitor::MonitorEvent;
use chain::transaction::OutPoint;
use chain::keysinterface;
use ln::channelmonitor;
use ln::features::{ChannelFeatures, InitFeatures};
use ln::msgs;
use ln::msgs::OptionalField;
use ln::channelmonitor::MonitorEvent;
use util::enforcing_trait_impls::EnforcingChannelKeys;
use util::events;
use util::logger::{Logger, Level, Record};
use util::ser::{Readable, Writer, Writeable};
use bitcoin::blockdata::constants::genesis_block;
use bitcoin::blockdata::transaction::Transaction;
use bitcoin::blockdata::transaction::{Transaction, TxOut};
use bitcoin::blockdata::script::{Builder, Script};
use bitcoin::blockdata::block::Block;
use bitcoin::blockdata::opcodes;
use bitcoin::network::constants::Network;
use bitcoin::hash_types::{Txid, BlockHash};
use bitcoin::hash_types::{BlockHash, Txid};
use bitcoin::secp256k1::{SecretKey, PublicKey, Secp256k1, Signature};
@ -37,7 +38,7 @@ use std::time::Duration;
use std::sync::Mutex;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::{cmp, mem};
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
pub struct TestVecWriter(pub Vec<u8>);
impl Writer for TestVecWriter {
@ -59,30 +60,30 @@ impl chaininterface::FeeEstimator for TestFeeEstimator {
}
}
pub struct TestChannelMonitor<'a> {
pub struct TestChainMonitor<'a> {
pub added_monitors: Mutex<Vec<(OutPoint, channelmonitor::ChannelMonitor<EnforcingChannelKeys>)>>,
pub latest_monitor_update_id: Mutex<HashMap<[u8; 32], (OutPoint, u64)>>,
pub simple_monitor: channelmonitor::SimpleManyChannelMonitor<OutPoint, EnforcingChannelKeys, &'a chaininterface::BroadcasterInterface, &'a TestFeeEstimator, &'a TestLogger, &'a ChainWatchInterface>,
pub chain_monitor: chainmonitor::ChainMonitor<EnforcingChannelKeys, &'a TestChainSource, &'a chaininterface::BroadcasterInterface, &'a TestFeeEstimator, &'a TestLogger>,
pub update_ret: Mutex<Result<(), channelmonitor::ChannelMonitorUpdateErr>>,
// If this is set to Some(), after the next return, we'll always return this until update_ret
// is changed:
pub next_update_ret: Mutex<Option<Result<(), channelmonitor::ChannelMonitorUpdateErr>>>,
}
impl<'a> TestChannelMonitor<'a> {
pub fn new(chain_monitor: &'a chaininterface::ChainWatchInterface, broadcaster: &'a chaininterface::BroadcasterInterface, logger: &'a TestLogger, fee_estimator: &'a TestFeeEstimator) -> Self {
impl<'a> TestChainMonitor<'a> {
pub fn new(chain_source: Option<&'a TestChainSource>, broadcaster: &'a chaininterface::BroadcasterInterface, logger: &'a TestLogger, fee_estimator: &'a TestFeeEstimator) -> Self {
Self {
added_monitors: Mutex::new(Vec::new()),
latest_monitor_update_id: Mutex::new(HashMap::new()),
simple_monitor: channelmonitor::SimpleManyChannelMonitor::new(chain_monitor, broadcaster, logger, fee_estimator),
chain_monitor: chainmonitor::ChainMonitor::new(chain_source, broadcaster, logger, fee_estimator),
update_ret: Mutex::new(Ok(())),
next_update_ret: Mutex::new(None),
}
}
}
impl<'a> channelmonitor::ManyChannelMonitor for TestChannelMonitor<'a> {
impl<'a> chain::Watch for TestChainMonitor<'a> {
type Keys = EnforcingChannelKeys;
fn add_monitor(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor<EnforcingChannelKeys>) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor<EnforcingChannelKeys>) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
// At every point where we get a monitor update, we should be able to send a useful monitor
// to a watchtower and disk...
let mut w = TestVecWriter(Vec::new());
@ -92,7 +93,7 @@ impl<'a> channelmonitor::ManyChannelMonitor for TestChannelMonitor<'a> {
assert!(new_monitor == monitor);
self.latest_monitor_update_id.lock().unwrap().insert(funding_txo.to_channel_id(), (funding_txo, monitor.get_latest_update_id()));
self.added_monitors.lock().unwrap().push((funding_txo, monitor));
assert!(self.simple_monitor.add_monitor(funding_txo, new_monitor).is_ok());
assert!(self.chain_monitor.watch_channel(funding_txo, new_monitor).is_ok());
let ret = self.update_ret.lock().unwrap().clone();
if let Some(next_ret) = self.next_update_ret.lock().unwrap().take() {
@ -101,7 +102,7 @@ impl<'a> channelmonitor::ManyChannelMonitor for TestChannelMonitor<'a> {
ret
}
fn update_monitor(&self, funding_txo: OutPoint, update: channelmonitor::ChannelMonitorUpdate) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
fn update_channel(&self, funding_txo: OutPoint, update: channelmonitor::ChannelMonitorUpdate) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
// Every monitor update should survive roundtrip
let mut w = TestVecWriter(Vec::new());
update.write(&mut w).unwrap();
@ -109,10 +110,10 @@ impl<'a> channelmonitor::ManyChannelMonitor for TestChannelMonitor<'a> {
&mut ::std::io::Cursor::new(&w.0)).unwrap() == update);
self.latest_monitor_update_id.lock().unwrap().insert(funding_txo.to_channel_id(), (funding_txo, update.update_id));
assert!(self.simple_monitor.update_monitor(funding_txo, update).is_ok());
assert!(self.chain_monitor.update_channel(funding_txo, update).is_ok());
// At every point where we get a monitor update, we should be able to send a useful monitor
// to a watchtower and disk...
let monitors = self.simple_monitor.monitors.lock().unwrap();
let monitors = self.chain_monitor.monitors.lock().unwrap();
let monitor = monitors.get(&funding_txo).unwrap();
w.0.clear();
monitor.write_for_disk(&mut w).unwrap();
@ -128,8 +129,8 @@ impl<'a> channelmonitor::ManyChannelMonitor for TestChannelMonitor<'a> {
ret
}
fn get_and_clear_pending_monitor_events(&self) -> Vec<MonitorEvent> {
return self.simple_monitor.get_and_clear_pending_monitor_events();
fn release_pending_monitor_events(&self) -> Vec<MonitorEvent> {
return self.chain_monitor.release_pending_monitor_events();
}
}
@ -393,27 +394,41 @@ impl TestKeysInterface {
}
}
pub struct TestChainWatcher {
pub utxo_ret: Mutex<Result<(Script, u64), ChainError>>,
pub struct TestChainSource {
pub genesis_hash: BlockHash,
pub utxo_ret: Mutex<Result<TxOut, chain::AccessError>>,
pub watched_txn: Mutex<HashSet<(Txid, Script)>>,
pub watched_outputs: Mutex<HashSet<(OutPoint, Script)>>,
}
impl TestChainWatcher {
pub fn new() -> Self {
let script = Builder::new().push_opcode(opcodes::OP_TRUE).into_script();
Self { utxo_ret: Mutex::new(Ok((script, u64::max_value()))) }
impl TestChainSource {
pub fn new(network: Network) -> Self {
let script_pubkey = Builder::new().push_opcode(opcodes::OP_TRUE).into_script();
Self {
genesis_hash: genesis_block(network).block_hash(),
utxo_ret: Mutex::new(Ok(TxOut { value: u64::max_value(), script_pubkey })),
watched_txn: Mutex::new(HashSet::new()),
watched_outputs: Mutex::new(HashSet::new()),
}
}
}
impl ChainWatchInterface for TestChainWatcher {
fn install_watch_tx(&self, _txid: &Txid, _script_pub_key: &Script) { }
fn install_watch_outpoint(&self, _outpoint: (Txid, u32), _out_script: &Script) { }
fn watch_all_txn(&self) { }
fn filter_block<'a>(&self, _block: &'a Block) -> Vec<usize> {
Vec::new()
}
fn reentered(&self) -> usize { 0 }
impl chain::Access for TestChainSource {
fn get_utxo(&self, genesis_hash: &BlockHash, _short_channel_id: u64) -> Result<TxOut, chain::AccessError> {
if self.genesis_hash != *genesis_hash {
return Err(chain::AccessError::UnknownChain);
}
fn get_chain_utxo(&self, _genesis_hash: BlockHash, _unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError> {
self.utxo_ret.lock().unwrap().clone()
}
}
impl chain::Filter for TestChainSource {
fn register_tx(&self, txid: &Txid, script_pubkey: &Script) {
self.watched_txn.lock().unwrap().insert((*txid, script_pubkey.clone()));
}
fn register_output(&self, outpoint: &OutPoint, script_pubkey: &Script) {
self.watched_outputs.lock().unwrap().insert((*outpoint, script_pubkey.clone()));
}
}