Skip to content

Commit 552005d

Browse files
authored
feat(dagcid): disallow libp2p-key CIDs in DagCid and add tests (#43) (#49)
1 parent e9f986c commit 552005d

File tree

2 files changed

+153
-4
lines changed

2 files changed

+153
-4
lines changed

src/DagCid.cs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Newtonsoft.Json;
1+
using System;
2+
using Newtonsoft.Json;
23

34
namespace Ipfs
45
{
@@ -10,11 +11,32 @@ namespace Ipfs
1011
/// </remarks>
1112
public record DagCid
1213
{
14+
private Cid _value = null!;
15+
1316
/// <summary>
1417
/// The <see cref="Cid"/> value of this DAG link.
1518
/// </summary>
19+
/// <exception cref="ArgumentException">
20+
/// Thrown when attempting to set a CID with ContentType "libp2p-key",
21+
/// as IPLD links must be immutable and libp2p-key CIDs represent mutable IPNS addresses.
22+
/// </exception>
1623
[JsonProperty("/")]
17-
public required Cid Value { get; set; }
24+
public required Cid Value
25+
{
26+
get => _value;
27+
set
28+
{
29+
if (value.ContentType == "libp2p-key")
30+
{
31+
throw new ArgumentException(
32+
"Cannot store CID-encoded libp2p key as DagCid link. " +
33+
"IPLD links must be immutable, but libp2p-key CIDs represent mutable IPNS addresses. " +
34+
"Use the resolved content CID instead.",
35+
nameof(value));
36+
}
37+
_value = value;
38+
}
39+
}
1840

1941
/// <summary>
2042
/// Implicit casting of a <see cref="DagCid"/> to a <see cref="Cid"/>.
@@ -25,8 +47,23 @@ public record DagCid
2547
/// <summary>
2648
/// Explicit casting of a <see cref="Cid"/> to a <see cref="DagCid"/>.
2749
/// </summary>
28-
/// <param name="cid">The <see cref="Cid"/> to cast.</param>"
29-
public static explicit operator DagCid(Cid cid) => new DagCid { Value = cid, };
50+
/// <param name="cid">The <see cref="Cid"/> to cast.</param>
51+
/// <exception cref="ArgumentException">
52+
/// Thrown when attempting to cast a CID with ContentType "libp2p-key",
53+
/// as IPLD links must be immutable and libp2p-key CIDs represent mutable IPNS addresses.
54+
/// </exception>
55+
public static explicit operator DagCid(Cid cid)
56+
{
57+
if (cid.ContentType == "libp2p-key")
58+
{
59+
throw new ArgumentException(
60+
"Cannot cast CID-encoded libp2p key to DagCid. " +
61+
"IPLD links must be immutable, but libp2p-key CIDs represent mutable IPNS addresses. " +
62+
"Use the resolved content CID instead.",
63+
nameof(cid));
64+
}
65+
return new DagCid { Value = cid, };
66+
}
3067

3168
/// <summary>
3269
/// Returns the string representation of the <see cref="DagCid"/>.

test/DagCidTest.cs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
using System;
3+
4+
namespace Ipfs
5+
{
6+
[TestClass]
7+
public class DagCidTest
8+
{
9+
[TestMethod]
10+
public void Value_ValidCid_SetsSuccessfully()
11+
{
12+
// Arrange
13+
Cid validCid = "QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V";
14+
15+
// Act & Assert
16+
var dagCid = new DagCid { Value = validCid };
17+
Assert.AreEqual(validCid, dagCid.Value);
18+
}
19+
20+
[TestMethod]
21+
public void Value_LibP2pKeyCid_ThrowsArgumentException()
22+
{
23+
// Arrange - using real IPNS key CID that should have libp2p-key content type
24+
Cid libp2pKeyCid = "k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8";
25+
26+
// Verify this CID actually has libp2p-key content type
27+
Assert.AreEqual("libp2p-key", libp2pKeyCid.ContentType);
28+
29+
// Act & Assert
30+
var exception = Assert.ThrowsException<ArgumentException>(() =>
31+
new DagCid { Value = libp2pKeyCid });
32+
33+
Assert.IsTrue(exception.Message.Contains("Cannot store CID-encoded libp2p key as DagCid link"));
34+
Assert.IsTrue(exception.Message.Contains("IPLD links must be immutable"));
35+
Assert.AreEqual("value", exception.ParamName);
36+
}
37+
38+
[TestMethod]
39+
public void Value_LibP2pKeyCid_SetAfterConstruction_ThrowsArgumentException()
40+
{
41+
// Arrange
42+
Cid validCid = "QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V";
43+
// Using another real IPNS key CID
44+
Cid libp2pKeyCid = "k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8";
45+
46+
var dagCid = new DagCid { Value = validCid };
47+
48+
// Act & Assert
49+
var exception = Assert.ThrowsException<ArgumentException>(() =>
50+
dagCid.Value = libp2pKeyCid);
51+
52+
Assert.IsTrue(exception.Message.Contains("Cannot store CID-encoded libp2p key as DagCid link"));
53+
Assert.AreEqual("value", exception.ParamName);
54+
}
55+
56+
[TestMethod]
57+
public void ExplicitCast_ValidCid_CastsSuccessfully()
58+
{
59+
// Arrange
60+
Cid validCid = "QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V";
61+
62+
// Act
63+
var dagCid = (DagCid)validCid;
64+
65+
// Assert
66+
Assert.AreEqual(validCid, dagCid.Value);
67+
}
68+
69+
[TestMethod]
70+
public void ExplicitCast_LibP2pKeyCid_ThrowsArgumentException()
71+
{
72+
// Arrange - using real IPNS key CID that should have libp2p-key content type
73+
Cid libp2pKeyCid = "k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8";
74+
75+
// Act & Assert
76+
var exception = Assert.ThrowsException<ArgumentException>(() =>
77+
(DagCid)libp2pKeyCid);
78+
79+
Assert.IsTrue(exception.Message.Contains("Cannot cast CID-encoded libp2p key to DagCid"));
80+
Assert.IsTrue(exception.Message.Contains("IPLD links must be immutable"));
81+
Assert.AreEqual("cid", exception.ParamName);
82+
}
83+
84+
[TestMethod]
85+
public void ImplicitCast_DagCidToCid_WorksCorrectly()
86+
{
87+
// Arrange
88+
Cid originalCid = "QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V";
89+
var dagCid = new DagCid { Value = originalCid };
90+
91+
// Act
92+
Cid convertedCid = dagCid;
93+
94+
// Assert
95+
Assert.AreEqual(originalCid, convertedCid);
96+
}
97+
98+
[TestMethod]
99+
public void ToString_ReturnsValueToString()
100+
{
101+
// Arrange
102+
Cid cid = "QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V";
103+
var dagCid = new DagCid { Value = cid };
104+
105+
// Act
106+
var result = dagCid.ToString();
107+
108+
// Assert
109+
Assert.AreEqual(cid.ToString(), result);
110+
}
111+
}
112+
}

0 commit comments

Comments
 (0)