Skip to content

Commit beaff5e

Browse files
authored
Expose shortid method for SessionContext (payjoin#698)
By exposing the shortid method for SessionContext it allows us to be able to track the id across all psbt intermediate steps and allows us to not need this method duplicated in every step of the process. Closes payjoin#697
2 parents 5b7678a + 14fb6bd commit beaff5e

File tree

3 files changed

+18
-24
lines changed

3 files changed

+18
-24
lines changed

payjoin/src/receive/multiparty/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ impl UncheckedProposalBuilder {
4444
{
4545
return Err(InternalMultipartyError::IdenticalProposals(
4646
IdenticalProposalError::IdenticalContexts(
47-
Box::new(duplicate_context.id()),
48-
Box::new(proposal.id()),
47+
Box::new(duplicate_context.context.id()),
48+
Box::new(proposal.context.id()),
4949
),
5050
)
5151
.into());
@@ -249,8 +249,8 @@ impl FinalizedProposal {
249249
{
250250
return Err(InternalMultipartyError::IdenticalProposals(
251251
IdenticalProposalError::IdenticalContexts(
252-
Box::new(duplicate_context.id()),
253-
Box::new(proposal.id()),
252+
Box::new(duplicate_context.context.id()),
253+
Box::new(proposal.context.id()),
254254
),
255255
)
256256
.into());
@@ -366,8 +366,8 @@ mod test {
366366
e.to_string(),
367367
MultipartyError::from(InternalMultipartyError::IdenticalProposals(
368368
IdenticalProposalError::IdenticalContexts(
369-
Box::new(proposal_one.id()),
370-
Box::new(proposal_two.id())
369+
Box::new(proposal_one.context.id()),
370+
Box::new(proposal_two.context.id())
371371
)
372372
))
373373
.to_string()

payjoin/src/receive/v2/mod.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ impl SessionContext {
5656
.join(&format!("/{directory_base}"))
5757
.map_err(|e| InternalSessionError::ParseUrl(e.into()))
5858
}
59+
60+
/// The per-session identifier
61+
pub fn id(&self) -> ShortId {
62+
sha256::Hash::hash(&self.s.public_key().to_compressed_bytes()).into()
63+
}
5964
}
6065

6166
fn deserialize_address_assume_checked<'de, D>(deserializer: D) -> Result<Address, D::Error>
@@ -182,7 +187,7 @@ impl Receiver {
182187
([u8; crate::directory::ENCAPSULATED_MESSAGE_BYTES], ohttp::ClientResponse),
183188
OhttpEncapsulationError,
184189
> {
185-
let fallback_target = subdir(&self.context.directory, &self.id());
190+
let fallback_target = subdir(&self.context.directory, &self.context.id());
186191
ohttp_encapsulate(&mut self.context.ohttp_keys, "GET", fallback_target.as_str(), None)
187192
}
188193

@@ -236,17 +241,14 @@ impl Receiver {
236241
/// Build a V2 Payjoin URI from the receiver's context
237242
pub fn pj_uri<'a>(&self) -> crate::PjUri<'a> {
238243
use crate::uri::{PayjoinExtras, UrlExt};
239-
let mut pj = subdir(&self.context.directory, &self.id()).clone();
244+
let mut pj = subdir(&self.context.directory, &self.context.id()).clone();
240245
pj.set_receiver_pubkey(self.context.s.public_key().clone());
241246
pj.set_ohttp(self.context.ohttp_keys.clone());
242247
pj.set_exp(self.context.expiry);
243248
let extras =
244249
PayjoinExtras { endpoint: pj, output_substitution: OutputSubstitution::Enabled };
245250
bitcoin_uri::Uri::with_extras(self.context.address.clone(), extras)
246251
}
247-
248-
/// The per-session identifier
249-
pub fn id(&self) -> ShortId { id(&self.context.s) }
250252
}
251253

252254
/// The sender's original PSBT and optional parameters
@@ -308,7 +310,7 @@ impl UncheckedProposal {
308310
err: &JsonReply,
309311
ohttp_relay: impl IntoUrl,
310312
) -> Result<(Request, ohttp::ClientResponse), SessionError> {
311-
let subdir = subdir(&self.context.directory, &id(&self.context.s));
313+
let subdir = subdir(&self.context.directory, &self.context.id());
312314
let (body, ohttp_ctx) = ohttp_encapsulate(
313315
&mut self.context.ohttp_keys,
314316
"POST",
@@ -338,9 +340,6 @@ impl UncheckedProposal {
338340
_ => Err(InternalSessionError::UnexpectedStatusCode(response.status()).into()),
339341
}
340342
}
341-
342-
/// The per-session identifier
343-
pub fn id(&self) -> ShortId { id(&self.context.s) }
344343
}
345344

346345
/// Typestate to validate that the Original PSBT has no receiver-owned inputs.
@@ -630,11 +629,6 @@ fn subdir(directory: &Url, id: &ShortId) -> Url {
630629
url
631630
}
632631

633-
/// The per-session identifier
634-
fn id(s: &HpkeKeyPair) -> ShortId {
635-
sha256::Hash::hash(&s.public_key().to_compressed_bytes()).into()
636-
}
637-
638632
#[cfg(test)]
639633
pub mod test {
640634
use std::str::FromStr;
@@ -724,7 +718,7 @@ pub mod test {
724718
#[test]
725719
fn receiver_ser_de_roundtrip() -> Result<(), serde_json::Error> {
726720
let session = Receiver { context: SHARED_CONTEXT.clone() };
727-
let short_id = id(&session.context.s);
721+
let short_id = &session.context.id();
728722
assert_eq!(session.key().as_ref(), short_id.as_bytes());
729723
let serialized = serde_json::to_string(&session)?;
730724
let deserialized: Receiver = serde_json::from_str(&serialized)?;

payjoin/src/receive/v2/persist.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::fmt::{self, Display};
22

3-
use super::{id, Receiver};
3+
use super::Receiver;
44
use crate::persist::{self};
55
use crate::uri::ShortId;
66

@@ -13,7 +13,7 @@ impl Display for ReceiverToken {
1313
}
1414

1515
impl From<Receiver> for ReceiverToken {
16-
fn from(receiver: Receiver) -> Self { ReceiverToken(id(&receiver.context.s)) }
16+
fn from(receiver: Receiver) -> Self { ReceiverToken(receiver.context.id()) }
1717
}
1818

1919
impl AsRef<[u8]> for ReceiverToken {
@@ -23,5 +23,5 @@ impl AsRef<[u8]> for ReceiverToken {
2323
impl persist::Value for Receiver {
2424
type Key = ReceiverToken;
2525

26-
fn key(&self) -> Self::Key { ReceiverToken(id(&self.context.s)) }
26+
fn key(&self) -> Self::Key { ReceiverToken(self.context.id()) }
2727
}

0 commit comments

Comments
 (0)