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
use std::marker::PhantomData;
use bellperson::{
bls::{Bls12, Fr},
gadgets::num::AllocatedNum,
Circuit, ConstraintSystem, SynthesisError,
};
use filecoin_hashers::{HashFunction, Hasher};
use storage_proofs_core::{
compound_proof::CircuitComponent, error::Result, gadgets::constraint, gadgets::por::PoRCircuit,
gadgets::variables::Root, merkle::MerkleTreeTrait,
};
pub struct RationalPoStCircuit<Tree: MerkleTreeTrait> {
pub comm_rs: Vec<Option<Fr>>,
pub comm_cs: Vec<Option<Fr>>,
pub comm_r_lasts: Vec<Option<Fr>>,
pub leafs: Vec<Option<Fr>>,
#[allow(clippy::type_complexity)]
pub paths: Vec<Vec<(Vec<Option<Fr>>, Option<usize>)>>,
pub _t: PhantomData<Tree>,
}
#[derive(Clone, Default)]
pub struct ComponentPrivateInputs {}
impl<'a, Tree: MerkleTreeTrait> CircuitComponent for RationalPoStCircuit<Tree> {
type ComponentPrivateInputs = ComponentPrivateInputs;
}
impl<'a, Tree: 'static + MerkleTreeTrait> Circuit<Bls12> for RationalPoStCircuit<Tree> {
fn synthesize<CS: ConstraintSystem<Bls12>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
let comm_rs = self.comm_rs;
let comm_cs = self.comm_cs;
let comm_r_lasts = self.comm_r_lasts;
let leafs = self.leafs;
let paths = self.paths;
assert_eq!(paths.len(), leafs.len());
assert_eq!(paths.len(), comm_rs.len());
assert_eq!(paths.len(), comm_cs.len());
assert_eq!(paths.len(), comm_r_lasts.len());
for (((i, comm_r_last), comm_c), comm_r) in comm_r_lasts
.iter()
.enumerate()
.zip(comm_cs.iter())
.zip(comm_rs.iter())
{
let comm_r_last_num =
AllocatedNum::alloc(cs.namespace(|| format!("comm_r_last_{}", i)), || {
comm_r_last
.map(Into::into)
.ok_or(SynthesisError::AssignmentMissing)
})?;
let comm_c_num = AllocatedNum::alloc(cs.namespace(|| format!("comm_c_{}", i)), || {
comm_c
.map(Into::into)
.ok_or(SynthesisError::AssignmentMissing)
})?;
let comm_r_num = AllocatedNum::alloc(cs.namespace(|| format!("comm_r_{}", i)), || {
comm_r
.map(Into::into)
.ok_or(SynthesisError::AssignmentMissing)
})?;
comm_r_num.inputize(cs.namespace(|| format!("comm_r_{}_input", i)))?;
{
let hash_num = <Tree::Hasher as Hasher>::Function::hash2_circuit(
cs.namespace(|| format!("H_comm_c_comm_r_last_{}", i)),
&comm_c_num,
&comm_r_last_num,
)?;
constraint::equal(
cs,
|| format!("enforce_comm_c_comm_r_last_hash_comm_r_{}", i),
&comm_r_num,
&hash_num,
);
}
PoRCircuit::<Tree>::synthesize(
cs.namespace(|| format!("challenge_inclusion{}", i)),
Root::Val(leafs[i]),
paths[i].clone().into(),
Root::from_allocated::<CS>(comm_r_last_num),
true,
)?;
}
Ok(())
}
}