Skip to content

Commit feeb893

Browse files
authored
Merge pull request #858 from jkczyz/2021-03-electrum-interface
Electrum interface for ChannelMonitor
2 parents 9397db6 + 524c532 commit feeb893

File tree

10 files changed

+738
-349
lines changed

10 files changed

+738
-349
lines changed

background-processor/src/lib.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ mod tests {
131131
use lightning::chain::keysinterface::{Sign, InMemorySigner, KeysInterface, KeysManager};
132132
use lightning::chain::transaction::OutPoint;
133133
use lightning::get_event_msg;
134-
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, SimpleArcChannelManager};
134+
use lightning::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, SimpleArcChannelManager};
135135
use lightning::ln::features::InitFeatures;
136136
use lightning::ln::msgs::ChannelMessageHandler;
137137
use lightning::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor};
@@ -192,14 +192,12 @@ mod tests {
192192
let persister = Arc::new(FilesystemPersister::new(format!("{}_persister_{}", persist_dir, i)));
193193
let seed = [i as u8; 32];
194194
let network = Network::Testnet;
195-
let genesis_block = genesis_block(network);
196-
let now = Duration::from_secs(genesis_block.header.time as u64);
195+
let now = Duration::from_secs(genesis_block(network).header.time as u64);
197196
let keys_manager = Arc::new(KeysManager::new(&seed, now.as_secs(), now.subsec_nanos()));
198197
let chain_monitor = Arc::new(chainmonitor::ChainMonitor::new(Some(chain_source.clone()), tx_broadcaster.clone(), logger.clone(), fee_estimator.clone(), persister.clone()));
199198
let params = ChainParameters {
200199
network,
201-
latest_hash: genesis_block.block_hash(),
202-
latest_height: 0,
200+
best_block: BestBlock::from_genesis(network),
203201
};
204202
let manager = Arc::new(ChannelManager::new(fee_estimator.clone(), chain_monitor.clone(), tx_broadcaster, logger.clone(), keys_manager.clone(), UserConfig::default(), params));
205203
let msg_handler = MessageHandler { chan_handler: Arc::new(test_utils::TestChannelMessageHandler::new()), route_handler: Arc::new(test_utils::TestRoutingMessageHandler::new() )};

fuzz/src/chanmon_consistency.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use lightning::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr,
3636
use lightning::chain::transaction::OutPoint;
3737
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
3838
use lightning::chain::keysinterface::{KeysInterface, InMemorySigner};
39-
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, PaymentSendFailure, ChannelManagerReadArgs};
39+
use lightning::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, PaymentSendFailure, ChannelManagerReadArgs};
4040
use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
4141
use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, DecodeError, ErrorAction, UpdateAddHTLC, Init};
4242
use lightning::util::enforcing_trait_impls::{EnforcingSigner, INITIAL_REVOKED_COMMITMENT_NUMBER};
@@ -322,8 +322,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
322322
let network = Network::Bitcoin;
323323
let params = ChainParameters {
324324
network,
325-
latest_hash: genesis_block(network).block_hash(),
326-
latest_height: 0,
325+
best_block: BestBlock::from_genesis(network),
327326
};
328327
(ChannelManager::new(fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, params),
329328
monitor, keys_manager)

fuzz/src/full_stack.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget,
3232
use lightning::chain::chainmonitor;
3333
use lightning::chain::transaction::OutPoint;
3434
use lightning::chain::keysinterface::{InMemorySigner, KeysInterface};
35-
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret};
35+
use lightning::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret};
3636
use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor};
3737
use lightning::ln::msgs::DecodeError;
3838
use lightning::routing::router::get_route;
@@ -355,15 +355,13 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
355355
config.channel_options.announced_channel = get_slice!(1)[0] != 0;
356356
config.peer_channel_config_limits.min_dust_limit_satoshis = 0;
357357
let network = Network::Bitcoin;
358-
let genesis_hash = genesis_block(network).block_hash();
359358
let params = ChainParameters {
360359
network,
361-
latest_hash: genesis_hash,
362-
latest_height: 0,
360+
best_block: BestBlock::from_genesis(network),
363361
};
364362
let channelmanager = Arc::new(ChannelManager::new(fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, params));
365363
let our_id = PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret());
366-
let net_graph_msg_handler = Arc::new(NetGraphMsgHandler::new(genesis_hash, None, Arc::clone(&logger)));
364+
let net_graph_msg_handler = Arc::new(NetGraphMsgHandler::new(genesis_block(network).block_hash(), None, Arc::clone(&logger)));
367365

