Skip to content

Commit 021c01f

Browse files
committed
skip unused fields, add detail tests
1 parent e346b84 commit 021c01f

File tree

7 files changed

+79
-131
lines changed

7 files changed

+79
-131
lines changed

src/CborDecode.sol

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,14 @@ library CBORDecoder {
147147
return (cborData[byteIdx], byteIdx + len);
148148
}
149149

150+
function skipString(bytes memory cborData, uint byteIdx) internal pure returns (uint) {
151+
uint8 maj;
152+
uint len;
153+
(maj, len, byteIdx) = parseCborHeader(cborData, byteIdx);
154+
require(maj == MajTextString, "invalid maj (expected MajTextString)");
155+
return byteIdx + len;
156+
}
157+
150158
/// @notice attempt to read an arbitrary length string value
151159
/// @param cborData cbor encoded bytes to parse from
152160
/// @param byteIdx current position to read on the cbor encoded bytes

src/CommitCbor.sol

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,22 @@ library CommitCbor {
2323
require(mapLen == 5, "expected 5 fields in commit");
2424

2525
for (uint i = 0; i < mapLen; i++) {
26-
bytes8 mapKey;
27-
(mapKey, byteIdx) = cborData.readStringBytes8(byteIdx);
28-
if ((mapKey == "did")) {
29-
(ret.did, byteIdx) = cborData.readString(byteIdx);
30-
require(bytes(ret.did).length == 32, "did string must be 32 bytes");
31-
} else if ((mapKey == "version")) {
26+
bytes memory mapKey;
27+
(mapKey, byteIdx) = cborData.readStringBytes(byteIdx);
28+
if (bytes8(mapKey) == "version") {
3229
(ret.version, byteIdx) = cborData.readUInt8(byteIdx);
33-
require(ret.version == COMMIT_VERSION, "unexpected commit version");
34-
} else if ((mapKey == "data")) {
30+
require(ret.version == COMMIT_VERSION, "commit version number must be 3");
31+
} else if (bytes5(mapKey) == "data") {
3532
(ret.data, byteIdx) = CidCbor.readCidIndex(cborData, byteIdx);
36-
} else if ((mapKey == "rev")) {
37-
(ret.rev, byteIdx) = cborData.readString(byteIdx);
38-
} else if ((mapKey == "prev")) {
33+
} else if (bytes5(mapKey) == "prev") {
3934
(ret.prev, byteIdx) = CidCbor.readNullableCidIndex(cborData, byteIdx);
35+
} else if (bytes4(mapKey) == "did") {
36+
(ret.did, byteIdx) = cborData.readString(byteIdx);
37+
require(bytes(ret.did).length == 32, "commit did string must be 32 bytes");
38+
} else if (bytes4(mapKey) == "rev") {
39+
(ret.rev, byteIdx) = cborData.readString(byteIdx);
4040
} else {
41-
revert("unexpected commit key");
41+
revert("unexpected commit field");
4242
}
4343
}
4444

src/RecordCbor.sol

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ library RecordCbor {
99
struct Record {
1010
string text;
1111
string dollarType;
12-
string[] langs;
13-
string createdAt;
1412
}
1513

1614
function readRecord(bytes memory cborData, uint byteIdx) internal pure returns (Record memory, uint) {
@@ -21,30 +19,27 @@ library RecordCbor {
2119

2220
string memory text;
2321
string memory dollarType;
24-
string[] memory langs;
25-
string memory createdAt;
2622

2723
for (uint i = 0; i < mapLen; i++) {
28-
bytes10 mapKey;
29-
(mapKey, byteIdx) = cborData.readStringBytes10(byteIdx);
30-
if (mapKey == "text") {
24+
bytes memory mapKey;
25+
(mapKey, byteIdx) = cborData.readStringBytes(byteIdx);
26+
if (bytes5(mapKey) == "text") {
3127
(text, byteIdx) = cborData.readString(byteIdx);
32-
} else if (mapKey == "$type") {
28+
} else if (bytes6(mapKey) == "$type") {
3329
(dollarType, byteIdx) = cborData.readString(byteIdx);
34-
} else if (mapKey == "langs") {
35-
uint arrayLength;
36-
(arrayLength, byteIdx) = cborData.readFixedArray(byteIdx);
37-
langs = new string[](arrayLength);
38-
for (uint j = 0; j < arrayLength; j++) {
39-
(langs[j], byteIdx) = cborData.readString(byteIdx);
30+
} else if (bytes6(mapKey) == "langs") {
31+
uint langsLength;
32+
(langsLength, byteIdx) = cborData.readFixedArray(byteIdx);
33+
for (uint j = 0; j < langsLength; j++) {
34+
byteIdx = cborData.skipString(byteIdx);
4035
}
41-
} else if (mapKey == "createdAt") {
42-
(createdAt, byteIdx) = cborData.readString(byteIdx);
36+
} else if (bytes10(mapKey) == "createdAt") {
37+
byteIdx = cborData.skipString(byteIdx);
4338
} else {
4439
revert("unexpected record key");
4540
}
4641
}
4742

48-
return (Record(text, dollarType, langs, createdAt), byteIdx);
43+
return (Record(text, dollarType), byteIdx);
4944
}
5045
}

src/TreeCbor.sol

Lines changed: 11 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,115 +4,63 @@ pragma solidity ^0.8.28;
44
import "./CborDecode.sol";
55
import "./CidCbor.sol";
66
import "./TreeNodeCbor.sol";
7-
import "./RecordCbor.sol";
87

98
library TreeCbor {
109
using CBORDecoder for bytes;
1110

12-
uint8 private constant CID_V1 = 0x01;
13-
uint8 private constant MULTICODEC_DAG_CBOR = 0x71;
14-
uint8 private constant MULTIHASH_SHA_256 = 0x12;
15-
uint8 private constant MULTIHASH_SIZE_32 = 0x20;
16-
1711
struct Tree {
18-
CidCbor.CidBytes32 root;
1912
TreeNodeCbor.TreeNode[] nodes;
20-
RecordCbor.Record[] records;
2113
CidCbor.CidBytes32[] cids;
22-
bool[] nodeOrRecord;
23-
}
24-
25-
function itemIsNode(bytes memory cborData) internal pure returns (bool) {
26-
(uint len, uint byteIdx) = cborData.readFixedMap(0);
27-
28-
string memory itemName;
29-
(itemName, byteIdx) = cborData.readString(byteIdx);
30-
return len == 2;
3114
}
3215

33-
function readTree(bytes[] memory cborData, CidCbor.CidBytes32 root) internal pure returns (Tree memory) {
16+
function _readTree(bytes[] memory cborData) internal pure returns (Tree memory) {
3417
TreeNodeCbor.TreeNode[] memory nodes = new TreeNodeCbor.TreeNode[](cborData.length);
35-
RecordCbor.Record[] memory records = new RecordCbor.Record[](cborData.length);
3618
CidCbor.CidBytes32[] memory cids = new CidCbor.CidBytes32[](cborData.length);
37-
bool[] memory nodeOrRecord = new bool[](cborData.length);
3819

3920
for (uint i = 0; i < cborData.length; i++) {
4021
cids[i] = CidCbor.CidBytes32.wrap(sha256(cborData[i]));
4122
uint byteIdx;
42-
if (itemIsNode(cborData[i])) {
43-
(nodes[i], byteIdx) = TreeNodeCbor.readTreeNode(cborData[i], 0);
44-
nodeOrRecord[i] = true;
45-
} else {
46-
(records[i], byteIdx) = RecordCbor.readRecord(cborData[i], 0);
47-
nodeOrRecord[i] = false;
48-
}
23+
(nodes[i], byteIdx) = TreeNodeCbor.readTreeNode(cborData[i], 0);
4924
require(byteIdx == cborData[i].length, "expected to read all bytes");
5025
}
5126

52-
return requireUniqueCidsAndRoot(Tree(root, nodes, records, cids, nodeOrRecord));
27+
return Tree(nodes, cids);
28+
}
29+
30+
function readTree(bytes[] memory cborData) internal pure returns (Tree memory) {
31+
return requireUniqueCids(_readTree(cborData));
5332
}
5433

55-
function nodeByCid(Tree memory tree, CidCbor.CidBytes32 indexCid)
34+
function getCid(Tree memory tree, CidCbor.CidBytes32 indexCid)
5635
internal
5736
pure
5837
returns (TreeNodeCbor.TreeNode memory, uint index)
5938
{
60-
return nodeByCid(tree, indexCid, 0);
39+
return getCid(tree, indexCid, 0);
6140
}
6241

63-
function nodeByCid(Tree memory tree, CidCbor.CidBytes32 indexCid, uint startIdx)
42+
function getCid(Tree memory tree, CidCbor.CidBytes32 indexCid, uint startIdx)
6443
internal
6544
pure
6645
returns (TreeNodeCbor.TreeNode memory, uint index)
6746
{
6847
bytes32 indexBytes = CidCbor.CidBytes32.unwrap(indexCid);
6948
for (uint i = startIdx; i < tree.cids.length; i++) {
7049
if (CidCbor.CidBytes32.unwrap(tree.cids[i]) == indexBytes) {
71-
require(tree.nodeOrRecord[i], "expected node");
7250
return (tree.nodes[i], i);
7351
}
7452
}
7553
revert("node not found");
7654
}
7755

78-
function recordByCid(Tree memory tree, CidCbor.CidBytes32 indexCid)
79-
internal
80-
pure
81-
returns (RecordCbor.Record memory, uint index)
82-
{
83-
return recordByCid(tree, indexCid, 0);
84-
}
85-
86-
function recordByCid(Tree memory tree, CidCbor.CidBytes32 indexCid, uint startIdx)
87-
internal
88-
pure
89-
returns (RecordCbor.Record memory, uint index)
90-
{
91-
bytes32 indexBytes = CidCbor.CidBytes32.unwrap(indexCid);
92-
93-
for (uint i = startIdx; i < tree.cids.length; i++) {
94-
if (CidCbor.CidBytes32.unwrap(tree.cids[i]) == indexBytes) {
95-
require(!tree.nodeOrRecord[i], "expected record");
96-
return (tree.records[i], i);
97-
}
98-
}
99-
revert("record not found");
100-
}
101-
102-
function requireUniqueCidsAndRoot(Tree memory tree) internal pure returns (Tree memory) {
103-
bool rootIncluded;
104-
bytes32 treeRoot = CidCbor.CidBytes32.unwrap(tree.root);
56+
function requireUniqueCids(Tree memory tree) internal pure returns (Tree memory) {
10557
for (uint i = 0; i < tree.cids.length; i++) {
10658
bytes32 thisCid = CidCbor.CidBytes32.unwrap(tree.cids[i]);
107-
if (!rootIncluded) {
108-
rootIncluded = thisCid == treeRoot;
109-
}
11059
for (uint j = i + 1; j < tree.nodes.length; j++) {
11160
bytes32 otherCid = CidCbor.CidBytes32.unwrap(tree.cids[j]);
11261
require(thisCid != otherCid, "node cids must be unique");
11362
}
11463
}
115-
require(rootIncluded, "root cid must be included");
11664
return tree;
11765
}
11866
}

test/CborDecode.t.sol

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,22 +162,22 @@ contract CborDecodeTest {
162162
(mapLen, index) = input.readFixedMap(index);
163163
require(mapLen == 3, "map len is not 2");
164164

165-
string memory mapKey;
165+
bytes1 mapKey;
166166
uint8 mapValue;
167-
(mapKey, index) = input.readString(index);
168-
require(keccak256(abi.encodePacked(mapKey)) == keccak256(abi.encodePacked("a")), "map key is not 'a'");
167+
(mapKey, index) = input.readStringBytes1(index);
168+
require(mapKey == bytes1("a"), "map key is not 'a'");
169169

170170
(mapValue, index) = input.readUInt8(index);
171171
require(mapValue == 1, "map value is not 1");
172172

173-
(mapKey, index) = input.readString(index);
174-
require(keccak256(abi.encodePacked(mapKey)) == keccak256(abi.encodePacked("b")), "map key is not 'b'");
173+
(mapKey, index) = input.readStringBytes1(index);
174+
require(mapKey == bytes1("b"), "map key is not 'b'");
175175

176176
(mapValue, index) = input.readUInt8(index);
177177
require(mapValue == 2, "map value is not 2");
178178

179-
(mapKey, index) = input.readString(index);
180-
require(keccak256(abi.encodePacked(mapKey)) == keccak256(abi.encodePacked("c")), "map key is not 'c'");
179+
(mapKey, index) = input.readStringBytes1(index);
180+
require(mapKey == bytes1("c"), "map key is not 'c'");
181181

182182
(mapValue, index) = input.readUInt8(index);
183183
require(mapValue == 3, "map value is not 3");

test/RecordCbor.t.sol

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,5 @@ contract RecordCborTest {
1919

2020
console.log("text", record.text);
2121
console.log("$type", record.dollarType);
22-
for (uint i = 0; i < record.langs.length; i++) {
23-
console.log("lang", i, record.langs[i]);
24-
}
25-
console.log("createdAt", record.createdAt);
2622
}
2723
}

0 commit comments

Comments
 (0)