From 3cc969574a929acb3d5cdcfc3e86ef4396dc53dc Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Fri, 9 Sep 2022 15:38:10 +0200 Subject: [PATCH] Implement `chain::Access` trait --- src/access.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++--- src/lib.rs | 20 ++++++++++++++------ src/scid_utils.rs | 33 ++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 9 deletions(-) create mode 100644 src/scid_utils.rs diff --git a/src/access.rs b/src/access.rs index 865aa656b..cdb66cebd 100644 --- a/src/access.rs +++ b/src/access.rs @@ -4,17 +4,18 @@ use crate::logger::{ log_error, log_given_level, log_info, log_internal, log_trace, log_warn, FilesystemLogger, Logger, }; +use crate::{scid_utils, LdkLiteConfig}; use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator}; use lightning::chain::WatchedOutput; -use lightning::chain::{Confirm, Filter}; +use lightning::chain::{Access, AccessError, Confirm, Filter}; use bdk::blockchain::{Blockchain, EsploraBlockchain, GetBlockHash, GetHeight, GetTx}; use bdk::database::BatchDatabase; use bdk::wallet::AddressIndex; use bdk::{SignOptions, SyncOptions}; -use bitcoin::{BlockHash, Script, Transaction, Txid}; +use bitcoin::{BlockHash, Script, Transaction, TxOut, Txid}; use std::sync::{Arc, Mutex}; @@ -29,6 +30,7 @@ where queued_outputs: Mutex>, watched_outputs: Mutex>, last_sync_height: Mutex>, + config: Arc, logger: Arc, } @@ -37,7 +39,8 @@ where D: BatchDatabase, { pub(crate) fn new( - blockchain: EsploraBlockchain, wallet: bdk::Wallet, logger: Arc, + blockchain: EsploraBlockchain, wallet: bdk::Wallet, config: Arc, + logger: Arc, ) -> Self { let wallet = Mutex::new(wallet); let watched_transactions = Mutex::new(Vec::new()); @@ -53,6 +56,7 @@ where queued_outputs, watched_outputs, last_sync_height, + config, logger, } } @@ -275,6 +279,44 @@ where } } +impl Access for LdkLiteChainAccess +where + D: BatchDatabase, +{ + fn get_utxo( + &self, genesis_hash: &BlockHash, short_channel_id: u64, + ) -> Result { + if genesis_hash + != &bitcoin::blockdata::constants::genesis_block(self.config.network) + .header + .block_hash() + { + return Err(AccessError::UnknownChain); + } + + let block_height = scid_utils::block_from_scid(&short_channel_id); + let tx_index = scid_utils::tx_index_from_scid(&short_channel_id); + let vout = scid_utils::vout_from_scid(&short_channel_id); + + let client = &*self.blockchain; + let block_hash = self + .blockchain + .get_block_hash(block_height.into()) + .map_err(|_| AccessError::UnknownTx)?; + let txid = client + .get_txid_at_block_index(&block_hash, tx_index as usize) + .map_err(|_| AccessError::UnknownTx)? + .ok_or(AccessError::UnknownTx)?; + let tx = client + .get_tx(&txid) + .map_err(|_| AccessError::UnknownTx)? + .ok_or(AccessError::UnknownTx)?; + let tx_out = tx.output.get(vout as usize).ok_or(AccessError::UnknownTx)?; + + Ok(tx_out.clone()) + } +} + impl Filter for LdkLiteChainAccess where D: BatchDatabase, diff --git a/src/lib.rs b/src/lib.rs index 063482174..620d9c4c8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,7 @@ mod hex; mod io; mod logger; mod peer_store; +mod scid_utils; use access::LdkLiteChainAccess; pub use error::LdkLiteError as Error; @@ -227,8 +228,12 @@ impl LdkLiteBuilder { let blockchain = EsploraBlockchain::new(&config.esplora_server_url, BDK_CLIENT_STOP_GAP) .with_concurrency(BDK_CLIENT_CONCURRENCY); - let chain_access = - Arc::new(LdkLiteChainAccess::new(blockchain, bdk_wallet, Arc::clone(&logger))); + let chain_access = Arc::new(LdkLiteChainAccess::new( + blockchain, + bdk_wallet, + Arc::clone(&config), + Arc::clone(&logger), + )); // Step 3: Initialize Persist let persister = Arc::new(FilesystemPersister::new(ldk_data_dir.clone())); @@ -303,7 +308,7 @@ impl LdkLiteBuilder { Arc::new(io::read_network_graph(Arc::clone(&config), Arc::clone(&logger))?); let gossip_sync = Arc::new(P2PGossipSync::new( Arc::clone(&network_graph), - None::>, + Some(Arc::clone(&chain_access)), Arc::clone(&logger), )); @@ -963,7 +968,7 @@ type PeerManager = SimpleArcPeerManager< ChainMonitor, LdkLiteChainAccess, LdkLiteChainAccess, - dyn Access + Send + Sync, + LdkLiteChainAccess, FilesystemLogger, >; @@ -985,8 +990,11 @@ type InvoicePayer = payment::InvoicePayer< type Router = DefaultRouter, Arc>; type Scorer = ProbabilisticScorer, Arc>; -type GossipSync = - P2PGossipSync, Arc, Arc>; +type GossipSync = P2PGossipSync< + Arc, + Arc>, + Arc, +>; pub(crate) type NetworkGraph = gossip::NetworkGraph>; diff --git a/src/scid_utils.rs b/src/scid_utils.rs new file mode 100644 index 000000000..bca2994f5 --- /dev/null +++ b/src/scid_utils.rs @@ -0,0 +1,33 @@ +// Copied from `rust-lightning` +// +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +/// Maximum transaction index that can be used in a `short_channel_id`. +/// This value is based on the 3-bytes available for tx index. +pub const MAX_SCID_TX_INDEX: u64 = 0x00ffffff; + +/// Maximum vout index that can be used in a `short_channel_id`. This +/// value is based on the 2-bytes available for the vout index. +pub const MAX_SCID_VOUT_INDEX: u64 = 0xffff; + +/// Extracts the block height (most significant 3-bytes) from the `short_channel_id` +pub fn block_from_scid(short_channel_id: &u64) -> u32 { + return (short_channel_id >> 40) as u32; +} + +/// Extracts the tx index (bytes [2..4]) from the `short_channel_id` +pub fn tx_index_from_scid(short_channel_id: &u64) -> u32 { + return ((short_channel_id >> 16) & MAX_SCID_TX_INDEX) as u32; +} + +/// Extracts the vout (bytes [0..2]) from the `short_channel_id` +pub fn vout_from_scid(short_channel_id: &u64) -> u16 { + return ((short_channel_id) & MAX_SCID_VOUT_INDEX) as u16; +}