use lightning::chain;
+/// Returns a validated block header of the source's best chain tip.
+///
+/// Upon success, the returned header can be used to initialize [`SpvClient`]. Useful during a fresh
+/// start when there are no chain listeners to sync yet.
+pub async fn validate_best_block_header<B: BlockSource>(block_source: &mut B) ->
+BlockSourceResult<ValidatedBlockHeader> {
+ let (best_block_hash, best_block_height) = block_source.get_best_block().await?;
+ block_source
+ .get_header(&best_block_hash, best_block_height).await?
+ .validate(best_block_hash)
+}
+
/// Performs a one-time sync of chain listeners using a single *trusted* block source, bringing each
/// listener's view of the chain from its paired block hash to `block_source`'s best chain tip.
///
/// ) {
/// // Read a serialized channel monitor paired with the block hash when it was persisted.
/// let serialized_monitor = "...";
- /// let (monitor_block_hash, mut monitor) = <(BlockHash, ChannelMonitor<S>)>::read(
+ /// let (monitor_block_hash_option, mut monitor) = <(Option<BlockHash>, ChannelMonitor<S>)>::read(
/// &mut Cursor::new(&serialized_monitor), keys_manager).unwrap();
///
/// // Read the channel manager paired with the block hash when it was persisted.
/// let serialized_manager = "...";
- /// let (manager_block_hash, mut manager) = {
+ /// let (manager_block_hash_option, mut manager) = {
/// let read_args = ChannelManagerReadArgs::new(
/// keys_manager,
/// fee_estimator,
/// config,
/// vec![&mut monitor],
/// );
- /// <(BlockHash, ChannelManager<S, &ChainMonitor<S, &C, &T, &F, &L, &P>, &T, &K, &F, &L>)>::read(
+ /// <(Option<BlockHash>, ChannelManager<S, &ChainMonitor<S, &C, &T, &F, &L, &P>, &T, &K, &F, &L>)>::read(
/// &mut Cursor::new(&serialized_manager), read_args).unwrap()
/// };
///
/// // Synchronize any channel monitors and the channel manager to be on the best block.
/// let mut cache = UnboundedCache::new();
/// let mut monitor_listener = (monitor, &*tx_broadcaster, &*fee_estimator, &*logger);
- /// let listeners = vec![
- /// (monitor_block_hash, &mut monitor_listener as &mut dyn chain::Listen),
- /// (manager_block_hash, &mut manager as &mut dyn chain::Listen),
- /// ];
+ /// let mut listeners = vec![];
+ /// if let Some(monitor_block_hash) = monitor_block_hash_option {
+ /// listeners.push((monitor_block_hash, &mut monitor_listener as &mut dyn chain::Listen))
+ /// }
+ /// if let Some(manager_block_hash) = manager_block_hash_option {
+ /// listeners.push((manager_block_hash, &mut manager as &mut dyn chain::Listen))
+ /// }
/// let chain_tip = init::synchronize_listeners(
/// block_source, Network::Bitcoin, &mut cache, listeners).await.unwrap();
///
header_cache: &mut C,
mut chain_listeners: Vec<(BlockHash, &mut dyn chain::Listen)>,
) -> BlockSourceResult<ValidatedBlockHeader> {
- let (best_block_hash, best_block_height) = block_source.get_best_block().await?;
- let best_header = block_source
- .get_header(&best_block_hash, best_block_height).await?
- .validate(best_block_hash)?;
+ let best_header = validate_best_block_header(block_source).await?;
// Fetch the header for the block hash paired with each listener.
let mut chain_listeners_with_old_headers = Vec::new();
/// issues such as overly long function definitions. Note that the ChannelManager can take any
/// type that implements KeysInterface for its keys manager, but this type alias chooses the
/// concrete type of the KeysManager.
-pub type SimpleArcChannelManager<M, T, F, L> = Arc<ChannelManager<InMemorySigner, Arc<M>, Arc<T>, Arc<KeysManager>, Arc<F>, Arc<L>>>;
+pub type SimpleArcChannelManager<M, T, F, L> = ChannelManager<InMemorySigner, Arc<M>, Arc<T>, Arc<KeysManager>, Arc<F>, Arc<L>>;
/// SimpleRefChannelManager is a type alias for a ChannelManager reference, and is the reference
/// counterpart to the SimpleArcChannelManager type alias. Use this type by default when you don't
/// ChannelMonitors passed by reference to read(), those channels will be force-closed based on the
/// ChannelMonitor state and no funds will be lost (mod on-chain transaction fees).
///
- /// Note that the deserializer is only implemented for (Sha256dHash, ChannelManager), which
+ /// Note that the deserializer is only implemented for (Option<BlockHash>, ChannelManager), which
/// tells you the last block hash which was block_connect()ed. You MUST rescan any blocks along
/// the "reorg path" (ie call block_disconnected() until you get to a common block and then call
/// block_connected() to step towards your best block) upon deserialization before using the
/// At a high-level, the process for deserializing a ChannelManager and resuming normal operation
/// is:
/// 1) Deserialize all stored ChannelMonitors.
- /// 2) Deserialize the ChannelManager by filling in this struct and calling <(Sha256dHash,
+ /// 2) Deserialize the ChannelManager by filling in this struct and calling <(Option<BlockHash>,
/// ChannelManager)>::read(reader, args).
/// This may result in closing some Channels if the ChannelMonitor is newer than the stored
/// ChannelManager state to ensure no loss of funds. Thus, transactions may be broadcasted.
// Implement ReadableArgs for an Arc'd ChannelManager to make it a bit easier to work with the
// SipmleArcChannelManager type:
impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
- ReadableArgs<ChannelManagerReadArgs<'a, Signer, M, T, K, F, L>> for (BlockHash, Arc<ChannelManager<Signer, M, T, K, F, L>>)
+ ReadableArgs<ChannelManagerReadArgs<'a, Signer, M, T, K, F, L>> for (Option<BlockHash>, Arc<ChannelManager<Signer, M, T, K, F, L>>)
where M::Target: chain::Watch<Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<Signer = Signer>,
L::Target: Logger,
{
fn read<R: ::std::io::Read>(reader: &mut R, args: ChannelManagerReadArgs<'a, Signer, M, T, K, F, L>) -> Result<Self, DecodeError> {
- let (blockhash, chan_manager) = <(BlockHash, ChannelManager<Signer, M, T, K, F, L>)>::read(reader, args)?;
+ let (blockhash, chan_manager) = <(Option<BlockHash>, ChannelManager<Signer, M, T, K, F, L>)>::read(reader, args)?;
Ok((blockhash, Arc::new(chan_manager)))
}
}
impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
- ReadableArgs<ChannelManagerReadArgs<'a, Signer, M, T, K, F, L>> for (BlockHash, ChannelManager<Signer, M, T, K, F, L>)
+ ReadableArgs<ChannelManagerReadArgs<'a, Signer, M, T, K, F, L>> for (Option<BlockHash>, ChannelManager<Signer, M, T, K, F, L>)
where M::Target: chain::Watch<Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<Signer = Signer>,
//TODO: Broadcast channel update for closed channels, but only after we've made a
//connection or two.
- Ok((last_block_hash.clone(), channel_manager))
+ let last_seen_block_hash = if last_block_hash == Default::default() {
+ None
+ } else {
+ Some(last_block_hash)
+ };
+ Ok((last_seen_block_hash, channel_manager))
}
}