UltrafastSecp256k1 3.50.0
Ultra high-performance secp256k1 elliptic curve cryptography library
Loading...
Searching...
No Matches
batch_add_affine.hpp
Go to the documentation of this file.
1#ifndef SECP256K1_BATCH_ADD_AFFINE_HPP
2#define SECP256K1_BATCH_ADD_AFFINE_HPP
3
4#include "field.hpp"
5#include <cstddef>
6#include <vector>
7
8namespace secp256k1::fast {
9
10// ============================================================================
11// AFFINE BATCH ADDITION -- Fastest CPU pipeline for sequential ECC search
12// ============================================================================
13//
14// ## THE IDEA
15// Given a base point P = (x_base, y_base) in AFFINE coordinates and N
16// precomputed offsets T[0..N-1] = (x_i, y_i) also in AFFINE, compute
17// all N sums: result[i] = P + T[i], returning AFFINE X-coordinates.
18//
19// ## WHY THIS IS FAST
20// Standard Jacobian mixed-add: P += G costs 7M + 4S = ~354 ns/point
21// with subsequent batch Z-inverse adding ~62 ns -> total ~463 ns/point.
22//
23// Affine batch add uses Montgomery batch inversion on dx values:
24// dx[i] = x_T[i] - x_base -> 1 sub
25// batch_inverse(dx, N) -> 3(N-1) mul + 1 inv ~= 69 ns/pt
26// lambda[i] = (y_T[i] - y_base) * dx_inv[i] -> 1 mul
27// x3[i] = lambda[i]^2 - x_base - x_T[i] -> 1 sqr + 2 sub
28// y3[i] = lambda[i] * (x_base - x3[i]) - y_base -> 2 mul + 1 sub
29//
30// Cost: ~6M + 1S per point ~= 150 ns/point -> 3x faster than Jacobian!
31//
32// ## USE CASE
33// Satoshi puzzle / vanity search: walk through key range sequentially.
34// Pre-compute T[i] = i*G in affine, then for each batch:
35// 1. P_base = start_scalar * G (compute once per batch)
36// 2. result[i] = P_base + T[i] (affine batch add -- this function!)
37// 3. Check result X-coordinates against target(s)
38// 4. P_base += B*G (advance by batch size)
39//
40// ============================================================================
41
48
49// ============================================================================
50// Core batch addition API
51// ============================================================================
52
68 const FieldElement& base_x,
69 const FieldElement& base_y,
70 const AffinePointCompact* offsets,
71 FieldElement* out_x,
72 std::size_t count,
73 std::vector<FieldElement>& scratch);
74
79 const FieldElement& base_x,
80 const FieldElement& base_y,
81 const AffinePointCompact* offsets,
82 FieldElement* out_x,
83 FieldElement* out_y,
84 std::size_t count,
85 std::vector<FieldElement>& scratch);
86
90 const FieldElement& base_x,
91 const FieldElement& base_y,
92 const AffinePointCompact* offsets,
93 FieldElement* out_x,
94 std::size_t count);
95
96// ============================================================================
97// Precomputed Generator Table
98// ============================================================================
99
109std::vector<AffinePointCompact> precompute_g_multiples(std::size_t count);
110
113std::vector<AffinePointCompact> precompute_point_multiples(
114 const FieldElement& qx, const FieldElement& qy, std::size_t count);
115
116// ============================================================================
117// Full search pipeline helpers
118// ============================================================================
119
129 const FieldElement& base_x,
130 const FieldElement& base_y,
131 const AffinePointCompact* offsets_fwd,
132 const AffinePointCompact* offsets_bwd,
133 FieldElement* out_x_fwd,
134 FieldElement* out_x_bwd,
135 std::size_t count,
136 std::vector<FieldElement>& scratch);
137
140std::vector<AffinePointCompact> negate_affine_table(
141 const AffinePointCompact* table, std::size_t count);
142
143// ============================================================================
144// Y-parity extraction (for compressed pubkey byte without full Y)
145// ============================================================================
146
153 const FieldElement& base_x,
154 const FieldElement& base_y,
155 const AffinePointCompact* offsets,
156 FieldElement* out_x,
157 uint8_t* out_parity,
158 std::size_t count,
159 std::vector<FieldElement>& scratch);
160
161} // namespace secp256k1::fast
162
163#endif // SECP256K1_BATCH_ADD_AFFINE_HPP
std::vector< AffinePointCompact > precompute_point_multiples(const FieldElement &qx, const FieldElement &qy, std::size_t count)
void batch_add_affine_x(const FieldElement &base_x, const FieldElement &base_y, const AffinePointCompact *offsets, FieldElement *out_x, std::size_t count, std::vector< FieldElement > &scratch)
void batch_add_affine_x_with_parity(const FieldElement &base_x, const FieldElement &base_y, const AffinePointCompact *offsets, FieldElement *out_x, uint8_t *out_parity, std::size_t count, std::vector< FieldElement > &scratch)
void batch_add_affine_xy(const FieldElement &base_x, const FieldElement &base_y, const AffinePointCompact *offsets, FieldElement *out_x, FieldElement *out_y, std::size_t count, std::vector< FieldElement > &scratch)
std::vector< AffinePointCompact > precompute_g_multiples(std::size_t count)
std::vector< AffinePointCompact > negate_affine_table(const AffinePointCompact *table, std::size_t count)
void batch_add_affine_x_bidirectional(const FieldElement &base_x, const FieldElement &base_y, const AffinePointCompact *offsets_fwd, const AffinePointCompact *offsets_bwd, FieldElement *out_x_fwd, FieldElement *out_x_bwd, std::size_t count, std::vector< FieldElement > &scratch)