368366
let peers = RefCell::new([false; 256]);
369367
let mut loss_detector = MoneyLossDetector::new(&peers, channelmanager.clone(), monitor.clone(), PeerManager::new(MessageHandler {

lightning/src/chain/chainmonitor.rs

Lines changed: 91 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@
2424
//! servicing [`ChannelMonitor`] updates from the client.
2525
2626
use bitcoin::blockdata::block::{Block, BlockHeader};
27+
use bitcoin::hash_types::Txid;
2728

2829
use chain;
2930
use chain::{Filter, WatchedOutput};
3031
use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
3132
use chain::channelmonitor;
32-
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, MonitorEvent, Persist};
33+
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, MonitorEvent, Persist, TransactionOutputs};
3334
use chain::transaction::{OutPoint, TransactionData};
3435
use chain::keysinterface::Sign;
3536
use util::logger::Logger;
@@ -82,24 +83,77 @@ where C::Target: chain::Filter,
8283
/// descendants of such transactions. It is not necessary to re-fetch the block to obtain
8384
/// updated `txdata`.
8485
pub fn block_connected(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) {
86+
self.process_chain_data(header, txdata, |monitor, txdata| {
87+
monitor.block_connected(
88+
header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger)
89+
});
90+
}
91+
92+
/// Dispatches to per-channel monitors, which are responsible for updating their on-chain view
93+
/// of a channel and reacting accordingly to newly confirmed transactions. For details, see
94+
/// [`ChannelMonitor::transactions_confirmed`].
95+
///
96+
/// Used instead of [`block_connected`] by clients that are notified of transactions rather than
97+
/// blocks. May be called before or after [`update_best_block`] for transactions in the
98+
/// corresponding block. See [`update_best_block`] for further calling expectations.
99+
///
100+
/// [`block_connected`]: Self::block_connected
101+
/// [`update_best_block`]: Self::update_best_block
102+
pub fn transactions_confirmed(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) {
103+
self.process_chain_data(header, txdata, |monitor, txdata| {
104+
monitor.transactions_confirmed(
105+
header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger)
106+
});
107+
}
108+
109+
/// Dispatches to per-channel monitors, which are responsible for updating their on-chain view
110+
/// of a channel and reacting accordingly based on the new chain tip. For details, see
111+
/// [`ChannelMonitor::update_best_block`].
112+
///
113+
/// Used instead of [`block_connected`] by clients that are notified of transactions rather than
114+
/// blocks. May be called before or after [`transactions_confirmed`] for the corresponding
115+
/// block.
116+
///
117+
/// Must be called after new blocks become available for the most recent block. Intermediary
118+
/// blocks, however, may be safely skipped. In the event of a chain re-organization, this only
119+
/// needs to be called for the most recent block assuming `transaction_unconfirmed` is called
120+
/// for any affected transactions.
121+
///
122+
/// [`block_connected`]: Self::block_connected
123+
/// [`transactions_confirmed`]: Self::transactions_confirmed
124+
/// [`transaction_unconfirmed`]: Self::transaction_unconfirmed
125+
pub fn update_best_block(&self, header: &BlockHeader, height: u32) {
126+
self.process_chain_data(header, &[], |monitor, txdata| {
127+
// While in practice there shouldn't be any recursive calls when given empty txdata,
128+
// it's still possible if a chain::Filter implementation returns a transaction.
129+
debug_assert!(txdata.is_empty());
130+
monitor.update_best_block(
131+
header, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger)
132+
});
133+
}
134+
135+
fn process_chain_data<FN>(&self, header: &BlockHeader, txdata: &TransactionData, process: FN)
136+
where
137+
FN: Fn(&ChannelMonitor<ChannelSigner>, &TransactionData) -> Vec<TransactionOutputs>
138+
{
85139
let mut dependent_txdata = Vec::new();
86140
let monitors = self.monitors.read().unwrap();
87141
for monitor in monitors.values() {
88-
let mut txn_outputs = monitor.block_connected(header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
142+
let mut txn_outputs = process(monitor, txdata);
89143

90144
// Register any new outputs with the chain source for filtering, storing any dependent
91145
// transactions from within the block that previously had not been included in txdata.
92146
if let Some(ref chain_source) = self.chain_source {
93147
let block_hash = header.block_hash();
94-
for (txid, outputs) in txn_outputs.drain(..) {
95-
for (idx, output) in outputs.iter() {
148+
for (txid, mut outputs) in txn_outputs.drain(..) {
149+
for (idx, output) in outputs.drain(..) {
96150
// Register any new outputs with the chain source for filtering and recurse
97151
// if it indicates that there are dependent transactions within the block
98152
// that had not been previously included in txdata.
99153
let output = WatchedOutput {
100154
block_hash: Some(block_hash),
101-
outpoint: OutPoint { txid, index: *idx as u16 },
102-
script_pubkey: output.script_pubkey.clone(),
155+
outpoint: OutPoint { txid, index: idx as u16 },
156+
script_pubkey: output.script_pubkey,
103157
};
104158
if let Some(tx) = chain_source.register_output(output) {
105159
dependent_txdata.push(tx);
@@ -114,7 +168,7 @@ where C::Target: chain::Filter,
114168
dependent_txdata.sort_unstable_by_key(|(index, _tx)| *index);
115169
dependent_txdata.dedup_by_key(|(index, _tx)| *index);
116170
let txdata: Vec<_> = dependent_txdata.iter().map(|(index, tx)| (*index, tx)).collect();
117-
self.block_connected(header, &txdata, height);
171+
self.process_chain_data(header, &txdata, process);
118172
}
119173
}
120174

@@ -128,6 +182,36 @@ where C::Target: chain::Filter,
128182
}
129183
}
130184

185+
/// Dispatches to per-channel monitors, which are responsible for updating their on-chain view
186+
/// of a channel based on transactions unconfirmed as a result of a chain reorganization. See
187+
/// [`ChannelMonitor::transaction_unconfirmed`] for details.
188+
///
189+
/// Used instead of [`block_disconnected`] by clients that are notified of transactions rather
190+
/// than blocks. May be called before or after [`update_best_block`] for transactions in the
191+
/// corresponding block. See [`update_best_block`] for further calling expectations.
192+
///
193+
/// [`block_disconnected`]: Self::block_disconnected
194+
/// [`update_best_block`]: Self::update_best_block
195+
pub fn transaction_unconfirmed(&self, txid: &Txid) {
196+
let monitors = self.monitors.read().unwrap();
197+
for monitor in monitors.values() {
198+
monitor.transaction_unconfirmed(txid, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
199+
}
200+
}
201+
202+
/// Returns the set of txids that should be monitored for re-organization out of the chain.
203+
pub fn get_relevant_txids(&self) -> Vec<Txid> {
204+
let mut txids = Vec::new();
205+
let monitors = self.monitors.read().unwrap();
206+
for monitor in monitors.values() {
207+
txids.append(&mut monitor.get_relevant_txids());
208+
}
209+
210+
txids.sort_unstable();
211+
txids.dedup();
212+
txids
213+
}
214+
131215
/// Creates a new `ChainMonitor` used to watch on-chain activity pertaining to channels.
132216
///
133217
/// When an optional chain source implementing [`chain::Filter`] is provided, the chain monitor

0 commit comments

Comments
 (0)