@@ -15,24 +15,18 @@ use bdk::{
1515} ;
1616use jsonrpsee:: { core:: async_trait, proc_macros:: rpc, server:: Server , types:: ErrorObjectOwned } ;
1717use 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 } ;
3023use serde:: { Deserialize , Serialize } ;
3124use tokio:: {
3225 select,
3326 sync:: { broadcast, mpsc, oneshot, RwLock } ,
3427 task:: JoinSet ,
3528} ;
29+ use protocol:: validate:: TxChangeSet ;
3630use wallet:: {
3731 bdk_wallet as bdk, bdk_wallet:: template:: Bip86 , bitcoin:: hashes:: Hash , export:: WalletExport ,
3832 DoubleUtxo , SpacesWallet , WalletConfig , WalletDescriptors , WalletInfo ,
@@ -48,6 +42,7 @@ use crate::{
4842 WalletResponse ,
4943 } ,
5044} ;
45+ use crate :: checker:: TxChecker ;
5146
5247pub ( crate ) type Responder < T > = oneshot:: Sender < T > ;
5348
@@ -58,6 +53,10 @@ pub struct ServerInfo {
5853}
5954
6055pub enum ChainStateCommand {
56+ CheckPackage {
57+ txs : Vec < String > ,
58+ resp : Responder < anyhow:: Result < Vec < Option < TxChangeSet > > > > ,
59+ } ,
6160 GetTip {
6261 resp : Responder < anyhow:: Result < ChainAnchor > > ,
6362 } ,
@@ -117,6 +116,9 @@ pub trait Rpc {
117116 #[ method( name = "getspaceout" ) ]
118117 async fn get_spaceout ( & self , outpoint : OutPoint ) -> Result < Option < SpaceOut > , ErrorObjectOwned > ;
119118
119+ #[ method( name = "checkpackage" ) ]
120+ async fn check_package ( & self , txs : Vec < String > ) -> Result < Vec < Option < TxChangeSet > > , ErrorObjectOwned > ;
121+
120122 #[ method( name = "estimatebid" ) ]
121123 async fn estimate_bid ( & self , target : usize ) -> Result < u64 , ErrorObjectOwned > ;
122124
@@ -167,6 +169,7 @@ pub trait Rpc {
167169 wallet : & str ,
168170 txid : Txid ,
169171 fee_rate : FeeRate ,
172+ skip_tx_check : bool ,
170173 ) -> Result < Vec < TxResponse > , ErrorObjectOwned > ;
171174
172175 #[ method( name = "walletlisttransactions" ) ]
@@ -187,7 +190,7 @@ pub trait Rpc {
187190
188191 #[ method( name = "walletlistspaces" ) ]
189192 async fn wallet_list_spaces ( & self , wallet : & str )
190- -> Result < Vec < WalletOutput > , ErrorObjectOwned > ;
193+ -> Result < Vec < WalletOutput > , ErrorObjectOwned > ;
191194
192195 #[ method( name = "walletlistunspent" ) ]
193196 async fn wallet_list_unspent (
@@ -211,6 +214,7 @@ pub struct RpcWalletTxBuilder {
211214 pub dust : Option < Amount > ,
212215 pub force : bool ,
213216 pub confirmed_only : bool ,
217+ pub skip_tx_check : bool ,
214218}
215219
216220#[ derive( Clone , Serialize , Deserialize ) ]
@@ -617,6 +621,15 @@ impl RpcServer for RpcServerImpl {
617621 Ok ( spaceout)
618622 }
619623
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+
620633 async fn estimate_bid ( & self , target : usize ) -> Result < u64 , ErrorObjectOwned > {
621634 let info = self
622635 . store
@@ -731,10 +744,11 @@ impl RpcServer for RpcServerImpl {
731744 wallet : & str ,
732745 txid : Txid ,
733746 fee_rate : FeeRate ,
747+ skip_tx_check : bool
734748 ) -> Result < Vec < TxResponse > , ErrorObjectOwned > {
735749 self . wallet ( & wallet)
736750 . await ?
737- . send_fee_bump ( txid, fee_rate)
751+ . send_fee_bump ( txid, fee_rate, skip_tx_check )
738752 . await
739753 . map_err ( |error| ErrorObjectOwned :: owned ( -1 , error. to_string ( ) , None :: < String > ) )
740754 }
@@ -836,6 +850,7 @@ impl AsyncChainState {
836850 Ok ( None )
837851 }
838852
853+
839854 async fn get_indexed_block (
840855 index : & mut Option < LiveSnapshot > ,
841856 block_hash : & BlockHash ,
@@ -884,6 +899,22 @@ impl AsyncChainState {
884899 cmd : ChainStateCommand ,
885900 ) {
886901 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+ } ,
887918 ChainStateCommand :: GetTip { resp } => {
888919 let tip = chain_state. tip . read ( ) . expect ( "read meta" ) . clone ( ) ;
889920 _ = resp. send ( Ok ( tip) )
@@ -979,6 +1010,14 @@ impl AsyncChainState {
9791010 resp_rx. await ?
9801011 }
9811012
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+
9821021 pub async fn get_tip ( & self ) -> anyhow:: Result < ChainAnchor > {
9831022 let ( resp, resp_rx) = oneshot:: channel ( ) ;
9841023 self . sender . send ( ChainStateCommand :: GetTip { resp } ) . await ?;
0 commit comments