@@ -24,11 +24,6 @@ use serde_json::Value as Json;
2424// If bitcoind takes more than 3 minutes to answer one of our queries, fail.
2525const RPC_SOCKET_TIMEOUT : u64 = 180 ;
2626
27- // Labels used to tag utxos in the watchonly wallet
28- const DEPOSIT_UTXOS_LABEL : & str = "revault-deposit" ;
29- const UNVAULT_UTXOS_LABEL : & str = "revault-unvault" ;
30- const CPFP_UTXOS_LABEL : & str = "revault-cpfp" ;
31-
3227pub struct BitcoinD {
3328 node_client : Client ,
3429 watchonly_client : Client ,
@@ -350,32 +345,14 @@ impl BitcoinD {
350345 }
351346 }
352347
353- /// Constructs an `addr()` descriptor out of an address
354- pub fn addr_descriptor ( & self , address : & str ) -> Result < String , BitcoindError > {
355- let desc_wo_checksum = format ! ( "addr({})" , address) ;
356-
357- Ok ( self
358- . make_watchonly_request (
359- "getdescriptorinfo" ,
360- & params ! ( Json :: String ( desc_wo_checksum) ) ,
361- ) ?
362- . get ( "descriptor" )
363- . expect ( "No 'descriptor' in 'getdescriptorinfo'" )
364- . as_str ( )
365- . expect ( "'descriptor' in 'getdescriptorinfo' isn't a string anymore" )
366- . to_string ( ) )
367- }
368-
369- fn bulk_import_descriptors (
348+ fn import_descriptors (
370349 & self ,
371350 client : & Client ,
372351 descriptors : Vec < String > ,
373- timestamp : u32 ,
374- label : String ,
375- fresh_wallet : bool ,
352+ timestamp : Option < u32 > ,
376353 active : bool ,
377354 ) -> Result < ( ) , BitcoindError > {
378- if !fresh_wallet {
355+ if timestamp . is_some ( ) {
379356 log:: debug!( "Not a fresh wallet, rescan *may* take some time." ) ;
380357 }
381358
@@ -388,13 +365,11 @@ impl BitcoinD {
388365 // will rescan the last few blocks for each of them.
389366 desc_map. insert (
390367 "timestamp" . to_string ( ) ,
391- if fresh_wallet {
392- Json :: String ( "now" . to_string ( ) )
393- } else {
394- Json :: Number ( serde_json:: Number :: from ( timestamp) )
395- } ,
368+ timestamp
369+ . map ( serde_json:: Number :: from)
370+ . map ( Json :: Number )
371+ . unwrap_or_else ( || Json :: String ( "now" . to_string ( ) ) ) ,
396372 ) ;
397- desc_map. insert ( "label" . to_string ( ) , Json :: String ( label. clone ( ) ) ) ;
398373 desc_map. insert ( "active" . to_string ( ) , Json :: Bool ( active) ) ;
399374
400375 Json :: Object ( desc_map)
@@ -424,84 +399,26 @@ impl BitcoinD {
424399 ) ) )
425400 }
426401
427- pub fn startup_import_deposit_descriptors (
428- & self ,
429- descriptors : Vec < String > ,
430- timestamp : u32 ,
431- fresh_wallet : bool ,
432- ) -> Result < ( ) , BitcoindError > {
433- self . bulk_import_descriptors (
434- & self . watchonly_client ,
435- descriptors,
436- timestamp,
437- DEPOSIT_UTXOS_LABEL . to_string ( ) ,
438- fresh_wallet,
439- false ,
440- )
441- }
442-
443- pub fn startup_import_unvault_descriptors (
402+ /// Import the deposit and Unvault descriptors, when at startup.
403+ pub fn startup_import_descriptors (
444404 & self ,
445- descriptors : Vec < String > ,
446- timestamp : u32 ,
447- fresh_wallet : bool ,
405+ descriptors : [ String ; 2 ] ,
406+ timestamp : Option < u32 > ,
448407 ) -> Result < ( ) , BitcoindError > {
449- self . bulk_import_descriptors (
408+ self . import_descriptors (
450409 & self . watchonly_client ,
451- descriptors,
410+ descriptors. to_vec ( ) ,
452411 timestamp,
453- UNVAULT_UTXOS_LABEL . to_string ( ) ,
454- fresh_wallet,
455412 false ,
456413 )
457414 }
458415
459- pub fn startup_import_cpfp_descriptor (
460- & self ,
461- descriptor : String ,
462- timestamp : u32 ,
463- fresh_wallet : bool ,
464- ) -> Result < ( ) , BitcoindError > {
465- self . bulk_import_descriptors (
466- & self . cpfp_client ,
467- vec ! [ descriptor] ,
468- timestamp,
469- CPFP_UTXOS_LABEL . to_string ( ) ,
470- fresh_wallet,
471- true ,
472- )
473- }
474-
475- fn import_fresh_descriptor (
416+ pub fn import_cpfp_descriptor (
476417 & self ,
477418 descriptor : String ,
478- label : String ,
419+ timestamp : Option < u32 > ,
479420 ) -> Result < ( ) , BitcoindError > {
480- let mut desc_map = serde_json:: Map :: with_capacity ( 3 ) ;
481- desc_map. insert ( "desc" . to_string ( ) , Json :: String ( descriptor) ) ;
482- desc_map. insert ( "timestamp" . to_string ( ) , Json :: String ( "now" . to_string ( ) ) ) ;
483- desc_map. insert ( "label" . to_string ( ) , Json :: String ( label) ) ;
484-
485- let res = self . make_watchonly_request (
486- "importdescriptors" ,
487- & params ! ( Json :: Array ( vec![ Json :: Object ( desc_map, ) ] ) ) ,
488- ) ?;
489- if res. get ( 0 ) . map ( |x| x. get ( "success" ) ) . flatten ( ) == Some ( & Json :: Bool ( true ) ) {
490- return Ok ( ( ) ) ;
491- }
492-
493- Err ( BitcoindError :: Custom ( format ! (
494- "In import_fresh descriptor, no success returned from 'importdescriptor': {:?}" ,
495- res
496- ) ) )
497- }
498-
499- pub fn import_fresh_deposit_descriptor ( & self , descriptor : String ) -> Result < ( ) , BitcoindError > {
500- self . import_fresh_descriptor ( descriptor, DEPOSIT_UTXOS_LABEL . to_string ( ) )
501- }
502-
503- pub fn import_fresh_unvault_descriptor ( & self , descriptor : String ) -> Result < ( ) , BitcoindError > {
504- self . import_fresh_descriptor ( descriptor, UNVAULT_UTXOS_LABEL . to_string ( ) )
421+ self . import_descriptors ( & self . cpfp_client , vec ! [ descriptor] , timestamp, true )
505422 }
506423
507424 pub fn list_unspent_cpfp ( & self ) -> Result < Vec < ListUnspentEntry > , BitcoindError > {
@@ -559,15 +476,21 @@ impl BitcoinD {
559476 fn list_since_block (
560477 & self ,
561478 tip : & BlockchainTip ,
562- label : Option < & ' static str > ,
479+ descriptor : Option < String > ,
563480 ) -> Result < Vec < ListSinceBlockTransaction > , BitcoindError > {
564481 let req = if tip. height == 0 {
565482 self . make_request ( & self . watchonly_client , "listsinceblock" , & params ! ( ) ) ?
566483 } else {
567484 self . make_request (
568485 & self . watchonly_client ,
569486 "listsinceblock" ,
570- & params ! ( Json :: String ( tip. hash. to_string( ) ) ) ,
487+ & params ! (
488+ Json :: String ( tip. hash. to_string( ) ) ,
489+ Json :: Number ( 1 . into( ) ) ,
490+ Json :: Bool ( true ) ,
491+ Json :: Bool ( true ) ,
492+ Json :: Bool ( true )
493+ ) ,
571494 ) ?
572495 } ;
573496 Ok ( req
@@ -578,20 +501,26 @@ impl BitcoinD {
578501 . iter ( )
579502 . filter_map ( |t| {
580503 let t = ListSinceBlockTransaction :: from ( t) ;
581- if label. or_else ( || t. label . as_deref ( ) ) == t. label . as_deref ( ) {
582- Some ( t)
583- } else {
584- None
504+ match descriptor {
505+ None => Some ( t) ,
506+ Some ( ref desc) => {
507+ if t. wallet_descs . contains ( desc) {
508+ Some ( t)
509+ } else {
510+ None
511+ }
512+ }
585513 }
586514 } )
587515 . collect ( ) )
588516 }
589517
590- pub fn list_deposits_since_block (
518+ fn list_deposits_since_block (
591519 & self ,
592520 tip : & BlockchainTip ,
521+ deposit_desc : String ,
593522 ) -> Result < Vec < ListSinceBlockTransaction > , BitcoindError > {
594- self . list_since_block ( tip, Some ( DEPOSIT_UTXOS_LABEL ) )
523+ self . list_since_block ( tip, Some ( deposit_desc ) )
595524 }
596525
597526 /// Repeatedly called by our main loop to stay in sync with bitcoind.
@@ -601,6 +530,7 @@ impl BitcoinD {
601530 deposits_utxos : & HashMap < OutPoint , UtxoInfo > ,
602531 db_tip : & BlockchainTip ,
603532 min_conf : u32 ,
533+ deposit_desc : String ,
604534 ) -> Result < DepositsState , BitcoindError > {
605535 let ( mut new_unconf, mut new_conf, mut new_spent) =
606536 ( HashMap :: new ( ) , HashMap :: new ( ) , HashMap :: new ( ) ) ;
@@ -645,7 +575,7 @@ impl BitcoinD {
645575 }
646576
647577 // Second, we scan for new ones.
648- let utxos = self . list_deposits_since_block ( db_tip) ?;
578+ let utxos = self . list_deposits_since_block ( db_tip, deposit_desc ) ?;
649579 for utxo in utxos {
650580 if utxo. is_receive && deposits_utxos. get ( & utxo. outpoint ) . is_none ( ) {
651581 new_unconf. insert (
@@ -850,9 +780,6 @@ impl BitcoinD {
850780 continue ;
851781 }
852782
853- // TODO: i think we can also filter out the entries *with* a "revault-somthing" label,
854- // but we need to be sure.
855-
856783 let spending_txid = transaction
857784 . get ( "txid" )
858785 . map ( |t| t. as_str ( ) )
@@ -1169,7 +1096,7 @@ pub struct ListSinceBlockTransaction {
11691096 pub outpoint : OutPoint ,
11701097 pub txo : TxOut ,
11711098 pub is_receive : bool ,
1172- pub label : Option < String > ,
1099+ pub wallet_descs : Vec < String > ,
11731100 pub confirmations : i32 ,
11741101 pub blockheight : Option < u32 > ,
11751102}
@@ -1225,19 +1152,31 @@ impl From<&Json> for ListSinceBlockTransaction {
12251152 . map ( |a| a. as_u64 ( ) )
12261153 . flatten ( )
12271154 . map ( |b| b as u32 ) ;
1228- let label = j
1229- . get ( "label" )
1230- . map ( |l| l. as_str ( ) )
1231- . flatten ( )
1232- . map ( |l| l. to_string ( ) ) ;
1155+ // FIXME: allocs
1156+ let wallet_descs = j
1157+ . get ( "wallet_descs" )
1158+ . map ( |l| {
1159+ l. as_array ( )
1160+ . expect (
1161+ "API break, 'listsinceblock' entry didn't contain a valid 'wallet_descs'." ,
1162+ )
1163+ . iter ( )
1164+ . map ( |desc| {
1165+ desc. as_str ( )
1166+ . expect ( "Invalid desc string in 'listsinceblock'." )
1167+ . to_string ( )
1168+ } )
1169+ . collect ( )
1170+ } )
1171+ . unwrap_or_else ( || Vec :: new ( ) ) ;
12331172
12341173 ListSinceBlockTransaction {
12351174 outpoint : OutPoint {
12361175 txid,
12371176 vout : vout as u32 , // Bitcoin makes this safe
12381177 } ,
12391178 is_receive,
1240- label ,
1179+ wallet_descs ,
12411180 txo : TxOut {
12421181 value,
12431182 script_pubkey,
0 commit comments