Skip to content

Commit 61f0174

Browse files
committed
Merge #359: Add Deserialize macro to commands response
24eef7d Add Clone to config::Config (edouard) ac38367 Fix command get_spend_tx for consistency (edouard) 7091708 Fix command get_history for consistency (edouard) 0162c3b Fix command list_vaults for consistency (edouard) 23eefed Implem Display for HistoryEventKind (edouard) fb2fcf3 Add Clone macro to commands structs (edouard) f2b3446 commands: expose ServersStatuses fields (edouard) 903aaad Add Deserialize macro to commands response (edouard) Pull request description: Clients importing the revaultd lib and consuming the jsonrpc API need to deserialize the commands responses. This commit introduces new deserialization helpers and adds them to commands structs fields. ACKs for top commit: darosior: utACK 24eef7d Tree-SHA512: 30062d885332539e83fbbe2fa454c872432f08b2eae9837ab14262449d92aac1ebdc580f917b89ba4aa9c3ca9504b1336e801d358d478334209eab2741c44115
2 parents c46954a + 24eef7d commit 61f0174

File tree

7 files changed

+98
-66
lines changed

7 files changed

+98
-66
lines changed

src/bitcoind/interface.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ use jsonrpc::{
2222
client::Client,
2323
simple_http::{Error as HttpError, SimpleHttpTransport},
2424
};
25-
use serde::Serialize;
25+
26+
use serde::{Deserialize, Serialize};
2627
use serde_json::Value as Json;
2728

2829
// The minimum deposit value according to revault_tx depends also on the unvault's
@@ -920,7 +921,7 @@ impl BitcoinD {
920921
}
921922
}
922923

