@@ -2,7 +2,7 @@ use anyhow::{bail, Context, Result};
22use bitcoin:: {
33 consensus:: { deserialize, serialize} ,
44 hashes:: hex:: { FromHex , ToHex } ,
5- BlockHash , Txid ,
5+ BlockHash , OutPoint , Txid ,
66} ;
77use crossbeam_channel:: Receiver ;
88use rayon:: prelude:: * ;
@@ -19,7 +19,7 @@ use crate::{
1919 merkle:: Proof ,
2020 metrics:: { self , Histogram , Metrics } ,
2121 signals:: Signal ,
22- status:: ScriptHashStatus ,
22+ status:: { OutPointStatus , ScriptHashStatus } ,
2323 tracker:: Tracker ,
2424 types:: ScriptHash ,
2525} ;
@@ -34,6 +34,7 @@ const UNSUBSCRIBED_QUERY_MESSAGE: &str = "your wallet uses less efficient method
3434pub struct Client {
3535 tip : Option < BlockHash > ,
3636 scripthashes : HashMap < ScriptHash , ScriptHashStatus > ,
37+ outpoints : HashMap < OutPoint , OutPointStatus > ,
3738}
3839
3940#[ derive( Deserialize ) ]
@@ -183,7 +184,25 @@ impl Rpc {
183184 }
184185 } )
185186 . 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+ ) ;
187206
188207 if let Some ( old_tip) = client. tip {
189208 let new_tip = self . tracker . chain ( ) . tip ( ) ;
@@ -339,6 +358,28 @@ impl Rpc {
339358 } )
340359 }
341360
361+ fn outpoint_subscribe ( & self , client : & mut Client , ( txid, vout) : ( Txid , u32 ) ) -> Result < Value > {
362+ let outpoint = OutPoint :: new ( txid, vout) ;
363+ Ok ( match client. outpoints . entry ( outpoint) {
364+ Entry :: Occupied ( e) => json ! ( e. get( ) ) ,
365+ Entry :: Vacant ( e) => {
366+ let outpoint = OutPoint :: new ( txid, vout) ;
367+ let mut status = OutPointStatus :: new ( outpoint) ;
368+ self . tracker
369+ . update_outpoint_status ( & mut status, & self . daemon ) ?;
370+ json ! ( e. insert( status) )
371+ }
372+ } )
373+ }
374+
375+ fn outpoint_unsubscribe (
376+ & self ,
377+ client : & mut Client ,
378+ ( txid, vout) : ( Txid , u32 ) ,
379+ ) -> Result < Value > {
380+ Ok ( json ! ( client. outpoints. remove( & OutPoint :: new( txid, vout) ) ) )
381+ }
382+
342383 fn new_status ( & self , scripthash : ScriptHash ) -> Result < ScriptHashStatus > {
343384 let mut status = ScriptHashStatus :: new ( scripthash) ;
344385 self . tracker
@@ -518,6 +559,8 @@ impl Rpc {
518559 Params :: Features => self . features ( ) ,
519560 Params :: HeadersSubscribe => self . headers_subscribe ( client) ,
520561 Params :: MempoolFeeHistogram => self . get_fee_histogram ( ) ,
562+ Params :: OutPointSubscribe ( args) => self . outpoint_subscribe ( client, * args) ,
563+ Params :: OutPointUnsubscribe ( args) => self . outpoint_unsubscribe ( client, * args) ,
521564 Params :: PeersSubscribe => Ok ( json ! ( [ ] ) ) ,
522565 Params :: Ping => Ok ( Value :: Null ) ,
523566 Params :: RelayFee => self . relayfee ( ) ,
@@ -540,19 +583,21 @@ enum Params {
540583 Banner ,
541584 BlockHeader ( ( usize , ) ) ,
542585 BlockHeaders ( ( usize , usize ) ) ,
543- TransactionBroadcast ( ( String , ) ) ,
544586 Donation ,
545587 EstimateFee ( ( u16 , ) ) ,
546588 Features ,
547589 HeadersSubscribe ,
548590 MempoolFeeHistogram ,
591+ OutPointSubscribe ( ( Txid , u32 ) ) , // TODO: support spk_hint
592+ OutPointUnsubscribe ( ( Txid , u32 ) ) ,
549593 PeersSubscribe ,
550594 Ping ,
551595 RelayFee ,
552596 ScriptHashGetBalance ( ( ScriptHash , ) ) ,
553597 ScriptHashGetHistory ( ( ScriptHash , ) ) ,
554598 ScriptHashListUnspent ( ( ScriptHash , ) ) ,
555599 ScriptHashSubscribe ( ( ScriptHash , ) ) ,
600+ TransactionBroadcast ( ( String , ) ) ,
556601 TransactionGet ( TxGetArgs ) ,
557602 TransactionGetMerkle ( ( Txid , usize ) ) ,
558603 Version ( ( String , Version ) ) ,
@@ -565,6 +610,8 @@ impl Params {
565610 "blockchain.block.headers" => Params :: BlockHeaders ( convert ( params) ?) ,
566611 "blockchain.estimatefee" => Params :: EstimateFee ( convert ( params) ?) ,
567612 "blockchain.headers.subscribe" => Params :: HeadersSubscribe ,
613+ "blockchain.outpoint.subscribe" => Params :: OutPointSubscribe ( convert ( params) ?) ,
614+ "blockchain.outpoint.unsubscribe" => Params :: OutPointUnsubscribe ( convert ( params) ?) ,
568615 "blockchain.relayfee" => Params :: RelayFee ,
569616 "blockchain.scripthash.get_balance" => Params :: ScriptHashGetBalance ( convert ( params) ?) ,
570617 "blockchain.scripthash.get_history" => Params :: ScriptHashGetHistory ( convert ( params) ?) ,
0 commit comments