Skip to content

Commit 9fb3b71

Browse files
author
Antoine Riard
committed
Implement get_network, get_chain_txo, get_spendable_outpoint in
ChainWatchInterface to Router check on channel_announcement Needed for BOLT 7
1 parent d163c8a commit 9fb3b71

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

src/chain/chaininterface.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,26 @@
11
use bitcoin::blockdata::block::{Block, BlockHeader};
22
use bitcoin::blockdata::transaction::Transaction;
33
use bitcoin::blockdata::script::Script;
4+
use bitcoin::blockdata::constants::genesis_block;
45
use bitcoin::util::hash::Sha256dHash;
6+
use bitcoin::network::constants::Network;
7+
use bitcoin::network::serialize::BitcoinHash;
58
use util::logger::Logger;
69
use std::sync::{Mutex,Weak,MutexGuard,Arc};
710
use std::sync::atomic::{AtomicUsize, Ordering};
811

12+
/// Used to give chain error details upstream
13+
pub enum ChainError {
14+
/// Chain isn't supported
15+
NotSupported,
16+
/// Chain isn't the one watched
17+
NotWatched,
18+
/// Tx isn't there
19+
UnknownTx,
20+
/// Tx isn't confirmed
21+
UnconfirmedTx,
22+
}
23+
924
/// An interface to request notification of certain scripts as they appear the
1025
/// chain.
1126
/// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're
@@ -24,6 +39,15 @@ pub trait ChainWatchInterface: Sync + Send {
2439

2540
fn register_listener(&self, listener: Weak<ChainListener>);
2641
//TODO: unregister
42+
43+
/// Gets the chain currently watched
44+
fn get_network(&self) -> Network;
45+
46+
/// Gets the script and value in satoshis for a given txid and outpoint index
47+
fn get_chain_txo(&self, genesis_hash: Sha256dHash, txid: Sha256dHash, output_index: u16) -> Result<(Script, u64), ChainError>;
48+
49+
/// Gets if outpoint is among UTXO
50+
fn get_spendable_outpoint(&self, genesis_hash: Sha256dHash, txid: Sha256dHash, output_index: u16) -> Result<bool, ChainError>;
2751
}
2852

2953
/// An interface to send a transaction to the Bitcoin network.
@@ -69,12 +93,21 @@ pub trait FeeEstimator: Sync + Send {
6993
/// Utility to capture some common parts of ChainWatchInterface implementors.
7094
/// Keeping a local copy of this in a ChainWatchInterface implementor is likely useful.
7195
pub struct ChainWatchInterfaceUtil {
96+
network: Network,
7297
watched: Mutex<(Vec<Script>, Vec<(Sha256dHash, u32)>, bool)>, //TODO: Something clever to optimize this
7398
listeners: Mutex<Vec<Weak<ChainListener>>>,
7499
reentered: AtomicUsize,
75100
logger: Arc<Logger>,
76101
}
77102

103+
macro_rules! watched_chain {
104+
($self: ident, $hash: expr) => {
105+
if $hash != genesis_block($self.get_network()).header.bitcoin_hash() {
106+
return Err(ChainError::NotWatched);
107+
}
108+
}
109+
}
110+
78111
/// Register listener
79112
impl ChainWatchInterface for ChainWatchInterfaceUtil {
80113
fn install_watch_script(&self, script_pub_key: &Script) {
@@ -99,11 +132,31 @@ impl ChainWatchInterface for ChainWatchInterfaceUtil {
99132
let mut vec = self.listeners.lock().unwrap();
100133
vec.push(listener);
101134
}
135+
136+
fn get_network(&self) -> Network {
137+
self.network
138+
}
139+
140+
141+
fn get_chain_txo(&self, genesis_hash: Sha256dHash, _txid: Sha256dHash, _output_index: u16) -> Result<(Script, u64), ChainError> {
142+
watched_chain!(self, genesis_hash);
143+
144+
//TODO: self.BlockchainStore.get_txo(txid, output_index)
145+
Err(ChainError::UnknownTx)
146+
}
147+
148+
fn get_spendable_outpoint(&self, genesis_hash: Sha256dHash, _txid: Sha256dHash, _output_index: u16) -> Result<bool, ChainError> {
149+
watched_chain!(self, genesis_hash);
150+
151+
//TODO: self.BlockchainStore.is_utxo(txid, output_index)
152+
Err(ChainError::UnknownTx)
153+
}
102154
}
103155

104156
impl ChainWatchInterfaceUtil {
105-
pub fn new(logger: Arc<Logger>) -> ChainWatchInterfaceUtil {
157+
pub fn new(network: Network, logger: Arc<Logger>) -> ChainWatchInterfaceUtil {
106158
ChainWatchInterfaceUtil {
159+
network: network,
107160
watched: Mutex::new((Vec::new(), Vec::new(), false)),
108161
listeners: Mutex::new(Vec::new()),
109162
reentered: AtomicUsize::new(1),

src/ln/router.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use secp256k1::{Secp256k1,Message};
33
use secp256k1;
44

55
use bitcoin::util::hash::Sha256dHash;
6+
use bitcoin::blockdata::constants::genesis_block;
7+
use bitcoin::network::serialize::BitcoinHash;
68

79
use chain::chaininterface::ChainWatchInterface;
810
use ln::channelmanager;
@@ -203,13 +205,15 @@ impl RoutingMessageHandler for Router {
203205
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1);
204206
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2);
205207

206-
//TODO: Call blockchain thing to ask if the short_channel_id is valid
207-
//TODO: Only allow bitcoin chain_hash
208-
209208
if msg.contents.features.requires_unknown_bits() {
210209
panic!("Unknown-required-features ChannelAnnouncements should never deserialize!");
211210
}
212211

212+
//TODO: Call blockchain thing to ask if the short_channel_id is valid
213+
if msg.contents.chain_hash != genesis_block(self.chain_monitor.get_network()).header.bitcoin_hash() {
214+
return Err(HandleError{err: "Channel announced on an unknown chain", action: Some(ErrorAction::IgnoreError)});
215+
}
216+
213217
let mut network = self.network_map.write().unwrap();
214218

215219
match network.channels.entry(NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash)) {
@@ -643,6 +647,7 @@ mod tests {
643647
use util::logger::Logger;
644648

645649
use bitcoin::util::hash::Sha256dHash;
650+
use bitcoin::network::constants::Network;
646651

647652
use hex;
648653

0 commit comments

Comments
 (0)