From 33c018ac83b19d65f7cf77e7d0d83e7ac430f591 Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 2 May 2023 17:41:52 +0200 Subject: [PATCH 1/5] bump bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 7a8392f59c..0b59f9e3f9 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 7a8392f59c73effffcc484f93ebf117f8b66e21d +Subproject commit 0b59f9e3f983ca59f5f5f6e62b78fb7d0e25b90f From a673ceeea546e2b0894e89b9082e25909356c386 Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 2 May 2023 17:42:10 +0200 Subject: [PATCH 2/5] base off of bindings-2 --- src/lib/hash.ts | 37 +++++++++++++++++++++++++++++++++++-- src/snarky.d.ts | 7 +++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/lib/hash.ts b/src/lib/hash.ts index cef036df3d..053b364f9c 100644 --- a/src/lib/hash.ts +++ b/src/lib/hash.ts @@ -1,5 +1,10 @@ -import { HashInput, ProvableExtended, Struct } from './circuit_value.js'; -import { Poseidon as Poseidon_, Field } from '../snarky.js'; +import { + HashInput, + provable, + ProvableExtended, + Struct, +} from './circuit_value.js'; +import { Poseidon as Poseidon_, Field, Bool, Circuit } from '../snarky.js'; import { inCheckedComputation } from './proof_system.js'; import { createHashHelpers } from './hash-generic.js'; @@ -43,6 +48,34 @@ const Poseidon = { return Poseidon_.hash(input, isChecked); }, + hashToGroup(input: Field[]) { + let isChecked = !input.every((x) => x.isConstant()); + // y = sqrt(y^2) + let { x, y } = Poseidon_.hashToGroup(input, isChecked); + + let { x0, x1 } = Circuit.witness(provable({ x0: Field, x1: Field }), () => { + // the even root of y^2 will become x0, so the APIs are uniform + let isEven = y.toBigInt() % 2n === 0n; + + // r is the second root of sqrt(y^2) + let r = y.mul(-1); + // we just change the order so the even root is x0 and the odd x1 + return isEven ? { x0: y, x1: r } : { x0: r, x1: y }; + }); + + // we check that either x0 or x1 match the original root y + y.equals(x0).or(y.equals(x1)).assertTrue(); + + // and then we check that either x0 or x1 is the expected second root of y^2 + let y_ = y.mul(-1); + y_.equals(x0).or(y_.equals(x1)).assertTrue(); + + return { + x, + y: { x0, x1 }, + }; + }, + update(state: [Field, Field, Field], input: Field[]) { let isChecked = !( state.every((x) => x.isConstant()) && input.every((x) => x.isConstant()) diff --git a/src/snarky.d.ts b/src/snarky.d.ts index b9fcd7c58f..a23c38ae7f 100644 --- a/src/snarky.d.ts +++ b/src/snarky.d.ts @@ -1101,6 +1101,13 @@ declare const Poseidon: { input: Field[], isChecked: boolean ): [Field, Field, Field]; + hashToGroup( + input: Field[], + isChecked: boolean + ): { + x: Field; + y: Field; + }; prefixes: Record< | 'event' | 'events' From 167de551ca75ac29e7bdfdf466657f2314db6617 Mon Sep 17 00:00:00 2001 From: Florian Date: Wed, 3 May 2023 13:38:47 +0200 Subject: [PATCH 3/5] bump bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 0b59f9e3f9..d86ea91c54 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 0b59f9e3f983ca59f5f5f6e62b78fb7d0e25b90f +Subproject commit d86ea91c54a398a2f562f92586bc56dc3e5cd149 From f557db481d407396816b15f466b1fa126ded4127 Mon Sep 17 00:00:00 2001 From: Florian Date: Wed, 3 May 2023 15:00:26 +0200 Subject: [PATCH 4/5] bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index d86ea91c54..89e2d3c295 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit d86ea91c54a398a2f562f92586bc56dc3e5cd149 +Subproject commit 89e2d3c295bb35dfe7bea6a318686c05c8023897 From 5abe1945257ef0fb0122104397b7733c52312658 Mon Sep 17 00:00:00 2001 From: Florian Date: Thu, 4 May 2023 07:34:30 +0200 Subject: [PATCH 5/5] reduce constraints --- src/lib/hash.ts | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/lib/hash.ts b/src/lib/hash.ts index 053b364f9c..d4ba94caa1 100644 --- a/src/lib/hash.ts +++ b/src/lib/hash.ts @@ -53,27 +53,21 @@ const Poseidon = { // y = sqrt(y^2) let { x, y } = Poseidon_.hashToGroup(input, isChecked); - let { x0, x1 } = Circuit.witness(provable({ x0: Field, x1: Field }), () => { + let x0 = Circuit.witness(Field, () => { // the even root of y^2 will become x0, so the APIs are uniform let isEven = y.toBigInt() % 2n === 0n; - // r is the second root of sqrt(y^2) - let r = y.mul(-1); - // we just change the order so the even root is x0 and the odd x1 - return isEven ? { x0: y, x1: r } : { x0: r, x1: y }; + // we just change the order so the even root is x0 + // y.mul(-1); is the second root of sqrt(y^2) + return isEven ? y : y.mul(-1); }); + let x1 = x0.mul(-1); + // we check that either x0 or x1 match the original root y y.equals(x0).or(y.equals(x1)).assertTrue(); - // and then we check that either x0 or x1 is the expected second root of y^2 - let y_ = y.mul(-1); - y_.equals(x0).or(y_.equals(x1)).assertTrue(); - - return { - x, - y: { x0, x1 }, - }; + return { x, y: { x0, x1 } }; }, update(state: [Field, Field, Field], input: Field[]) {