-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathrotation.rs
More file actions
142 lines (119 loc) · 4.37 KB
/
rotation.rs
File metadata and controls
142 lines (119 loc) · 4.37 KB
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// The Licensed Work is (c) 2023 ChainSafe
// Code: https://github.com/ChainSafe/Spectre
// SPDX-License-Identifier: LGPL-3.0-only
use eth_types::Spec;
use ethereum_consensus_types::BeaconBlockHeader;
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::{iter, marker::PhantomData};
use crate::witness::beacon_header_multiproof_and_helper_indices;
/// Input datum for the `CommitteeUpdateCircuit` to map next sync committee SSZ root in the finalized state root to the corresponding Poseidon commitment to the public keys.
///
/// Assumes that public keys are BLS12-381 points on G1; `sync_committee_branch` is exactly `S::SYNC_COMMITTEE_PUBKEYS_DEPTH` hashes in lenght.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommitteeUpdateArgs<S: Spec> {
pub pubkeys_compressed: Vec<Vec<u8>>,
pub finalized_header: BeaconBlockHeader,
pub sync_committee_branch: Vec<Vec<u8>>,
pub finalized_header_multiproof: Vec<Vec<u8>>,
pub finalized_header_helper_indices: Vec<usize>,
#[serde(skip)]
pub _spec: PhantomData<S>,
}
// This default witness is intended for circuit setup and testing purposes only.
impl<S: Spec> Default for CommitteeUpdateArgs<S> {
fn default() -> Self {
let dummy_x_bytes = iter::once(192).pad_using(48, |_| 0).rev().collect_vec();
let sync_committee_branch = vec![vec![0; 32]; S::SYNC_COMMITTEE_PUBKEYS_DEPTH];
let hashed_pk = sha2::Sha256::digest(
&dummy_x_bytes
.iter()
.copied()
.pad_using(64, |_| 0)
.collect_vec(),
)
.to_vec();
assert!(S::SYNC_COMMITTEE_SIZE.is_power_of_two());
let mut chunks = vec![hashed_pk; S::SYNC_COMMITTEE_SIZE];
while chunks.len() > 1 {
chunks = chunks
.into_iter()
.tuples()
.map(|(left, right)| sha2::Sha256::digest(&[left, right].concat()).to_vec())
.collect();
}
let committee_root = chunks.pop().unwrap();
let state_root = mock_root(
committee_root,
&sync_committee_branch,
S::SYNC_COMMITTEE_PUBKEYS_ROOT_INDEX,
);
let finalized_header = BeaconBlockHeader {
state_root: state_root.as_slice().try_into().unwrap(),
..Default::default()
};
let (finalized_header_multiproof, finalized_header_helper_indices) =
beacon_header_multiproof_and_helper_indices(
&mut finalized_header.clone(),
&[S::HEADER_STATE_ROOT_INDEX],
);
Self {
pubkeys_compressed: iter::repeat(dummy_x_bytes)
.take(S::SYNC_COMMITTEE_SIZE)
.collect_vec(),
sync_committee_branch,
finalized_header,
_spec: PhantomData,
finalized_header_multiproof,
finalized_header_helper_indices,
}
}
}
pub(crate) fn mock_root(leaf: Vec<u8>, branch: &[Vec<u8>], mut gindex: usize) -> Vec<u8> {
let mut last_hash = leaf;
for i in 0..branch.len() {
last_hash = Sha256::digest(
&if gindex % 2 == 0 {
[last_hash, branch[i].clone()]
} else {
[branch[i].clone(), last_hash]
}
.concat(),
)
.to_vec();
gindex /= 2;
}
last_hash
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{committee_update_circuit::CommitteeUpdateCircuit, util::AppCircuit};
use eth_types::Testnet;
use halo2_base::{
gates::circuit::CircuitBuilderStage,
halo2_proofs::dev::MockProver,
halo2_proofs::{
halo2curves::bn256::{Bn256, Fr},
poly::kzg::commitment::ParamsKZG,
},
utils::fs::gen_srs,
};
use snark_verifier_sdk::CircuitExt;
#[test]
fn test_committee_update_default_witness() {
const K: u32 = 18;
let witness = CommitteeUpdateArgs::<Testnet>::default();
let params: ParamsKZG<Bn256> = gen_srs(K);
let circuit = CommitteeUpdateCircuit::<Testnet, Fr>::create_circuit(
CircuitBuilderStage::Mock,
None,
&witness,
¶ms,
)
.unwrap();
let prover = MockProver::<Fr>::run(K, &circuit, circuit.instances()).unwrap();
prover.assert_satisfied_par();
}
}