Skip to content

Commit fa68437

Browse files
committed
Audit serialization trait implementations
Remove unintended serde derives from types that shouldn't be serializable by default. Conditionally enable serialization behind feature flag to prevent accidental API exposure through serialization.
1 parent 96965a8 commit fa68437

File tree

7 files changed

+29
-24
lines changed

7 files changed

+29
-24
lines changed

payjoin-ffi/src/receive/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ macro_rules! impl_save_for_transition {
4343
};
4444
}
4545

46-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, uniffi::Object)]
46+
#[derive(Debug, Clone, uniffi::Object)]
4747
pub struct ReceiverSessionEvent(payjoin::receive::v2::SessionEvent);
4848

4949
impl From<payjoin::receive::v2::SessionEvent> for ReceiverSessionEvent {
@@ -385,7 +385,7 @@ impl From<ReceiverBuilder> for payjoin::receive::v2::ReceiverBuilder {
385385
fn from(value: ReceiverBuilder) -> Self { value.0 }
386386
}
387387

388-
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, uniffi::Object)]
388+
#[derive(Clone, Debug, uniffi::Object)]
389389
pub struct Initialized(payjoin::receive::v2::Receiver<payjoin::receive::v2::Initialized>);
390390

391391
impl From<Initialized> for payjoin::receive::v2::Receiver<payjoin::receive::v2::Initialized> {

payjoin-ffi/src/send/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ macro_rules! impl_save_for_transition {
3232
};
3333
}
3434

35-
#[derive(uniffi::Object, Debug, Clone, serde::Serialize, serde::Deserialize)]
35+
#[derive(uniffi::Object, Debug, Clone)]
3636
pub struct SenderSessionEvent(payjoin::send::v2::SessionEvent);
3737

