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
use cid::{
Cid, Multihash, FIL_COMMITMENT_SEALED, FIL_COMMITMENT_UNSEALED, POSEIDON_BLS12_381_A1_FC1,
SHA2_256_TRUNC254_PADDED,
};
pub type Commitment = [u8; 32];
pub fn commitment_to_cid(mc: u64, 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<(u64, 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(FIL_COMMITMENT_UNSEALED, 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 != FIL_COMMITMENT_UNSEALED {
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(FIL_COMMITMENT_SEALED, 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 != FIL_COMMITMENT_SEALED {
return Err("data commitment codec must be Sealed");
}
Ok(comm_r)
}
fn validate_filecoin_cid_segments(mc: u64, mh: u64, comm_x: &[u8]) -> Result<(), &'static str> {
match mc {
FIL_COMMITMENT_UNSEALED => {
if mh != SHA2_256_TRUNC254_PADDED {
return Err("Incorrect hash function for unsealed commitment");
}
}
FIL_COMMITMENT_SEALED => {
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)
}