bitcoin/ecmult.h

144 lines
3.3 KiB
C
Raw Normal View History

2013-03-07 22:52:50 -03:00
#ifndef _SECP256K1_ECMULT_
#define _SECP256K1_ECMULT_
2013-03-09 18:47:40 -03:00
#include <sstream>
#include <algorithm>
2013-03-07 22:52:50 -03:00
#include "group.h"
#include "scalar.h"
2013-03-09 21:49:42 -03:00
#define WINDOW_A 5
#define WINDOW_G 11
2013-03-07 22:52:50 -03:00
namespace secp256k1 {
template<typename G, int W> class WNAFPrecomp {
private:
G pre[1 << (W-2)];
public:
2013-03-09 18:47:40 -03:00
WNAFPrecomp(const G &base) {
2013-03-07 22:52:50 -03:00
pre[0] = base;
2013-03-09 21:49:42 -03:00
GroupElemJac x(base);
// printf("base=%s x=%s\n", base.ToString().c_str(), x.ToString().c_str());
2013-03-07 22:52:50 -03:00
GroupElemJac d; d.SetDouble(x);
2013-03-09 21:49:42 -03:00
// printf("d=%s\n", d.ToString().c_str());
2013-03-07 22:52:50 -03:00
for (int i=1; i<(1 << (W-2)); i++) {
x.SetAdd(d,pre[i-1]);
2013-03-09 18:47:40 -03:00
pre[i].SetJac(x);
2013-03-09 21:49:42 -03:00
// printf("precomp %s*%i = %s\n", base.ToString().c_str(), i*2 +1, pre[i].ToString().c_str());
2013-03-07 22:52:50 -03:00
}
}
2013-03-09 18:47:40 -03:00
void Get(G &out, int exp) const {
2013-03-07 22:52:50 -03:00
assert((exp & 1) == 1);
assert(exp >= -((1 << (W-1)) - 1));
assert(exp <= ((1 << (W-1)) - 1));
if (exp > 0) {
out = pre[(exp-1)/2];
} else {
2013-03-09 21:49:42 -03:00
out.SetNeg(pre[(-exp-1)/2]);
2013-03-07 22:52:50 -03:00
}
}
};
2013-03-09 18:47:40 -03:00
template<int B> class WNAF {
2013-03-07 22:52:50 -03:00
private:
2013-03-09 18:47:40 -03:00
int naf[B+1];
int used;
void PushNAF(int num, int zeroes) {
for (int i=0; i<zeroes; i++) {
naf[used++]=0;
}
naf[used++]=num;
}
public:
2013-03-09 21:49:42 -03:00
WNAF(Context &ctx, const Scalar &exp, int w) : used(0) {
2013-03-09 18:47:40 -03:00
int zeroes = 0;
2013-03-09 21:49:42 -03:00
Context ct(ctx);
Scalar x(ct);
x.SetNumber(exp);
while (!x.IsZero()) {
while (!x.IsOdd()) {
2013-03-09 18:47:40 -03:00
zeroes++;
2013-03-09 21:49:42 -03:00
x.Shift1();
2013-03-09 18:47:40 -03:00
}
2013-03-09 21:49:42 -03:00
int word = x.ShiftLowBits(ctx,w);
2013-03-09 18:47:40 -03:00
if (word & (1 << (w-1))) {
2013-03-09 21:49:42 -03:00
x.Inc();
2013-03-09 18:47:40 -03:00
PushNAF(word - (1 << w), zeroes);
} else {
PushNAF(word, zeroes);
}
zeroes = w-1;
}
}
int GetSize() const {
return used;
}
int Get(int pos) const {
2013-03-09 21:49:42 -03:00
assert(pos >= 0 && pos < used);
return naf[pos];
2013-03-09 18:47:40 -03:00
}
std::string ToString() {
std::stringstream ss;
ss << "(";
for (int i=0; i<GetSize(); i++) {
2013-03-09 21:49:42 -03:00
ss << Get(used-1-i);
2013-03-09 18:47:40 -03:00
if (i != used-1)
ss << ',';
}
ss << ")";
return ss.str();
}
};
class ECMultConsts {
public:
2013-03-09 21:49:42 -03:00
const WNAFPrecomp<GroupElem,WINDOW_G> wpg;
2013-03-07 22:52:50 -03:00
2013-03-09 18:47:40 -03:00
ECMultConsts() : wpg(GetGroupConst().g) {}
2013-03-07 22:52:50 -03:00
};
2013-03-09 18:47:40 -03:00
const ECMultConsts &GetECMultConsts() {
static const ECMultConsts ecmult_consts;
return ecmult_consts;
}
2013-03-09 21:49:42 -03:00
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;
2013-03-09 18:47:40 -03:00
2013-03-09 21:49:42 -03:00
int size_a = wa.GetSize();
int size_g = wg.GetSize();
int size = std::max(size_a, size_g);
2013-03-09 18:47:40 -03:00
out = GroupElemJac();
GroupElemJac tmpj;
GroupElem tmpa;
2013-03-09 21:49:42 -03:00
for (int i=size-1; i>=0; i--) {
2013-03-09 18:47:40 -03:00
out.SetDouble(out);
2013-03-09 21:49:42 -03:00
int nw;
if (i < size_a && (nw = wa.Get(i))) {
wpa.Get(tmpj, nw);
2013-03-09 18:47:40 -03:00
out.SetAdd(out, tmpj);
}
2013-03-09 21:49:42 -03:00
if (i < size_g && (nw = wg.Get(i))) {
wpg.Get(tmpa, nw);
2013-03-09 18:47:40 -03:00
out.SetAdd(out, tmpa);
}
}
}
2013-03-07 22:52:50 -03:00
}
#endif