3838
impl From<SenderSessionEvent> for payjoin::send::v2::SessionEvent {

payjoin/src/core/receive/error.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ pub enum ProtocolError {
7777
/// "message": "Human readable error message"
7878
/// }
7979
/// ```
80-
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
80+
#[derive(Debug, Clone, PartialEq, Eq)]
81+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8182
pub struct JsonReply {
8283
/// The error code
8384
error_code: ErrorCode,

payjoin/src/core/receive/v2/mod.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
//! Note: Even fresh requests may be linkable via metadata (e.g. client IP, request timing),
2525
//! but request reuse makes correlation trivial for the relay.
2626
27-
use std::str::FromStr;
2827
#[cfg(not(target_arch = "wasm32"))]
2928
use std::time::Duration;
3029

@@ -33,8 +32,6 @@ use bitcoin::psbt::Psbt;
3332
use bitcoin::{Address, Amount, FeeRate, OutPoint, Script, TxOut, Txid};
3433
pub(crate) use error::InternalSessionError;
3534
pub use error::SessionError;
36-
use serde::de::Deserializer;
37-
use serde::{Deserialize, Serialize};
3835
pub use session::{replay_event_log, SessionEvent, SessionHistory, SessionOutcome, SessionStatus};
3936
use url::Url;
4037
#[cfg(target_arch = "wasm32")]
@@ -66,9 +63,10 @@ const SUPPORTED_VERSIONS: &[Version] = &[Version::One, Version::Two];
6663

6764
static TWENTY_FOUR_HOURS_DEFAULT_EXPIRATION: Duration = Duration::from_secs(60 * 60 * 24);
6865

69-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
66+
#[derive(Debug, Clone, PartialEq, Eq)]
67+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7068
pub struct SessionContext {
71-
#[serde(deserialize_with = "deserialize_address_assume_checked")]
69+
#[cfg_attr(feature = "serde", serde(deserialize_with = "deserialize_address_assume_checked"))]
7270
address: Address,
7371
directory: url::Url,
7472
ohttp_keys: OhttpKeys,
@@ -110,10 +108,14 @@ impl SessionContext {
110108
}
111109
}
112110

111+
#[cfg(feature = "serde")]
113112
fn deserialize_address_assume_checked<'de, D>(deserializer: D) -> Result<Address, D::Error>
114113
where
115-
D: Deserializer<'de>,
114+
D: serde::de::Deserializer<'de>,
116115
{
116+
use std::str::FromStr;
117+
118+
use serde::Deserialize;
117119
let s = String::deserialize(deserializer)?;
118120
let address = Address::from_str(&s).map_err(serde::de::Error::custom)?;
119121
Ok(address.assume_checked())
@@ -265,7 +267,7 @@ pub trait State: sealed::State {}
265267
/// various functions to accomplish the goals of the typestate, and one or more functions which
266268
/// will commit the changes/checks in the current typestate and move to the next one. For more
267269
/// information on the typestate pattern, see [The Typestate Pattern in Rust](https://cliffle.com/blog/rust-typestate/).
268-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
270+
#[derive(Debug, Clone, PartialEq, Eq)]
269271
pub struct Receiver<State> {
270272
/// Data associated with the current state of the receiver.
271273
pub(crate) state: State,
@@ -342,7 +344,7 @@ impl ReceiverBuilder {
342344
}
343345
}
344346

345-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
347+
#[derive(Debug, Clone, PartialEq, Eq)]
346348
pub struct Initialized {}
347349

348350
impl Receiver<Initialized> {
@@ -1214,7 +1216,7 @@ impl Receiver<HasReplyableError> {
12141216
}
12151217
}
12161218

1217-
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1219+
#[derive(Debug, Clone, PartialEq, Eq)]
12181220
pub struct Monitor {
12191221
psbt_context: PsbtContext,
12201222
}

payjoin/src/core/receive/v2/session.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use serde::{Deserialize, Serialize};
2-
31
use super::{ReceiveSession, SessionContext};
42
use crate::error::{InternalReplayError, ReplayError};
53
use crate::output_substitution::OutputSubstitution;
@@ -142,7 +140,8 @@ pub enum SessionStatus {
142140

143141
/// Represents a piece of information that the receiver has obtained from the session
144142
/// Each event can be used to transition the receiver state machine to a new state
145-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
143+
#[derive(Debug, Clone, PartialEq, Eq)]
144+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
146145
pub enum SessionEvent {
147146
Created(SessionContext),
148147
RetrievedOriginalPayload { original: OriginalPayload, reply_key: Option<crate::HpkePublicKey> },
@@ -160,7 +159,8 @@ pub enum SessionEvent {
160159
}
161160

162161
/// Represents all possible outcomes for a closed Payjoin session
163-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
162+
#[derive(Debug, Clone, PartialEq, Eq)]
163+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
164164
pub enum SessionOutcome {
165165
/// Payjoin completed successfully
166166
Success(Vec<(bitcoin::ScriptBuf, bitcoin::Witness)>),

payjoin/src/core/send/v2/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ use bitcoin::Address;
3333
pub use error::{CreateRequestError, EncapsulationError};
3434
use error::{InternalCreateRequestError, InternalEncapsulationError};
3535
use ohttp::ClientResponse;
36-
use serde::{Deserialize, Serialize};
3736
pub use session::{replay_event_log, SessionEvent, SessionHistory, SessionOutcome, SessionStatus};
3837
use url::Url;
3938

@@ -190,13 +189,14 @@ mod sealed {
190189
/// can implement this trait, ensuring type safety and protocol integrity.
191190
pub trait State: sealed::State {}
192191

193-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
192+
#[derive(Debug, Clone, PartialEq, Eq)]
194193
pub struct Sender<State> {
195194
pub(crate) state: State,
196195
pub(crate) session_context: SessionContext,
197196
}
198197

199-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
198+
#[derive(Debug, Clone, PartialEq, Eq)]
199+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
200200
pub struct SessionContext {
201201
/// The endpoint in the Payjoin URI
202202
pub(crate) pj_param: PjParam,
@@ -278,7 +278,7 @@ impl SendSession {
278278

279279
/// A payjoin V2 sender, allowing the construction of a payjoin V2 request
280280
/// and the resulting [`ClientResponse`].
281-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
281+
#[derive(Debug, Clone, PartialEq, Eq)]
282282
pub struct WithReplyKey;
283283

284284
impl Sender<WithReplyKey> {
@@ -412,7 +412,7 @@ pub(crate) fn serialize_v2_body(
412412
///
413413
/// This type is used to make a BIP77 GET request and process the response.
414414
/// Call [`Sender<PollingForProposal>::process_response`] on it to continue the BIP77 flow.
415-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
415+
#[derive(Debug, Clone, PartialEq, Eq)]
416416
pub struct PollingForProposal;
417417

418418
impl ResponseError {

payjoin/src/core/send/v2/session.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ pub enum SessionStatus {
103103
Completed,
104104
}
105105

106-
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
106+
#[derive(Debug, Clone, PartialEq, Eq)]
107+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
107108
pub enum SessionEvent {
108109
/// Sender was created with session data
109110
Created(Box<SessionContext>),
@@ -114,7 +115,8 @@ pub enum SessionEvent {
114115
}
115116

116117
/// Represents all possible outcomes for a closed Payjoin session
117-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
118+
#[derive(Debug, Clone, PartialEq, Eq)]
119+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
118120
pub enum SessionOutcome {
119121
/// Successful payjoin
120122
Success(bitcoin::Psbt),

0 commit comments

Comments
 (0)