UltrafastSecp256k1 3.50.0
Ultra high-performance secp256k1 elliptic curve cryptography library
Loading...
Searching...
No Matches
ecmult_gen_comb.hpp
Go to the documentation of this file.
1#ifndef SECP256K1_ECMULT_GEN_COMB_HPP
2#define SECP256K1_ECMULT_GEN_COMB_HPP
3#pragma once
4
5// ============================================================================
6// ecmult_gen: Lim-Lee Comb Method for Generator Multiplication
7// ============================================================================
8//
9// Computes k*G using the comb method (Lim & Lee, 1994).
10// This is the algorithm used by bitcoin-core/secp256k1's ecmult_gen.
11//
12// Key advantage over windowed methods:
13// - Table is precomputed ONCE for G (at init time or from cache)
14// - No runtime GLV decomposition (saves ~14us overhead per mul)
15// - Table fits in L1/L2 cache for reasonable tooth counts
16// - Exactly 256/teeth doublings + 256/teeth additions (fixed cost)
17//
18// Algorithm:
19// Given teeth t and spacing d = ceil(256/t):
20// 1. Pre-compute table[i][j] = (2^(j*d)) * G for i=0..d-1, j=0..t-1
21// Actually stored per-comb: table[comb][entry] where entry is t-bit index
22// 2. For each bit position b from d-1 down to 0:
23// a. R = 2*R (double)
24// b. For each comb c, look up bits at positions b, b+d, b+2d, ...
25// forming a t-bit index -> add table[c][index] to R
26//
27// Table size: d * 2^t affine points
28// teeth=15, d=17: 17 * 2^15 = 557K points ~= 35 MB
29// teeth=11, d=24: 24 * 2^11 = 49K points ~= 3 MB (L2-friendly)
30// teeth= 6, d=43: 43 * 2^6 = 2752 points ~= 176 KB (L1-friendly)
31//
32// Cost: d doublings + d*combs additions = d*(1 + combs) point ops
33// teeth=15: 17 dbl + 17 add = 34 ops (fastest, but big table)
34// teeth=11: 24 dbl + 24 add = 48 ops (good balance)
35// teeth= 6: 43 dbl + 43 add = 86 ops (tiny table, cache-optimal)
36//
37// USAGE:
38// secp256k1::fast::CombGenContext ctx;
39// ctx.init(); // or ctx.init(teeth)
40//
41// Point R = ctx.mul(scalar); // fast generator multiplication
42// ============================================================================
43
44#include <cstddef>
45#include <cstdint>
46#include <vector>
47#include <string>
48#include "secp256k1/scalar.hpp"
49#include "secp256k1/point.hpp"
50#include "secp256k1/field.hpp"
51
52namespace secp256k1::fast {
53
54// -- Stored affine point (compact, cache-friendly) ----------------------------
60
61// -- Comb Generator Context ---------------------------------------------------
63public:
64 CombGenContext() = default;
65 ~CombGenContext() = default;
66
67 // Non-copyable (large table)
72
73 // Initialize with given number of teeth (comb width).
74 // teeth=15 -> libsecp256k1 default (fastest, 35MB table)
75 // teeth=11 -> good balance (3MB, fits L2)
76 // teeth=6 -> compact (176KB, fits L1)
77 void init(unsigned teeth = 15);
78
79 // Is context initialized?
80 bool ready() const noexcept { return teeth_ > 0; }
81
82 // Generator multiplication: R = k*G
83 // Fixed-cost: spacing_ doublings + spacing_ additions.
84 Point mul(const Scalar& k) const;
85
86 // Constant-time generator multiplication (scans all table entries)
87 Point mul_ct(const Scalar& k) const;
88
89 // Table info
90 unsigned teeth() const noexcept { return teeth_; }
91 unsigned spacing() const noexcept { return spacing_; }
92 std::size_t table_size_bytes() const noexcept;
93
94 // Cache: save/load precomputed table
95 bool save_cache(const std::string& path) const;
96 bool load_cache(const std::string& path);
97
98private:
99 unsigned teeth_ = 0; // Number of "teeth" (comb width in bits)
100 unsigned spacing_ = 0; // = ceil(256 / teeth_)
101 unsigned num_combs_ = 1; // Number of comb tables (always 1 for standard)
102
103 // Table layout: table_[comb_idx * (1 << teeth_) + entry]
104 // where entry is a teeth_-bit index formed by gathering bits at
105 // positions b, b+spacing, b+2*spacing, ..., b+(teeth-1)*spacing
106 std::vector<CombAffinePoint> table_;
107
108 // Build the comb table from generator G
109 void build_table();
110
111 // Extract teeth-bit comb index for bit position b
112 uint32_t extract_comb_index(const Scalar& k, unsigned b) const;
113};
114
115// -- Global comb context (singleton, like libsecp256k1's secp256k1_ecmult_gen_context) --
116void init_comb_gen(unsigned teeth = 15);
120
121} // namespace secp256k1::fast
122
123#endif // SECP256K1_ECMULT_GEN_COMB_HPP
void init(unsigned teeth=15)
CombGenContext(CombGenContext &&)=default
unsigned teeth() const noexcept
bool load_cache(const std::string &path)
CombGenContext(const CombGenContext &)=delete
std::size_t table_size_bytes() const noexcept
unsigned spacing() const noexcept
CombGenContext & operator=(CombGenContext &&)=default
Point mul(const Scalar &k) const
CombGenContext & operator=(const CombGenContext &)=delete
bool save_cache(const std::string &path) const
Point mul_ct(const Scalar &k) const
void init_comb_gen(unsigned teeth=15)
Point comb_gen_mul(const Scalar &k)
Point comb_gen_mul_ct(const Scalar &k)
bool comb_gen_ready()