@@ -906,11 +906,39 @@ pub fn discover_account(
906
906
Ok ( false )
907
907
}
908
908
909
+ /// Populate `derivation_path` and `scriptpubkey` in `UnspentOutput` by looking in our internal
910
+ /// cache by provided `subaccount`, `txid` and `pt_idx` (vout) and return an error if not present.
911
+ /// This allows to have this data if missing, but also avoid trusting the user input for this fields.
912
+ pub fn populate_unspent_from_db (
913
+ account : & Account ,
914
+ request : & mut CreateTransaction ,
915
+ ) -> Result < ( ) , Error > {
916
+ let store = account. store . read ( ) ?;
917
+
918
+ for u in request. utxos . 0 . values_mut ( ) . flat_map ( |e| e. iter_mut ( ) ) {
919
+ let cache = store. account_cache ( u. subaccount ) ?;
920
+ let txid = BETxid :: from_hex ( & u. txhash , account. network . id ( ) ) ?;
921
+ let tx_entry = cache. all_txs . get ( & txid) . ok_or_else ( || Error :: TxNotFound ( txid) ) ?;
922
+ let tx = & tx_entry. tx ;
923
+ let vout = u. pt_idx ;
924
+ if ( vout as usize ) >= tx. output_len ( ) {
925
+ return Err ( Error :: Generic ( "vout greater or equal number of outputs" . into ( ) ) ) ;
926
+ }
927
+ let script_pubkey = tx. output_script ( vout) ;
928
+ let derivation_path =
929
+ cache. paths . get ( & script_pubkey) . ok_or_else ( || Error :: ScriptPubkeyNotFound ) ?;
930
+ u. user_path = account. get_full_path ( derivation_path) . into ( ) ;
931
+ u. scriptpubkey = script_pubkey;
932
+ }
933
+ Ok ( ( ) )
934
+ }
935
+
909
936
#[ allow( clippy:: cognitive_complexity) ]
910
937
pub fn create_tx (
911
938
account : & Account ,
912
939
request : & mut CreateTransaction ,
913
940
) -> Result < TransactionMeta , Error > {
941
+ let _ = populate_unspent_from_db ( account, request) ;
914
942
info ! ( "create_tx {:?}" , request) ;
915
943
916
944
let network = & account. network ;
0 commit comments