1+ // SPDX-License-Identifier: MIT
2+ pragma solidity ^ 0.8.28 ;
3+
4+ import "./CborDecode.sol " ;
5+ import "./Compare.sol " ;
6+
7+ library CidCbor {
8+ using CBORDecoder for bytes ;
9+
10+ uint8 private constant MAJOR_TYPE_TAG = 6 ;
11+ uint8 private constant TAG_CID = 42 ;
12+
13+ uint8 private constant MULTIBASE_FORMAT = 0x00 ;
14+ uint8 private constant CID_V1 = 0x01 ;
15+ uint8 private constant MULTICODEC_DAG_CBOR = 0x71 ;
16+ uint8 private constant MULTIHASH_SHA_256 = 0x12 ;
17+ uint8 private constant MULTIHASH_SIZE_32 = 0x20 ;
18+
19+ struct Cid {
20+ bytes4 prefix;
21+ bytes32 sha;
22+ bool nullish;
23+ }
24+
25+ function cidMatches (Cid memory one , Cid memory other ) internal pure returns (bool ) {
26+ require (! (one.nullish && other.nullish), "two nullish cids should not be compared " );
27+ return Compare.bytesMatch (abi.encodePacked (one.prefix, one.sha, one.nullish), abi.encodePacked (other.prefix, other.sha, other.nullish));
28+ }
29+
30+ function expectCidTag (bytes memory cborData , uint byteIdx ) internal pure returns (uint ) {
31+ uint8 maj;
32+ uint value;
33+ (maj, value, byteIdx) = cborData.parseCborHeader (byteIdx);
34+ require (maj == MAJOR_TYPE_TAG, "expected major type tag " );
35+ require (value == TAG_CID, "expected tag for CID " );
36+ return byteIdx;
37+ }
38+
39+ function readCid (bytes memory cborData , uint byteIdx , bool expectTag ) internal pure returns (Cid memory ret , uint ) {
40+ if (expectTag) {
41+ (byteIdx) = expectCidTag (cborData, byteIdx);
42+ }
43+
44+ if (cborData.isNullNext (byteIdx)) {
45+ ret.nullish = true ;
46+ return (ret, byteIdx + 1 );
47+ }
48+
49+ bytes memory cidBytes;
50+ (cidBytes, byteIdx) = cborData.readBytes (byteIdx);
51+
52+ if (cidBytes.length == 0 ) {
53+ ret.nullish = true ;
54+ return (ret, byteIdx);
55+ }
56+
57+ // multibase format
58+ require (uint8 (cidBytes[0 ]) == MULTIBASE_FORMAT, "expected multibase item " );
59+
60+ // cid prefix
61+ require (uint8 (cidBytes[1 ]) == CID_V1, "expected CID v1 " );
62+ require (uint8 (cidBytes[2 ]) == MULTICODEC_DAG_CBOR, "expected CID multicodec DAG-CBOR " );
63+ require (uint8 (cidBytes[3 ]) == MULTIHASH_SHA_256, "expected CID multihash sha-256 " );
64+ require (uint8 (cidBytes[4 ]) == MULTIHASH_SIZE_32, "expected CID content size 32 bytes " );
65+
66+ ret.prefix = bytes4 (abi.encodePacked (
67+ cidBytes[1 ], cidBytes[2 ], cidBytes[3 ], cidBytes[4 ]
68+ ));
69+
70+ // cid data length plus prefix length
71+ require (cidBytes.length == 1 + 4 + MULTIHASH_SIZE_32, "expected cid data to be 37 bytes " );
72+
73+ // TODO: ;_;
74+ bytes memory shaBytes = new bytes (32 );
75+ for (uint i = 0 ; i < 32 ; i++ ) {
76+ shaBytes[i] = cidBytes[5 + i];
77+ }
78+ ret.sha = bytes32 (shaBytes);
79+
80+ return (ret, byteIdx);
81+ }
82+ }
0 commit comments