Skip to content

Commit e3f8477

Browse files
committed
Merge bitcoin-core#1126: API cleanup with respect to contexts
4386a23 examples: Switch to NONE contexts (Tim Ruffing) 7289b51 docs: Use doxygen style if and only if comment is user-facing (Tim Ruffing) e7d0185 docs: Get rid of "initialized for signing" terminology (Tim Ruffing) 0612636 docs: Tidy and improve docs about contexts and randomization (Tim Ruffing) e02d686 selftest: Expose in public API (Tim Ruffing) e383fbf selftest: Rename internal function to make name available for API (Tim Ruffing) d2c6d48 tests: Use new name of static context (Tim Ruffing) 53796d2 contexts: Rename static context (Tim Ruffing) 72fedf8 docs: Improve docs for static context (Tim Ruffing) 316ac76 contexts: Deprecate all context flags except SECP256K1_CONTEXT_NONE (Tim Ruffing) 1a553ee docs: Change signature "validation" to "verification" (Tim Ruffing) ee7341f docs: Never require a verification context (Tim Ruffing) Pull request description: ACKs for top commit: sipa: utACK 4386a23 jonasnick: ACK 4386a23 Tree-SHA512: 7bf07dfae0ecbf7de1418de64ef743a23dc5f244aeba2c1cf3ecbdc117d6ac12bb6c8f17f739605566074a9b901765ee4a32288b6edc6f9a0040a70cb472f6ee
2 parents 477f02c + 4386a23 commit e3f8477

16 files changed

+174
-99
lines changed

