How to use pedersen hash/commitment?

I’ve been exploring Pedersen hash/commitment and encountered some challenges while attempting to generate the same hash in both JavaScript and Noir.
Despite my efforts, I haven’t achieved the desired outcome.

Here the noir pedersen use:

let hashPedersen = std::hash::pedersen_hash([value1, value2, value3, value4]);
let commitPedersen = std::hash::pedersen_commitment([value1, value2, value3, value4]);

std::println(hashPedersen);
std::println(commitPedersen);

And here multiple test in JS.
Firstly with Barretenberg:

async function pedersenHash(inputs: any[]) {
	const bb: Barretenberg = await Barretenberg.new(2);
	const inputArray: Fr[] = inputs.map((str) => Fr.fromString(str));
	return (await bb.pedersenCompress(inputArray)).toString();
}

secondly with circom JS

function pedersenHash(inputs: any[]) {
  const hash = pedersenB.hash(inputs);
  return hash;
}

function pedersenHashUnpack(inputs: any[]) {
  const unpackP = babyJub.unpackPoint(pedersenHash(inputs));
  return unpackP;
}

I’m aiming for a clear understanding of how to implement Pedersen hash/commitment in both JavaScript and Noir, ensuring consistency in the generated hashes.

Any assistance, code snippets, or recommendations would be immensely helpful.
Thanks in advance for your expertise!

80 Likes

Hello. Seems like you’re using a quite old version of bb.js… As pedersenCompress was removed some time ago.

Can you try to update, and if you still don’t get any other results, please let us know about your versions for Nargo and bb.js?

29 Likes

Finally, the safest solution for hash matching between JS and noir is to create a separate black-box program outside the ZKP circuit and execute it in JS.

It’s not the most optimized solution, but it’s certainly the easiest way to avoid going through all the JS libraries :wink:

The noir program:

use dep::std::hash::poseidon2;

fn main(value1: pub Field, value2: pub Field, value3: pub Field) -> pub  Field {
    let commitment = poseidon2::Poseidon2::hash([value1, value2, value3], 3);
    commitment
}

And here the Javascript code:

async function poseidonHash(data1: any, data2: any, data3: any): Promise<string> {
  const backendPoseidon = new BarretenbergBackend(poseidonCompiled);
  const noirPoseidon = new Noir(poseidonCompiled as any, backendPoseidon);

  const hashPrivate = await noirPoseidon.execute({
    amount1: data1.toString(),
    amount2: data2.toString(),
    secretShare: data3.toString(),
  });

  return hashPrivate.returnValue.toString();
}