1
1
use bitcoin:: blockdata:: block:: { Block , BlockHeader } ;
2
2
use bitcoin:: blockdata:: transaction:: Transaction ;
3
3
use bitcoin:: blockdata:: script:: Script ;
4
+ use bitcoin:: blockdata:: constants:: genesis_block;
4
5
use bitcoin:: util:: hash:: Sha256dHash ;
6
+ use bitcoin:: network:: constants:: Network ;
7
+ use bitcoin:: network:: serialize:: BitcoinHash ;
5
8
use util:: logger:: Logger ;
6
9
use std:: sync:: { Mutex , Weak , MutexGuard , Arc } ;
7
10
use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
8
11
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
+
9
24
/// An interface to request notification of certain scripts as they appear the
10
25
/// chain.
11
26
/// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're
@@ -24,6 +39,15 @@ pub trait ChainWatchInterface: Sync + Send {
24
39
25
40
fn register_listener ( & self , listener : Weak < ChainListener > ) ;
26
41
//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 > ;
27
51
}
28
52
29
53
/// An interface to send a transaction to the Bitcoin network.
@@ -69,12 +93,21 @@ pub trait FeeEstimator: Sync + Send {
69
93
/// Utility to capture some common parts of ChainWatchInterface implementors.
70
94
/// Keeping a local copy of this in a ChainWatchInterface implementor is likely useful.
71
95
pub struct ChainWatchInterfaceUtil {
96
+ network : Network ,
72
97
watched : Mutex < ( Vec < Script > , Vec < ( Sha256dHash , u32 ) > , bool ) > , //TODO: Something clever to optimize this
73
98
listeners : Mutex < Vec < Weak < ChainListener > > > ,
74
99
reentered : AtomicUsize ,
75
100
logger : Arc < Logger > ,
76
101
}
77
102
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
+
78
111
/// Register listener
79
112
impl ChainWatchInterface for ChainWatchInterfaceUtil {
80
113
fn install_watch_script ( & self , script_pub_key : & Script ) {
@@ -99,11 +132,31 @@ impl ChainWatchInterface for ChainWatchInterfaceUtil {
99
132
let mut vec = self . listeners . lock ( ) . unwrap ( ) ;
100
133
vec. push ( listener) ;
101
134
}
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
+ }
102
154
}
103
155
104
156
impl ChainWatchInterfaceUtil {
105
- pub fn new ( logger : Arc < Logger > ) -> ChainWatchInterfaceUtil {
157
+ pub fn new ( network : Network , logger : Arc < Logger > ) -> ChainWatchInterfaceUtil {
106
158
ChainWatchInterfaceUtil {
159
+ network : network,
107
160
watched : Mutex :: new ( ( Vec :: new ( ) , Vec :: new ( ) , false ) ) ,
108
161
listeners : Mutex :: new ( Vec :: new ( ) ) ,
109
162
reentered : AtomicUsize :: new ( 1 ) ,
0 commit comments