use bitcoin::blockdata::block::{Block, BlockHeader};
use bitcoin::blockdata::transaction::Transaction;
use bitcoin::blockdata::script::Script;
+use bitcoin::blockdata::constants::genesis_block;
use bitcoin::util::hash::Sha256dHash;
+use bitcoin::network::constants::Network;
+use bitcoin::network::serialize::BitcoinHash;
use util::logger::Logger;
use std::sync::{Mutex,Weak,MutexGuard,Arc};
use std::sync::atomic::{AtomicUsize, Ordering};
+/// Used to give chain error details upstream
+pub enum ChainError {
+ /// Chain isn't supported
+ NotSupported,
+ /// Chain isn't the one watched
+ NotWatched,
+ /// Tx isn't there
+ UnknownTx,
+ /// Tx isn't confirmed
+ UnconfirmedTx,
+}
+
/// An interface to request notification of certain scripts as they appear the
/// chain.
/// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're
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>;
}
/// An interface to send a transaction to the Bitcoin network.
/// Utility to capture some common parts of ChainWatchInterface implementors.
/// Keeping a local copy of this in a ChainWatchInterface implementor is likely useful.
pub struct ChainWatchInterfaceUtil {
+ network: Network,
watched: Mutex<(Vec<Script>, Vec<(Sha256dHash, u32)>, bool)>, //TODO: Something clever to optimize this
listeners: Mutex<Vec<Weak<ChainListener>>>,
reentered: AtomicUsize,
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) {
let mut vec = self.listeners.lock().unwrap();
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)
+ }
}
impl ChainWatchInterfaceUtil {
- pub fn new(logger: Arc<Logger>) -> ChainWatchInterfaceUtil {
+ pub fn new(network: Network, logger: Arc<Logger>) -> ChainWatchInterfaceUtil {
ChainWatchInterfaceUtil {
+ network: network,
watched: Mutex::new((Vec::new(), Vec::new(), false)),
listeners: Mutex::new(Vec::new()),
reentered: AtomicUsize::new(1),
use secp256k1;
use bitcoin::util::hash::Sha256dHash;
+use bitcoin::blockdata::constants::genesis_block;
+use bitcoin::network::serialize::BitcoinHash;
use chain::chaininterface::ChainWatchInterface;
use ln::channelmanager;
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1);
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2);
- //TODO: Call blockchain thing to ask if the short_channel_id is valid
- //TODO: Only allow bitcoin chain_hash
-
if msg.contents.features.requires_unknown_bits() {
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)});
+ }
+
let mut network = self.network_map.write().unwrap();
match network.channels.entry(NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash)) {
use util::logger::Logger;
use bitcoin::util::hash::Sha256dHash;
+ use bitcoin::network::constants::Network;
use hex;