923-
#[derive(Debug, Clone, Serialize)]
924+
#[derive(Debug, Clone, Serialize, Deserialize)]
924925
pub struct WalletTransaction {
925926
pub hex: String,
926927
#[serde(rename = "received_at")]

src/commands/mod.rs

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ use crate::{
3232
DaemonControl, VERSION,
3333
};
3434
use utils::{
35-
finalized_emer_txs, gethistory, listvaults_from_db, presigned_txs, ser_amount, ser_to_string,
36-
serialize_option_tx_hex, vaults_from_deposits,
35+
deser_amount_from_sats, deser_from_str, finalized_emer_txs, gethistory, listvaults_from_db,
36+
presigned_txs, ser_amount, ser_to_string, serialize_option_tx_hex, vaults_from_deposits,
3737
};
3838

3939
use revault_tx::{
@@ -198,7 +198,6 @@ impl DaemonControl {
198198
} = db_tip(&revaultd.db_file()).expect("Database must not be dead");
199199
let number_of_vaults = self
200200
.list_vaults(None, None)
201-
.vaults
202201
.iter()
203202
.filter(|l| {
204203
l.status != VaultStatus::Spent
@@ -226,14 +225,12 @@ impl DaemonControl {
226225
/// List the current vaults, optionally filtered by status and/or deposit outpoints.
227226
pub fn list_vaults(
228227
&self,
229-
statuses: Option<Vec<VaultStatus>>,
230-
deposit_outpoints: Option<Vec<OutPoint>>,
231-
) -> ListVaultsResult {
228+
statuses: Option<&[VaultStatus]>,
229+
deposit_outpoints: Option<&[OutPoint]>,
230+
) -> Vec<ListVaultsEntry> {
232231
let revaultd = self.revaultd.read().unwrap();
233-
ListVaultsResult {
234-
vaults: listvaults_from_db(&revaultd, statuses, deposit_outpoints)
235-
.expect("Database must be available"),
236-
}
232+
listvaults_from_db(&revaultd, statuses, deposit_outpoints)
233+
.expect("Database must be available")
237234
}
238235

239236
/// Get the deposit address at the lowest still unused derivation index
@@ -863,7 +860,7 @@ impl DaemonControl {
863860
pub fn get_spend_tx(
864861
&self,
865862
outpoints: &[OutPoint],
866-
destinations: BTreeMap<Address, u64>,
863+
destinations: &BTreeMap<Address, u64>,
867864
feerate_vb: u64,
868865
) -> Result<SpendTransaction, CommandError> {
869866
let revaultd = self.revaultd.read().unwrap();
@@ -897,11 +894,11 @@ impl DaemonControl {
897894
}
898895

899896
let txos: Vec<SpendTxOut> = destinations
900-
.into_iter()
897+
.iter()
901898
.map(|(addr, value)| {
902899
let script_pubkey = addr.script_pubkey();
903900
SpendTxOut::new(TxOut {
904-
value,
901+
value: *value,
905902
script_pubkey,
906903
})
907904
})
@@ -1344,26 +1341,26 @@ impl DaemonControl {
13441341
start: u32,
13451342
end: u32,
13461343
limit: u64,
1347-
kind: Vec<HistoryEventKind>,
1344+
kind: &[HistoryEventKind],
13481345
) -> Result<Vec<HistoryEvent>, CommandError> {
13491346
let revaultd = self.revaultd.read().unwrap();
13501347
gethistory(&revaultd, &self.bitcoind_conn, start, end, limit, kind)
13511348
}
13521349
}
13531350

13541351
/// Descriptors the daemon was configured with
1355-
#[derive(Debug, Clone, Serialize)]
1352+
#[derive(Debug, Clone, Serialize, Deserialize)]
13561353
pub struct GetInfoDescriptors {
1357-
#[serde(serialize_with = "ser_to_string")]
1354+
#[serde(serialize_with = "ser_to_string", deserialize_with = "deser_from_str")]
13581355
pub deposit: DepositDescriptor,
1359-
#[serde(serialize_with = "ser_to_string")]
1356+
#[serde(serialize_with = "ser_to_string", deserialize_with = "deser_from_str")]
13601357
pub unvault: UnvaultDescriptor,
1361-
#[serde(serialize_with = "ser_to_string")]
1358+
#[serde(serialize_with = "ser_to_string", deserialize_with = "deser_from_str")]
13621359
pub cpfp: CpfpDescriptor,
13631360
}
13641361

13651362
/// Information about the current state of the daemon
1366-
#[derive(Debug, Clone, Serialize)]
1363+
#[derive(Debug, Clone, Serialize, Deserialize)]
13671364
pub struct GetInfoResult {
13681365
pub version: String,
13691366
pub network: Network,
@@ -1375,12 +1372,15 @@ pub struct GetInfoResult {
13751372
}
13761373

13771374
/// Information about a vault.
1378-
#[derive(Debug, Clone, Serialize)]
1375+
#[derive(Debug, Clone, Serialize, Deserialize)]
13791376
pub struct ListVaultsEntry {
1380-
#[serde(serialize_with = "ser_amount")]
1377+
#[serde(
1378+
serialize_with = "ser_amount",
1379+
deserialize_with = "deser_amount_from_sats"
1380+
)]
13811381
pub amount: Amount,
13821382
pub blockheight: u32,
1383-
#[serde(serialize_with = "ser_to_string")]
1383+
#[serde(serialize_with = "ser_to_string", deserialize_with = "deser_from_str")]
13841384
pub status: VaultStatus,
13851385
pub txid: Txid,
13861386
pub vout: u32,
@@ -1392,14 +1392,8 @@ pub struct ListVaultsEntry {
13921392
pub moved_at: Option<u32>,
13931393
}
13941394

1395-
/// Information about all our current vaults.
1396-
#[derive(Debug, Clone, Serialize)]
1397-
pub struct ListVaultsResult {
1398-
pub vaults: Vec<ListVaultsEntry>,
1399-
}
1400-
14011395
/// Revocation transactions for a given vault
1402-
#[derive(Debug, Clone, Serialize)]
1396+
#[derive(Debug, Clone, Serialize, Deserialize)]
14031397
pub struct RevocationTransactions {
14041398
pub cancel_tx: CancelTransaction,
14051399
pub emergency_tx: EmergencyTransaction,
@@ -1408,7 +1402,7 @@ pub struct RevocationTransactions {
14081402
}
14091403

14101404
/// A vault's presigned transaction.
1411-
#[derive(Debug, Clone, Serialize)]
1405+
#[derive(Debug, Clone, Serialize, Deserialize)]
14121406
pub struct VaultPresignedTransaction<T: RevaultTransaction> {
14131407
pub psbt: T,
14141408
// FIXME: is it really necessary?.. It's mostly contained in the PSBT already
@@ -1417,7 +1411,7 @@ pub struct VaultPresignedTransaction<T: RevaultTransaction> {
14171411
}
14181412

14191413
/// Information about a vault's presigned transactions.
1420-
#[derive(Debug, Clone, Serialize)]
1414+
#[derive(Debug, Clone, Serialize, Deserialize)]
14211415
pub struct ListPresignedTxEntry {
14221416
pub vault_outpoint: OutPoint,
14231417
pub unvault: VaultPresignedTransaction<UnvaultTransaction>,
@@ -1429,7 +1423,7 @@ pub struct ListPresignedTxEntry {
14291423
}
14301424

14311425
/// Information about a vault's onchain transactions.
1432-
#[derive(Debug, Clone, Serialize)]
1426+
#[derive(Debug, Clone, Serialize, Deserialize)]
14331427
pub struct ListOnchainTxEntry {
14341428
pub vault_outpoint: OutPoint,
14351429
pub deposit: WalletTransaction,
@@ -1443,7 +1437,7 @@ pub struct ListOnchainTxEntry {
14431437
}
14441438

14451439
/// Status of a Spend transaction
1446-
#[derive(Debug, Deserialize, PartialEq)]
1440+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
14471441
#[serde(rename_all = "snake_case")]
14481442
pub enum ListSpendStatus {
14491443
NonFinal,
@@ -1452,7 +1446,7 @@ pub enum ListSpendStatus {
14521446
}
14531447

14541448
/// Information about a Spend transaction
1455-
#[derive(Debug, Serialize)]
1449+
#[derive(Debug, Clone, Serialize, Deserialize)]
14561450
pub struct ListSpendEntry {
14571451
pub deposit_outpoints: Vec<OutPoint>,
14581452
pub psbt: SpendTransaction,
@@ -1461,15 +1455,15 @@ pub struct ListSpendEntry {
14611455
}
14621456

14631457
/// Information about the configured servers.
1464-
#[derive(Debug, Clone, Serialize)]
1458+
#[derive(Debug, Clone, Serialize, Deserialize)]
14651459
pub struct ServersStatuses {
1466-
coordinator: ServerStatus,
1467-
cosigners: Vec<ServerStatus>,
1468-
watchtowers: Vec<ServerStatus>,
1460+
pub coordinator: ServerStatus,
1461+
pub cosigners: Vec<ServerStatus>,
1462+
pub watchtowers: Vec<ServerStatus>,
14691463
}
14701464

14711465
/// The type of an accounting event.
1472-
#[derive(Debug, PartialEq, Serialize, Deserialize)]
1466+
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14731467
pub enum HistoryEventKind {
14741468
#[serde(rename = "cancel")]
14751469
Cancel,
@@ -1479,8 +1473,18 @@ pub enum HistoryEventKind {
14791473
Spend,
14801474
}
14811475

1476+
impl fmt::Display for HistoryEventKind {
1477+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1478+
match self {
1479+
Self::Cancel => write!(f, "Cancel"),
1480+
Self::Deposit => write!(f, "Deposit"),
1481+
Self::Spend => write!(f, "Spend"),
1482+
}
1483+
}
1484+
}
1485+
14821486
/// An accounting event.
1483-
#[derive(Debug, Serialize)]
1487+
#[derive(Debug, Clone, Serialize, Deserialize)]
14841488
pub struct HistoryEvent {
14851489
pub kind: HistoryEventKind,
14861490
pub date: u32,

src/commands/utils.rs

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ use revault_tx::{
3232
use std::{
3333
collections::{HashMap, HashSet},
3434
fmt,
35+
str::FromStr,
3536
};
3637

37-
use serde::Serializer;
38+
use serde::{de, Deserialize, Deserializer, Serializer};
3839

3940
fn serialize_tx_hex<S>(tx: &BitcoinTransaction, s: S) -> Result<S::Ok, S::Error>
4041
where
@@ -61,17 +62,39 @@ pub fn ser_to_string<T: fmt::Display, S: Serializer>(field: T, s: S) -> Result<S
6162
s.serialize_str(&field.to_string())
6263
}
6364

65+
/// Deserialize a type `S` by deserializing a string, then using the `FromStr`
66+
/// impl of `S` to create the result. The generic type `S` is not required to
67+
/// implement `Deserialize`.
68+
pub fn deser_from_str<'de, S, D>(deserializer: D) -> Result<S, D::Error>
69+
where
70+
S: FromStr,
71+
S::Err: fmt::Display,
72+
D: Deserializer<'de>,
73+
{
74+
let s: String = Deserialize::deserialize(deserializer)?;
75+
S::from_str(&s).map_err(de::Error::custom)
76+
}
77+
6478
/// Serialize an amount as sats
6579
pub fn ser_amount<S: Serializer>(amount: &Amount, s: S) -> Result<S::Ok, S::Error> {
6680
s.serialize_u64(amount.as_sat())
6781
}
6882

83+
/// Deserialize an amount from sats
84+
pub fn deser_amount_from_sats<'de, D>(deserializer: D) -> Result<Amount, D::Error>
85+
where
86+
D: Deserializer<'de>,
87+
{
88+
let a = u64::deserialize(deserializer)?;
89+
Ok(Amount::from_sat(a))
90+
}
91+
6992
/// List the vaults from DB, and filter out the info the RPC wants
7093
// FIXME: we could make this more efficient with smarter SQL queries
7194
pub fn listvaults_from_db(
7295
revaultd: &RevaultD,
73-
statuses: Option<Vec<VaultStatus>>,
74-
outpoints: Option<Vec<OutPoint>>,
96+
statuses: Option<&[VaultStatus]>,
97+
outpoints: Option<&[OutPoint]>,
7598
) -> Result<Vec<ListVaultsEntry>, DatabaseError> {
7699
db_vaults(&revaultd.db_file()).map(|db_vaults| {
77100
db_vaults
@@ -257,7 +280,7 @@ pub fn gethistory<T: BitcoindThread>(
257280
start: u32,
258281
end: u32,
259282
limit: u64,
260-
kind: Vec<HistoryEventKind>,
283+
kind: &[HistoryEventKind],
261284
) -> Result<Vec<HistoryEvent>, CommandError> {
262285
let db_path = revaultd.db_file();
263286
// All vaults which have one transaction (either the funding, the canceling, the unvaulting, the spending)
@@ -873,8 +896,8 @@ mod tests {
873896
for v in &vaults {
874897
let res = &listvaults_from_db(
875898
&revaultd,
876-
Some(vec![v.db_vault.status]),
877-
Some(vec![v.db_vault.deposit_outpoint]),
899+
Some(&[v.db_vault.status]),
900+
Some(&[v.db_vault.deposit_outpoint]),
878901
)
879902
.unwrap()[0];
880903
assert_eq!(res.amount, v.db_vault.amount);
@@ -891,16 +914,16 @@ mod tests {
891914
// Checking that filters work
892915
assert_eq!(listvaults_from_db(&revaultd, None, None).unwrap().len(), 4);
893916
assert_eq!(
894-
listvaults_from_db(&revaultd, Some(vec![VaultStatus::Unconfirmed]), None)
917+
listvaults_from_db(&revaultd, Some(&[VaultStatus::Unconfirmed]), None)
895918
.unwrap()
896919
.len(),
897920
1
898921
);
899922
assert_eq!(
900923
listvaults_from_db(
901924
&revaultd,
902-
Some(vec![VaultStatus::Unconfirmed]),
903-
Some(vec![vaults[1].db_vault.deposit_outpoint])
925+
Some(&[VaultStatus::Unconfirmed]),
926+
Some(&[vaults[1].db_vault.deposit_outpoint])
904927
)
905928
.unwrap()
906929
.len(),
@@ -910,7 +933,7 @@ mod tests {
910933
listvaults_from_db(
911934
&revaultd,
912935
None,
913-
Some(vec![
936+
Some(&[
914937
vaults[0].db_vault.deposit_outpoint,
915938
vaults[1].db_vault.deposit_outpoint
916939
])
@@ -922,7 +945,7 @@ mod tests {
922945
assert_eq!(
923946
listvaults_from_db(
924947
&revaultd,
925-
Some(vec![
948+
Some(&[
926949
VaultStatus::Unconfirmed,
927950
VaultStatus::Funded,
928951
VaultStatus::Secured
@@ -936,7 +959,7 @@ mod tests {
936959
assert_eq!(
937960
listvaults_from_db(
938961
&revaultd,
939-
Some(vec![
962+
Some(&[
940963
VaultStatus::Unconfirmed,
941964
VaultStatus::Funded,
942965
VaultStatus::Secured,
@@ -1469,7 +1492,7 @@ mod tests {
14691492
0,
14701493
4,
14711494
20,
1472-
vec![
1495+
&[
14731496
HistoryEventKind::Deposit,
14741497
HistoryEventKind::Cancel,
14751498
HistoryEventKind::Spend,
@@ -1516,7 +1539,7 @@ mod tests {
15161539
0,
15171540
2,
15181541
20,
1519-
vec![
1542+
&[
15201543
HistoryEventKind::Deposit,
15211544
HistoryEventKind::Cancel,
15221545
HistoryEventKind::Spend,

src/communication.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use revault_tx::{
1818

1919
use std::{collections::BTreeMap, fmt};
2020

21-
use serde::Serialize;
21+
use serde::{Deserialize, Serialize};
2222

2323
/// The kind of signature the WT refused
2424
#[derive(Debug)]
@@ -306,7 +306,7 @@ pub fn get_presigs(
306306
Ok(resp.signatures)
307307
}
308308

309-
#[derive(Debug, Clone, Serialize)]
309+
#[derive(Debug, Clone, Deserialize, Serialize)]
310310
pub struct ServerStatus {
311311
pub host: String,
312312
pub reachable: bool,

0 commit comments

Comments
 (0)