Skip to content

Commit 5950aa2

Browse files
committed
chore(rust/hermes-ipfs): utilize UuidV7 from catalyst-types
1 parent 50f65f2 commit 5950aa2

File tree

2 files changed

+36
-128
lines changed

2 files changed

+36
-128
lines changed

rust/hermes-ipfs/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ repository.workspace = true
1313
workspace = true
1414

1515
[features]
16-
doc-sync = ["minicbor", "uuid", "ed25519-dalek"]
16+
doc-sync = ["minicbor", "ed25519-dalek", "catalyst-types"]
1717

1818
[dependencies]
1919
anyhow = "1.0.100"
@@ -26,9 +26,9 @@ tokio = "1.46.0"
2626
futures = "0.3.31"
2727
libp2p = "0.56.0"
2828
connexa = { version = "0.4.1", features = ["identify", "dcutr", "gossipsub", "autonat", "relay", "kad", "keypair_base64_encoding", "ping", "request-response", "request-response-misc", "rendezvous", "mdns"] }
29-
minicbor = { version = "0.26.5", features = ["alloc", "derive"], optional = true }
30-
uuid = { version = "1.19.0", features = ["v7"], optional = true }
29+
minicbor = { version = "0.25.1", features = ["alloc"], optional = true }
3130
ed25519-dalek = { version = "2.1.1", optional = true}
31+
catalyst-types = { version = "0.0.11", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "catalyst-types/v0.0.11", optional = true }
3232

3333
[dev-dependencies]
3434
# Dependencies used by examples

rust/hermes-ipfs/src/doc_sync/envelope.rs

Lines changed: 33 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,12 @@
77
use std::convert::Infallible;
88

99
use anyhow::{Context, ensure};
10+
use catalyst_types::uuid::{self, CborContext, UuidV7};
1011
use ed25519_dalek::VerifyingKey;
11-
use minicbor::{
12-
Decode, Encode, Encoder,
13-
data::{Tag, Type},
14-
encode::Write,
15-
};
16-
use uuid::Timestamp;
12+
use minicbor::{Decode, Encode, Encoder, data::Type, encode::Write};
1713

1814
use crate::doc_sync::PROTOCOL_VERSION;
1915

20-
/// CBOR semantic tag value used for UUIDs (`#6.37`).
21-
const CBOR_TAG_UUID: u64 = 37;
22-
2316
/// Ed25519 public key instance.
2417
/// Wrapper over `ed25519_dalek::VerifyingKey`.
2518
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -78,53 +71,6 @@ impl<'b, C> Decode<'b, C> for Signature {
7871
}
7972
}
8073

81-
/// New type wrapper.
82-
struct UUIDv7(uuid::Uuid);
83-
84-
impl UUIDv7 {
85-
/// Create a new version 7 UUID using a time value and random bytes.
86-
fn new(timestamp: Timestamp) -> Self {
87-
Self(uuid::Uuid::new_v7(timestamp))
88-
}
89-
90-
/// Create a new version 7 UUID using the current time value.
91-
fn now() -> Self {
92-
Self(uuid::Uuid::now_v7())
93-
}
94-
}
95-
96-
impl<C> Encode<C> for UUIDv7 {
97-
fn encode<W: Write>(
98-
&self,
99-
e: &mut Encoder<W>,
100-
_ctx: &mut C,
101-
) -> Result<(), minicbor::encode::Error<W::Error>> {
102-
e.tag(Tag::new(CBOR_TAG_UUID))?;
103-
e.bytes(self.0.as_bytes())?;
104-
Ok(())
105-
}
106-
}
107-
108-
impl<'b, C> Decode<'b, C> for UUIDv7 {
109-
fn decode(
110-
d: &mut minicbor::Decoder<'b>,
111-
_ctx: &mut C,
112-
) -> Result<Self, minicbor::decode::Error> {
113-
let tag = d.tag()?;
114-
if tag != Tag::new(CBOR_TAG_UUID) {
115-
return Err(minicbor::decode::Error::message(format!(
116-
"UUIDv7 must be tagged with #{CBOR_TAG_UUID}, got #{}",
117-
u64::from(tag)
118-
)));
119-
}
120-
uuid::Uuid::from_slice(d.bytes()?)
121-
.map_err(|err| {
122-
minicbor::decode::Error::message(format!("error during UUIDv7 decode: {err}"))
123-
})
124-
.map(UUIDv7)
125-
}
126-
}
127-
12874
/// The unsigned portion of the message envelope.
12975
/// This structure corresponds to the **signature input** array:
13076
/// `[peer, seq, ver, payload]`.
@@ -137,7 +83,7 @@ pub struct EnvelopePayload {
13783
peer: PublicKey,
13884
/// Unique nonce and timestamp.
13985
/// Prevents and helps detect message duplication.
140-
seq: UUIDv7,
86+
seq: UuidV7,
14187
/// Protocol version number.
14288
/// This should be `1` for the current specification.
14389
ver: u64,
@@ -152,32 +98,13 @@ impl EnvelopePayload {
15298
///
15399
/// Returns an error when `payload` is not a single CBOR map.
154100
pub fn new(
155-
peer: ed25519_dalek::VerifyingKey,
156-
seq: Timestamp,
157-
payload: Vec<u8>,
158-
) -> anyhow::Result<Self> {
159-
ensure_payload_body(&payload)?;
160-
Ok(Self {
161-
peer: PublicKey(peer),
162-
seq: UUIDv7::new(seq),
163-
ver: PROTOCOL_VERSION,
164-
payload,
165-
})
166-
}
167-
168-
/// Create new instance of `EnvelopePayload` using the current time value.
169-
///
170-
/// # Errors
171-
///
172-
/// Returns an error when `payload` is not a single CBOR map.
173-
pub fn now(
174101
peer: ed25519_dalek::VerifyingKey,
175102
payload: Vec<u8>,
176103
) -> anyhow::Result<Self> {
177104
ensure_payload_body(&payload)?;
178105
Ok(Self {
179106
peer: PublicKey(peer),
180-
seq: UUIDv7::now(),
107+
seq: UuidV7::new(),
181108
ver: PROTOCOL_VERSION,
182109
payload,
183110
})
@@ -189,10 +116,10 @@ impl EnvelopePayload {
189116
&self.peer.0
190117
}
191118

192-
/// Returns the `UUIDv7` sequence value.
119+
/// Returns the `UuidV7` sequence value.
193120
#[must_use]
194-
pub fn seq(&self) -> &uuid::Uuid {
195-
&self.seq.0
121+
pub fn seq(&self) -> uuid::Uuid {
122+
self.seq.uuid()
196123
}
197124

198125
/// Returns the encoded payload-body bytes.
@@ -209,16 +136,16 @@ impl EnvelopePayload {
209136
///
210137
/// Returns an error if encoding fails (should not happen with `Vec<u8>` writers).
211138
pub fn to_bytes(&self) -> Result<Vec<u8>, minicbor::encode::Error<Infallible>> {
212-
minicbor::to_vec(self)
139+
minicbor::to_vec_with(self, &mut CborContext::Tagged)
213140
}
214141

215142
/// Decodes `[peer, seq, ver, payload]` from the signed payload array.
216-
fn decode_from_signed<C>(
143+
fn decode_from_signed(
217144
decoder: &mut minicbor::Decoder<'_>,
218-
ctx: &mut C,
145+
ctx: &mut CborContext,
219146
) -> Result<Self, minicbor::decode::Error> {
220147
let peer: PublicKey = decoder.decode_with(ctx)?;
221-
let seq: UUIDv7 = decoder.decode_with(ctx)?;
148+
let seq: UuidV7 = decoder.decode_with(ctx)?;
222149
let ver = decoder.u64()?;
223150

224151
if ver != PROTOCOL_VERSION {
@@ -251,24 +178,26 @@ impl EnvelopePayload {
251178
}
252179
}
253180

254-
impl<C> Encode<C> for EnvelopePayload {
181+
impl Encode<CborContext> for EnvelopePayload {
255182
fn encode<W: Write>(
256183
&self,
257184
e: &mut Encoder<W>,
258-
_ctx: &mut C,
185+
ctx: &mut CborContext,
259186
) -> Result<(), minicbor::encode::Error<W::Error>> {
260187
e.array(4)?;
261-
e.encode(&self.peer)?.encode(&self.seq)?.u64(self.ver)?;
188+
e.encode(&self.peer)?
189+
.encode_with(self.seq, ctx)?
190+
.u64(self.ver)?;
262191
<W as Write>::write_all(e.writer_mut(), &self.payload)
263192
.map_err(minicbor::encode::Error::write)?;
264193
Ok(())
265194
}
266195
}
267196

268-
impl<'b, C> Decode<'b, C> for EnvelopePayload {
197+
impl<'b> Decode<'b, CborContext> for EnvelopePayload {
269198
fn decode(
270199
d: &mut minicbor::Decoder<'b>,
271-
ctx: &mut C,
200+
ctx: &mut CborContext,
272201
) -> Result<Self, minicbor::decode::Error> {
273202
let len = d.array()?;
274203
match len {
@@ -286,7 +215,7 @@ impl<'b, C> Decode<'b, C> for EnvelopePayload {
286215
}
287216

288217
let peer: PublicKey = d.decode_with(ctx)?;
289-
let seq: UUIDv7 = d.decode_with(ctx)?;
218+
let seq: UuidV7 = d.decode_with(ctx)?;
290219
let ver = d.u64()?;
291220

292221
if ver != PROTOCOL_VERSION {
@@ -393,7 +322,7 @@ impl Envelope {
393322
let mut encoder = Encoder::new(Vec::new());
394323
encoder.array(5)?;
395324
encoder.encode(&self.payload.peer)?;
396-
encoder.encode(&self.payload.seq)?;
325+
encoder.encode_with(self.payload.seq, &mut CborContext::Tagged)?;
397326
encoder.u64(self.payload.ver)?;
398327
encoder
399328
.writer_mut()
@@ -419,10 +348,10 @@ impl<C> Encode<C> for Envelope {
419348
}
420349
}
421350

422-
impl<'b, C> Decode<'b, C> for Envelope {
351+
impl<'b> Decode<'b, CborContext> for Envelope {
423352
fn decode(
424353
d: &mut minicbor::Decoder<'b>,
425-
ctx: &mut C,
354+
ctx: &mut CborContext,
426355
) -> Result<Self, minicbor::decode::Error> {
427356
let signed_payload_bytes = d.bytes()?;
428357
let mut signed_decoder = minicbor::Decoder::new(signed_payload_bytes);
@@ -490,7 +419,7 @@ mod tests {
490419
fn envelope_roundtrip_matches_spec_bstr() {
491420
let signing_key = signing_key();
492421
let payload_body = sample_payload_body();
493-
let payload = EnvelopePayload::now(signing_key.verifying_key(), payload_body.clone())
422+
let payload = EnvelopePayload::new(signing_key.verifying_key(), payload_body.clone())
494423
.expect("payload");
495424

496425
let signature = signing_key
@@ -512,8 +441,9 @@ mod tests {
512441

513442
// Decode fully to ensure `Decode` impl works.
514443
let mut envelope_decoder = Decoder::new(&encoded);
515-
let mut ctx = ();
516-
let decoded: Envelope = envelope_decoder.decode_with(&mut ctx).expect("decode");
444+
let decoded: Envelope = envelope_decoder
445+
.decode_with(&mut CborContext::Tagged)
446+
.expect("decode");
517447
assert_eq!(decoded.payload().payload_bytes(), payload_body.as_slice());
518448
}
519449

@@ -522,7 +452,7 @@ mod tests {
522452
let signing_key = signing_key();
523453
let payload_body = sample_payload_body();
524454
let payload =
525-
EnvelopePayload::now(signing_key.verifying_key(), payload_body).expect("payload");
455+
EnvelopePayload::new(signing_key.verifying_key(), payload_body).expect("payload");
526456

527457
let signature = signing_key
528458
.try_sign(&payload.to_bytes().expect("bytes"))
@@ -531,7 +461,9 @@ mod tests {
531461
let mut signed = Encoder::new(Vec::new());
532462
signed.array(5).unwrap();
533463
signed.encode(&payload.peer).unwrap();
534-
signed.encode(&payload.seq).unwrap();
464+
signed
465+
.encode_with(payload.seq, &mut CborContext::Tagged)
466+
.unwrap();
535467
signed.u64(PROTOCOL_VERSION + 1).unwrap();
536468
<Vec<u8> as Write>::write_all(signed.writer_mut(), &payload.payload).unwrap();
537469
signed.encode(Signature(signature)).unwrap();
@@ -541,8 +473,7 @@ mod tests {
541473
let bytes = envelope.into_writer();
542474

543475
let mut decoder = Decoder::new(&bytes);
544-
let mut ctx = ();
545-
let result: Result<Envelope, _> = decoder.decode_with(&mut ctx);
476+
let result: Result<Envelope, _> = decoder.decode_with(&mut CborContext::Tagged);
546477
assert!(result.is_err(), "expected version mismatch error");
547478
}
548479

@@ -551,7 +482,7 @@ mod tests {
551482
let signing_key = signing_key();
552483
let payload_body = sample_payload_body();
553484
let payload =
554-
EnvelopePayload::now(signing_key.verifying_key(), payload_body).expect("payload");
485+
EnvelopePayload::new(signing_key.verifying_key(), payload_body).expect("payload");
555486

556487
let mut signature = signing_key
557488
.try_sign(&payload.to_bytes().expect("bytes"))
@@ -572,30 +503,7 @@ mod tests {
572503
enc.u8(42).unwrap();
573504
let payload_bytes = enc.into_writer();
574505

575-
let result = EnvelopePayload::now(signing_key.verifying_key(), payload_bytes);
506+
let result = EnvelopePayload::new(signing_key.verifying_key(), payload_bytes);
576507
assert!(result.is_err(), "non-map payload must be rejected");
577508
}
578-
579-
#[test]
580-
fn uuidv7_uses_cbor_tag_37() {
581-
let seq = UUIDv7::now();
582-
let bytes = minicbor::to_vec(&seq).expect("encode");
583-
584-
let mut decoder = Decoder::new(&bytes);
585-
let tag = decoder.tag().expect("tag");
586-
assert_eq!(u64::from(tag), CBOR_TAG_UUID);
587-
}
588-
589-
#[test]
590-
fn uuidv7_decode_rejects_missing_tag() {
591-
let seq = UUIDv7::now();
592-
let mut encoder = Encoder::new(Vec::new());
593-
encoder.bytes(seq.0.as_bytes()).expect("bytes");
594-
let bytes = encoder.into_writer();
595-
596-
let mut decoder = Decoder::new(&bytes);
597-
let mut ctx = ();
598-
let result: Result<UUIDv7, _> = decoder.decode_with(&mut ctx);
599-
assert!(result.is_err(), "untagged UUID must be rejected");
600-
}
601509
}

0 commit comments

Comments
 (0)