@@ -15,24 +15,18 @@ use bdk::{
15
15
} ;
16
16
use jsonrpsee:: { core:: async_trait, proc_macros:: rpc, server:: Server , types:: ErrorObjectOwned } ;
17
17
use log:: info;
18
- use protocol:: {
19
- bitcoin:: {
20
- bip32:: Xpriv ,
21
- Network :: { Regtest , Testnet } ,
22
- OutPoint ,
23
- } ,
24
- constants:: ChainAnchor ,
25
- hasher:: { BaseHash , KeyHasher , SpaceKey } ,
26
- prepare:: DataSource ,
27
- slabel:: SLabel ,
28
- FullSpaceOut , SpaceOut ,
29
- } ;
18
+ use protocol:: { bitcoin, bitcoin:: {
19
+ bip32:: Xpriv ,
20
+ Network :: { Regtest , Testnet } ,
21
+ OutPoint ,
22
+ } , constants:: ChainAnchor , hasher:: { BaseHash , KeyHasher , SpaceKey } , prepare:: DataSource , slabel:: SLabel , FullSpaceOut , SpaceOut } ;
30
23
use serde:: { Deserialize , Serialize } ;
31
24
use tokio:: {
32
25
select,
33
26
sync:: { broadcast, mpsc, oneshot, RwLock } ,
34
27
task:: JoinSet ,
35
28
} ;
29
+ use protocol:: validate:: TxChangeSet ;
36
30
use wallet:: {
37
31
bdk_wallet as bdk, bdk_wallet:: template:: Bip86 , bitcoin:: hashes:: Hash , export:: WalletExport ,
38
32
DoubleUtxo , SpacesWallet , WalletConfig , WalletDescriptors , WalletInfo ,
@@ -48,6 +42,7 @@ use crate::{
48
42
WalletResponse ,
49
43
} ,
50
44
} ;
45
+ use crate :: checker:: TxChecker ;
51
46
52
47
pub ( crate ) type Responder < T > = oneshot:: Sender < T > ;
53
48
@@ -58,6 +53,10 @@ pub struct ServerInfo {
58
53
}
59
54
60
55
pub enum ChainStateCommand {
56
+ CheckPackage {
57
+ txs : Vec < String > ,
58
+ resp : Responder < anyhow:: Result < Vec < Option < TxChangeSet > > > > ,
59
+ } ,
61
60
GetTip {
62
61
resp : Responder < anyhow:: Result < ChainAnchor > > ,
63
62
} ,
@@ -117,6 +116,9 @@ pub trait Rpc {
117
116
#[ method( name = "getspaceout" ) ]
118
117
async fn get_spaceout ( & self , outpoint : OutPoint ) -> Result < Option < SpaceOut > , ErrorObjectOwned > ;
119
118
119
+ #[ method( name = "checkpackage" ) ]
120
+ async fn check_package ( & self , txs : Vec < String > ) -> Result < Vec < Option < TxChangeSet > > , ErrorObjectOwned > ;
121
+
120
122
#[ method( name = "estimatebid" ) ]
121
123
async fn estimate_bid ( & self , target : usize ) -> Result < u64 , ErrorObjectOwned > ;
122
124
@@ -167,6 +169,7 @@ pub trait Rpc {
167
169
wallet : & str ,
168
170
txid : Txid ,
169
171
fee_rate : FeeRate ,
172
+ skip_tx_check : bool ,
170
173
) -> Result < Vec < TxResponse > , ErrorObjectOwned > ;
171
174
172
175
#[ method( name = "walletlisttransactions" ) ]
@@ -187,7 +190,7 @@ pub trait Rpc {
187
190
188
191
#[ method( name = "walletlistspaces" ) ]
189
192
async fn wallet_list_spaces ( & self , wallet : & str )
190
- -> Result < Vec < WalletOutput > , ErrorObjectOwned > ;
193
+ -> Result < Vec < WalletOutput > , ErrorObjectOwned > ;
191
194
192
195
#[ method( name = "walletlistunspent" ) ]
193
196
async fn wallet_list_unspent (
@@ -211,6 +214,7 @@ pub struct RpcWalletTxBuilder {
211
214
pub dust : Option < Amount > ,
212
215
pub force : bool ,
213
216
pub confirmed_only : bool ,
217
+ pub skip_tx_check : bool ,
214
218
}
215
219
216
220
#[ derive( Clone , Serialize , Deserialize ) ]
@@ -617,6 +621,15 @@ impl RpcServer for RpcServerImpl {
617
621
Ok ( spaceout)
618
622
}
619
623
624
+ async fn check_package ( & self , txs : Vec < String > ) -> Result < Vec < Option < TxChangeSet > > , ErrorObjectOwned > {
625
+ let spaceout = self
626
+ . store
627
+ . check_package ( txs)
628
+ . await
629
+ . map_err ( |error| ErrorObjectOwned :: owned ( -1 , error. to_string ( ) , None :: < String > ) ) ?;
630
+ Ok ( spaceout)
631
+ }
632
+
620
633
async fn estimate_bid ( & self , target : usize ) -> Result < u64 , ErrorObjectOwned > {
621
634
let info = self
622
635
. store
@@ -731,10 +744,11 @@ impl RpcServer for RpcServerImpl {
731
744
wallet : & str ,
732
745
txid : Txid ,
733
746
fee_rate : FeeRate ,
747
+ skip_tx_check : bool
734
748
) -> Result < Vec < TxResponse > , ErrorObjectOwned > {
735
749
self . wallet ( & wallet)
736
750
. await ?
737
- . send_fee_bump ( txid, fee_rate)
751
+ . send_fee_bump ( txid, fee_rate, skip_tx_check )
738
752
. await
739
753
. map_err ( |error| ErrorObjectOwned :: owned ( -1 , error. to_string ( ) , None :: < String > ) )
740
754
}
@@ -836,6 +850,7 @@ impl AsyncChainState {
836
850
Ok ( None )
837
851
}
838
852
853
+
839
854
async fn get_indexed_block (
840
855
index : & mut Option < LiveSnapshot > ,
841
856
block_hash : & BlockHash ,
@@ -884,6 +899,22 @@ impl AsyncChainState {
884
899
cmd : ChainStateCommand ,
885
900
) {
886
901
match cmd {
902
+ ChainStateCommand :: CheckPackage { txs : raw_txs, resp } => {
903
+ let mut txs = Vec :: with_capacity ( raw_txs. len ( ) ) ;
904
+ for raw_tx in raw_txs {
905
+ let tx = bitcoin:: consensus:: encode:: deserialize_hex ( & raw_tx) ;
906
+ if tx. is_err ( ) {
907
+ let _ = resp. send ( Err ( anyhow ! ( "could not decode hex transaction" ) ) ) ;
908
+ return ;
909
+ }
910
+ txs. push ( tx. unwrap ( ) ) ;
911
+ }
912
+
913
+ let tip = chain_state. tip . read ( ) . expect ( "read meta" ) . clone ( ) ;
914
+ let mut emulator = TxChecker :: new ( chain_state) ;
915
+ let result = emulator. apply_package ( tip. height +1 , txs) ;
916
+ let _ = resp. send ( result) ;
917
+ } ,
887
918
ChainStateCommand :: GetTip { resp } => {
888
919
let tip = chain_state. tip . read ( ) . expect ( "read meta" ) . clone ( ) ;
889
920
_ = resp. send ( Ok ( tip) )
@@ -979,6 +1010,14 @@ impl AsyncChainState {
979
1010
resp_rx. await ?
980
1011
}
981
1012
1013
+ pub async fn check_package ( & self , txs : Vec < String > ) -> anyhow:: Result < Vec < Option < TxChangeSet > > > {
1014
+ let ( resp, resp_rx) = oneshot:: channel ( ) ;
1015
+ self . sender
1016
+ . send ( ChainStateCommand :: CheckPackage { txs, resp } )
1017
+ . await ?;
1018
+ resp_rx. await ?
1019
+ }
1020
+
982
1021
pub async fn get_tip ( & self ) -> anyhow:: Result < ChainAnchor > {
983
1022
let ( resp, resp_rx) = oneshot:: channel ( ) ;
984
1023
self . sender . send ( ChainStateCommand :: GetTip { resp } ) . await ?;
0 commit comments