// This file is auto-generated by gen_target.sh based on msg_target_template.txt
// To modify it, modify msg_target_template.txt and run gen_target.sh instead.
+extern crate bitcoin;
extern crate lightning;
+use bitcoin::util::hash::Sha256dHash;
+
use lightning::ln::channelmonitor;
use lightning::util::reset_rng_state;
use lightning::util::ser::{ReadableArgs, Writer};
pub fn do_test(data: &[u8]) {
reset_rng_state();
let logger = Arc::new(test_logger::TestLogger{});
- if let Ok(monitor) = channelmonitor::ChannelMonitor::read(&mut Cursor::new(data), logger.clone()) {
+ if let Ok((latest_block_hash, monitor)) = <(Sha256dHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(data), logger.clone()) {
let mut w = VecWriter(Vec::new());
monitor.write_for_disk(&mut w).unwrap();
- assert!(channelmonitor::ChannelMonitor::read(&mut Cursor::new(&w.0), logger.clone()).unwrap() == monitor);
+ let deserialized_copy = <(Sha256dHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(&w.0), logger.clone()).unwrap();
+ assert!(latest_block_hash == deserialized_copy.0);
+ assert!(monitor == deserialized_copy.1);
w.0.clear();
monitor.write_for_watchtower(&mut w).unwrap();
}
use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
use bitcoin::blockdata::script::Script;
use bitcoin::network::serialize;
+use bitcoin::network::serialize::BitcoinHash;
use bitcoin::network::encodable::{ConsensusDecodable, ConsensusEncodable};
use bitcoin::util::hash::Sha256dHash;
use bitcoin::util::bip143;
}
impl<Key : Send + cmp::Eq + hash::Hash> ChainListener for SimpleManyChannelMonitor<Key> {
- fn block_connected(&self, _header: &BlockHeader, height: u32, txn_matched: &[&Transaction], _indexes_of_txn_matched: &[u32]) {
+ fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], _indexes_of_txn_matched: &[u32]) {
+ let block_hash = header.bitcoin_hash();
let mut new_events: Vec<events::Event> = Vec::with_capacity(0);
{
- let monitors = self.monitors.lock().unwrap();
- for monitor in monitors.values() {
- let (txn_outputs, spendable_outputs) = monitor.block_connected(txn_matched, height, &*self.broadcaster);
+ let mut monitors = self.monitors.lock().unwrap();
+ for monitor in monitors.values_mut() {
+ let (txn_outputs, spendable_outputs) = monitor.block_connected(txn_matched, height, &block_hash, &*self.broadcaster);
if spendable_outputs.len() > 0 {
new_events.push(events::Event::SpendableOutputs {
outputs: spendable_outputs,
destination_script: Script,
+ // We simply modify last_block_hash in Channel's block_connected so that serialization is
+ // consistent but hopefully the users' copy handles block_connected in a consistent way.
+ // (we do *not*, however, update them in insert_combine to ensure any local user copies keep
+ // their last_block_hash from its state and not based on updated copies that didn't run through
+ // the full block_connected).
+ pub(crate) last_block_hash: Sha256dHash,
secp_ctx: Secp256k1<secp256k1::All>, //TODO: dedup this a bit...
logger: Arc<Logger>,
}
payment_preimages: self.payment_preimages.clone(),
destination_script: self.destination_script.clone(),
+ last_block_hash: self.last_block_hash.clone(),
secp_ctx: self.secp_ctx.clone(),
logger: self.logger.clone(),
}
payment_preimages: HashMap::new(),
destination_script: destination_script,
+ last_block_hash: Default::default(),
secp_ctx: Secp256k1::new(),
logger,
}
writer.write_all(payment_preimage)?;
}
+ self.last_block_hash.write(writer)?;
self.destination_script.write(writer)?;
Ok(())
}
/// Writes this monitor into the given writer, suitable for writing to disk.
+ ///
+ /// Note that the deserializer is only implemented for (Sha256dHash, ChannelMonitor), which
+ /// tells you the last block hash which was block_connect()ed. You MUST rescan any blocks along
+ /// the "reorg path" (ie not just starting at the same height but starting at the highest
+ /// common block that appears on your best chain as well as on the chain which contains the
+ /// last block hash returned) upon deserializing the object!
pub fn write_for_disk<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
self.write(writer, true)
}
/// Encodes this monitor into the given writer, suitable for sending to a remote watchtower
+ ///
+ /// Note that the deserializer is only implemented for (Sha256dHash, ChannelMonitor), which
+ /// tells you the last block hash which was block_connect()ed. You MUST rescan any blocks along
+ /// the "reorg path" (ie not just starting at the same height but starting at the highest
+ /// common block that appears on your best chain as well as on the chain which contains the
+ /// last block hash returned) upon deserializing the object!
pub fn write_for_watchtower<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
self.write(writer, false)
}
(Vec::new(), Vec::new())
}
- fn block_connected(&self, txn_matched: &[&Transaction], height: u32, broadcaster: &BroadcasterInterface)-> (Vec<(Sha256dHash, Vec<TxOut>)>, Vec<SpendableOutputDescriptor>) {
+ fn block_connected(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &Sha256dHash, broadcaster: &BroadcasterInterface)-> (Vec<(Sha256dHash, Vec<TxOut>)>, Vec<SpendableOutputDescriptor>) {
let mut watch_outputs = Vec::new();
let mut spendable_outputs = Vec::new();
for tx in txn_matched {
}
}
}
+ self.last_block_hash = block_hash.clone();
(watch_outputs, spendable_outputs)
}
const MAX_ALLOC_SIZE: usize = 64*1024;
-impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for ChannelMonitor {
+impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelMonitor) {
fn read(reader: &mut R, logger: Arc<Logger>) -> Result<Self, DecodeError> {
let secp_ctx = Secp256k1::new();
macro_rules! unwrap_obj {
}
}
+ let last_block_hash: Sha256dHash = Readable::read(reader)?;
let destination_script = Readable::read(reader)?;
- Ok(ChannelMonitor {
+ Ok((last_block_hash.clone(), ChannelMonitor {
funding_txo,
commitment_transaction_number_obscure_factor,
payment_preimages,
destination_script,
+ last_block_hash,
secp_ctx,
logger,
- })
+ }))
}
}