From 12275d0bfe0e0745aa5c3d9507f534cb0e2e39a2 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 30 Jun 2022 13:44:37 +0200 Subject: [PATCH] cln-grpc: Skip serializing fields when Option> is empty too The CLN API is rather strict about the fact that we should skip providing a field whenever it is empty. Checking for `is_none` would still include empty arrays. Changelog-Fixed cln-rpc: Optional empty arrays will no longer be serialized in requests --- cln-rpc/src/lib.rs | 10 ++++++++ cln-rpc/src/model.rs | 42 +++++++++++++++---------------- contrib/msggen/msggen/gen/rust.py | 2 +- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/cln-rpc/src/lib.rs b/cln-rpc/src/lib.rs index f2c34ba23..d53ad0cad 100644 --- a/cln-rpc/src/lib.rs +++ b/cln-rpc/src/lib.rs @@ -106,6 +106,16 @@ impl ClnRpc { } } +/// Used to skip optional arrays when serializing requests. +fn is_none_or_empty(f: &Option>) -> bool +where + T: Clone, +{ + // TODO Find a better way to check, possibly without cloning + let f = f.clone(); + f.is_none() || f.unwrap().is_empty() +} + #[cfg(test)] mod test { use super::*; diff --git a/cln-rpc/src/model.rs b/cln-rpc/src/model.rs index 61a759592..15b1b02d8 100644 --- a/cln-rpc/src/model.rs +++ b/cln-rpc/src/model.rs @@ -220,7 +220,7 @@ pub mod requests { pub wrong_funding: Option, #[serde(alias = "force_lease_closed", skip_serializing_if = "Option::is_none")] pub force_lease_closed: Option, - #[serde(alias = "feerange", skip_serializing_if = "Option::is_none")] + #[serde(alias = "feerange", skip_serializing_if = "crate::is_none_or_empty")] pub feerange: Option>, } @@ -361,7 +361,7 @@ pub mod requests { pub label: String, #[serde(alias = "expiry", skip_serializing_if = "Option::is_none")] pub expiry: Option, - #[serde(alias = "fallbacks", skip_serializing_if = "Option::is_none")] + #[serde(alias = "fallbacks", skip_serializing_if = "crate::is_none_or_empty")] pub fallbacks: Option>, #[serde(alias = "preimage", skip_serializing_if = "Option::is_none")] pub preimage: Option, @@ -375,7 +375,7 @@ pub mod requests { #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ListdatastoreRequest { - #[serde(alias = "key", skip_serializing_if = "Option::is_none")] + #[serde(alias = "key", skip_serializing_if = "crate::is_none_or_empty")] pub key: Option>, } @@ -409,7 +409,7 @@ pub mod requests { pub payment_hash: Sha256, #[serde(alias = "label", skip_serializing_if = "Option::is_none")] pub label: Option, - #[serde(alias = "shared_secrets", skip_serializing_if = "Option::is_none")] + #[serde(alias = "shared_secrets", skip_serializing_if = "crate::is_none_or_empty")] pub shared_secrets: Option>, #[serde(alias = "partid", skip_serializing_if = "Option::is_none")] pub partid: Option, @@ -480,7 +480,7 @@ pub mod requests { pub exemptfee: Option, #[serde(alias = "localofferid", skip_serializing_if = "Option::is_none")] pub localofferid: Option, - #[serde(alias = "exclude", skip_serializing_if = "Option::is_none")] + #[serde(alias = "exclude", skip_serializing_if = "crate::is_none_or_empty")] pub exclude: Option>, #[serde(alias = "maxfee", skip_serializing_if = "Option::is_none")] pub maxfee: Option, @@ -557,7 +557,7 @@ pub mod requests { pub feerate: Option, #[serde(alias = "minconf", skip_serializing_if = "Option::is_none")] pub minconf: Option, - #[serde(alias = "utxos", skip_serializing_if = "Option::is_none")] + #[serde(alias = "utxos", skip_serializing_if = "crate::is_none_or_empty")] pub utxos: Option>, } @@ -617,7 +617,7 @@ pub mod requests { pub struct SignpsbtRequest { #[serde(alias = "psbt")] pub psbt: String, - #[serde(alias = "signonly", skip_serializing_if = "Option::is_none")] + #[serde(alias = "signonly", skip_serializing_if = "crate::is_none_or_empty")] pub signonly: Option>, } @@ -657,7 +657,7 @@ pub mod requests { pub feerate: Option, #[serde(alias = "minconf", skip_serializing_if = "Option::is_none")] pub minconf: Option, - #[serde(alias = "utxos", skip_serializing_if = "Option::is_none")] + #[serde(alias = "utxos", skip_serializing_if = "crate::is_none_or_empty")] pub utxos: Option>, } @@ -720,7 +720,7 @@ pub mod requests { pub request_amt: Option, #[serde(alias = "compact_lease", skip_serializing_if = "Option::is_none")] pub compact_lease: Option, - #[serde(alias = "utxos", skip_serializing_if = "Option::is_none")] + #[serde(alias = "utxos", skip_serializing_if = "crate::is_none_or_empty")] pub utxos: Option>, } @@ -738,7 +738,7 @@ pub mod requests { pub fromid: Option, #[serde(alias = "fuzzpercent", skip_serializing_if = "Option::is_none")] pub fuzzpercent: Option, - #[serde(alias = "exclude", skip_serializing_if = "Option::is_none")] + #[serde(alias = "exclude", skip_serializing_if = "crate::is_none_or_empty")] pub exclude: Option>, #[serde(alias = "maxhops", skip_serializing_if = "Option::is_none")] pub maxhops: Option, @@ -955,9 +955,9 @@ pub mod responses { pub network: String, #[serde(alias = "fees_collected_msat")] pub fees_collected_msat: Amount, - #[serde(alias = "address", skip_serializing_if = "Option::is_none")] + #[serde(alias = "address", skip_serializing_if = "crate::is_none_or_empty")] pub address: Option>, - #[serde(alias = "binding", skip_serializing_if = "Option::is_none")] + #[serde(alias = "binding", skip_serializing_if = "crate::is_none_or_empty")] pub binding: Option>, #[serde(alias = "warning_bitcoind_sync", skip_serializing_if = "Option::is_none")] pub warning_bitcoind_sync: Option, @@ -1185,7 +1185,7 @@ pub mod responses { pub next_feerate: Option, #[serde(alias = "next_fee_step", skip_serializing_if = "Option::is_none")] pub next_fee_step: Option, - #[serde(alias = "inflight", skip_serializing_if = "Option::is_none")] + #[serde(alias = "inflight", skip_serializing_if = "crate::is_none_or_empty")] pub inflight: Option>, #[serde(alias = "close_to", skip_serializing_if = "Option::is_none")] pub close_to: Option, @@ -1234,9 +1234,9 @@ pub mod responses { pub our_to_self_delay: Option, #[serde(alias = "max_accepted_htlcs", skip_serializing_if = "Option::is_none")] pub max_accepted_htlcs: Option, - #[serde(alias = "state_changes", skip_serializing_if = "Option::is_none")] + #[serde(alias = "state_changes", skip_serializing_if = "crate::is_none_or_empty")] pub state_changes: Option>, - #[serde(alias = "status", skip_serializing_if = "Option::is_none")] + #[serde(alias = "status", skip_serializing_if = "crate::is_none_or_empty")] pub status: Option>, #[serde(alias = "in_payments_offered", skip_serializing_if = "Option::is_none")] pub in_payments_offered: Option, @@ -1254,7 +1254,7 @@ pub mod responses { pub out_payments_fulfilled: Option, #[serde(alias = "out_fulfilled_msat", skip_serializing_if = "Option::is_none")] pub out_fulfilled_msat: Option, - #[serde(alias = "htlcs", skip_serializing_if = "Option::is_none")] + #[serde(alias = "htlcs", skip_serializing_if = "crate::is_none_or_empty")] pub htlcs: Option>, #[serde(alias = "close_to_addr", skip_serializing_if = "Option::is_none")] pub close_to_addr: Option, @@ -1266,11 +1266,11 @@ pub mod responses { pub id: Pubkey, #[serde(alias = "connected")] pub connected: bool, - #[serde(alias = "log", skip_serializing_if = "Option::is_none")] + #[serde(alias = "log", skip_serializing_if = "crate::is_none_or_empty")] pub log: Option>, #[serde(alias = "channels")] pub channels: Vec, - #[serde(alias = "netaddr", skip_serializing_if = "Option::is_none")] + #[serde(alias = "netaddr", skip_serializing_if = "crate::is_none_or_empty")] pub netaddr: Option>, #[serde(alias = "remote_addr", skip_serializing_if = "Option::is_none")] pub remote_addr: Option, @@ -2172,7 +2172,7 @@ pub mod responses { pub color: Option, #[serde(alias = "features", skip_serializing_if = "Option::is_none")] pub features: Option, - #[serde(alias = "addresses", skip_serializing_if = "Option::is_none")] + #[serde(alias = "addresses", skip_serializing_if = "crate::is_none_or_empty")] pub addresses: Option>, } @@ -2408,7 +2408,7 @@ pub mod responses { pub excess_msat: Amount, #[serde(alias = "change_outnum", skip_serializing_if = "Option::is_none")] pub change_outnum: Option, - #[serde(alias = "reservations", skip_serializing_if = "Option::is_none")] + #[serde(alias = "reservations", skip_serializing_if = "crate::is_none_or_empty")] pub reservations: Option>, } @@ -2452,7 +2452,7 @@ pub mod responses { pub excess_msat: Amount, #[serde(alias = "change_outnum", skip_serializing_if = "Option::is_none")] pub change_outnum: Option, - #[serde(alias = "reservations", skip_serializing_if = "Option::is_none")] + #[serde(alias = "reservations", skip_serializing_if = "crate::is_none_or_empty")] pub reservations: Option>, } diff --git a/contrib/msggen/msggen/gen/rust.py b/contrib/msggen/msggen/gen/rust.py index 2fbe3278f..7eac8ecf6 100644 --- a/contrib/msggen/msggen/gen/rust.py +++ b/contrib/msggen/msggen/gen/rust.py @@ -176,7 +176,7 @@ def gen_array(a): if a.required: defi = f" #[serde(alias = \"{alias}\")]\n pub {name}: {'Vec<'*a.dims}{itemtype}{'>'*a.dims},\n" else: - defi = f" #[serde(alias = \"{alias}\", skip_serializing_if = \"Option::is_none\")]\n pub {name}: Option<{'Vec<'*a.dims}{itemtype}{'>'*a.dims}>,\n" + defi = f" #[serde(alias = \"{alias}\", skip_serializing_if = \"crate::is_none_or_empty\")]\n pub {name}: Option<{'Vec<'*a.dims}{itemtype}{'>'*a.dims}>,\n" return (defi, decl)