-
Notifications
You must be signed in to change notification settings - Fork 135
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
Efficient scalar mul and other Scalar improvements #1530
Merged
Merged
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
5008583
simplify internal repr of scalar
mitschabaude 5420cb2
expose scale_fast_unpack
mitschabaude b8c19b9
first attempt at efficient scale gadget
mitschabaude a00a15a
wip debugging
mitschabaude 57de1f4
fix accessing ml curve point
mitschabaude 2eb6354
improve efficiency by using incomplete additions
mitschabaude d659493
rename gadget file
mitschabaude 43a0637
refactor 3 statements to loop
mitschabaude dcc58ee
move addition gadget to gadget file
mitschabaude 2192f29
remove cyclic dependency on group
mitschabaude bb0716c
simplify witness generation code
mitschabaude ddbec87
change scalar type to shifted 5 / 250 representation
mitschabaude 011d6a8
bring back fromBits, remove unused shifting methods
mitschabaude bc9b4ae
add scale from field element to test
mitschabaude b508437
bindings
mitschabaude 0f93cc2
dump vks
mitschabaude 04f8648
switch to repr with 1 low bit
mitschabaude 9f11f0c
but scaling with 0 or 1 doesn't work now
mitschabaude 32fd2b3
0 doesn't work anyway
mitschabaude 7ce21a7
vk regression
mitschabaude 5bc9543
fix
mitschabaude 4c06ce1
Revert "switch to repr with 1 low bit"
mitschabaude 6886184
add missing range checks, document more assumptions, add comments
mitschabaude 8fbfe9b
remove scalar limitations from group unit test
mitschabaude 5107a95
dump vks
mitschabaude d8fb076
move isOdd gadget to reuse it
mitschabaude 51ee9f5
dedicated gadget of 130 rows for scaling by Field
mitschabaude f88222d
use 1, 254 split and handle edge cases
mitschabaude 00680ed
reduce constraints
mitschabaude 0aad84e
tighten fromBits gadget
mitschabaude 37534df
remove unused split5 gadgets
mitschabaude ad7e7a3
dump vks
mitschabaude 8d5d338
renaming and test utils
mitschabaude 494e627
test utils
mitschabaude a8fea23
minor
mitschabaude fddead2
Merge branch 'main' into feature/no-shifted-scale
mitschabaude 35eb475
changelog
mitschabaude 7bcc84b
remove shifting stuff from foreign field unit test
mitschabaude e21fa33
comment
mitschabaude 9c799ed
add nullifier to vk-regression
mitschabaude 9e9ca06
mina
mitschabaude 4b4787e
Merge branch 'main' into feature/no-shifted-scale
mitschabaude 224b95c
fix changelog
mitschabaude dab6eb3
dump vks
mitschabaude 0877e26
Merge branch 'main' into feature/no-shifted-scale
mitschabaude 523330a
fixes and tweaks to scaling gadgets
mitschabaude 45837fc
remove redundant constraint
mitschabaude 9822654
dump vks
mitschabaude File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import type { Field } from '../field.js'; | ||
import type { Bool } from '../bool.js'; | ||
import { Fq } from '../../../bindings/crypto/finite-field.js'; | ||
import { PallasAffine } from '../../../bindings/crypto/elliptic-curve.js'; | ||
import { fieldToField3 } from './comparison.js'; | ||
import { Field3, ForeignField } from './foreign-field.js'; | ||
import { exists, existsOne } from '../core/exists.js'; | ||
import { bit, isConstant, packBits } from './common.js'; | ||
import { TupleN } from '../../util/types.js'; | ||
import { l } from './range-check.js'; | ||
import { createField } from '../core/field-constructor.js'; | ||
import { Snarky } from '../../../snarky.js'; | ||
import { Provable } from '../provable.js'; | ||
import { Group } from '../group.js'; | ||
|
||
export { scale, scaleShiftedSplit5 }; | ||
|
||
/** | ||
* Gadget to scale a point by a scalar, where the scalar is represented as a _native_ Field. | ||
*/ | ||
function scale(P: { x: Field; y: Field }, s: Field): Group { | ||
// constant case | ||
let { x, y } = P; | ||
if (x.isConstant() && y.isConstant() && s.isConstant()) { | ||
let sP = PallasAffine.scale( | ||
PallasAffine.fromNonzero({ x: x.toBigInt(), y: y.toBigInt() }), | ||
s.toBigInt() | ||
); | ||
return new Group({ x: createField(sP.x), y: createField(sP.y) }); | ||
} | ||
|
||
// compute t = s - 2^254 mod q using foreign field subtraction | ||
let sBig = fieldToField3(s); | ||
let twoTo254 = Field3.from(1n << 254n); | ||
let [t0, t1, t2] = ForeignField.sub(sBig, twoTo254, Fq.modulus); | ||
|
||
// split t into 250 high bits and 5 low bits | ||
// => split t0 into [5, 83] | ||
let tLo = exists(5, () => { | ||
let t = t0.toBigInt(); | ||
return [bit(t, 0), bit(t, 1), bit(t, 2), bit(t, 3), bit(t, 4)]; | ||
}); | ||
let tLoBools = TupleN.map(tLo, (x) => x.assertBool()); | ||
let tHi0 = existsOne(() => t0.toBigInt() >> 5n); | ||
|
||
// prove split | ||
// since we know that t0 < 2^88, this proves that t0High < 2^83 | ||
packBits(tLo) | ||
.add(tHi0.mul(1n << 5n)) | ||
.assertEquals(t0); | ||
|
||
// pack tHi | ||
let tHi = tHi0 | ||
.add(t1.mul(1n << (l - 5n))) | ||
.add(t2.mul(1n << (2n * l - 5n))) | ||
.seal(); | ||
|
||
// return (t + 2^254)*P = (s - 2^254 + 2^254)*P = s*P | ||
return scaleShiftedSplit5(P, tHi, tLoBools); | ||
} | ||
|
||
/** | ||
* Internal helper to compute `(t + 2^254)*P`. | ||
* `t` is expected to be split into 250 high bits (t >> 5) and 5 low bits (t & 0xf1). | ||
querolita marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* The gadget proves that `tHi` is in [0, 2^250) but assumes that `tLo` consists of bits. | ||
*/ | ||
function scaleShiftedSplit5( | ||
{ x, y }: { x: Field; y: Field }, | ||
tHi: Field, | ||
tLo: TupleN<Bool, 5> | ||
): Group { | ||
// constant case | ||
if (isConstant(x, y, tHi, ...tLo)) { | ||
let sP = PallasAffine.scale( | ||
PallasAffine.fromNonzero({ x: x.toBigInt(), y: y.toBigInt() }), | ||
Fq.add(packBits(tLo).toBigInt() + (tHi.toBigInt() << 5n), 1n << 254n) | ||
); | ||
return new Group({ x: createField(sP.x), y: createField(sP.y) }); | ||
} | ||
|
||
// R = (2*(t >> 5) + 1 + 2^250)P | ||
let [, RMl] = Snarky.group.scaleFastUnpack( | ||
[0, x.value, y.value], | ||
[0, tHi.value], | ||
250 | ||
); | ||
let P = new Group({ x, y }); | ||
let R = new Group({ x: RMl[0], y: RMl[1] }); | ||
let [t0, t1, t2, t3, t4] = tLo; | ||
|
||
// TODO: use faster group ops which don't allow zero inputs | ||
|
||
// R = t4 ? R : R - P = ((t >> 4) + 2^250)P | ||
R = Provable.if(t4, R, R.sub(P)); | ||
|
||
// R = ((t >> 3) + 2^251)P | ||
R = R.add(R); | ||
R = Provable.if(t3, R.add(P), R); | ||
|
||
// R = ((t >> 2) + 2^252)P | ||
R = R.add(R); | ||
R = Provable.if(t2, R.add(P), R); | ||
|
||
// R = ((t >> 1) + 2^253)P | ||
R = R.add(R); | ||
R = Provable.if(t1, R.add(P), R); | ||
|
||
// R = (t + 2^254)P | ||
R = R.add(R); | ||
R = Provable.if(t0, R.add(P), R); | ||
|
||
return R; | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tHi0 you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid you're reviewing outdated code :O
yeah I meant tHi0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, yesterday I was commit-reviewing to gain more context. Today I will focus on the updated
native-curve.ts
file