/// Used to give chain error details upstream
pub enum ChainError {
- /// Chain isn't supported
+ /// Client doesn't support UTXO lookup (but the chain hash matches our genesis block hash)
NotSupported,
/// Chain isn't the one watched
NotWatched,
- /// Tx isn't there
+ /// Tx doesn't exist or is unconfirmed
UnknownTx,
- /// Tx isn't confirmed
- UnconfirmedTx,
}
/// An interface to request notification of certain scripts as they appear the
fn register_listener(&self, listener: Weak<ChainListener>);
//TODO: unregister
- /// Gets the chain currently watched
- fn get_network(&self) -> Network;
-
- /// Gets the script and value in satoshis for a given txid and outpoint index
- fn get_chain_txo(&self, genesis_hash: Sha256dHash, txid: Sha256dHash, output_index: u16) -> Result<(Script, u64), ChainError>;
-
- /// Gets if outpoint is among UTXO
- fn get_spendable_outpoint(&self, genesis_hash: Sha256dHash, txid: Sha256dHash, output_index: u16) -> Result<bool, ChainError>;
+ /// Gets the script and value in satoshis for a given unspent transaction output given a
+ /// short_channel_id (aka unspent_tx_output_identier). For BTC/tBTC channels the top three
+ /// bytes are the block height, the next 3 the transaction index within the block, and the
+ /// final two the output within the transaction.
+ fn get_chain_utxo(&self, genesis_hash: Sha256dHash, unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError>;
}
/// An interface to send a transaction to the Bitcoin network.
logger: Arc<Logger>,
}
-macro_rules! watched_chain {
- ($self: ident, $hash: expr) => {
- if $hash != genesis_block($self.get_network()).header.bitcoin_hash() {
- return Err(ChainError::NotWatched);
- }
- }
-}
-
/// Register listener
impl ChainWatchInterface for ChainWatchInterfaceUtil {
fn install_watch_script(&self, script_pub_key: &Script) {
vec.push(listener);
}
- fn get_network(&self) -> Network {
- self.network
- }
-
-
- fn get_chain_txo(&self, genesis_hash: Sha256dHash, _txid: Sha256dHash, _output_index: u16) -> Result<(Script, u64), ChainError> {
- watched_chain!(self, genesis_hash);
-
- //TODO: self.BlockchainStore.get_txo(txid, output_index)
- Err(ChainError::UnknownTx)
- }
-
- fn get_spendable_outpoint(&self, genesis_hash: Sha256dHash, _txid: Sha256dHash, _output_index: u16) -> Result<bool, ChainError> {
- watched_chain!(self, genesis_hash);
-
- //TODO: self.BlockchainStore.is_utxo(txid, output_index)
- Err(ChainError::UnknownTx)
+ fn get_chain_utxo(&self, genesis_hash: Sha256dHash, _unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError> {
+ if genesis_hash != genesis_block(self.network).header.bitcoin_hash() {
+ return Err(ChainError::NotWatched);
+ }
+ Err(ChainError::NotSupported)
}
}
use secp256k1;
use bitcoin::util::hash::Sha256dHash;
-use bitcoin::blockdata::constants::genesis_block;
-use bitcoin::network::serialize::BitcoinHash;
-use chain::chaininterface::ChainWatchInterface;
+use chain::chaininterface::{ChainError, ChainWatchInterface};
use ln::channelmanager;
use ln::msgs::{ErrorAction,HandleError,RoutingMessageHandler,MsgEncodable,NetAddress,GlobalFeatures};
use ln::msgs;
panic!("Unknown-required-features ChannelAnnouncements should never deserialize!");
}
- //TODO: Call blockchain thing to ask if the short_channel_id is valid
- if msg.contents.chain_hash != genesis_block(self.chain_monitor.get_network()).header.bitcoin_hash() {
- return Err(HandleError{err: "Channel announced on an unknown chain", action: Some(ErrorAction::IgnoreError)});
+ match self.chain_monitor.get_chain_utxo(msg.contents.chain_hash, msg.contents.short_channel_id) {
+ Ok((script_pubkey, _value)) => {
+ //TODO: Check if script_pubkey matches bitcoin_key_1 and bitcoin_key_2
+ },
+ Err(ChainError::NotSupported) => {
+ // Tenatively accept, potentially exposing us to DoS attacks
+ },
+ Err(ChainError::NotWatched) => {
+ return Err(HandleError{err: "Channel announced on an unknown chain", action: Some(ErrorAction::IgnoreError)});
+ },
+ Err(ChainError::UnknownTx) => {
+ return Err(HandleError{err: "Channel announced without corresponding UTXO entry", action: Some(ErrorAction::IgnoreError)});
+ },
}
let mut network = self.network_map.write().unwrap();