Have hash functions take references to avoid cloning (#438)

And other tweaks to `MerkleTree::new`
This commit is contained in:
Daniel Lubarov 2022-01-18 12:51:04 -08:00 committed by GitHub
parent fcdcc86569
commit dcf63f536e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 39 additions and 32 deletions

View File

@ -1,3 +1,4 @@
use itertools::Itertools;
use plonky2_field::extension_field::{flatten, unflatten, Extendable};
use plonky2_field::polynomial::{PolynomialCoeffs, PolynomialValues};
use plonky2_util::reverse_index_bits_in_place;
@ -116,12 +117,12 @@ fn fri_proof_of_work<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, c
.into_par_iter()
.find_any(|&i| {
C::InnerHasher::hash(
current_hash
&current_hash
.elements
.iter()
.copied()
.chain(Some(F::from_canonical_u64(i)))
.collect(),
.collect_vec(),
false,
)
.elements[0]

View File

@ -107,7 +107,7 @@ impl<F: RichField> Hasher<F> for GMiMCHash {
type Hash = HashOut<F>;
type Permutation = GMiMCPermutation;
fn hash(input: Vec<F>, pad: bool) -> Self::Hash {
fn hash(input: &[F], pad: bool) -> Self::Hash {
hash_n_to_hash::<F, Self::Permutation>(input, pad)
}

View File

@ -18,7 +18,7 @@ pub fn hash_or_noop<F: RichField, P: PlonkyPermutation<F>>(inputs: Vec<F>) -> Ha
if inputs.len() <= 4 {
HashOut::from_partial(inputs)
} else {
hash_n_to_hash::<F, P>(inputs, false)
hash_n_to_hash::<F, P>(&inputs, false)
}
}
@ -101,16 +101,18 @@ pub trait PlonkyPermutation<F: RichField> {
/// for the hash to be secure, but it can safely be disabled in certain cases, like if the input
/// length is fixed.
pub fn hash_n_to_m<F: RichField, P: PlonkyPermutation<F>>(
mut inputs: Vec<F>,
inputs: &[F],
num_outputs: usize,
pad: bool,
) -> Vec<F> {
if pad {
inputs.push(F::ZERO);
while (inputs.len() + 1) % SPONGE_WIDTH != 0 {
inputs.push(F::ONE);
let mut padded_inputs = inputs.to_vec();
padded_inputs.push(F::ZERO);
while (padded_inputs.len() + 1) % SPONGE_WIDTH != 0 {
padded_inputs.push(F::ONE);
}
inputs.push(F::ZERO);
padded_inputs.push(F::ZERO);
return hash_n_to_m::<F, P>(&padded_inputs, num_outputs, false);
}
let mut state = [F::ZERO; SPONGE_WIDTH];
@ -135,7 +137,7 @@ pub fn hash_n_to_m<F: RichField, P: PlonkyPermutation<F>>(
}
pub fn hash_n_to_hash<F: RichField, P: PlonkyPermutation<F>>(
inputs: Vec<F>,
inputs: &[F],
pad: bool,
) -> HashOut<F> {
HashOut::from_vec(hash_n_to_m::<F, P>(inputs, 4, pad))

View File

@ -56,9 +56,9 @@ impl<F: RichField, const N: usize> Hasher<F> for KeccakHash<N> {
type Hash = BytesHash<N>;
type Permutation = KeccakPermutation;
fn hash(input: Vec<F>, _pad: bool) -> Self::Hash {
fn hash(input: &[F], _pad: bool) -> Self::Hash {
let mut buffer = Buffer::new(Vec::new());
buffer.write_field_vec(&input).unwrap();
buffer.write_field_vec(input).unwrap();
let mut arr = [0; N];
let hash_bytes = keccak(buffer.bytes()).0;
arr.copy_from_slice(&hash_bytes[..N]);

View File

@ -32,7 +32,7 @@ pub(crate) fn verify_merkle_proof<F: RichField, H: Hasher<F>>(
proof: &MerkleProof<F, H>,
) -> Result<()> {
let mut index = leaf_index;
let mut current_digest = H::hash(leaf_data, false);
let mut current_digest = H::hash(&leaf_data, false);
for &sibling_digest in proof.siblings.iter() {
let bit = index & 1;
index >>= 1;

View File

@ -36,21 +36,24 @@ pub struct MerkleTree<F: RichField, H: Hasher<F>> {
impl<F: RichField, H: Hasher<F>> MerkleTree<F, H> {
pub fn new(leaves: Vec<Vec<F>>, cap_height: usize) -> Self {
let mut layers = vec![leaves
let mut current_layer = leaves
.par_iter()
.map(|l| H::hash(l.clone(), false))
.collect::<Vec<_>>()];
while let Some(l) = layers.last() {
if l.len() == 1 << cap_height {
break;
.map(|l| H::hash(l, false))
.collect::<Vec<_>>();
let mut layers = vec![];
let cap = loop {
if current_layer.len() == 1 << cap_height {
break current_layer;
}
let next_layer = l
let next_layer = current_layer
.par_chunks(2)
.map(|chunk| H::two_to_one(chunk[0], chunk[1]))
.collect::<Vec<_>>();
layers.push(next_layer);
}
let cap = layers.pop().unwrap();
layers.push(current_layer);
current_layer = next_layer;
};
Self {
leaves,
layers,

View File

@ -66,7 +66,7 @@ pub(crate) fn decompress_merkle_proofs<F: RichField, H: Hasher<F>>(
for (&i, v) in leaves_indices.iter().zip(leaves_data) {
// Observe the leaves.
seen.insert(i + num_leaves, H::hash(v.to_vec(), false));
seen.insert(i + num_leaves, H::hash(v, false));
}
// Iterators over the siblings.

View File

@ -633,7 +633,7 @@ impl<F: RichField> Hasher<F> for PoseidonHash {
type Hash = HashOut<F>;
type Permutation = PoseidonPermutation;
fn hash(input: Vec<F>, pad: bool) -> Self::Hash {
fn hash(input: &[F], pad: bool) -> Self::Hash {
hash_n_to_hash::<F, Self::Permutation>(input, pad)
}

View File

@ -725,7 +725,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
constants_sigmas_cap.flatten(),
vec![/* Add other circuit data here */],
];
let circuit_digest = C::Hasher::hash(circuit_digest_parts.concat(), false);
let circuit_digest = C::Hasher::hash(&circuit_digest_parts.concat(), false);
let common = CommonCircuitData {
config: self.config,

View File

@ -32,7 +32,7 @@ pub trait Hasher<F: RichField>: Sized + Clone + Debug + Eq + PartialEq {
/// Permutation used in the sponge construction.
type Permutation: PlonkyPermutation<F>;
fn hash(input: Vec<F>, pad: bool) -> Self::Hash;
fn hash(input: &[F], pad: bool) -> Self::Hash;
fn two_to_one(left: Self::Hash, right: Self::Hash) -> Self::Hash;
}

View File

@ -1,5 +1,6 @@
use std::collections::HashSet;
use itertools::Itertools;
use plonky2_field::extension_field::Extendable;
use plonky2_field::polynomial::PolynomialCoeffs;
@ -65,13 +66,13 @@ fn get_challenges<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, cons
challenger.observe_extension_elements(&final_poly.coeffs);
let fri_pow_response = C::InnerHasher::hash(
challenger
&challenger
.get_hash()
.elements
.iter()
.copied()
.chain(Some(pow_witness))
.collect(),
.collect_vec(),
false,
)
.elements[0];

View File

@ -90,7 +90,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
pub(crate) fn get_public_inputs_hash(
&self,
) -> <<C as GenericConfig<D>>::InnerHasher as Hasher<F>>::Hash {
C::InnerHasher::hash(self.public_inputs.clone(), true)
C::InnerHasher::hash(&self.public_inputs, true)
}
pub fn to_bytes(&self) -> anyhow::Result<Vec<u8>> {
@ -206,7 +206,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
pub(crate) fn get_public_inputs_hash(
&self,
) -> <<C as GenericConfig<D>>::InnerHasher as Hasher<F>>::Hash {
C::InnerHasher::hash(self.public_inputs.clone(), true)
C::InnerHasher::hash(&self.public_inputs, true)
}
pub fn to_bytes(&self) -> anyhow::Result<Vec<u8>> {

View File

@ -43,7 +43,7 @@ pub(crate) fn prove<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, co
);
let public_inputs = partition_witness.get_targets(&prover_data.public_inputs);
let public_inputs_hash = C::InnerHasher::hash(public_inputs.clone(), true);
let public_inputs_hash = C::InnerHasher::hash(&public_inputs, true);
if cfg!(debug_assertions) {
// Display the marked targets for debugging purposes.