@@ -2,7 +2,7 @@ use anyhow::{bail, Context, Result};
2
2
use bitcoin:: {
3
3
consensus:: { deserialize, serialize} ,
4
4
hashes:: hex:: { FromHex , ToHex } ,
5
- BlockHash , Txid ,
5
+ BlockHash , OutPoint , Txid ,
6
6
} ;
7
7
use crossbeam_channel:: Receiver ;
8
8
use rayon:: prelude:: * ;
@@ -19,7 +19,7 @@ use crate::{
19
19
merkle:: Proof ,
20
20
metrics:: { self , Histogram , Metrics } ,
21
21
signals:: Signal ,
22
- status:: ScriptHashStatus ,
22
+ status:: { OutPointStatus , ScriptHashStatus } ,
23
23
tracker:: Tracker ,
24
24
types:: ScriptHash ,
25
25
} ;
@@ -34,6 +34,7 @@ const UNSUBSCRIBED_QUERY_MESSAGE: &str = "your wallet uses less efficient method
34
34
pub struct Client {
35
35
tip : Option < BlockHash > ,
36
36
scripthashes : HashMap < ScriptHash , ScriptHashStatus > ,
37
+ outpoints : HashMap < OutPoint , OutPointStatus > ,
37
38
}
38
39
39
40
#[ derive( Deserialize ) ]
@@ -183,7 +184,25 @@ impl Rpc {
183
184
}
184
185
} )
185
186
. collect :: < Result < Vec < Value > > > ( )
186
- . context ( "failed to update status" ) ?;
187
+ . context ( "failed to update scripthash status" ) ?;
188
+
189
+ notifications. extend (
190
+ client
191
+ . outpoints
192
+ . par_iter_mut ( )
193
+ . filter_map ( |( outpoint, status) | -> Option < Result < Value > > {
194
+ match self . tracker . update_outpoint_status ( status, & self . daemon ) {
195
+ Ok ( true ) => Some ( Ok ( notification (
196
+ "blockchain.outpoint.subscribe" ,
197
+ & [ json ! ( [ outpoint. txid, outpoint. vout] ) , json ! ( status) ] ,
198
+ ) ) ) ,
199
+ Ok ( false ) => None , // outpoint status is the same
200
+ Err ( e) => Some ( Err ( e) ) ,
201
+ }
202
+ } )
203
+ . collect :: < Result < Vec < Value > > > ( )
204
+ . context ( "failed to update scripthash status" ) ?,
205
+ ) ;
187
206
188
207
if let Some ( old_tip) = client. tip {
189
208
let new_tip = self . tracker . chain ( ) . tip ( ) ;
@@ -342,6 +361,28 @@ impl Rpc {
342
361
} )
343
362
}
344
363
364
+ fn outpoint_subscribe ( & self , client : & mut Client , ( txid, vout) : ( Txid , u32 ) ) -> Result < Value > {
365
+ let outpoint = OutPoint :: new ( txid, vout) ;
366
+ Ok ( match client. outpoints . entry ( outpoint) {
367
+ Entry :: Occupied ( e) => json ! ( e. get( ) ) ,
368
+ Entry :: Vacant ( e) => {
369
+ let outpoint = OutPoint :: new ( txid, vout) ;
370
+ let mut status = OutPointStatus :: new ( outpoint) ;
371
+ self . tracker
372
+ . update_outpoint_status ( & mut status, & self . daemon ) ?;
373
+ json ! ( e. insert( status) )
374
+ }
375
+ } )
376
+ }
377
+
378
+ fn outpoint_unsubscribe (
379
+ & self ,
380
+ client : & mut Client ,
381
+ ( txid, vout) : ( Txid , u32 ) ,
382
+ ) -> Result < Value > {
383
+ Ok ( json ! ( client. outpoints. remove( & OutPoint :: new( txid, vout) ) ) )
384
+ }
385
+
345
386
fn new_status ( & self , scripthash : ScriptHash ) -> Result < ScriptHashStatus > {
346
387
let mut status = ScriptHashStatus :: new ( scripthash) ;
347
388
self . tracker
@@ -525,6 +566,8 @@ impl Rpc {
525
566
Params :: Features => self . features ( ) ,
526
567
Params :: HeadersSubscribe => self . headers_subscribe ( client) ,
527
568
Params :: MempoolFeeHistogram => self . get_fee_histogram ( ) ,
569
+ Params :: OutPointSubscribe ( args) => self . outpoint_subscribe ( client, * args) ,
570
+ Params :: OutPointUnsubscribe ( args) => self . outpoint_unsubscribe ( client, * args) ,
528
571
Params :: PeersSubscribe => Ok ( json ! ( [ ] ) ) ,
529
572
Params :: Ping => Ok ( Value :: Null ) ,
530
573
Params :: RelayFee => self . relayfee ( ) ,
@@ -547,19 +590,21 @@ enum Params {
547
590
Banner ,
548
591
BlockHeader ( ( usize , ) ) ,
549
592
BlockHeaders ( ( usize , usize ) ) ,
550
- TransactionBroadcast ( ( String , ) ) ,
551
593
Donation ,
552
594
EstimateFee ( ( u16 , ) ) ,
553
595
Features ,
554
596
HeadersSubscribe ,
555
597
MempoolFeeHistogram ,
598
+ OutPointSubscribe ( ( Txid , u32 ) ) , // TODO: support spk_hint
599
+ OutPointUnsubscribe ( ( Txid , u32 ) ) ,
556
600
PeersSubscribe ,
557
601
Ping ,
558
602
RelayFee ,
559
603
ScriptHashGetBalance ( ( ScriptHash , ) ) ,
560
604
ScriptHashGetHistory ( ( ScriptHash , ) ) ,
561
605
ScriptHashListUnspent ( ( ScriptHash , ) ) ,
562
606
ScriptHashSubscribe ( ( ScriptHash , ) ) ,
607
+ TransactionBroadcast ( ( String , ) ) ,
563
608
TransactionGet ( TxGetArgs ) ,
564
609
TransactionGetMerkle ( ( Txid , usize ) ) ,
565
610
Version ( ( String , Version ) ) ,
@@ -572,6 +617,8 @@ impl Params {
572
617
"blockchain.block.headers" => Params :: BlockHeaders ( convert ( params) ?) ,
573
618
"blockchain.estimatefee" => Params :: EstimateFee ( convert ( params) ?) ,
574
619
"blockchain.headers.subscribe" => Params :: HeadersSubscribe ,
620
+ "blockchain.outpoint.subscribe" => Params :: OutPointSubscribe ( convert ( params) ?) ,
621
+ "blockchain.outpoint.unsubscribe" => Params :: OutPointUnsubscribe ( convert ( params) ?) ,
575
622
"blockchain.relayfee" => Params :: RelayFee ,
576
623
"blockchain.scripthash.get_balance" => Params :: ScriptHashGetBalance ( convert ( params) ?) ,
577
624
"blockchain.scripthash.get_history" => Params :: ScriptHashGetHistory ( convert ( params) ?) ,
0 commit comments