GLV optimization
This commit is contained in:
parent
7ba40aa4cd
commit
949bea9262
93
ecmult.h
93
ecmult.h
|
@ -5,10 +5,10 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "group.h"
|
||||
#include "scalar.h"
|
||||
#include "num.h"
|
||||
|
||||
#define WINDOW_A 5
|
||||
#define WINDOW_G 11
|
||||
#define WINDOW_G 15
|
||||
|
||||
namespace secp256k1 {
|
||||
|
||||
|
@ -17,19 +17,22 @@ private:
|
|||
G pre[1 << (W-2)];
|
||||
|
||||
public:
|
||||
WNAFPrecomp(const G &base) {
|
||||
WNAFPrecomp() {}
|
||||
|
||||
void Build(const G &base) {
|
||||
pre[0] = base;
|
||||
GroupElemJac x(base);
|
||||
// printf("base=%s x=%s\n", base.ToString().c_str(), x.ToString().c_str());
|
||||
GroupElemJac d; d.SetDouble(x);
|
||||
// printf("d=%s\n", d.ToString().c_str());
|
||||
for (int i=1; i<(1 << (W-2)); i++) {
|
||||
x.SetAdd(d,pre[i-1]);
|
||||
pre[i].SetJac(x);
|
||||
// printf("precomp %s*%i = %s\n", base.ToString().c_str(), i*2 +1, pre[i].ToString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
WNAFPrecomp(const G &base) {
|
||||
Build(base);
|
||||
}
|
||||
|
||||
void Get(G &out, int exp) const {
|
||||
assert((exp & 1) == 1);
|
||||
assert(exp >= -((1 << (W-1)) - 1));
|
||||
|
@ -55,11 +58,16 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
WNAF(Context &ctx, const Scalar &exp, int w) : used(0) {
|
||||
WNAF(Context &ctx, const Number &exp, int w) : used(0) {
|
||||
int zeroes = 0;
|
||||
Context ct(ctx);
|
||||
Scalar x(ct);
|
||||
Number x(ct);
|
||||
x.SetNumber(exp);
|
||||
int sign = 1;
|
||||
if (x.IsNeg()) {
|
||||
sign = -1;
|
||||
x.Negate();
|
||||
}
|
||||
while (!x.IsZero()) {
|
||||
while (!x.IsOdd()) {
|
||||
zeroes++;
|
||||
|
@ -68,9 +76,9 @@ public:
|
|||
int word = x.ShiftLowBits(ctx,w);
|
||||
if (word & (1 << (w-1))) {
|
||||
x.Inc();
|
||||
PushNAF(word - (1 << w), zeroes);
|
||||
PushNAF(sign * (word - (1 << w)), zeroes);
|
||||
} else {
|
||||
PushNAF(word, zeroes);
|
||||
PushNAF(sign * word, zeroes);
|
||||
}
|
||||
zeroes = w-1;
|
||||
}
|
||||
|
@ -100,9 +108,20 @@ public:
|
|||
|
||||
class ECMultConsts {
|
||||
public:
|
||||
const WNAFPrecomp<GroupElem,WINDOW_G> wpg;
|
||||
WNAFPrecomp<GroupElem,WINDOW_G> wpg;
|
||||
WNAFPrecomp<GroupElem,WINDOW_G> wpg128;
|
||||
|
||||
ECMultConsts() : wpg(GetGroupConst().g) {}
|
||||
ECMultConsts() {
|
||||
printf("Precomputing G multiplies...\n");
|
||||
const GroupElem &g = GetGroupConst().g;
|
||||
GroupElemJac g128j(g);
|
||||
for (int i=0; i<128; i++)
|
||||
g128j.SetDouble(g128j);
|
||||
GroupElem g128; g128.SetJac(g128j);
|
||||
wpg.Build(g);
|
||||
wpg128.Build(g128);
|
||||
printf("Done precomputing\n");
|
||||
}
|
||||
};
|
||||
|
||||
const ECMultConsts &GetECMultConsts() {
|
||||
|
@ -110,15 +129,33 @@ const ECMultConsts &GetECMultConsts() {
|
|||
return ecmult_consts;
|
||||
}
|
||||
|
||||
void ECMult(Context &ctx, GroupElemJac &out, const GroupElemJac &a, Scalar &an, Scalar &gn) {
|
||||
WNAF<256> wa(ctx, an, WINDOW_A);
|
||||
WNAF<256> wg(ctx, gn, WINDOW_G);
|
||||
WNAFPrecomp<GroupElemJac,WINDOW_A> wpa(a);
|
||||
const WNAFPrecomp<GroupElem,WINDOW_G> &wpg = GetECMultConsts().wpg;
|
||||
void ECMult(Context &ctx, GroupElemJac &out, const GroupElemJac &a, Number &an, Number &gn) {
|
||||
Context ct(ctx);
|
||||
Number an1(ct), an2(ct);
|
||||
Number gn1(ct), gn2(ct);
|
||||
|
||||
int size_a = wa.GetSize();
|
||||
int size_g = wg.GetSize();
|
||||
int size = std::max(size_a, size_g);
|
||||
SplitExp(ct, an, an1, an2);
|
||||
// printf("an=%s\n", an.ToString().c_str());
|
||||
// printf("an1=%s\n", an1.ToString().c_str());
|
||||
// printf("an2=%s\n", an2.ToString().c_str());
|
||||
// printf("an1.len=%i\n", an1.GetBits());
|
||||
// printf("an2.len=%i\n", an2.GetBits());
|
||||
gn.SplitInto(ct, 128, gn1, gn2);
|
||||
|
||||
WNAF<129> wa1(ct, an1, WINDOW_A);
|
||||
WNAF<129> wa2(ct, an2, WINDOW_A);
|
||||
WNAF<128> wg1(ct, gn1, WINDOW_G);
|
||||
WNAF<128> wg2(ct, gn2, WINDOW_G);
|
||||
GroupElemJac a2; a2.SetMulLambda(a);
|
||||
WNAFPrecomp<GroupElemJac,WINDOW_A> wpa1(a);
|
||||
WNAFPrecomp<GroupElemJac,WINDOW_A> wpa2(a2);
|
||||
const ECMultConsts &c = GetECMultConsts();
|
||||
|
||||
int size_a1 = wa1.GetSize();
|
||||
int size_a2 = wa2.GetSize();
|
||||
int size_g1 = wg1.GetSize();
|
||||
int size_g2 = wg2.GetSize();
|
||||
int size = std::max(std::max(size_a1, size_a2), std::max(size_g1, size_g2));
|
||||
|
||||
out = GroupElemJac();
|
||||
GroupElemJac tmpj;
|
||||
|
@ -127,12 +164,20 @@ void ECMult(Context &ctx, GroupElemJac &out, const GroupElemJac &a, Scalar &an,
|
|||
for (int i=size-1; i>=0; i--) {
|
||||
out.SetDouble(out);
|
||||
int nw;
|
||||
if (i < size_a && (nw = wa.Get(i))) {
|
||||
wpa.Get(tmpj, nw);
|
||||
if (i < size_a1 && (nw = wa1.Get(i))) {
|
||||
wpa1.Get(tmpj, nw);
|
||||
out.SetAdd(out, tmpj);
|
||||
}
|
||||
if (i < size_g && (nw = wg.Get(i))) {
|
||||
wpg.Get(tmpa, nw);
|
||||
if (i < size_a2 && (nw = wa2.Get(i))) {
|
||||
wpa2.Get(tmpj, nw);
|
||||
out.SetAdd(out, tmpj);
|
||||
}
|
||||
if (i < size_g1 && (nw = wg1.Get(i))) {
|
||||
c.wpg.Get(tmpa, nw);
|
||||
out.SetAdd(out, tmpa);
|
||||
}
|
||||
if (i < size_g2 && (nw = wg2.Get(i))) {
|
||||
c.wpg128.Get(tmpa, nw);
|
||||
out.SetAdd(out, tmpa);
|
||||
}
|
||||
}
|
||||
|
|
58
group.h
58
group.h
|
@ -239,6 +239,8 @@ public:
|
|||
cop.GetAffine(aff);
|
||||
return aff.ToString();
|
||||
}
|
||||
|
||||
void SetMulLambda(const GroupElemJac &p);
|
||||
};
|
||||
|
||||
void GroupElem::SetJac(GroupElemJac &jac) {
|
||||
|
@ -260,6 +262,22 @@ static const unsigned char g_y_[] = {0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,
|
|||
0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,
|
||||
0x9C,0x47,0xD0,0x8F,0xFB,0x10,0xD4,0xB8};
|
||||
|
||||
// properties of secp256k1's efficiently computable endomorphism
|
||||
static const unsigned char lambda_[] = {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,
|
||||
0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a,
|
||||
0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,
|
||||
0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72};
|
||||
static const unsigned char beta_[] = {0x7a,0xe9,0x6a,0x2b,0x65,0x7c,0x07,0x10,
|
||||
0x6e,0x64,0x47,0x9e,0xac,0x34,0x34,0xe9,
|
||||
0x9c,0xf0,0x49,0x75,0x12,0xf5,0x89,0x95,
|
||||
0xc1,0x39,0x6c,0x28,0x71,0x95,0x01,0xee};
|
||||
static const unsigned char a1b2_[] = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,
|
||||
0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15};
|
||||
static const unsigned char b1_[] = {0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,
|
||||
0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3};
|
||||
static const unsigned char a2_[] = {0x01,
|
||||
0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,
|
||||
0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8};
|
||||
class GroupConstants {
|
||||
private:
|
||||
Context ctx;
|
||||
|
@ -269,10 +287,16 @@ private:
|
|||
public:
|
||||
const Number order;
|
||||
const GroupElem g;
|
||||
const FieldElem beta;
|
||||
const Number lambda, a1b2, b1, a2;
|
||||
|
||||
GroupConstants() : order(ctx, order_, sizeof(order_)),
|
||||
g_x(g_x_), g_y(g_y_),
|
||||
g(g_x,g_y) {}
|
||||
g_x(g_x_), g_y(g_y_), g(g_x,g_y),
|
||||
beta(beta_),
|
||||
lambda(ctx, lambda_, sizeof(lambda_)),
|
||||
a1b2(ctx, a1b2_, sizeof(a1b2_)),
|
||||
b1(ctx, b1_, sizeof(b1_)),
|
||||
a2(ctx, a2_, sizeof(a2_)) {}
|
||||
};
|
||||
|
||||
const GroupConstants &GetGroupConst() {
|
||||
|
@ -280,6 +304,36 @@ const GroupConstants &GetGroupConst() {
|
|||
return group_const;
|
||||
}
|
||||
|
||||
void GroupElemJac::SetMulLambda(const GroupElemJac &p) {
|
||||
FieldElem beta = GetGroupConst().beta;
|
||||
*this = p;
|
||||
x.SetMult(x, beta);
|
||||
}
|
||||
|
||||
void SplitExp(Context &ctx, const Number &exp, Number &exp1, Number exp2) {
|
||||
const GroupConstants &c = GetGroupConst();
|
||||
Context ct(ctx);
|
||||
Number bnc1(ct), bnc2(ct), bnt1(ct), bnt2(ct), bnn2(ct);
|
||||
bnn2.SetNumber(c.order);
|
||||
bnn2.Shift1();
|
||||
|
||||
bnc1.SetMult(ct, exp, c.a1b2);
|
||||
bnc1.SetAdd(ct, bnc1, bnn2);
|
||||
bnc1.SetDiv(ct, bnc1, c.order);
|
||||
|
||||
bnc2.SetMult(ct, exp, c.b1);
|
||||
bnc2.SetAdd(ct, bnc2, bnn2);
|
||||
bnc2.SetDiv(ct, bnc2, c.order);
|
||||
|
||||
bnt1.SetMult(ct, bnc1, c.a1b2);
|
||||
bnt2.SetMult(ct, bnc2, c.a2);
|
||||
bnt1.SetAdd(ct, bnt1, bnt2);
|
||||
exp1.SetSub(ct, exp, bnt1);
|
||||
bnt1.SetMult(ct, bnc1, c.b1);
|
||||
bnt2.SetMult(ct, bnc2, c.a1b2);
|
||||
exp2.SetSub(ct, bnt1, bnt2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
27
num.h
27
num.h
|
@ -74,6 +74,18 @@ public:
|
|||
void SetModMul(Context &ctx, const Number &f, const Number &m) {
|
||||
BN_mod_mul(bn, bn, f.bn, m.bn, ctx);
|
||||
}
|
||||
void SetAdd(Context &ctx, const Number &a1, const Number &a2) {
|
||||
BN_add(bn, a1.bn, a2.bn);
|
||||
}
|
||||
void SetSub(Context &ctx, const Number &a1, const Number &a2) {
|
||||
BN_sub(bn, a1.bn, a2.bn);
|
||||
}
|
||||
void SetMult(Context &ctx, const Number &a1, const Number &a2) {
|
||||
BN_mul(bn, a1.bn, a2.bn, ctx);
|
||||
}
|
||||
void SetDiv(Context &ctx, const Number &a1, const Number &a2) {
|
||||
BN_div(bn, NULL, a1.bn, a2.bn, ctx);
|
||||
}
|
||||
int GetBits() const {
|
||||
return BN_num_bits(bn);
|
||||
}
|
||||
|
@ -91,10 +103,15 @@ public:
|
|||
bool IsZero() {
|
||||
return BN_is_zero(bn);
|
||||
}
|
||||
// right-shift as many zeroes as possible
|
||||
int IsOdd() {
|
||||
bool IsOdd() {
|
||||
return BN_is_odd(bn);
|
||||
}
|
||||
bool IsNeg() {
|
||||
return BN_is_negative(bn);
|
||||
}
|
||||
void Negate() {
|
||||
BN_set_negative(bn, !IsNeg());
|
||||
}
|
||||
void Shift1() {
|
||||
BN_rshift1(bn,bn);
|
||||
}
|
||||
|
@ -104,6 +121,12 @@ public:
|
|||
void SetHex(const std::string &str) {
|
||||
BN_hex2bn(&bn, str.c_str());
|
||||
}
|
||||
void SplitInto(Context &ctx, int bits, Number &low, Number &high) const {
|
||||
BN_copy(low.bn, bn);
|
||||
BN_mask_bits(low.bn, bits);
|
||||
BN_rshift(high.bn, bn, bits);
|
||||
}
|
||||
|
||||
std::string ToString() {
|
||||
char *str = BN_bn2hex(bn);
|
||||
std::string ret(str);
|
||||
|
|
23
scalar.h
23
scalar.h
|
@ -1,23 +0,0 @@
|
|||
#ifndef _SECP256K1_SCALAR_
|
||||
#define _SECP256K1_SCALAR_
|
||||
|
||||
#include "num.h"
|
||||
#include "group.h"
|
||||
|
||||
namespace secp256k1 {
|
||||
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141,
|
||||
* using OpenSSL's BIGNUM
|
||||
*/
|
||||
class Scalar : public Number {
|
||||
public:
|
||||
Scalar(Context &ctx) : Number(ctx) {}
|
||||
|
||||
void Multiply(Context &ctx, const Scalar &f) {
|
||||
const GroupConstants &c = GetGroupConst();
|
||||
SetModMul(ctx, f, c.order);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -3,7 +3,6 @@
|
|||
#include "num.h"
|
||||
#include "field.h"
|
||||
#include "group.h"
|
||||
#include "scalar.h"
|
||||
#include "ecmult.h"
|
||||
|
||||
using namespace secp256k1;
|
||||
|
@ -11,25 +10,30 @@ using namespace secp256k1;
|
|||
int main() {
|
||||
Context ctx;
|
||||
FieldElem x,y;
|
||||
const Number &order = GetGroupConst().order;
|
||||
x.SetHex("8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004");
|
||||
y.SetHex("a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f");
|
||||
GroupElemJac a(x,y);
|
||||
printf("a=%s\n", a.ToString().c_str());
|
||||
Scalar an(ctx);
|
||||
Number an(ctx);
|
||||
an.SetHex("8b30bce9ad2a890696b23f671709eff3727fd8cc04d3362c6c7bf458f2846fff");
|
||||
Scalar af(ctx);
|
||||
Number af(ctx);
|
||||
af.SetHex("1337");
|
||||
printf("an=%s\n", an.ToString().c_str());
|
||||
Scalar gn(ctx);
|
||||
Number gn(ctx);
|
||||
gn.SetHex("f557be925d4b65381409fdf30514750f1eb4343a91216a4f71163cb35f2f6e0e");
|
||||
Scalar gf(ctx);
|
||||
gf.SetHex("2113");
|
||||
Number gf(ctx);
|
||||
gf.SetHex("7113");
|
||||
printf("gn=%s\n", gn.ToString().c_str());
|
||||
for (int i=0; i<50000; i++) {
|
||||
for (int i=0; i<1000000; i++) {
|
||||
ECMult(ctx, a, a, an, gn);
|
||||
an.Multiply(ctx, af);
|
||||
gn.Multiply(ctx, gf);
|
||||
// an.SetModMul(ctx, af, order);
|
||||
// gn.SetModMul(ctx, gf, order);
|
||||
an.Inc();
|
||||
gn.Inc();
|
||||
}
|
||||
printf("%s\n", an.ToString().c_str());
|
||||
printf("%s\n", gn.ToString().c_str());
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue