Skip to content

Commit 01d94a1

Browse files
committed
wallet: Enhance plan_input by including after + older
The idea is that if the local chain has surpassed the lock height needed to spend a utxo, then the wallet can respond accordingly with no interaction on the part of the user.
1 parent b14f663 commit 01d94a1

File tree

1 file changed

+35
-21
lines changed

1 file changed

+35
-21
lines changed

wallet/src/wallet/mod.rs

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use bitcoin::{
3737
absolute,
3838
consensus::encode::serialize,
3939
constants::genesis_block,
40-
psbt,
40+
psbt, relative,
4141
secp256k1::Secp256k1,
4242
sighash::{EcdsaSighashType, TapSighashType},
4343
transaction, Address, Amount, Block, BlockHash, FeeRate, Network, OutPoint, Psbt, ScriptBuf,
@@ -2793,42 +2793,56 @@ impl Wallet {
27932793
Ok((psbt, finalizer))
27942794
}
27952795

2796-
/// Plan the output with the available assets and return a new [`Input`].
2797-
fn plan_input(&self, output: &LocalOutput, assets: &Assets) -> Option<Input> {
2796+
/// Plan the output with the available assets and return a new [`Input`] if possible. See also
2797+
/// [`Self::try_plan`].
2798+
fn plan_input(&self, output: &LocalOutput, spend_assets: &Assets) -> Option<Input> {
27982799
let op = output.outpoint;
27992800
let txid = op.txid;
2800-
if let Some(plan) = self.try_plan(op, assets) {
2801-
let tx = self.indexed_graph.graph().get_tx(txid).unwrap();
2802-
return Some(
2803-
Input::from_prev_tx(
2804-
plan,
2805-
tx,
2806-
op.vout as usize,
2807-
status_from_position(output.chain_position),
2808-
)
2809-
.expect("invalid outpoint"),
2810-
);
2811-
}
28122801

2813-
None
2802+
// We want to afford the output with as many assets as we can. The plan
2803+
// will use only the ones needed to produce the minimum satisfaction.
2804+
let cur_height = self.latest_checkpoint().height();
2805+
let abs_locktime = spend_assets
2806+
.absolute_timelock
2807+
.unwrap_or(absolute::LockTime::from_consensus(cur_height));
2808+
2809+
let rel_locktime = spend_assets.relative_timelock.unwrap_or_else(|| {
2810+
let age = match output.chain_position.confirmation_height_upper_bound() {
2811+
Some(conf_height) => cur_height
2812+
.saturating_add(1)
2813+
.saturating_sub(conf_height)
2814+
.try_into()
2815+
.unwrap_or(u16::MAX),
2816+
None => 0,
2817+
};
2818+
relative::LockTime::from_height(age)
2819+
});
2820+
2821+
let mut assets = Assets::new();
2822+
assets.extend(spend_assets);
2823+
assets = assets.after(abs_locktime);
2824+
assets = assets.older(rel_locktime);
2825+
2826+
let plan = self.try_plan(op, &assets)?;
2827+
let tx = self.indexed_graph.graph().get_tx(txid)?;
2828+
let tx_status = status_from_position(output.chain_position);
2829+
2830+
Input::from_prev_tx(plan, tx, op.vout as usize, tx_status).ok()
28142831
}
28152832

28162833
/// Attempt to create a spending plan for the UTXO of the given `outpoint`
28172834
/// with the provided `assets`.
28182835
///
28192836
/// Return `None` if `outpoint` doesn't correspond to an indexed txout, or
28202837
/// if the assets are not sufficient to create a plan.
2821-
//
2822-
// TODO: This should internally set the after/older for `outpoint`
2823-
// based on the current height and age of the coin respectively.
28242838
fn try_plan(&self, outpoint: OutPoint, assets: &Assets) -> Option<Plan> {
28252839
let indexer = &self.indexed_graph.index;
28262840
let ((keychain, index), _) = indexer.txout(outpoint)?;
2827-
let desc = indexer
2841+
let def_desc = indexer
28282842
.get_descriptor(keychain)?
28292843
.at_derivation_index(index)
28302844
.expect("must be valid derivation index");
2831-
desc.plan(assets).ok()
2845+
def_desc.plan(assets).ok()
28322846
}
28332847
}
28342848

0 commit comments

Comments
 (0)