1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use cid::{Cid, Codec, Multihash, POSEIDON_BLS12_381_A1_FC1, SHA2_256_TRUNC254_PADDED};
pub type Commitment = [u8; 32];
pub fn commitment_to_cid(mc: Codec, mh: u64, commitment: &Commitment) -> Result<Cid, &'static str> {
validate_filecoin_cid_segments(mc, mh, commitment)?;
let mh = Multihash::wrap(mh, commitment).map_err(|_| "failed to wrap commitment cid")?;
Ok(Cid::new_v1(mc, mh))
}
pub fn cid_to_commitment(c: &Cid) -> Result<(Codec, u64, Commitment), &'static str> {
validate_filecoin_cid_segments(c.codec, c.hash.code(), c.hash.digest())?;
let mut comm = Commitment::default();
comm.copy_from_slice(c.hash.digest());
Ok((c.codec, c.hash.code(), comm))
}
pub fn data_commitment_v1_to_cid(comm_d: &Commitment) -> Result<Cid, &'static str> {
commitment_to_cid(
Codec::FilCommitmentUnsealed,
SHA2_256_TRUNC254_PADDED,
comm_d,
)
}
pub fn cid_to_data_commitment_v1(c: &Cid) -> Result<Commitment, &'static str> {
let (codec, _, comm_d) = cid_to_commitment(c)?;
if codec != Codec::FilCommitmentUnsealed {
return Err("data commitment codec must be Unsealed");
}
Ok(comm_d)
}
pub fn replica_commitment_v1_to_cid(comm_r: &Commitment) -> Result<Cid, &'static str> {
commitment_to_cid(
Codec::FilCommitmentSealed,
POSEIDON_BLS12_381_A1_FC1,
comm_r,
)
}
pub fn cid_to_replica_commitment_v1(c: &Cid) -> Result<Commitment, &'static str> {
let (codec, _, comm_r) = cid_to_commitment(c)?;
if codec != Codec::FilCommitmentSealed {
return Err("data commitment codec must be Sealed");
}
Ok(comm_r)
}
fn validate_filecoin_cid_segments(mc: Codec, mh: u64, comm_x: &[u8]) -> Result<(), &'static str> {
match mc {
Codec::FilCommitmentUnsealed => {
if mh != SHA2_256_TRUNC254_PADDED {
return Err("Incorrect hash function for unsealed commitment");
}
}
Codec::FilCommitmentSealed => {
if mh != POSEIDON_BLS12_381_A1_FC1 {
return Err("Incorrect hash function for sealed commitment");
}
}
_ => return Err("Invalid Codec, expected sealed or unsealed commitment codec"),
}
if comm_x.len() != 32 {
Err("commitments must be 32 bytes long")
} else {
Ok(())
}
}
pub fn piece_commitment_v1_to_cid(comm_p: &Commitment) -> Result<Cid, &'static str> {
data_commitment_v1_to_cid(comm_p)
}
pub fn cid_to_piece_commitment_v1(c: &Cid) -> Result<Commitment, &'static str> {
cid_to_data_commitment_v1(c)
}