Skip to content

Commit c4ba1d2

Browse files
committed
add eq, neq operators to cid
1 parent 335e585 commit c4ba1d2

File tree

7 files changed

+67
-70
lines changed

7 files changed

+67
-70
lines changed

src/CidCbor.sol

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,22 @@ pragma solidity ^0.8.28;
33

44
import "./CborDecode.sol";
55

6+
using {cidEq as ==, cidNeq as !=} for Cid global;
7+
8+
/**
9+
* we will only encounter Cid v1 dag-cbor sha256, so the entire hash is 32
10+
* bytes and will fit in a uint256
11+
*/
12+
type Cid is uint256;
13+
14+
function cidEq(Cid a, Cid b) pure returns (bool) {
15+
return Cid.unwrap(a) == Cid.unwrap(b);
16+
}
17+
18+
function cidNeq(Cid a, Cid b) pure returns (bool) {
19+
return Cid.unwrap(a) != Cid.unwrap(b);
20+
}
21+
622
library CidCbor {
723
using CBORDecoder for bytes;
824

@@ -14,12 +30,6 @@ library CidCbor {
1430
uint8 private constant MULTIHASH_SHA_256 = 0x12;
1531
uint8 private constant MULTIHASH_SIZE_32 = 0x20;
1632

17-
/**
18-
* we will only encounter Cid v1 dag-cbor sha256, so the entire hash is 32
19-
* bytes and will fit in a uint256
20-
*/
21-
type Cid is uint256;
22-
2333
function expectTagCid(bytes memory cborData, uint byteIdx) internal pure returns (uint) {
2434
uint8 head = uint8(cborData[byteIdx]);
2535
uint8 tagValue = uint8(cborData[byteIdx + 1]);

src/CommitCbor.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ library CommitCbor {
1111
struct Commit {
1212
string did;
1313
uint8 version;
14-
CidCbor.Cid data;
14+
Cid data;
1515
string rev;
16-
CidCbor.Cid prev;
16+
Cid prev;
1717
}
1818

1919
function readCommit(bytes memory cborData, uint byteIdx) internal pure returns (Commit memory ret, uint) {

src/TreeCbor.sol

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ library TreeCbor {
1010

1111
struct Tree {
1212
TreeNodeCbor.TreeNode[] nodes;
13-
CidCbor.Cid[] cids;
13+
Cid[] cids;
1414
}
1515

1616
function _readTree(bytes[] memory cborData) internal pure returns (Tree memory) {
1717
require(cborData.length > 0, "Tree must contain nodes");
1818
TreeNodeCbor.TreeNode[] memory nodes = new TreeNodeCbor.TreeNode[](cborData.length);
19-
CidCbor.Cid[] memory cids = new CidCbor.Cid[](cborData.length);
19+
Cid[] memory cids = new Cid[](cborData.length);
2020

2121
for (uint i = 0; i < cborData.length; i++) {
22-
cids[i] = CidCbor.Cid.wrap(uint256(sha256(cborData[i])));
22+
cids[i] = Cid.wrap(uint256(sha256(cborData[i])));
2323
uint byteIdx;
2424
(nodes[i], byteIdx) = TreeNodeCbor.readTreeNode(cborData[i], 0);
2525
require(byteIdx == cborData[i].length, "expected to read all bytes");
@@ -32,14 +32,13 @@ library TreeCbor {
3232
return validTree(_readTree(cborData));
3333
}
3434

35-
function hasCid(Tree memory tree, CidCbor.Cid cid) internal pure returns (bool, uint) {
35+
function hasCid(Tree memory tree, Cid cid) internal pure returns (bool, uint) {
3636
return _hasCid(tree, cid, 0);
3737
}
3838

39-
function _hasCid(Tree memory tree, CidCbor.Cid cid, uint startIdx) internal pure returns (bool, uint) {
40-
uint256 index = CidCbor.Cid.unwrap(cid);
39+
function _hasCid(Tree memory tree, Cid cid, uint startIdx) internal pure returns (bool, uint) {
4140
for (uint i = startIdx; i < tree.cids.length; i++) {
42-
if (CidCbor.Cid.unwrap(tree.cids[i]) == index) {
41+
if (tree.cids[i] == cid) {
4342
return (true, i);
4443
}
4544
}
@@ -48,29 +47,23 @@ library TreeCbor {
4847

4948
function validTree(Tree memory tree) internal pure returns (Tree memory) {
5049
for (uint i = 0; i < tree.cids.length; i++) {
51-
uint256 thisCid = CidCbor.Cid.unwrap(tree.cids[i]);
5250
for (uint j = i + 1; j < tree.nodes.length; j++) {
53-
uint256 otherCid = CidCbor.Cid.unwrap(tree.cids[j]);
54-
require(thisCid != otherCid, "node cids must be unique");
51+
require(tree.cids[i] != tree.cids[j], "node cids must be unique");
5552
}
5653
}
5754
return tree;
5855
}
5956

60-
function memPop(CidCbor.Cid[] memory arr) internal pure returns (CidCbor.Cid[] memory) {
61-
CidCbor.Cid[] memory newArr = new CidCbor.Cid[](arr.length - 1);
57+
function memPop(Cid[] memory arr) internal pure returns (Cid[] memory) {
58+
Cid[] memory newArr = new Cid[](arr.length - 1);
6259
for (uint i = 1; i < arr.length; i++) {
6360
newArr[i - 1] = arr[i];
6461
}
6562
return newArr;
6663
}
6764

68-
function memCat(CidCbor.Cid[] memory arr1, CidCbor.Cid[] memory arr2)
69-
internal
70-
pure
71-
returns (CidCbor.Cid[] memory)
72-
{
73-
CidCbor.Cid[] memory newArr = new CidCbor.Cid[](arr1.length + arr2.length);
65+
function memCat(Cid[] memory arr1, Cid[] memory arr2) internal pure returns (Cid[] memory) {
66+
Cid[] memory newArr = new Cid[](arr1.length + arr2.length);
7467
for (uint i = 0; i < arr1.length; i++) {
7568
newArr[i] = arr1[i];
7669
}
@@ -82,19 +75,19 @@ library TreeCbor {
8275

8376
function verifyInclusion(
8477
TreeCbor.Tree memory tree,
85-
CidCbor.Cid entryCid,
78+
Cid entryCid,
8679
bytes memory targetRecord,
8780
string memory targetKey
8881
) internal pure returns (bool) {
89-
CidCbor.Cid[] memory rightWalk;
90-
CidCbor.Cid currentCid;
82+
Cid[] memory rightWalk;
83+
Cid currentCid;
9184
TreeNodeCbor.TreeNode memory currentNode;
9285
uint currentIndex;
9386
bool found = false;
9487
bool hasCurrent = false;
9588

96-
CidCbor.Cid targetCid = CidCbor.Cid.wrap(uint256(sha256(targetRecord)));
97-
CidCbor.Cid[] memory queue = new CidCbor.Cid[](1);
89+
Cid targetCid = Cid.wrap(uint256(sha256(targetRecord)));
90+
Cid[] memory queue = new Cid[](1);
9891
queue[0] = entryCid;
9992

10093
while (queue.length > 0) {
@@ -106,15 +99,12 @@ library TreeCbor {
10699
}
107100
currentNode = tree.nodes[currentIndex];
108101

109-
rightWalk = new CidCbor.Cid[](currentNode.entries.length);
102+
rightWalk = new Cid[](currentNode.entries.length);
110103

111104
for (uint i = 0; i < currentNode.entries.length; i++) {
112105
rightWalk[i] = currentNode.entries[i].tree;
113106
if (keccak256(abi.encode(currentNode.entries[i].key)) == keccak256(abi.encode(targetKey))) {
114-
require(
115-
CidCbor.Cid.unwrap(currentNode.entries[i].value) == CidCbor.Cid.unwrap(targetCid),
116-
"cid mismatch"
117-
);
107+
require(currentNode.entries[i].value == targetCid, "cid mismatch");
118108
require(!found, "duplicate entry");
119109
found = true;
120110
}

src/TreeNodeCbor.sol

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@ library TreeNodeCbor {
77
using CBORDecoder for bytes;
88

99
struct TreeNode {
10-
CidCbor.Cid left;
10+
Cid left;
1111
TreeNodeEntry[] entries;
1212
}
1313

1414
struct TreeNodeEntry {
1515
string key;
16-
CidCbor.Cid value;
17-
CidCbor.Cid tree;
16+
Cid value;
17+
Cid tree;
1818
}
1919

2020
struct TreeNodeE {
2121
uint8 p; // prefixlen
2222
bytes k; // keysuffix
23-
CidCbor.Cid v; // value
24-
CidCbor.Cid t; // tree
23+
Cid v; // value
24+
Cid t; // tree
2525
}
2626

2727
function readNodeE(bytes memory cborData, uint byteIdx) internal pure returns (TreeNodeE[] memory, uint) {
@@ -44,8 +44,8 @@ library TreeNodeCbor {
4444

4545
uint8 p;
4646
bytes memory k;
47-
CidCbor.Cid v;
48-
CidCbor.Cid t;
47+
Cid v;
48+
Cid t;
4949

5050
for (uint i = 0; i < mapLen; i++) {
5151
bytes1 mapKey;

test/CommitCbor.t.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ contract CommitCborTest {
99
bytes private constant rootCommitData =
1010
hex"a56364696478206469643a706c633a6d74713365346d67743777796a6868616e69657a656a3637637265766d336c61796b6c746f73703232716464617461d82a5825000171122066da6655bf8da79b69a87299cf170fed8497fa3059379dc4a8bfe1e28cab5d936470726576f66776657273696f6e03";
1111

12-
uint256 private constant expectCommitDataCidHash =
13-
uint256(bytes32(hex"66da6655bf8da79b69a87299cf170fed8497fa3059379dc4a8bfe1e28cab5d93"));
12+
Cid private constant expectCommitDataCidHash =
13+
Cid.wrap(uint256(bytes32(hex"66da6655bf8da79b69a87299cf170fed8497fa3059379dc4a8bfe1e28cab5d93")));
1414

1515
function test_readCommit_only() public pure {
1616
CommitCbor.readCommit(rootCommitData, 0);
@@ -23,7 +23,7 @@ contract CommitCborTest {
2323
require(commit.version == 3, "expected version 3");
2424
require(bytes(commit.rev).length == 13, "expected rev to be 13 bytes");
2525
require(bytes(commit.did).length == 32, "expected did to be 32 bytes");
26-
require(CidCbor.Cid.unwrap(commit.data) != 0, "expected data cid to be non-null");
27-
require(CidCbor.Cid.unwrap(commit.data) == expectCommitDataCidHash, "expected cid hash");
26+
require(commit.data != Cid.wrap(0), "expected data cid to be non-null");
27+
require(commit.data == expectCommitDataCidHash, "expected cid hash");
2828
}
2929
}

test/TreeCbor.t.sol

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,18 @@ contract TreeTest is Test {
1212
//bytes memory rootSig = hex"D395A8C48C851C0AE8ABE772D9FC33CAC0619709CA2BCC5B60F7FF9E6FF7BF8363F68F57C10E0277403E800C5B9FD7C448F9816BF4AB878FD8148CEB24EF520B";
1313
bytes public constant rootCborWithoutSig =
1414
hex"A56364696478206469643A706C633A6D74713365346D67743777796A6868616E69657A656A3637637265766D336C61796B6C746F73703232716464617461D82A5825000171122066DA6655BF8DA79B69A87299CF170FED8497FA3059379DC4A8BFE1E28CAB5D936470726576F66776657273696F6E03";
15-
uint256 private constant correctLeftCidBytes =
16-
uint256(bytes32(hex"6E7335ED248EDAE3ED49D47B88A5FCAD2985E15F416F8AE23A49DFC1231AEB91"));
15+
Cid private constant expectLeftCid =
16+
Cid.wrap(uint256(bytes32(hex"6E7335ED248EDAE3ED49D47B88A5FCAD2985E15F416F8AE23A49DFC1231AEB91")));
1717

1818
bytes private constant targetRecord =
1919
hex"a4647465787478196361722066696c65732063616e6e6f74206875727420796f75652474797065726170702e62736b792e666565642e706f7374656c616e67738162656e696372656174656441747818323032342d31312d31355431323a31303a33322e3031345a";
2020

2121
//bytes32 private constant recordCidBytes = hex"6d51f125727763752e073d9301892fbddaa4cc6090d5fff9af7d49106b92d457";
22-
//CidCbor.Cid private constant recordIdx = CidCbor.Cid.wrap(recordCidBytes);
22+
//Cid private constant recordIdx = Cid.wrap(recordCidBytes);
2323

2424
CommitCbor.Commit private rootCommit;
25-
CidCbor.Cid private rootCid;
26-
CidCbor.Cid private wrongRootCid;
25+
Cid private rootCid;
26+
Cid private wrongRootCid;
2727
bytes[] private nodeCbors = [
2828
bytes(
2929
hex"a2616584a4616b58236170702e62736b792e67726170682e666f6c6c6f772f336b77767473726366736332346170006174d82a58250001711220232061c4165ce246d7f0b997b4a4212a0355faadf93fdecd64fca89db1d7bd9e6176d82a58250001711220181c3cddd15732e2a37c4455038c71ba75c1d5ca1850f78086d7bf29b490f7cba4616b487470346b797332346170181b6174d82a5825000171122096273e2ef4796b720c8e9f12292dfde8ce593a898ddd3c4c8d6d94c292736d1b6176d82a58250001711220783771b7cd8110221784049f5a1aba5ca85f660433233adb67f2045f1c05af72a4616b47773332356332346170181c6174d82a58250001711220f597936ae0b3636bcd64599dce397d33bcd1d0983af996b5ed02bdad5a6234156176d82a5825000171122009a988e6d9558a6e503e6f3194693953308be2fcbbb8831147b062b308cb291aa4616b497533366f62716332346170181a6174d82a58250001711220d5aa58f18245f4332affc4ce8fad050370013160f764027ea5897184caeb62446176d82a582500017112208e3047b78dad736d03697eedf8f49570c614c4e49cb89d86bd85d8351436e15d616cd82a58250001711220876175f10e6458ab735dbacf697d9caacec33486bc4a633be553fd43531012f5"
@@ -52,25 +52,23 @@ contract TreeTest is Test {
5252
TreeCbor.readTree(nodeCbors);
5353
}
5454

55-
function test_getCid_only() public view {
56-
(bool nodePresent, uint nodeIndex) = TreeCbor.hasCid(tree, rootCid);
57-
TreeNodeCbor.TreeNode memory node = tree.nodes[nodeIndex];
55+
function test_hasCid_only() public view {
56+
(bool nodePresent,) = TreeCbor.hasCid(tree, rootCid);
57+
require(nodePresent);
5858
}
5959

6060
function test_getCid_valid() public view {
6161
(bool nodePresent, uint nodeIndex) = TreeCbor.hasCid(tree, rootCid);
62-
TreeNodeCbor.TreeNode memory node = tree.nodes[nodeIndex];
62+
console.log("node index", nodeIndex);
6363
require(nodePresent);
6464
TreeNodeCbor.TreeNode memory rootNode = tree.nodes[nodeIndex];
65-
CidCbor.Cid leftCid = rootNode.left;
66-
require(CidCbor.Cid.unwrap(leftCid) == correctLeftCidBytes, "left cid incorrect");
67-
console.log("node index", nodeIndex);
68-
console.log("node.left index", CidCbor.Cid.unwrap(rootNode.left));
65+
require(rootNode.left == expectLeftCid, "expected left cid");
66+
console.log("node.left", Cid.unwrap(rootNode.left));
6967
console.log("node.entries length", rootNode.entries.length);
7068
}
7169

7270
function test_verifyInclusion_only() public view {
7371
bool result = TreeCbor.verifyInclusion(tree, rootCid, targetRecord, "app.bsky.feed.post/3laydu3mgac2v");
74-
console.log("Verify Inclusion %s", result);
72+
require(result, "inclusion");
7573
}
7674
}

test/TreeNodeCbor.t.sol

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ contract TreeNodeCborTest is Test {
1010
bytes private constant treeNodeBytes =
1111
hex"a2616585a4616b58236170702e62736b792e67726170682e666f6c6c6f772f336b77767534737665647332346170006174d82a58250001711220b000383f1466f65b0a02da763f46cf0e4510d832f6c609a9df56db73b81259376176d82a582500017112205cd7382608fb47afda979840cf0024b3d2d2e9e43448713909e998b6a1849490a4616b486679656a776332346170181b6174d82a58250001711220b295211bc0bfc8a6c8404f4877e96c37b25272c85e4942a29b178d26803f13996176d82a5825000171122017428f68c9c19f59b08b4b2d71ce96e04cdaf6139b94baf0a2c5ee51aa74493fa4616b486d77686f6e3232346170181b6174d82a58250001711220752be9d63155323fc5ce8753bdb5832fc7f5ad762c4e37944a6de84bbb9516876176d82a582500017112200fe8a27c597fcc6059888660b321e473bdaa94b45d0a702f3bd05e013ff17564a4616b486e337667376332346170181b6174d82a58250001711220ff7f6bd81b38a383101aec250c290ec6cd33555baf1e644f4b6d9b60a2e1fb856176d82a58250001711220a9f192fea504ecf8ae900d2a4f9f37551865132ae50bf680ac1687636afee7e1a4616b486f797875373232346170181b6174d82a582500017112204afcab072750efa8755714ca8477b35e871b71856a329c9973c4b94b7a4c98986176d82a58250001711220c46c805c774dcd3eaf4f90cef5e63f1f2a53f9c6bdb14b7397e736678b54dc97616cd82a582500017112206e7335ed248edae3ed49d47b88a5fcad2985e15f416f8ae23a49dfc1231aeb91";
1212

13+
Cid private constant expectLeftCid =
14+
Cid.wrap(uint256(bytes32(hex"6e7335ed248edae3ed49d47b88a5fcad2985e15f416f8ae23a49dfc1231aeb91")));
15+
1316
TreeNodeCbor.TreeNodeE[] private e;
1417

1518
function setUp() public {
@@ -25,20 +28,16 @@ contract TreeNodeCborTest is Test {
2528

2629
require(byteIdx == treeNodeBytes.length, "expected to read all bytes");
2730
require(node.entries.length == 5, "expected 5 entries");
28-
require(CidCbor.Cid.unwrap(node.left) != 0, "expected left cid to be non-null");
31+
require(node.left != Cid.wrap(0), "expected left cid to be non-null");
2932

30-
CidCbor.Cid leftCid = node.left;
33+
Cid leftCid = node.left;
3134

32-
require(
33-
CidCbor.Cid.unwrap(leftCid)
34-
== uint256(bytes32(hex"6e7335ed248edae3ed49d47b88a5fcad2985e15f416f8ae23a49dfc1231aeb91")),
35-
"left sha"
36-
);
35+
require(leftCid == expectLeftCid, "left sha");
3736
for (uint i = 0; i < node.entries.length; i++) {
3837
console.log("node entry %s", i);
3938
console.log("key", node.entries[i].key);
40-
console.log("value", CidCbor.Cid.unwrap(node.entries[i].value));
41-
console.log("tree", CidCbor.Cid.unwrap(node.entries[i].tree));
39+
console.log("value", Cid.unwrap(node.entries[i].value));
40+
console.log("tree", Cid.unwrap(node.entries[i].tree));
4241
}
4342
}
4443

0 commit comments

Comments
 (0)