Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Hash to Curve Utility for Secp256k1 #261

Open
wants to merge 24 commits into
base: community-edition
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
18a0fc0
feat: added expand msg impl
shreyas-londhe Feb 3, 2024
b2e2cde
feat: hash to field
shreyas-londhe Feb 6, 2024
8741785
feat(wip): hash_to_curve impl
shreyas-londhe Feb 6, 2024
9e0a842
feat: hash_to_curve impl done
shreyas-londhe Feb 7, 2024
58c190b
chore: minor changes
shreyas-londhe Feb 8, 2024
65713b9
fix(wip): bigint conversion
shreyas-londhe Feb 13, 2024
657276d
fix(wip): hash_to_curve_working
shreyas-londhe Feb 13, 2024
2d4adae
chore: code cleanup
shreyas-londhe Feb 13, 2024
b24d103
fix: hash_to_curve w/o precompute values
shreyas-londhe Feb 14, 2024
a202c6d
fix: minor changes
shreyas-londhe Feb 14, 2024
90d647b
feat: hash_to_curve working 🚀
shreyas-londhe Feb 14, 2024
23f3419
test: added more test cases
shreyas-londhe Feb 15, 2024
39a84fe
fix: added missing bit range checks
shreyas-londhe Apr 22, 2024
bffb790
fix: changed utils functions
shreyas-londhe Apr 26, 2024
5b64f76
Add link to PLUME to examples (#263)
Divide-By-0 Mar 10, 2024
63d58f5
chore: update rust toolchain (#266)
jonathanpwang Mar 22, 2024
5195ae6
Fix some typos (#265)
0xisk Mar 29, 2024
5ce9ecf
chore: fix typo (#267)
goofylfg Apr 16, 2024
957445b
chore(all):fix typos (#268)
AdventureSeeker987 Apr 26, 2024
72037c8
fix: mod_inverse bug
shreyas-londhe May 17, 2024
ce67506
fix: added check on p for sqrt
shreyas-londhe Jun 14, 2024
b7f4960
fix: sha256 init_state in fixed column
shreyas-londhe Jun 21, 2024
243f778
fix: xy2_selector
shreyas-londhe Jun 21, 2024
3cd064f
docs: added acknowledgement
shreyas-londhe Jun 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ cd halo2-lib
- [halo2-rsa](https://github.com/zkemail/halo2-rsa/tree/feat/new_bigint)
- [halo2-fri-gadget](https://github.com/maxgillett/halo2-fri-gadget) -- FRI verifier in halo2.
- [eth-voice-recovery](https://github.com/SoraSuegami/voice_recovery_circuit) -- Verify the voice recovery process.
- [PLUME ERC 7524 Signatures](https://github.com/plume-sig/zk-nullifier-sig/pull/83) - Verify deterministic PLUME signatures of Ethereum keys, for private voting nullifiers.
- [zkEVM signature verification circuit](https://github.com/scroll-tech/zkevm-circuits/tree/develop/zkevm-circuits/src/sig_circuit.rs)
- [zkEVM tx-circuit](https://github.com/scroll-tech/zkevm-circuits/tree/develop/zkevm-circuits/src/tx_circuit)
- [webauthn-halo2](https://github.com/zkwebauthn/webauthn-halo2) -- Proving and verifying WebAuthn with halo2.
Expand Down
2 changes: 1 addition & 1 deletion halo2-base/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ QuantumCell contains the following enum variants.
Assigns an entirely new witness value into the advice column, such as a private input. When `assign_cell()` is called the value is wrapped in as an `Assigned::Trivial()` which marks it for exclusion from batch inversion.

- **WitnessFraction**:
Assigns an entirely new witness value to the advice column. `WitnessFraction` exists for optimization purposes and accepts Assigned values wrapped in `Assigned::Rational()` marked for batch inverion (see [Assigned](#assigned)).
Assigns an entirely new witness value to the advice column. `WitnessFraction` exists for optimization purposes and accepts Assigned values wrapped in `Assigned::Rational()` marked for batch inversion (see [Assigned](#assigned)).

- **Constant**:
A value that is a "known" constant. A "known" refers to known at circuit creation time to both the Prover and Verifier. When you assign a constant value there exists another secret Fixed column in the circuit constraint table whose values are fixed at circuit creation time. When you assign a Constant value, you are adding this value to the Fixed column, adding the value as a witness to the Advice column, and then imposing an equality constraint between the two corresponding cells in the Fixed and Advice columns.
4 changes: 2 additions & 2 deletions halo2-base/src/gates/circuit/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl<F: ScalarField> Default for BaseCircuitBuilder<F> {
impl<F: ScalarField> BaseCircuitBuilder<F> {
/// Creates a new [BaseCircuitBuilder] with all default managers.
/// * `witness_gen_only`:
/// * If true, the builder only does witness asignments and does not store constraint information -- this should only be used for the real prover.
/// * If true, the builder only does witness assignments and does not store constraint information -- this should only be used for the real prover.
/// * If false, the builder also imposes constraints (selectors, fixed columns, copy constraints). Primarily used for keygen and mock prover (but can also be used for real prover).
///
/// By default, **no** circuit configuration parameters have been set.
Expand Down Expand Up @@ -254,7 +254,7 @@ impl<F: ScalarField> BaseCircuitBuilder<F> {

/// Auto-calculates configuration parameters for the circuit and sets them.
///
/// * `k`: The number of in the circuit (i.e. numeber of rows = 2<sup>k</sup>)
/// * `k`: The number of in the circuit (i.e. number of rows = 2<sup>k</sup>)
/// * `minimum_rows`: The minimum number of rows in the circuit that cannot be used for witness assignments and contain random `blinding factors` to ensure zk property, defaults to 0.
/// * `lookup_bits`: The fixed lookup table will consist of [0, 2<sup>lookup_bits</sup>)
pub fn calculate_params(&mut self, minimum_rows: Option<usize>) -> BaseCircuitParams {
Expand Down
8 changes: 4 additions & 4 deletions halo2-base/src/gates/flex_gate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl<F: ScalarField> FlexGateConfig<F> {
Self {
basic_gates,
constants,
/// Warning: this needs to be updated if you create more advice columns after this `FlexGateConfig` is created
// Warning: this needs to be updated if you create more advice columns after this `FlexGateConfig` is created
max_rows: (1 << params.k) - meta.minimum_rows(),
}
}
Expand Down Expand Up @@ -545,7 +545,7 @@ pub trait GateInstructions<F: ScalarField> {
ctx.last().unwrap()
}

/// Constrains and returns `a & b`, assumeing `a` and `b` are boolean.
/// Constrains and returns `a & b`, assuming `a` and `b` are boolean.
///
/// Defines a vertical gate of form | 0 | a | b | out |, where out = a * b.
/// * `ctx`: [Context] to add the constraints to.
Expand Down Expand Up @@ -590,7 +590,7 @@ pub trait GateInstructions<F: ScalarField> {
ctx.last().unwrap()
}

/// Constrains and returns `!a` assumeing `a` is boolean.
/// Constrains and returns `!a` assuming `a` is boolean.
///
/// Defines a vertical gate of form | 1 - a | a | 1 | 1 |, where 1 - a = out.
/// * `ctx`: [Context] to add the constraints to.
Expand Down Expand Up @@ -1204,7 +1204,7 @@ impl<F: ScalarField> GateInstructions<F> for GateChip<F> {
ctx.last().unwrap()
}

/// Constains and returns `a || (b && c)`, assuming `a`, `b` and `c` are boolean.
/// Constrains and returns `a || (b && c)`, assuming `a`, `b` and `c` are boolean.
///
/// Defines a vertical gate of form `| 1 - b c | b | c | 1 | a - 1 | 1 - b c | out | a - 1 | 1 | 1 | a |`, where out = a + b * c - a * b * c.
/// * `ctx`: [Context] to add the constraints to
Expand Down
4 changes: 2 additions & 2 deletions halo2-base/src/gates/flex_gate/threads/multi_phase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl<F: ScalarField> MultiPhaseCoreManager<F> {
/// Creates a new [MultiPhaseCoreManager] with a default [SinglePhaseCoreManager] in phase 0.
/// Creates an empty [SharedCopyConstraintManager] and sets `witness_gen_only` flag.
/// * `witness_gen_only`: If true, the [MultiPhaseCoreManager] is used for witness generation only.
/// * If true, the gate thread builder only does witness asignments and does not store constraint information -- this should only be used for the real prover.
/// * If true, the gate thread builder only does witness assignments and does not store constraint information -- this should only be used for the real prover.
/// * If false, the gate thread builder is used for keygen and mock prover (it can also be used for real prover) and the builder stores circuit information (e.g. copy constraints, fixed columns, enabled selectors).
/// * These values are fixed for the circuit at key generation time, and they do not need to be re-computed by the prover in the actual proving phase.
pub fn new(witness_gen_only: bool) -> Self {
Expand Down Expand Up @@ -126,7 +126,7 @@ impl<F: ScalarField> MultiPhaseCoreManager<F> {

/// Auto-calculates configuration parameters for the circuit
///
/// * `k`: The number of in the circuit (i.e. numeber of rows = 2<sup>k</sup>)
/// * `k`: The number of in the circuit (i.e. number of rows = 2<sup>k</sup>)
/// * `minimum_rows`: The minimum number of rows in the circuit that cannot be used for witness assignments and contain random `blinding factors` to ensure zk property, defaults to 0.
pub fn calculate_params(&self, k: usize, minimum_rows: Option<usize>) -> FlexGateConfigParams {
let max_rows = (1 << k) - minimum_rows.unwrap_or(0);
Expand Down
2 changes: 1 addition & 1 deletion halo2-base/src/gates/flex_gate/threads/single_phase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub struct SinglePhaseCoreManager<F: ScalarField> {
impl<F: ScalarField> SinglePhaseCoreManager<F> {
/// Creates a new [SinglePhaseCoreManager] and spawns a main thread.
/// * `witness_gen_only`: If true, the [SinglePhaseCoreManager] is used for witness generation only.
/// * If true, the gate thread builder only does witness asignments and does not store constraint information -- this should only be used for the real prover.
/// * If true, the gate thread builder only does witness assignments and does not store constraint information -- this should only be used for the real prover.
/// * If false, the gate thread builder is used for keygen and mock prover (it can also be used for real prover) and the builder stores circuit information (e.g. copy constraints, fixed columns, enabled selectors).
/// * These values are fixed for the circuit at key generation time, and they do not need to be re-computed by the prover in the actual proving phase.
pub fn new(witness_gen_only: bool, copy_manager: SharedCopyConstraintManager<F>) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion halo2-base/src/gates/tests/bitwise_rotate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ fn test_bitwise_rotate_gen<const BIT: usize, const NUM_BITS: usize>(

#[test]
fn test_bitwise_rotate() {
// "<<" is leftroate. ">>" is rightrotate.
// "<<" is leftrotate. ">>" is rightrotate.
// 1 << 8 == 256
test_bitwise_rotate_gen::<8, 10>(8, true, 1, 256, true);
// 1 << 8 != 255
Expand Down
2 changes: 1 addition & 1 deletion halo2-base/src/gates/tests/neg_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ fn arb_indicator<F: ScalarField>(max_size: usize) -> impl Strategy<Value = Vec<F

fn check_idx_to_indicator(idx: Fr, len: usize, ind_witnesses: &[Fr]) -> bool {
// check that:
// the length of the witnes array is correct
// the length of the witness array is correct
// the sum of the witnesses is 1, indicting that there is only one index that is 1
if ind_witnesses.len() != len
|| ind_witnesses.iter().fold(Fr::zero(), |acc, val| acc + *val) != Fr::one()
Expand Down
2 changes: 1 addition & 1 deletion halo2-base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ use virtual_region::copy_constraints::SharedCopyConstraintManager;
pub mod gates;
/// Module for the Poseidon hash function.
pub mod poseidon;
/// Module for SafeType which enforce value range and realted functions.
/// Module for SafeType which enforce value range and related functions.
pub mod safe_types;
/// Utility functions for converting between different types of field elements.
pub mod utils;
Expand Down
2 changes: 1 addition & 1 deletion halo2-base/src/poseidon/hasher/mds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct SparseMDSMatrix<F: PrimeField, const T: usize, const RATE: usize> {
pub(crate) col_hat: [F; RATE],
}

/// `MDSMatrix` is applied to `State` to achive linear layer of Poseidon
/// `MDSMatrix` is applied to `State` to achieve linear layer of Poseidon
#[derive(Clone, Debug)]
pub struct MDSMatrix<F, const T: usize, const RATE: usize>(pub(crate) Mds<F, T>);

Expand Down
2 changes: 1 addition & 1 deletion halo2-base/src/poseidon/hasher/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ impl<F: ScalarField, const T: usize, const RATE: usize> PoseidonHasher<F, T, RAT
let is_full = gate.is_equal(ctx, input.len, Constant(F::from(RATE as u64)));
// Case 1: if len != RATE.
state.permutation(ctx, gate, &input.inputs, Some(input.len), &self.spec);
// Case 2: if len == RATE, an extra permuation is needed for squeeze.
// Case 2: if len == RATE, an extra permutation is needed for squeeze.
let mut state_2 = state.clone();
state_2.permutation(ctx, gate, &[], None, &self.spec);
// Select the result of case 1/2 depending on if len == RATE.
Expand Down
22 changes: 12 additions & 10 deletions halo2-base/src/poseidon/hasher/tests/hasher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct Payload<F: ScalarField> {
}

// check if the results from hasher and native sponge are same for hash_var_len_array.
fn hasher_compatiblity_verification<
fn hasher_compatibility_verification<
const T: usize,
const RATE: usize,
const R_F: usize,
Expand Down Expand Up @@ -50,7 +50,7 @@ fn hasher_compatiblity_verification<
}

// check if the results from hasher and native sponge are same for hash_compact_input.
fn hasher_compact_inputs_compatiblity_verification<
fn hasher_compact_inputs_compatibility_verification<
const T: usize,
const RATE: usize,
const R_F: usize,
Expand Down Expand Up @@ -115,7 +115,7 @@ fn hasher_compact_inputs_compatiblity_verification<
}

// check if the results from hasher and native sponge are same for hash_compact_input.
fn hasher_compact_chunk_inputs_compatiblity_verification<
fn hasher_compact_chunk_inputs_compatibility_verification<
const T: usize,
const RATE: usize,
const R_F: usize,
Expand Down Expand Up @@ -189,7 +189,7 @@ fn random_payload_without_len<F: ScalarField>(max_len: usize, max_value: usize)
}

#[test]
fn test_poseidon_hasher_compatiblity() {
fn test_poseidon_hasher_compatibility() {
{
const T: usize = 3;
const RATE: usize = 2;
Expand All @@ -216,7 +216,7 @@ fn test_poseidon_hasher_compatiblity() {
random_payload(RATE * 2 + 1, RATE * 2 + 1, usize::MAX),
random_payload(RATE * 5 + 1, RATE * 5 + 1, usize::MAX),
];
hasher_compatiblity_verification::<T, RATE, 8, 57>(payloads);
hasher_compatibility_verification::<T, RATE, 8, 57>(payloads);
}
}

Expand Down Expand Up @@ -262,7 +262,9 @@ fn test_poseidon_hasher_compact_inputs() {
random_payload(RATE * 5, RATE * 5, usize::MAX),
];
base_test().k(12).run(|ctx, range| {
hasher_compact_inputs_compatiblity_verification::<T, RATE, 8, 57>(payloads, ctx, range);
hasher_compact_inputs_compatibility_verification::<T, RATE, 8, 57>(
payloads, ctx, range,
);
});
}
}
Expand All @@ -289,7 +291,7 @@ fn test_poseidon_hasher_compact_inputs_with_prover() {
.collect::<Vec<_>>();
base_test().k(12).bench_builder(init_payloads, logic_payloads, |pool, range, input| {
let ctx = pool.main();
hasher_compact_inputs_compatiblity_verification::<T, RATE, 8, 57>(input, ctx, range);
hasher_compact_inputs_compatibility_verification::<T, RATE, 8, 57>(input, ctx, range);
});
}
}
Expand All @@ -306,7 +308,7 @@ fn test_poseidon_hasher_compact_chunk_inputs() {
(random_payload(RATE * 3, RATE * 3, usize::MAX), true),
];
base_test().k(12).run(|ctx, range| {
hasher_compact_chunk_inputs_compatiblity_verification::<T, RATE, 8, 57>(
hasher_compact_chunk_inputs_compatibility_verification::<T, RATE, 8, 57>(
payloads, ctx, range,
);
});
Expand All @@ -320,7 +322,7 @@ fn test_poseidon_hasher_compact_chunk_inputs() {
(random_payload(0, 0, usize::MAX), false),
];
base_test().k(12).run(|ctx, range| {
hasher_compact_chunk_inputs_compatiblity_verification::<T, RATE, 8, 57>(
hasher_compact_chunk_inputs_compatibility_verification::<T, RATE, 8, 57>(
payloads, ctx, range,
);
});
Expand Down Expand Up @@ -349,7 +351,7 @@ fn test_poseidon_hasher_compact_chunk_inputs_with_prover() {
.collect::<Vec<_>>();
base_test().k(12).bench_builder(init_payloads, logic_payloads, |pool, range, input| {
let ctx = pool.main();
hasher_compact_chunk_inputs_compatiblity_verification::<T, RATE, 8, 57>(
hasher_compact_chunk_inputs_compatibility_verification::<T, RATE, 8, 57>(
input, ctx, range,
);
});
Expand Down
8 changes: 4 additions & 4 deletions halo2-base/src/poseidon/hasher/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ mod state;
fn test_mds() {
let spec = OptimizedPoseidonSpec::<Fr, 3, 2>::new::<8, 57, 0>();

let mds = vec![
vec![
let mds = [
[
"7511745149465107256748700652201246547602992235352608707588321460060273774987",
"10370080108974718697676803824769673834027675643658433702224577712625900127200",
"19705173408229649878903981084052839426532978878058043055305024233888854471533",
],
vec![
[
"18732019378264290557468133440468564866454307626475683536618613112504878618481",
"20870176810702568768751421378473869562658540583882454726129544628203806653987",
"7266061498423634438633389053804536045105766754026813321943009179476902321146",
],
vec![
[
"9131299761947733513298312097611845208338517739621853568979632113419485819303",
"10595341252162738537912664445405114076324478519622938027420701542910180337937",
"11597556804922396090267472882856054602429588299176362916247939723151043581408",
Expand Down
8 changes: 4 additions & 4 deletions halo2-base/src/safe_types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const BITS_PER_BYTE: usize = 8;
/// where each [`AssignedValue`] represents 1 byte. However, the range of [`AssignedValue<F>`] is much
/// larger than 1 byte(0~255). If a circuit takes 32 [`AssignedValue<F>`] as inputs and some of them
/// are actually greater than 255, there could be some undefined behaviors.
/// [`SafeType`] gurantees the value range of its owned [`AssignedValue<F>`]. So circuits don't need to
/// [`SafeType`] guarantees the value range of its owned [`AssignedValue<F>`]. So circuits don't need to
/// do any extra value checking if they take SafeType as inputs.
/// - `TOTAL_BITS` is the number of total bits of this type.
/// - `BYTES_PER_ELE` is the number of bytes of each element.
Expand Down Expand Up @@ -131,7 +131,7 @@ impl<'a, F: ScalarField> SafeTypeChip<'a, F> {

/// Convert a vector of AssignedValue (treated as little-endian) to a SafeType.
/// The number of bytes of inputs must equal to the number of bytes of outputs.
/// This function also add contraints that a AssignedValue in inputs must be in the range of a byte.
/// This function also add constraints that a AssignedValue in inputs must be in the range of a byte.
pub fn raw_bytes_to<const BYTES_PER_ELE: usize, const TOTAL_BITS: usize>(
&self,
ctx: &mut Context<F>,
Expand Down Expand Up @@ -276,7 +276,7 @@ impl<'a, F: ScalarField> SafeTypeChip<'a, F> {
///
/// * inputs: Vector representing the byte array, right padded to `max_len`. See [VarLenBytesVec] for details about padding.
/// * len: [`AssignedValue<F>`] witness representing the variable length of the byte array. Constrained to be `<= max_len`.
/// * max_len: [usize] representing the maximum length of the byte array and the number of elements it must contain. We enforce this to be provided explictly to make sure length of `inputs` is determinstic.
/// * max_len: [usize] representing the maximum length of the byte array and the number of elements it must contain. We enforce this to be provided explicitly to make sure length of `inputs` is deterministic.
///
/// ## Assumptions
/// * `max_len < u64::MAX` to prevent overflow (but you should never make an array this large)
Expand Down Expand Up @@ -311,7 +311,7 @@ impl<'a, F: ScalarField> SafeTypeChip<'a, F> {
/// Converts a slice of AssignedValue(treated as little-endian) to FixLenBytesVec.
///
/// * inputs: Slice representing the byte array.
/// * len: length of the byte array. We enforce this to be provided explictly to make sure length of `inputs` is determinstic.
/// * len: length of the byte array. We enforce this to be provided explicitly to make sure length of `inputs` is deterministic.
pub fn raw_to_fix_len_bytes_vec(
&self,
ctx: &mut Context<F>,
Expand Down
2 changes: 1 addition & 1 deletion halo2-base/src/safe_types/tests/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use rand::rngs::OsRng;
use std::vec;
use test_case::test_case;

// =========== Utilies ===============
// =========== Utilities ===============
fn mock_circuit_test<FM: FnMut(&mut Context<Fr>, SafeTypeChip<'_, Fr>)>(mut f: FM) {
base_test().k(10).lookup_bits(8).run(|ctx, range| {
let safe = SafeTypeChip::new(range);
Expand Down
2 changes: 1 addition & 1 deletion halo2-base/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub trait ScalarField: PrimeField + FromUniformBytes<64> + From<bool> + Hash + O
/// Creates a field element from a little endian byte representation.
///
/// The default implementation assumes that `PrimeField::from_repr` is implemented for little-endian.
/// It should be overriden if this is not the case.
/// It should be overridden if this is not the case.
fn from_bytes_le(bytes: &[u8]) -> Self {
let mut repr = Self::Repr::default();
repr.as_mut()[..bytes.len()].copy_from_slice(bytes);
Expand Down
3 changes: 2 additions & 1 deletion halo2-ecc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ rust-version = "1.73.0"
itertools = "0.11"
num-bigint = { version = "0.4", features = ["rand"] }
num-integer = "0.1"
num-traits = "0.2"
num-traits = "0.2.17"
rand_core = { version = "0.6", default-features = false, features = ["getrandom"] }
rand = "0.8"
rand_chacha = "0.3.1"
Expand All @@ -26,6 +26,7 @@ halo2-base = { version = "=0.4.1", path = "../halo2-base", default-features = fa

# plotting circuit layout
plotters = { version = "0.3.0", optional = true }
sha2 = "0.10.8"

[dev-dependencies]
ark-std = { version = "0.3.0", features = ["print-trace"] }
Expand Down
Loading