1 #ifndef _SECP256K1_ECMULT_
2 #define _SECP256K1_ECMULT_
10 // optimal for 128-bit and 256-bit exponents
13 // larger numbers may result in slightly better performance, at the cost of
14 // exponentially larger precomputed tables. WINDOW_G == 13 results in 640 KiB.
19 template<typename G, int W> class WNAFPrecomp {
26 void Build(Context &ctx, const G &base) {
29 GroupElemJac d; d.SetDouble(x);
30 for (int i=1; i<(1 << (W-2)); i++) {
32 pre[i].SetJac(ctx, x);
36 WNAFPrecomp(Context &ctx, const G &base) {
40 void Get(G &out, int exp) const {
41 assert((exp & 1) == 1);
42 assert(exp >= -((1 << (W-1)) - 1));
43 assert(exp <= ((1 << (W-1)) - 1));
47 out.SetNeg(pre[(-exp-1)/2]);
52 template<int B> class WNAF {
57 void PushNAF(int num, int zeroes) {
59 for (int i=0; i<zeroes; i++) {
66 WNAF(Context &ctx, const Number &exp, int w) : used(0) {
81 int word = x.ShiftLowBits(ct,w);
82 if (word & (1 << (w-1))) {
84 PushNAF(sign * (word - (1 << w)), zeroes);
86 PushNAF(sign * word, zeroes);
96 int Get(int pos) const {
97 assert(pos >= 0 && pos < used);
101 std::string ToString() {
102 std::stringstream ss;
104 for (int i=0; i<GetSize(); i++) {
116 WNAFPrecomp<GroupElem,WINDOW_G> wpg;
117 WNAFPrecomp<GroupElem,WINDOW_G> wpg128;
121 const GroupElem &g = GetGroupConst().g;
122 GroupElemJac g128j(g);
123 for (int i=0; i<128; i++)
124 g128j.SetDouble(g128j);
125 GroupElem g128; g128.SetJac(ctx, g128j);
127 wpg128.Build(ctx, g128);
131 const ECMultConsts &GetECMultConsts() {
132 static const ECMultConsts ecmult_consts;
133 return ecmult_consts;
136 void ECMult(Context &ctx, GroupElemJac &out, const GroupElemJac &a, const Number &an, const Number &gn) {
138 Number an1(ct), an2(ct);
139 Number gn1(ct), gn2(ct);
141 SplitExp(ct, an, an1, an2);
142 // printf("an=%s\n", an.ToString().c_str());
143 // printf("an1=%s\n", an1.ToString().c_str());
144 // printf("an2=%s\n", an2.ToString().c_str());
145 // printf("an1.len=%i\n", an1.GetBits());
146 // printf("an2.len=%i\n", an2.GetBits());
147 gn.SplitInto(ct, 128, gn1, gn2);
149 WNAF<128> wa1(ct, an1, WINDOW_A);
150 WNAF<128> wa2(ct, an2, WINDOW_A);
151 WNAF<128> wg1(ct, gn1, WINDOW_G);
152 WNAF<128> wg2(ct, gn2, WINDOW_G);
153 GroupElemJac a2; a2.SetMulLambda(a);
154 WNAFPrecomp<GroupElemJac,WINDOW_A> wpa1(ct, a);
155 WNAFPrecomp<GroupElemJac,WINDOW_A> wpa2(ct, a2);
156 const ECMultConsts &c = GetECMultConsts();
158 int size_a1 = wa1.GetSize();
159 int size_a2 = wa2.GetSize();
160 int size_g1 = wg1.GetSize();
161 int size_g2 = wg2.GetSize();
162 int size = std::max(std::max(size_a1, size_a2), std::max(size_g1, size_g2));
164 out = GroupElemJac();
168 for (int i=size-1; i>=0; i--) {
171 if (i < size_a1 && (nw = wa1.Get(i))) {
173 out.SetAdd(out, tmpj);
175 if (i < size_a2 && (nw = wa2.Get(i))) {
177 out.SetAdd(out, tmpj);
179 if (i < size_g1 && (nw = wg1.Get(i))) {
181 out.SetAdd(out, tmpa);
183 if (i < size_g2 && (nw = wg2.Get(i))) {
184 c.wpg128.Get(tmpa, nw);
185 out.SetAdd(out, tmpa);