Skip to content

Commit 6de782b

Browse files
committed
rust: create_transaction: set used_utxos
1 parent 47478a4 commit 6de782b

File tree

1 file changed

+68
-5
lines changed

1 file changed

+68
-5
lines changed

subprojects/gdk_rust/gdk_electrum/src/account.rs

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ use gdk_common::be::{
2121
};
2222
use gdk_common::error::fn_err;
2323
use gdk_common::model::{
24-
AccountInfo, AddressAmount, AddressPointer, Balances, CreateTransaction, GetTransactionsOpt,
25-
SPVVerifyTxResult, TransactionMeta, UpdateAccountOpt, UtxoStrategy,
24+
parse_path, AccountInfo, AddressAmount, AddressPointer, Balances, CreateTransaction,
25+
GetTransactionsOpt, SPVVerifyTxResult, TransactionMeta, UnspentOutput, UpdateAccountOpt,
26+
UtxoStrategy,
2627
};
2728
use gdk_common::scripts::{p2pkh_script, p2shwpkh_script_sig, ScriptType};
2829
use gdk_common::util::is_confidential_txoutsecrets;
@@ -57,7 +58,7 @@ pub struct Account {
5758
/// thus at following logins it will be false.
5859
discovered: bool,
5960

60-
_path: DerivationPath,
61+
path: DerivationPath,
6162
}
6263

6364
/// Compare xpub ignoring the fingerprint (which computation might be skipped).
@@ -106,8 +107,7 @@ impl Account {
106107
chains,
107108
store,
108109
master_blinding,
109-
// currently unused, but seems useful to have around
110-
_path: path,
110+
path,
111111
discovered,
112112
})
113113
}
@@ -116,6 +116,16 @@ impl Account {
116116
self.account_num
117117
}
118118

119+
/// Get the full path from the master key to address index
120+
///
121+
/// // < full path >
122+
/// m / purpose' / coin_type ' / account' / change / address_index
123+
/// // < account path >
124+
///
125+
fn get_full_path(&self, account_path: &DerivationPath) -> DerivationPath {
126+
self.path.extend(account_path)
127+
}
128+
119129
pub fn info(&self) -> Result<AccountInfo, Error> {
120130
let settings = self.store.read()?.get_account_settings(self.account_num).cloned();
121131

@@ -298,6 +308,57 @@ impl Account {
298308
p2pkh_script(public_key).into()
299309
}
300310

311+
fn txo(&self, outpoint: &BEOutPoint) -> Result<UnspentOutput, Error> {
312+
let vout = outpoint.vout();
313+
let txid = outpoint.txid();
314+
315+
let store_read = self.store.read()?;
316+
let acc_store = store_read.account_cache(self.account_num)?;
317+
318+
let txe =
319+
acc_store.all_txs.get(&txid).ok_or_else(|| Error::TxNotFound(txid.to_string()))?;
320+
let tx = &txe.tx;
321+
let height = acc_store.heights.get(&txid).cloned().flatten().unwrap_or(0);
322+
let script_pubkey = tx.output_script(vout);
323+
let account_path: DerivationPath = acc_store
324+
.paths
325+
.get(&script_pubkey)
326+
.ok_or_else(|| Error::Generic("can't find derivation path".into()))?
327+
.clone();
328+
let (is_internal, pointer) = parse_path(&account_path)?;
329+
let satoshi = tx.output_value(vout, &acc_store.unblinded).unwrap_or_default();
330+
331+
Ok(UnspentOutput {
332+
address_type: self.script_type.to_string(),
333+
block_height: height,
334+
pointer: pointer,
335+
pt_idx: vout,
336+
txhash: txid.to_hex(),
337+
satoshi: satoshi,
338+
subaccount: self.account_num,
339+
is_internal: is_internal,
340+
confidential: tx.output_is_confidential(vout),
341+
scriptpubkey: tx.output_script(vout),
342+
sequence: None,
343+
script_code: self.script_code(&account_path).to_hex(),
344+
user_path: self.get_full_path(&account_path).into(),
345+
})
346+
}
347+
348+
pub fn used_utxos(&self, tx: &BETransaction) -> Result<Vec<UnspentOutput>, Error> {
349+
tx.previous_sequence_and_outpoints()
350+
.into_iter()
351+
.map(|(sequence, outpoint)| {
352+
self.txo(&outpoint)
353+
.map(|mut u| {
354+
u.sequence = Some(sequence);
355+
u
356+
})
357+
.map_err(|_| Error::Generic("missing inputs not supported yet".into()))
358+
})
359+
.collect()
360+
}
361+
301362
pub fn utxos(&self, num_confs: u32, confidential_utxos_only: bool) -> Result<Utxos, Error> {
302363
info!("start utxos");
303364
let store_read = self.store.read()?;
@@ -1181,6 +1242,7 @@ pub fn create_tx(
11811242
*v = v.abs();
11821243
}
11831244

1245+
let used_utxos = account.used_utxos(&tx)?;
11841246
let mut created_tx = TransactionMeta::new(
11851247
tx,
11861248
None,
@@ -1193,6 +1255,7 @@ pub fn create_tx(
11931255
false,
11941256
SPVVerifyTxResult::InProgress,
11951257
);
1258+
created_tx.used_utxos = used_utxos;
11961259
created_tx.changes_used = Some(changes.len() as u32);
11971260
created_tx.addressees_read_only = request.previous_transaction.is_some();
11981261
info!("returning: {:?}", created_tx);

0 commit comments

Comments
 (0)