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

Commit 3eff4e1

Browse files
bors[bot]cdata
andauthored
Merge #493
493: Strict ordering for DAG-CBOR-encoded map keys r=koivunej a=cdata This change proposes a fix for #492 . `Ipld::Map` keys are sorted according to [the strictness guidelines in the DAG-CBOR spec](https://github.com/ipld/ipld/blob/master/specs/codecs/dag-cbor/spec.md#:~:text=The%20keys%20in,order%20sorts%20earlier.) when encoding them as DAG-CBOR. Co-authored-by: Chris Joel <[email protected]> Co-authored-by: Christopher Joel <[email protected]>
2 parents a78a623 + 80d2b79 commit 3eff4e1

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* perf: use hash_hasher where the key is Cid [#467]
1313
* chore: upgrade to libp2p 0.39.1, update most of the other deps with the notable exception of cid and multihash [#472]
1414
* refactor(swarm): swarm cleanup following libp2p upgrade to v0.39.1 [#473]
15+
* fix: strict ordering for DAG-CBOR-encoded map keys [#493]
1516

1617
[#429]: https://github.com/rs-ipfs/rust-ipfs/pull/429
1718
[#428]: https://github.com/rs-ipfs/rust-ipfs/pull/428
@@ -27,6 +28,7 @@
2728
[#467]: https://github.com/rs-ipfs/rust-ipfs/pull/467
2829
[#472]: https://github.com/rs-ipfs/rust-ipfs/pull/472
2930
[#473]: https://github.com/rs-ipfs/rust-ipfs/pull/473
31+
[#493]: https://github.com/rs-ipfs/rust-ipfs/pull/493
3032

3133
# 0.2.1
3234

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: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,10 +321,17 @@ impl<T: WriteCbor + 'static> WriteCbor for BTreeMap<String, T> {
321321
#[inline]
322322
fn write_cbor<W: Write>(&self, w: &mut W) -> CborResult<()> {
323323
write_u64(w, 5, self.len() as u64)?;
324-
for (k, v) in self {
324+
let mut keys: Vec<&String> = self.keys().collect();
325+
326+
// See: https://github.com/ipld/ipld/blob/master/specs/codecs/dag-cbor/spec.md#strictness
327+
keys.sort_by(|l, r| l.len().cmp(&r.len()).then_with(|| l.cmp(r)));
328+
329+
for k in keys {
330+
let v = self.get(k).unwrap();
325331
k.write_cbor(w)?;
326332
v.write_cbor(w)?;
327333
}
334+
328335
Ok(())
329336
}
330337
}

0 commit comments

Comments
 (0)