Skip to content

Refactor chain monitoring #649

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a7b2eb6
Remove ChainWatchInterface from BlockNotifier
jkczyz Jun 16, 2020
f69d9d7
Align ChannelMonitor interface with ChainListener
jkczyz Jun 26, 2020
82b608d
Simplify BlockNotifier tests
jkczyz Jun 16, 2020
5381c23
Replace BlockNotifier with Node in test utilities
jkczyz Jul 14, 2020
1ab0a1a
Add test utilities for {dis}connecting a block
jkczyz Jul 14, 2020
bd39b20
Replace use of ChainWatchInterface with WatchEvent
jkczyz Jul 9, 2020
87398be
Remove ChainWatchInterface from channelmonitor.rs
jkczyz Jul 16, 2020
3ee6a27
Replace ChainWatchInterface in NetGraphMsgHandler
jkczyz Jul 18, 2020
bc4f463
Remove ChainWatchInterface
jkczyz Jul 18, 2020
801b775
Replace ManyChannelMonitor with chain::Watch
jkczyz Jul 21, 2020
6662e95
Rename SimpleManyChannelMonitor to ChainMonitor
jkczyz Jul 21, 2020
851283d
Remove Key parameter from ChainMonitor
jkczyz Aug 6, 2020
367834c
Remove BlockNotifier
jkczyz Jul 29, 2020
1599a13
Remove ChainListener
jkczyz Jul 29, 2020
98bc46b
Replace WatchEventProvider with chain::Filter
jkczyz Jul 30, 2020
e83dcda
Fix architecture diagram line length
jkczyz Aug 3, 2020
95b7eee
Fix architecture diagram arrow directions
jkczyz Aug 3, 2020
9e14256
Include funding TXO in outputs to watch
jkczyz Aug 29, 2020
71230c9
Replace WatchEvent usage with get_outputs_to_watch
jkczyz Aug 7, 2020
8b1e5af
Define type alias for enumerated transaction data
jkczyz Sep 9, 2020
e09767b
Merge ChainMonitor impl blocks
jkczyz Sep 10, 2020
819a865
Move channelmonitor.rs from ln to chain module
jkczyz Aug 7, 2020
51a5a1a
Move ln/channelmonitor.rs to chain/chainmonitor.rs
jkczyz Oct 1, 2020
6cd6816
Merge branch '2020-06-refactor-chain-listener-move-chainmonitor' into…
jkczyz Oct 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 23 additions & 23 deletions ARCH.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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 |
---------------------- --------- -----------------
```
56 changes: 25 additions & 31 deletions fuzz/src/chanmon_consistency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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
Expand All @@ -93,32 +94,32 @@ 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()),
should_update_manager: atomic::AtomicBool::new(false),
}
}
}
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,
Expand All @@ -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();
}
}

Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand All @@ -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() {
Expand All @@ -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)
} }
}

Expand Down Expand Up @@ -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);
}
} }
}
Expand Down
2 changes: 1 addition & 1 deletion fuzz/src/chanmon_deser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading