Skip to content
This repository was archived by the owner on Oct 23, 2022. It is now read-only.

Commit c843f07

Browse files
committed
Strict ordering for DAG-CBOR-encoded map keys
1 parent a78a623 commit c843f07

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

src/dag.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ fn resolve_local_ipld<'a>(
598598
#[cfg(test)]
599599
mod tests {
600600
use super::*;
601-
use crate::{make_ipld, Node};
601+
use crate::{ipld::dag_cbor::DagCborCodec, make_ipld, Node};
602602

603603
#[tokio::test]
604604
async fn test_resolve_root_cid() {
@@ -996,4 +996,24 @@ mod tests {
996996
format!("no link named \"second-best-file\" under {}", cids[1])
997997
);
998998
}
999+
1000+
#[test]
1001+
fn observes_strict_order_of_map_keys() {
1002+
let map = make_ipld!({
1003+
"omega": Ipld::Null,
1004+
"bar": Ipld::Null,
1005+
"alpha": Ipld::Null,
1006+
"foo": Ipld::Null,
1007+
});
1008+
1009+
let bytes = DagCborCodec::encode(&map).unwrap();
1010+
1011+
assert_eq!(
1012+
bytes.as_ref(),
1013+
&[
1014+
164, 99, 98, 97, 114, 246, 99, 102, 111, 111, 246, 101, 97, 108, 112, 104, 97, 246,
1015+
101, 111, 109, 101, 103, 97, 246
1016+
]
1017+
);
1018+
}
9991019
}

src/ipld/dag_cbor.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::ipld::{BlockError, Ipld, IpldError};
44
use byteorder::{BigEndian, ByteOrder};
55
use cid::Cid;
66
use std::{
7+
cmp::Ordering,
78
collections::BTreeMap,
89
convert::TryFrom,
910
io::{Read, Write},
@@ -321,10 +322,25 @@ impl<T: WriteCbor + 'static> WriteCbor for BTreeMap<String, T> {
321322
#[inline]
322323
fn write_cbor<W: Write>(&self, w: &mut W) -> CborResult<()> {
323324
write_u64(w, 5, self.len() as u64)?;
324-
for (k, v) in self {
325+
let mut keys: Vec<&String> = self.keys().collect();
326+
327+
// See: https://github.com/ipld/ipld/blob/master/specs/codecs/dag-cbor/spec.md#strictness
328+
keys.sort_by(|l, r| {
329+
if r.len() > l.len() {
330+
Ordering::Less
331+
} else if r.len() < l.len() {
332+
Ordering::Greater
333+
} else {
334+
l.partial_cmp(r).or(Some(Ordering::Equal)).unwrap()
335+
}
336+
});
337+
338+
for k in keys {
339+
let v = self.get(k).unwrap();
325340
k.write_cbor(w)?;
326341
v.write_cbor(w)?;
327342
}
343+
328344
Ok(())
329345
}
330346
}

0 commit comments

Comments
 (0)