Skip to content

Commit a9b6595

Browse files
committed
[API BREAK] Introduce explicit contexts
1 parent a0d3b89 commit a9b6595

File tree

14 files changed

+342
-277
lines changed

14 files changed

+342
-277
lines changed

include/secp256k1.h

Lines changed: 75 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -40,42 +40,52 @@ extern "C" {
4040
# define SECP256K1_ARG_NONNULL(_x)
4141
# endif
4242

43+
/** Opaque data structure that holds context information (precomputed tables etc.).
44+
* Only functions that take a pointer to a non-const context require exclusive
45+
* access to it. Multiple functions that take a pointer to a const context may
46+
* run simultaneously.
47+
*/
48+
typedef struct secp256k1_context_struct secp256k1_context_t;
4349

44-
/** Flags to pass to secp256k1_start. */
45-
# define SECP256K1_START_VERIFY (1 << 0)
46-
# define SECP256K1_START_SIGN (1 << 1)
50+
/** Flags to pass to secp256k1_context_create. */
51+
# define SECP256K1_CONTEXT_VERIFY (1 << 0)
52+
# define SECP256K1_CONTEXT_SIGN (1 << 1)
4753

48-
/** Initialize the library. This may take some time (10-100 ms).
49-
* You need to call this before calling any other function.
50-
* It cannot run in parallel with any other functions, but once
51-
* secp256k1_start() returns, all other functions are thread-safe.
54+
/** Create a secp256k1 context object.
55+
* Returns: a newly created context object.
56+
* In: flags: which parts of the context to initialize.
5257
*/
53-
void secp256k1_start(unsigned int flags);
58+
secp256k1_context_t* secp256k1_context_create(
59+
int flags
60+
) SECP256K1_WARN_UNUSED_RESULT;
5461

55-
/** Free all memory associated with this library. After this, no
56-
* functions can be called anymore, except secp256k1_start()
62+
/** Destroy a secp256k1 context object.
63+
* The context pointer may not be used afterwards.
5764
*/
58-
void secp256k1_stop(void);
65+
void secp256k1_context_destroy(
66+
secp256k1_context_t* ctx
67+
) SECP256K1_ARG_NONNULL(1);
5968

6069
/** Verify an ECDSA signature.
6170
* Returns: 1: correct signature
6271
* 0: incorrect signature
6372
* -1: invalid public key
6473
* -2: invalid signature
65-
* In: msg32: the 32-byte message hash being verified (cannot be NULL)
74+
* In: ctx: a secp256k1 context object, initialized for verification.
75+
* msg32: the 32-byte message hash being verified (cannot be NULL)
6676
* sig: the signature being verified (cannot be NULL)
6777
* siglen: the length of the signature
6878
* pubkey: the public key to verify with (cannot be NULL)
6979
* pubkeylen: the length of pubkey
70-
* Requires starting using SECP256K1_START_VERIFY.
7180
*/
7281
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
82+
const secp256k1_context_t* ctx,
7383
const unsigned char *msg32,
7484
const unsigned char *sig,
7585
int siglen,
7686
const unsigned char *pubkey,
7787
int pubkeylen
78-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
88+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
7989

8090
/** A pointer to a function to deterministically generate a nonce.
8191
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail.
@@ -111,15 +121,14 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_default;
111121
* Returns: 1: signature created
112122
* 0: the nonce generation function failed, the private key was invalid, or there is not
113123
* enough space in the signature (as indicated by siglen).
114-
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
124+
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
125+
* msg32: the 32-byte message hash being signed (cannot be NULL)
115126
* seckey: pointer to a 32-byte secret key (cannot be NULL)
116127
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
117128
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
118129
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
119130
* In/Out: siglen: pointer to an int with the length of sig, which will be updated
120-
* to contain the actual signature length (<=72). If 0 is returned, this will be
121-
* set to zero.
122-
* Requires starting using SECP256K1_START_SIGN.
131+
* to contain the actual signature length (<=72).
123132
*
124133
* The sig always has an s value in the lower half of the range (From 0x1
125134
* to 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
@@ -148,89 +157,103 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_default;
148157
* be taken when this property is required for an application.
149158
*/
150159
int secp256k1_ecdsa_sign(
160+
const secp256k1_context_t* ctx,
151161
const unsigned char *msg32,
152162
unsigned char *sig,
153163
int *siglen,
154164
const unsigned char *seckey,
155165
secp256k1_nonce_function_t noncefp,
156166
const void *ndata
157-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
167+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
158168

159169
/** Create a compact ECDSA signature (64 byte + recovery id).
160170
* Returns: 1: signature created
161171
* 0: the nonce generation function failed, or the secret key was invalid.
162-
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
172+
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
173+
* msg32: the 32-byte message hash being signed (cannot be NULL)
163174
* seckey: pointer to a 32-byte secret key (cannot be NULL)
164175
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
165176
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
166177
* Out: sig: pointer to a 64-byte array where the signature will be placed (cannot be NULL)
167178
* In case 0 is returned, the returned signature length will be zero.
168179
* recid: pointer to an int, which will be updated to contain the recovery id (can be NULL)
169-
* Requires starting using SECP256K1_START_SIGN.
170180
*/
171181
int secp256k1_ecdsa_sign_compact(
182+
const secp256k1_context_t* ctx,
172183
const unsigned char *msg32,
173184
unsigned char *sig64,
174185
const unsigned char *seckey,
175186
secp256k1_nonce_function_t noncefp,
176187
const void *ndata,
177188
int *recid
178-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
189+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
179190

180191
/** Recover an ECDSA public key from a compact signature.
181192
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
182193
* 0: otherwise.
183-
* In: msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
194+
* In: ctx: pointer to a context object, initialized for verification (cannot be NULL)
195+
* msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
184196
* sig64: signature as 64 byte array (cannot be NULL)
185197
* compressed: whether to recover a compressed or uncompressed pubkey
186198
* recid: the recovery id (0-3, as returned by ecdsa_sign_compact)
187199
* Out: pubkey: pointer to a 33 or 65 byte array to put the pubkey (cannot be NULL)
188200
* pubkeylen: pointer to an int that will contain the pubkey length (cannot be NULL)
189-
* Requires starting using SECP256K1_START_VERIFY.
190201
*/
191202
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover_compact(
203+
const secp256k1_context_t* ctx,
192204
const unsigned char *msg32,
193205
const unsigned char *sig64,
194206
unsigned char *pubkey,
195207
int *pubkeylen,
196208
int compressed,
197209
int recid
198-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
210+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
199211

200212
/** Verify an ECDSA secret key.
201213
* Returns: 1: secret key is valid
202214
* 0: secret key is invalid
203-
* In: seckey: pointer to a 32-byte secret key (cannot be NULL)
215+
* In: ctx: pointer to a context object (cannot be NULL)
216+
* seckey: pointer to a 32-byte secret key (cannot be NULL)
204217
*/
205-
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(const unsigned char *seckey) SECP256K1_ARG_NONNULL(1);
218+
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
219+
const secp256k1_context_t* ctx,
220+
const unsigned char *seckey
221+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
206222

207-
/** Verify an ECDSA public key.
223+
/** Just validate a public key.
208224
* Returns: 1: public key is valid
209225
* 0: public key is invalid
210-
* In: pubkey: pointer to a 33-byte or 65-byte public key (cannot be NULL).
226+
* In: ctx: pointer to a context object (cannot be NULL)
227+
* pubkey: pointer to a 33-byte or 65-byte public key (cannot be NULL).
211228
* pubkeylen: length of pubkey
212229
*/
213-
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_verify(const unsigned char *pubkey, int pubkeylen) SECP256K1_ARG_NONNULL(1);
230+
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_verify(
231+
const secp256k1_context_t* ctx,
232+
const unsigned char *pubkey,
233+
int pubkeylen
234+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
214235

215236
/** Compute the public key for a secret key.
216-
* In: compressed: whether the computed public key should be compressed
237+
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
238+
* compressed: whether the computed public key should be compressed
217239
* seckey: pointer to a 32-byte private key (cannot be NULL)
218240
* Out: pubkey: pointer to a 33-byte (if compressed) or 65-byte (if uncompressed)
219241
* area to store the public key (cannot be NULL)
220242
* pubkeylen: pointer to int that will be updated to contains the pubkey's
221243
* length (cannot be NULL)
222244
* Returns: 1: secret was valid, public key stores
223245
* 0: secret was invalid, try again
224-
* Requires starting using SECP256K1_START_SIGN.
225246
*/
226247
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
248+
const secp256k1_context_t* ctx,
227249
unsigned char *pubkey,
228250
int *pubkeylen,
229251
const unsigned char *seckey,
230252
int compressed
231-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
253+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
232254

233255
/** Decompress a public key.
256+
* In: ctx: pointer to a context object (cannot be NULL)
234257
* In/Out: pubkey: pointer to a 65-byte array to put the decompressed public key.
235258
* It must contain a 33-byte or 65-byte public key already (cannot be NULL)
236259
* pubkeylen: pointer to the size of the public key pointed to by pubkey (cannot be NULL)
@@ -239,54 +262,63 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
239262
* 1: pubkey was valid, and was replaced with its decompressed version
240263
*/
241264
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_decompress(
265+
const secp256k1_context_t* ctx,
242266
unsigned char *pubkey,
243267
int *pubkeylen
244-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
268+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
245269

246-
/** Export a private key in DER format. */
270+
/** Export a private key in DER format.
271+
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
272+
*/
247273
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export(
274+
const secp256k1_context_t* ctx,
248275
const unsigned char *seckey,
249276
unsigned char *privkey,
250277
int *privkeylen,
251278
int compressed
252-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
279+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
253280

254281
/** Import a private key in DER format. */
255282
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_import(
283+
const secp256k1_context_t* ctx,
256284
unsigned char *seckey,
257285
const unsigned char *privkey,
258286
int privkeylen
259-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
287+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
260288

261289
/** Tweak a private key by adding tweak to it. */
262290
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
291+
const secp256k1_context_t* ctx,
263292
unsigned char *seckey,
264293
const unsigned char *tweak
265-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
294+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
266295

267296
/** Tweak a public key by adding tweak times the generator to it.
268-
* Requires starting with SECP256K1_START_VERIFY.
297+
* In: ctx: pointer to a context object, initialized for verification (cannot be NULL)
269298
*/
270299
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
300+
const secp256k1_context_t* ctx,
271301
unsigned char *pubkey,
272302
int pubkeylen,
273303
const unsigned char *tweak
274-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3);
304+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
275305

276306
/** Tweak a private key by multiplying it with tweak. */
277307
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
308+
const secp256k1_context_t* ctx,
278309
unsigned char *seckey,
279310
const unsigned char *tweak
280-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
311+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
281312

282313
/** Tweak a public key by multiplying it with tweak.
283-
* Requires starting with SECP256K1_START_VERIFY.
314+
* In: ctx: pointer to a context object, initialized for verification (cannot be NULL)
284315
*/
285316
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
317+
const secp256k1_context_t* ctx,
286318
unsigned char *pubkey,
287319
int pubkeylen,
288320
const unsigned char *tweak
289-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3);
321+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
290322

291323
# ifdef __cplusplus
292324
}

src/bench_recover.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "bench.h"
1010

1111
typedef struct {
12+
secp256k1_context_t *ctx;
1213
unsigned char msg[32];
1314
unsigned char sig[64];
1415
} bench_recover_t;
@@ -21,7 +22,7 @@ void bench_recover(void* arg) {
2122
for (i = 0; i < 20000; i++) {
2223
int j;
2324
int pubkeylen = 33;
24-
CHECK(secp256k1_ecdsa_recover_compact(data->msg, data->sig, pubkey, &pubkeylen, 1, i % 2));
25+
CHECK(secp256k1_ecdsa_recover_compact(data->ctx, data->msg, data->sig, pubkey, &pubkeylen, 1, i % 2));
2526
for (j = 0; j < 32; j++) {
2627
data->sig[j + 32] = data->msg[j]; /* Move former message to S. */
2728
data->msg[j] = data->sig[j]; /* Move former R to message. */
@@ -40,10 +41,11 @@ void bench_recover_setup(void* arg) {
4041

4142
int main(void) {
4243
bench_recover_t data;
43-
secp256k1_start(SECP256K1_START_VERIFY);
44+
45+
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
4446

4547
run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, 20000);
4648

47-
secp256k1_stop();
49+
secp256k1_context_destroy(data.ctx);
4850
return 0;
4951
}

src/bench_sign.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "bench.h"
1010

1111
typedef struct {
12+
secp256k1_context_t* ctx;
1213
unsigned char msg[32];
1314
unsigned char key[32];
1415
} bench_sign_t;
@@ -29,7 +30,7 @@ static void bench_sign(void* arg) {
2930
for (i = 0; i < 20000; i++) {
3031
int j;
3132
int recid = 0;
32-
CHECK(secp256k1_ecdsa_sign_compact(data->msg, sig, data->key, NULL, NULL, &recid));
33+
CHECK(secp256k1_ecdsa_sign_compact(data->ctx, data->msg, sig, data->key, NULL, NULL, &recid));
3334
for (j = 0; j < 32; j++) {
3435
data->msg[j] = sig[j]; /* Move former R to message. */
3536
data->key[j] = sig[j + 32]; /* Move former S to key. */
@@ -39,10 +40,11 @@ static void bench_sign(void* arg) {
3940

4041
int main(void) {
4142
bench_sign_t data;
42-
secp256k1_start(SECP256K1_START_SIGN);
43+
44+
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
4345

4446
run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000);
4547

46-
secp256k1_stop();
48+
secp256k1_context_destroy(data.ctx);
4749
return 0;
4850
}

src/bench_verify.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "bench.h"
1313

1414
typedef struct {
15+
secp256k1_context_t *ctx;
1516
unsigned char msg[32];
1617
unsigned char key[32];
1718
unsigned char sig[72];
@@ -28,7 +29,7 @@ static void benchmark_verify(void* arg) {
2829
data->sig[data->siglen - 1] ^= (i & 0xFF);
2930
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
3031
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
31-
CHECK(secp256k1_ecdsa_verify(data->msg, data->sig, data->siglen, data->pubkey, data->pubkeylen) == (i == 0));
32+
CHECK(secp256k1_ecdsa_verify(data->ctx, data->msg, data->sig, data->siglen, data->pubkey, data->pubkeylen) == (i == 0));
3233
data->sig[data->siglen - 1] ^= (i & 0xFF);
3334
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
3435
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
@@ -39,17 +40,17 @@ int main(void) {
3940
int i;
4041
benchmark_verify_t data;
4142

42-
secp256k1_start(SECP256K1_START_VERIFY | SECP256K1_START_SIGN);
43+
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
4344

4445
for (i = 0; i < 32; i++) data.msg[i] = 1 + i;
4546
for (i = 0; i < 32; i++) data.key[i] = 33 + i;
4647
data.siglen = 72;
47-
secp256k1_ecdsa_sign(data.msg, data.sig, &data.siglen, data.key, NULL, NULL);
48+
secp256k1_ecdsa_sign(data.ctx, data.msg, data.sig, &data.siglen, data.key, NULL, NULL);
4849
data.pubkeylen = 33;
49-
CHECK(secp256k1_ec_pubkey_create(data.pubkey, &data.pubkeylen, data.key, 1));
50+
CHECK(secp256k1_ec_pubkey_create(data.ctx, data.pubkey, &data.pubkeylen, data.key, 1));
5051

5152
run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000);
5253

53-
secp256k1_stop();
54+
secp256k1_context_destroy(data.ctx);
5455
return 0;
5556
}

src/ecdsa.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@
99

1010
#include "scalar.h"
1111
#include "group.h"
12+
#include "ecmult.h"
1213

1314
typedef struct {
1415
secp256k1_scalar_t r, s;
1516
} secp256k1_ecdsa_sig_t;
1617

1718
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size);
1819
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a);
19-
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message);
20-
static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
21-
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid);
20+
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message);
21+
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
22+
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid);
2223

2324
#endif

0 commit comments

Comments
 (0)