Skip to content

Commit 9b8c60c

Browse files
committed
more complete tests, fix entries
1 parent 86757ff commit 9b8c60c

File tree

6 files changed

+53
-135
lines changed

6 files changed

+53
-135
lines changed

src/CborDecode.sol

Lines changed: 1 addition & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,6 @@
2020
// SPDX-License-Identifier: Apache-2.0
2121
pragma solidity ^0.8.17;
2222

23-
// MajUnsignedInt = 0
24-
// MajSignedInt = 1
25-
// MajByteString = 2
26-
// MajTextString = 3
27-
// MajArray = 4
28-
// MajMap = 5
29-
// MajTag = 6
30-
// MajOther = 7
3123

3224
uint8 constant MajUnsignedInt = 0;
3325
uint8 constant MajSignedInt = 1;
@@ -38,9 +30,6 @@ uint8 constant MajMap = 5;
3830
uint8 constant MajTag = 6;
3931
uint8 constant MajOther = 7;
4032

41-
uint8 constant TagTypeBigNum = 2;
42-
uint8 constant TagTypeNegativeBigNum = 3;
43-
4433
uint8 constant True_Type = 21;
4534
uint8 constant False_Type = 20;
4635

@@ -130,12 +119,7 @@ library CBORDecoder {
130119
uint len;
131120

132121
(maj, len, byteIdx) = parseCborHeader(cborData, byteIdx);
133-
require(maj == MajTag || maj == MajByteString, "invalid maj (expected MajTag or MajByteString)");
134-
135-
if (maj == MajTag) {
136-
(maj, len, byteIdx) = parseCborHeader(cborData, byteIdx);
137-
assert(maj == MajByteString);
138-
}
122+
require(maj == MajByteString, "invalid maj (expected MajByteString)");
139123

140124
uint max_len = byteIdx + len;
141125
bytes memory slice = new bytes(len);
@@ -148,86 +132,6 @@ library CBORDecoder {
148132
return (slice, byteIdx + len);
149133
}
150134

151-
/// @notice attempt to read a bytes32 value
152-
/// @param cborData cbor encoded bytes to parse from
153-
/// @param byteIdx current position to read on the cbor encoded bytes
154-
/// @return a bytes32 decoded from input bytes and the byte index after moving past the value
155-
function readBytes32(bytes memory cborData, uint byteIdx) internal pure returns (bytes32, uint) {
156-
uint8 maj;
157-
uint len;
158-
159-
(maj, len, byteIdx) = parseCborHeader(cborData, byteIdx);
160-
require(maj == MajByteString, "invalid maj (expected MajByteString)");
161-
162-
uint max_len = byteIdx + len;
163-
bytes memory slice = new bytes(32);
164-
uint slice_index = 32 - len;
165-
for (uint256 i = byteIdx; i < max_len; i++) {
166-
slice[slice_index] = cborData[i];
167-
slice_index++;
168-
}
169-
170-
return (bytes32(slice), byteIdx + len);
171-
}
172-
173-
/// @notice attempt to read a uint256 value encoded per cbor specification
174-
/// @param cborData cbor encoded bytes to parse from
175-
/// @param byteIdx current position to read on the cbor encoded bytes
176-
/// @return an uint256 decoded from input bytes and the byte index after moving past the value
177-
function readUInt256(bytes memory cborData, uint byteIdx) internal pure returns (uint256, uint) {
178-
uint8 maj;
179-
uint256 value;
180-
181-
(maj, value, byteIdx) = parseCborHeader(cborData, byteIdx);
182-
require(maj == MajTag || maj == MajUnsignedInt, "invalid maj (expected MajTag or MajUnsignedInt)");
183-
184-
if (maj == MajTag) {
185-
require(value == TagTypeBigNum, "invalid tag (expected TagTypeBigNum)");
186-
187-
uint len;
188-
(maj, len, byteIdx) = parseCborHeader(cborData, byteIdx);
189-
require(maj == MajByteString, "invalid maj (expected MajByteString)");
190-
191-
require(cborData.length >= byteIdx + len, "slicing out of range");
192-
assembly {
193-
value := mload(add(cborData, add(len, byteIdx)))
194-
}
195-
196-
return (value, byteIdx + len);
197-
}
198-
199-
return (value, byteIdx);
200-
}
201-
202-
/// @notice attempt to read a int256 value encoded per cbor specification
203-
/// @param cborData cbor encoded bytes to parse from
204-
/// @param byteIdx current position to read on the cbor encoded bytes
205-
/// @return an int256 decoded from input bytes and the byte index after moving past the value
206-
function readInt256(bytes memory cborData, uint byteIdx) internal pure returns (int256, uint) {
207-
uint8 maj;
208-
uint value;
209-
210-
(maj, value, byteIdx) = parseCborHeader(cborData, byteIdx);
211-
require(maj == MajTag || maj == MajSignedInt, "invalid maj (expected MajTag or MajSignedInt)");
212-
213-
if (maj == MajTag) {
214-
assert(value == TagTypeNegativeBigNum);
215-
216-
uint len;
217-
(maj, len, byteIdx) = parseCborHeader(cborData, byteIdx);
218-
require(maj == MajByteString, "invalid maj (expected MajByteString)");
219-
220-
require(cborData.length >= byteIdx + len, "slicing out of range");
221-
assembly {
222-
value := mload(add(cborData, add(len, byteIdx)))
223-
}
224-
225-
return (int256(value), byteIdx + len);
226-
}
227-
228-
return (int256(value), byteIdx);
229-
}
230-
231135
/// @notice attempt to read a uint64 value
232136
/// @param cborData cbor encoded bytes to parse from
233137
/// @param byteIdx current position to read on the cbor encoded bytes

src/CidCbor.sol

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.28;
33

4+
45
import "./CborDecode.sol";
56
import "./Compare.sol";
67

@@ -38,28 +39,24 @@ library CidCbor {
3839
return byteIdx;
3940
}
4041

41-
function readCid(bytes memory cborData, uint byteIdx, bool expectTag)
42-
internal
43-
pure
44-
returns (Cid memory ret, uint)
45-
{
46-
if (expectTag) {
47-
(byteIdx) = expectCidTag(cborData, byteIdx);
42+
function readCid(bytes memory cborData, uint byteIdx) internal pure returns (Cid memory, uint) {
43+
bool nullish = false;
44+
45+
if (cborData.isNullNext(byteIdx)) {
46+
nullish = true;
47+
return (Cid(bytes4(0), bytes32(0), nullish), byteIdx + 1);
4848
}
4949

50+
(byteIdx) = CidCbor.expectCidTag(cborData, byteIdx);
51+
5052
if (cborData.isNullNext(byteIdx)) {
51-
ret.nullish = true;
52-
return (ret, byteIdx + 1);
53+
nullish = true;
54+
return (Cid(bytes4(0), bytes32(0), nullish), byteIdx + 1);
5355
}
5456

5557
bytes memory cidBytes;
5658
(cidBytes, byteIdx) = cborData.readBytes(byteIdx);
5759

58-
if (cidBytes.length == 0) {
59-
ret.nullish = true;
60-
return (ret, byteIdx);
61-
}
62-
6360
// multibase format
6461
require(uint8(cidBytes[0]) == MULTIBASE_FORMAT, "expected multibase item");
6562

@@ -69,18 +66,17 @@ library CidCbor {
6966
require(uint8(cidBytes[3]) == MULTIHASH_SHA_256, "expected CID multihash sha-256");
7067
require(uint8(cidBytes[4]) == MULTIHASH_SIZE_32, "expected CID content size 32 bytes");
7168

72-
ret.prefix = bytes4(abi.encodePacked(cidBytes[1], cidBytes[2], cidBytes[3], cidBytes[4]));
69+
bytes4 prefix = bytes4(abi.encodePacked(cidBytes[1], cidBytes[2], cidBytes[3], cidBytes[4]));
7370

7471
// cid data length plus prefix length
7572
require(cidBytes.length == 1 + 4 + MULTIHASH_SIZE_32, "expected cid data to be 37 bytes");
7673

77-
// TODO: ;_;
78-
bytes memory shaBytes = new bytes(32);
74+
75+
bytes memory sha = new bytes(32);
7976
for (uint i = 0; i < 32; i++) {
80-
shaBytes[i] = cidBytes[5 + i];
77+
sha[i] = cidBytes[5 + i];
8178
}
82-
ret.sha = bytes32(shaBytes);
8379

84-
return (ret, byteIdx);
80+
return (Cid(prefix, bytes32(sha), nullish), byteIdx);
8581
}
8682
}

src/CommitCbor.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ library CommitCbor {
3333
(ret.version, byteIdx) = cborData.readUInt8(byteIdx);
3434
require(ret.version == COMMIT_VERSION, "unexpected commit version");
3535
} else if (Compare.stringsMatch(mapKey, "data")) {
36-
(ret.data, byteIdx) = CidCbor.readCid(cborData, byteIdx, false);
36+
(ret.data, byteIdx) = CidCbor.readCid(cborData, byteIdx);
3737
} else if (Compare.stringsMatch(mapKey, "rev")) {
3838
(ret.rev, byteIdx) = cborData.readString(byteIdx);
3939
} else if (Compare.stringsMatch(mapKey, "prev")) {
40-
(ret.prev, byteIdx) = CidCbor.readCid(cborData, byteIdx, false);
40+
(ret.prev, byteIdx) = CidCbor.readCid(cborData, byteIdx);
4141
}
4242
}
4343

src/TreeNodeCbor.sol

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
pragma solidity ^0.8.28;
33

44
import "./CidCbor.sol";
5+
import "./Compare.sol";
56

67
library TreeNodeCbor {
78
using CBORDecoder for bytes;
@@ -36,30 +37,36 @@ library TreeNodeCbor {
3637
return (ret, byteIdx);
3738
}
3839

39-
function readE(bytes memory cborData, uint byteIdx) internal pure returns (TreeNodeE memory ret, uint) {
40+
function readE(bytes memory cborData, uint byteIdx) internal pure returns (TreeNodeE memory, uint) {
4041
uint mapLen;
4142
(mapLen, byteIdx) = cborData.readFixedMap(byteIdx);
4243

4344
require(mapLen == 4, "expected 4 fields in node entry");
45+
46+
uint8 p;
47+
bytes memory k;
48+
CidCbor.Cid memory v;
49+
CidCbor.Cid memory t;
50+
4451
for (uint i = 0; i < mapLen; i++) {
4552
string memory mapKey;
4653
(mapKey, byteIdx) = cborData.readString(byteIdx);
4754
if (Compare.stringsMatch(mapKey, "p")) {
48-
(ret.p, byteIdx) = cborData.readUInt8(byteIdx);
55+
(p, byteIdx) = cborData.readUInt8(byteIdx);
4956
} else if (Compare.stringsMatch(mapKey, "k")) {
50-
(ret.k, byteIdx) = cborData.readBytes(byteIdx);
57+
(k, byteIdx) = cborData.readBytes(byteIdx);
5158
} else if (Compare.stringsMatch(mapKey, "t")) {
52-
(ret.t, byteIdx) = CidCbor.readCid(cborData, byteIdx, false);
59+
(t, byteIdx) = CidCbor.readCid(cborData, byteIdx);
5360
} else if (Compare.stringsMatch(mapKey, "v")) {
54-
(ret.v, byteIdx) = CidCbor.readCid(cborData, byteIdx, false);
61+
(v, byteIdx) = CidCbor.readCid(cborData, byteIdx);
5562
}
5663
}
5764

58-
return (ret, byteIdx);
65+
return (TreeNodeE(p, k, v, t), byteIdx);
5966
}
6067

61-
function buildEntryKeys(TreeNodeE[] memory e) internal pure returns (TreeNodeEntry[] memory entries) {
62-
entries = new TreeNodeEntry[](e.length);
68+
function buildEntryKeys(TreeNodeE[] memory e) internal pure returns (TreeNodeEntry[] memory) {
69+
TreeNodeEntry[] memory entries = new TreeNodeEntry[](e.length);
6370
bytes memory previousKey = new bytes(0);
6471
for (uint i = 0; i < e.length; i++) {
6572
uint8 p = e[i].p;
@@ -71,7 +78,7 @@ library TreeNodeCbor {
7178
for (uint j = p; j < p + k.length; j++) {
7279
key[j] = k[j - p];
7380
}
74-
entries[i].key = string(key);
81+
entries[i] = TreeNodeEntry(string(key), e[i].v, e[i].t);
7582
previousKey = key;
7683
}
7784
return entries;
@@ -85,7 +92,7 @@ library TreeNodeCbor {
8592
string memory mapKey;
8693
(mapKey, byteIdx) = cborData.readString(byteIdx);
8794
if (Compare.stringsMatch(mapKey, "l")) {
88-
(node.left, byteIdx) = CidCbor.readCid(cborData, byteIdx, false);
95+
(node.left, byteIdx) = CidCbor.readCid(cborData, byteIdx);
8996
} else if (Compare.stringsMatch(mapKey, "e")) {
9097
TreeNodeE[] memory e;
9198
(e, byteIdx) = readNodeE(cborData, byteIdx);

test/CommitCbor.t.sol

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ contract CommitCborTest {
1212

1313
(CommitCbor.Commit memory commit, uint byteIdx) = CommitCbor.readCommit(rootCommitData, 0);
1414

15-
console.log("byteIdx: %s", byteIdx);
16-
console.log("did: %s", commit.did);
17-
console.log("version: %s", commit.version);
18-
console.log("rev: %s", commit.rev);
15+
require(byteIdx == rootCommitData.length, "expected to read all bytes");
16+
require(commit.version == 3, "expected version 3");
17+
require(bytes(commit.rev).length == 13, "expected rev to be 13 bytes");
18+
require(bytes(commit.did).length == 32, "expected did to be 32 bytes");
19+
require(commit.data.nullish == false, "expected data cid to be non-null");
20+
require(Compare.bytesMatch(abi.encodePacked(commit.data.sha), hex"66da6655bf8da79b69a87299cf170fed8497fa3059379dc4a8bfe1e28cab5d93"), "expected cid hash");
21+
require(Compare.bytesMatch(abi.encodePacked(commit.data.prefix), hex"01711220"), "expected data cid prefix to be 01711220");
1922
}
2023
}

test/TreeNodeCbor.t.sol

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,15 @@ contract TreeNodeCborTest {
1212

1313
(TreeNodeCbor.TreeNode memory node, uint byteIdx) = TreeNodeCbor.readTreeNode(treeNode, 0);
1414

15-
console.log("byteIdx: %s", byteIdx);
16-
console.log("entries: %s", node.entries.length);
15+
require(byteIdx == treeNode.length, "expected to read all bytes");
16+
require(node.entries.length == 5, "expected 5 entries");
17+
18+
require(Compare.bytesMatch(abi.encodePacked(node.left.sha), hex"6e7335ed248edae3ed49d47b88a5fcad2985e15f416f8ae23a49dfc1231aeb91"), "left sha");
19+
for (uint i = 0; i < node.entries.length; i++) {
20+
console.log("node entry %s", i);
21+
console.log(node.entries[i].key);
22+
console.logBytes32(node.entries[i].value.sha);
23+
console.logBytes32(node.entries[i].tree.sha);
24+
}
1725
}
1826
}

0 commit comments

Comments
 (0)