mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-25 07:17:40 +01:00
Merge pull request #649 from jkczyz/2020-06-refactor-chain-listener
Refactor chain monitoring
This commit is contained in:
commit
8fb4a3ddc2
26 changed files with 1242 additions and 1425 deletions
46
ARCH.md
46
ARCH.md
|
@ -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 |
|
||||
---------------------- --------- -----------------
|
||||
```
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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] {
|
||||
|
|
|
@ -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!
|
||||
//! }
|
||||
//! }
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
|
227
lightning/src/chain/chainmonitor.rs
Normal file
227
lightning/src/chain/chainmonitor.rs
Normal 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
|
||||
}
|
||||
}
|
|
@ -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};
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, |_| {}, || {
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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-
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue