Skip to content

Commit f433bbc

Browse files
committed
Merge #350: app + dummysigner: handle multi cancel derivation and signature
5314664 dummysigner: bump revault_tx and change api (edouard) 712a102 app: handle multiple cancel txs (edouard) ae1cccd bump revaultd (edouard) Pull request description: based on revault/revaultd#393 ACKs for top commit: edouardparis: ACK 5314664 Tree-SHA512: 30adc9198a8faf7ff0c13e9b0ca714a23252c847c93b5718cb916366eed1745ad1366575ba2624a1833ee0029d1e79f83d3ba937f1d9756fc234e19986de2930
2 parents 60146fd + 5314664 commit f433bbc

File tree

19 files changed

+190
-89
lines changed

19 files changed

+190
-89
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ path = "src/main.rs"
2121

2222
[dependencies]
2323
bitcoin = { version = "0.27", features = ["base64", "use-serde"] }
24-
revaultd = { git = "https://github.com/revault/revaultd", branch = "master", default-features = false}
24+
revaultd = { git = "https://github.com/revault/revaultd", default-features = false}
2525
backtrace = "0.3"
2626

2727
iced = { version = "0.4", default-features= false, features = ["tokio", "wgpu", "svg", "qr_code"] }

contrib/tools/dummysigner/Cargo.lock

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/tools/dummysigner/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ edition = "2018"
99
[workspace]
1010

1111
[dependencies]
12-
revault_tx = { version = "0.4.0", features = ["use-serde"] }
12+
revault_tx = { git = "https://github.com/revault/revault_tx", features = ["use-serde"] }
1313

1414
base64 = "0.13.0"
1515
iced = {version = "0.3", default-features = false, features = ["wgpu", "tokio"]}

contrib/tools/dummysigner/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ If the signature request was refused the response looks like:
8484

8585
```json
8686
{
87-
"cancel_tx": "<base64 encoded psbt>",
87+
"cancel_txs": ["<base64 encoded psbt>"],
8888
"emergency_tx": "<base64 encoded psbt>",
8989
"emergency_unvault_tx": "<base64 encoded psbt>"
9090
}
@@ -94,7 +94,7 @@ If the signature request was refused the response looks like:
9494

9595
```json
9696
{
97-
"cancel_tx": "<base64 encoded psbt>",
97+
"cancel_tx": ["<base64 encoded psbt>"],
9898
"emergency_tx": "<base64 encoded psbt>",
9999
"emergency_unvault_tx": "<base64 encoded psbt>"
100100
}
@@ -124,7 +124,7 @@ This method requires the descriptors and the emergency address.
124124
```json
125125
[
126126
{
127-
"cancel_tx": "<base64 encoded psbt>",
127+
"cancel_txs": ["<base64 encoded psbt>"],
128128
"emergency_tx": "<base64 encoded psbt>",
129129
"emergency_unvault_tx": "<base64 encoded psbt>"
130130
},

contrib/tools/dummysigner/src/api.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ pub struct DelegateBatch {
2727

2828
#[derive(Debug, Clone, Serialize, Deserialize)]
2929
pub struct RevocationTransactions {
30-
#[serde(with = "bitcoin_psbt")]
31-
pub cancel_tx: PartiallySignedTransaction,
30+
#[serde(with = "bitcoin_psbt_array")]
31+
pub cancel_txs: [PartiallySignedTransaction; 5],
3232

3333
#[serde(with = "bitcoin_psbt")]
3434
pub emergency_tx: PartiallySignedTransaction,
@@ -121,3 +121,41 @@ mod bitcoin_psbt {
121121
serializer.serialize_str(&base64::encode(encode::serialize(&psbt)))
122122
}
123123
}
124+
125+
mod bitcoin_psbt_array {
126+
use revault_tx::bitcoin::{consensus::encode, util::psbt::PartiallySignedTransaction as Psbt};
127+
use serde::{self, ser::SerializeSeq, Deserialize, Deserializer, Serializer};
128+
129+
pub fn deserialize<'de, D>(deserializer: D) -> Result<[Psbt; 5], D::Error>
130+
where
131+
D: Deserializer<'de>,
132+
{
133+
let array: [String; 5] = Deserialize::deserialize(deserializer)?;
134+
let to_psbt = |s: &str| -> Result<Psbt, D::Error> {
135+
let bytes: Vec<u8> = base64::decode(s).map_err(serde::de::Error::custom)?;
136+
encode::deserialize(&bytes).map_err(serde::de::Error::custom)
137+
};
138+
Ok([
139+
to_psbt(&array[0])?,
140+
to_psbt(&array[1])?,
141+
to_psbt(&array[2])?,
142+
to_psbt(&array[3])?,
143+
to_psbt(&array[4])?,
144+
])
145+
}
146+
147+
pub fn serialize<'se, S>(psbts: &[Psbt; 5], serializer: S) -> Result<S::Ok, S::Error>
148+
where
149+
S: Serializer,
150+
{
151+
let array: Vec<String> = psbts
152+
.iter()
153+
.map(|psbt| base64::encode(encode::serialize(&psbt)))
154+
.collect();
155+
let mut seq = serializer.serialize_seq(Some(array.len()))?;
156+
for element in array {
157+
seq.serialize_element(&element)?;
158+
}
159+
seq.end()
160+
}
161+
}

contrib/tools/dummysigner/src/app.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,9 @@ impl Application for App {
187187
self.signer
188188
.sign_psbt(&selected_keys, &mut target.emergency_unvault_tx)
189189
.unwrap();
190-
self.signer
191-
.sign_psbt(&selected_keys, &mut target.cancel_tx)
192-
.unwrap();
190+
for cancel_tx in &mut target.cancel_txs {
191+
self.signer.sign_psbt(&selected_keys, cancel_tx).unwrap();
192+
}
193193
*signed = true;
194194
return Command::perform(
195195
server::respond(writer.clone(), json!(target)),
@@ -212,9 +212,9 @@ impl Application for App {
212212
.sign_psbt(&selected_keys, &mut revocation_txs.emergency_tx)
213213
.unwrap();
214214

215-
self.signer
216-
.sign_psbt(&selected_keys, &mut revocation_txs.cancel_tx)
217-
.unwrap();
215+
for cancel_tx in &mut revocation_txs.cancel_txs {
216+
self.signer.sign_psbt(&selected_keys, cancel_tx).unwrap();
217+
}
218218

219219
self.signer
220220
.sign_psbt(
@@ -443,7 +443,7 @@ impl Method {
443443
)
444444
.unwrap();
445445
api::RevocationTransactions {
446-
cancel_tx: txs.cancel_tx,
446+
cancel_txs: txs.cancel_txs,
447447
emergency_unvault_tx: txs.emergency_unvault_tx,
448448
emergency_tx: txs.emergency_tx,
449449
}

contrib/tools/dummysigner/src/sign.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,21 +135,27 @@ impl Signer {
135135
.emergency_address
136136
.as_ref()
137137
.ok_or(Error("Wallet does not have emergency_address".to_string()))?;
138-
let (_, cancel_tx, emergency_tx, emergency_unvault_tx) = transaction_chain(
138+
let (_, cancel_txs, emergency_tx, emergency_unvault_tx) = transaction_chain(
139139
outpoint,
140140
amount,
141141
&descriptors.deposit_descriptor,
142142
&descriptors.unvault_descriptor,
143143
&descriptors.cpfp_descriptor,
144144
derivation_index,
145145
emer_address.clone(),
146-
0,
147146
&self.curve,
148147
)
149148
.map_err(|e| Error(e.to_string()))?;
149+
let cancel_txs = cancel_txs.all_feerates();
150150

151151
Ok(RevocationTransactions {
152-
cancel_tx: cancel_tx.into_psbt(),
152+
cancel_txs: [
153+
cancel_txs[0].psbt().clone(),
154+
cancel_txs[1].psbt().clone(),
155+
cancel_txs[2].psbt().clone(),
156+
cancel_txs[3].psbt().clone(),
157+
cancel_txs[4].psbt().clone(),
158+
],
153159
emergency_tx: emergency_tx.into_psbt(),
154160
emergency_unvault_tx: emergency_unvault_tx.into_psbt(),
155161
})
@@ -179,15 +185,15 @@ impl Signer {
179185
.derive(derivation_index, &self.curve);
180186

181187
let unvault_tx =
182-
UnvaultTransaction::new(deposit_txin, &unvault_descriptor, &cpfp_descriptor, 0)
188+
UnvaultTransaction::new(deposit_txin, &unvault_descriptor, &cpfp_descriptor)
183189
.map_err(|e| Error(e.to_string()))?;
184190

185191
Ok(unvault_tx.into_psbt())
186192
}
187193
}
188194

189195
pub struct RevocationTransactions {
190-
pub cancel_tx: PartiallySignedTransaction,
196+
pub cancel_txs: [PartiallySignedTransaction; 5],
191197
pub emergency_tx: PartiallySignedTransaction,
192198
pub emergency_unvault_tx: PartiallySignedTransaction,
193199
}
@@ -226,16 +232,16 @@ mod tests {
226232
.unwrap();
227233

228234
assert_eq!(
229-
base64::encode(encode::serialize(&revocation_txs.cancel_tx)).to_string(),
230-
"cHNidP8BAF4CAAAAATdzv51EXeeNc1fv6E852OhRxc67KNaWd+BrA3qN1a/1AAAAAAD9////ARRLJgcAAAAAIgAgdfJpF3TIFneDGEawKCIA4oiyxZcQtY90MYPUklUH28UAAAAAAAEBK7iGJgcAAAAAIgAgSOjPZes2prPdrcgiv+IG1sjXyTCc4KDr9+C9F+xk6LwBAwSBAAAAAQVhIQICkzqxA36tCqSnhYxtSdZwXh+zvF9msAkYr3ufAOzVJqxRh2R2qRRyqV8ir5obrrhS+alScvjCHZjyZIisa3apFLbJrbicjJNybIPiobXZR4nXe5VhiKxsk1KHZ1iyaCIGAgKTOrEDfq0KpKeFjG1J1nBeH7O8X2awCRive58A7NUmCCUdYAkAAAAAIgYCWC3tv0T0ZWTl2M2wZ1NtYOvjTNHRgBz/Ubv516wom0MI1n1/6QAAAAAiBgNHBN7LVbWqiP/R710GNmJIwTFOGWVRE2/xTquLukpJDghyqV8iAAAAAAAiAgJYLe2/RPRlZOXYzbBnU21g6+NM0dGAHP9Ru/nXrCibQwjWfX/pAAAAACICA0cE3stVtaqI/9HvXQY2YkjBMU4ZZVETb/FOq4u6SkkOCHKpXyIAAAAAAA=="
235+
base64::encode(encode::serialize(&revocation_txs.cancel_txs[0])).to_string(),
236+
"cHNidP8BAF4CAAAAATdzv51EXeeNc1fv6E852OhRxc67KNaWd+BrA3qN1a/1AAAAAAD9////ASp5JgcAAAAAIgAgdfJpF3TIFneDGEawKCIA4oiyxZcQtY90MYPUklUH28UAAAAAAAEBK7iGJgcAAAAAIgAgSOjPZes2prPdrcgiv+IG1sjXyTCc4KDr9+C9F+xk6LwBBWEhAgKTOrEDfq0KpKeFjG1J1nBeH7O8X2awCRive58A7NUmrFGHZHapFHKpXyKvmhuuuFL5qVJy+MIdmPJkiKxrdqkUtsmtuJyMk3Jsg+KhtdlHidd7lWGIrGyTUodnWLJoIgYCApM6sQN+rQqkp4WMbUnWcF4fs7xfZrAJGK97nwDs1SYIJR1gCQAAAAAiBgJYLe2/RPRlZOXYzbBnU21g6+NM0dGAHP9Ru/nXrCibQwjWfX/pAAAAACIGA0cE3stVtaqI/9HvXQY2YkjBMU4ZZVETb/FOq4u6SkkOCHKpXyIAAAAAACICAlgt7b9E9GVk5djNsGdTbWDr40zR0YAc/1G7+desKJtDCNZ9f+kAAAAAIgIDRwTey1W1qoj/0e9dBjZiSMExThllURNv8U6ri7pKSQ4IcqlfIgAAAAAA"
231237
);
232238
assert_eq!(
233239
base64::encode(encode::serialize(&revocation_txs.emergency_tx)).to_string(),
234-
"cHNidP8BAF4CAAAAAUeuD/NEqc88sk3DoBrKoVKjXbN2xW8Jr/4GO5q87JqJAQAAAAD9////ATheJgcAAAAAIgAgy7Co1PHzwoce0hHQR5RHMS72lSZudTF3bYrNgqLbkDYAAAAAAAEBKwAOJwcAAAAAIgAgdfJpF3TIFneDGEawKCIA4oiyxZcQtY90MYPUklUH28UBAwSBAAAAAQVHUiECWC3tv0T0ZWTl2M2wZ1NtYOvjTNHRgBz/Ubv516wom0MhA0cE3stVtaqI/9HvXQY2YkjBMU4ZZVETb/FOq4u6SkkOUq4iBgJYLe2/RPRlZOXYzbBnU21g6+NM0dGAHP9Ru/nXrCibQwjWfX/pAAAAACIGA0cE3stVtaqI/9HvXQY2YkjBMU4ZZVETb/FOq4u6SkkOCHKpXyIAAAAAAAA="
240+
"cHNidP8BAF4CAAAAAUeuD/NEqc88sk3DoBrKoVKjXbN2xW8Jr/4GO5q87JqJAQAAAAD9////ARDEJAcAAAAAIgAgy7Co1PHzwoce0hHQR5RHMS72lSZudTF3bYrNgqLbkDYAAAAAAAEBKwAOJwcAAAAAIgAgdfJpF3TIFneDGEawKCIA4oiyxZcQtY90MYPUklUH28UBBUdSIQJYLe2/RPRlZOXYzbBnU21g6+NM0dGAHP9Ru/nXrCibQyEDRwTey1W1qoj/0e9dBjZiSMExThllURNv8U6ri7pKSQ5SriIGAlgt7b9E9GVk5djNsGdTbWDr40zR0YAc/1G7+desKJtDCNZ9f+kAAAAAIgYDRwTey1W1qoj/0e9dBjZiSMExThllURNv8U6ri7pKSQ4IcqlfIgAAAAAAAA=="
235241
);
236242
assert_eq!(
237243
base64::encode(encode::serialize(&revocation_txs.emergency_unvault_tx)).to_string(),
238-
"cHNidP8BAF4CAAAAATdzv51EXeeNc1fv6E852OhRxc67KNaWd+BrA3qN1a/1AAAAAAD9////AWa7JQcAAAAAIgAgy7Co1PHzwoce0hHQR5RHMS72lSZudTF3bYrNgqLbkDYAAAAAAAEBK7iGJgcAAAAAIgAgSOjPZes2prPdrcgiv+IG1sjXyTCc4KDr9+C9F+xk6LwBAwSBAAAAAQVhIQICkzqxA36tCqSnhYxtSdZwXh+zvF9msAkYr3ufAOzVJqxRh2R2qRRyqV8ir5obrrhS+alScvjCHZjyZIisa3apFLbJrbicjJNybIPiobXZR4nXe5VhiKxsk1KHZ1iyaCIGAgKTOrEDfq0KpKeFjG1J1nBeH7O8X2awCRive58A7NUmCCUdYAkAAAAAIgYCWC3tv0T0ZWTl2M2wZ1NtYOvjTNHRgBz/Ubv516wom0MI1n1/6QAAAAAiBgNHBN7LVbWqiP/R710GNmJIwTFOGWVRE2/xTquLukpJDghyqV8iAAAAAAAA"
244+
"cHNidP8BAF4CAAAAATdzv51EXeeNc1fv6E852OhRxc67KNaWd+BrA3qN1a/1AAAAAAD9////AfzgIwcAAAAAIgAgy7Co1PHzwoce0hHQR5RHMS72lSZudTF3bYrNgqLbkDYAAAAAAAEBK7iGJgcAAAAAIgAgSOjPZes2prPdrcgiv+IG1sjXyTCc4KDr9+C9F+xk6LwBBWEhAgKTOrEDfq0KpKeFjG1J1nBeH7O8X2awCRive58A7NUmrFGHZHapFHKpXyKvmhuuuFL5qVJy+MIdmPJkiKxrdqkUtsmtuJyMk3Jsg+KhtdlHidd7lWGIrGyTUodnWLJoIgYCApM6sQN+rQqkp4WMbUnWcF4fs7xfZrAJGK97nwDs1SYIJR1gCQAAAAAiBgJYLe2/RPRlZOXYzbBnU21g6+NM0dGAHP9Ru/nXrCibQwjWfX/pAAAAACIGA0cE3stVtaqI/9HvXQY2YkjBMU4ZZVETb/FOq4u6SkkOCHKpXyIAAAAAAAA="
239245
);
240246
}
241247

@@ -264,7 +270,7 @@ mod tests {
264270

265271
assert_eq!(
266272
base64::encode(encode::serialize(&unvault_tx)).to_string(),
267-
"cHNidP8BAIkCAAAAAUeuD/NEqc88sk3DoBrKoVKjXbN2xW8Jr/4GO5q87JqJAQAAAAD9////AriGJgcAAAAAIgAgSOjPZes2prPdrcgiv+IG1sjXyTCc4KDr9+C9F+xk6LwwdQAAAAAAACIAIAjkMa8elv7dHUmYpDATWBtmMmpv9yyKFawMunvGQ1AMAAAAAAABASsADicHAAAAACIAIHXyaRd0yBZ3gxhGsCgiAOKIssWXELWPdDGD1JJVB9vFAQMEAQAAAAEFR1IhAlgt7b9E9GVk5djNsGdTbWDr40zR0YAc/1G7+desKJtDIQNHBN7LVbWqiP/R710GNmJIwTFOGWVRE2/xTquLukpJDlKuIgYCWC3tv0T0ZWTl2M2wZ1NtYOvjTNHRgBz/Ubv516wom0MI1n1/6QAAAAAiBgNHBN7LVbWqiP/R710GNmJIwTFOGWVRE2/xTquLukpJDghyqV8iAAAAAAAiAgICkzqxA36tCqSnhYxtSdZwXh+zvF9msAkYr3ufAOzVJgglHWAJAAAAACICAlgt7b9E9GVk5djNsGdTbWDr40zR0YAc/1G7+desKJtDCNZ9f+kAAAAAIgIDRwTey1W1qoj/0e9dBjZiSMExThllURNv8U6ri7pKSQ4IcqlfIgAAAAAAIgICUHL04HZXilyJ1B118e1Smr+S8c1qtja46Le7DzMCaUMI+93szQAAAAAA"
273+
"cHNidP8BAIkCAAAAAUeuD/NEqc88sk3DoBrKoVKjXbN2xW8Jr/4GO5q87JqJAQAAAAD9////AriGJgcAAAAAIgAgSOjPZes2prPdrcgiv+IG1sjXyTCc4KDr9+C9F+xk6LwwdQAAAAAAACIAIAjkMa8elv7dHUmYpDATWBtmMmpv9yyKFawMunvGQ1AMAAAAAAABASsADicHAAAAACIAIHXyaRd0yBZ3gxhGsCgiAOKIssWXELWPdDGD1JJVB9vFAQVHUiECWC3tv0T0ZWTl2M2wZ1NtYOvjTNHRgBz/Ubv516wom0MhA0cE3stVtaqI/9HvXQY2YkjBMU4ZZVETb/FOq4u6SkkOUq4iBgJYLe2/RPRlZOXYzbBnU21g6+NM0dGAHP9Ru/nXrCibQwjWfX/pAAAAACIGA0cE3stVtaqI/9HvXQY2YkjBMU4ZZVETb/FOq4u6SkkOCHKpXyIAAAAAACICAgKTOrEDfq0KpKeFjG1J1nBeH7O8X2awCRive58A7NUmCCUdYAkAAAAAIgICWC3tv0T0ZWTl2M2wZ1NtYOvjTNHRgBz/Ubv516wom0MI1n1/6QAAAAAiAgNHBN7LVbWqiP/R710GNmJIwTFOGWVRE2/xTquLukpJDghyqV8iAAAAAAAiAgJQcvTgdleKXInUHXXx7VKav5LxzWq2Nrjot7sPMwJpQwj73ezNAAAAAAA="
268274
);
269275
}
270276
}

hwi/src/app/revault.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ pub trait RevaultHWI: HWI {
1919
&mut self,
2020
emergency_tx: &Psbt,
2121
emergency_unvault_tx: &Psbt,
22-
cancel_tx: &Psbt,
23-
) -> Result<(Psbt, Psbt, Psbt), HWIError>;
22+
cancel_tx: &[Psbt; 5],
23+
) -> Result<(Psbt, Psbt, [Psbt; 5]), HWIError>;
2424

2525
/// Sign the unvault transaction required for delegation.
2626
async fn sign_unvault_tx(&mut self, unvault_tx: &Psbt) -> Result<Psbt, HWIError>;
@@ -30,7 +30,7 @@ pub trait RevaultHWI: HWI {
3030
async fn create_vaults(
3131
&mut self,
3232
deposits: &[(OutPoint, Amount, u32)],
33-
) -> Result<Vec<(Psbt, Psbt, Psbt)>, HWIError>;
33+
) -> Result<Vec<(Psbt, Psbt, [Psbt; 5])>, HWIError>;
3434

3535
/// Delegate a list of vaults by giving the utxos to an hardware wallet storing the
3636
/// descriptors and deriving itself the unvault transactions.
@@ -52,12 +52,18 @@ impl<T: HWI + NoRevaultApp + Send> RevaultHWI for T {
5252
&mut self,
5353
emergency_tx: &Psbt,
5454
emergency_unvault_tx: &Psbt,
55-
cancel_tx: &Psbt,
56-
) -> Result<(Psbt, Psbt, Psbt), HWIError> {
55+
cancel_txs: &[Psbt; 5],
56+
) -> Result<(Psbt, Psbt, [Psbt; 5]), HWIError> {
5757
let emergency_tx = self.sign_tx(emergency_tx).await?;
5858
let emergency_unvault_tx = self.sign_tx(emergency_unvault_tx).await?;
59-
let cancel_tx = self.sign_tx(cancel_tx).await?;
60-
Ok((emergency_tx, emergency_unvault_tx, cancel_tx))
59+
let cancel_txs = [
60+
self.sign_tx(&cancel_txs[0]).await?,
61+
self.sign_tx(&cancel_txs[1]).await?,
62+
self.sign_tx(&cancel_txs[2]).await?,
63+
self.sign_tx(&cancel_txs[3]).await?,
64+
self.sign_tx(&cancel_txs[4]).await?,
65+
];
66+
Ok((emergency_tx, emergency_unvault_tx, cancel_txs))
6167
}
6268

6369
async fn sign_unvault_tx(&mut self, unvault_tx: &Psbt) -> Result<Psbt, HWIError> {
@@ -67,7 +73,7 @@ impl<T: HWI + NoRevaultApp + Send> RevaultHWI for T {
6773
async fn create_vaults(
6874
&mut self,
6975
_deposits: &[(OutPoint, Amount, u32)],
70-
) -> Result<Vec<(Psbt, Psbt, Psbt)>, HWIError> {
76+
) -> Result<Vec<(Psbt, Psbt, [Psbt; 5])>, HWIError> {
7177
Err(HWIError::UnimplementedMethod)
7278
}
7379

0 commit comments

Comments
 (0)