Skip to content

Commit

Permalink
Refactor for supporting only one currency due to preventing rebalanci…
Browse files Browse the repository at this point in the history
…ng attack
  • Loading branch information
sifnoc committed Jun 4, 2024
1 parent 2460efe commit 9d3b52c
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 256 deletions.
2 changes: 1 addition & 1 deletion prover/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ criterion= "0.3"

[[bench]]
name = "proof_of_liabilities"
harness = false
harness = false
61 changes: 26 additions & 35 deletions prover/benches/proof_of_liabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ use summa_hyperplonk::{
utils::{big_uint_to_fp, generate_dummy_entries, uni_to_multivar_binary_index},
};

fn bench_summa<const K: u32, const N_USERS: usize, const N_CURRENCIES: usize>() {
let name = format!("K = {K}, N_USERS = {N_USERS}, N_CURRENCIES = {N_CURRENCIES}");
// There is only one currency in V3c
fn bench_summa<const K: u32, const N_USERS: usize>() {
let name = format!("K = {K}, N_USERS = {N_USERS}");
let mut c = Criterion::default().sample_size(10);

let grand_sum_proof_bench_name = format!("<{}> grand sum proof", name);
Expand All @@ -29,16 +30,13 @@ fn bench_summa<const K: u32, const N_USERS: usize, const N_CURRENCIES: usize>()
let inclusion_verification_bench_name = format!("<{}> user inclusion verification", name);

type ProvingBackend = HyperPlonk<MultilinearKzg<Bn256>>;
let entries = generate_dummy_entries::<N_USERS, N_CURRENCIES>().unwrap();
let entries = generate_dummy_entries::<N_USERS>().unwrap();
let halo2_circuit =
SummaHyperplonk::<N_USERS, N_CURRENCIES, RangeCheckConfig<N_CURRENCIES, N_USERS>>::init(
entries.to_vec(),
);
SummaHyperplonk::<N_USERS, RangeCheckConfig<N_USERS>>::init(entries.to_vec());

let circuit = Halo2Circuit::<
Fp,
SummaHyperplonk<N_USERS, N_CURRENCIES, RangeCheckConfig<N_CURRENCIES, N_USERS>>,
>::new::<ProvingBackend>(K as usize, halo2_circuit.clone());
let circuit = Halo2Circuit::<Fp, SummaHyperplonk<N_USERS, RangeCheckConfig<N_USERS>>>::new::<
ProvingBackend,
>(K as usize, halo2_circuit.clone());

let circuit_info: PlonkishCircuitInfo<_> = circuit.circuit_info().unwrap();
let instances = circuit.instances();
Expand All @@ -49,10 +47,9 @@ fn bench_summa<const K: u32, const N_USERS: usize, const N_CURRENCIES: usize>()
c.bench_function(&grand_sum_proof_bench_name, |b| {
b.iter_batched(
|| {
Halo2Circuit::<
Fp,
SummaHyperplonk<N_USERS, N_CURRENCIES, RangeCheckConfig<N_CURRENCIES, N_USERS>>,
>::new::<ProvingBackend>(K as usize, halo2_circuit.clone())
Halo2Circuit::<Fp, SummaHyperplonk<N_USERS, RangeCheckConfig<N_USERS>>>::new::<
ProvingBackend,
>(K as usize, halo2_circuit.clone())
},
|circuit| {
let mut transcript = Keccak256Transcript::default();
Expand All @@ -79,7 +76,7 @@ fn bench_summa<const K: u32, const N_USERS: usize, const N_CURRENCIES: usize>()
.unwrap();
(witness_polys, proof_transcript)
};
let num_points = N_CURRENCIES + 1;
let num_points = 2;
let user_entry_polynomials = witness_polys.iter().take(num_points).collect::<Vec<_>>();

let mut transcript = Keccak256Transcript::default();
Expand All @@ -106,23 +103,18 @@ fn bench_summa<const K: u32, const N_USERS: usize, const N_CURRENCIES: usize>()
let multivariate_challenge =
uni_to_multivar_binary_index(&random_user_index, num_vars as usize);

let mut evals = vec![];

for i in 0..N_CURRENCIES + 1 {
if i == 0 {
evals.push(Evaluation::new(
i,
0,
big_uint_to_fp::<Fp>(entries[random_user_index].username_as_big_uint()),
));
} else {
evals.push(Evaluation::new(
i,
0,
big_uint_to_fp::<Fp>(&entries[random_user_index].balances()[i - 1]),
));
}
}
let evals: Vec<Evaluation<Fp>> = vec![
Evaluation::new(
0,
0,
big_uint_to_fp::<Fp>(entries[random_user_index].username_as_big_uint()),
),
Evaluation::new(
1,
0,
big_uint_to_fp::<Fp>(&entries[random_user_index].balance()),
),
];

c.bench_function(&inclusion_proof_bench_name, |b| {
b.iter_batched(
Expand Down Expand Up @@ -192,12 +184,11 @@ fn bench_summa<const K: u32, const N_USERS: usize, const N_CURRENCIES: usize>()
}

fn criterion_benchmark(_c: &mut Criterion) {
const N_CURRENCIES: usize = 100;

// Only one currency will be handled in V3c
{
const K: u32 = 17;
const N_USERS: usize = (1 << K as usize) - 6;
bench_summa::<K, N_USERS, N_CURRENCIES>();
bench_summa::<K, N_USERS>();
}
}

Expand Down
78 changes: 36 additions & 42 deletions prover/src/circuits/config/circuit_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,33 @@ use halo2_proofs::halo2curves::bn256::Fr as Fp;
/// grand total to the instance values.
///
/// The specific implementations have to provide the range check logic.
pub trait CircuitConfig<const N_CURRENCIES: usize, const N_USERS: usize>: Clone {
pub trait CircuitConfig<const N_USERS: usize>: Clone {
/// Configures the circuit
fn configure(
meta: &mut ConstraintSystem<Fp>,
username: Column<Advice>,
balances: [Column<Advice>; N_CURRENCIES],
balance: Column<Advice>,
instance: Column<Instance>,
) -> Self;

fn get_username(&self) -> Column<Advice>;

fn get_balances(&self) -> [Column<Advice>; N_CURRENCIES];
fn get_balance(&self) -> Column<Advice>;

fn get_instance(&self) -> Column<Instance>;

/// Assigns the entries to the circuit, constrains the grand total to the instance values.
fn synthesize(
&self,
mut layouter: impl Layouter<Fp>,
entries: &[Entry<N_CURRENCIES>],
grand_total: &[Fp],
entries: &[Entry],
grand_total: &Fp,
) -> Result<(), Error> {
// Initiate the range check chips
let range_check_chips = self.initialize_range_check_chips();
let range_check_chip = self.initialize_range_check_chip();

for (i, entry) in entries.iter().enumerate() {
let last_decompositions = layouter.assign_region(
let last_decomposition = layouter.assign_region(
|| format!("assign entry {} to the table", i),
|mut region| {
region.assign_advice(
Expand All @@ -49,71 +49,65 @@ pub trait CircuitConfig<const N_CURRENCIES: usize, const N_USERS: usize>: Clone
|| Value::known(big_uint_to_fp::<Fp>(entry.username_as_big_uint())),
)?;

let mut last_decompositions = vec![];
let mut zs = Vec::with_capacity(4);

for (j, balance) in entry.balances().iter().enumerate() {
let assigned_balance = region.assign_advice(
|| format!("balance {}", j),
self.get_balances()[j],
// The range check chip is empty when perform with "no_range_check_config"
if range_check_chip.is_empty() {
let zero_balance = region.assign_advice(
|| "balance",
self.get_balance(),
0,
|| Value::known(big_uint_to_fp(balance)),
|| Value::known(Fp::zero()),
)?;

let mut zs = Vec::with_capacity(4);

if !range_check_chips.is_empty() {
range_check_chips[j].assign(&mut region, &mut zs, &assigned_balance)?;

last_decompositions.push(zs[3].clone());
}
Ok(zero_balance)
} else {
let assigned_balance = region.assign_advice(
|| "balance",
self.get_balance(),
0,
|| Value::known(big_uint_to_fp(entry.balance())),
)?;
range_check_chip[0].assign(&mut region, &mut zs, &assigned_balance)?;
Ok(zs[3].clone())
}

Ok(last_decompositions)
},
)?;

self.constrain_decompositions(last_decompositions, &mut layouter)?;
self.constrain_decompositions(last_decomposition, &mut layouter)?;
}

let assigned_total = layouter.assign_region(
|| "assign total".to_string(),
|mut region| {
let mut assigned_total = vec![];

for (j, total) in grand_total.iter().enumerate() {
let balance_total = region.assign_advice(
|| format!("total {}", j),
self.get_balances()[j],
0,
|| Value::known(total.neg()),
)?;

assigned_total.push(balance_total);
}

Ok(assigned_total)
let balance_total = region.assign_advice(
|| "total balance",
self.get_balance(),
0,
|| Value::known(grand_total.neg()),
)?;

Ok(balance_total)
},
)?;

for (j, total) in assigned_total.iter().enumerate() {
layouter.constrain_instance(total.cell(), self.get_instance(), 1 + j)?;
}
layouter.constrain_instance(assigned_total.cell(), self.get_instance(), 1)?;

self.load_lookup_table(layouter)?;

Ok(())
}

/// Initializes the range check chips
fn initialize_range_check_chips(&self) -> Vec<RangeCheckU64Chip>;
fn initialize_range_check_chip(&self) -> Vec<RangeCheckU64Chip>;

/// Loads the lookup table
fn load_lookup_table(&self, layouter: impl Layouter<Fp>) -> Result<(), Error>;

/// Constrains the last decompositions of the balances to be zero
fn constrain_decompositions(
&self,
last_decompositions: Vec<halo2_proofs::circuit::AssignedCell<Fp, Fp>>,
last_decomposition: halo2_proofs::circuit::AssignedCell<Fp, Fp>,
layouter: &mut impl Layouter<Fp>,
) -> Result<(), Error>;
}
25 changes: 11 additions & 14 deletions prover/src/circuits/config/no_range_check_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,29 @@ use super::circuit_config::CircuitConfig;
///
/// # Type Parameters
///
/// * `N_CURRENCIES`: The number of currencies for which the solvency is verified.
/// * `N_USERS`: The number of users for which the solvency is verified.
///
/// # Fields
///
/// * `username`: Advice column used to store the usernames of the users
/// * `balances`: Advice columns used to store the balances of the users
/// * `balance`: Advice columns used to store the balance of the users
#[derive(Clone)]
pub struct NoRangeCheckConfig<const N_CURRENCIES: usize, const N_USERS: usize> {
pub struct NoRangeCheckConfig<const N_USERS: usize> {
username: Column<Advice>,
balances: [Column<Advice>; N_CURRENCIES],
balance: Column<Advice>,
instance: Column<Instance>,
}

impl<const N_CURRENCIES: usize, const N_USERS: usize> CircuitConfig<N_CURRENCIES, N_USERS>
for NoRangeCheckConfig<N_CURRENCIES, N_USERS>
{
impl<const N_USERS: usize> CircuitConfig<N_USERS> for NoRangeCheckConfig<N_USERS> {
fn configure(
_: &mut ConstraintSystem<Fp>,
username: Column<Advice>,
balances: [Column<Advice>; N_CURRENCIES],
balance: Column<Advice>,
instance: Column<Instance>,
) -> NoRangeCheckConfig<N_CURRENCIES, N_USERS> {
) -> NoRangeCheckConfig<N_USERS> {
Self {
username,
balances,
balance,
instance,
}
}
Expand All @@ -47,8 +44,8 @@ impl<const N_CURRENCIES: usize, const N_USERS: usize> CircuitConfig<N_CURRENCIES
self.username
}

fn get_balances(&self) -> [Column<Advice>; N_CURRENCIES] {
self.balances
fn get_balance(&self) -> Column<Advice> {
self.balance
}

fn get_instance(&self) -> Column<Instance> {
Expand All @@ -57,7 +54,7 @@ impl<const N_CURRENCIES: usize, const N_USERS: usize> CircuitConfig<N_CURRENCIES

// The following methods are not implemented for NoRangeCheckConfig

fn initialize_range_check_chips(&self) -> Vec<RangeCheckU64Chip> {
fn initialize_range_check_chip(&self) -> Vec<RangeCheckU64Chip> {
vec![]
}

Expand All @@ -67,7 +64,7 @@ impl<const N_CURRENCIES: usize, const N_USERS: usize> CircuitConfig<N_CURRENCIES

fn constrain_decompositions(
&self,
_: Vec<halo2_proofs::circuit::AssignedCell<Fp, Fp>>,
_: halo2_proofs::circuit::AssignedCell<Fp, Fp>,
_: &mut impl Layouter<Fp>,
) -> Result<(), Error> {
Ok(())
Expand Down
Loading

0 comments on commit 9d3b52c

Please sign in to comment.