@@ -14,40 +14,96 @@ func init() {
1414}
1515
1616func GetHints () []solver.Hint {
17- return []solver.Hint {decomposeScalarG1 }
17+ return []solver.Hint {decomposeScalarG1 , decomposeScalarG1Signs , decomposeScalarG1Subscalars }
18+ }
19+
20+ func decomposeScalarG1Subscalars (mod * big.Int , inputs []* big.Int , outputs []* big.Int ) error {
21+ return emulated .UnwrapHint (inputs , outputs , func (field * big.Int , inputs , outputs []* big.Int ) error {
22+ if len (inputs ) != 2 {
23+ return fmt .Errorf ("expecting two inputs" )
24+ }
25+ if len (outputs ) != 2 {
26+ return fmt .Errorf ("expecting two outputs" )
27+ }
28+ glvBasis := new (ecc.Lattice )
29+ ecc .PrecomputeLattice (field , inputs [1 ], glvBasis )
30+ sp := ecc .SplitScalar (inputs [0 ], glvBasis )
31+ outputs [0 ].Set (& (sp [0 ]))
32+ outputs [1 ].Set (& (sp [1 ]))
33+ // we need the absolute values for the in-circuit computations,
34+ // otherwise the negative values will be reduced modulo the SNARK scalar
35+ // field and not the emulated field.
36+ // output0 = |s0| mod r
37+ // output1 = |s1| mod r
38+ if outputs [0 ].Sign () == - 1 {
39+ outputs [0 ].Neg (outputs [0 ])
40+ }
41+ if outputs [1 ].Sign () == - 1 {
42+ outputs [1 ].Neg (outputs [1 ])
43+ }
44+
45+ return nil
46+ })
47+ }
48+
49+ func decomposeScalarG1Signs (mod * big.Int , inputs []* big.Int , outputs []* big.Int ) error {
50+ return emulated .UnwrapHintWithNativeOutput (inputs , outputs , func (field * big.Int , inputs , outputs []* big.Int ) error {
51+ if len (inputs ) != 2 {
52+ return fmt .Errorf ("expecting two inputs" )
53+ }
54+ if len (outputs ) != 2 {
55+ return fmt .Errorf ("expecting two outputs" )
56+ }
57+ glvBasis := new (ecc.Lattice )
58+ ecc .PrecomputeLattice (field , inputs [1 ], glvBasis )
59+ sp := ecc .SplitScalar (inputs [0 ], glvBasis )
60+ outputs [0 ].SetUint64 (0 )
61+ if sp [0 ].Sign () == - 1 {
62+ outputs [0 ].SetUint64 (1 )
63+ }
64+ outputs [1 ].SetUint64 (0 )
65+ if sp [1 ].Sign () == - 1 {
66+ outputs [1 ].SetUint64 (1 )
67+ }
68+
69+ return nil
70+ })
1871}
1972
2073func decomposeScalarG1 (mod * big.Int , inputs []* big.Int , outputs []* big.Int ) error {
2174 return emulated .UnwrapHint (inputs , outputs , func (field * big.Int , inputs , outputs []* big.Int ) error {
2275 if len (inputs ) != 3 {
23- return fmt .Errorf ("expecting three inputs" )
76+ return fmt .Errorf ("expecting two inputs" )
2477 }
25- if len (outputs ) != 5 {
26- return fmt .Errorf ("expecting five outputs" )
78+ if len (outputs ) != 6 {
79+ return fmt .Errorf ("expecting two outputs" )
2780 }
2881 glvBasis := new (ecc.Lattice )
2982 ecc .PrecomputeLattice (inputs [2 ], inputs [1 ], glvBasis )
3083 sp := ecc .SplitScalar (inputs [0 ], glvBasis )
3184 outputs [0 ].Set (& (sp [0 ]))
3285 outputs [1 ].Set (& (sp [1 ]))
33- // figure out how many times we have overflowed
34- outputs [1 ].Set (& (sp [1 ]))
35- outputs [2 ].Mul (outputs [1 ], inputs [1 ]).Add (outputs [2 ], outputs [0 ])
36- outputs [2 ].Sub (outputs [2 ], inputs [0 ])
37- outputs [2 ].Div (outputs [2 ], inputs [2 ])
38-
39- // return:
40- // output0 = s0 mod r
41- // output1 = s1 mod r
42- // output3 = |s0| mod r
43- // output4 = |s1| mod r
44- outputs [3 ].Set (outputs [0 ])
86+ // we need the negative values for to check that s0+λ*s1 == s mod r
87+ // output4 = s0 mod r
88+ // output5 = s1 mod r
89+ outputs [4 ].Set (outputs [0 ])
90+ outputs [5 ].Set (outputs [1 ])
91+ // we need the absolute values for the in-circuit computations,
92+ // otherwise the negative values will be reduced modulo the SNARK scalar
93+ // field and not the emulated field.
94+ // output0 = |s0| mod r
95+ // output1 = |s1| mod r
96+ // output2 = 1 if s0 is positive, 0 if s0 is negative
97+ // output3 = 1 if s1 is positive, 0 if s0 is negative
98+ outputs [2 ].SetUint64 (1 )
4599 if outputs [0 ].Sign () == - 1 {
46- outputs [3 ].Neg (outputs [0 ])
100+ outputs [0 ].Neg (outputs [0 ])
101+ outputs [2 ].SetUint64 (0 )
47102 }
48- outputs [4 ]. Set ( outputs [ 1 ] )
103+ outputs [3 ]. SetUint64 ( 1 )
49104 if outputs [1 ].Sign () == - 1 {
50- outputs [4 ].Neg (outputs [1 ])
105+ outputs [1 ].Neg (outputs [1 ])
106+ outputs [3 ].SetUint64 (0 )
51107 }
52108
53109 return nil
0 commit comments