contrib/lax_der_privatekey_parsing.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ extern "C" {
4343
/** Export a private key in DER format.
4444
*
4545
* Returns: 1 if the private key was valid.
46-
* Args: ctx: pointer to a context object, initialized for signing (cannot
47-
* be NULL)
46+
* Args: ctx: pointer to a context object (not secp256k1_context_static).
4847
* Out: privkey: pointer to an array for storing the private key in BER.
4948
* Should have space for 279 bytes, and cannot be NULL.
5049
* privkeylen: Pointer to an int where the length of the private key in

doc/CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ Each change falls into one of the following categories: Added, Changed, Deprecat
99
### Changed
1010
- Enable modules schnorrsig, extrakeys and ECDH by default in ./configure
1111

12+
### Deprecated
13+
- Deprecated context flags `SECP256K1_CONTEXT_VERIFY` and `SECP256K1_CONTEXT_SIGN`. Use `SECP256K1_CONTEXT_NONE` instead.
14+
- Renamed `secp256k1_context_no_precomp` to `secp256k1_context_static`.
15+
16+
### Added
17+
- Added `secp256k1_selftest`, to be used in conjunction with `secp256k1_context_static`.
18+
1219
## [MAJOR.MINOR.PATCH] - YYYY-MM-DD
1320

1421
### Added/Changed/Deprecated/Removed/Fixed/Security

examples/ecdh.c

+2-6
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,8 @@ int main(void) {
3030
secp256k1_pubkey pubkey1;
3131
secp256k1_pubkey pubkey2;
3232

33-
/* The specification in secp256k1.h states that `secp256k1_ec_pubkey_create`
34-
* needs a context object initialized for signing, which is why we create
35-
* a context with the SECP256K1_CONTEXT_SIGN flag.
36-
* (The docs for `secp256k1_ecdh` don't require any special context, just
37-
* some initialized context) */
38-
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
33+
/* Before we can call actual API functions, we need to create a "context". */
34+
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
3935
if (!fill_random(randomize, sizeof(randomize))) {
4036
printf("Failed to generate randomness\n");
4137
return 1;

examples/ecdsa.c

+2-6
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,8 @@ int main(void) {
3838
int return_val;
3939
secp256k1_pubkey pubkey;
4040
secp256k1_ecdsa_signature sig;
41-
/* The specification in secp256k1.h states that `secp256k1_ec_pubkey_create` needs
42-
* a context object initialized for signing and `secp256k1_ecdsa_verify` needs
43-
* a context initialized for verification, which is why we create a context
44-
* for both signing and verification with the SECP256K1_CONTEXT_SIGN and
45-
* SECP256K1_CONTEXT_VERIFY flags. */
46-
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
41+
/* Before we can call actual API functions, we need to create a "context". */
42+
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
4743
if (!fill_random(randomize, sizeof(randomize))) {
4844
printf("Failed to generate randomness\n");
4945
return 1;

examples/schnorr.c

+2-6
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,8 @@ int main(void) {
3030
int return_val;
3131
secp256k1_xonly_pubkey pubkey;
3232
secp256k1_keypair keypair;
33-
/* The specification in secp256k1_extrakeys.h states that `secp256k1_keypair_create`
34-
* needs a context object initialized for signing. And in secp256k1_schnorrsig.h
35-
* they state that `secp256k1_schnorrsig_verify` needs a context initialized for
36-
* verification, which is why we create a context for both signing and verification
37-
* with the SECP256K1_CONTEXT_SIGN and SECP256K1_CONTEXT_VERIFY flags. */
38-
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
33+
/* Before we can call actual API functions, we need to create a "context". */
34+
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
3935
if (!fill_random(randomize, sizeof(randomize))) {
4036
printf("Failed to generate randomness\n");
4137
return 1;

include/secp256k1.h

+120-55
Large diffs are not rendered by default.

include/secp256k1_extrakeys.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubke
108108
* invalid (only when the tweak is the negation of the corresponding
109109
* secret key). 1 otherwise.
110110
*
111-
* Args: ctx: pointer to a context object initialized for verification.
111+
* Args: ctx: pointer to a context object.
112112
* Out: output_pubkey: pointer to a public key to store the result. Will be set
113113
* to an invalid value if this function returns 0.
114114
* In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to.
@@ -137,7 +137,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
137137
*
138138
* Returns: 0 if the arguments are invalid or the tweaked pubkey is not the
139139
* result of tweaking the internal_pubkey with tweak32. 1 otherwise.
140-
* Args: ctx: pointer to a context object initialized for verification.
140+
* Args: ctx: pointer to a context object.
141141
* In: tweaked_pubkey32: pointer to a serialized xonly_pubkey.
142142
* tweaked_pk_parity: the parity of the tweaked pubkey (whose serialization
143143
* is passed in as tweaked_pubkey32). This must match the
@@ -159,7 +159,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_
159159
*
160160
* Returns: 1: secret was valid, keypair is ready to use
161161
* 0: secret was invalid, try again with a different secret
162-
* Args: ctx: pointer to a context object, initialized for signing.
162+
* Args: ctx: pointer to a context object (not secp256k1_context_static).
163163
* Out: keypair: pointer to the created keypair.
164164
* In: seckey: pointer to a 32-byte secret key.
165165
*/
@@ -228,7 +228,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
228228
* invalid (only when the tweak is the negation of the keypair's
229229
* secret key). 1 otherwise.
230230
*
231-
* Args: ctx: pointer to a context object initialized for verification.
231+
* Args: ctx: pointer to a context object.
232232
* In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to
233233
* an invalid value if this function returns 0.
234234
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according

include/secp256k1_preallocated.h

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ SECP256K1_API size_t secp256k1_context_preallocated_size(
5858
* bytes, as detailed above.
5959
* flags: which parts of the context to initialize.
6060
*
61+
* See secp256k1_context_create (in secp256k1.h) for further details.
62+
*
6163
* See also secp256k1_context_randomize (in secp256k1.h)
6264
* and secp256k1_context_preallocated_destroy.
6365
*/

include/secp256k1_recovery.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
7272
*
7373
* Returns: 1: signature created
7474
* 0: the nonce generation function failed, or the secret key was invalid.
75-
* Args: ctx: pointer to a context object, initialized for signing.
75+
* Args: ctx: pointer to a context object (not secp256k1_context_static).
7676
* Out: sig: pointer to an array where the signature will be placed.
7777
* In: msghash32: the 32-byte message hash being signed.
7878
* seckey: pointer to a 32-byte secret key.
@@ -94,7 +94,7 @@ SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
9494
*
9595
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
9696
* 0: otherwise.
97-
* Args: ctx: pointer to a context object, initialized for verification.
97+
* Args: ctx: pointer to a context object.
9898
* Out: pubkey: pointer to the recovered public key.
9999
* In: sig: pointer to initialized signature that supports pubkey recovery.
100100
* msghash32: the 32-byte message hash assumed to be signed.

include/secp256k1_schnorrsig.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ typedef struct {
106106
* signatures from being valid in multiple contexts by accident.
107107
*
108108
* Returns 1 on success, 0 on failure.
109-
* Args: ctx: pointer to a context object, initialized for signing.
109+
* Args: ctx: pointer to a context object (not secp256k1_context_static).
110110
* Out: sig64: pointer to a 64-byte array to store the serialized signature.
111111
* In: msg32: the 32-byte message being signed.
112112
* keypair: pointer to an initialized keypair.
@@ -161,7 +161,7 @@ SECP256K1_API int secp256k1_schnorrsig_sign_custom(
161161
*
162162
* Returns: 1: correct signature
163163
* 0: incorrect signature
164-
* Args: ctx: a secp256k1 context object, initialized for verification.
164+
* Args: ctx: a secp256k1 context object.
165165
* In: sig64: pointer to the 64-byte signature to verify.
166166
* msg: the message being verified. Can only be NULL if msglen is 0.
167167
* msglen: length of the message

src/modules/extrakeys/tests_impl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ void test_keypair(void) {
359359
secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
360360
secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
361361
secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
362-
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
362+
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static);
363363
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
364364
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
365365

src/modules/recovery/tests_impl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void test_ecdsa_recovery_api(void) {
3434
secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
3535
secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
3636
secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
37-
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
37+
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static);
3838
secp256k1_pubkey pubkey;
3939
secp256k1_pubkey recpubkey;
4040
secp256k1_ecdsa_signature normal_sig;

src/modules/schnorrsig/tests_impl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ void test_schnorrsig_api(void) {
132132
secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
133133
secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
134134
secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
135-
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
135+
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static);
136136
int ecount;
137137

138138
secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);

src/secp256k1.c

+13-8
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,20 @@ struct secp256k1_context_struct {
6464
int declassify;
6565
};
6666

67-
static const secp256k1_context secp256k1_context_no_precomp_ = {
67+
static const secp256k1_context secp256k1_context_static_ = {
6868
{ 0 },
6969
{ secp256k1_default_illegal_callback_fn, 0 },
7070
{ secp256k1_default_error_callback_fn, 0 },
7171
0
7272
};
73-
const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_no_precomp_;
73+
const secp256k1_context *secp256k1_context_static = &secp256k1_context_static_;
74+
const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_static_;
75+
76+
void secp256k1_selftest(void) {
77+
if (!secp256k1_selftest_passes()) {
78+
secp256k1_callback_call(&default_error_callback, "self test failed");
79+
}
80+
}
7481

7582
size_t secp256k1_context_preallocated_size(unsigned int flags) {
7683
size_t ret = sizeof(secp256k1_context);
@@ -96,9 +103,7 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne
96103
size_t prealloc_size;
97104
secp256k1_context* ret;
98105

99-
if (!secp256k1_selftest()) {
100-
secp256k1_callback_call(&default_error_callback, "self test failed");
101-
}
106+
secp256k1_selftest();
102107

103108
prealloc_size = secp256k1_context_preallocated_size(flags);
104109
if (prealloc_size == 0) {
@@ -150,7 +155,7 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
150155
}
151156

152157
void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) {
153-
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
158+
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_static);
154159
if (ctx != NULL) {
155160
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
156161
}
@@ -164,7 +169,7 @@ void secp256k1_context_destroy(secp256k1_context* ctx) {
164169
}
165170

166171
void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
167-
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
172+
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_static);
168173
if (fun == NULL) {
169174
fun = secp256k1_default_illegal_callback_fn;
170175
}
@@ -173,7 +178,7 @@ void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(
173178
}
174179

175180
void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
176-
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
181+
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_static);
177182
if (fun == NULL) {
178183
fun = secp256k1_default_error_callback_fn;
179184
}

src/selftest.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ static int secp256k1_selftest_sha256(void) {
2525
return secp256k1_memcmp_var(out, output32, 32) == 0;
2626
}
2727

28-
static int secp256k1_selftest(void) {
28+
static int secp256k1_selftest_passes(void) {
2929
return secp256k1_selftest_sha256();
3030
}
3131

src/tests.c

+13-4
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ void random_scalar_order_b32(unsigned char *b32) {
141141
secp256k1_scalar_get_b32(b32, &num);
142142
}
143143

144+
void run_selftest_tests(void) {
145+
/* Test public API */
146+
secp256k1_selftest();
147+
}
148+
144149
void run_context_tests(int use_prealloc) {
145150
secp256k1_pubkey pubkey;
146151
secp256k1_pubkey zero_pubkey;
@@ -164,12 +169,15 @@ void run_context_tests(int use_prealloc) {
164169
secp256k1_scalar msg, key, nonce;
165170
secp256k1_scalar sigr, sigs;
166171

172+
/* Check that deprecated secp256k1_context_no_precomp is an alias to secp256k1_context_static. */
173+
CHECK(secp256k1_context_no_precomp == secp256k1_context_static);
174+
167175
if (use_prealloc) {
168176
none_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
169177
sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN));
170178
vrfy_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY));
171179
both_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY));
172-
sttc_prealloc = malloc(secp256k1_context_preallocated_clone_size(secp256k1_context_no_precomp));
180+
sttc_prealloc = malloc(secp256k1_context_preallocated_clone_size(secp256k1_context_static));
173181
CHECK(none_prealloc != NULL);
174182
CHECK(sign_prealloc != NULL);
175183
CHECK(vrfy_prealloc != NULL);
@@ -179,13 +187,13 @@ void run_context_tests(int use_prealloc) {
179187
sign = secp256k1_context_preallocated_create(sign_prealloc, SECP256K1_CONTEXT_SIGN);
180188
vrfy = secp256k1_context_preallocated_create(vrfy_prealloc, SECP256K1_CONTEXT_VERIFY);
181189
both = secp256k1_context_preallocated_create(both_prealloc, SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
182-
sttc = secp256k1_context_preallocated_clone(secp256k1_context_no_precomp, sttc_prealloc);
190+
sttc = secp256k1_context_preallocated_clone(secp256k1_context_static, sttc_prealloc);
183191
} else {
184192
none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
185193
sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
186194
vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
187195
both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
188-
sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
196+
sttc = secp256k1_context_clone(secp256k1_context_static);
189197
}
190198

191199
memset(&zero_pubkey, 0, sizeof(zero_pubkey));
@@ -5799,7 +5807,7 @@ void run_ec_pubkey_parse_test(void) {
57995807
ecount = 0;
58005808
VG_UNDEF(&pubkey, sizeof(pubkey));
58015809
CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 65) == 1);
5802-
CHECK(secp256k1_ec_pubkey_parse(secp256k1_context_no_precomp, &pubkey, pubkeyc, 65) == 1);
5810+
CHECK(secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, pubkeyc, 65) == 1);
58035811
VG_CHECK(&pubkey, sizeof(pubkey));
58045812
CHECK(ecount == 0);
58055813
VG_UNDEF(&ge, sizeof(ge));
@@ -7385,6 +7393,7 @@ int main(int argc, char **argv) {
73857393
secp256k1_testrand_init(argc > 2 ? argv[2] : NULL);
73867394

73877395
/* initialize */
7396+
run_selftest_tests();
73887397
run_context_tests(0);
73897398
run_context_tests(1);
73907399
run_scratch_tests();

0 commit comments

Comments
 (0)