Skip to content

Commit 3940978

Browse files
fix(storage-proofs): encoding_proof: remove redundant storage
1 parent 1753197 commit 3940978

File tree

8 files changed

+126
-128
lines changed

8 files changed

+126
-128
lines changed

storage-proofs/src/circuit/stacked/column.rs

+6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ impl Column {
3333
}
3434
}
3535

36+
pub fn get_node_at_layer(&self, layer: usize) -> &Option<Fr> {
37+
assert!(layer > 0, "layer must be greater than 0");
38+
let row_index = layer - 1;
39+
&self.rows[row_index]
40+
}
41+
3642
pub fn hash<CS: ConstraintSystem<Bls12>>(
3743
self,
3844
mut cs: CS,

storage-proofs/src/circuit/stacked/column_proof.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use bellperson::{ConstraintSystem, SynthesisError};
22
use fil_sapling_crypto::circuit::num;
33
use fil_sapling_crypto::jubjub::JubjubEngine;
4-
use paired::bls12_381::Bls12;
4+
use paired::bls12_381::{Bls12, Fr};
55

66
use crate::circuit::{
77
constraint,
@@ -25,6 +25,10 @@ impl<H: Hasher> ColumnProof<H> {
2525
}
2626
}
2727

28+
pub fn get_node_at_layer(&self, layer: usize) -> &Option<Fr> {
29+
self.column.get_node_at_layer(layer)
30+
}
31+
2832
pub fn synthesize<CS: ConstraintSystem<Bls12>>(
2933
self,
3034
mut cs: CS,

storage-proofs/src/circuit/stacked/encoding_proof.rs

+40-60
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,20 @@ use crate::stacked::{EncodingProof as VanillaEncodingProof, PublicParams};
1111
#[derive(Debug, Clone)]
1212
pub struct EncodingProof {
1313
node: Option<u64>,
14-
encoded_node: Option<Fr>,
15-
// The inner `Option` is for the circuit, the outer to determine if
16-
// if we need to encode sth.
17-
#[allow(clippy::option_option)]
18-
decoded_node: Option<Option<Fr>>,
1914
parents: Vec<Option<Fr>>,
2015
}
2116

2217
impl EncodingProof {
2318
/// Create an empty proof, used in `blank_circuit`s.
24-
pub fn empty<H: Hasher>(params: &PublicParams<H>) -> Self {
25-
EncodingProof {
26-
node: None,
27-
encoded_node: None,
28-
decoded_node: None,
29-
parents: vec![None; params.graph.degree()],
30-
}
31-
}
32-
33-
/// Create an empty proof, used in `blank_circuit`s.
34-
pub fn empty_base<H: Hasher>(params: &PublicParams<H>) -> Self {
35-
EncodingProof {
36-
node: None,
37-
encoded_node: None,
38-
decoded_node: None,
39-
parents: vec![None; params.graph.base_graph().degree()],
40-
}
41-
}
42-
43-
/// Create an empty proof, used in `blank_circuit`s.
44-
pub fn empty_with_decoded<H: Hasher>(params: &PublicParams<H>) -> Self {
19+
pub fn empty<H: Hasher>(params: &PublicParams<H>, layer: usize) -> Self {
20+
let degree = if layer == 1 {
21+
params.graph.base_graph().degree()
22+
} else {
23+
params.graph.degree()
24+
};
4525
EncodingProof {
4626
node: None,
47-
encoded_node: None,
48-
decoded_node: Some(None),
49-
parents: vec![None; params.graph.degree()],
27+
parents: vec![None; degree],
5028
}
5129
}
5230

@@ -91,18 +69,38 @@ impl EncodingProof {
9169
)
9270
}
9371

94-
pub fn synthesize<CS: ConstraintSystem<Bls12>>(
72+
pub fn synthesize_key<CS: ConstraintSystem<Bls12>>(
9573
self,
9674
mut cs: CS,
9775
params: &<Bls12 as JubjubEngine>::Params,
9876
replica_id: &[Boolean],
77+
exp_encoded_node: &num::AllocatedNum<Bls12>,
9978
) -> Result<(), SynthesisError> {
100-
let EncodingProof {
79+
let EncodingProof { node, parents } = self;
80+
81+
let key = Self::create_key(
82+
cs.namespace(|| "create_key"),
83+
params,
84+
replica_id,
10185
node,
10286
parents,
103-
encoded_node,
104-
decoded_node,
105-
} = self;
87+
)?;
88+
89+
// enforce equality
90+
constraint::equal(&mut cs, || "equality_key", &exp_encoded_node, &key);
91+
92+
Ok(())
93+
}
94+
95+
pub fn synthesize_decoded<CS: ConstraintSystem<Bls12>>(
96+
self,
97+
mut cs: CS,
98+
params: &<Bls12 as JubjubEngine>::Params,
99+
replica_id: &[Boolean],
100+
exp_encoded_node: &num::AllocatedNum<Bls12>,
101+
decoded_node: &num::AllocatedNum<Bls12>,
102+
) -> Result<(), SynthesisError> {
103+
let EncodingProof { node, parents } = self;
106104

107105
let key = Self::create_key(
108106
cs.namespace(|| "create_key"),
@@ -112,44 +110,26 @@ impl EncodingProof {
112110
parents,
113111
)?;
114112

115-
let encoded_node = num::AllocatedNum::alloc(cs.namespace(|| "encoded_num"), || {
116-
encoded_node
117-
.map(Into::into)
118-
.ok_or_else(|| SynthesisError::AssignmentMissing)
119-
})?;
120-
121-
let encoded_node_new = if let Some(decoded_node) = decoded_node {
122-
let decoded_num = num::AllocatedNum::alloc(cs.namespace(|| "decoded_num"), || {
123-
decoded_node
124-
.map(Into::into)
125-
.ok_or_else(|| SynthesisError::AssignmentMissing)
126-
})?;
127-
encode(cs.namespace(|| "encode"), &key, &decoded_num)?
128-
} else {
129-
key
130-
};
113+
let encoded_node = encode(cs.namespace(|| "encode"), &key, decoded_node)?;
131114

132115
// enforce equality
133-
constraint::equal(&mut cs, || "equality", &encoded_node_new, &encoded_node);
116+
constraint::equal(
117+
&mut cs,
118+
|| "equality_encoded_node",
119+
&exp_encoded_node,
120+
&encoded_node,
121+
);
134122

135123
Ok(())
136124
}
137125
}
138126

139127
impl<H: Hasher> From<VanillaEncodingProof<H>> for EncodingProof {
140128
fn from(vanilla_proof: VanillaEncodingProof<H>) -> Self {
141-
let VanillaEncodingProof {
142-
parents,
143-
decoded_node,
144-
encoded_node,
145-
node,
146-
..
147-
} = vanilla_proof;
129+
let VanillaEncodingProof { parents, node, .. } = vanilla_proof;
148130

149131
EncodingProof {
150132
node: Some(node),
151-
encoded_node: Some(encoded_node.into_fr()),
152-
decoded_node: decoded_node.map(|n| Some(n.into_fr())),
153133
parents: parents.into_iter().map(|p| Some(p.into())).collect(),
154134
}
155135
}

storage-proofs/src/circuit/stacked/params.rs

+33-18
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,8 @@ impl<H: Hasher> Proof<H> {
3636
continue;
3737
}
3838

39-
if layer == 1 {
40-
// first layer has no expansion parents
41-
encoding_proofs.push(EncodingProof::empty_base(params));
42-
} else if layer == layers {
43-
// last layer has a decoded node
44-
encoding_proofs.push(EncodingProof::empty_with_decoded(params));
45-
} else {
46-
encoding_proofs.push(EncodingProof::empty(params));
47-
}
39+
encoding_proofs.push(EncodingProof::empty(params, layer));
4840
}
49-
5041
Proof {
5142
comm_d_proof: InclusionPath::empty(&params.graph),
5243
comm_r_last_proof: InclusionPath::empty(&params.graph),
@@ -61,6 +52,7 @@ impl<H: Hasher> Proof<H> {
6152
self,
6253
mut cs: CS,
6354
params: &<Bls12 as JubjubEngine>::Params,
55+
layers: usize,
6456
comm_d: &num::AllocatedNum<Bls12>,
6557
comm_c: &num::AllocatedNum<Bls12>,
6658
comm_r_last: &num::AllocatedNum<Bls12>,
@@ -82,21 +74,44 @@ impl<H: Hasher> Proof<H> {
8274
comm_d_leaf.clone(),
8375
)?;
8476

77+
let comm_r_last_data_leaf =
78+
comm_r_last_proof.alloc_value(cs.namespace(|| "comm_r_last_data_leaf"))?;
79+
8580
// verify encodings
86-
for (layer, proof) in encoding_proofs.into_iter().enumerate() {
87-
proof.synthesize(
88-
cs.namespace(|| format!("encoding_proof_{}", layer)),
89-
params,
90-
replica_id,
91-
)?;
81+
for (i, proof) in encoding_proofs.into_iter().enumerate() {
82+
let layer = i + 1;
83+
84+
if layer == layers {
85+
proof.synthesize_decoded(
86+
cs.namespace(|| format!("encoding_proof_{}", layer)),
87+
params,
88+
replica_id,
89+
&comm_r_last_data_leaf,
90+
&comm_d_leaf,
91+
)?;
92+
} else {
93+
let raw = replica_column_proof.c_x.get_node_at_layer(layer);
94+
let encoded_node = num::AllocatedNum::alloc(
95+
cs.namespace(|| format!("enc_node_{}", layer)),
96+
|| {
97+
raw.map(Into::into)
98+
.ok_or_else(|| SynthesisError::AssignmentMissing)
99+
},
100+
)?;
101+
102+
proof.synthesize_key(
103+
cs.namespace(|| format!("encoding_proof_{}", layer)),
104+
params,
105+
replica_id,
106+
&encoded_node,
107+
)?;
108+
}
92109
}
93110

94111
// verify replica column openings
95112
replica_column_proof.synthesize(cs.namespace(|| "replica_column_proof"), params, comm_c)?;
96113

97114
// verify final replica layer
98-
let comm_r_last_data_leaf =
99-
comm_r_last_proof.alloc_value(cs.namespace(|| "comm_r_last_data_leaf"))?;
100115
comm_r_last_proof.synthesize(
101116
cs.namespace(|| "comm_r_last_data_inclusion"),
102117
params,

storage-proofs/src/circuit/stacked/proof.rs

+1
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ impl<'a, H: Hasher> Circuit<Bls12> for StackedCircuit<'a, Bls12, H> {
173173
proof.synthesize(
174174
&mut cs.namespace(|| format!("challenge_{}", i)),
175175
&self.params,
176+
public_params.layer_challenges.layers(),
176177
&comm_d_num,
177178
&comm_c_num,
178179
&comm_r_last_num,

storage-proofs/src/stacked/encoding_proof.rs

+9-25
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,25 @@
11
use std::marker::PhantomData;
22

33
use blake2s_simd::Params as Blake2s;
4-
use serde::de::Deserialize;
5-
use serde::ser::Serialize;
64

75
use crate::fr32::bytes_into_fr_repr_safe;
86
use crate::hasher::Hasher;
9-
use crate::merkle::IncludedNode;
107
use crate::stacked::encode::encode;
118
use crate::util::NODE_SIZE;
129

1310
#[derive(Debug, Clone, Serialize, Deserialize)]
1411
pub struct EncodingProof<H: Hasher> {
15-
#[serde(bound(
16-
serialize = "IncludedNode<H>: Serialize",
17-
deserialize = "IncludedNode<H>: Deserialize<'de>"
18-
))]
19-
pub(crate) encoded_node: IncludedNode<H>,
20-
#[serde(bound(
21-
serialize = "IncludedNode<H>: Serialize",
22-
deserialize = "IncludedNode<H>: Deserialize<'de>"
23-
))]
24-
pub(crate) decoded_node: Option<IncludedNode<H>>,
2512
pub(crate) parents: Vec<H::Domain>,
2613
pub(crate) node: u64,
2714
#[serde(skip)]
2815
_h: PhantomData<H>,
2916
}
3017

3118
impl<H: Hasher> EncodingProof<H> {
32-
pub fn new(
33-
node: u64,
34-
parents: Vec<H::Domain>,
35-
encoded_node: IncludedNode<H>,
36-
decoded_node: Option<IncludedNode<H>>,
37-
) -> Self {
19+
pub fn new(node: u64, parents: Vec<H::Domain>) -> Self {
3820
EncodingProof {
3921
node,
4022
parents,
41-
encoded_node,
42-
decoded_node,
4323
_h: PhantomData,
4424
}
4525
}
@@ -60,16 +40,20 @@ impl<H: Hasher> EncodingProof<H> {
6040
bytes_into_fr_repr_safe(hasher.finalize().as_ref()).into()
6141
}
6242

63-
pub fn verify(&self, replica_id: &H::Domain) -> bool {
43+
pub fn verify(
44+
&self,
45+
replica_id: &H::Domain,
46+
exp_encoded_node: &H::Domain,
47+
decoded_node: Option<&H::Domain>,
48+
) -> bool {
6449
let key = self.create_key(replica_id);
6550

66-
let encoded_node = if let Some(ref decoded_node) = self.decoded_node {
67-
encode(key, **decoded_node)
51+
let encoded_node = if let Some(decoded_node) = decoded_node {
52+
encode(key, *decoded_node)
6853
} else {
6954
key
7055
};
7156

72-
let exp_encoded_node: &H::Domain = &self.encoded_node;
7357
check_eq!(exp_encoded_node, &encoded_node);
7458

7559
true

storage-proofs/src/stacked/params.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,23 @@ impl<H: Hasher> Proof<H> {
230230
layer,
231231
expect_challenge
232232
);
233+
234+
let (encoded_node, decoded_node) = if layer == layer_challenges.layers() {
235+
(
236+
self.comm_r_last_proof.leaf(),
237+
Some(self.comm_d_proofs.leaf()),
238+
)
239+
} else {
240+
(
241+
self.replica_column_proofs.c_x.get_node_at_layer(layer),
242+
None,
243+
)
244+
};
245+
233246
if expect_challenge {
234247
check!(self.encoding_proofs.get(layer - 1).is_some());
235248
let encoding_proof = &self.encoding_proofs[layer - 1];
236-
check!(encoding_proof.verify(replica_id));
249+
check!(encoding_proof.verify(replica_id, encoded_node, decoded_node));
237250
} else {
238251
check!(self.encoding_proofs.get(layer - 1).is_none());
239252
}

0 commit comments

Comments
 (0)