Merge #938: gui: use descriptor method to detect psbt change outputs
366e9b7d49eb7261df4801534224cb737a49149f gui: use descriptor method to detect psbt change outputs (edouardparis) Pull request description: This commit also fix handling of create_spend result while updating liana:master close #841 ACKs for top commit: edouardparis: Self-ACK 366e9b7d49eb7261df4801534224cb737a49149f Tree-SHA512: 5316e610ec6fe1c09447329c031a52710fa7802c0135cc2e386d9926d5f189f1b381596b1f5b081beb2904341d4d7468fa1b4148e9fc49644670e5d8335ca015
This commit is contained in:
commit
a34070dce1
4
gui/Cargo.lock
generated
4
gui/Cargo.lock
generated
@ -2668,7 +2668,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "liana"
|
name = "liana"
|
||||||
version = "4.0.0"
|
version = "4.0.0"
|
||||||
source = "git+https://github.com/wizardsardine/liana?branch=master#7ca6cc8dfa8dfdde805dc34fa408337f1a3291e2"
|
source = "git+https://github.com/wizardsardine/liana?branch=master#5a56fdb108351d0a6877a11a1dec7a27a3b0928f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bdk_coin_select",
|
"bdk_coin_select",
|
||||||
@ -4270,7 +4270,7 @@ version = "0.28.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f622567e3b4b38154fb8190bcf6b160d7a4301d70595a49195b48c116007a27"
|
checksum = "3f622567e3b4b38154fb8190bcf6b160d7a4301d70595a49195b48c116007a27"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitcoin_hashes 0.13.0",
|
"bitcoin_hashes 0.12.0",
|
||||||
"secp256k1-sys",
|
"secp256k1-sys",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -4,7 +4,10 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use iced::Command;
|
use iced::Command;
|
||||||
|
|
||||||
use liana::miniscript::bitcoin::bip32::{DerivationPath, Fingerprint};
|
use liana::miniscript::bitcoin::{
|
||||||
|
bip32::{DerivationPath, Fingerprint},
|
||||||
|
secp256k1,
|
||||||
|
};
|
||||||
use liana_ui::{component::form, widget::Element};
|
use liana_ui::{component::form, widget::Element};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -162,7 +165,14 @@ impl State for RecoveryPanel {
|
|||||||
.any(|input| input.previous_output == coin.outpoint)
|
.any(|input| input.previous_output == coin.outpoint)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
Ok(SpendTx::new(None, psbt, coins, &desc, network))
|
Ok(SpendTx::new(
|
||||||
|
None,
|
||||||
|
psbt,
|
||||||
|
coins,
|
||||||
|
&desc,
|
||||||
|
&secp256k1::Secp256k1::verification_only(),
|
||||||
|
network,
|
||||||
|
))
|
||||||
},
|
},
|
||||||
Message::Recovery,
|
Message::Recovery,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -19,7 +19,7 @@ use liana_ui::{component::form, widget::Element};
|
|||||||
use crate::{
|
use crate::{
|
||||||
app::{cache::Cache, error::Error, message::Message, state::psbt, view, wallet::Wallet},
|
app::{cache::Cache, error::Error, message::Message, state::psbt, view, wallet::Wallet},
|
||||||
daemon::{
|
daemon::{
|
||||||
model::{remaining_sequence, Coin, SpendTx},
|
model::{remaining_sequence, Coin, CreateSpendResult, SpendTx},
|
||||||
Daemon,
|
Daemon,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -382,8 +382,16 @@ impl Step for DefineSpend {
|
|||||||
async move {
|
async move {
|
||||||
daemon
|
daemon
|
||||||
.create_spend_tx(&inputs, &outputs, feerate_vb)
|
.create_spend_tx(&inputs, &outputs, feerate_vb)
|
||||||
.map(|res| res.psbt)
|
|
||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
|
.and_then(|res| match res {
|
||||||
|
CreateSpendResult::Success { psbt, .. } => Ok(psbt),
|
||||||
|
CreateSpendResult::InsufficientFunds { missing } => {
|
||||||
|
Err(SpendCreationError::CoinSelection(
|
||||||
|
liana::spend::InsufficientFunds { missing },
|
||||||
|
)
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
Message::Psbt,
|
Message::Psbt,
|
||||||
);
|
);
|
||||||
@ -576,6 +584,7 @@ impl Recipient {
|
|||||||
pub struct SaveSpend {
|
pub struct SaveSpend {
|
||||||
wallet: Arc<Wallet>,
|
wallet: Arc<Wallet>,
|
||||||
spend: Option<psbt::PsbtState>,
|
spend: Option<psbt::PsbtState>,
|
||||||
|
curve: secp256k1::Secp256k1<secp256k1::VerifyOnly>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SaveSpend {
|
impl SaveSpend {
|
||||||
@ -583,6 +592,7 @@ impl SaveSpend {
|
|||||||
Self {
|
Self {
|
||||||
wallet,
|
wallet,
|
||||||
spend: None,
|
spend: None,
|
||||||
|
curve: secp256k1::Secp256k1::verification_only(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -595,6 +605,7 @@ impl Step for SaveSpend {
|
|||||||
psbt,
|
psbt,
|
||||||
draft.inputs.clone(),
|
draft.inputs.clone(),
|
||||||
&self.wallet.main_descriptor,
|
&self.wallet.main_descriptor,
|
||||||
|
&self.curve,
|
||||||
draft.network,
|
draft.network,
|
||||||
);
|
);
|
||||||
tx.labels = draft.labels.clone();
|
tx.labels = draft.labels.clone();
|
||||||
|
|||||||
@ -5,7 +5,10 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use iced::Command;
|
use iced::Command;
|
||||||
use liana::{miniscript::bitcoin::Txid, spend::MAX_FEERATE};
|
use liana::{
|
||||||
|
miniscript::bitcoin::Txid,
|
||||||
|
spend::{SpendCreationError, MAX_FEERATE},
|
||||||
|
};
|
||||||
use liana_ui::{
|
use liana_ui::{
|
||||||
component::{form, modal::Modal},
|
component::{form, modal::Modal},
|
||||||
widget::*,
|
widget::*,
|
||||||
@ -20,7 +23,7 @@ use crate::app::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::daemon::{
|
use crate::daemon::{
|
||||||
model::{HistoryTransaction, Labelled},
|
model::{CreateSpendResult, HistoryTransaction, Labelled},
|
||||||
Daemon,
|
Daemon,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -302,7 +305,18 @@ impl CreateRbfModal {
|
|||||||
self.warning = None;
|
self.warning = None;
|
||||||
|
|
||||||
let psbt = match daemon.rbf_psbt(&self.txid, self.is_cancel, self.feerate_vb) {
|
let psbt = match daemon.rbf_psbt(&self.txid, self.is_cancel, self.feerate_vb) {
|
||||||
Ok(res) => res.psbt,
|
Ok(res) => match res {
|
||||||
|
CreateSpendResult::Success { psbt, .. } => psbt,
|
||||||
|
CreateSpendResult::InsufficientFunds { missing } => {
|
||||||
|
self.warning = Some(
|
||||||
|
SpendCreationError::CoinSelection(
|
||||||
|
liana::spend::InsufficientFunds { missing },
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
return Command::none();
|
||||||
|
}
|
||||||
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.warning = Some(e.into());
|
self.warning = Some(e.into());
|
||||||
return Command::none();
|
return Command::none();
|
||||||
|
|||||||
@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet};
|
|||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
use liana::commands::CreateRecoveryResult;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
@ -154,7 +155,7 @@ impl<C: Client + Debug> Daemon for Lianad<C> {
|
|||||||
feerate_vb: u64,
|
feerate_vb: u64,
|
||||||
sequence: Option<u16>,
|
sequence: Option<u16>,
|
||||||
) -> Result<Psbt, DaemonError> {
|
) -> Result<Psbt, DaemonError> {
|
||||||
let res: CreateSpendResult = self.call(
|
let res: CreateRecoveryResult = self.call(
|
||||||
"createrecovery",
|
"createrecovery",
|
||||||
Some(vec![json!(address), json!(feerate_vb), json!(sequence)]),
|
Some(vec![json!(address), json!(feerate_vb), json!(sequence)]),
|
||||||
)?;
|
)?;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ use std::iter::FromIterator;
|
|||||||
use liana::{
|
use liana::{
|
||||||
commands::LabelItem,
|
commands::LabelItem,
|
||||||
config::Config,
|
config::Config,
|
||||||
miniscript::bitcoin::{address, psbt::Psbt, Address, OutPoint, Txid},
|
miniscript::bitcoin::{address, psbt::Psbt, secp256k1, Address, OutPoint, Txid},
|
||||||
StartupError,
|
StartupError,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -102,6 +102,7 @@ pub trait Daemon: Debug {
|
|||||||
let info = self.get_info()?;
|
let info = self.get_info()?;
|
||||||
let coins = self.list_coins()?.coins;
|
let coins = self.list_coins()?.coins;
|
||||||
let mut spend_txs = Vec::new();
|
let mut spend_txs = Vec::new();
|
||||||
|
let curve = secp256k1::Secp256k1::verification_only();
|
||||||
for tx in self.list_spend_txs()?.spend_txs {
|
for tx in self.list_spend_txs()?.spend_txs {
|
||||||
if let Some(txids) = txids {
|
if let Some(txids) = txids {
|
||||||
if !txids.contains(&tx.psbt.unsigned_tx.txid()) {
|
if !txids.contains(&tx.psbt.unsigned_tx.txid()) {
|
||||||
@ -125,6 +126,7 @@ pub trait Daemon: Debug {
|
|||||||
tx.psbt,
|
tx.psbt,
|
||||||
coins,
|
coins,
|
||||||
&info.descriptors.main,
|
&info.descriptors.main,
|
||||||
|
&curve,
|
||||||
info.network,
|
info.network,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ pub use liana::{
|
|||||||
miniscript::bitcoin::{
|
miniscript::bitcoin::{
|
||||||
bip32::{DerivationPath, Fingerprint},
|
bip32::{DerivationPath, Fingerprint},
|
||||||
psbt::Psbt,
|
psbt::Psbt,
|
||||||
Address, Amount, Network, OutPoint, Transaction, Txid,
|
secp256k1, Address, Amount, Network, OutPoint, Transaction, Txid,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -61,15 +61,19 @@ impl SpendTx {
|
|||||||
psbt: Psbt,
|
psbt: Psbt,
|
||||||
coins: Vec<Coin>,
|
coins: Vec<Coin>,
|
||||||
desc: &LianaDescriptor,
|
desc: &LianaDescriptor,
|
||||||
|
secp: &secp256k1::Secp256k1<impl secp256k1::Verification>,
|
||||||
network: Network,
|
network: Network,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let max_vbytes = desc.unsigned_tx_max_vbytes(&psbt.unsigned_tx);
|
let max_vbytes = desc.unsigned_tx_max_vbytes(&psbt.unsigned_tx);
|
||||||
let mut change_indexes = Vec::new();
|
let change_indexes: Vec<usize> = desc
|
||||||
|
.change_indexes(&psbt, secp)
|
||||||
|
.into_iter()
|
||||||
|
.map(|c| c.index())
|
||||||
|
.collect();
|
||||||
let (change_amount, spend_amount) = psbt.unsigned_tx.output.iter().enumerate().fold(
|
let (change_amount, spend_amount) = psbt.unsigned_tx.output.iter().enumerate().fold(
|
||||||
(Amount::from_sat(0), Amount::from_sat(0)),
|
(Amount::from_sat(0), Amount::from_sat(0)),
|
||||||
|(change, spend), (i, output)| {
|
|(change, spend), (i, output)| {
|
||||||
if !psbt.outputs[i].bip32_derivation.is_empty() {
|
if change_indexes.contains(&i) {
|
||||||
change_indexes.push(i);
|
|
||||||
(change + output.value, spend)
|
(change + output.value, spend)
|
||||||
} else {
|
} else {
|
||||||
(change, spend + output.value)
|
(change, spend + output.value)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user