//! channel being force-closed.
use bitcoin::BitcoinHash;
-use bitcoin::blockdata::block::{Block, BlockHeader};
+use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::transaction::{Transaction, TxOut};
use bitcoin::blockdata::script::{Builder, Script};
use bitcoin::blockdata::opcodes;
macro_rules! confirm_txn {
($node: expr) => { {
- let mut block = Block {
- header: BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
- txdata: channel_txn.clone(),
- };
- $node.block_connected(&block, 1);
+ let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ 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 {
- block = Block {
- header: BlockHeader { version: 0x20000000, prev_blockhash: block.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
- txdata: vec![],
- };
- $node.block_connected(&block, i);
+ header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ $node.block_connected(&header, &[], i);
}
} }
}
//! or payments to send/ways to handle events generated.
//! This test has been very useful, though due to its complexity good starting inputs are critical.
-use bitcoin::blockdata::block::{Block, BlockHeader};
+use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::transaction::{Transaction, TxOut};
use bitcoin::blockdata::script::{Builder, Script};
use bitcoin::blockdata::opcodes;
}
fn connect_block(&mut self, all_txn: &[Transaction]) {
- for tx in all_txn.iter() {
+ 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);
+ txdata.push((idx + 1, tx));
},
_ => {},
}
}
- let block = Block {
- header: BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: self.blocks_connected, bits: 42, nonce: 42 },
- txdata: all_txn.to_vec(),
- };
+ 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(&block, self.height as u32);
- (*self.monitor).block_connected(&block, self.height as u32);
+ 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] = block.bitcoin_hash();
+ self.header_hashes[self.height] = header.bitcoin_hash();
} else {
assert_eq!(self.header_hashes.len(), self.height);
- self.header_hashes.push(block.bitcoin_hash());
+ self.header_hashes.push(header.bitcoin_hash());
}
self.max_height = cmp::max(self.height, self.max_height);
}
use bitcoin::blockdata::script::{Script, Builder};
-use bitcoin::blockdata::block::Block;
+use bitcoin::blockdata::block::BlockHeader;
+use bitcoin::blockdata::transaction::Transaction;
use bitcoin::hash_types::{Txid, BlockHash};
use lightning::chain::chaininterface::{ChainError,ChainWatchInterface};
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> {
+ fn filter_block(&self, _header: &BlockHeader, _txdata: &[(usize, &Transaction)]) -> Vec<usize> {
Vec::new()
}
fn reentered(&self) -> usize { 0 }
/// Gets the list of transaction indices within a given block that the ChainWatchInterface is
/// watching for.
- fn filter_block(&self, block: &Block) -> Vec<usize>;
+ fn filter_block(&self, header: &BlockHeader, txdata: &[(usize, &Transaction)]) -> 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
/// 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.
- fn block_connected(&self, block: &Block, height: u32);
+ /// Notifies a listener that a block was connected. Transactions may be filtered and are given
+ /// paired with their position within the block.
+ fn block_connected(&self, header: &BlockHeader, txdata: &[(usize, &Transaction)], height: u32);
+
/// 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)
}
/// Notify listeners that a block was connected.
- pub fn block_connected<'b>(&self, block: &'b Block, height: u32) {
+ pub fn block_connected(&self, block: &Block, height: u32) {
+ let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
let listeners = self.listeners.lock().unwrap();
for listener in listeners.iter() {
- listener.block_connected(block, height);
+ listener.block_connected(&block.header, &txdata, height);
}
}
Err(ChainError::NotSupported)
}
- fn filter_block(&self, block: &Block) -> Vec<usize> {
+ fn filter_block(&self, _header: &BlockHeader, txdata: &[(usize, &Transaction)]) -> Vec<usize> {
let mut matched_index = Vec::new();
{
let watched = self.watched.lock().unwrap();
- for (index, transaction) in block.txdata.iter().enumerate() {
- if self.does_match_tx_unguarded(transaction, &watched) {
- matched_index.push(index);
+ for (i, transaction) in txdata.iter().enumerate() {
+ if self.does_match_tx_unguarded(transaction.1, &watched) {
+ matched_index.push(i);
}
}
}
-use bitcoin::blockdata::block::{Block, BlockHeader};
+use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::script::{Script,Builder};
use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType};
use bitcoin::blockdata::opcodes;
///
/// May return some HTLCs (and their payment_hash) which have timed out and should be failed
/// back.
- pub fn block_connected(&mut self, block: &Block, height: u32) -> Result<(Option<msgs::FundingLocked>, Vec<(HTLCSource, PaymentHash)>), msgs::ErrorMessage> {
+ pub fn block_connected(&mut self, header: &BlockHeader, txdata: &[(usize, &Transaction)], 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 {
}
});
let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS);
- if block.bitcoin_hash() != self.last_block_connected {
+ if header.bitcoin_hash() != self.last_block_connected {
if self.funding_tx_confirmations > 0 {
self.funding_tx_confirmations += 1;
}
}
if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 {
- for (index_in_block, ref tx) in block.txdata.iter().enumerate() {
+ 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() ||
}
}
}
- if block.bitcoin_hash() != self.last_block_connected {
- self.last_block_connected = block.bitcoin_hash();
- self.update_time_counter = cmp::max(self.update_time_counter, block.header.time);
+ if header.bitcoin_hash() != self.last_block_connected {
+ self.last_block_connected = header.bitcoin_hash();
+ self.update_time_counter = cmp::max(self.update_time_counter, header.time);
if let Some(channel_monitor) = self.channel_monitor.as_mut() {
channel_monitor.last_block_hash = self.last_block_connected;
}
// funding_tx_confirmed_in and return.
false
};
- self.funding_tx_confirmed_in = Some(block.bitcoin_hash());
+ self.funding_tx_confirmed_in = Some(header.bitcoin_hash());
//TODO: Note that this must be a duplicate of the previous commitment point they sent us,
//as otherwise we will have a commitment transaction that they can't revoke (well, kinda,
//! on-chain transactions (it only monitors the chain to watch for any force-closes that might
//! imply it needs to fail HTLCs/payments/channels it manages).
-use bitcoin::blockdata::block::{Block, BlockHeader};
+use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::constants::genesis_block;
+use bitcoin::blockdata::transaction::Transaction;
use bitcoin::network::constants::Network;
use bitcoin::util::hash::BitcoinHash;
F::Target: FeeEstimator,
L::Target: Logger,
{
- fn block_connected(&self, block: &Block, height: u32) {
- let header_hash = block.bitcoin_hash();
+ fn block_connected(&self, header: &BlockHeader, txdata: &[(usize, &Transaction)], height: u32) {
+ let header_hash = header.bitcoin_hash();
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 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(block, height);
+ 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
return false;
}
if let Some(funding_txo) = channel.get_funding_txo() {
- for tx in block.txdata.iter() {
+ 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()));
// Just in case we end up in a race, we loop until we either successfully update
// last_node_announcement_serial or decide we don't need to.
let old_serial = self.last_node_announcement_serial.load(Ordering::Acquire);
- if old_serial >= block.header.time as usize { break; }
- if self.last_node_announcement_serial.compare_exchange(old_serial, block.header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() {
+ if old_serial >= header.time as usize { break; }
+ if self.last_node_announcement_serial.compare_exchange(old_serial, header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() {
break;
}
}
//! security-domain-separated system design, you should consider having multiple paths for
//! ChannelMonitors to get out of the HSM and onto monitoring devices.
-use bitcoin::blockdata::block::{Block, BlockHeader};
+use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::transaction::{TxOut,Transaction};
use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
use bitcoin::blockdata::script::{Script, Builder};
L::Target: Logger,
C::Target: ChainWatchInterface,
{
- fn block_connected(&self, block: &Block, height: u32) {
+ fn block_connected(&self, header: &BlockHeader, txdata: &[(usize, &Transaction)], height: u32) {
let mut reentered = true;
while reentered {
- let matched_indexes = self.chain_monitor.filter_block(block);
- let matched_txn: Vec<&Transaction> = matched_indexes.iter().map(|index| &block.txdata[*index]).collect();
+ let matched_indexes = self.chain_monitor.filter_block(header, txdata);
+ let matched_txn: Vec<_> = matched_indexes.iter().map(|index| txdata[*index].1).collect();
let last_seen = self.chain_monitor.reentered();
- let block_hash = block.bitcoin_hash();
+ let block_hash = header.bitcoin_hash();
{
let mut monitors = self.monitors.lock().unwrap();
for monitor in monitors.values_mut() {
output: vec![outp]
};
- let block = Block {
- header: BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
- txdata: vec![dummy_tx],
- };
- nodes[0].chan_monitor.simple_monitor.block_connected(&block, 1);
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ nodes[0].chan_monitor.simple_monitor.block_connected(&header, &[(0, &dummy_tx)], 1);
assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
assert_eq!(nodes[0].node.get_and_clear_pending_msg_events().len(), 0);
// We broadcast a few more block to check everything is all right
- connect_blocks(&nodes[0].block_notifier, 20, 1, true, block.bitcoin_hash());
+ connect_blocks(&nodes[0].block_notifier, 20, 1, true, header.bitcoin_hash());
assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
assert_eq!(nodes[0].node.get_and_clear_pending_msg_events().len(), 0);
assert!(watchtower.add_monitor(outpoint, new_monitor).is_ok());
watchtower
};
- let block = Block {
- header: BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
- txdata: vec![],
- };
- watchtower.simple_monitor.block_connected(&block, 200);
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ watchtower.simple_monitor.block_connected(&header, &[], 200);
// Try to update ChannelMonitor
assert!(nodes[1].node.claim_funds(preimage, &None, 9_000_000));
use bitcoin::blockdata::constants::genesis_block;
use bitcoin::blockdata::transaction::Transaction;
use bitcoin::blockdata::script::{Builder, Script};
-use bitcoin::blockdata::block::Block;
+use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::opcodes;
use bitcoin::network::constants::Network;
use bitcoin::hash_types::{Txid, BlockHash};
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> {
+ fn filter_block(&self, _header: &BlockHeader, _txdata: &[(usize, &Transaction)]) -> Vec<usize> {
Vec::new()
}
fn reentered(&self) -> usize { 0 }